Blame view

drivers/md/dm-snap.c 52.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
  /*
   * dm-snapshot.c
   *
   * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
   *
   * This file is released under the GPL.
   */
  
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/device-mapper.h>
90fa1527b   Mikulas Patocka   dm snapshot: chan...
11
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
  #include <linux/fs.h>
  #include <linux/init.h>
  #include <linux/kdev_t.h>
  #include <linux/list.h>
  #include <linux/mempool.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/vmalloc.h>
6f3c3f0af   vignesh babu   dm: use is_power_...
20
  #include <linux/log2.h>
a765e20ee   Alasdair G Kergon   dm: move include ...
21
  #include <linux/dm-kcopyd.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22

aea53d92f   Jonathan Brassow   dm snapshot: sepa...
23
  #include "dm-exception-store.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

72d948616   Alasdair G Kergon   [PATCH] dm: impro...
25
  #define DM_MSG_PREFIX "snapshots"
d698aa450   Mikulas Patocka   dm snapshot: add ...
26
27
28
29
  static const char dm_snapshot_merge_target_name[] = "snapshot-merge";
  
  #define dm_target_is_snapshot_merge(ti) \
  	((ti)->type->name == dm_snapshot_merge_target_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  /*
cd45daffd   Mikulas Patocka   dm snapshot: trac...
31
32
33
   * The size of the mempool used to track chunks in use.
   */
  #define MIN_IOS 256
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
34
35
36
  #define DM_TRACKED_CHUNK_HASH_SIZE	16
  #define DM_TRACKED_CHUNK_HASH(x)	((unsigned long)(x) & \
  					 (DM_TRACKED_CHUNK_HASH_SIZE - 1))
191437a53   Jon Brassow   dm snapshot: rena...
37
  struct dm_exception_table {
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
38
39
40
41
42
43
44
45
46
  	uint32_t hash_mask;
  	unsigned hash_shift;
  	struct list_head *table;
  };
  
  struct dm_snapshot {
  	struct rw_semaphore lock;
  
  	struct dm_dev *origin;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
47
48
49
  	struct dm_dev *cow;
  
  	struct dm_target *ti;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
50
51
52
  
  	/* List of snapshots per Origin */
  	struct list_head list;
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
53
54
55
56
  	/*
  	 * You can't use a snapshot if this is 0 (e.g. if full).
  	 * A snapshot-merge target never clears this.
  	 */
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
57
58
59
60
  	int valid;
  
  	/* Origin writes don't trigger exceptions until this is set */
  	int active;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
61
  	atomic_t pending_exceptions_count;
924e600d4   Mike Snitzer   dm: eliminate som...
62
  	mempool_t *pending_pool;
191437a53   Jon Brassow   dm snapshot: rena...
63
64
  	struct dm_exception_table pending;
  	struct dm_exception_table complete;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
65
66
67
68
69
70
  
  	/*
  	 * pe_lock protects all pending_exception operations and access
  	 * as well as the snapshot_bios list.
  	 */
  	spinlock_t pe_lock;
924e600d4   Mike Snitzer   dm: eliminate som...
71
72
73
74
  	/* Chunks with outstanding reads */
  	spinlock_t tracked_chunk_lock;
  	mempool_t *tracked_chunk_pool;
  	struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
75
76
77
78
  	/* The on disk metadata handler */
  	struct dm_exception_store *store;
  
  	struct dm_kcopyd_client *kcopyd_client;
924e600d4   Mike Snitzer   dm: eliminate som...
79
80
81
82
83
84
  	/* Wait for events based on state_bits */
  	unsigned long state_bits;
  
  	/* Range of chunks currently being merged. */
  	chunk_t first_merging_chunk;
  	int num_merging_chunks;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
85

d8ddb1cff   Mike Snitzer   dm snapshot: repo...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  	/*
  	 * The merge operation failed if this flag is set.
  	 * Failure modes are handled as follows:
  	 * - I/O error reading the header
  	 *   	=> don't load the target; abort.
  	 * - Header does not have "valid" flag set
  	 *   	=> use the origin; forget about the snapshot.
  	 * - I/O error when reading exceptions
  	 *   	=> don't load the target; abort.
  	 *         (We can't use the intermediate origin state.)
  	 * - I/O error while merging
  	 *	=> stop merging; set merge_failed; process I/O normally.
  	 */
  	int merge_failed;
9fe862548   Mikulas Patocka   dm snapshot: queu...
100
101
102
103
104
  	/*
  	 * Incoming bios that overlap with chunks being merged must wait
  	 * for them to be committed.
  	 */
  	struct bio_list bios_queued_during_merge;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
105
  };
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
106
107
108
109
110
111
112
113
  /*
   * state_bits:
   *   RUNNING_MERGE  - Merge operation is in progress.
   *   SHUTDOWN_MERGE - Set to signal that merge needs to be stopped;
   *                    cleared afterwards.
   */
  #define RUNNING_MERGE          0
  #define SHUTDOWN_MERGE         1
c24110450   Mikulas Patocka   dm snapshot: test...
114
115
116
117
118
  struct dm_dev *dm_snap_origin(struct dm_snapshot *s)
  {
  	return s->origin;
  }
  EXPORT_SYMBOL(dm_snap_origin);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
119
120
121
122
123
  struct dm_dev *dm_snap_cow(struct dm_snapshot *s)
  {
  	return s->cow;
  }
  EXPORT_SYMBOL(dm_snap_cow);
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  static sector_t chunk_to_sector(struct dm_exception_store *store,
  				chunk_t chunk)
  {
  	return chunk << store->chunk_shift;
  }
  
  static int bdev_equal(struct block_device *lhs, struct block_device *rhs)
  {
  	/*
  	 * There is only ever one instance of a particular block
  	 * device so we can compare pointers safely.
  	 */
  	return lhs == rhs;
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
138
  struct dm_snap_pending_exception {
1d4989c85   Jon Brassow   dm snapshot: rena...
139
  	struct dm_exception e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
142
143
144
145
146
  
  	/*
  	 * Origin buffers waiting for this to complete are held
  	 * in a bio list
  	 */
  	struct bio_list origin_bios;
  	struct bio_list snapshot_bios;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
150
151
152
153
154
  	/* Pointer back to snapshot context */
  	struct dm_snapshot *snap;
  
  	/*
  	 * 1 indicates the exception has already been sent to
  	 * kcopyd.
  	 */
  	int started;
a6e50b409   Mikulas Patocka   dm snapshot: skip...
155
156
157
158
159
160
161
  
  	/*
  	 * For writing a complete chunk, bypassing the copy.
  	 */
  	struct bio *full_bio;
  	bio_end_io_t *full_bio_end_io;
  	void *full_bio_private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
165
166
167
  };
  
  /*
   * Hash table mapping origin volumes to lists of snapshots and
   * a lock to protect it
   */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
168
169
  static struct kmem_cache *exception_cache;
  static struct kmem_cache *pending_cache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170

cd45daffd   Mikulas Patocka   dm snapshot: trac...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  struct dm_snap_tracked_chunk {
  	struct hlist_node node;
  	chunk_t chunk;
  };
  
  static struct kmem_cache *tracked_chunk_cache;
  
  static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
  						 chunk_t chunk)
  {
  	struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
  							GFP_NOIO);
  	unsigned long flags;
  
  	c->chunk = chunk;
  
  	spin_lock_irqsave(&s->tracked_chunk_lock, flags);
  	hlist_add_head(&c->node,
  		       &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
  	spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
  
  	return c;
  }
  
  static void stop_tracking_chunk(struct dm_snapshot *s,
  				struct dm_snap_tracked_chunk *c)
  {
  	unsigned long flags;
  
  	spin_lock_irqsave(&s->tracked_chunk_lock, flags);
  	hlist_del(&c->node);
  	spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
  
  	mempool_free(c, s->tracked_chunk_pool);
  }
a8d41b59f   Mikulas Patocka   dm snapshot: fix ...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk)
  {
  	struct dm_snap_tracked_chunk *c;
  	struct hlist_node *hn;
  	int found = 0;
  
  	spin_lock_irq(&s->tracked_chunk_lock);
  
  	hlist_for_each_entry(c, hn,
  	    &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)], node) {
  		if (c->chunk == chunk) {
  			found = 1;
  			break;
  		}
  	}
  
  	spin_unlock_irq(&s->tracked_chunk_lock);
  
  	return found;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  /*
615d1eb9c   Mike Snitzer   dm snapshot: crea...
227
228
229
230
231
232
233
234
235
236
   * This conflicting I/O is extremely improbable in the caller,
   * so msleep(1) is sufficient and there is no need for a wait queue.
   */
  static void __check_for_conflicting_io(struct dm_snapshot *s, chunk_t chunk)
  {
  	while (__chunk_is_tracked(s, chunk))
  		msleep(1);
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
   * One of these per registered origin, held in the snapshot_origins hash
   */
  struct origin {
  	/* The origin device */
  	struct block_device *bdev;
  
  	struct list_head hash_list;
  
  	/* List of snapshots for this origin */
  	struct list_head snapshots;
  };
  
  /*
   * Size of the hash table for origin volumes. If we make this
   * the size of the minors list then it should be nearly perfect
   */
  #define ORIGIN_HASH_SIZE 256
  #define ORIGIN_MASK      0xFF
  static struct list_head *_origins;
  static struct rw_semaphore _origins_lock;
73dfd078c   Mikulas Patocka   dm snapshot: trig...
257
258
259
  static DECLARE_WAIT_QUEUE_HEAD(_pending_exceptions_done);
  static DEFINE_SPINLOCK(_pending_exceptions_done_spinlock);
  static uint64_t _pending_exceptions_done_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
265
266
  static int init_origin_hash(void)
  {
  	int i;
  
  	_origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
  			   GFP_KERNEL);
  	if (!_origins) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
267
  		DMERR("unable to allocate memory");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  		return -ENOMEM;
  	}
  
  	for (i = 0; i < ORIGIN_HASH_SIZE; i++)
  		INIT_LIST_HEAD(_origins + i);
  	init_rwsem(&_origins_lock);
  
  	return 0;
  }
  
  static void exit_origin_hash(void)
  {
  	kfree(_origins);
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
282
  static unsigned origin_hash(struct block_device *bdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  {
  	return bdev->bd_dev & ORIGIN_MASK;
  }
  
  static struct origin *__lookup_origin(struct block_device *origin)
  {
  	struct list_head *ol;
  	struct origin *o;
  
  	ol = &_origins[origin_hash(origin)];
  	list_for_each_entry (o, ol, hash_list)
  		if (bdev_equal(o->bdev, origin))
  			return o;
  
  	return NULL;
  }
  
  static void __insert_origin(struct origin *o)
  {
  	struct list_head *sl = &_origins[origin_hash(o->bdev)];
  	list_add_tail(&o->hash_list, sl);
  }
  
  /*
c1f0c183f   Mike Snitzer   dm snapshot: allo...
307
308
309
310
   * _origins_lock must be held when calling this function.
   * Returns number of snapshots registered using the supplied cow device, plus:
   * snap_src - a snapshot suitable for use as a source of exception handover
   * snap_dest - a snapshot capable of receiving exception handover.
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
311
312
   * snap_merge - an existing snapshot-merge target linked to the same origin.
   *   There can be at most one snapshot-merge target. The parameter is optional.
c1f0c183f   Mike Snitzer   dm snapshot: allo...
313
   *
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
314
   * Possible return values and states of snap_src and snap_dest.
c1f0c183f   Mike Snitzer   dm snapshot: allo...
315
316
317
318
319
320
321
322
   *   0: NULL, NULL  - first new snapshot
   *   1: snap_src, NULL - normal snapshot
   *   2: snap_src, snap_dest  - waiting for handover
   *   2: snap_src, NULL - handed over, waiting for old to be deleted
   *   1: NULL, snap_dest - source got destroyed without handover
   */
  static int __find_snapshots_sharing_cow(struct dm_snapshot *snap,
  					struct dm_snapshot **snap_src,
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
323
324
  					struct dm_snapshot **snap_dest,
  					struct dm_snapshot **snap_merge)
c1f0c183f   Mike Snitzer   dm snapshot: allo...
325
326
327
328
329
330
331
332
333
334
335
  {
  	struct dm_snapshot *s;
  	struct origin *o;
  	int count = 0;
  	int active;
  
  	o = __lookup_origin(snap->origin->bdev);
  	if (!o)
  		goto out;
  
  	list_for_each_entry(s, &o->snapshots, list) {
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
336
337
  		if (dm_target_is_snapshot_merge(s->ti) && snap_merge)
  			*snap_merge = s;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
  		if (!bdev_equal(s->cow->bdev, snap->cow->bdev))
  			continue;
  
  		down_read(&s->lock);
  		active = s->active;
  		up_read(&s->lock);
  
  		if (active) {
  			if (snap_src)
  				*snap_src = s;
  		} else if (snap_dest)
  			*snap_dest = s;
  
  		count++;
  	}
  
  out:
  	return count;
  }
  
  /*
   * On success, returns 1 if this snapshot is a handover destination,
   * otherwise returns 0.
   */
  static int __validate_exception_handover(struct dm_snapshot *snap)
  {
  	struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
365
  	struct dm_snapshot *snap_merge = NULL;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
366
367
  
  	/* Does snapshot need exceptions handed over to it? */
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
368
369
  	if ((__find_snapshots_sharing_cow(snap, &snap_src, &snap_dest,
  					  &snap_merge) == 2) ||
c1f0c183f   Mike Snitzer   dm snapshot: allo...
370
371
372
373
374
375
376
377
378
379
380
381
  	    snap_dest) {
  		snap->ti->error = "Snapshot cow pairing for exception "
  				  "table handover failed";
  		return -EINVAL;
  	}
  
  	/*
  	 * If no snap_src was found, snap cannot become a handover
  	 * destination.
  	 */
  	if (!snap_src)
  		return 0;
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
382
383
384
385
386
387
388
389
390
391
392
393
394
  	/*
  	 * Non-snapshot-merge handover?
  	 */
  	if (!dm_target_is_snapshot_merge(snap->ti))
  		return 1;
  
  	/*
  	 * Do not allow more than one merging snapshot.
  	 */
  	if (snap_merge) {
  		snap->ti->error = "A snapshot is already merging.";
  		return -EINVAL;
  	}
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
395
396
397
398
399
400
  	if (!snap_src->store->type->prepare_merge ||
  	    !snap_src->store->type->commit_merge) {
  		snap->ti->error = "Snapshot exception store does not "
  				  "support snapshot-merge.";
  		return -EINVAL;
  	}
c1f0c183f   Mike Snitzer   dm snapshot: allo...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  	return 1;
  }
  
  static void __insert_snapshot(struct origin *o, struct dm_snapshot *s)
  {
  	struct dm_snapshot *l;
  
  	/* Sort the list according to chunk size, largest-first smallest-last */
  	list_for_each_entry(l, &o->snapshots, list)
  		if (l->store->chunk_size < s->store->chunk_size)
  			break;
  	list_add_tail(&s->list, &l->list);
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
   * Make a note of the snapshot and its origin so we can look it
   * up when the origin has a write on it.
c1f0c183f   Mike Snitzer   dm snapshot: allo...
418
419
420
421
   *
   * Also validate snapshot exception store handovers.
   * On success, returns 1 if this registration is a handover destination,
   * otherwise returns 0.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
   */
  static int register_snapshot(struct dm_snapshot *snap)
  {
c1f0c183f   Mike Snitzer   dm snapshot: allo...
425
  	struct origin *o, *new_o = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
  	struct block_device *bdev = snap->origin->bdev;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
427
  	int r = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428

60c856c8e   Mikulas Patocka   dm snapshot: fix ...
429
430
431
  	new_o = kmalloc(sizeof(*new_o), GFP_KERNEL);
  	if (!new_o)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  	down_write(&_origins_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433

c1f0c183f   Mike Snitzer   dm snapshot: allo...
434
435
436
437
438
439
440
  	r = __validate_exception_handover(snap);
  	if (r < 0) {
  		kfree(new_o);
  		goto out;
  	}
  
  	o = __lookup_origin(bdev);
60c856c8e   Mikulas Patocka   dm snapshot: fix ...
441
442
443
  	if (o)
  		kfree(new_o);
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  		/* New origin */
60c856c8e   Mikulas Patocka   dm snapshot: fix ...
445
  		o = new_o;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
449
450
451
452
  
  		/* Initialise the struct */
  		INIT_LIST_HEAD(&o->snapshots);
  		o->bdev = bdev;
  
  		__insert_origin(o);
  	}
c1f0c183f   Mike Snitzer   dm snapshot: allo...
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
  	__insert_snapshot(o, snap);
  
  out:
  	up_write(&_origins_lock);
  
  	return r;
  }
  
  /*
   * Move snapshot to correct place in list according to chunk size.
   */
  static void reregister_snapshot(struct dm_snapshot *s)
  {
  	struct block_device *bdev = s->origin->bdev;
  
  	down_write(&_origins_lock);
  
  	list_del(&s->list);
  	__insert_snapshot(__lookup_origin(bdev), s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
  
  	up_write(&_origins_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
477
478
479
480
481
482
483
  }
  
  static void unregister_snapshot(struct dm_snapshot *s)
  {
  	struct origin *o;
  
  	down_write(&_origins_lock);
  	o = __lookup_origin(s->origin->bdev);
  
  	list_del(&s->list);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
484
  	if (o && list_empty(&o->snapshots)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
488
489
490
491
492
493
  		list_del(&o->hash_list);
  		kfree(o);
  	}
  
  	up_write(&_origins_lock);
  }
  
  /*
   * Implementation of the exception hash tables.
d74f81f8a   Milan Broz   dm snapshot: comb...
494
495
   * The lowest hash_shift bits of the chunk number are ignored, allowing
   * some consecutive chunks to be grouped together.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
   */
3510cb94f   Jon Brassow   dm snapshot: rena...
497
498
  static int dm_exception_table_init(struct dm_exception_table *et,
  				   uint32_t size, unsigned hash_shift)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
  {
  	unsigned int i;
d74f81f8a   Milan Broz   dm snapshot: comb...
501
  	et->hash_shift = hash_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
507
508
509
510
511
  	et->hash_mask = size - 1;
  	et->table = dm_vcalloc(size, sizeof(struct list_head));
  	if (!et->table)
  		return -ENOMEM;
  
  	for (i = 0; i < size; i++)
  		INIT_LIST_HEAD(et->table + i);
  
  	return 0;
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
512
513
  static void dm_exception_table_exit(struct dm_exception_table *et,
  				    struct kmem_cache *mem)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
  {
  	struct list_head *slot;
1d4989c85   Jon Brassow   dm snapshot: rena...
516
  	struct dm_exception *ex, *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
519
520
521
522
523
524
525
526
527
528
  	int i, size;
  
  	size = et->hash_mask + 1;
  	for (i = 0; i < size; i++) {
  		slot = et->table + i;
  
  		list_for_each_entry_safe (ex, next, slot, hash_list)
  			kmem_cache_free(mem, ex);
  	}
  
  	vfree(et->table);
  }
191437a53   Jon Brassow   dm snapshot: rena...
529
  static uint32_t exception_hash(struct dm_exception_table *et, chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  {
d74f81f8a   Milan Broz   dm snapshot: comb...
531
  	return (chunk >> et->hash_shift) & et->hash_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
533
  static void dm_remove_exception(struct dm_exception *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
539
540
541
  {
  	list_del(&e->hash_list);
  }
  
  /*
   * Return the exception data for a sector, or NULL if not
   * remapped.
   */
3510cb94f   Jon Brassow   dm snapshot: rena...
542
543
  static struct dm_exception *dm_lookup_exception(struct dm_exception_table *et,
  						chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
  {
  	struct list_head *slot;
1d4989c85   Jon Brassow   dm snapshot: rena...
546
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
  
  	slot = &et->table[exception_hash(et, chunk)];
  	list_for_each_entry (e, slot, hash_list)
d74f81f8a   Milan Broz   dm snapshot: comb...
550
551
  		if (chunk >= e->old_chunk &&
  		    chunk <= e->old_chunk + dm_consecutive_chunk_count(e))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
555
  			return e;
  
  	return NULL;
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
556
  static struct dm_exception *alloc_completed_exception(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  {
1d4989c85   Jon Brassow   dm snapshot: rena...
558
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
562
563
564
565
  
  	e = kmem_cache_alloc(exception_cache, GFP_NOIO);
  	if (!e)
  		e = kmem_cache_alloc(exception_cache, GFP_ATOMIC);
  
  	return e;
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
566
  static void free_completed_exception(struct dm_exception *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
  {
  	kmem_cache_free(exception_cache, e);
  }
92e868122   Mikulas Patocka   dm snapshot: use ...
570
  static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snapshot *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
  {
92e868122   Mikulas Patocka   dm snapshot: use ...
572
573
  	struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool,
  							     GFP_NOIO);
879129d20   Mikulas Patocka   dm snapshot: wait...
574
  	atomic_inc(&s->pending_exceptions_count);
92e868122   Mikulas Patocka   dm snapshot: use ...
575
576
577
  	pe->snap = s;
  
  	return pe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
579
  static void free_pending_exception(struct dm_snap_pending_exception *pe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  {
879129d20   Mikulas Patocka   dm snapshot: wait...
581
582
583
584
585
  	struct dm_snapshot *s = pe->snap;
  
  	mempool_free(pe, s->pending_pool);
  	smp_mb__before_atomic_dec();
  	atomic_dec(&s->pending_exceptions_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
587
588
  static void dm_insert_exception(struct dm_exception_table *eh,
  				struct dm_exception *new_e)
d74f81f8a   Milan Broz   dm snapshot: comb...
589
  {
d74f81f8a   Milan Broz   dm snapshot: comb...
590
  	struct list_head *l;
1d4989c85   Jon Brassow   dm snapshot: rena...
591
  	struct dm_exception *e = NULL;
d74f81f8a   Milan Broz   dm snapshot: comb...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
  
  	l = &eh->table[exception_hash(eh, new_e->old_chunk)];
  
  	/* Add immediately if this table doesn't support consecutive chunks */
  	if (!eh->hash_shift)
  		goto out;
  
  	/* List is ordered by old_chunk */
  	list_for_each_entry_reverse(e, l, hash_list) {
  		/* Insert after an existing chunk? */
  		if (new_e->old_chunk == (e->old_chunk +
  					 dm_consecutive_chunk_count(e) + 1) &&
  		    new_e->new_chunk == (dm_chunk_number(e->new_chunk) +
  					 dm_consecutive_chunk_count(e) + 1)) {
  			dm_consecutive_chunk_count_inc(e);
3510cb94f   Jon Brassow   dm snapshot: rena...
607
  			free_completed_exception(new_e);
d74f81f8a   Milan Broz   dm snapshot: comb...
608
609
610
611
612
613
614
615
616
  			return;
  		}
  
  		/* Insert before an existing chunk? */
  		if (new_e->old_chunk == (e->old_chunk - 1) &&
  		    new_e->new_chunk == (dm_chunk_number(e->new_chunk) - 1)) {
  			dm_consecutive_chunk_count_inc(e);
  			e->old_chunk--;
  			e->new_chunk--;
3510cb94f   Jon Brassow   dm snapshot: rena...
617
  			free_completed_exception(new_e);
d74f81f8a   Milan Broz   dm snapshot: comb...
618
619
620
621
622
623
624
625
626
627
  			return;
  		}
  
  		if (new_e->old_chunk > e->old_chunk)
  			break;
  	}
  
  out:
  	list_add(&new_e->hash_list, e ? &e->hash_list : l);
  }
a159c1ac5   Jonathan Brassow   dm snapshot: exte...
628
629
630
631
632
  /*
   * Callback used by the exception stores to load exceptions when
   * initialising.
   */
  static int dm_add_exception(void *context, chunk_t old, chunk_t new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
  {
a159c1ac5   Jonathan Brassow   dm snapshot: exte...
634
  	struct dm_snapshot *s = context;
1d4989c85   Jon Brassow   dm snapshot: rena...
635
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636

3510cb94f   Jon Brassow   dm snapshot: rena...
637
  	e = alloc_completed_exception();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
  	if (!e)
  		return -ENOMEM;
  
  	e->old_chunk = old;
d74f81f8a   Milan Broz   dm snapshot: comb...
642
643
  
  	/* Consecutive_count is implicitly initialised to zero */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
  	e->new_chunk = new;
d74f81f8a   Milan Broz   dm snapshot: comb...
645

3510cb94f   Jon Brassow   dm snapshot: rena...
646
  	dm_insert_exception(&s->complete, e);
d74f81f8a   Milan Broz   dm snapshot: comb...
647

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
  	return 0;
  }
7e201b351   Mikulas Patocka   dm snapshot: abst...
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
  /*
   * Return a minimum chunk size of all snapshots that have the specified origin.
   * Return zero if the origin has no snapshots.
   */
  static sector_t __minimum_chunk_size(struct origin *o)
  {
  	struct dm_snapshot *snap;
  	unsigned chunk_size = 0;
  
  	if (o)
  		list_for_each_entry(snap, &o->snapshots, list)
  			chunk_size = min_not_zero(chunk_size,
  						  snap->store->chunk_size);
  
  	return chunk_size;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
671
672
673
674
675
676
677
678
  /*
   * Hard coded magic.
   */
  static int calc_max_buckets(void)
  {
  	/* use a fixed size of 2MB */
  	unsigned long mem = 2 * 1024 * 1024;
  	mem /= sizeof(struct list_head);
  
  	return mem;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
   * Allocate room for a suitable hash table.
   */
fee1998e9   Jonathan Brassow   dm snapshot: move...
681
  static int init_hash_tables(struct dm_snapshot *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
682
683
684
685
686
687
688
  {
  	sector_t hash_size, cow_dev_size, origin_dev_size, max_buckets;
  
  	/*
  	 * Calculate based on the size of the original volume or
  	 * the COW volume...
  	 */
fc56f6fbc   Mike Snitzer   dm snapshot: move...
689
  	cow_dev_size = get_dev_size(s->cow->bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
  	origin_dev_size = get_dev_size(s->origin->bdev);
  	max_buckets = calc_max_buckets();
fee1998e9   Jonathan Brassow   dm snapshot: move...
692
  	hash_size = min(origin_dev_size, cow_dev_size) >> s->store->chunk_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  	hash_size = min(hash_size, max_buckets);
8e87b9b81   Mikulas Patocka   dm snapshot: cope...
694
695
  	if (hash_size < 64)
  		hash_size = 64;
8defd8308   Robert P. J. Day   dm snapshot: use ...
696
  	hash_size = rounddown_pow_of_two(hash_size);
3510cb94f   Jon Brassow   dm snapshot: rena...
697
698
  	if (dm_exception_table_init(&s->complete, hash_size,
  				    DM_CHUNK_CONSECUTIVE_BITS))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
702
703
704
705
706
707
  		return -ENOMEM;
  
  	/*
  	 * Allocate hash table for in-flight exceptions
  	 * Make this smaller than the real hash table
  	 */
  	hash_size >>= 3;
  	if (hash_size < 64)
  		hash_size = 64;
3510cb94f   Jon Brassow   dm snapshot: rena...
708
709
  	if (dm_exception_table_init(&s->pending, hash_size, 0)) {
  		dm_exception_table_exit(&s->complete, exception_cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
711
712
713
714
  		return -ENOMEM;
  	}
  
  	return 0;
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
715
716
717
718
719
720
  static void merge_shutdown(struct dm_snapshot *s)
  {
  	clear_bit_unlock(RUNNING_MERGE, &s->state_bits);
  	smp_mb__after_clear_bit();
  	wake_up_bit(&s->state_bits, RUNNING_MERGE);
  }
9fe862548   Mikulas Patocka   dm snapshot: queu...
721
722
723
724
725
726
727
  static struct bio *__release_queued_bios_after_merge(struct dm_snapshot *s)
  {
  	s->first_merging_chunk = 0;
  	s->num_merging_chunks = 0;
  
  	return bio_list_get(&s->bios_queued_during_merge);
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
728
729
730
731
732
733
734
  /*
   * Remove one chunk from the index of completed exceptions.
   */
  static int __remove_single_exception_chunk(struct dm_snapshot *s,
  					   chunk_t old_chunk)
  {
  	struct dm_exception *e;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
  	e = dm_lookup_exception(&s->complete, old_chunk);
  	if (!e) {
  		DMERR("Corruption detected: exception for block %llu is "
  		      "on disk but not in memory",
  		      (unsigned long long)old_chunk);
  		return -EINVAL;
  	}
  
  	/*
  	 * If this is the only chunk using this exception, remove exception.
  	 */
  	if (!dm_consecutive_chunk_count(e)) {
  		dm_remove_exception(e);
  		free_completed_exception(e);
  		return 0;
  	}
  
  	/*
  	 * The chunk may be either at the beginning or the end of a
  	 * group of consecutive chunks - never in the middle.  We are
  	 * removing chunks in the opposite order to that in which they
  	 * were added, so this should always be true.
  	 * Decrement the consecutive chunk counter and adjust the
  	 * starting point if necessary.
  	 */
  	if (old_chunk == e->old_chunk) {
  		e->old_chunk++;
  		e->new_chunk++;
  	} else if (old_chunk != e->old_chunk +
  		   dm_consecutive_chunk_count(e)) {
  		DMERR("Attempt to merge block %llu from the "
  		      "middle of a chunk range [%llu - %llu]",
  		      (unsigned long long)old_chunk,
  		      (unsigned long long)e->old_chunk,
  		      (unsigned long long)
  		      e->old_chunk + dm_consecutive_chunk_count(e));
  		return -EINVAL;
  	}
  
  	dm_consecutive_chunk_count_dec(e);
  
  	return 0;
  }
9fe862548   Mikulas Patocka   dm snapshot: queu...
778
779
780
  static void flush_bios(struct bio *bio);
  
  static int remove_single_exception_chunk(struct dm_snapshot *s)
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
781
  {
9fe862548   Mikulas Patocka   dm snapshot: queu...
782
783
784
  	struct bio *b = NULL;
  	int r;
  	chunk_t old_chunk = s->first_merging_chunk + s->num_merging_chunks - 1;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
785
786
  
  	down_write(&s->lock);
9fe862548   Mikulas Patocka   dm snapshot: queu...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  
  	/*
  	 * Process chunks (and associated exceptions) in reverse order
  	 * so that dm_consecutive_chunk_count_dec() accounting works.
  	 */
  	do {
  		r = __remove_single_exception_chunk(s, old_chunk);
  		if (r)
  			goto out;
  	} while (old_chunk-- > s->first_merging_chunk);
  
  	b = __release_queued_bios_after_merge(s);
  
  out:
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
801
  	up_write(&s->lock);
9fe862548   Mikulas Patocka   dm snapshot: queu...
802
803
  	if (b)
  		flush_bios(b);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
804
805
806
  
  	return r;
  }
73dfd078c   Mikulas Patocka   dm snapshot: trig...
807
808
  static int origin_write_extent(struct dm_snapshot *merging_snap,
  			       sector_t sector, unsigned chunk_size);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
809
810
  static void merge_callback(int read_err, unsigned long write_err,
  			   void *context);
73dfd078c   Mikulas Patocka   dm snapshot: trig...
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
  static uint64_t read_pending_exceptions_done_count(void)
  {
  	uint64_t pending_exceptions_done;
  
  	spin_lock(&_pending_exceptions_done_spinlock);
  	pending_exceptions_done = _pending_exceptions_done_count;
  	spin_unlock(&_pending_exceptions_done_spinlock);
  
  	return pending_exceptions_done;
  }
  
  static void increment_pending_exceptions_done_count(void)
  {
  	spin_lock(&_pending_exceptions_done_spinlock);
  	_pending_exceptions_done_count++;
  	spin_unlock(&_pending_exceptions_done_spinlock);
  
  	wake_up_all(&_pending_exceptions_done);
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
830
831
  static void snapshot_merge_next_chunks(struct dm_snapshot *s)
  {
8a2d52862   Mike Snitzer   dm snapshot: merg...
832
  	int i, linear_chunks;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
833
834
  	chunk_t old_chunk, new_chunk;
  	struct dm_io_region src, dest;
8a2d52862   Mike Snitzer   dm snapshot: merg...
835
  	sector_t io_size;
73dfd078c   Mikulas Patocka   dm snapshot: trig...
836
  	uint64_t previous_count;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
837
838
839
840
841
842
843
844
845
846
847
848
  
  	BUG_ON(!test_bit(RUNNING_MERGE, &s->state_bits));
  	if (unlikely(test_bit(SHUTDOWN_MERGE, &s->state_bits)))
  		goto shut;
  
  	/*
  	 * valid flag never changes during merge, so no lock required.
  	 */
  	if (!s->valid) {
  		DMERR("Snapshot is invalid: can't merge");
  		goto shut;
  	}
8a2d52862   Mike Snitzer   dm snapshot: merg...
849
850
851
  	linear_chunks = s->store->type->prepare_merge(s->store, &old_chunk,
  						      &new_chunk);
  	if (linear_chunks <= 0) {
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
852
  		if (linear_chunks < 0) {
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
853
854
  			DMERR("Read error in exception store: "
  			      "shutting down merge");
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
855
856
857
858
  			down_write(&s->lock);
  			s->merge_failed = 1;
  			up_write(&s->lock);
  		}
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
859
860
  		goto shut;
  	}
8a2d52862   Mike Snitzer   dm snapshot: merg...
861
862
863
864
865
866
867
868
869
  	/* Adjust old_chunk and new_chunk to reflect start of linear region */
  	old_chunk = old_chunk + 1 - linear_chunks;
  	new_chunk = new_chunk + 1 - linear_chunks;
  
  	/*
  	 * Use one (potentially large) I/O to copy all 'linear_chunks'
  	 * from the exception store to the origin
  	 */
  	io_size = linear_chunks * s->store->chunk_size;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
870

1e03f97e4   Mikulas Patocka   dm snapshot: add ...
871
872
  	dest.bdev = s->origin->bdev;
  	dest.sector = chunk_to_sector(s->store, old_chunk);
8a2d52862   Mike Snitzer   dm snapshot: merg...
873
  	dest.count = min(io_size, get_dev_size(dest.bdev) - dest.sector);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
874
875
876
877
  
  	src.bdev = s->cow->bdev;
  	src.sector = chunk_to_sector(s->store, new_chunk);
  	src.count = dest.count;
73dfd078c   Mikulas Patocka   dm snapshot: trig...
878
879
880
881
882
883
884
885
886
887
  	/*
  	 * Reallocate any exceptions needed in other snapshots then
  	 * wait for the pending exceptions to complete.
  	 * Each time any pending exception (globally on the system)
  	 * completes we are woken and repeat the process to find out
  	 * if we can proceed.  While this may not seem a particularly
  	 * efficient algorithm, it is not expected to have any
  	 * significant impact on performance.
  	 */
  	previous_count = read_pending_exceptions_done_count();
8a2d52862   Mike Snitzer   dm snapshot: merg...
888
  	while (origin_write_extent(s, dest.sector, io_size)) {
73dfd078c   Mikulas Patocka   dm snapshot: trig...
889
890
891
892
893
894
  		wait_event(_pending_exceptions_done,
  			   (read_pending_exceptions_done_count() !=
  			    previous_count));
  		/* Retry after the wait, until all exceptions are done. */
  		previous_count = read_pending_exceptions_done_count();
  	}
9fe862548   Mikulas Patocka   dm snapshot: queu...
895
896
  	down_write(&s->lock);
  	s->first_merging_chunk = old_chunk;
8a2d52862   Mike Snitzer   dm snapshot: merg...
897
  	s->num_merging_chunks = linear_chunks;
9fe862548   Mikulas Patocka   dm snapshot: queu...
898
  	up_write(&s->lock);
8a2d52862   Mike Snitzer   dm snapshot: merg...
899
900
901
  	/* Wait until writes to all 'linear_chunks' drain */
  	for (i = 0; i < linear_chunks; i++)
  		__check_for_conflicting_io(s, old_chunk + i);
9fe862548   Mikulas Patocka   dm snapshot: queu...
902

1e03f97e4   Mikulas Patocka   dm snapshot: add ...
903
904
905
906
907
908
  	dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, merge_callback, s);
  	return;
  
  shut:
  	merge_shutdown(s);
  }
9fe862548   Mikulas Patocka   dm snapshot: queu...
909
  static void error_bios(struct bio *bio);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
910
911
912
  static void merge_callback(int read_err, unsigned long write_err, void *context)
  {
  	struct dm_snapshot *s = context;
9fe862548   Mikulas Patocka   dm snapshot: queu...
913
  	struct bio *b = NULL;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
914
915
916
917
918
919
920
921
  
  	if (read_err || write_err) {
  		if (read_err)
  			DMERR("Read error: shutting down merge.");
  		else
  			DMERR("Write error: shutting down merge.");
  		goto shut;
  	}
9fe862548   Mikulas Patocka   dm snapshot: queu...
922
923
  	if (s->store->type->commit_merge(s->store,
  					 s->num_merging_chunks) < 0) {
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
924
925
926
  		DMERR("Write error in exception store: shutting down merge");
  		goto shut;
  	}
9fe862548   Mikulas Patocka   dm snapshot: queu...
927
928
  	if (remove_single_exception_chunk(s) < 0)
  		goto shut;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
929
930
931
932
933
  	snapshot_merge_next_chunks(s);
  
  	return;
  
  shut:
9fe862548   Mikulas Patocka   dm snapshot: queu...
934
  	down_write(&s->lock);
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
935
  	s->merge_failed = 1;
9fe862548   Mikulas Patocka   dm snapshot: queu...
936
937
938
  	b = __release_queued_bios_after_merge(s);
  	up_write(&s->lock);
  	error_bios(b);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
  	merge_shutdown(s);
  }
  
  static void start_merge(struct dm_snapshot *s)
  {
  	if (!test_and_set_bit(RUNNING_MERGE, &s->state_bits))
  		snapshot_merge_next_chunks(s);
  }
  
  static int wait_schedule(void *ptr)
  {
  	schedule();
  
  	return 0;
  }
  
  /*
   * Stop the merging process and wait until it finishes.
   */
  static void stop_merge(struct dm_snapshot *s)
  {
  	set_bit(SHUTDOWN_MERGE, &s->state_bits);
  	wait_on_bit(&s->state_bits, RUNNING_MERGE, wait_schedule,
  		    TASK_UNINTERRUPTIBLE);
  	clear_bit(SHUTDOWN_MERGE, &s->state_bits);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
968
969
970
   * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
   */
  static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
  {
  	struct dm_snapshot *s;
cd45daffd   Mikulas Patocka   dm snapshot: trac...
971
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
  	int r = -EINVAL;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
973
  	char *origin_path, *cow_path;
10b8106a7   Mike Snitzer   dm snapshot: supp...
974
975
  	unsigned args_used, num_flush_requests = 1;
  	fmode_t origin_mode = FMODE_READ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976

4c7e3bf44   Mark McLoughlin   [PATCH] dm snapsh...
977
  	if (argc != 4) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
978
  		ti->error = "requires exactly 4 arguments";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  		r = -EINVAL;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
980
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
981
  	}
10b8106a7   Mike Snitzer   dm snapshot: supp...
982
983
984
985
  	if (dm_target_is_snapshot_merge(ti)) {
  		num_flush_requests = 2;
  		origin_mode = FMODE_WRITE;
  	}
fc56f6fbc   Mike Snitzer   dm snapshot: move...
986
987
  	s = kmalloc(sizeof(*s), GFP_KERNEL);
  	if (!s) {
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
988
  		ti->error = "Cannot allocate private snapshot structure";
fc56f6fbc   Mike Snitzer   dm snapshot: move...
989
990
991
  		r = -ENOMEM;
  		goto bad;
  	}
c24110450   Mikulas Patocka   dm snapshot: test...
992
993
994
995
996
997
998
999
1000
  	origin_path = argv[0];
  	argv++;
  	argc--;
  
  	r = dm_get_device(ti, origin_path, origin_mode, &s->origin);
  	if (r) {
  		ti->error = "Cannot get origin device";
  		goto bad_origin;
  	}
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1001
1002
1003
  	cow_path = argv[0];
  	argv++;
  	argc--;
024d37e95   Milan Broz   dm: fix opening l...
1004
  	r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1005
1006
1007
1008
1009
1010
  	if (r) {
  		ti->error = "Cannot get COW device";
  		goto bad_cow;
  	}
  
  	r = dm_exception_store_create(ti, argc, argv, s, &args_used, &s->store);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1011
1012
  	if (r) {
  		ti->error = "Couldn't create exception store";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
  		r = -EINVAL;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1014
  		goto bad_store;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
  	}
fee1998e9   Jonathan Brassow   dm snapshot: move...
1016
1017
  	argv += args_used;
  	argc -= args_used;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1018
  	s->ti = ti;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
  	s->valid = 1;
aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
1020
  	s->active = 0;
879129d20   Mikulas Patocka   dm snapshot: wait...
1021
  	atomic_set(&s->pending_exceptions_count, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022
  	init_rwsem(&s->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1023
  	INIT_LIST_HEAD(&s->list);
ca3a931fd   Alasdair G Kergon   [PATCH] dm snapsh...
1024
  	spin_lock_init(&s->pe_lock);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1025
  	s->state_bits = 0;
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
1026
  	s->merge_failed = 0;
9fe862548   Mikulas Patocka   dm snapshot: queu...
1027
1028
1029
  	s->first_merging_chunk = 0;
  	s->num_merging_chunks = 0;
  	bio_list_init(&s->bios_queued_during_merge);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
  
  	/* Allocate hash table for COW data */
fee1998e9   Jonathan Brassow   dm snapshot: move...
1032
  	if (init_hash_tables(s)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
1034
  		ti->error = "Unable to allocate hash table space";
  		r = -ENOMEM;
fee1998e9   Jonathan Brassow   dm snapshot: move...
1035
  		goto bad_hash_tables;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
  	}
fa34ce730   Mikulas Patocka   dm kcopyd: return...
1037
1038
1039
  	s->kcopyd_client = dm_kcopyd_client_create();
  	if (IS_ERR(s->kcopyd_client)) {
  		r = PTR_ERR(s->kcopyd_client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1040
  		ti->error = "Could not create kcopyd client";
fee1998e9   Jonathan Brassow   dm snapshot: move...
1041
  		goto bad_kcopyd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1042
  	}
92e868122   Mikulas Patocka   dm snapshot: use ...
1043
1044
1045
  	s->pending_pool = mempool_create_slab_pool(MIN_IOS, pending_cache);
  	if (!s->pending_pool) {
  		ti->error = "Could not allocate mempool for pending exceptions";
fee1998e9   Jonathan Brassow   dm snapshot: move...
1046
  		goto bad_pending_pool;
92e868122   Mikulas Patocka   dm snapshot: use ...
1047
  	}
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1048
1049
1050
1051
1052
  	s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS,
  							 tracked_chunk_cache);
  	if (!s->tracked_chunk_pool) {
  		ti->error = "Could not allocate tracked_chunk mempool for "
  			    "tracking reads";
92e868122   Mikulas Patocka   dm snapshot: use ...
1053
  		goto bad_tracked_chunk_pool;
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1054
1055
1056
1057
1058
1059
  	}
  
  	for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
  		INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]);
  
  	spin_lock_init(&s->tracked_chunk_lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1060
  	ti->private = s;
10b8106a7   Mike Snitzer   dm snapshot: supp...
1061
  	ti->num_flush_requests = num_flush_requests;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
  
  	/* Add snapshot to the list of snapshots for this origin */
  	/* Exceptions aren't triggered till snapshot_resume() is called */
  	r = register_snapshot(s);
  	if (r == -ENOMEM) {
  		ti->error = "Snapshot origin struct allocation failed";
  		goto bad_load_and_register;
  	} else if (r < 0) {
  		/* invalid handover, register_snapshot has set ti->error */
  		goto bad_load_and_register;
  	}
  
  	/*
  	 * Metadata must only be loaded into one table at once, so skip this
  	 * if metadata will be handed over during resume.
  	 * Chunk size will be set during the handover - set it to zero to
  	 * ensure it's ignored.
  	 */
  	if (r > 0) {
  		s->store->chunk_size = 0;
  		return 0;
  	}
493df71c6   Jonathan Brassow   dm exception stor...
1084
1085
  	r = s->store->type->read_metadata(s->store, dm_add_exception,
  					  (void *)s);
0764147b1   Milan Broz   dm snapshot: perm...
1086
  	if (r < 0) {
f9cea4f70   Mark McLoughlin   [PATCH] dm snapsh...
1087
  		ti->error = "Failed to read snapshot metadata";
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1088
  		goto bad_read_metadata;
0764147b1   Milan Broz   dm snapshot: perm...
1089
1090
1091
  	} else if (r > 0) {
  		s->valid = 0;
  		DMWARN("Snapshot is marked invalid.");
f9cea4f70   Mark McLoughlin   [PATCH] dm snapsh...
1092
  	}
aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
1093

3f2412dc8   Mikulas Patocka   dm snapshot: requ...
1094
1095
  	if (!s->store->chunk_size) {
  		ti->error = "Chunk size not set";
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1096
  		goto bad_read_metadata;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1097
  	}
d02168495   Jonathan Brassow   dm exception stor...
1098
  	ti->split_io = s->store->chunk_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
1100
  
  	return 0;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1101
1102
  bad_read_metadata:
  	unregister_snapshot(s);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1103
  bad_load_and_register:
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1104
  	mempool_destroy(s->tracked_chunk_pool);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1105
  bad_tracked_chunk_pool:
92e868122   Mikulas Patocka   dm snapshot: use ...
1106
  	mempool_destroy(s->pending_pool);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1107
  bad_pending_pool:
eb69aca5d   Heinz Mauelshagen   dm kcopyd: clean ...
1108
  	dm_kcopyd_client_destroy(s->kcopyd_client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109

fee1998e9   Jonathan Brassow   dm snapshot: move...
1110
  bad_kcopyd:
3510cb94f   Jon Brassow   dm snapshot: rena...
1111
1112
  	dm_exception_table_exit(&s->pending, pending_cache);
  	dm_exception_table_exit(&s->complete, exception_cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113

fee1998e9   Jonathan Brassow   dm snapshot: move...
1114
  bad_hash_tables:
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1115
  	dm_exception_store_destroy(s->store);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1116

fc56f6fbc   Mike Snitzer   dm snapshot: move...
1117
1118
  bad_store:
  	dm_put_device(ti, s->cow);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1119

fc56f6fbc   Mike Snitzer   dm snapshot: move...
1120
  bad_cow:
c24110450   Mikulas Patocka   dm snapshot: test...
1121
1122
1123
  	dm_put_device(ti, s->origin);
  
  bad_origin:
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1124
1125
1126
  	kfree(s);
  
  bad:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
  	return r;
  }
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1129
1130
  static void __free_exceptions(struct dm_snapshot *s)
  {
eb69aca5d   Heinz Mauelshagen   dm kcopyd: clean ...
1131
  	dm_kcopyd_client_destroy(s->kcopyd_client);
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1132
  	s->kcopyd_client = NULL;
3510cb94f   Jon Brassow   dm snapshot: rena...
1133
1134
  	dm_exception_table_exit(&s->pending, pending_cache);
  	dm_exception_table_exit(&s->complete, exception_cache);
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1135
  }
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  static void __handover_exceptions(struct dm_snapshot *snap_src,
  				  struct dm_snapshot *snap_dest)
  {
  	union {
  		struct dm_exception_table table_swap;
  		struct dm_exception_store *store_swap;
  	} u;
  
  	/*
  	 * Swap all snapshot context information between the two instances.
  	 */
  	u.table_swap = snap_dest->complete;
  	snap_dest->complete = snap_src->complete;
  	snap_src->complete = u.table_swap;
  
  	u.store_swap = snap_dest->store;
  	snap_dest->store = snap_src->store;
  	snap_src->store = u.store_swap;
  
  	snap_dest->store->snap = snap_dest;
  	snap_src->store->snap = snap_src;
  
  	snap_dest->ti->split_io = snap_dest->store->chunk_size;
  	snap_dest->valid = snap_src->valid;
  
  	/*
  	 * Set source invalid to ensure it receives no further I/O.
  	 */
  	snap_src->valid = 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
1167
  static void snapshot_dtr(struct dm_target *ti)
  {
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1168
1169
1170
  #ifdef CONFIG_DM_DEBUG
  	int i;
  #endif
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1171
  	struct dm_snapshot *s = ti->private;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1172
  	struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173

c1f0c183f   Mike Snitzer   dm snapshot: allo...
1174
1175
  	down_read(&_origins_lock);
  	/* Check whether exception handover must be cancelled */
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
1176
  	(void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1177
1178
1179
1180
1181
1182
1183
  	if (snap_src && snap_dest && (s == snap_src)) {
  		down_write(&snap_dest->lock);
  		snap_dest->valid = 0;
  		up_write(&snap_dest->lock);
  		DMERR("Cancelling snapshot handover.");
  	}
  	up_read(&_origins_lock);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1184
1185
  	if (dm_target_is_snapshot_merge(ti))
  		stop_merge(s);
138728dc9   Alasdair G Kergon   [PATCH] dm snapsh...
1186
1187
  	/* Prevent further origin writes from using this snapshot. */
  	/* After this returns there can be no new kcopyd jobs. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
  	unregister_snapshot(s);
879129d20   Mikulas Patocka   dm snapshot: wait...
1189
  	while (atomic_read(&s->pending_exceptions_count))
90fa1527b   Mikulas Patocka   dm snapshot: chan...
1190
  		msleep(1);
879129d20   Mikulas Patocka   dm snapshot: wait...
1191
1192
1193
1194
1195
  	/*
  	 * Ensure instructions in mempool_destroy aren't reordered
  	 * before atomic_read.
  	 */
  	smp_mb();
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1196
1197
1198
1199
1200
1201
  #ifdef CONFIG_DM_DEBUG
  	for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
  		BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
  #endif
  
  	mempool_destroy(s->tracked_chunk_pool);
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1202
  	__free_exceptions(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1203

92e868122   Mikulas Patocka   dm snapshot: use ...
1204
  	mempool_destroy(s->pending_pool);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1205
  	dm_exception_store_destroy(s->store);
138728dc9   Alasdair G Kergon   [PATCH] dm snapsh...
1206

fc56f6fbc   Mike Snitzer   dm snapshot: move...
1207
  	dm_put_device(ti, s->cow);
c24110450   Mikulas Patocka   dm snapshot: test...
1208
  	dm_put_device(ti, s->origin);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
  	kfree(s);
  }
  
  /*
   * Flush a list of buffers.
   */
  static void flush_bios(struct bio *bio)
  {
  	struct bio *n;
  
  	while (bio) {
  		n = bio->bi_next;
  		bio->bi_next = NULL;
  		generic_make_request(bio);
  		bio = n;
  	}
  }
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
  static int do_origin(struct dm_dev *origin, struct bio *bio);
  
  /*
   * Flush a list of buffers.
   */
  static void retry_origin_bios(struct dm_snapshot *s, struct bio *bio)
  {
  	struct bio *n;
  	int r;
  
  	while (bio) {
  		n = bio->bi_next;
  		bio->bi_next = NULL;
  		r = do_origin(s->origin, bio);
  		if (r == DM_MAPIO_REMAPPED)
  			generic_make_request(bio);
  		bio = n;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
  /*
   * Error a list of buffers.
   */
  static void error_bios(struct bio *bio)
  {
  	struct bio *n;
  
  	while (bio) {
  		n = bio->bi_next;
  		bio->bi_next = NULL;
6712ecf8f   NeilBrown   Drop 'size' argum...
1255
  		bio_io_error(bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256
1257
1258
  		bio = n;
  	}
  }
695368ac3   Alasdair G Kergon   [PATCH] dm snapsh...
1259
  static void __invalidate_snapshot(struct dm_snapshot *s, int err)
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1260
1261
1262
1263
1264
1265
1266
1267
  {
  	if (!s->valid)
  		return;
  
  	if (err == -EIO)
  		DMERR("Invalidating snapshot: Error reading/writing.");
  	else if (err == -ENOMEM)
  		DMERR("Invalidating snapshot: Unable to allocate exception.");
493df71c6   Jonathan Brassow   dm exception stor...
1268
1269
  	if (s->store->type->drop_snapshot)
  		s->store->type->drop_snapshot(s->store);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1270
1271
  
  	s->valid = 0;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1272
  	dm_table_event(s->ti->table);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1273
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1274
  static void pending_complete(struct dm_snap_pending_exception *pe, int success)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1275
  {
1d4989c85   Jon Brassow   dm snapshot: rena...
1276
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
  	struct dm_snapshot *s = pe->snap;
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1278
1279
  	struct bio *origin_bios = NULL;
  	struct bio *snapshot_bios = NULL;
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1280
  	struct bio *full_bio = NULL;
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1281
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282

76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1283
1284
  	if (!success) {
  		/* Read/write error - snapshot is unusable */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
  		down_write(&s->lock);
695368ac3   Alasdair G Kergon   [PATCH] dm snapsh...
1286
  		__invalidate_snapshot(s, -EIO);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1287
  		error = 1;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1288
1289
  		goto out;
  	}
3510cb94f   Jon Brassow   dm snapshot: rena...
1290
  	e = alloc_completed_exception();
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1291
  	if (!e) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1292
  		down_write(&s->lock);
695368ac3   Alasdair G Kergon   [PATCH] dm snapsh...
1293
  		__invalidate_snapshot(s, -ENOMEM);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1294
  		error = 1;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1295
1296
1297
  		goto out;
  	}
  	*e = pe->e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298

76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1299
1300
  	down_write(&s->lock);
  	if (!s->valid) {
3510cb94f   Jon Brassow   dm snapshot: rena...
1301
  		free_completed_exception(e);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1302
  		error = 1;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1303
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1304
  	}
615d1eb9c   Mike Snitzer   dm snapshot: crea...
1305
1306
  	/* Check for conflicting reads */
  	__check_for_conflicting_io(s, pe->e.old_chunk);
a8d41b59f   Mikulas Patocka   dm snapshot: fix ...
1307
1308
  
  	/*
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1309
1310
1311
  	 * Add a proper exception, and remove the
  	 * in-flight exception from the list.
  	 */
3510cb94f   Jon Brassow   dm snapshot: rena...
1312
  	dm_insert_exception(&s->complete, e);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1313

a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1314
  out:
3510cb94f   Jon Brassow   dm snapshot: rena...
1315
  	dm_remove_exception(&pe->e);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1316
  	snapshot_bios = bio_list_get(&pe->snapshot_bios);
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1317
  	origin_bios = bio_list_get(&pe->origin_bios);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1318
1319
1320
1321
1322
  	full_bio = pe->full_bio;
  	if (full_bio) {
  		full_bio->bi_end_io = pe->full_bio_end_io;
  		full_bio->bi_private = pe->full_bio_private;
  	}
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1323
  	free_pending_exception(pe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324

73dfd078c   Mikulas Patocka   dm snapshot: trig...
1325
  	increment_pending_exceptions_done_count();
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1326
1327
1328
  	up_write(&s->lock);
  
  	/* Submit any pending write bios */
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1329
1330
1331
  	if (error) {
  		if (full_bio)
  			bio_io_error(full_bio);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1332
  		error_bios(snapshot_bios);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1333
1334
1335
  	} else {
  		if (full_bio)
  			bio_endio(full_bio, 0);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1336
  		flush_bios(snapshot_bios);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1337
  	}
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1338

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1339
  	retry_origin_bios(s, origin_bios);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
1342
1343
  }
  
  static void commit_callback(void *context, int success)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1344
  	struct dm_snap_pending_exception *pe = context;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
1346
1347
1348
1349
1350
1351
  	pending_complete(pe, success);
  }
  
  /*
   * Called when the copy I/O has finished.  kcopyd actually runs
   * this code so don't block.
   */
4cdc1d1fa   Alasdair G Kergon   dm io: write erro...
1352
  static void copy_callback(int read_err, unsigned long write_err, void *context)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1354
  	struct dm_snap_pending_exception *pe = context;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
1356
1357
1358
1359
1360
1361
  	struct dm_snapshot *s = pe->snap;
  
  	if (read_err || write_err)
  		pending_complete(pe, 0);
  
  	else
  		/* Update the metadata if we are persistent */
493df71c6   Jonathan Brassow   dm exception stor...
1362
1363
  		s->store->type->commit_exception(s->store, &pe->e,
  						 commit_callback, pe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
1365
1366
1367
1368
  }
  
  /*
   * Dispatches the copy operation to kcopyd.
   */
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1369
  static void start_copy(struct dm_snap_pending_exception *pe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1370
1371
  {
  	struct dm_snapshot *s = pe->snap;
22a1ceb1e   Heinz Mauelshagen   dm io: clean inte...
1372
  	struct dm_io_region src, dest;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1373
1374
1375
1376
1377
1378
  	struct block_device *bdev = s->origin->bdev;
  	sector_t dev_size;
  
  	dev_size = get_dev_size(bdev);
  
  	src.bdev = bdev;
71fab00a6   Jonathan Brassow   dm snapshot: remo...
1379
  	src.sector = chunk_to_sector(s->store, pe->e.old_chunk);
df96eee67   Mikulas Patocka   dm snapshot: use ...
1380
  	src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381

fc56f6fbc   Mike Snitzer   dm snapshot: move...
1382
  	dest.bdev = s->cow->bdev;
71fab00a6   Jonathan Brassow   dm snapshot: remo...
1383
  	dest.sector = chunk_to_sector(s->store, pe->e.new_chunk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
1385
1386
  	dest.count = src.count;
  
  	/* Hand over to kcopyd */
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1387
  	dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
  }
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
  static void full_bio_end_io(struct bio *bio, int error)
  {
  	void *callback_data = bio->bi_private;
  
  	dm_kcopyd_do_callback(callback_data, 0, error ? 1 : 0);
  }
  
  static void start_full_bio(struct dm_snap_pending_exception *pe,
  			   struct bio *bio)
  {
  	struct dm_snapshot *s = pe->snap;
  	void *callback_data;
  
  	pe->full_bio = bio;
  	pe->full_bio_end_io = bio->bi_end_io;
  	pe->full_bio_private = bio->bi_private;
  
  	callback_data = dm_kcopyd_prepare_callback(s->kcopyd_client,
  						   copy_callback, pe);
  
  	bio->bi_end_io = full_bio_end_io;
  	bio->bi_private = callback_data;
  
  	generic_make_request(bio);
  }
2913808eb   Mikulas Patocka   dm snapshot: refa...
1414
1415
1416
  static struct dm_snap_pending_exception *
  __lookup_pending_exception(struct dm_snapshot *s, chunk_t chunk)
  {
3510cb94f   Jon Brassow   dm snapshot: rena...
1417
  	struct dm_exception *e = dm_lookup_exception(&s->pending, chunk);
2913808eb   Mikulas Patocka   dm snapshot: refa...
1418
1419
1420
1421
1422
1423
  
  	if (!e)
  		return NULL;
  
  	return container_of(e, struct dm_snap_pending_exception, e);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
1425
1426
1427
1428
1429
1430
1431
  /*
   * Looks to see if this snapshot already has a pending exception
   * for this chunk, otherwise it allocates a new one and inserts
   * it into the pending table.
   *
   * NOTE: a write lock must be held on snap->lock before calling
   * this.
   */
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1432
  static struct dm_snap_pending_exception *
c66213921   Mikulas Patocka   dm snapshot: avoi...
1433
1434
  __find_pending_exception(struct dm_snapshot *s,
  			 struct dm_snap_pending_exception *pe, chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1435
  {
c66213921   Mikulas Patocka   dm snapshot: avoi...
1436
  	struct dm_snap_pending_exception *pe2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437

2913808eb   Mikulas Patocka   dm snapshot: refa...
1438
1439
  	pe2 = __lookup_pending_exception(s, chunk);
  	if (pe2) {
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1440
  		free_pending_exception(pe);
2913808eb   Mikulas Patocka   dm snapshot: refa...
1441
  		return pe2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1442
  	}
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1443
1444
1445
  	pe->e.old_chunk = chunk;
  	bio_list_init(&pe->origin_bios);
  	bio_list_init(&pe->snapshot_bios);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1446
  	pe->started = 0;
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1447
  	pe->full_bio = NULL;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1448

493df71c6   Jonathan Brassow   dm exception stor...
1449
  	if (s->store->type->prepare_exception(s->store, &pe->e)) {
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1450
1451
1452
  		free_pending_exception(pe);
  		return NULL;
  	}
3510cb94f   Jon Brassow   dm snapshot: rena...
1453
  	dm_insert_exception(&s->pending, &pe->e);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1454

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
1456
  	return pe;
  }
1d4989c85   Jon Brassow   dm snapshot: rena...
1457
  static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
d74f81f8a   Milan Broz   dm snapshot: comb...
1458
  			    struct bio *bio, chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1459
  {
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1460
  	bio->bi_bdev = s->cow->bdev;
71fab00a6   Jonathan Brassow   dm snapshot: remo...
1461
1462
1463
1464
1465
  	bio->bi_sector = chunk_to_sector(s->store,
  					 dm_chunk_number(e->new_chunk) +
  					 (chunk - e->old_chunk)) +
  					 (bio->bi_sector &
  					  s->store->chunk_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
1467
1468
1469
1470
  }
  
  static int snapshot_map(struct dm_target *ti, struct bio *bio,
  			union map_info *map_context)
  {
1d4989c85   Jon Brassow   dm snapshot: rena...
1471
  	struct dm_exception *e;
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1472
  	struct dm_snapshot *s = ti->private;
d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
1473
  	int r = DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
  	chunk_t chunk;
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1475
  	struct dm_snap_pending_exception *pe = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476

d87f4c14f   Tejun Heo   dm: implement REQ...
1477
  	if (bio->bi_rw & REQ_FLUSH) {
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1478
  		bio->bi_bdev = s->cow->bdev;
494b3ee7d   Mikulas Patocka   dm snapshot: supp...
1479
1480
  		return DM_MAPIO_REMAPPED;
  	}
71fab00a6   Jonathan Brassow   dm snapshot: remo...
1481
  	chunk = sector_to_chunk(s->store, bio->bi_sector);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
1483
  
  	/* Full snapshots are not usable */
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1484
  	/* To get here the table must be live so s->active is always set. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
  	if (!s->valid)
f6a80ea8e   Alasdair G Kergon   [PATCH] device-ma...
1486
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1487

ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
  	/* FIXME: should only take write lock if we need
  	 * to copy an exception */
  	down_write(&s->lock);
  
  	if (!s->valid) {
  		r = -EIO;
  		goto out_unlock;
  	}
  
  	/* If the block is already remapped - use that, else remap it */
3510cb94f   Jon Brassow   dm snapshot: rena...
1498
  	e = dm_lookup_exception(&s->complete, chunk);
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1499
  	if (e) {
d74f81f8a   Milan Broz   dm snapshot: comb...
1500
  		remap_exception(s, e, bio, chunk);
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1501
1502
  		goto out_unlock;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
1504
1505
1506
1507
1508
  	/*
  	 * Write to snapshot - higher level takes care of RW/RO
  	 * flags so we should only get this if we are
  	 * writeable.
  	 */
  	if (bio_rw(bio) == WRITE) {
2913808eb   Mikulas Patocka   dm snapshot: refa...
1509
  		pe = __lookup_pending_exception(s, chunk);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1510
  		if (!pe) {
c66213921   Mikulas Patocka   dm snapshot: avoi...
1511
1512
1513
1514
1515
1516
1517
1518
1519
  			up_write(&s->lock);
  			pe = alloc_pending_exception(s);
  			down_write(&s->lock);
  
  			if (!s->valid) {
  				free_pending_exception(pe);
  				r = -EIO;
  				goto out_unlock;
  			}
3510cb94f   Jon Brassow   dm snapshot: rena...
1520
  			e = dm_lookup_exception(&s->complete, chunk);
35bf659b0   Mikulas Patocka   dm snapshot: avoi...
1521
1522
1523
1524
1525
  			if (e) {
  				free_pending_exception(pe);
  				remap_exception(s, e, bio, chunk);
  				goto out_unlock;
  			}
c66213921   Mikulas Patocka   dm snapshot: avoi...
1526
  			pe = __find_pending_exception(s, pe, chunk);
2913808eb   Mikulas Patocka   dm snapshot: refa...
1527
1528
1529
1530
1531
  			if (!pe) {
  				__invalidate_snapshot(s, -ENOMEM);
  				r = -EIO;
  				goto out_unlock;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1532
  		}
d74f81f8a   Milan Broz   dm snapshot: comb...
1533
  		remap_exception(s, &pe->e, bio, chunk);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1534

d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
1535
  		r = DM_MAPIO_SUBMITTED;
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1536

a6e50b409   Mikulas Patocka   dm snapshot: skip...
1537
1538
1539
1540
1541
1542
1543
1544
1545
  		if (!pe->started &&
  		    bio->bi_size == (s->store->chunk_size << SECTOR_SHIFT)) {
  			pe->started = 1;
  			up_write(&s->lock);
  			start_full_bio(pe, bio);
  			goto out;
  		}
  
  		bio_list_add(&pe->snapshot_bios, bio);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1546
1547
1548
  		if (!pe->started) {
  			/* this is protected by snap->lock */
  			pe->started = 1;
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1549
  			up_write(&s->lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1550
  			start_copy(pe);
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1551
1552
  			goto out;
  		}
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1553
  	} else {
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1554
  		bio->bi_bdev = s->origin->bdev;
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1555
1556
  		map_context->ptr = track_chunk(s, chunk);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557

a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1558
  out_unlock:
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1559
  	up_write(&s->lock);
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1560
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
1562
  	return r;
  }
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1563
1564
1565
1566
1567
1568
1569
1570
1571
  /*
   * A snapshot-merge target behaves like a combination of a snapshot
   * target and a snapshot-origin target.  It only generates new
   * exceptions in other snapshots and not in the one that is being
   * merged.
   *
   * For each chunk, if there is an existing exception, it is used to
   * redirect I/O to the cow device.  Otherwise I/O is sent to the origin,
   * which in turn might generate exceptions in other snapshots.
9fe862548   Mikulas Patocka   dm snapshot: queu...
1572
1573
   * If merging is currently taking place on the chunk in question, the
   * I/O is deferred by adding it to s->bios_queued_during_merge.
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1574
1575
1576
1577
1578
1579
1580
1581
   */
  static int snapshot_merge_map(struct dm_target *ti, struct bio *bio,
  			      union map_info *map_context)
  {
  	struct dm_exception *e;
  	struct dm_snapshot *s = ti->private;
  	int r = DM_MAPIO_REMAPPED;
  	chunk_t chunk;
d87f4c14f   Tejun Heo   dm: implement REQ...
1582
  	if (bio->bi_rw & REQ_FLUSH) {
57cba5d36   Mike Snitzer   dm: rename map_in...
1583
  		if (!map_context->target_request_nr)
10b8106a7   Mike Snitzer   dm snapshot: supp...
1584
1585
1586
1587
1588
1589
  			bio->bi_bdev = s->origin->bdev;
  		else
  			bio->bi_bdev = s->cow->bdev;
  		map_context->ptr = NULL;
  		return DM_MAPIO_REMAPPED;
  	}
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1590
  	chunk = sector_to_chunk(s->store, bio->bi_sector);
9fe862548   Mikulas Patocka   dm snapshot: queu...
1591
  	down_write(&s->lock);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1592

d2fdb776e   Mikulas Patocka   dm snapshot: use ...
1593
1594
1595
  	/* Full merging snapshots are redirected to the origin */
  	if (!s->valid)
  		goto redirect_to_origin;
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1596
1597
1598
1599
  
  	/* If the block is already remapped - use that */
  	e = dm_lookup_exception(&s->complete, chunk);
  	if (e) {
9fe862548   Mikulas Patocka   dm snapshot: queu...
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
  		/* Queue writes overlapping with chunks being merged */
  		if (bio_rw(bio) == WRITE &&
  		    chunk >= s->first_merging_chunk &&
  		    chunk < (s->first_merging_chunk +
  			     s->num_merging_chunks)) {
  			bio->bi_bdev = s->origin->bdev;
  			bio_list_add(&s->bios_queued_during_merge, bio);
  			r = DM_MAPIO_SUBMITTED;
  			goto out_unlock;
  		}
17aa03326   Mikulas Patocka   dm snapshot: dela...
1610

3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1611
  		remap_exception(s, e, bio, chunk);
17aa03326   Mikulas Patocka   dm snapshot: dela...
1612
1613
1614
  
  		if (bio_rw(bio) == WRITE)
  			map_context->ptr = track_chunk(s, chunk);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1615
1616
  		goto out_unlock;
  	}
d2fdb776e   Mikulas Patocka   dm snapshot: use ...
1617
  redirect_to_origin:
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1618
1619
1620
  	bio->bi_bdev = s->origin->bdev;
  
  	if (bio_rw(bio) == WRITE) {
9fe862548   Mikulas Patocka   dm snapshot: queu...
1621
  		up_write(&s->lock);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1622
1623
1624
1625
  		return do_origin(s->origin, bio);
  	}
  
  out_unlock:
9fe862548   Mikulas Patocka   dm snapshot: queu...
1626
  	up_write(&s->lock);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1627
1628
1629
  
  	return r;
  }
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
  static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
  			   int error, union map_info *map_context)
  {
  	struct dm_snapshot *s = ti->private;
  	struct dm_snap_tracked_chunk *c = map_context->ptr;
  
  	if (c)
  		stop_tracking_chunk(s, c);
  
  	return 0;
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1641
1642
1643
1644
1645
1646
  static void snapshot_merge_presuspend(struct dm_target *ti)
  {
  	struct dm_snapshot *s = ti->private;
  
  	stop_merge(s);
  }
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1647
1648
1649
1650
1651
1652
1653
  static int snapshot_preresume(struct dm_target *ti)
  {
  	int r = 0;
  	struct dm_snapshot *s = ti->private;
  	struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
  
  	down_read(&_origins_lock);
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
1654
  	(void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1655
1656
1657
1658
1659
1660
  	if (snap_src && snap_dest) {
  		down_read(&snap_src->lock);
  		if (s == snap_src) {
  			DMERR("Unable to resume snapshot source until "
  			      "handover completes.");
  			r = -EINVAL;
b83b2f295   Mike Snitzer   dm snapshot: avoi...
1661
  		} else if (!dm_suspended(snap_src->ti)) {
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
  			DMERR("Unable to perform snapshot handover until "
  			      "source is suspended.");
  			r = -EINVAL;
  		}
  		up_read(&snap_src->lock);
  	}
  	up_read(&_origins_lock);
  
  	return r;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
1673
  static void snapshot_resume(struct dm_target *ti)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1674
  	struct dm_snapshot *s = ti->private;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1675
1676
1677
  	struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
  
  	down_read(&_origins_lock);
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
1678
  	(void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
  	if (snap_src && snap_dest) {
  		down_write(&snap_src->lock);
  		down_write_nested(&snap_dest->lock, SINGLE_DEPTH_NESTING);
  		__handover_exceptions(snap_src, snap_dest);
  		up_write(&snap_dest->lock);
  		up_write(&snap_src->lock);
  	}
  	up_read(&_origins_lock);
  
  	/* Now we have correct chunk size, reregister */
  	reregister_snapshot(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1690

aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
1691
1692
1693
  	down_write(&s->lock);
  	s->active = 1;
  	up_write(&s->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1694
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
  static sector_t get_origin_minimum_chunksize(struct block_device *bdev)
  {
  	sector_t min_chunksize;
  
  	down_read(&_origins_lock);
  	min_chunksize = __minimum_chunk_size(__lookup_origin(bdev));
  	up_read(&_origins_lock);
  
  	return min_chunksize;
  }
  
  static void snapshot_merge_resume(struct dm_target *ti)
  {
  	struct dm_snapshot *s = ti->private;
  
  	/*
  	 * Handover exceptions from existing snapshot.
  	 */
  	snapshot_resume(ti);
  
  	/*
  	 * snapshot-merge acts as an origin, so set ti->split_io
  	 */
  	ti->split_io = get_origin_minimum_chunksize(s->origin->bdev);
  
  	start_merge(s);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1722
1723
1724
  static int snapshot_status(struct dm_target *ti, status_type_t type,
  			   char *result, unsigned int maxlen)
  {
2e4a31df2   Jonathan Brassow   dm snapshot: use ...
1725
  	unsigned sz = 0;
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1726
  	struct dm_snapshot *snap = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1727
1728
1729
  
  	switch (type) {
  	case STATUSTYPE_INFO:
94e76572b   Mikulas Patocka   dm snapshot: only...
1730
1731
  
  		down_write(&snap->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
  		if (!snap->valid)
2e4a31df2   Jonathan Brassow   dm snapshot: use ...
1733
  			DMEMIT("Invalid");
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
1734
1735
  		else if (snap->merge_failed)
  			DMEMIT("Merge failed");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
  		else {
985903bb3   Mike Snitzer   dm snapshot: add ...
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
  			if (snap->store->type->usage) {
  				sector_t total_sectors, sectors_allocated,
  					 metadata_sectors;
  				snap->store->type->usage(snap->store,
  							 &total_sectors,
  							 &sectors_allocated,
  							 &metadata_sectors);
  				DMEMIT("%llu/%llu %llu",
  				       (unsigned long long)sectors_allocated,
  				       (unsigned long long)total_sectors,
  				       (unsigned long long)metadata_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1748
1749
  			}
  			else
2e4a31df2   Jonathan Brassow   dm snapshot: use ...
1750
  				DMEMIT("Unknown");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751
  		}
94e76572b   Mikulas Patocka   dm snapshot: only...
1752
1753
  
  		up_write(&snap->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1754
1755
1756
1757
1758
1759
1760
1761
  		break;
  
  	case STATUSTYPE_TABLE:
  		/*
  		 * kdevname returns a static pointer so we need
  		 * to make private copies if the output is to
  		 * make sense.
  		 */
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1762
  		DMEMIT("%s %s", snap->origin->name, snap->cow->name);
1e302a929   Jonathan Brassow   dm snapshot: move...
1763
1764
  		snap->store->type->status(snap->store, type, result + sz,
  					  maxlen - sz);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1765
1766
1767
1768
1769
  		break;
  	}
  
  	return 0;
  }
8811f46c1   Mike Snitzer   dm snapshot: impl...
1770
1771
1772
1773
  static int snapshot_iterate_devices(struct dm_target *ti,
  				    iterate_devices_callout_fn fn, void *data)
  {
  	struct dm_snapshot *snap = ti->private;
1e5554c84   Mikulas Patocka   dm snapshot: iter...
1774
1775
1776
  	int r;
  
  	r = fn(ti, snap->origin, 0, ti->len, data);
8811f46c1   Mike Snitzer   dm snapshot: impl...
1777

1e5554c84   Mikulas Patocka   dm snapshot: iter...
1778
1779
1780
1781
  	if (!r)
  		r = fn(ti, snap->cow, 0, get_dev_size(snap->cow->bdev), data);
  
  	return r;
8811f46c1   Mike Snitzer   dm snapshot: impl...
1782
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1783
1784
1785
  /*-----------------------------------------------------------------
   * Origin methods
   *---------------------------------------------------------------*/
9eaae8ffb   Mikulas Patocka   dm snapshot: make...
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
  
  /*
   * If no exceptions need creating, DM_MAPIO_REMAPPED is returned and any
   * supplied bio was ignored.  The caller may submit it immediately.
   * (No remapping actually occurs as the origin is always a direct linear
   * map.)
   *
   * If further exceptions are required, DM_MAPIO_SUBMITTED is returned
   * and any supplied bio is added to a list to be submitted once all
   * the necessary exceptions exist.
   */
  static int __origin_write(struct list_head *snapshots, sector_t sector,
  			  struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1799
  {
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1800
  	int r = DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
  	struct dm_snapshot *snap;
1d4989c85   Jon Brassow   dm snapshot: rena...
1802
  	struct dm_exception *e;
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1803
1804
1805
  	struct dm_snap_pending_exception *pe;
  	struct dm_snap_pending_exception *pe_to_start_now = NULL;
  	struct dm_snap_pending_exception *pe_to_start_last = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
1807
1808
1809
  	chunk_t chunk;
  
  	/* Do all the snapshots on this origin */
  	list_for_each_entry (snap, snapshots, list) {
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1810
1811
1812
1813
1814
1815
  		/*
  		 * Don't make new exceptions in a merging snapshot
  		 * because it has effectively been deleted
  		 */
  		if (dm_target_is_snapshot_merge(snap->ti))
  			continue;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1816
  		down_write(&snap->lock);
aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
1817
1818
  		/* Only deal with valid and active snapshots */
  		if (!snap->valid || !snap->active)
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1819
  			goto next_snapshot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820

d5e404c10   Alasdair G Kergon   [PATCH] device-ma...
1821
  		/* Nothing to do if writing beyond end of snapshot */
9eaae8ffb   Mikulas Patocka   dm snapshot: make...
1822
  		if (sector >= dm_table_get_size(snap->ti->table))
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1823
  			goto next_snapshot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1824
1825
1826
1827
1828
  
  		/*
  		 * Remember, different snapshots can have
  		 * different chunk sizes.
  		 */
9eaae8ffb   Mikulas Patocka   dm snapshot: make...
1829
  		chunk = sector_to_chunk(snap->store, sector);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
1831
1832
1833
1834
1835
  
  		/*
  		 * Check exception table to see if block
  		 * is already remapped in this snapshot
  		 * and trigger an exception if not.
  		 */
3510cb94f   Jon Brassow   dm snapshot: rena...
1836
  		e = dm_lookup_exception(&snap->complete, chunk);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1837
1838
  		if (e)
  			goto next_snapshot;
2913808eb   Mikulas Patocka   dm snapshot: refa...
1839
  		pe = __lookup_pending_exception(snap, chunk);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1840
  		if (!pe) {
c66213921   Mikulas Patocka   dm snapshot: avoi...
1841
1842
1843
1844
1845
1846
1847
1848
  			up_write(&snap->lock);
  			pe = alloc_pending_exception(snap);
  			down_write(&snap->lock);
  
  			if (!snap->valid) {
  				free_pending_exception(pe);
  				goto next_snapshot;
  			}
3510cb94f   Jon Brassow   dm snapshot: rena...
1849
  			e = dm_lookup_exception(&snap->complete, chunk);
35bf659b0   Mikulas Patocka   dm snapshot: avoi...
1850
1851
1852
1853
  			if (e) {
  				free_pending_exception(pe);
  				goto next_snapshot;
  			}
c66213921   Mikulas Patocka   dm snapshot: avoi...
1854
  			pe = __find_pending_exception(snap, pe, chunk);
2913808eb   Mikulas Patocka   dm snapshot: refa...
1855
1856
1857
1858
  			if (!pe) {
  				__invalidate_snapshot(snap, -ENOMEM);
  				goto next_snapshot;
  			}
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1859
  		}
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1860
  		r = DM_MAPIO_SUBMITTED;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1861

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1862
1863
1864
1865
1866
1867
1868
1869
  		/*
  		 * If an origin bio was supplied, queue it to wait for the
  		 * completion of this exception, and start this one last,
  		 * at the end of the function.
  		 */
  		if (bio) {
  			bio_list_add(&pe->origin_bios, bio);
  			bio = NULL;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1870

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1871
1872
1873
1874
  			if (!pe->started) {
  				pe->started = 1;
  				pe_to_start_last = pe;
  			}
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1875
1876
1877
1878
  		}
  
  		if (!pe->started) {
  			pe->started = 1;
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1879
  			pe_to_start_now = pe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1880
  		}
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1881
  next_snapshot:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882
  		up_write(&snap->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1884
1885
1886
1887
  		if (pe_to_start_now) {
  			start_copy(pe_to_start_now);
  			pe_to_start_now = NULL;
  		}
b4b610f68   Alasdair G Kergon   [PATCH] device-ma...
1888
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
  	/*
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1890
1891
  	 * Submit the exception against which the bio is queued last,
  	 * to give the other exceptions a head start.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1892
  	 */
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1893
1894
  	if (pe_to_start_last)
  		start_copy(pe_to_start_last);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
  
  	return r;
  }
  
  /*
   * Called on a write from the origin driver.
   */
  static int do_origin(struct dm_dev *origin, struct bio *bio)
  {
  	struct origin *o;
d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
1905
  	int r = DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1906
1907
1908
1909
  
  	down_read(&_origins_lock);
  	o = __lookup_origin(origin->bdev);
  	if (o)
9eaae8ffb   Mikulas Patocka   dm snapshot: make...
1910
  		r = __origin_write(&o->snapshots, bio->bi_sector, bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1911
1912
1913
1914
1915
1916
  	up_read(&_origins_lock);
  
  	return r;
  }
  
  /*
73dfd078c   Mikulas Patocka   dm snapshot: trig...
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
   * Trigger exceptions in all non-merging snapshots.
   *
   * The chunk size of the merging snapshot may be larger than the chunk
   * size of some other snapshot so we may need to reallocate multiple
   * chunks in other snapshots.
   *
   * We scan all the overlapping exceptions in the other snapshots.
   * Returns 1 if anything was reallocated and must be waited for,
   * otherwise returns 0.
   *
   * size must be a multiple of merging_snap's chunk_size.
   */
  static int origin_write_extent(struct dm_snapshot *merging_snap,
  			       sector_t sector, unsigned size)
  {
  	int must_wait = 0;
  	sector_t n;
  	struct origin *o;
  
  	/*
  	 * The origin's __minimum_chunk_size() got stored in split_io
  	 * by snapshot_merge_resume().
  	 */
  	down_read(&_origins_lock);
  	o = __lookup_origin(merging_snap->origin->bdev);
  	for (n = 0; n < size; n += merging_snap->ti->split_io)
  		if (__origin_write(&o->snapshots, sector + n, NULL) ==
  		    DM_MAPIO_SUBMITTED)
  			must_wait = 1;
  	up_read(&_origins_lock);
  
  	return must_wait;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
   * Origin: maps a linear range of a device, with hooks for snapshotting.
   */
  
  /*
   * Construct an origin mapping: <dev_path>
   * The context for an origin is merely a 'struct dm_dev *'
   * pointing to the real device.
   */
  static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
  {
  	int r;
  	struct dm_dev *dev;
  
  	if (argc != 1) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
1966
  		ti->error = "origin: incorrect number of arguments";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1967
1968
  		return -EINVAL;
  	}
8215d6ec5   Nikanth Karthikesan   dm table: remove ...
1969
  	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1970
1971
1972
1973
1974
1975
  	if (r) {
  		ti->error = "Cannot get target device";
  		return r;
  	}
  
  	ti->private = dev;
494b3ee7d   Mikulas Patocka   dm snapshot: supp...
1976
  	ti->num_flush_requests = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1977
1978
1979
1980
1981
  	return 0;
  }
  
  static void origin_dtr(struct dm_target *ti)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1982
  	struct dm_dev *dev = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1983
1984
1985
1986
1987
1988
  	dm_put_device(ti, dev);
  }
  
  static int origin_map(struct dm_target *ti, struct bio *bio,
  		      union map_info *map_context)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1989
  	struct dm_dev *dev = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1990
  	bio->bi_bdev = dev->bdev;
d87f4c14f   Tejun Heo   dm: implement REQ...
1991
  	if (bio->bi_rw & REQ_FLUSH)
494b3ee7d   Mikulas Patocka   dm snapshot: supp...
1992
  		return DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1993
  	/* Only tell snapshots if this is a write */
d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
1994
  	return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1995
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1996
1997
1998
1999
2000
2001
  /*
   * Set the target "split_io" field to the minimum of all the snapshots'
   * chunk sizes.
   */
  static void origin_resume(struct dm_target *ti)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
2002
  	struct dm_dev *dev = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2003

1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2004
  	ti->split_io = get_origin_minimum_chunksize(dev->bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2005
2006
2007
2008
2009
  }
  
  static int origin_status(struct dm_target *ti, status_type_t type, char *result,
  			 unsigned int maxlen)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
2010
  	struct dm_dev *dev = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
  
  	switch (type) {
  	case STATUSTYPE_INFO:
  		result[0] = '\0';
  		break;
  
  	case STATUSTYPE_TABLE:
  		snprintf(result, maxlen, "%s", dev->name);
  		break;
  	}
  
  	return 0;
  }
b1d555283   Mikulas Patocka   dm snapshot: impl...
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
  static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
  			struct bio_vec *biovec, int max_size)
  {
  	struct dm_dev *dev = ti->private;
  	struct request_queue *q = bdev_get_queue(dev->bdev);
  
  	if (!q->merge_bvec_fn)
  		return max_size;
  
  	bvm->bi_bdev = dev->bdev;
  	bvm->bi_sector = bvm->bi_sector;
  
  	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
  }
8811f46c1   Mike Snitzer   dm snapshot: impl...
2038
2039
2040
2041
2042
2043
2044
  static int origin_iterate_devices(struct dm_target *ti,
  				  iterate_devices_callout_fn fn, void *data)
  {
  	struct dm_dev *dev = ti->private;
  
  	return fn(ti, dev, 0, ti->len, data);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2045
2046
  static struct target_type origin_target = {
  	.name    = "snapshot-origin",
b83b2f295   Mike Snitzer   dm snapshot: avoi...
2047
  	.version = {1, 7, 1},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2048
2049
2050
2051
2052
2053
  	.module  = THIS_MODULE,
  	.ctr     = origin_ctr,
  	.dtr     = origin_dtr,
  	.map     = origin_map,
  	.resume  = origin_resume,
  	.status  = origin_status,
b1d555283   Mikulas Patocka   dm snapshot: impl...
2054
  	.merge	 = origin_merge,
8811f46c1   Mike Snitzer   dm snapshot: impl...
2055
  	.iterate_devices = origin_iterate_devices,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2056
2057
2058
2059
  };
  
  static struct target_type snapshot_target = {
  	.name    = "snapshot",
b83b2f295   Mike Snitzer   dm snapshot: avoi...
2060
  	.version = {1, 10, 0},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2061
2062
2063
2064
  	.module  = THIS_MODULE,
  	.ctr     = snapshot_ctr,
  	.dtr     = snapshot_dtr,
  	.map     = snapshot_map,
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2065
  	.end_io  = snapshot_end_io,
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2066
  	.preresume  = snapshot_preresume,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2067
2068
  	.resume  = snapshot_resume,
  	.status  = snapshot_status,
8811f46c1   Mike Snitzer   dm snapshot: impl...
2069
  	.iterate_devices = snapshot_iterate_devices,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2070
  };
d698aa450   Mikulas Patocka   dm snapshot: add ...
2071
2072
  static struct target_type merge_target = {
  	.name    = dm_snapshot_merge_target_name,
b83b2f295   Mike Snitzer   dm snapshot: avoi...
2073
  	.version = {1, 1, 0},
d698aa450   Mikulas Patocka   dm snapshot: add ...
2074
2075
2076
  	.module  = THIS_MODULE,
  	.ctr     = snapshot_ctr,
  	.dtr     = snapshot_dtr,
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2077
  	.map     = snapshot_merge_map,
d698aa450   Mikulas Patocka   dm snapshot: add ...
2078
  	.end_io  = snapshot_end_io,
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2079
  	.presuspend = snapshot_merge_presuspend,
d698aa450   Mikulas Patocka   dm snapshot: add ...
2080
  	.preresume  = snapshot_preresume,
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2081
  	.resume  = snapshot_merge_resume,
d698aa450   Mikulas Patocka   dm snapshot: add ...
2082
2083
2084
  	.status  = snapshot_status,
  	.iterate_devices = snapshot_iterate_devices,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2085
2086
2087
  static int __init dm_snapshot_init(void)
  {
  	int r;
4db6bfe02   Alasdair G Kergon   dm snapshot: spli...
2088
2089
2090
2091
2092
  	r = dm_exception_store_init();
  	if (r) {
  		DMERR("Failed to initialize exception stores");
  		return r;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2093
  	r = dm_register_target(&snapshot_target);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2094
  	if (r < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2095
  		DMERR("snapshot target register failed %d", r);
034a186d2   Jonathan Brassow   dm snapshot: free...
2096
  		goto bad_register_snapshot_target;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2097
2098
2099
2100
  	}
  
  	r = dm_register_target(&origin_target);
  	if (r < 0) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
2101
  		DMERR("Origin target register failed %d", r);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2102
2103
2104
2105
2106
2107
2108
  		goto bad_register_origin_target;
  	}
  
  	r = dm_register_target(&merge_target);
  	if (r < 0) {
  		DMERR("Merge target register failed %d", r);
  		goto bad_register_merge_target;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2109
2110
2111
2112
2113
  	}
  
  	r = init_origin_hash();
  	if (r) {
  		DMERR("init_origin_hash failed.");
d698aa450   Mikulas Patocka   dm snapshot: add ...
2114
  		goto bad_origin_hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2115
  	}
1d4989c85   Jon Brassow   dm snapshot: rena...
2116
  	exception_cache = KMEM_CACHE(dm_exception, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2117
2118
2119
  	if (!exception_cache) {
  		DMERR("Couldn't create exception cache.");
  		r = -ENOMEM;
d698aa450   Mikulas Patocka   dm snapshot: add ...
2120
  		goto bad_exception_cache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2121
  	}
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
2122
  	pending_cache = KMEM_CACHE(dm_snap_pending_exception, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2123
2124
2125
  	if (!pending_cache) {
  		DMERR("Couldn't create pending cache.");
  		r = -ENOMEM;
d698aa450   Mikulas Patocka   dm snapshot: add ...
2126
  		goto bad_pending_cache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2127
  	}
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2128
2129
2130
2131
  	tracked_chunk_cache = KMEM_CACHE(dm_snap_tracked_chunk, 0);
  	if (!tracked_chunk_cache) {
  		DMERR("Couldn't create cache to track chunks in use.");
  		r = -ENOMEM;
d698aa450   Mikulas Patocka   dm snapshot: add ...
2132
  		goto bad_tracked_chunk_cache;
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2133
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2134
  	return 0;
d698aa450   Mikulas Patocka   dm snapshot: add ...
2135
  bad_tracked_chunk_cache:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2136
  	kmem_cache_destroy(pending_cache);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2137
  bad_pending_cache:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2138
  	kmem_cache_destroy(exception_cache);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2139
  bad_exception_cache:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2140
  	exit_origin_hash();
d698aa450   Mikulas Patocka   dm snapshot: add ...
2141
2142
2143
  bad_origin_hash:
  	dm_unregister_target(&merge_target);
  bad_register_merge_target:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
  	dm_unregister_target(&origin_target);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2145
  bad_register_origin_target:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2146
  	dm_unregister_target(&snapshot_target);
034a186d2   Jonathan Brassow   dm snapshot: free...
2147
2148
  bad_register_snapshot_target:
  	dm_exception_store_exit();
d698aa450   Mikulas Patocka   dm snapshot: add ...
2149

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2150
2151
2152
2153
2154
  	return r;
  }
  
  static void __exit dm_snapshot_exit(void)
  {
10d3bd09a   Mikulas Patocka   dm: consolidate t...
2155
2156
  	dm_unregister_target(&snapshot_target);
  	dm_unregister_target(&origin_target);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2157
  	dm_unregister_target(&merge_target);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2158
2159
  
  	exit_origin_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2160
2161
  	kmem_cache_destroy(pending_cache);
  	kmem_cache_destroy(exception_cache);
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2162
  	kmem_cache_destroy(tracked_chunk_cache);
4db6bfe02   Alasdair G Kergon   dm snapshot: spli...
2163
2164
  
  	dm_exception_store_exit();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2165
2166
2167
2168
2169
2170
2171
2172
2173
  }
  
  /* Module hooks */
  module_init(dm_snapshot_init);
  module_exit(dm_snapshot_exit);
  
  MODULE_DESCRIPTION(DM_NAME " snapshot target");
  MODULE_AUTHOR("Joe Thornber");
  MODULE_LICENSE("GPL");