xref: /openbmc/linux/drivers/md/dm-snap-persistent.c (revision 4db6bfe02bdc7dc5048f46dd682a94801d029adc)
1*4db6bfe0SAlasdair G Kergon /*
2*4db6bfe0SAlasdair G Kergon  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
3*4db6bfe0SAlasdair G Kergon  * Copyright (C) 2006-2008 Red Hat GmbH
4*4db6bfe0SAlasdair G Kergon  *
5*4db6bfe0SAlasdair G Kergon  * This file is released under the GPL.
6*4db6bfe0SAlasdair G Kergon  */
7*4db6bfe0SAlasdair G Kergon 
8*4db6bfe0SAlasdair G Kergon #include "dm-exception-store.h"
9*4db6bfe0SAlasdair G Kergon #include "dm-snap.h"
10*4db6bfe0SAlasdair G Kergon 
11*4db6bfe0SAlasdair G Kergon #include <linux/mm.h>
12*4db6bfe0SAlasdair G Kergon #include <linux/pagemap.h>
13*4db6bfe0SAlasdair G Kergon #include <linux/vmalloc.h>
14*4db6bfe0SAlasdair G Kergon #include <linux/slab.h>
15*4db6bfe0SAlasdair G Kergon #include <linux/dm-io.h>
16*4db6bfe0SAlasdair G Kergon 
17*4db6bfe0SAlasdair G Kergon #define DM_MSG_PREFIX "persistent snapshot"
18*4db6bfe0SAlasdair G Kergon #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32	/* 16KB */
19*4db6bfe0SAlasdair G Kergon 
20*4db6bfe0SAlasdair G Kergon /*-----------------------------------------------------------------
21*4db6bfe0SAlasdair G Kergon  * Persistent snapshots, by persistent we mean that the snapshot
22*4db6bfe0SAlasdair G Kergon  * will survive a reboot.
23*4db6bfe0SAlasdair G Kergon  *---------------------------------------------------------------*/
24*4db6bfe0SAlasdair G Kergon 
25*4db6bfe0SAlasdair G Kergon /*
26*4db6bfe0SAlasdair G Kergon  * We need to store a record of which parts of the origin have
27*4db6bfe0SAlasdair G Kergon  * been copied to the snapshot device.  The snapshot code
28*4db6bfe0SAlasdair G Kergon  * requires that we copy exception chunks to chunk aligned areas
29*4db6bfe0SAlasdair G Kergon  * of the COW store.  It makes sense therefore, to store the
30*4db6bfe0SAlasdair G Kergon  * metadata in chunk size blocks.
31*4db6bfe0SAlasdair G Kergon  *
32*4db6bfe0SAlasdair G Kergon  * There is no backward or forward compatibility implemented,
33*4db6bfe0SAlasdair G Kergon  * snapshots with different disk versions than the kernel will
34*4db6bfe0SAlasdair G Kergon  * not be usable.  It is expected that "lvcreate" will blank out
35*4db6bfe0SAlasdair G Kergon  * the start of a fresh COW device before calling the snapshot
36*4db6bfe0SAlasdair G Kergon  * constructor.
37*4db6bfe0SAlasdair G Kergon  *
38*4db6bfe0SAlasdair G Kergon  * The first chunk of the COW device just contains the header.
39*4db6bfe0SAlasdair G Kergon  * After this there is a chunk filled with exception metadata,
40*4db6bfe0SAlasdair G Kergon  * followed by as many exception chunks as can fit in the
41*4db6bfe0SAlasdair G Kergon  * metadata areas.
42*4db6bfe0SAlasdair G Kergon  *
43*4db6bfe0SAlasdair G Kergon  * All on disk structures are in little-endian format.  The end
44*4db6bfe0SAlasdair G Kergon  * of the exceptions info is indicated by an exception with a
45*4db6bfe0SAlasdair G Kergon  * new_chunk of 0, which is invalid since it would point to the
46*4db6bfe0SAlasdair G Kergon  * header chunk.
47*4db6bfe0SAlasdair G Kergon  */
48*4db6bfe0SAlasdair G Kergon 
49*4db6bfe0SAlasdair G Kergon /*
50*4db6bfe0SAlasdair G Kergon  * Magic for persistent snapshots: "SnAp" - Feeble isn't it.
51*4db6bfe0SAlasdair G Kergon  */
52*4db6bfe0SAlasdair G Kergon #define SNAP_MAGIC 0x70416e53
53*4db6bfe0SAlasdair G Kergon 
54*4db6bfe0SAlasdair G Kergon /*
55*4db6bfe0SAlasdair G Kergon  * The on-disk version of the metadata.
56*4db6bfe0SAlasdair G Kergon  */
57*4db6bfe0SAlasdair G Kergon #define SNAPSHOT_DISK_VERSION 1
58*4db6bfe0SAlasdair G Kergon 
59*4db6bfe0SAlasdair G Kergon struct disk_header {
60*4db6bfe0SAlasdair G Kergon 	uint32_t magic;
61*4db6bfe0SAlasdair G Kergon 
62*4db6bfe0SAlasdair G Kergon 	/*
63*4db6bfe0SAlasdair G Kergon 	 * Is this snapshot valid.  There is no way of recovering
64*4db6bfe0SAlasdair G Kergon 	 * an invalid snapshot.
65*4db6bfe0SAlasdair G Kergon 	 */
66*4db6bfe0SAlasdair G Kergon 	uint32_t valid;
67*4db6bfe0SAlasdair G Kergon 
68*4db6bfe0SAlasdair G Kergon 	/*
69*4db6bfe0SAlasdair G Kergon 	 * Simple, incrementing version. no backward
70*4db6bfe0SAlasdair G Kergon 	 * compatibility.
71*4db6bfe0SAlasdair G Kergon 	 */
72*4db6bfe0SAlasdair G Kergon 	uint32_t version;
73*4db6bfe0SAlasdair G Kergon 
74*4db6bfe0SAlasdair G Kergon 	/* In sectors */
75*4db6bfe0SAlasdair G Kergon 	uint32_t chunk_size;
76*4db6bfe0SAlasdair G Kergon };
77*4db6bfe0SAlasdair G Kergon 
78*4db6bfe0SAlasdair G Kergon struct disk_exception {
79*4db6bfe0SAlasdair G Kergon 	uint64_t old_chunk;
80*4db6bfe0SAlasdair G Kergon 	uint64_t new_chunk;
81*4db6bfe0SAlasdair G Kergon };
82*4db6bfe0SAlasdair G Kergon 
83*4db6bfe0SAlasdair G Kergon struct commit_callback {
84*4db6bfe0SAlasdair G Kergon 	void (*callback)(void *, int success);
85*4db6bfe0SAlasdair G Kergon 	void *context;
86*4db6bfe0SAlasdair G Kergon };
87*4db6bfe0SAlasdair G Kergon 
88*4db6bfe0SAlasdair G Kergon /*
89*4db6bfe0SAlasdair G Kergon  * The top level structure for a persistent exception store.
90*4db6bfe0SAlasdair G Kergon  */
91*4db6bfe0SAlasdair G Kergon struct pstore {
92*4db6bfe0SAlasdair G Kergon 	struct dm_snapshot *snap;	/* up pointer to my snapshot */
93*4db6bfe0SAlasdair G Kergon 	int version;
94*4db6bfe0SAlasdair G Kergon 	int valid;
95*4db6bfe0SAlasdair G Kergon 	uint32_t exceptions_per_area;
96*4db6bfe0SAlasdair G Kergon 
97*4db6bfe0SAlasdair G Kergon 	/*
98*4db6bfe0SAlasdair G Kergon 	 * Now that we have an asynchronous kcopyd there is no
99*4db6bfe0SAlasdair G Kergon 	 * need for large chunk sizes, so it wont hurt to have a
100*4db6bfe0SAlasdair G Kergon 	 * whole chunks worth of metadata in memory at once.
101*4db6bfe0SAlasdair G Kergon 	 */
102*4db6bfe0SAlasdair G Kergon 	void *area;
103*4db6bfe0SAlasdair G Kergon 
104*4db6bfe0SAlasdair G Kergon 	/*
105*4db6bfe0SAlasdair G Kergon 	 * An area of zeros used to clear the next area.
106*4db6bfe0SAlasdair G Kergon 	 */
107*4db6bfe0SAlasdair G Kergon 	void *zero_area;
108*4db6bfe0SAlasdair G Kergon 
109*4db6bfe0SAlasdair G Kergon 	/*
110*4db6bfe0SAlasdair G Kergon 	 * Used to keep track of which metadata area the data in
111*4db6bfe0SAlasdair G Kergon 	 * 'chunk' refers to.
112*4db6bfe0SAlasdair G Kergon 	 */
113*4db6bfe0SAlasdair G Kergon 	chunk_t current_area;
114*4db6bfe0SAlasdair G Kergon 
115*4db6bfe0SAlasdair G Kergon 	/*
116*4db6bfe0SAlasdair G Kergon 	 * The next free chunk for an exception.
117*4db6bfe0SAlasdair G Kergon 	 */
118*4db6bfe0SAlasdair G Kergon 	chunk_t next_free;
119*4db6bfe0SAlasdair G Kergon 
120*4db6bfe0SAlasdair G Kergon 	/*
121*4db6bfe0SAlasdair G Kergon 	 * The index of next free exception in the current
122*4db6bfe0SAlasdair G Kergon 	 * metadata area.
123*4db6bfe0SAlasdair G Kergon 	 */
124*4db6bfe0SAlasdair G Kergon 	uint32_t current_committed;
125*4db6bfe0SAlasdair G Kergon 
126*4db6bfe0SAlasdair G Kergon 	atomic_t pending_count;
127*4db6bfe0SAlasdair G Kergon 	uint32_t callback_count;
128*4db6bfe0SAlasdair G Kergon 	struct commit_callback *callbacks;
129*4db6bfe0SAlasdair G Kergon 	struct dm_io_client *io_client;
130*4db6bfe0SAlasdair G Kergon 
131*4db6bfe0SAlasdair G Kergon 	struct workqueue_struct *metadata_wq;
132*4db6bfe0SAlasdair G Kergon };
133*4db6bfe0SAlasdair G Kergon 
134*4db6bfe0SAlasdair G Kergon static unsigned sectors_to_pages(unsigned sectors)
135*4db6bfe0SAlasdair G Kergon {
136*4db6bfe0SAlasdair G Kergon 	return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
137*4db6bfe0SAlasdair G Kergon }
138*4db6bfe0SAlasdair G Kergon 
139*4db6bfe0SAlasdair G Kergon static int alloc_area(struct pstore *ps)
140*4db6bfe0SAlasdair G Kergon {
141*4db6bfe0SAlasdair G Kergon 	int r = -ENOMEM;
142*4db6bfe0SAlasdair G Kergon 	size_t len;
143*4db6bfe0SAlasdair G Kergon 
144*4db6bfe0SAlasdair G Kergon 	len = ps->snap->chunk_size << SECTOR_SHIFT;
145*4db6bfe0SAlasdair G Kergon 
146*4db6bfe0SAlasdair G Kergon 	/*
147*4db6bfe0SAlasdair G Kergon 	 * Allocate the chunk_size block of memory that will hold
148*4db6bfe0SAlasdair G Kergon 	 * a single metadata area.
149*4db6bfe0SAlasdair G Kergon 	 */
150*4db6bfe0SAlasdair G Kergon 	ps->area = vmalloc(len);
151*4db6bfe0SAlasdair G Kergon 	if (!ps->area)
152*4db6bfe0SAlasdair G Kergon 		return r;
153*4db6bfe0SAlasdair G Kergon 
154*4db6bfe0SAlasdair G Kergon 	ps->zero_area = vmalloc(len);
155*4db6bfe0SAlasdair G Kergon 	if (!ps->zero_area) {
156*4db6bfe0SAlasdair G Kergon 		vfree(ps->area);
157*4db6bfe0SAlasdair G Kergon 		return r;
158*4db6bfe0SAlasdair G Kergon 	}
159*4db6bfe0SAlasdair G Kergon 	memset(ps->zero_area, 0, len);
160*4db6bfe0SAlasdair G Kergon 
161*4db6bfe0SAlasdair G Kergon 	return 0;
162*4db6bfe0SAlasdair G Kergon }
163*4db6bfe0SAlasdair G Kergon 
164*4db6bfe0SAlasdair G Kergon static void free_area(struct pstore *ps)
165*4db6bfe0SAlasdair G Kergon {
166*4db6bfe0SAlasdair G Kergon 	vfree(ps->area);
167*4db6bfe0SAlasdair G Kergon 	ps->area = NULL;
168*4db6bfe0SAlasdair G Kergon 	vfree(ps->zero_area);
169*4db6bfe0SAlasdair G Kergon 	ps->zero_area = NULL;
170*4db6bfe0SAlasdair G Kergon }
171*4db6bfe0SAlasdair G Kergon 
172*4db6bfe0SAlasdair G Kergon struct mdata_req {
173*4db6bfe0SAlasdair G Kergon 	struct dm_io_region *where;
174*4db6bfe0SAlasdair G Kergon 	struct dm_io_request *io_req;
175*4db6bfe0SAlasdair G Kergon 	struct work_struct work;
176*4db6bfe0SAlasdair G Kergon 	int result;
177*4db6bfe0SAlasdair G Kergon };
178*4db6bfe0SAlasdair G Kergon 
179*4db6bfe0SAlasdair G Kergon static void do_metadata(struct work_struct *work)
180*4db6bfe0SAlasdair G Kergon {
181*4db6bfe0SAlasdair G Kergon 	struct mdata_req *req = container_of(work, struct mdata_req, work);
182*4db6bfe0SAlasdair G Kergon 
183*4db6bfe0SAlasdair G Kergon 	req->result = dm_io(req->io_req, 1, req->where, NULL);
184*4db6bfe0SAlasdair G Kergon }
185*4db6bfe0SAlasdair G Kergon 
186*4db6bfe0SAlasdair G Kergon /*
187*4db6bfe0SAlasdair G Kergon  * Read or write a chunk aligned and sized block of data from a device.
188*4db6bfe0SAlasdair G Kergon  */
189*4db6bfe0SAlasdair G Kergon static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
190*4db6bfe0SAlasdair G Kergon {
191*4db6bfe0SAlasdair G Kergon 	struct dm_io_region where = {
192*4db6bfe0SAlasdair G Kergon 		.bdev = ps->snap->cow->bdev,
193*4db6bfe0SAlasdair G Kergon 		.sector = ps->snap->chunk_size * chunk,
194*4db6bfe0SAlasdair G Kergon 		.count = ps->snap->chunk_size,
195*4db6bfe0SAlasdair G Kergon 	};
196*4db6bfe0SAlasdair G Kergon 	struct dm_io_request io_req = {
197*4db6bfe0SAlasdair G Kergon 		.bi_rw = rw,
198*4db6bfe0SAlasdair G Kergon 		.mem.type = DM_IO_VMA,
199*4db6bfe0SAlasdair G Kergon 		.mem.ptr.vma = ps->area,
200*4db6bfe0SAlasdair G Kergon 		.client = ps->io_client,
201*4db6bfe0SAlasdair G Kergon 		.notify.fn = NULL,
202*4db6bfe0SAlasdair G Kergon 	};
203*4db6bfe0SAlasdair G Kergon 	struct mdata_req req;
204*4db6bfe0SAlasdair G Kergon 
205*4db6bfe0SAlasdair G Kergon 	if (!metadata)
206*4db6bfe0SAlasdair G Kergon 		return dm_io(&io_req, 1, &where, NULL);
207*4db6bfe0SAlasdair G Kergon 
208*4db6bfe0SAlasdair G Kergon 	req.where = &where;
209*4db6bfe0SAlasdair G Kergon 	req.io_req = &io_req;
210*4db6bfe0SAlasdair G Kergon 
211*4db6bfe0SAlasdair G Kergon 	/*
212*4db6bfe0SAlasdair G Kergon 	 * Issue the synchronous I/O from a different thread
213*4db6bfe0SAlasdair G Kergon 	 * to avoid generic_make_request recursion.
214*4db6bfe0SAlasdair G Kergon 	 */
215*4db6bfe0SAlasdair G Kergon 	INIT_WORK(&req.work, do_metadata);
216*4db6bfe0SAlasdair G Kergon 	queue_work(ps->metadata_wq, &req.work);
217*4db6bfe0SAlasdair G Kergon 	flush_workqueue(ps->metadata_wq);
218*4db6bfe0SAlasdair G Kergon 
219*4db6bfe0SAlasdair G Kergon 	return req.result;
220*4db6bfe0SAlasdair G Kergon }
221*4db6bfe0SAlasdair G Kergon 
222*4db6bfe0SAlasdair G Kergon /*
223*4db6bfe0SAlasdair G Kergon  * Convert a metadata area index to a chunk index.
224*4db6bfe0SAlasdair G Kergon  */
225*4db6bfe0SAlasdair G Kergon static chunk_t area_location(struct pstore *ps, chunk_t area)
226*4db6bfe0SAlasdair G Kergon {
227*4db6bfe0SAlasdair G Kergon 	return 1 + ((ps->exceptions_per_area + 1) * area);
228*4db6bfe0SAlasdair G Kergon }
229*4db6bfe0SAlasdair G Kergon 
230*4db6bfe0SAlasdair G Kergon /*
231*4db6bfe0SAlasdair G Kergon  * Read or write a metadata area.  Remembering to skip the first
232*4db6bfe0SAlasdair G Kergon  * chunk which holds the header.
233*4db6bfe0SAlasdair G Kergon  */
234*4db6bfe0SAlasdair G Kergon static int area_io(struct pstore *ps, int rw)
235*4db6bfe0SAlasdair G Kergon {
236*4db6bfe0SAlasdair G Kergon 	int r;
237*4db6bfe0SAlasdair G Kergon 	chunk_t chunk;
238*4db6bfe0SAlasdair G Kergon 
239*4db6bfe0SAlasdair G Kergon 	chunk = area_location(ps, ps->current_area);
240*4db6bfe0SAlasdair G Kergon 
241*4db6bfe0SAlasdair G Kergon 	r = chunk_io(ps, chunk, rw, 0);
242*4db6bfe0SAlasdair G Kergon 	if (r)
243*4db6bfe0SAlasdair G Kergon 		return r;
244*4db6bfe0SAlasdair G Kergon 
245*4db6bfe0SAlasdair G Kergon 	return 0;
246*4db6bfe0SAlasdair G Kergon }
247*4db6bfe0SAlasdair G Kergon 
248*4db6bfe0SAlasdair G Kergon static void zero_memory_area(struct pstore *ps)
249*4db6bfe0SAlasdair G Kergon {
250*4db6bfe0SAlasdair G Kergon 	memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
251*4db6bfe0SAlasdair G Kergon }
252*4db6bfe0SAlasdair G Kergon 
253*4db6bfe0SAlasdair G Kergon static int zero_disk_area(struct pstore *ps, chunk_t area)
254*4db6bfe0SAlasdair G Kergon {
255*4db6bfe0SAlasdair G Kergon 	struct dm_io_region where = {
256*4db6bfe0SAlasdair G Kergon 		.bdev = ps->snap->cow->bdev,
257*4db6bfe0SAlasdair G Kergon 		.sector = ps->snap->chunk_size * area_location(ps, area),
258*4db6bfe0SAlasdair G Kergon 		.count = ps->snap->chunk_size,
259*4db6bfe0SAlasdair G Kergon 	};
260*4db6bfe0SAlasdair G Kergon 	struct dm_io_request io_req = {
261*4db6bfe0SAlasdair G Kergon 		.bi_rw = WRITE,
262*4db6bfe0SAlasdair G Kergon 		.mem.type = DM_IO_VMA,
263*4db6bfe0SAlasdair G Kergon 		.mem.ptr.vma = ps->zero_area,
264*4db6bfe0SAlasdair G Kergon 		.client = ps->io_client,
265*4db6bfe0SAlasdair G Kergon 		.notify.fn = NULL,
266*4db6bfe0SAlasdair G Kergon 	};
267*4db6bfe0SAlasdair G Kergon 
268*4db6bfe0SAlasdair G Kergon 	return dm_io(&io_req, 1, &where, NULL);
269*4db6bfe0SAlasdair G Kergon }
270*4db6bfe0SAlasdair G Kergon 
271*4db6bfe0SAlasdair G Kergon static int read_header(struct pstore *ps, int *new_snapshot)
272*4db6bfe0SAlasdair G Kergon {
273*4db6bfe0SAlasdair G Kergon 	int r;
274*4db6bfe0SAlasdair G Kergon 	struct disk_header *dh;
275*4db6bfe0SAlasdair G Kergon 	chunk_t chunk_size;
276*4db6bfe0SAlasdair G Kergon 	int chunk_size_supplied = 1;
277*4db6bfe0SAlasdair G Kergon 
278*4db6bfe0SAlasdair G Kergon 	/*
279*4db6bfe0SAlasdair G Kergon 	 * Use default chunk size (or hardsect_size, if larger) if none supplied
280*4db6bfe0SAlasdair G Kergon 	 */
281*4db6bfe0SAlasdair G Kergon 	if (!ps->snap->chunk_size) {
282*4db6bfe0SAlasdair G Kergon 		ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
283*4db6bfe0SAlasdair G Kergon 		    bdev_hardsect_size(ps->snap->cow->bdev) >> 9);
284*4db6bfe0SAlasdair G Kergon 		ps->snap->chunk_mask = ps->snap->chunk_size - 1;
285*4db6bfe0SAlasdair G Kergon 		ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1;
286*4db6bfe0SAlasdair G Kergon 		chunk_size_supplied = 0;
287*4db6bfe0SAlasdair G Kergon 	}
288*4db6bfe0SAlasdair G Kergon 
289*4db6bfe0SAlasdair G Kergon 	ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
290*4db6bfe0SAlasdair G Kergon 							     chunk_size));
291*4db6bfe0SAlasdair G Kergon 	if (IS_ERR(ps->io_client))
292*4db6bfe0SAlasdair G Kergon 		return PTR_ERR(ps->io_client);
293*4db6bfe0SAlasdair G Kergon 
294*4db6bfe0SAlasdair G Kergon 	r = alloc_area(ps);
295*4db6bfe0SAlasdair G Kergon 	if (r)
296*4db6bfe0SAlasdair G Kergon 		return r;
297*4db6bfe0SAlasdair G Kergon 
298*4db6bfe0SAlasdair G Kergon 	r = chunk_io(ps, 0, READ, 1);
299*4db6bfe0SAlasdair G Kergon 	if (r)
300*4db6bfe0SAlasdair G Kergon 		goto bad;
301*4db6bfe0SAlasdair G Kergon 
302*4db6bfe0SAlasdair G Kergon 	dh = (struct disk_header *) ps->area;
303*4db6bfe0SAlasdair G Kergon 
304*4db6bfe0SAlasdair G Kergon 	if (le32_to_cpu(dh->magic) == 0) {
305*4db6bfe0SAlasdair G Kergon 		*new_snapshot = 1;
306*4db6bfe0SAlasdair G Kergon 		return 0;
307*4db6bfe0SAlasdair G Kergon 	}
308*4db6bfe0SAlasdair G Kergon 
309*4db6bfe0SAlasdair G Kergon 	if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
310*4db6bfe0SAlasdair G Kergon 		DMWARN("Invalid or corrupt snapshot");
311*4db6bfe0SAlasdair G Kergon 		r = -ENXIO;
312*4db6bfe0SAlasdair G Kergon 		goto bad;
313*4db6bfe0SAlasdair G Kergon 	}
314*4db6bfe0SAlasdair G Kergon 
315*4db6bfe0SAlasdair G Kergon 	*new_snapshot = 0;
316*4db6bfe0SAlasdair G Kergon 	ps->valid = le32_to_cpu(dh->valid);
317*4db6bfe0SAlasdair G Kergon 	ps->version = le32_to_cpu(dh->version);
318*4db6bfe0SAlasdair G Kergon 	chunk_size = le32_to_cpu(dh->chunk_size);
319*4db6bfe0SAlasdair G Kergon 
320*4db6bfe0SAlasdair G Kergon 	if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size)
321*4db6bfe0SAlasdair G Kergon 		return 0;
322*4db6bfe0SAlasdair G Kergon 
323*4db6bfe0SAlasdair G Kergon 	DMWARN("chunk size %llu in device metadata overrides "
324*4db6bfe0SAlasdair G Kergon 	       "table chunk size of %llu.",
325*4db6bfe0SAlasdair G Kergon 	       (unsigned long long)chunk_size,
326*4db6bfe0SAlasdair G Kergon 	       (unsigned long long)ps->snap->chunk_size);
327*4db6bfe0SAlasdair G Kergon 
328*4db6bfe0SAlasdair G Kergon 	/* We had a bogus chunk_size. Fix stuff up. */
329*4db6bfe0SAlasdair G Kergon 	free_area(ps);
330*4db6bfe0SAlasdair G Kergon 
331*4db6bfe0SAlasdair G Kergon 	ps->snap->chunk_size = chunk_size;
332*4db6bfe0SAlasdair G Kergon 	ps->snap->chunk_mask = chunk_size - 1;
333*4db6bfe0SAlasdair G Kergon 	ps->snap->chunk_shift = ffs(chunk_size) - 1;
334*4db6bfe0SAlasdair G Kergon 
335*4db6bfe0SAlasdair G Kergon 	r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
336*4db6bfe0SAlasdair G Kergon 				ps->io_client);
337*4db6bfe0SAlasdair G Kergon 	if (r)
338*4db6bfe0SAlasdair G Kergon 		return r;
339*4db6bfe0SAlasdair G Kergon 
340*4db6bfe0SAlasdair G Kergon 	r = alloc_area(ps);
341*4db6bfe0SAlasdair G Kergon 	return r;
342*4db6bfe0SAlasdair G Kergon 
343*4db6bfe0SAlasdair G Kergon bad:
344*4db6bfe0SAlasdair G Kergon 	free_area(ps);
345*4db6bfe0SAlasdair G Kergon 	return r;
346*4db6bfe0SAlasdair G Kergon }
347*4db6bfe0SAlasdair G Kergon 
348*4db6bfe0SAlasdair G Kergon static int write_header(struct pstore *ps)
349*4db6bfe0SAlasdair G Kergon {
350*4db6bfe0SAlasdair G Kergon 	struct disk_header *dh;
351*4db6bfe0SAlasdair G Kergon 
352*4db6bfe0SAlasdair G Kergon 	memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
353*4db6bfe0SAlasdair G Kergon 
354*4db6bfe0SAlasdair G Kergon 	dh = (struct disk_header *) ps->area;
355*4db6bfe0SAlasdair G Kergon 	dh->magic = cpu_to_le32(SNAP_MAGIC);
356*4db6bfe0SAlasdair G Kergon 	dh->valid = cpu_to_le32(ps->valid);
357*4db6bfe0SAlasdair G Kergon 	dh->version = cpu_to_le32(ps->version);
358*4db6bfe0SAlasdair G Kergon 	dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
359*4db6bfe0SAlasdair G Kergon 
360*4db6bfe0SAlasdair G Kergon 	return chunk_io(ps, 0, WRITE, 1);
361*4db6bfe0SAlasdair G Kergon }
362*4db6bfe0SAlasdair G Kergon 
363*4db6bfe0SAlasdair G Kergon /*
364*4db6bfe0SAlasdair G Kergon  * Access functions for the disk exceptions, these do the endian conversions.
365*4db6bfe0SAlasdair G Kergon  */
366*4db6bfe0SAlasdair G Kergon static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
367*4db6bfe0SAlasdair G Kergon {
368*4db6bfe0SAlasdair G Kergon 	BUG_ON(index >= ps->exceptions_per_area);
369*4db6bfe0SAlasdair G Kergon 
370*4db6bfe0SAlasdair G Kergon 	return ((struct disk_exception *) ps->area) + index;
371*4db6bfe0SAlasdair G Kergon }
372*4db6bfe0SAlasdair G Kergon 
373*4db6bfe0SAlasdair G Kergon static void read_exception(struct pstore *ps,
374*4db6bfe0SAlasdair G Kergon 			   uint32_t index, struct disk_exception *result)
375*4db6bfe0SAlasdair G Kergon {
376*4db6bfe0SAlasdair G Kergon 	struct disk_exception *e = get_exception(ps, index);
377*4db6bfe0SAlasdair G Kergon 
378*4db6bfe0SAlasdair G Kergon 	/* copy it */
379*4db6bfe0SAlasdair G Kergon 	result->old_chunk = le64_to_cpu(e->old_chunk);
380*4db6bfe0SAlasdair G Kergon 	result->new_chunk = le64_to_cpu(e->new_chunk);
381*4db6bfe0SAlasdair G Kergon }
382*4db6bfe0SAlasdair G Kergon 
383*4db6bfe0SAlasdair G Kergon static void write_exception(struct pstore *ps,
384*4db6bfe0SAlasdair G Kergon 			    uint32_t index, struct disk_exception *de)
385*4db6bfe0SAlasdair G Kergon {
386*4db6bfe0SAlasdair G Kergon 	struct disk_exception *e = get_exception(ps, index);
387*4db6bfe0SAlasdair G Kergon 
388*4db6bfe0SAlasdair G Kergon 	/* copy it */
389*4db6bfe0SAlasdair G Kergon 	e->old_chunk = cpu_to_le64(de->old_chunk);
390*4db6bfe0SAlasdair G Kergon 	e->new_chunk = cpu_to_le64(de->new_chunk);
391*4db6bfe0SAlasdair G Kergon }
392*4db6bfe0SAlasdair G Kergon 
393*4db6bfe0SAlasdair G Kergon /*
394*4db6bfe0SAlasdair G Kergon  * Registers the exceptions that are present in the current area.
395*4db6bfe0SAlasdair G Kergon  * 'full' is filled in to indicate if the area has been
396*4db6bfe0SAlasdair G Kergon  * filled.
397*4db6bfe0SAlasdair G Kergon  */
398*4db6bfe0SAlasdair G Kergon static int insert_exceptions(struct pstore *ps, int *full)
399*4db6bfe0SAlasdair G Kergon {
400*4db6bfe0SAlasdair G Kergon 	int r;
401*4db6bfe0SAlasdair G Kergon 	unsigned int i;
402*4db6bfe0SAlasdair G Kergon 	struct disk_exception de;
403*4db6bfe0SAlasdair G Kergon 
404*4db6bfe0SAlasdair G Kergon 	/* presume the area is full */
405*4db6bfe0SAlasdair G Kergon 	*full = 1;
406*4db6bfe0SAlasdair G Kergon 
407*4db6bfe0SAlasdair G Kergon 	for (i = 0; i < ps->exceptions_per_area; i++) {
408*4db6bfe0SAlasdair G Kergon 		read_exception(ps, i, &de);
409*4db6bfe0SAlasdair G Kergon 
410*4db6bfe0SAlasdair G Kergon 		/*
411*4db6bfe0SAlasdair G Kergon 		 * If the new_chunk is pointing at the start of
412*4db6bfe0SAlasdair G Kergon 		 * the COW device, where the first metadata area
413*4db6bfe0SAlasdair G Kergon 		 * is we know that we've hit the end of the
414*4db6bfe0SAlasdair G Kergon 		 * exceptions.  Therefore the area is not full.
415*4db6bfe0SAlasdair G Kergon 		 */
416*4db6bfe0SAlasdair G Kergon 		if (de.new_chunk == 0LL) {
417*4db6bfe0SAlasdair G Kergon 			ps->current_committed = i;
418*4db6bfe0SAlasdair G Kergon 			*full = 0;
419*4db6bfe0SAlasdair G Kergon 			break;
420*4db6bfe0SAlasdair G Kergon 		}
421*4db6bfe0SAlasdair G Kergon 
422*4db6bfe0SAlasdair G Kergon 		/*
423*4db6bfe0SAlasdair G Kergon 		 * Keep track of the start of the free chunks.
424*4db6bfe0SAlasdair G Kergon 		 */
425*4db6bfe0SAlasdair G Kergon 		if (ps->next_free <= de.new_chunk)
426*4db6bfe0SAlasdair G Kergon 			ps->next_free = de.new_chunk + 1;
427*4db6bfe0SAlasdair G Kergon 
428*4db6bfe0SAlasdair G Kergon 		/*
429*4db6bfe0SAlasdair G Kergon 		 * Otherwise we add the exception to the snapshot.
430*4db6bfe0SAlasdair G Kergon 		 */
431*4db6bfe0SAlasdair G Kergon 		r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk);
432*4db6bfe0SAlasdair G Kergon 		if (r)
433*4db6bfe0SAlasdair G Kergon 			return r;
434*4db6bfe0SAlasdair G Kergon 	}
435*4db6bfe0SAlasdair G Kergon 
436*4db6bfe0SAlasdair G Kergon 	return 0;
437*4db6bfe0SAlasdair G Kergon }
438*4db6bfe0SAlasdair G Kergon 
439*4db6bfe0SAlasdair G Kergon static int read_exceptions(struct pstore *ps)
440*4db6bfe0SAlasdair G Kergon {
441*4db6bfe0SAlasdair G Kergon 	int r, full = 1;
442*4db6bfe0SAlasdair G Kergon 
443*4db6bfe0SAlasdair G Kergon 	/*
444*4db6bfe0SAlasdair G Kergon 	 * Keeping reading chunks and inserting exceptions until
445*4db6bfe0SAlasdair G Kergon 	 * we find a partially full area.
446*4db6bfe0SAlasdair G Kergon 	 */
447*4db6bfe0SAlasdair G Kergon 	for (ps->current_area = 0; full; ps->current_area++) {
448*4db6bfe0SAlasdair G Kergon 		r = area_io(ps, READ);
449*4db6bfe0SAlasdair G Kergon 		if (r)
450*4db6bfe0SAlasdair G Kergon 			return r;
451*4db6bfe0SAlasdair G Kergon 
452*4db6bfe0SAlasdair G Kergon 		r = insert_exceptions(ps, &full);
453*4db6bfe0SAlasdair G Kergon 		if (r)
454*4db6bfe0SAlasdair G Kergon 			return r;
455*4db6bfe0SAlasdair G Kergon 	}
456*4db6bfe0SAlasdair G Kergon 
457*4db6bfe0SAlasdair G Kergon 	ps->current_area--;
458*4db6bfe0SAlasdair G Kergon 
459*4db6bfe0SAlasdair G Kergon 	return 0;
460*4db6bfe0SAlasdair G Kergon }
461*4db6bfe0SAlasdair G Kergon 
462*4db6bfe0SAlasdair G Kergon static struct pstore *get_info(struct dm_exception_store *store)
463*4db6bfe0SAlasdair G Kergon {
464*4db6bfe0SAlasdair G Kergon 	return (struct pstore *) store->context;
465*4db6bfe0SAlasdair G Kergon }
466*4db6bfe0SAlasdair G Kergon 
467*4db6bfe0SAlasdair G Kergon static void persistent_fraction_full(struct dm_exception_store *store,
468*4db6bfe0SAlasdair G Kergon 				     sector_t *numerator, sector_t *denominator)
469*4db6bfe0SAlasdair G Kergon {
470*4db6bfe0SAlasdair G Kergon 	*numerator = get_info(store)->next_free * store->snap->chunk_size;
471*4db6bfe0SAlasdair G Kergon 	*denominator = get_dev_size(store->snap->cow->bdev);
472*4db6bfe0SAlasdair G Kergon }
473*4db6bfe0SAlasdair G Kergon 
474*4db6bfe0SAlasdair G Kergon static void persistent_destroy(struct dm_exception_store *store)
475*4db6bfe0SAlasdair G Kergon {
476*4db6bfe0SAlasdair G Kergon 	struct pstore *ps = get_info(store);
477*4db6bfe0SAlasdair G Kergon 
478*4db6bfe0SAlasdair G Kergon 	destroy_workqueue(ps->metadata_wq);
479*4db6bfe0SAlasdair G Kergon 	dm_io_client_destroy(ps->io_client);
480*4db6bfe0SAlasdair G Kergon 	vfree(ps->callbacks);
481*4db6bfe0SAlasdair G Kergon 	free_area(ps);
482*4db6bfe0SAlasdair G Kergon 	kfree(ps);
483*4db6bfe0SAlasdair G Kergon }
484*4db6bfe0SAlasdair G Kergon 
485*4db6bfe0SAlasdair G Kergon static int persistent_read_metadata(struct dm_exception_store *store)
486*4db6bfe0SAlasdair G Kergon {
487*4db6bfe0SAlasdair G Kergon 	int r, uninitialized_var(new_snapshot);
488*4db6bfe0SAlasdair G Kergon 	struct pstore *ps = get_info(store);
489*4db6bfe0SAlasdair G Kergon 
490*4db6bfe0SAlasdair G Kergon 	/*
491*4db6bfe0SAlasdair G Kergon 	 * Read the snapshot header.
492*4db6bfe0SAlasdair G Kergon 	 */
493*4db6bfe0SAlasdair G Kergon 	r = read_header(ps, &new_snapshot);
494*4db6bfe0SAlasdair G Kergon 	if (r)
495*4db6bfe0SAlasdair G Kergon 		return r;
496*4db6bfe0SAlasdair G Kergon 
497*4db6bfe0SAlasdair G Kergon 	/*
498*4db6bfe0SAlasdair G Kergon 	 * Now we know correct chunk_size, complete the initialisation.
499*4db6bfe0SAlasdair G Kergon 	 */
500*4db6bfe0SAlasdair G Kergon 	ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
501*4db6bfe0SAlasdair G Kergon 				  sizeof(struct disk_exception);
502*4db6bfe0SAlasdair G Kergon 	ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
503*4db6bfe0SAlasdair G Kergon 			sizeof(*ps->callbacks));
504*4db6bfe0SAlasdair G Kergon 	if (!ps->callbacks)
505*4db6bfe0SAlasdair G Kergon 		return -ENOMEM;
506*4db6bfe0SAlasdair G Kergon 
507*4db6bfe0SAlasdair G Kergon 	/*
508*4db6bfe0SAlasdair G Kergon 	 * Do we need to setup a new snapshot ?
509*4db6bfe0SAlasdair G Kergon 	 */
510*4db6bfe0SAlasdair G Kergon 	if (new_snapshot) {
511*4db6bfe0SAlasdair G Kergon 		r = write_header(ps);
512*4db6bfe0SAlasdair G Kergon 		if (r) {
513*4db6bfe0SAlasdair G Kergon 			DMWARN("write_header failed");
514*4db6bfe0SAlasdair G Kergon 			return r;
515*4db6bfe0SAlasdair G Kergon 		}
516*4db6bfe0SAlasdair G Kergon 
517*4db6bfe0SAlasdair G Kergon 		ps->current_area = 0;
518*4db6bfe0SAlasdair G Kergon 		zero_memory_area(ps);
519*4db6bfe0SAlasdair G Kergon 		r = zero_disk_area(ps, 0);
520*4db6bfe0SAlasdair G Kergon 		if (r) {
521*4db6bfe0SAlasdair G Kergon 			DMWARN("zero_disk_area(0) failed");
522*4db6bfe0SAlasdair G Kergon 			return r;
523*4db6bfe0SAlasdair G Kergon 		}
524*4db6bfe0SAlasdair G Kergon 	} else {
525*4db6bfe0SAlasdair G Kergon 		/*
526*4db6bfe0SAlasdair G Kergon 		 * Sanity checks.
527*4db6bfe0SAlasdair G Kergon 		 */
528*4db6bfe0SAlasdair G Kergon 		if (ps->version != SNAPSHOT_DISK_VERSION) {
529*4db6bfe0SAlasdair G Kergon 			DMWARN("unable to handle snapshot disk version %d",
530*4db6bfe0SAlasdair G Kergon 			       ps->version);
531*4db6bfe0SAlasdair G Kergon 			return -EINVAL;
532*4db6bfe0SAlasdair G Kergon 		}
533*4db6bfe0SAlasdair G Kergon 
534*4db6bfe0SAlasdair G Kergon 		/*
535*4db6bfe0SAlasdair G Kergon 		 * Metadata are valid, but snapshot is invalidated
536*4db6bfe0SAlasdair G Kergon 		 */
537*4db6bfe0SAlasdair G Kergon 		if (!ps->valid)
538*4db6bfe0SAlasdair G Kergon 			return 1;
539*4db6bfe0SAlasdair G Kergon 
540*4db6bfe0SAlasdair G Kergon 		/*
541*4db6bfe0SAlasdair G Kergon 		 * Read the metadata.
542*4db6bfe0SAlasdair G Kergon 		 */
543*4db6bfe0SAlasdair G Kergon 		r = read_exceptions(ps);
544*4db6bfe0SAlasdair G Kergon 		if (r)
545*4db6bfe0SAlasdair G Kergon 			return r;
546*4db6bfe0SAlasdair G Kergon 	}
547*4db6bfe0SAlasdair G Kergon 
548*4db6bfe0SAlasdair G Kergon 	return 0;
549*4db6bfe0SAlasdair G Kergon }
550*4db6bfe0SAlasdair G Kergon 
551*4db6bfe0SAlasdair G Kergon static int persistent_prepare(struct dm_exception_store *store,
552*4db6bfe0SAlasdair G Kergon 			      struct dm_snap_exception *e)
553*4db6bfe0SAlasdair G Kergon {
554*4db6bfe0SAlasdair G Kergon 	struct pstore *ps = get_info(store);
555*4db6bfe0SAlasdair G Kergon 	uint32_t stride;
556*4db6bfe0SAlasdair G Kergon 	chunk_t next_free;
557*4db6bfe0SAlasdair G Kergon 	sector_t size = get_dev_size(store->snap->cow->bdev);
558*4db6bfe0SAlasdair G Kergon 
559*4db6bfe0SAlasdair G Kergon 	/* Is there enough room ? */
560*4db6bfe0SAlasdair G Kergon 	if (size < ((ps->next_free + 1) * store->snap->chunk_size))
561*4db6bfe0SAlasdair G Kergon 		return -ENOSPC;
562*4db6bfe0SAlasdair G Kergon 
563*4db6bfe0SAlasdair G Kergon 	e->new_chunk = ps->next_free;
564*4db6bfe0SAlasdair G Kergon 
565*4db6bfe0SAlasdair G Kergon 	/*
566*4db6bfe0SAlasdair G Kergon 	 * Move onto the next free pending, making sure to take
567*4db6bfe0SAlasdair G Kergon 	 * into account the location of the metadata chunks.
568*4db6bfe0SAlasdair G Kergon 	 */
569*4db6bfe0SAlasdair G Kergon 	stride = (ps->exceptions_per_area + 1);
570*4db6bfe0SAlasdair G Kergon 	next_free = ++ps->next_free;
571*4db6bfe0SAlasdair G Kergon 	if (sector_div(next_free, stride) == 1)
572*4db6bfe0SAlasdair G Kergon 		ps->next_free++;
573*4db6bfe0SAlasdair G Kergon 
574*4db6bfe0SAlasdair G Kergon 	atomic_inc(&ps->pending_count);
575*4db6bfe0SAlasdair G Kergon 	return 0;
576*4db6bfe0SAlasdair G Kergon }
577*4db6bfe0SAlasdair G Kergon 
578*4db6bfe0SAlasdair G Kergon static void persistent_commit(struct dm_exception_store *store,
579*4db6bfe0SAlasdair G Kergon 			      struct dm_snap_exception *e,
580*4db6bfe0SAlasdair G Kergon 			      void (*callback) (void *, int success),
581*4db6bfe0SAlasdair G Kergon 			      void *callback_context)
582*4db6bfe0SAlasdair G Kergon {
583*4db6bfe0SAlasdair G Kergon 	unsigned int i;
584*4db6bfe0SAlasdair G Kergon 	struct pstore *ps = get_info(store);
585*4db6bfe0SAlasdair G Kergon 	struct disk_exception de;
586*4db6bfe0SAlasdair G Kergon 	struct commit_callback *cb;
587*4db6bfe0SAlasdair G Kergon 
588*4db6bfe0SAlasdair G Kergon 	de.old_chunk = e->old_chunk;
589*4db6bfe0SAlasdair G Kergon 	de.new_chunk = e->new_chunk;
590*4db6bfe0SAlasdair G Kergon 	write_exception(ps, ps->current_committed++, &de);
591*4db6bfe0SAlasdair G Kergon 
592*4db6bfe0SAlasdair G Kergon 	/*
593*4db6bfe0SAlasdair G Kergon 	 * Add the callback to the back of the array.  This code
594*4db6bfe0SAlasdair G Kergon 	 * is the only place where the callback array is
595*4db6bfe0SAlasdair G Kergon 	 * manipulated, and we know that it will never be called
596*4db6bfe0SAlasdair G Kergon 	 * multiple times concurrently.
597*4db6bfe0SAlasdair G Kergon 	 */
598*4db6bfe0SAlasdair G Kergon 	cb = ps->callbacks + ps->callback_count++;
599*4db6bfe0SAlasdair G Kergon 	cb->callback = callback;
600*4db6bfe0SAlasdair G Kergon 	cb->context = callback_context;
601*4db6bfe0SAlasdair G Kergon 
602*4db6bfe0SAlasdair G Kergon 	/*
603*4db6bfe0SAlasdair G Kergon 	 * If there are exceptions in flight and we have not yet
604*4db6bfe0SAlasdair G Kergon 	 * filled this metadata area there's nothing more to do.
605*4db6bfe0SAlasdair G Kergon 	 */
606*4db6bfe0SAlasdair G Kergon 	if (!atomic_dec_and_test(&ps->pending_count) &&
607*4db6bfe0SAlasdair G Kergon 	    (ps->current_committed != ps->exceptions_per_area))
608*4db6bfe0SAlasdair G Kergon 		return;
609*4db6bfe0SAlasdair G Kergon 
610*4db6bfe0SAlasdair G Kergon 	/*
611*4db6bfe0SAlasdair G Kergon 	 * If we completely filled the current area, then wipe the next one.
612*4db6bfe0SAlasdair G Kergon 	 */
613*4db6bfe0SAlasdair G Kergon 	if ((ps->current_committed == ps->exceptions_per_area) &&
614*4db6bfe0SAlasdair G Kergon 	     zero_disk_area(ps, ps->current_area + 1))
615*4db6bfe0SAlasdair G Kergon 		ps->valid = 0;
616*4db6bfe0SAlasdair G Kergon 
617*4db6bfe0SAlasdair G Kergon 	/*
618*4db6bfe0SAlasdair G Kergon 	 * Commit exceptions to disk.
619*4db6bfe0SAlasdair G Kergon 	 */
620*4db6bfe0SAlasdair G Kergon 	if (ps->valid && area_io(ps, WRITE))
621*4db6bfe0SAlasdair G Kergon 		ps->valid = 0;
622*4db6bfe0SAlasdair G Kergon 
623*4db6bfe0SAlasdair G Kergon 	/*
624*4db6bfe0SAlasdair G Kergon 	 * Advance to the next area if this one is full.
625*4db6bfe0SAlasdair G Kergon 	 */
626*4db6bfe0SAlasdair G Kergon 	if (ps->current_committed == ps->exceptions_per_area) {
627*4db6bfe0SAlasdair G Kergon 		ps->current_committed = 0;
628*4db6bfe0SAlasdair G Kergon 		ps->current_area++;
629*4db6bfe0SAlasdair G Kergon 		zero_memory_area(ps);
630*4db6bfe0SAlasdair G Kergon 	}
631*4db6bfe0SAlasdair G Kergon 
632*4db6bfe0SAlasdair G Kergon 	for (i = 0; i < ps->callback_count; i++) {
633*4db6bfe0SAlasdair G Kergon 		cb = ps->callbacks + i;
634*4db6bfe0SAlasdair G Kergon 		cb->callback(cb->context, ps->valid);
635*4db6bfe0SAlasdair G Kergon 	}
636*4db6bfe0SAlasdair G Kergon 
637*4db6bfe0SAlasdair G Kergon 	ps->callback_count = 0;
638*4db6bfe0SAlasdair G Kergon }
639*4db6bfe0SAlasdair G Kergon 
640*4db6bfe0SAlasdair G Kergon static void persistent_drop(struct dm_exception_store *store)
641*4db6bfe0SAlasdair G Kergon {
642*4db6bfe0SAlasdair G Kergon 	struct pstore *ps = get_info(store);
643*4db6bfe0SAlasdair G Kergon 
644*4db6bfe0SAlasdair G Kergon 	ps->valid = 0;
645*4db6bfe0SAlasdair G Kergon 	if (write_header(ps))
646*4db6bfe0SAlasdair G Kergon 		DMWARN("write header failed");
647*4db6bfe0SAlasdair G Kergon }
648*4db6bfe0SAlasdair G Kergon 
649*4db6bfe0SAlasdair G Kergon int dm_create_persistent(struct dm_exception_store *store)
650*4db6bfe0SAlasdair G Kergon {
651*4db6bfe0SAlasdair G Kergon 	struct pstore *ps;
652*4db6bfe0SAlasdair G Kergon 
653*4db6bfe0SAlasdair G Kergon 	/* allocate the pstore */
654*4db6bfe0SAlasdair G Kergon 	ps = kmalloc(sizeof(*ps), GFP_KERNEL);
655*4db6bfe0SAlasdair G Kergon 	if (!ps)
656*4db6bfe0SAlasdair G Kergon 		return -ENOMEM;
657*4db6bfe0SAlasdair G Kergon 
658*4db6bfe0SAlasdair G Kergon 	ps->snap = store->snap;
659*4db6bfe0SAlasdair G Kergon 	ps->valid = 1;
660*4db6bfe0SAlasdair G Kergon 	ps->version = SNAPSHOT_DISK_VERSION;
661*4db6bfe0SAlasdair G Kergon 	ps->area = NULL;
662*4db6bfe0SAlasdair G Kergon 	ps->next_free = 2;	/* skipping the header and first area */
663*4db6bfe0SAlasdair G Kergon 	ps->current_committed = 0;
664*4db6bfe0SAlasdair G Kergon 
665*4db6bfe0SAlasdair G Kergon 	ps->callback_count = 0;
666*4db6bfe0SAlasdair G Kergon 	atomic_set(&ps->pending_count, 0);
667*4db6bfe0SAlasdair G Kergon 	ps->callbacks = NULL;
668*4db6bfe0SAlasdair G Kergon 
669*4db6bfe0SAlasdair G Kergon 	ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
670*4db6bfe0SAlasdair G Kergon 	if (!ps->metadata_wq) {
671*4db6bfe0SAlasdair G Kergon 		kfree(ps);
672*4db6bfe0SAlasdair G Kergon 		DMERR("couldn't start header metadata update thread");
673*4db6bfe0SAlasdair G Kergon 		return -ENOMEM;
674*4db6bfe0SAlasdair G Kergon 	}
675*4db6bfe0SAlasdair G Kergon 
676*4db6bfe0SAlasdair G Kergon 	store->destroy = persistent_destroy;
677*4db6bfe0SAlasdair G Kergon 	store->read_metadata = persistent_read_metadata;
678*4db6bfe0SAlasdair G Kergon 	store->prepare_exception = persistent_prepare;
679*4db6bfe0SAlasdair G Kergon 	store->commit_exception = persistent_commit;
680*4db6bfe0SAlasdair G Kergon 	store->drop_snapshot = persistent_drop;
681*4db6bfe0SAlasdair G Kergon 	store->fraction_full = persistent_fraction_full;
682*4db6bfe0SAlasdair G Kergon 	store->context = ps;
683*4db6bfe0SAlasdair G Kergon 
684*4db6bfe0SAlasdair G Kergon 	return 0;
685*4db6bfe0SAlasdair G Kergon }
686*4db6bfe0SAlasdair G Kergon 
687*4db6bfe0SAlasdair G Kergon int dm_persistent_snapshot_init(void)
688*4db6bfe0SAlasdair G Kergon {
689*4db6bfe0SAlasdair G Kergon 	return 0;
690*4db6bfe0SAlasdair G Kergon }
691*4db6bfe0SAlasdair G Kergon 
692*4db6bfe0SAlasdair G Kergon void dm_persistent_snapshot_exit(void)
693*4db6bfe0SAlasdair G Kergon {
694*4db6bfe0SAlasdair G Kergon }
695