Blame view

drivers/md/dm-snap.c 68.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
   * 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
8
  #include <linux/device-mapper.h>
90fa1527b   Mikulas Patocka   dm snapshot: chan...
9
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
  #include <linux/fs.h>
  #include <linux/init.h>
  #include <linux/kdev_t.h>
  #include <linux/list.h>
f79ae415b   Nikos Tsironis   dm snapshot: Make...
14
  #include <linux/list_bl.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
  #include <linux/mempool.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/vmalloc.h>
6f3c3f0af   vignesh babu   dm: use is_power_...
19
  #include <linux/log2.h>
a765e20ee   Alasdair G Kergon   dm: move include ...
20
  #include <linux/dm-kcopyd.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21

b735fede8   Mikulas Patocka   dm snapshot: susp...
22
  #include "dm.h"
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
  	uint32_t hash_mask;
  	unsigned hash_shift;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
40
  	struct hlist_bl_head *table;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
41
42
43
  };
  
  struct dm_snapshot {
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
44
  	struct rw_semaphore lock;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
45
46
  
  	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
  	int valid;
76c44f6d8   Mikulas Patocka   dm snapshot: don'...
58
59
60
61
62
63
  	/*
  	 * The snapshot overflowed because of a write to the snapshot device.
  	 * We don't have to invalidate the snapshot in this case, but we need
  	 * to prevent further writes.
  	 */
  	int snapshot_overflowed;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
64
65
  	/* Origin writes don't trigger exceptions until this is set */
  	int active;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
66
  	atomic_t pending_exceptions_count;
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
67
68
69
  	spinlock_t pe_allocation_lock;
  
  	/* Protected by "pe_allocation_lock" */
230c83afd   Mikulas Patocka   dm snapshot: avoi...
70
71
72
73
74
75
76
77
78
  	sector_t exception_start_sequence;
  
  	/* Protected by kcopyd single-threaded callback */
  	sector_t exception_complete_sequence;
  
  	/*
  	 * A list of pending exceptions that completed out of order.
  	 * Protected by kcopyd single-threaded callback.
  	 */
3db2776d9   David Jeffery   dm snapshot: impr...
79
  	struct rb_root out_of_order_tree;
230c83afd   Mikulas Patocka   dm snapshot: avoi...
80

6f1c819c2   Kent Overstreet   dm: convert to bi...
81
  	mempool_t pending_pool;
924e600d4   Mike Snitzer   dm: eliminate som...
82

191437a53   Jon Brassow   dm snapshot: rena...
83
84
  	struct dm_exception_table pending;
  	struct dm_exception_table complete;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
85
86
87
88
89
90
  
  	/*
  	 * 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...
91
92
  	/* Chunks with outstanding reads */
  	spinlock_t tracked_chunk_lock;
924e600d4   Mike Snitzer   dm: eliminate som...
93
  	struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
94
95
  	/* The on disk metadata handler */
  	struct dm_exception_store *store;
b21555786   Mikulas Patocka   dm snapshot: rewo...
96
97
  	unsigned in_progress;
  	struct wait_queue_head in_progress_wait;
721b1d98f   Nikos Tsironis   dm snapshot: Fix ...
98

ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
99
  	struct dm_kcopyd_client *kcopyd_client;
924e600d4   Mike Snitzer   dm: eliminate som...
100
101
102
103
104
105
  	/* 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 ...
106

d8ddb1cff   Mike Snitzer   dm snapshot: repo...
107
108
109
110
111
112
113
114
115
116
117
118
119
  	/*
  	 * 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.
  	 */
2e6023850   Mike Snitzer   dm snapshot: add ...
120
121
122
123
  	bool merge_failed:1;
  
  	bool discard_zeroes_cow:1;
  	bool discard_passdown_origin:1;
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
124

9fe862548   Mikulas Patocka   dm snapshot: queu...
125
126
127
128
129
  	/*
  	 * Incoming bios that overlap with chunks being merged must wait
  	 * for them to be committed.
  	 */
  	struct bio_list bios_queued_during_merge;
1ac4156de   Akilesh Kailash   dm snapshot: flus...
130
131
132
133
134
  
  	/*
  	 * Flush data after merge.
  	 */
  	struct bio flush_bio;
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
135
  };
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
136
137
138
139
140
141
142
143
  /*
   * 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
721b1d98f   Nikos Tsironis   dm snapshot: Fix ...
144
145
146
147
148
149
150
151
  /*
   * Maximum number of chunks being copied on write.
   *
   * The value was decided experimentally as a trade-off between memory
   * consumption, stalling the kernel's workqueues and maintaining a high enough
   * throughput.
   */
  #define DEFAULT_COW_THRESHOLD 2048
b21555786   Mikulas Patocka   dm snapshot: rewo...
152
153
  static unsigned cow_threshold = DEFAULT_COW_THRESHOLD;
  module_param_named(snapshot_cow_threshold, cow_threshold, uint, 0644);
721b1d98f   Nikos Tsironis   dm snapshot: Fix ...
154
  MODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write");
df5d2e908   Mikulas Patocka   dm kcopyd: introd...
155
156
  DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,
  		"A percentage of time allocated for copy on write");
c24110450   Mikulas Patocka   dm snapshot: test...
157
158
159
160
161
  struct dm_dev *dm_snap_origin(struct dm_snapshot *s)
  {
  	return s->origin;
  }
  EXPORT_SYMBOL(dm_snap_origin);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
162
163
164
165
166
  struct dm_dev *dm_snap_cow(struct dm_snapshot *s)
  {
  	return s->cow;
  }
  EXPORT_SYMBOL(dm_snap_cow);
ccc45ea8a   Jonathan Brassow   dm snapshot: remo...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  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...
181
  struct dm_snap_pending_exception {
1d4989c85   Jon Brassow   dm snapshot: rena...
182
  	struct dm_exception e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
189
  
  	/*
  	 * 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
190
191
192
193
194
195
196
197
  	/* 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...
198

230c83afd   Mikulas Patocka   dm snapshot: avoi...
199
200
201
202
203
  	/* There was copying error. */
  	int copy_error;
  
  	/* A sequence number, it is used for in-order completion. */
  	sector_t exception_sequence;
3db2776d9   David Jeffery   dm snapshot: impr...
204
  	struct rb_node out_of_order_node;
230c83afd   Mikulas Patocka   dm snapshot: avoi...
205

a6e50b409   Mikulas Patocka   dm snapshot: skip...
206
207
208
209
210
  	/*
  	 * For writing a complete chunk, bypassing the copy.
  	 */
  	struct bio *full_bio;
  	bio_end_io_t *full_bio_end_io;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
216
  };
  
  /*
   * Hash table mapping origin volumes to lists of snapshots and
   * a lock to protect it
   */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
217
218
  static struct kmem_cache *exception_cache;
  static struct kmem_cache *pending_cache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219

cd45daffd   Mikulas Patocka   dm snapshot: trac...
220
221
222
223
  struct dm_snap_tracked_chunk {
  	struct hlist_node node;
  	chunk_t chunk;
  };
ee18026ac   Mikulas Patocka   dm snapshot: do n...
224
225
226
227
228
229
230
231
232
233
234
235
236
  static void init_tracked_chunk(struct bio *bio)
  {
  	struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
  	INIT_HLIST_NODE(&c->node);
  }
  
  static bool is_bio_tracked(struct bio *bio)
  {
  	struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
  	return !hlist_unhashed(&c->node);
  }
  
  static void track_chunk(struct dm_snapshot *s, struct bio *bio, chunk_t chunk)
cd45daffd   Mikulas Patocka   dm snapshot: trac...
237
  {
42bc954f2   Mikulas Patocka   dm snapshot: use ...
238
  	struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
cd45daffd   Mikulas Patocka   dm snapshot: trac...
239
240
  
  	c->chunk = chunk;
9aa0c0e60   Mikulas Patocka   dm snapshot: opti...
241
  	spin_lock_irq(&s->tracked_chunk_lock);
cd45daffd   Mikulas Patocka   dm snapshot: trac...
242
243
  	hlist_add_head(&c->node,
  		       &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
9aa0c0e60   Mikulas Patocka   dm snapshot: opti...
244
  	spin_unlock_irq(&s->tracked_chunk_lock);
cd45daffd   Mikulas Patocka   dm snapshot: trac...
245
  }
ee18026ac   Mikulas Patocka   dm snapshot: do n...
246
  static void stop_tracking_chunk(struct dm_snapshot *s, struct bio *bio)
cd45daffd   Mikulas Patocka   dm snapshot: trac...
247
  {
ee18026ac   Mikulas Patocka   dm snapshot: do n...
248
  	struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk));
cd45daffd   Mikulas Patocka   dm snapshot: trac...
249
250
251
252
253
  	unsigned long flags;
  
  	spin_lock_irqsave(&s->tracked_chunk_lock, flags);
  	hlist_del(&c->node);
  	spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
cd45daffd   Mikulas Patocka   dm snapshot: trac...
254
  }
a8d41b59f   Mikulas Patocka   dm snapshot: fix ...
255
256
257
  static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk)
  {
  	struct dm_snap_tracked_chunk *c;
a8d41b59f   Mikulas Patocka   dm snapshot: fix ...
258
259
260
  	int found = 0;
  
  	spin_lock_irq(&s->tracked_chunk_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
261
  	hlist_for_each_entry(c,
a8d41b59f   Mikulas Patocka   dm snapshot: fix ...
262
263
264
265
266
267
268
269
270
271
272
  	    &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
273
  /*
615d1eb9c   Mike Snitzer   dm snapshot: crea...
274
275
276
277
278
279
280
281
282
283
   * 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
284
285
286
287
288
289
290
291
292
293
294
295
296
   * 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;
  };
  
  /*
b735fede8   Mikulas Patocka   dm snapshot: susp...
297
298
299
300
301
302
303
304
305
306
   * This structure is allocated for each origin target
   */
  struct dm_origin {
  	struct dm_dev *dev;
  	struct dm_target *ti;
  	unsigned split_boundary;
  	struct list_head hash_list;
  };
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
310
311
312
   * 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;
b735fede8   Mikulas Patocka   dm snapshot: susp...
313
  static struct list_head *_dm_origins;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  static struct rw_semaphore _origins_lock;
73dfd078c   Mikulas Patocka   dm snapshot: trig...
315
316
317
  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
318
319
320
  static int init_origin_hash(void)
  {
  	int i;
6da2ec560   Kees Cook   treewide: kmalloc...
321
322
  	_origins = kmalloc_array(ORIGIN_HASH_SIZE, sizeof(struct list_head),
  				 GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	if (!_origins) {
b735fede8   Mikulas Patocka   dm snapshot: susp...
324
  		DMERR("unable to allocate memory for _origins");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
  		return -ENOMEM;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
  	for (i = 0; i < ORIGIN_HASH_SIZE; i++)
  		INIT_LIST_HEAD(_origins + i);
b735fede8   Mikulas Patocka   dm snapshot: susp...
329

6da2ec560   Kees Cook   treewide: kmalloc...
330
331
332
  	_dm_origins = kmalloc_array(ORIGIN_HASH_SIZE,
  				    sizeof(struct list_head),
  				    GFP_KERNEL);
b735fede8   Mikulas Patocka   dm snapshot: susp...
333
334
335
336
337
338
339
  	if (!_dm_origins) {
  		DMERR("unable to allocate memory for _dm_origins");
  		kfree(_origins);
  		return -ENOMEM;
  	}
  	for (i = 0; i < ORIGIN_HASH_SIZE; i++)
  		INIT_LIST_HEAD(_dm_origins + i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
344
345
346
347
  	init_rwsem(&_origins_lock);
  
  	return 0;
  }
  
  static void exit_origin_hash(void)
  {
  	kfree(_origins);
b735fede8   Mikulas Patocka   dm snapshot: susp...
348
  	kfree(_dm_origins);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
350
  static unsigned origin_hash(struct block_device *bdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  {
  	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);
  }
b735fede8   Mikulas Patocka   dm snapshot: susp...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
  static struct dm_origin *__lookup_dm_origin(struct block_device *origin)
  {
  	struct list_head *ol;
  	struct dm_origin *o;
  
  	ol = &_dm_origins[origin_hash(origin)];
  	list_for_each_entry (o, ol, hash_list)
  		if (bdev_equal(o->dev->bdev, origin))
  			return o;
  
  	return NULL;
  }
  
  static void __insert_dm_origin(struct dm_origin *o)
  {
  	struct list_head *sl = &_dm_origins[origin_hash(o->dev->bdev)];
  	list_add_tail(&o->hash_list, sl);
  }
  
  static void __remove_dm_origin(struct dm_origin *o)
  {
  	list_del(&o->hash_list);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  /*
c1f0c183f   Mike Snitzer   dm snapshot: allo...
397
398
399
400
   * _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...
401
402
   * 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...
403
   *
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
404
   * Possible return values and states of snap_src and snap_dest.
c1f0c183f   Mike Snitzer   dm snapshot: allo...
405
406
407
408
409
410
411
412
   *   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...
413
414
  					struct dm_snapshot **snap_dest,
  					struct dm_snapshot **snap_merge)
c1f0c183f   Mike Snitzer   dm snapshot: allo...
415
416
417
418
419
420
421
422
423
424
425
  {
  	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...
426
427
  		if (dm_target_is_snapshot_merge(s->ti) && snap_merge)
  			*snap_merge = s;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
428
429
  		if (!bdev_equal(s->cow->bdev, snap->cow->bdev))
  			continue;
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
430
  		down_read(&s->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
431
  		active = s->active;
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
432
  		up_read(&s->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
  
  		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...
454
  	struct dm_snapshot *snap_merge = NULL;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
455
456
  
  	/* Does snapshot need exceptions handed over to it? */
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
457
458
  	if ((__find_snapshots_sharing_cow(snap, &snap_src, &snap_dest,
  					  &snap_merge) == 2) ||
c1f0c183f   Mike Snitzer   dm snapshot: allo...
459
460
461
462
463
464
465
466
467
468
469
470
  	    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...
471
472
473
474
475
476
477
478
479
480
481
482
483
  	/*
  	 * 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 ...
484
485
486
487
488
489
  	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...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  	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
505
506
   * 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...
507
508
509
510
   *
   * 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
511
512
513
   */
  static int register_snapshot(struct dm_snapshot *snap)
  {
c1f0c183f   Mike Snitzer   dm snapshot: allo...
514
  	struct origin *o, *new_o = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  	struct block_device *bdev = snap->origin->bdev;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
516
  	int r = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517

60c856c8e   Mikulas Patocka   dm snapshot: fix ...
518
519
520
  	new_o = kmalloc(sizeof(*new_o), GFP_KERNEL);
  	if (!new_o)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  	down_write(&_origins_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522

c1f0c183f   Mike Snitzer   dm snapshot: allo...
523
524
525
526
527
528
529
  	r = __validate_exception_handover(snap);
  	if (r < 0) {
  		kfree(new_o);
  		goto out;
  	}
  
  	o = __lookup_origin(bdev);
60c856c8e   Mikulas Patocka   dm snapshot: fix ...
530
531
532
  	if (o)
  		kfree(new_o);
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  		/* New origin */
60c856c8e   Mikulas Patocka   dm snapshot: fix ...
534
  		o = new_o;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
541
  
  		/* Initialise the struct */
  		INIT_LIST_HEAD(&o->snapshots);
  		o->bdev = bdev;
  
  		__insert_origin(o);
  	}
c1f0c183f   Mike Snitzer   dm snapshot: allo...
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  	__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
561
562
  
  	up_write(&_origins_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
565
566
567
568
569
570
571
572
  }
  
  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...
573
  	if (o && list_empty(&o->snapshots)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
576
577
578
579
580
581
582
  		list_del(&o->hash_list);
  		kfree(o);
  	}
  
  	up_write(&_origins_lock);
  }
  
  /*
   * Implementation of the exception hash tables.
d74f81f8a   Milan Broz   dm snapshot: comb...
583
584
   * 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
585
   */
f79ae415b   Nikos Tsironis   dm snapshot: Make...
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
  static uint32_t exception_hash(struct dm_exception_table *et, chunk_t chunk);
  
  /* Lock to protect access to the completed and pending exception hash tables. */
  struct dm_exception_table_lock {
  	struct hlist_bl_head *complete_slot;
  	struct hlist_bl_head *pending_slot;
  };
  
  static void dm_exception_table_lock_init(struct dm_snapshot *s, chunk_t chunk,
  					 struct dm_exception_table_lock *lock)
  {
  	struct dm_exception_table *complete = &s->complete;
  	struct dm_exception_table *pending = &s->pending;
  
  	lock->complete_slot = &complete->table[exception_hash(complete, chunk)];
  	lock->pending_slot = &pending->table[exception_hash(pending, chunk)];
  }
  
  static void dm_exception_table_lock(struct dm_exception_table_lock *lock)
  {
  	hlist_bl_lock(lock->complete_slot);
  	hlist_bl_lock(lock->pending_slot);
  }
  
  static void dm_exception_table_unlock(struct dm_exception_table_lock *lock)
  {
  	hlist_bl_unlock(lock->pending_slot);
  	hlist_bl_unlock(lock->complete_slot);
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
615
616
  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
617
618
  {
  	unsigned int i;
d74f81f8a   Milan Broz   dm snapshot: comb...
619
  	et->hash_shift = hash_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
  	et->hash_mask = size - 1;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
621
  	et->table = dm_vcalloc(size, sizeof(struct hlist_bl_head));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
624
625
  	if (!et->table)
  		return -ENOMEM;
  
  	for (i = 0; i < size; i++)
f79ae415b   Nikos Tsironis   dm snapshot: Make...
626
  		INIT_HLIST_BL_HEAD(et->table + i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
629
  
  	return 0;
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
630
631
  static void dm_exception_table_exit(struct dm_exception_table *et,
  				    struct kmem_cache *mem)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
633
634
635
  	struct hlist_bl_head *slot;
  	struct dm_exception *ex;
  	struct hlist_bl_node *pos, *n;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
637
638
639
640
  	int i, size;
  
  	size = et->hash_mask + 1;
  	for (i = 0; i < size; i++) {
  		slot = et->table + i;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
641
  		hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
643
644
645
646
  			kmem_cache_free(mem, ex);
  	}
  
  	vfree(et->table);
  }
191437a53   Jon Brassow   dm snapshot: rena...
647
  static uint32_t exception_hash(struct dm_exception_table *et, chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  {
d74f81f8a   Milan Broz   dm snapshot: comb...
649
  	return (chunk >> et->hash_shift) & et->hash_mask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
651
  static void dm_remove_exception(struct dm_exception *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
  {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
653
  	hlist_bl_del(&e->hash_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
657
658
659
  }
  
  /*
   * Return the exception data for a sector, or NULL if not
   * remapped.
   */
3510cb94f   Jon Brassow   dm snapshot: rena...
660
661
  static struct dm_exception *dm_lookup_exception(struct dm_exception_table *et,
  						chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
  {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
663
664
  	struct hlist_bl_head *slot;
  	struct hlist_bl_node *pos;
1d4989c85   Jon Brassow   dm snapshot: rena...
665
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
  
  	slot = &et->table[exception_hash(et, chunk)];
f79ae415b   Nikos Tsironis   dm snapshot: Make...
668
  	hlist_bl_for_each_entry(e, pos, slot, hash_list)
d74f81f8a   Milan Broz   dm snapshot: comb...
669
670
  		if (chunk >= e->old_chunk &&
  		    chunk <= e->old_chunk + dm_consecutive_chunk_count(e))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
674
  			return e;
  
  	return NULL;
  }
119bc5473   Mikulas Patocka   dm snapshot: use ...
675
  static struct dm_exception *alloc_completed_exception(gfp_t gfp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  {
1d4989c85   Jon Brassow   dm snapshot: rena...
677
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678

119bc5473   Mikulas Patocka   dm snapshot: use ...
679
680
  	e = kmem_cache_alloc(exception_cache, gfp);
  	if (!e && gfp == GFP_NOIO)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
684
  		e = kmem_cache_alloc(exception_cache, GFP_ATOMIC);
  
  	return e;
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
685
  static void free_completed_exception(struct dm_exception *e)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
  {
  	kmem_cache_free(exception_cache, e);
  }
92e868122   Mikulas Patocka   dm snapshot: use ...
689
  static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snapshot *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
  {
6f1c819c2   Kent Overstreet   dm: convert to bi...
691
  	struct dm_snap_pending_exception *pe = mempool_alloc(&s->pending_pool,
92e868122   Mikulas Patocka   dm snapshot: use ...
692
  							     GFP_NOIO);
879129d20   Mikulas Patocka   dm snapshot: wait...
693
  	atomic_inc(&s->pending_exceptions_count);
92e868122   Mikulas Patocka   dm snapshot: use ...
694
695
696
  	pe->snap = s;
  
  	return pe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
  }
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
698
  static void free_pending_exception(struct dm_snap_pending_exception *pe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
  {
879129d20   Mikulas Patocka   dm snapshot: wait...
700
  	struct dm_snapshot *s = pe->snap;
6f1c819c2   Kent Overstreet   dm: convert to bi...
701
  	mempool_free(pe, &s->pending_pool);
4e857c58e   Peter Zijlstra   arch: Mass conver...
702
  	smp_mb__before_atomic();
879129d20   Mikulas Patocka   dm snapshot: wait...
703
  	atomic_dec(&s->pending_exceptions_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  }
3510cb94f   Jon Brassow   dm snapshot: rena...
705
706
  static void dm_insert_exception(struct dm_exception_table *eh,
  				struct dm_exception *new_e)
d74f81f8a   Milan Broz   dm snapshot: comb...
707
  {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
708
709
  	struct hlist_bl_head *l;
  	struct hlist_bl_node *pos;
1d4989c85   Jon Brassow   dm snapshot: rena...
710
  	struct dm_exception *e = NULL;
d74f81f8a   Milan Broz   dm snapshot: comb...
711
712
713
714
715
716
717
718
  
  	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 */
f79ae415b   Nikos Tsironis   dm snapshot: Make...
719
  	hlist_bl_for_each_entry(e, pos, l, hash_list) {
d74f81f8a   Milan Broz   dm snapshot: comb...
720
721
722
723
724
725
  		/* 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...
726
  			free_completed_exception(new_e);
d74f81f8a   Milan Broz   dm snapshot: comb...
727
728
729
730
731
732
733
734
735
  			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...
736
  			free_completed_exception(new_e);
d74f81f8a   Milan Broz   dm snapshot: comb...
737
738
  			return;
  		}
f79ae415b   Nikos Tsironis   dm snapshot: Make...
739
  		if (new_e->old_chunk < e->old_chunk)
d74f81f8a   Milan Broz   dm snapshot: comb...
740
741
742
743
  			break;
  	}
  
  out:
f79ae415b   Nikos Tsironis   dm snapshot: Make...
744
745
746
747
748
749
750
751
752
753
754
755
756
  	if (!e) {
  		/*
  		 * Either the table doesn't support consecutive chunks or slot
  		 * l is empty.
  		 */
  		hlist_bl_add_head(&new_e->hash_list, l);
  	} else if (new_e->old_chunk < e->old_chunk) {
  		/* Add before an existing exception */
  		hlist_bl_add_before(&new_e->hash_list, &e->hash_list);
  	} else {
  		/* Add to l's tail: e is the last exception in this slot */
  		hlist_bl_add_behind(&new_e->hash_list, &e->hash_list);
  	}
d74f81f8a   Milan Broz   dm snapshot: comb...
757
  }
a159c1ac5   Jonathan Brassow   dm snapshot: exte...
758
759
760
761
762
  /*
   * 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
763
  {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
764
  	struct dm_exception_table_lock lock;
a159c1ac5   Jonathan Brassow   dm snapshot: exte...
765
  	struct dm_snapshot *s = context;
1d4989c85   Jon Brassow   dm snapshot: rena...
766
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767

119bc5473   Mikulas Patocka   dm snapshot: use ...
768
  	e = alloc_completed_exception(GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
771
772
  	if (!e)
  		return -ENOMEM;
  
  	e->old_chunk = old;
d74f81f8a   Milan Broz   dm snapshot: comb...
773
774
  
  	/* Consecutive_count is implicitly initialised to zero */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
775
  	e->new_chunk = new;
d74f81f8a   Milan Broz   dm snapshot: comb...
776

f79ae415b   Nikos Tsironis   dm snapshot: Make...
777
778
779
780
781
782
783
784
785
  	/*
  	 * Although there is no need to lock access to the exception tables
  	 * here, if we don't then hlist_bl_add_head(), called by
  	 * dm_insert_exception(), will complain about accessing the
  	 * corresponding list without locking it first.
  	 */
  	dm_exception_table_lock_init(s, old, &lock);
  
  	dm_exception_table_lock(&lock);
3510cb94f   Jon Brassow   dm snapshot: rena...
786
  	dm_insert_exception(&s->complete, e);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
787
  	dm_exception_table_unlock(&lock);
d74f81f8a   Milan Broz   dm snapshot: comb...
788

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
  	return 0;
  }
7e201b351   Mikulas Patocka   dm snapshot: abst...
791
792
793
794
  /*
   * Return a minimum chunk size of all snapshots that have the specified origin.
   * Return zero if the origin has no snapshots.
   */
542f90381   Mike Snitzer   dm: support non p...
795
  static uint32_t __minimum_chunk_size(struct origin *o)
7e201b351   Mikulas Patocka   dm snapshot: abst...
796
797
798
799
800
801
802
803
  {
  	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);
542f90381   Mike Snitzer   dm: support non p...
804
  	return (uint32_t) chunk_size;
7e201b351   Mikulas Patocka   dm snapshot: abst...
805
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
806
807
808
809
810
811
812
  /*
   * Hard coded magic.
   */
  static int calc_max_buckets(void)
  {
  	/* use a fixed size of 2MB */
  	unsigned long mem = 2 * 1024 * 1024;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
813
  	mem /= sizeof(struct hlist_bl_head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
815
816
817
818
  
  	return mem;
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
820
   * Allocate room for a suitable hash table.
   */
fee1998e9   Jonathan Brassow   dm snapshot: move...
821
  static int init_hash_tables(struct dm_snapshot *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  {
60e356f38   Mikulas Patocka   dm-snapshot: fix ...
823
  	sector_t hash_size, cow_dev_size, max_buckets;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
826
827
828
  
  	/*
  	 * Calculate based on the size of the original volume or
  	 * the COW volume...
  	 */
fc56f6fbc   Mike Snitzer   dm snapshot: move...
829
  	cow_dev_size = get_dev_size(s->cow->bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
  	max_buckets = calc_max_buckets();
60e356f38   Mikulas Patocka   dm-snapshot: fix ...
831
  	hash_size = cow_dev_size >> s->store->chunk_shift;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
  	hash_size = min(hash_size, max_buckets);
8e87b9b81   Mikulas Patocka   dm snapshot: cope...
833
834
  	if (hash_size < 64)
  		hash_size = 64;
8defd8308   Robert P. J. Day   dm snapshot: use ...
835
  	hash_size = rounddown_pow_of_two(hash_size);
3510cb94f   Jon Brassow   dm snapshot: rena...
836
837
  	if (dm_exception_table_init(&s->complete, hash_size,
  				    DM_CHUNK_CONSECUTIVE_BITS))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
839
840
841
842
843
844
845
846
  		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...
847
848
  	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
849
850
851
852
853
  		return -ENOMEM;
  	}
  
  	return 0;
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
854
855
856
  static void merge_shutdown(struct dm_snapshot *s)
  {
  	clear_bit_unlock(RUNNING_MERGE, &s->state_bits);
4e857c58e   Peter Zijlstra   arch: Mass conver...
857
  	smp_mb__after_atomic();
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
858
859
  	wake_up_bit(&s->state_bits, RUNNING_MERGE);
  }
9fe862548   Mikulas Patocka   dm snapshot: queu...
860
861
862
863
864
865
866
  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 ...
867
868
869
870
871
872
873
  /*
   * 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 ...
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
  	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...
917
918
919
  static void flush_bios(struct bio *bio);
  
  static int remove_single_exception_chunk(struct dm_snapshot *s)
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
920
  {
9fe862548   Mikulas Patocka   dm snapshot: queu...
921
922
923
  	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 ...
924

4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
925
  	down_write(&s->lock);
9fe862548   Mikulas Patocka   dm snapshot: queu...
926
927
928
929
930
931
932
933
934
935
936
937
938
939
  
  	/*
  	 * 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:
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
940
  	up_write(&s->lock);
9fe862548   Mikulas Patocka   dm snapshot: queu...
941
942
  	if (b)
  		flush_bios(b);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
943
944
945
  
  	return r;
  }
73dfd078c   Mikulas Patocka   dm snapshot: trig...
946
947
  static int origin_write_extent(struct dm_snapshot *merging_snap,
  			       sector_t sector, unsigned chunk_size);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
948
949
  static void merge_callback(int read_err, unsigned long write_err,
  			   void *context);
73dfd078c   Mikulas Patocka   dm snapshot: trig...
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
  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 ...
969
970
  static void snapshot_merge_next_chunks(struct dm_snapshot *s)
  {
8a2d52862   Mike Snitzer   dm snapshot: merg...
971
  	int i, linear_chunks;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
972
973
  	chunk_t old_chunk, new_chunk;
  	struct dm_io_region src, dest;
8a2d52862   Mike Snitzer   dm snapshot: merg...
974
  	sector_t io_size;
73dfd078c   Mikulas Patocka   dm snapshot: trig...
975
  	uint64_t previous_count;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
976
977
978
979
980
981
982
983
984
985
986
987
  
  	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...
988
989
990
  	linear_chunks = s->store->type->prepare_merge(s->store, &old_chunk,
  						      &new_chunk);
  	if (linear_chunks <= 0) {
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
991
  		if (linear_chunks < 0) {
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
992
993
  			DMERR("Read error in exception store: "
  			      "shutting down merge");
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
994
  			down_write(&s->lock);
1d1dda8ca   zhengbin   dm snapshot: use ...
995
  			s->merge_failed = true;
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
996
  			up_write(&s->lock);
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
997
  		}
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
998
999
  		goto shut;
  	}
8a2d52862   Mike Snitzer   dm snapshot: merg...
1000
1001
1002
1003
1004
1005
1006
1007
1008
  	/* 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 ...
1009

1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1010
1011
  	dest.bdev = s->origin->bdev;
  	dest.sector = chunk_to_sector(s->store, old_chunk);
8a2d52862   Mike Snitzer   dm snapshot: merg...
1012
  	dest.count = min(io_size, get_dev_size(dest.bdev) - dest.sector);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1013
1014
1015
1016
  
  	src.bdev = s->cow->bdev;
  	src.sector = chunk_to_sector(s->store, new_chunk);
  	src.count = dest.count;
73dfd078c   Mikulas Patocka   dm snapshot: trig...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  	/*
  	 * 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...
1027
  	while (origin_write_extent(s, dest.sector, io_size)) {
73dfd078c   Mikulas Patocka   dm snapshot: trig...
1028
1029
1030
1031
1032
1033
  		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();
  	}
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1034
  	down_write(&s->lock);
9fe862548   Mikulas Patocka   dm snapshot: queu...
1035
  	s->first_merging_chunk = old_chunk;
8a2d52862   Mike Snitzer   dm snapshot: merg...
1036
  	s->num_merging_chunks = linear_chunks;
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1037
  	up_write(&s->lock);
9fe862548   Mikulas Patocka   dm snapshot: queu...
1038

8a2d52862   Mike Snitzer   dm snapshot: merg...
1039
1040
1041
  	/* 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...
1042

1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1043
1044
1045
1046
1047
1048
  	dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, merge_callback, s);
  	return;
  
  shut:
  	merge_shutdown(s);
  }
9fe862548   Mikulas Patocka   dm snapshot: queu...
1049
  static void error_bios(struct bio *bio);
1ac4156de   Akilesh Kailash   dm snapshot: flus...
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
  static int flush_data(struct dm_snapshot *s)
  {
  	struct bio *flush_bio = &s->flush_bio;
  
  	bio_reset(flush_bio);
  	bio_set_dev(flush_bio, s->origin->bdev);
  	flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
  
  	return submit_bio_wait(flush_bio);
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1060
1061
1062
  static void merge_callback(int read_err, unsigned long write_err, void *context)
  {
  	struct dm_snapshot *s = context;
9fe862548   Mikulas Patocka   dm snapshot: queu...
1063
  	struct bio *b = NULL;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1064
1065
1066
1067
1068
1069
1070
1071
  
  	if (read_err || write_err) {
  		if (read_err)
  			DMERR("Read error: shutting down merge.");
  		else
  			DMERR("Write error: shutting down merge.");
  		goto shut;
  	}
1ac4156de   Akilesh Kailash   dm snapshot: flus...
1072
1073
1074
1075
  	if (flush_data(s) < 0) {
  		DMERR("Flush after merge failed: shutting down merge");
  		goto shut;
  	}
9fe862548   Mikulas Patocka   dm snapshot: queu...
1076
1077
  	if (s->store->type->commit_merge(s->store,
  					 s->num_merging_chunks) < 0) {
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1078
1079
1080
  		DMERR("Write error in exception store: shutting down merge");
  		goto shut;
  	}
9fe862548   Mikulas Patocka   dm snapshot: queu...
1081
1082
  	if (remove_single_exception_chunk(s) < 0)
  		goto shut;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1083
1084
1085
1086
1087
  	snapshot_merge_next_chunks(s);
  
  	return;
  
  shut:
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1088
  	down_write(&s->lock);
1d1dda8ca   zhengbin   dm snapshot: use ...
1089
  	s->merge_failed = true;
9fe862548   Mikulas Patocka   dm snapshot: queu...
1090
  	b = __release_queued_bios_after_merge(s);
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1091
  	up_write(&s->lock);
9fe862548   Mikulas Patocka   dm snapshot: queu...
1092
  	error_bios(b);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1093
1094
1095
1096
1097
1098
1099
1100
  	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);
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1101
1102
1103
1104
1105
1106
  /*
   * Stop the merging process and wait until it finishes.
   */
  static void stop_merge(struct dm_snapshot *s)
  {
  	set_bit(SHUTDOWN_MERGE, &s->state_bits);
743162013   NeilBrown   sched: Remove pro...
1107
  	wait_on_bit(&s->state_bits, RUNNING_MERGE, TASK_UNINTERRUPTIBLE);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1108
1109
  	clear_bit(SHUTDOWN_MERGE, &s->state_bits);
  }
2e6023850   Mike Snitzer   dm snapshot: add ...
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
  static int parse_snapshot_features(struct dm_arg_set *as, struct dm_snapshot *s,
  				   struct dm_target *ti)
  {
  	int r;
  	unsigned argc;
  	const char *arg_name;
  
  	static const struct dm_arg _args[] = {
  		{0, 2, "Invalid number of feature arguments"},
  	};
  
  	/*
  	 * No feature arguments supplied.
  	 */
  	if (!as->argc)
  		return 0;
  
  	r = dm_read_arg_group(_args, as, &argc, &ti->error);
  	if (r)
  		return -EINVAL;
  
  	while (argc && !r) {
  		arg_name = dm_shift_arg(as);
  		argc--;
  
  		if (!strcasecmp(arg_name, "discard_zeroes_cow"))
  			s->discard_zeroes_cow = true;
  
  		else if (!strcasecmp(arg_name, "discard_passdown_origin"))
  			s->discard_passdown_origin = true;
  
  		else {
  			ti->error = "Unrecognised feature requested";
  			r = -EINVAL;
  			break;
  		}
  	}
  
  	if (!s->discard_zeroes_cow && s->discard_passdown_origin) {
  		/*
  		 * TODO: really these are disjoint.. but ti->num_discard_bios
  		 * and dm_bio_get_target_bio_nr() require rigid constraints.
  		 */
  		ti->error = "discard_passdown_origin feature depends on discard_zeroes_cow";
  		r = -EINVAL;
  	}
  
  	return r;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159
  /*
2e6023850   Mike Snitzer   dm snapshot: add ...
1160
1161
   * Construct a snapshot mapping:
   * <origin_dev> <COW-dev> <p|po|n> <chunk-size> [<# feature args> [<arg>]*]
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
1163
1164
1165
   */
  static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
  {
  	struct dm_snapshot *s;
2e6023850   Mike Snitzer   dm snapshot: add ...
1166
  	struct dm_arg_set as;
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1167
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1168
  	int r = -EINVAL;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1169
  	char *origin_path, *cow_path;
4df2bf466   DingXiang   dm snapshot: disa...
1170
  	dev_t origin_dev, cow_dev;
55a62eef8   Alasdair G Kergon   dm: rename reques...
1171
  	unsigned args_used, num_flush_bios = 1;
10b8106a7   Mike Snitzer   dm snapshot: supp...
1172
  	fmode_t origin_mode = FMODE_READ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1173

2e6023850   Mike Snitzer   dm snapshot: add ...
1174
1175
  	if (argc < 4) {
  		ti->error = "requires 4 or more arguments";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1176
  		r = -EINVAL;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1177
  		goto bad;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  	}
10b8106a7   Mike Snitzer   dm snapshot: supp...
1179
  	if (dm_target_is_snapshot_merge(ti)) {
55a62eef8   Alasdair G Kergon   dm: rename reques...
1180
  		num_flush_bios = 2;
10b8106a7   Mike Snitzer   dm snapshot: supp...
1181
1182
  		origin_mode = FMODE_WRITE;
  	}
d37753540   Kent Overstreet   dm: Use kzalloc f...
1183
  	s = kzalloc(sizeof(*s), GFP_KERNEL);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1184
  	if (!s) {
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1185
  		ti->error = "Cannot allocate private snapshot structure";
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1186
1187
1188
  		r = -ENOMEM;
  		goto bad;
  	}
2e6023850   Mike Snitzer   dm snapshot: add ...
1189
1190
1191
1192
1193
1194
  	as.argc = argc;
  	as.argv = argv;
  	dm_consume_args(&as, 4);
  	r = parse_snapshot_features(&as, s, ti);
  	if (r)
  		goto bad_features;
c24110450   Mikulas Patocka   dm snapshot: test...
1195
1196
1197
1198
1199
1200
1201
1202
1203
  	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;
  	}
4df2bf466   DingXiang   dm snapshot: disa...
1204
  	origin_dev = s->origin->bdev->bd_dev;
c24110450   Mikulas Patocka   dm snapshot: test...
1205

fc56f6fbc   Mike Snitzer   dm snapshot: move...
1206
1207
1208
  	cow_path = argv[0];
  	argv++;
  	argc--;
4df2bf466   DingXiang   dm snapshot: disa...
1209
1210
1211
1212
1213
1214
  	cow_dev = dm_get_dev_t(cow_path);
  	if (cow_dev && cow_dev == origin_dev) {
  		ti->error = "COW device cannot be the same as origin device";
  		r = -EINVAL;
  		goto bad_cow;
  	}
024d37e95   Milan Broz   dm: fix opening l...
1215
  	r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1216
1217
1218
1219
1220
1221
  	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...
1222
1223
  	if (r) {
  		ti->error = "Couldn't create exception store";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
  		r = -EINVAL;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1225
  		goto bad_store;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
  	}
fee1998e9   Jonathan Brassow   dm snapshot: move...
1227
1228
  	argv += args_used;
  	argc -= args_used;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1229
  	s->ti = ti;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1230
  	s->valid = 1;
76c44f6d8   Mikulas Patocka   dm snapshot: don'...
1231
  	s->snapshot_overflowed = 0;
aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
1232
  	s->active = 0;
879129d20   Mikulas Patocka   dm snapshot: wait...
1233
  	atomic_set(&s->pending_exceptions_count, 0);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1234
  	spin_lock_init(&s->pe_allocation_lock);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1235
1236
  	s->exception_start_sequence = 0;
  	s->exception_complete_sequence = 0;
3db2776d9   David Jeffery   dm snapshot: impr...
1237
  	s->out_of_order_tree = RB_ROOT;
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1238
  	init_rwsem(&s->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1239
  	INIT_LIST_HEAD(&s->list);
ca3a931fd   Alasdair G Kergon   [PATCH] dm snapsh...
1240
  	spin_lock_init(&s->pe_lock);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1241
  	s->state_bits = 0;
1d1dda8ca   zhengbin   dm snapshot: use ...
1242
  	s->merge_failed = false;
9fe862548   Mikulas Patocka   dm snapshot: queu...
1243
1244
1245
  	s->first_merging_chunk = 0;
  	s->num_merging_chunks = 0;
  	bio_list_init(&s->bios_queued_during_merge);
1ac4156de   Akilesh Kailash   dm snapshot: flus...
1246
  	bio_init(&s->flush_bio, NULL, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1247
1248
  
  	/* Allocate hash table for COW data */
fee1998e9   Jonathan Brassow   dm snapshot: move...
1249
  	if (init_hash_tables(s)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250
1251
  		ti->error = "Unable to allocate hash table space";
  		r = -ENOMEM;
fee1998e9   Jonathan Brassow   dm snapshot: move...
1252
  		goto bad_hash_tables;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1253
  	}
b21555786   Mikulas Patocka   dm snapshot: rewo...
1254
  	init_waitqueue_head(&s->in_progress_wait);
721b1d98f   Nikos Tsironis   dm snapshot: Fix ...
1255

df5d2e908   Mikulas Patocka   dm kcopyd: introd...
1256
  	s->kcopyd_client = dm_kcopyd_client_create(&dm_kcopyd_throttle);
fa34ce730   Mikulas Patocka   dm kcopyd: return...
1257
1258
  	if (IS_ERR(s->kcopyd_client)) {
  		r = PTR_ERR(s->kcopyd_client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259
  		ti->error = "Could not create kcopyd client";
fee1998e9   Jonathan Brassow   dm snapshot: move...
1260
  		goto bad_kcopyd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1261
  	}
6f1c819c2   Kent Overstreet   dm: convert to bi...
1262
1263
  	r = mempool_init_slab_pool(&s->pending_pool, MIN_IOS, pending_cache);
  	if (r) {
92e868122   Mikulas Patocka   dm snapshot: use ...
1264
  		ti->error = "Could not allocate mempool for pending exceptions";
fee1998e9   Jonathan Brassow   dm snapshot: move...
1265
  		goto bad_pending_pool;
92e868122   Mikulas Patocka   dm snapshot: use ...
1266
  	}
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1267
1268
1269
1270
  	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...
1271
  	ti->private = s;
55a62eef8   Alasdair G Kergon   dm: rename reques...
1272
  	ti->num_flush_bios = num_flush_bios;
2e6023850   Mike Snitzer   dm snapshot: add ...
1273
1274
  	if (s->discard_zeroes_cow)
  		ti->num_discard_bios = (s->discard_passdown_origin ? 2 : 1);
30187e1d4   Mike Snitzer   dm: rename target...
1275
  	ti->per_io_data_size = sizeof(struct dm_snap_tracked_chunk);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
  
  	/* 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...
1298
1299
  	r = s->store->type->read_metadata(s->store, dm_add_exception,
  					  (void *)s);
0764147b1   Milan Broz   dm snapshot: perm...
1300
  	if (r < 0) {
f9cea4f70   Mark McLoughlin   [PATCH] dm snapsh...
1301
  		ti->error = "Failed to read snapshot metadata";
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1302
  		goto bad_read_metadata;
0764147b1   Milan Broz   dm snapshot: perm...
1303
1304
1305
  	} else if (r > 0) {
  		s->valid = 0;
  		DMWARN("Snapshot is marked invalid.");
f9cea4f70   Mark McLoughlin   [PATCH] dm snapsh...
1306
  	}
aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
1307

3f2412dc8   Mikulas Patocka   dm snapshot: requ...
1308
1309
  	if (!s->store->chunk_size) {
  		ti->error = "Chunk size not set";
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1310
  		goto bad_read_metadata;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1311
  	}
542f90381   Mike Snitzer   dm: support non p...
1312
1313
1314
1315
  
  	r = dm_set_target_max_io_len(ti, s->store->chunk_size);
  	if (r)
  		goto bad_read_metadata;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
1317
  
  	return 0;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1318
1319
  bad_read_metadata:
  	unregister_snapshot(s);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1320
  bad_load_and_register:
6f1c819c2   Kent Overstreet   dm: convert to bi...
1321
  	mempool_exit(&s->pending_pool);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1322
  bad_pending_pool:
eb69aca5d   Heinz Mauelshagen   dm kcopyd: clean ...
1323
  	dm_kcopyd_client_destroy(s->kcopyd_client);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1324
  bad_kcopyd:
3510cb94f   Jon Brassow   dm snapshot: rena...
1325
1326
  	dm_exception_table_exit(&s->pending, pending_cache);
  	dm_exception_table_exit(&s->complete, exception_cache);
fee1998e9   Jonathan Brassow   dm snapshot: move...
1327
  bad_hash_tables:
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1328
  	dm_exception_store_destroy(s->store);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1329
1330
  bad_store:
  	dm_put_device(ti, s->cow);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1331
  bad_cow:
c24110450   Mikulas Patocka   dm snapshot: test...
1332
  	dm_put_device(ti, s->origin);
c24110450   Mikulas Patocka   dm snapshot: test...
1333
  bad_origin:
2e6023850   Mike Snitzer   dm snapshot: add ...
1334
  bad_features:
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1335
  	kfree(s);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1336
  bad:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
  	return r;
  }
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1339
1340
  static void __free_exceptions(struct dm_snapshot *s)
  {
eb69aca5d   Heinz Mauelshagen   dm kcopyd: clean ...
1341
  	dm_kcopyd_client_destroy(s->kcopyd_client);
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1342
  	s->kcopyd_client = NULL;
3510cb94f   Jon Brassow   dm snapshot: rena...
1343
1344
  	dm_exception_table_exit(&s->pending, pending_cache);
  	dm_exception_table_exit(&s->complete, exception_cache);
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1345
  }
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
  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;
b0d3cc011   Mike Snitzer   dm snapshot: add ...
1363
  	snap_dest->store->userspace_supports_overflow = u.store_swap->userspace_supports_overflow;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1364
1365
1366
1367
  	snap_src->store = u.store_swap;
  
  	snap_dest->store->snap = snap_dest;
  	snap_src->store->snap = snap_src;
542f90381   Mike Snitzer   dm: support non p...
1368
  	snap_dest->ti->max_io_len = snap_dest->store->chunk_size;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1369
  	snap_dest->valid = snap_src->valid;
76c44f6d8   Mikulas Patocka   dm snapshot: don'...
1370
  	snap_dest->snapshot_overflowed = snap_src->snapshot_overflowed;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1371
1372
1373
1374
1375
1376
  
  	/*
  	 * Set source invalid to ensure it receives no further I/O.
  	 */
  	snap_src->valid = 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
1378
  static void snapshot_dtr(struct dm_target *ti)
  {
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1379
1380
1381
  #ifdef CONFIG_DM_DEBUG
  	int i;
  #endif
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1382
  	struct dm_snapshot *s = ti->private;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1383
  	struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384

c1f0c183f   Mike Snitzer   dm snapshot: allo...
1385
1386
  	down_read(&_origins_lock);
  	/* Check whether exception handover must be cancelled */
9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
1387
  	(void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1388
  	if (snap_src && snap_dest && (s == snap_src)) {
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1389
  		down_write(&snap_dest->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1390
  		snap_dest->valid = 0;
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1391
  		up_write(&snap_dest->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
1392
1393
1394
  		DMERR("Cancelling snapshot handover.");
  	}
  	up_read(&_origins_lock);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
1395
1396
  	if (dm_target_is_snapshot_merge(ti))
  		stop_merge(s);
138728dc9   Alasdair G Kergon   [PATCH] dm snapsh...
1397
1398
  	/* 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
1399
  	unregister_snapshot(s);
879129d20   Mikulas Patocka   dm snapshot: wait...
1400
  	while (atomic_read(&s->pending_exceptions_count))
90fa1527b   Mikulas Patocka   dm snapshot: chan...
1401
  		msleep(1);
879129d20   Mikulas Patocka   dm snapshot: wait...
1402
  	/*
6f1c819c2   Kent Overstreet   dm: convert to bi...
1403
  	 * Ensure instructions in mempool_exit aren't reordered
879129d20   Mikulas Patocka   dm snapshot: wait...
1404
1405
1406
  	 * before atomic_read.
  	 */
  	smp_mb();
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1407
1408
1409
1410
  #ifdef CONFIG_DM_DEBUG
  	for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
  		BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
  #endif
31c93a0c2   Milan Broz   [PATCH] dm: snaps...
1411
  	__free_exceptions(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412

6f1c819c2   Kent Overstreet   dm: convert to bi...
1413
  	mempool_exit(&s->pending_pool);
92e868122   Mikulas Patocka   dm snapshot: use ...
1414

fee1998e9   Jonathan Brassow   dm snapshot: move...
1415
  	dm_exception_store_destroy(s->store);
138728dc9   Alasdair G Kergon   [PATCH] dm snapsh...
1416

1ac4156de   Akilesh Kailash   dm snapshot: flus...
1417
  	bio_uninit(&s->flush_bio);
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1418
  	dm_put_device(ti, s->cow);
c24110450   Mikulas Patocka   dm snapshot: test...
1419
  	dm_put_device(ti, s->origin);
b21555786   Mikulas Patocka   dm snapshot: rewo...
1420
  	WARN_ON(s->in_progress);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421
1422
  	kfree(s);
  }
a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1423
1424
  static void account_start_copy(struct dm_snapshot *s)
  {
b21555786   Mikulas Patocka   dm snapshot: rewo...
1425
1426
1427
  	spin_lock(&s->in_progress_wait.lock);
  	s->in_progress++;
  	spin_unlock(&s->in_progress_wait.lock);
a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1428
1429
1430
1431
  }
  
  static void account_end_copy(struct dm_snapshot *s)
  {
b21555786   Mikulas Patocka   dm snapshot: rewo...
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
  	spin_lock(&s->in_progress_wait.lock);
  	BUG_ON(!s->in_progress);
  	s->in_progress--;
  	if (likely(s->in_progress <= cow_threshold) &&
  	    unlikely(waitqueue_active(&s->in_progress_wait)))
  		wake_up_locked(&s->in_progress_wait);
  	spin_unlock(&s->in_progress_wait.lock);
  }
  
  static bool wait_for_in_progress(struct dm_snapshot *s, bool unlock_origins)
  {
  	if (unlikely(s->in_progress > cow_threshold)) {
  		spin_lock(&s->in_progress_wait.lock);
  		if (likely(s->in_progress > cow_threshold)) {
  			/*
  			 * NOTE: this throttle doesn't account for whether
  			 * the caller is servicing an IO that will trigger a COW
  			 * so excess throttling may result for chunks not required
  			 * to be COW'd.  But if cow_threshold was reached, extra
  			 * throttling is unlikely to negatively impact performance.
  			 */
  			DECLARE_WAITQUEUE(wait, current);
  			__add_wait_queue(&s->in_progress_wait, &wait);
  			__set_current_state(TASK_UNINTERRUPTIBLE);
  			spin_unlock(&s->in_progress_wait.lock);
  			if (unlock_origins)
  				up_read(&_origins_lock);
  			io_schedule();
  			remove_wait_queue(&s->in_progress_wait, &wait);
  			return false;
  		}
  		spin_unlock(&s->in_progress_wait.lock);
  	}
  	return true;
a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1466
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
  /*
   * 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;
ed00aabd5   Christoph Hellwig   block: rename gen...
1477
  		submit_bio_noacct(bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
1479
1480
  		bio = n;
  	}
  }
b21555786   Mikulas Patocka   dm snapshot: rewo...
1481
  static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit);
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
  
  /*
   * 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;
b21555786   Mikulas Patocka   dm snapshot: rewo...
1494
  		r = do_origin(s->origin, bio, false);
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1495
  		if (r == DM_MAPIO_REMAPPED)
ed00aabd5   Christoph Hellwig   block: rename gen...
1496
  			submit_bio_noacct(bio);
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1497
1498
1499
  		bio = n;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
  /*
   * 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...
1510
  		bio_io_error(bio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1511
1512
1513
  		bio = n;
  	}
  }
695368ac3   Alasdair G Kergon   [PATCH] dm snapsh...
1514
  static void __invalidate_snapshot(struct dm_snapshot *s, int err)
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1515
1516
1517
1518
1519
1520
1521
1522
  {
  	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...
1523
1524
  	if (s->store->type->drop_snapshot)
  		s->store->type->drop_snapshot(s->store);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1525
1526
  
  	s->valid = 0;
fc56f6fbc   Mike Snitzer   dm snapshot: move...
1527
  	dm_table_event(s->ti->table);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1528
  }
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1529
1530
1531
1532
1533
1534
  static void invalidate_snapshot(struct dm_snapshot *s, int err)
  {
  	down_write(&s->lock);
  	__invalidate_snapshot(s, err);
  	up_write(&s->lock);
  }
385277bfb   Mikulas Patocka   dm snapshot: fix ...
1535
  static void pending_complete(void *context, int success)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1536
  {
385277bfb   Mikulas Patocka   dm snapshot: fix ...
1537
  	struct dm_snap_pending_exception *pe = context;
1d4989c85   Jon Brassow   dm snapshot: rena...
1538
  	struct dm_exception *e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1539
  	struct dm_snapshot *s = pe->snap;
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1540
1541
  	struct bio *origin_bios = NULL;
  	struct bio *snapshot_bios = NULL;
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1542
  	struct bio *full_bio = NULL;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1543
  	struct dm_exception_table_lock lock;
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1544
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545

f79ae415b   Nikos Tsironis   dm snapshot: Make...
1546
  	dm_exception_table_lock_init(s, pe->e.old_chunk, &lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1547
1548
  	if (!success) {
  		/* Read/write error - snapshot is unusable */
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1549
  		invalidate_snapshot(s, -EIO);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1550
  		error = 1;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1551
1552
  
  		dm_exception_table_lock(&lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1553
1554
  		goto out;
  	}
119bc5473   Mikulas Patocka   dm snapshot: use ...
1555
  	e = alloc_completed_exception(GFP_NOIO);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1556
  	if (!e) {
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1557
  		invalidate_snapshot(s, -ENOMEM);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1558
  		error = 1;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1559
1560
  
  		dm_exception_table_lock(&lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1561
1562
1563
  		goto out;
  	}
  	*e = pe->e;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1564

3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1565
  	down_read(&s->lock);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1566
  	dm_exception_table_lock(&lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1567
  	if (!s->valid) {
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1568
  		up_read(&s->lock);
3510cb94f   Jon Brassow   dm snapshot: rena...
1569
  		free_completed_exception(e);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1570
  		error = 1;
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1571

76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1572
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1573
  	}
a8d41b59f   Mikulas Patocka   dm snapshot: fix ...
1574
  	/*
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1575
1576
1577
1578
1579
  	 * Add a proper exception. After inserting the completed exception all
  	 * subsequent snapshot reads to this chunk will be redirected to the
  	 * COW device.  This ensures that we do not starve. Moreover, as long
  	 * as the pending exception exists, neither origin writes nor snapshot
  	 * merging can overwrite the chunk in origin.
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1580
  	 */
3510cb94f   Jon Brassow   dm snapshot: rena...
1581
  	dm_insert_exception(&s->complete, e);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1582
  	up_read(&s->lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1583

65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1584
1585
  	/* Wait for conflicting reads to drain */
  	if (__chunk_is_tracked(s, pe->e.old_chunk)) {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1586
  		dm_exception_table_unlock(&lock);
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1587
  		__check_for_conflicting_io(s, pe->e.old_chunk);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1588
  		dm_exception_table_lock(&lock);
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1589
  	}
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1590
  out:
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1591
  	/* Remove the in-flight exception from the list */
3510cb94f   Jon Brassow   dm snapshot: rena...
1592
  	dm_remove_exception(&pe->e);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1593
1594
  
  	dm_exception_table_unlock(&lock);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1595
  	snapshot_bios = bio_list_get(&pe->snapshot_bios);
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1596
  	origin_bios = bio_list_get(&pe->origin_bios);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1597
  	full_bio = pe->full_bio;
fe3265b18   Mikulas Patocka   dm: don't save an...
1598
  	if (full_bio)
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1599
  		full_bio->bi_end_io = pe->full_bio_end_io;
73dfd078c   Mikulas Patocka   dm snapshot: trig...
1600
  	increment_pending_exceptions_done_count();
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1601
  	/* Submit any pending write bios */
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1602
1603
1604
  	if (error) {
  		if (full_bio)
  			bio_io_error(full_bio);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1605
  		error_bios(snapshot_bios);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1606
1607
  	} else {
  		if (full_bio)
4246a0b63   Christoph Hellwig   block: add a bi_e...
1608
  			bio_endio(full_bio);
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1609
  		flush_bios(snapshot_bios);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1610
  	}
9d493fa8c   Alasdair G Kergon   [PATCH] dm snapsh...
1611

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
1612
  	retry_origin_bios(s, origin_bios);
22aa66a3e   Mikulas Patocka   dm snapshot: fix ...
1613
1614
  
  	free_pending_exception(pe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1615
  }
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1616
1617
1618
  static void complete_exception(struct dm_snap_pending_exception *pe)
  {
  	struct dm_snapshot *s = pe->snap;
385277bfb   Mikulas Patocka   dm snapshot: fix ...
1619
1620
1621
  	/* Update the metadata if we are persistent */
  	s->store->type->commit_exception(s->store, &pe->e, !pe->copy_error,
  					 pending_complete, pe);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1622
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1623
1624
1625
1626
  /*
   * 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...
1627
  static void copy_callback(int read_err, unsigned long write_err, void *context)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1628
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1629
  	struct dm_snap_pending_exception *pe = context;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1630
  	struct dm_snapshot *s = pe->snap;
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1631
  	pe->copy_error = read_err || write_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632

230c83afd   Mikulas Patocka   dm snapshot: avoi...
1633
  	if (pe->exception_sequence == s->exception_complete_sequence) {
3db2776d9   David Jeffery   dm snapshot: impr...
1634
  		struct rb_node *next;
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1635
1636
  		s->exception_complete_sequence++;
  		complete_exception(pe);
3db2776d9   David Jeffery   dm snapshot: impr...
1637
1638
1639
1640
  		next = rb_first(&s->out_of_order_tree);
  		while (next) {
  			pe = rb_entry(next, struct dm_snap_pending_exception,
  					out_of_order_node);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1641
1642
  			if (pe->exception_sequence != s->exception_complete_sequence)
  				break;
3db2776d9   David Jeffery   dm snapshot: impr...
1643
  			next = rb_next(next);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1644
  			s->exception_complete_sequence++;
3db2776d9   David Jeffery   dm snapshot: impr...
1645
  			rb_erase(&pe->out_of_order_node, &s->out_of_order_tree);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1646
  			complete_exception(pe);
3db2776d9   David Jeffery   dm snapshot: impr...
1647
  			cond_resched();
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1648
1649
  		}
  	} else {
3db2776d9   David Jeffery   dm snapshot: impr...
1650
1651
  		struct rb_node *parent = NULL;
  		struct rb_node **p = &s->out_of_order_tree.rb_node;
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1652
  		struct dm_snap_pending_exception *pe2;
3db2776d9   David Jeffery   dm snapshot: impr...
1653
1654
1655
1656
1657
1658
1659
1660
1661
  		while (*p) {
  			pe2 = rb_entry(*p, struct dm_snap_pending_exception, out_of_order_node);
  			parent = *p;
  
  			BUG_ON(pe->exception_sequence == pe2->exception_sequence);
  			if (pe->exception_sequence < pe2->exception_sequence)
  				p = &((*p)->rb_left);
  			else
  				p = &((*p)->rb_right);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1662
  		}
3db2776d9   David Jeffery   dm snapshot: impr...
1663
1664
1665
  
  		rb_link_node(&pe->out_of_order_node, parent, p);
  		rb_insert_color(&pe->out_of_order_node, &s->out_of_order_tree);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1666
  	}
a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1667
  	account_end_copy(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668
1669
1670
1671
1672
  }
  
  /*
   * Dispatches the copy operation to kcopyd.
   */
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1673
  static void start_copy(struct dm_snap_pending_exception *pe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
1675
  {
  	struct dm_snapshot *s = pe->snap;
22a1ceb1e   Heinz Mauelshagen   dm io: clean inte...
1676
  	struct dm_io_region src, dest;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1677
1678
1679
1680
1681
1682
  	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...
1683
  	src.sector = chunk_to_sector(s->store, pe->e.old_chunk);
df96eee67   Mikulas Patocka   dm snapshot: use ...
1684
  	src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1685

fc56f6fbc   Mike Snitzer   dm snapshot: move...
1686
  	dest.bdev = s->cow->bdev;
71fab00a6   Jonathan Brassow   dm snapshot: remo...
1687
  	dest.sector = chunk_to_sector(s->store, pe->e.new_chunk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
1689
1690
  	dest.count = src.count;
  
  	/* Hand over to kcopyd */
a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1691
  	account_start_copy(s);
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1692
  	dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
  }
4246a0b63   Christoph Hellwig   block: add a bi_e...
1694
  static void full_bio_end_io(struct bio *bio)
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1695
1696
  {
  	void *callback_data = bio->bi_private;
4e4cbee93   Christoph Hellwig   block: switch bio...
1697
  	dm_kcopyd_do_callback(callback_data, 0, bio->bi_status ? 1 : 0);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
  }
  
  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;
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1708

a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1709
  	account_start_copy(s);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1710
1711
1712
1713
1714
  	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;
ed00aabd5   Christoph Hellwig   block: rename gen...
1715
  	submit_bio_noacct(bio);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1716
  }
2913808eb   Mikulas Patocka   dm snapshot: refa...
1717
1718
1719
  static struct dm_snap_pending_exception *
  __lookup_pending_exception(struct dm_snapshot *s, chunk_t chunk)
  {
3510cb94f   Jon Brassow   dm snapshot: rena...
1720
  	struct dm_exception *e = dm_lookup_exception(&s->pending, chunk);
2913808eb   Mikulas Patocka   dm snapshot: refa...
1721
1722
1723
1724
1725
1726
  
  	if (!e)
  		return NULL;
  
  	return container_of(e, struct dm_snap_pending_exception, e);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1727
  /*
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1728
   * Inserts a pending exception into the pending table.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1729
   *
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1730
1731
   * NOTE: a write lock must be held on the chunk's pending exception table slot
   * before calling this.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
   */
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1733
  static struct dm_snap_pending_exception *
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1734
1735
  __insert_pending_exception(struct dm_snapshot *s,
  			   struct dm_snap_pending_exception *pe, chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
  {
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1737
1738
1739
  	pe->e.old_chunk = chunk;
  	bio_list_init(&pe->origin_bios);
  	bio_list_init(&pe->snapshot_bios);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1740
  	pe->started = 0;
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1741
  	pe->full_bio = NULL;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1742

3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1743
  	spin_lock(&s->pe_allocation_lock);
493df71c6   Jonathan Brassow   dm exception stor...
1744
  	if (s->store->type->prepare_exception(s->store, &pe->e)) {
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1745
  		spin_unlock(&s->pe_allocation_lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1746
1747
1748
  		free_pending_exception(pe);
  		return NULL;
  	}
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1749
  	pe->exception_sequence = s->exception_start_sequence++;
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1750
  	spin_unlock(&s->pe_allocation_lock);
230c83afd   Mikulas Patocka   dm snapshot: avoi...
1751

3510cb94f   Jon Brassow   dm snapshot: rena...
1752
  	dm_insert_exception(&s->pending, &pe->e);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1753

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1754
1755
  	return pe;
  }
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1756
1757
1758
1759
1760
  /*
   * 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.
   *
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1761
1762
   * NOTE: a write lock must be held on the chunk's pending exception table slot
   * before calling this.
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
   */
  static struct dm_snap_pending_exception *
  __find_pending_exception(struct dm_snapshot *s,
  			 struct dm_snap_pending_exception *pe, chunk_t chunk)
  {
  	struct dm_snap_pending_exception *pe2;
  
  	pe2 = __lookup_pending_exception(s, chunk);
  	if (pe2) {
  		free_pending_exception(pe);
  		return pe2;
  	}
  
  	return __insert_pending_exception(s, pe, chunk);
  }
1d4989c85   Jon Brassow   dm snapshot: rena...
1778
  static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
d74f81f8a   Milan Broz   dm snapshot: comb...
1779
  			    struct bio *bio, chunk_t chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1780
  {
74d46992e   Christoph Hellwig   block: replace bi...
1781
  	bio_set_dev(bio, s->cow->bdev);
4f024f379   Kent Overstreet   block: Abstract o...
1782
1783
1784
1785
  	bio->bi_iter.bi_sector =
  		chunk_to_sector(s->store, dm_chunk_number(e->new_chunk) +
  				(chunk - e->old_chunk)) +
  		(bio->bi_iter.bi_sector & s->store->chunk_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1786
  }
2e6023850   Mike Snitzer   dm snapshot: add ...
1787
1788
1789
1790
  static void zero_callback(int read_err, unsigned long write_err, void *context)
  {
  	struct bio *bio = context;
  	struct dm_snapshot *s = bio->bi_private;
a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1791
  	account_end_copy(s);
2e6023850   Mike Snitzer   dm snapshot: add ...
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
  	bio->bi_status = write_err ? BLK_STS_IOERR : 0;
  	bio_endio(bio);
  }
  
  static void zero_exception(struct dm_snapshot *s, struct dm_exception *e,
  			   struct bio *bio, chunk_t chunk)
  {
  	struct dm_io_region dest;
  
  	dest.bdev = s->cow->bdev;
  	dest.sector = bio->bi_iter.bi_sector;
  	dest.count = s->store->chunk_size;
a2f83e8b0   Mikulas Patocka   dm snapshot: intr...
1804
  	account_start_copy(s);
2e6023850   Mike Snitzer   dm snapshot: add ...
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
  	WARN_ON_ONCE(bio->bi_private);
  	bio->bi_private = s;
  	dm_kcopyd_zero(s->kcopyd_client, 1, &dest, 0, zero_callback, bio);
  }
  
  static bool io_overlaps_chunk(struct dm_snapshot *s, struct bio *bio)
  {
  	return bio->bi_iter.bi_size ==
  		(s->store->chunk_size << SECTOR_SHIFT);
  }
7de3ee57d   Mikulas Patocka   dm: remove map_info
1815
  static int snapshot_map(struct dm_target *ti, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816
  {
1d4989c85   Jon Brassow   dm snapshot: rena...
1817
  	struct dm_exception *e;
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1818
  	struct dm_snapshot *s = ti->private;
d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
1819
  	int r = DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820
  	chunk_t chunk;
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
1821
  	struct dm_snap_pending_exception *pe = NULL;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1822
  	struct dm_exception_table_lock lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1823

ee18026ac   Mikulas Patocka   dm snapshot: do n...
1824
  	init_tracked_chunk(bio);
1eff9d322   Jens Axboe   block: rename bio...
1825
  	if (bio->bi_opf & REQ_PREFLUSH) {
74d46992e   Christoph Hellwig   block: replace bi...
1826
  		bio_set_dev(bio, s->cow->bdev);
494b3ee7d   Mikulas Patocka   dm snapshot: supp...
1827
1828
  		return DM_MAPIO_REMAPPED;
  	}
4f024f379   Kent Overstreet   block: Abstract o...
1829
  	chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1830
  	dm_exception_table_lock_init(s, chunk, &lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1831
1832
  
  	/* Full snapshots are not usable */
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1833
  	/* To get here the table must be live so s->active is always set. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1834
  	if (!s->valid)
846785e6a   Christoph Hellwig   dm: don't return ...
1835
  		return DM_MAPIO_KILL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836

b21555786   Mikulas Patocka   dm snapshot: rewo...
1837
1838
1839
1840
  	if (bio_data_dir(bio) == WRITE) {
  		while (unlikely(!wait_for_in_progress(s, false)))
  			; /* wait_for_in_progress() has slept */
  	}
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1841
  	down_read(&s->lock);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1842
  	dm_exception_table_lock(&lock);
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1843

70246286e   Christoph Hellwig   block: get rid of...
1844
1845
  	if (!s->valid || (unlikely(s->snapshot_overflowed) &&
  	    bio_data_dir(bio) == WRITE)) {
846785e6a   Christoph Hellwig   dm: don't return ...
1846
  		r = DM_MAPIO_KILL;
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1847
1848
  		goto out_unlock;
  	}
2e6023850   Mike Snitzer   dm snapshot: add ...
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
  	if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) {
  		if (s->discard_passdown_origin && dm_bio_get_target_bio_nr(bio)) {
  			/*
  			 * passdown discard to origin (without triggering
  			 * snapshot exceptions via do_origin; doing so would
  			 * defeat the goal of freeing space in origin that is
  			 * implied by the "discard_passdown_origin" feature)
  			 */
  			bio_set_dev(bio, s->origin->bdev);
  			track_chunk(s, bio, chunk);
  			goto out_unlock;
  		}
  		/* discard to snapshot (target_bio_nr == 0) zeroes exceptions */
  	}
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1863
  	/* If the block is already remapped - use that, else remap it */
3510cb94f   Jon Brassow   dm snapshot: rena...
1864
  	e = dm_lookup_exception(&s->complete, chunk);
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1865
  	if (e) {
d74f81f8a   Milan Broz   dm snapshot: comb...
1866
  		remap_exception(s, e, bio, chunk);
2e6023850   Mike Snitzer   dm snapshot: add ...
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
  		if (unlikely(bio_op(bio) == REQ_OP_DISCARD) &&
  		    io_overlaps_chunk(s, bio)) {
  			dm_exception_table_unlock(&lock);
  			up_read(&s->lock);
  			zero_exception(s, e, bio, chunk);
  			r = DM_MAPIO_SUBMITTED; /* discard is not issued */
  			goto out;
  		}
  		goto out_unlock;
  	}
  
  	if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) {
  		/*
  		 * If no exception exists, complete discard immediately
  		 * otherwise it'll trigger copy-out.
  		 */
  		bio_endio(bio);
  		r = DM_MAPIO_SUBMITTED;
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1885
1886
  		goto out_unlock;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1887
1888
1889
1890
1891
  	/*
  	 * Write to snapshot - higher level takes care of RW/RO
  	 * flags so we should only get this if we are
  	 * writeable.
  	 */
70246286e   Christoph Hellwig   block: get rid of...
1892
  	if (bio_data_dir(bio) == WRITE) {
2913808eb   Mikulas Patocka   dm snapshot: refa...
1893
  		pe = __lookup_pending_exception(s, chunk);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1894
  		if (!pe) {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1895
  			dm_exception_table_unlock(&lock);
c66213921   Mikulas Patocka   dm snapshot: avoi...
1896
  			pe = alloc_pending_exception(s);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1897
  			dm_exception_table_lock(&lock);
c66213921   Mikulas Patocka   dm snapshot: avoi...
1898

3510cb94f   Jon Brassow   dm snapshot: rena...
1899
  			e = dm_lookup_exception(&s->complete, chunk);
35bf659b0   Mikulas Patocka   dm snapshot: avoi...
1900
1901
1902
1903
1904
  			if (e) {
  				free_pending_exception(pe);
  				remap_exception(s, e, bio, chunk);
  				goto out_unlock;
  			}
c66213921   Mikulas Patocka   dm snapshot: avoi...
1905
  			pe = __find_pending_exception(s, pe, chunk);
2913808eb   Mikulas Patocka   dm snapshot: refa...
1906
  			if (!pe) {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1907
  				dm_exception_table_unlock(&lock);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1908
1909
1910
  				up_read(&s->lock);
  
  				down_write(&s->lock);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1911

b0d3cc011   Mike Snitzer   dm snapshot: add ...
1912
  				if (s->store->userspace_supports_overflow) {
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1913
1914
1915
1916
  					if (s->valid && !s->snapshot_overflowed) {
  						s->snapshot_overflowed = 1;
  						DMERR("Snapshot overflowed: Unable to allocate exception.");
  					}
b0d3cc011   Mike Snitzer   dm snapshot: add ...
1917
1918
  				} else
  					__invalidate_snapshot(s, -ENOMEM);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1919
  				up_write(&s->lock);
846785e6a   Christoph Hellwig   dm: don't return ...
1920
  				r = DM_MAPIO_KILL;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1921
  				goto out;
2913808eb   Mikulas Patocka   dm snapshot: refa...
1922
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
  		}
d74f81f8a   Milan Broz   dm snapshot: comb...
1924
  		remap_exception(s, &pe->e, bio, chunk);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1925

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

2e6023850   Mike Snitzer   dm snapshot: add ...
1928
  		if (!pe->started && io_overlaps_chunk(s, bio)) {
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1929
  			pe->started = 1;
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1930

f79ae415b   Nikos Tsironis   dm snapshot: Make...
1931
  			dm_exception_table_unlock(&lock);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1932
  			up_read(&s->lock);
a6e50b409   Mikulas Patocka   dm snapshot: skip...
1933
1934
1935
1936
1937
  			start_full_bio(pe, bio);
  			goto out;
  		}
  
  		bio_list_add(&pe->snapshot_bios, bio);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1938
  		if (!pe->started) {
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1939
  			/* this is protected by the exception table lock */
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1940
  			pe->started = 1;
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1941

f79ae415b   Nikos Tsironis   dm snapshot: Make...
1942
  			dm_exception_table_unlock(&lock);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1943
  			up_read(&s->lock);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
1944
  			start_copy(pe);
ba40a2aa6   Alasdair G Kergon   [PATCH] dm snapsh...
1945
1946
  			goto out;
  		}
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1947
  	} else {
74d46992e   Christoph Hellwig   block: replace bi...
1948
  		bio_set_dev(bio, s->origin->bdev);
ee18026ac   Mikulas Patocka   dm snapshot: do n...
1949
  		track_chunk(s, bio, chunk);
cd45daffd   Mikulas Patocka   dm snapshot: trac...
1950
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1951

a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1952
  out_unlock:
f79ae415b   Nikos Tsironis   dm snapshot: Make...
1953
  	dm_exception_table_unlock(&lock);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
1954
  	up_read(&s->lock);
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
1955
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956
1957
  	return r;
  }
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1958
1959
1960
1961
1962
1963
1964
1965
1966
  /*
   * 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...
1967
1968
   * 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...
1969
   */
7de3ee57d   Mikulas Patocka   dm: remove map_info
1970
  static int snapshot_merge_map(struct dm_target *ti, struct bio *bio)
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1971
1972
1973
1974
1975
  {
  	struct dm_exception *e;
  	struct dm_snapshot *s = ti->private;
  	int r = DM_MAPIO_REMAPPED;
  	chunk_t chunk;
ee18026ac   Mikulas Patocka   dm snapshot: do n...
1976
  	init_tracked_chunk(bio);
1eff9d322   Jens Axboe   block: rename bio...
1977
  	if (bio->bi_opf & REQ_PREFLUSH) {
55a62eef8   Alasdair G Kergon   dm: rename reques...
1978
  		if (!dm_bio_get_target_bio_nr(bio))
74d46992e   Christoph Hellwig   block: replace bi...
1979
  			bio_set_dev(bio, s->origin->bdev);
10b8106a7   Mike Snitzer   dm snapshot: supp...
1980
  		else
74d46992e   Christoph Hellwig   block: replace bi...
1981
  			bio_set_dev(bio, s->cow->bdev);
10b8106a7   Mike Snitzer   dm snapshot: supp...
1982
1983
  		return DM_MAPIO_REMAPPED;
  	}
3ee25485b   Mike Snitzer   dm snapshot: fix ...
1984
1985
1986
1987
1988
  	if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) {
  		/* Once merging, discards no longer effect change */
  		bio_endio(bio);
  		return DM_MAPIO_SUBMITTED;
  	}
4f024f379   Kent Overstreet   block: Abstract o...
1989
  	chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1990

4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
1991
  	down_write(&s->lock);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1992

d2fdb776e   Mikulas Patocka   dm snapshot: use ...
1993
1994
1995
  	/* Full merging snapshots are redirected to the origin */
  	if (!s->valid)
  		goto redirect_to_origin;
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
1996
1997
1998
1999
  
  	/* If the block is already remapped - use that */
  	e = dm_lookup_exception(&s->complete, chunk);
  	if (e) {
9fe862548   Mikulas Patocka   dm snapshot: queu...
2000
  		/* Queue writes overlapping with chunks being merged */
70246286e   Christoph Hellwig   block: get rid of...
2001
  		if (bio_data_dir(bio) == WRITE &&
9fe862548   Mikulas Patocka   dm snapshot: queu...
2002
2003
2004
  		    chunk >= s->first_merging_chunk &&
  		    chunk < (s->first_merging_chunk +
  			     s->num_merging_chunks)) {
74d46992e   Christoph Hellwig   block: replace bi...
2005
  			bio_set_dev(bio, s->origin->bdev);
9fe862548   Mikulas Patocka   dm snapshot: queu...
2006
2007
2008
2009
  			bio_list_add(&s->bios_queued_during_merge, bio);
  			r = DM_MAPIO_SUBMITTED;
  			goto out_unlock;
  		}
17aa03326   Mikulas Patocka   dm snapshot: dela...
2010

3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2011
  		remap_exception(s, e, bio, chunk);
17aa03326   Mikulas Patocka   dm snapshot: dela...
2012

70246286e   Christoph Hellwig   block: get rid of...
2013
  		if (bio_data_dir(bio) == WRITE)
ee18026ac   Mikulas Patocka   dm snapshot: do n...
2014
  			track_chunk(s, bio, chunk);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2015
2016
  		goto out_unlock;
  	}
d2fdb776e   Mikulas Patocka   dm snapshot: use ...
2017
  redirect_to_origin:
74d46992e   Christoph Hellwig   block: replace bi...
2018
  	bio_set_dev(bio, s->origin->bdev);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2019

70246286e   Christoph Hellwig   block: get rid of...
2020
  	if (bio_data_dir(bio) == WRITE) {
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2021
  		up_write(&s->lock);
b21555786   Mikulas Patocka   dm snapshot: rewo...
2022
  		return do_origin(s->origin, bio, false);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2023
2024
2025
  	}
  
  out_unlock:
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2026
  	up_write(&s->lock);
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2027
2028
2029
  
  	return r;
  }
4e4cbee93   Christoph Hellwig   block: switch bio...
2030
2031
  static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
  		blk_status_t *error)
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2032
2033
  {
  	struct dm_snapshot *s = ti->private;
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2034

ee18026ac   Mikulas Patocka   dm snapshot: do n...
2035
2036
  	if (is_bio_tracked(bio))
  		stop_tracking_chunk(s, bio);
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2037

1be569098   Christoph Hellwig   dm: change ->end_...
2038
  	return DM_ENDIO_DONE;
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2039
  }
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2040
2041
2042
2043
2044
2045
  static void snapshot_merge_presuspend(struct dm_target *ti)
  {
  	struct dm_snapshot *s = ti->private;
  
  	stop_merge(s);
  }
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2046
2047
2048
2049
2050
2051
2052
  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...
2053
  	(void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2054
  	if (snap_src && snap_dest) {
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2055
  		down_read(&snap_src->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2056
2057
2058
2059
  		if (s == snap_src) {
  			DMERR("Unable to resume snapshot source until "
  			      "handover completes.");
  			r = -EINVAL;
b83b2f295   Mike Snitzer   dm snapshot: avoi...
2060
  		} else if (!dm_suspended(snap_src->ti)) {
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2061
2062
2063
2064
  			DMERR("Unable to perform snapshot handover until "
  			      "source is suspended.");
  			r = -EINVAL;
  		}
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2065
  		up_read(&snap_src->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2066
2067
2068
2069
2070
  	}
  	up_read(&_origins_lock);
  
  	return r;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2071
2072
  static void snapshot_resume(struct dm_target *ti)
  {
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
2073
  	struct dm_snapshot *s = ti->private;
09ee96b21   Mikulas Patocka   dm snapshot: susp...
2074
  	struct dm_snapshot *snap_src = NULL, *snap_dest = NULL, *snap_merging = NULL;
b735fede8   Mikulas Patocka   dm snapshot: susp...
2075
2076
  	struct dm_origin *o;
  	struct mapped_device *origin_md = NULL;
09ee96b21   Mikulas Patocka   dm snapshot: susp...
2077
  	bool must_restart_merging = false;
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2078
2079
  
  	down_read(&_origins_lock);
b735fede8   Mikulas Patocka   dm snapshot: susp...
2080
2081
2082
2083
  
  	o = __lookup_dm_origin(s->origin->bdev);
  	if (o)
  		origin_md = dm_table_get_md(o->ti->table);
09ee96b21   Mikulas Patocka   dm snapshot: susp...
2084
2085
2086
2087
2088
  	if (!origin_md) {
  		(void) __find_snapshots_sharing_cow(s, NULL, NULL, &snap_merging);
  		if (snap_merging)
  			origin_md = dm_table_get_md(snap_merging->ti->table);
  	}
b735fede8   Mikulas Patocka   dm snapshot: susp...
2089
2090
  	if (origin_md == dm_table_get_md(ti->table))
  		origin_md = NULL;
09ee96b21   Mikulas Patocka   dm snapshot: susp...
2091
2092
2093
2094
  	if (origin_md) {
  		if (dm_hold(origin_md))
  			origin_md = NULL;
  	}
b735fede8   Mikulas Patocka   dm snapshot: susp...
2095

09ee96b21   Mikulas Patocka   dm snapshot: susp...
2096
2097
2098
  	up_read(&_origins_lock);
  
  	if (origin_md) {
b735fede8   Mikulas Patocka   dm snapshot: susp...
2099
  		dm_internal_suspend_fast(origin_md);
09ee96b21   Mikulas Patocka   dm snapshot: susp...
2100
2101
2102
2103
2104
2105
2106
  		if (snap_merging && test_bit(RUNNING_MERGE, &snap_merging->state_bits)) {
  			must_restart_merging = true;
  			stop_merge(snap_merging);
  		}
  	}
  
  	down_read(&_origins_lock);
b735fede8   Mikulas Patocka   dm snapshot: susp...
2107

9d3b15c4c   Mikulas Patocka   dm snapshot: perm...
2108
  	(void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2109
  	if (snap_src && snap_dest) {
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2110
2111
  		down_write(&snap_src->lock);
  		down_write_nested(&snap_dest->lock, SINGLE_DEPTH_NESTING);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2112
  		__handover_exceptions(snap_src, snap_dest);
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2113
2114
  		up_write(&snap_dest->lock);
  		up_write(&snap_src->lock);
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2115
  	}
b735fede8   Mikulas Patocka   dm snapshot: susp...
2116

c1f0c183f   Mike Snitzer   dm snapshot: allo...
2117
  	up_read(&_origins_lock);
09ee96b21   Mikulas Patocka   dm snapshot: susp...
2118
2119
2120
2121
2122
2123
  	if (origin_md) {
  		if (must_restart_merging)
  			start_merge(snap_merging);
  		dm_internal_resume_fast(origin_md);
  		dm_put(origin_md);
  	}
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2124
2125
  	/* Now we have correct chunk size, reregister */
  	reregister_snapshot(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2126

4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2127
  	down_write(&s->lock);
aa14edeb9   Alasdair G Kergon   [PATCH] device-ma...
2128
  	s->active = 1;
4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2129
  	up_write(&s->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2130
  }
542f90381   Mike Snitzer   dm: support non p...
2131
  static uint32_t get_origin_minimum_chunksize(struct block_device *bdev)
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2132
  {
542f90381   Mike Snitzer   dm: support non p...
2133
  	uint32_t min_chunksize;
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
  
  	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);
  
  	/*
542f90381   Mike Snitzer   dm: support non p...
2152
  	 * snapshot-merge acts as an origin, so set ti->max_io_len
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2153
  	 */
542f90381   Mike Snitzer   dm: support non p...
2154
  	ti->max_io_len = get_origin_minimum_chunksize(s->origin->bdev);
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2155
2156
2157
  
  	start_merge(s);
  }
fd7c092e7   Mikulas Patocka   dm: fix truncated...
2158
2159
  static void snapshot_status(struct dm_target *ti, status_type_t type,
  			    unsigned status_flags, char *result, unsigned maxlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2160
  {
2e4a31df2   Jonathan Brassow   dm snapshot: use ...
2161
  	unsigned sz = 0;
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
2162
  	struct dm_snapshot *snap = ti->private;
2e6023850   Mike Snitzer   dm snapshot: add ...
2163
  	unsigned num_features;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2164
2165
2166
  
  	switch (type) {
  	case STATUSTYPE_INFO:
94e76572b   Mikulas Patocka   dm snapshot: only...
2167

4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2168
  		down_write(&snap->lock);
94e76572b   Mikulas Patocka   dm snapshot: only...
2169

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2170
  		if (!snap->valid)
2e4a31df2   Jonathan Brassow   dm snapshot: use ...
2171
  			DMEMIT("Invalid");
d8ddb1cff   Mike Snitzer   dm snapshot: repo...
2172
2173
  		else if (snap->merge_failed)
  			DMEMIT("Merge failed");
76c44f6d8   Mikulas Patocka   dm snapshot: don'...
2174
2175
  		else if (snap->snapshot_overflowed)
  			DMEMIT("Overflow");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2176
  		else {
985903bb3   Mike Snitzer   dm snapshot: add ...
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
  			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
2188
2189
  			}
  			else
2e4a31df2   Jonathan Brassow   dm snapshot: use ...
2190
  				DMEMIT("Unknown");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
  		}
94e76572b   Mikulas Patocka   dm snapshot: only...
2192

4ad8d880b   Nikos Tsironis   dm snapshot: Repl...
2193
  		up_write(&snap->lock);
94e76572b   Mikulas Patocka   dm snapshot: only...
2194

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2195
2196
2197
2198
2199
2200
2201
2202
  		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...
2203
  		DMEMIT("%s %s", snap->origin->name, snap->cow->name);
2e6023850   Mike Snitzer   dm snapshot: add ...
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
  		sz += snap->store->type->status(snap->store, type, result + sz,
  						maxlen - sz);
  		num_features = snap->discard_zeroes_cow + snap->discard_passdown_origin;
  		if (num_features) {
  			DMEMIT(" %u", num_features);
  			if (snap->discard_zeroes_cow)
  				DMEMIT(" discard_zeroes_cow");
  			if (snap->discard_passdown_origin)
  				DMEMIT(" discard_passdown_origin");
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2214
2215
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2216
  }
8811f46c1   Mike Snitzer   dm snapshot: impl...
2217
2218
2219
2220
  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...
2221
2222
2223
  	int r;
  
  	r = fn(ti, snap->origin, 0, ti->len, data);
8811f46c1   Mike Snitzer   dm snapshot: impl...
2224

1e5554c84   Mikulas Patocka   dm snapshot: iter...
2225
2226
2227
2228
  	if (!r)
  		r = fn(ti, snap->cow, 0, get_dev_size(snap->cow->bdev), data);
  
  	return r;
8811f46c1   Mike Snitzer   dm snapshot: impl...
2229
  }
2e6023850   Mike Snitzer   dm snapshot: add ...
2230
2231
2232
2233
2234
2235
  static void snapshot_io_hints(struct dm_target *ti, struct queue_limits *limits)
  {
  	struct dm_snapshot *snap = ti->private;
  
  	if (snap->discard_zeroes_cow) {
  		struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
3ee25485b   Mike Snitzer   dm snapshot: fix ...
2236
  		down_read(&_origins_lock);
2e6023850   Mike Snitzer   dm snapshot: add ...
2237
2238
2239
2240
2241
2242
2243
  		(void) __find_snapshots_sharing_cow(snap, &snap_src, &snap_dest, NULL);
  		if (snap_src && snap_dest)
  			snap = snap_src;
  
  		/* All discards are split on chunk_size boundary */
  		limits->discard_granularity = snap->store->chunk_size;
  		limits->max_discard_sectors = snap->store->chunk_size;
3ee25485b   Mike Snitzer   dm snapshot: fix ...
2244
2245
  
  		up_read(&_origins_lock);
2e6023850   Mike Snitzer   dm snapshot: add ...
2246
2247
  	}
  }
8811f46c1   Mike Snitzer   dm snapshot: impl...
2248

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2249
2250
2251
  /*-----------------------------------------------------------------
   * Origin methods
   *---------------------------------------------------------------*/
9eaae8ffb   Mikulas Patocka   dm snapshot: make...
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
  
  /*
   * 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
2265
  {
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2266
  	int r = DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2267
  	struct dm_snapshot *snap;
1d4989c85   Jon Brassow   dm snapshot: rena...
2268
  	struct dm_exception *e;
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
2269
  	struct dm_snap_pending_exception *pe, *pe2;
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2270
2271
  	struct dm_snap_pending_exception *pe_to_start_now = NULL;
  	struct dm_snap_pending_exception *pe_to_start_last = NULL;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2272
  	struct dm_exception_table_lock lock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2273
2274
2275
2276
  	chunk_t chunk;
  
  	/* Do all the snapshots on this origin */
  	list_for_each_entry (snap, snapshots, list) {
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2277
2278
2279
2280
2281
2282
  		/*
  		 * Don't make new exceptions in a merging snapshot
  		 * because it has effectively been deleted
  		 */
  		if (dm_target_is_snapshot_merge(snap->ti))
  			continue;
d5e404c10   Alasdair G Kergon   [PATCH] device-ma...
2283
  		/* Nothing to do if writing beyond end of snapshot */
9eaae8ffb   Mikulas Patocka   dm snapshot: make...
2284
  		if (sector >= dm_table_get_size(snap->ti->table))
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2285
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2286
2287
2288
2289
2290
  
  		/*
  		 * Remember, different snapshots can have
  		 * different chunk sizes.
  		 */
9eaae8ffb   Mikulas Patocka   dm snapshot: make...
2291
  		chunk = sector_to_chunk(snap->store, sector);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2292
  		dm_exception_table_lock_init(snap, chunk, &lock);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
2293
  		down_read(&snap->lock);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2294
2295
2296
2297
2298
  		dm_exception_table_lock(&lock);
  
  		/* Only deal with valid and active snapshots */
  		if (!snap->valid || !snap->active)
  			goto next_snapshot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2299

2913808eb   Mikulas Patocka   dm snapshot: refa...
2300
  		pe = __lookup_pending_exception(snap, chunk);
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
2301
  		if (!pe) {
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
2302
2303
2304
2305
2306
2307
2308
2309
  			/*
  			 * Check exception table to see if block is already
  			 * remapped in this snapshot and trigger an exception
  			 * if not.
  			 */
  			e = dm_lookup_exception(&snap->complete, chunk);
  			if (e)
  				goto next_snapshot;
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2310
  			dm_exception_table_unlock(&lock);
c66213921   Mikulas Patocka   dm snapshot: avoi...
2311
  			pe = alloc_pending_exception(snap);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2312
  			dm_exception_table_lock(&lock);
c66213921   Mikulas Patocka   dm snapshot: avoi...
2313

65fc7c370   Nikos Tsironis   dm snapshot: Don'...
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
  			pe2 = __lookup_pending_exception(snap, chunk);
  
  			if (!pe2) {
  				e = dm_lookup_exception(&snap->complete, chunk);
  				if (e) {
  					free_pending_exception(pe);
  					goto next_snapshot;
  				}
  
  				pe = __insert_pending_exception(snap, pe, chunk);
  				if (!pe) {
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2325
  					dm_exception_table_unlock(&lock);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
2326
  					up_read(&snap->lock);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2327

3f1637f21   Nikos Tsironis   dm snapshot: Use ...
2328
  					invalidate_snapshot(snap, -ENOMEM);
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2329
  					continue;
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
2330
2331
  				}
  			} else {
35bf659b0   Mikulas Patocka   dm snapshot: avoi...
2332
  				free_pending_exception(pe);
65fc7c370   Nikos Tsironis   dm snapshot: Don'...
2333
  				pe = pe2;
2913808eb   Mikulas Patocka   dm snapshot: refa...
2334
  			}
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
2335
  		}
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2336
  		r = DM_MAPIO_SUBMITTED;
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
2337

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2338
2339
2340
2341
2342
2343
2344
2345
  		/*
  		 * 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...
2346

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2347
2348
2349
2350
  			if (!pe->started) {
  				pe->started = 1;
  				pe_to_start_last = pe;
  			}
76df1c651   Alasdair G Kergon   [PATCH] device-ma...
2351
2352
2353
2354
  		}
  
  		if (!pe->started) {
  			pe->started = 1;
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2355
  			pe_to_start_now = pe;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2356
  		}
a2d2b0345   Jonathan Brassow   dm snapshot: styl...
2357
  next_snapshot:
f79ae415b   Nikos Tsironis   dm snapshot: Make...
2358
  		dm_exception_table_unlock(&lock);
3f1637f21   Nikos Tsironis   dm snapshot: Use ...
2359
  		up_read(&snap->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2360

515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2361
2362
2363
2364
  		if (pe_to_start_now) {
  			start_copy(pe_to_start_now);
  			pe_to_start_now = NULL;
  		}
b4b610f68   Alasdair G Kergon   [PATCH] device-ma...
2365
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2366
  	/*
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2367
2368
  	 * 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
2369
  	 */
515ad66cc   Mikulas Patocka   dm snapshot: rewo...
2370
2371
  	if (pe_to_start_last)
  		start_copy(pe_to_start_last);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2372
2373
2374
2375
2376
2377
2378
  
  	return r;
  }
  
  /*
   * Called on a write from the origin driver.
   */
b21555786   Mikulas Patocka   dm snapshot: rewo...
2379
  static int do_origin(struct dm_dev *origin, struct bio *bio, bool limit)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2380
2381
  {
  	struct origin *o;
d2a7ad29a   Kiyoshi Ueda   [PATCH] dm: map a...
2382
  	int r = DM_MAPIO_REMAPPED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2383

b21555786   Mikulas Patocka   dm snapshot: rewo...
2384
  again:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2385
2386
  	down_read(&_origins_lock);
  	o = __lookup_origin(origin->bdev);
b21555786   Mikulas Patocka   dm snapshot: rewo...
2387
2388
2389
2390
2391
2392
2393
  	if (o) {
  		if (limit) {
  			struct dm_snapshot *s;
  			list_for_each_entry(s, &o->snapshots, list)
  				if (unlikely(!wait_for_in_progress(s, true)))
  					goto again;
  		}
4f024f379   Kent Overstreet   block: Abstract o...
2394
  		r = __origin_write(&o->snapshots, bio->bi_iter.bi_sector, bio);
b21555786   Mikulas Patocka   dm snapshot: rewo...
2395
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2396
2397
2398
2399
2400
2401
  	up_read(&_origins_lock);
  
  	return r;
  }
  
  /*
73dfd078c   Mikulas Patocka   dm snapshot: trig...
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
   * 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;
  
  	/*
542f90381   Mike Snitzer   dm: support non p...
2422
  	 * The origin's __minimum_chunk_size() got stored in max_io_len
73dfd078c   Mikulas Patocka   dm snapshot: trig...
2423
2424
2425
2426
  	 * by snapshot_merge_resume().
  	 */
  	down_read(&_origins_lock);
  	o = __lookup_origin(merging_snap->origin->bdev);
542f90381   Mike Snitzer   dm: support non p...
2427
  	for (n = 0; n < size; n += merging_snap->ti->max_io_len)
73dfd078c   Mikulas Patocka   dm snapshot: trig...
2428
2429
2430
2431
2432
2433
2434
2435
2436
  		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
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
   * 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;
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2448
  	struct dm_origin *o;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2449
2450
  
  	if (argc != 1) {
72d948616   Alasdair G Kergon   [PATCH] dm: impro...
2451
  		ti->error = "origin: incorrect number of arguments";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2452
2453
  		return -EINVAL;
  	}
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2454
2455
2456
2457
2458
2459
2460
2461
  	o = kmalloc(sizeof(struct dm_origin), GFP_KERNEL);
  	if (!o) {
  		ti->error = "Cannot allocate private origin structure";
  		r = -ENOMEM;
  		goto bad_alloc;
  	}
  
  	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &o->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2462
2463
  	if (r) {
  		ti->error = "Cannot get target device";
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2464
  		goto bad_open;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2465
  	}
b735fede8   Mikulas Patocka   dm snapshot: susp...
2466
  	o->ti = ti;
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2467
  	ti->private = o;
55a62eef8   Alasdair G Kergon   dm: rename reques...
2468
  	ti->num_flush_bios = 1;
494b3ee7d   Mikulas Patocka   dm snapshot: supp...
2469

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2470
  	return 0;
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2471
2472
2473
2474
2475
  
  bad_open:
  	kfree(o);
  bad_alloc:
  	return r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2476
2477
2478
2479
  }
  
  static void origin_dtr(struct dm_target *ti)
  {
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2480
  	struct dm_origin *o = ti->private;
b735fede8   Mikulas Patocka   dm snapshot: susp...
2481

599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2482
2483
  	dm_put_device(ti, o->dev);
  	kfree(o);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2484
  }
7de3ee57d   Mikulas Patocka   dm: remove map_info
2485
  static int origin_map(struct dm_target *ti, struct bio *bio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2486
  {
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2487
  	struct dm_origin *o = ti->private;
298eaa89b   Mikulas Patocka   dm snapshot: do n...
2488
  	unsigned available_sectors;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2489

74d46992e   Christoph Hellwig   block: replace bi...
2490
  	bio_set_dev(bio, o->dev->bdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2491

1eff9d322   Jens Axboe   block: rename bio...
2492
  	if (unlikely(bio->bi_opf & REQ_PREFLUSH))
494b3ee7d   Mikulas Patocka   dm snapshot: supp...
2493
  		return DM_MAPIO_REMAPPED;
70246286e   Christoph Hellwig   block: get rid of...
2494
  	if (bio_data_dir(bio) != WRITE)
494b3ee7d   Mikulas Patocka   dm snapshot: supp...
2495
  		return DM_MAPIO_REMAPPED;
298eaa89b   Mikulas Patocka   dm snapshot: do n...
2496
2497
2498
2499
2500
  	available_sectors = o->split_boundary -
  		((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1));
  
  	if (bio_sectors(bio) > available_sectors)
  		dm_accept_partial_bio(bio, available_sectors);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2501
  	/* Only tell snapshots if this is a write */
b21555786   Mikulas Patocka   dm snapshot: rewo...
2502
  	return do_origin(o->dev, bio, true);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2503
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2504
  /*
542f90381   Mike Snitzer   dm: support non p...
2505
   * Set the target "max_io_len" field to the minimum of all the snapshots'
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2506
2507
2508
2509
   * chunk sizes.
   */
  static void origin_resume(struct dm_target *ti)
  {
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2510
  	struct dm_origin *o = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2511

298eaa89b   Mikulas Patocka   dm snapshot: do n...
2512
  	o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev);
b735fede8   Mikulas Patocka   dm snapshot: susp...
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
  
  	down_write(&_origins_lock);
  	__insert_dm_origin(o);
  	up_write(&_origins_lock);
  }
  
  static void origin_postsuspend(struct dm_target *ti)
  {
  	struct dm_origin *o = ti->private;
  
  	down_write(&_origins_lock);
  	__remove_dm_origin(o);
  	up_write(&_origins_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2526
  }
fd7c092e7   Mikulas Patocka   dm: fix truncated...
2527
2528
  static void origin_status(struct dm_target *ti, status_type_t type,
  			  unsigned status_flags, char *result, unsigned maxlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2529
  {
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2530
  	struct dm_origin *o = ti->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2531
2532
2533
2534
2535
2536
2537
  
  	switch (type) {
  	case STATUSTYPE_INFO:
  		result[0] = '\0';
  		break;
  
  	case STATUSTYPE_TABLE:
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2538
  		snprintf(result, maxlen, "%s", o->dev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2539
2540
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2541
  }
8811f46c1   Mike Snitzer   dm snapshot: impl...
2542
2543
2544
  static int origin_iterate_devices(struct dm_target *ti,
  				  iterate_devices_callout_fn fn, void *data)
  {
599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2545
  	struct dm_origin *o = ti->private;
8811f46c1   Mike Snitzer   dm snapshot: impl...
2546

599cdf3bf   Mikulas Patocka   dm snapshot: allo...
2547
  	return fn(ti, o->dev, 0, ti->len, data);
8811f46c1   Mike Snitzer   dm snapshot: impl...
2548
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2549
2550
  static struct target_type origin_target = {
  	.name    = "snapshot-origin",
b735fede8   Mikulas Patocka   dm snapshot: susp...
2551
  	.version = {1, 9, 0},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2552
2553
2554
2555
2556
  	.module  = THIS_MODULE,
  	.ctr     = origin_ctr,
  	.dtr     = origin_dtr,
  	.map     = origin_map,
  	.resume  = origin_resume,
b735fede8   Mikulas Patocka   dm snapshot: susp...
2557
  	.postsuspend = origin_postsuspend,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2558
  	.status  = origin_status,
8811f46c1   Mike Snitzer   dm snapshot: impl...
2559
  	.iterate_devices = origin_iterate_devices,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2560
2561
2562
2563
  };
  
  static struct target_type snapshot_target = {
  	.name    = "snapshot",
2e6023850   Mike Snitzer   dm snapshot: add ...
2564
  	.version = {1, 16, 0},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2565
2566
2567
2568
  	.module  = THIS_MODULE,
  	.ctr     = snapshot_ctr,
  	.dtr     = snapshot_dtr,
  	.map     = snapshot_map,
cd45daffd   Mikulas Patocka   dm snapshot: trac...
2569
  	.end_io  = snapshot_end_io,
c1f0c183f   Mike Snitzer   dm snapshot: allo...
2570
  	.preresume  = snapshot_preresume,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2571
2572
  	.resume  = snapshot_resume,
  	.status  = snapshot_status,
8811f46c1   Mike Snitzer   dm snapshot: impl...
2573
  	.iterate_devices = snapshot_iterate_devices,
2e6023850   Mike Snitzer   dm snapshot: add ...
2574
  	.io_hints = snapshot_io_hints,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2575
  };
d698aa450   Mikulas Patocka   dm snapshot: add ...
2576
2577
  static struct target_type merge_target = {
  	.name    = dm_snapshot_merge_target_name,
2e6023850   Mike Snitzer   dm snapshot: add ...
2578
  	.version = {1, 5, 0},
d698aa450   Mikulas Patocka   dm snapshot: add ...
2579
2580
2581
  	.module  = THIS_MODULE,
  	.ctr     = snapshot_ctr,
  	.dtr     = snapshot_dtr,
3452c2a1e   Mikulas Patocka   dm snapshot: avoi...
2582
  	.map     = snapshot_merge_map,
d698aa450   Mikulas Patocka   dm snapshot: add ...
2583
  	.end_io  = snapshot_end_io,
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2584
  	.presuspend = snapshot_merge_presuspend,
d698aa450   Mikulas Patocka   dm snapshot: add ...
2585
  	.preresume  = snapshot_preresume,
1e03f97e4   Mikulas Patocka   dm snapshot: add ...
2586
  	.resume  = snapshot_merge_resume,
d698aa450   Mikulas Patocka   dm snapshot: add ...
2587
2588
  	.status  = snapshot_status,
  	.iterate_devices = snapshot_iterate_devices,
2e6023850   Mike Snitzer   dm snapshot: add ...
2589
  	.io_hints = snapshot_io_hints,
d698aa450   Mikulas Patocka   dm snapshot: add ...
2590
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2591
2592
2593
  static int __init dm_snapshot_init(void)
  {
  	int r;
4db6bfe02   Alasdair G Kergon   dm snapshot: spli...
2594
2595
2596
2597
2598
  	r = dm_exception_store_init();
  	if (r) {
  		DMERR("Failed to initialize exception stores");
  		return r;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2599
2600
2601
  	r = init_origin_hash();
  	if (r) {
  		DMERR("init_origin_hash failed.");
d698aa450   Mikulas Patocka   dm snapshot: add ...
2602
  		goto bad_origin_hash;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2603
  	}
1d4989c85   Jon Brassow   dm snapshot: rena...
2604
  	exception_cache = KMEM_CACHE(dm_exception, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2605
2606
2607
  	if (!exception_cache) {
  		DMERR("Couldn't create exception cache.");
  		r = -ENOMEM;
d698aa450   Mikulas Patocka   dm snapshot: add ...
2608
  		goto bad_exception_cache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2609
  	}
028867ac2   Alasdair G Kergon   dm: use kmem_cach...
2610
  	pending_cache = KMEM_CACHE(dm_snap_pending_exception, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2611
2612
2613
  	if (!pending_cache) {
  		DMERR("Couldn't create pending cache.");
  		r = -ENOMEM;
d698aa450   Mikulas Patocka   dm snapshot: add ...
2614
  		goto bad_pending_cache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2615
  	}
7e6358d24   monty_pavel@sina.com   dm: fix various t...
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
  	r = dm_register_target(&snapshot_target);
  	if (r < 0) {
  		DMERR("snapshot target register failed %d", r);
  		goto bad_register_snapshot_target;
  	}
  
  	r = dm_register_target(&origin_target);
  	if (r < 0) {
  		DMERR("Origin target register failed %d", r);
  		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
2633
  	return 0;
d698aa450   Mikulas Patocka   dm snapshot: add ...
2634
  bad_register_merge_target:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2635
  	dm_unregister_target(&origin_target);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2636
  bad_register_origin_target:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2637
  	dm_unregister_target(&snapshot_target);
034a186d2   Jonathan Brassow   dm snapshot: free...
2638
  bad_register_snapshot_target:
7e6358d24   monty_pavel@sina.com   dm: fix various t...
2639
2640
2641
2642
2643
2644
  	kmem_cache_destroy(pending_cache);
  bad_pending_cache:
  	kmem_cache_destroy(exception_cache);
  bad_exception_cache:
  	exit_origin_hash();
  bad_origin_hash:
034a186d2   Jonathan Brassow   dm snapshot: free...
2645
  	dm_exception_store_exit();
d698aa450   Mikulas Patocka   dm snapshot: add ...
2646

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2647
2648
2649
2650
2651
  	return r;
  }
  
  static void __exit dm_snapshot_exit(void)
  {
10d3bd09a   Mikulas Patocka   dm: consolidate t...
2652
2653
  	dm_unregister_target(&snapshot_target);
  	dm_unregister_target(&origin_target);
d698aa450   Mikulas Patocka   dm snapshot: add ...
2654
  	dm_unregister_target(&merge_target);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2655
2656
  
  	exit_origin_hash();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2657
2658
  	kmem_cache_destroy(pending_cache);
  	kmem_cache_destroy(exception_cache);
4db6bfe02   Alasdair G Kergon   dm snapshot: spli...
2659
2660
  
  	dm_exception_store_exit();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2661
2662
2663
2664
2665
2666
2667
2668
2669
  }
  
  /* 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");
23cb21092   Mikulas Patocka   dm snapshot: add ...
2670
2671
  MODULE_ALIAS("dm-snapshot-origin");
  MODULE_ALIAS("dm-snapshot-merge");