Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] device-mapper snapshot: load metadata on creation

Move snapshot metadata loading to happen when the table is created instead of
when the device is resumed. Writes to the origin device don't trigger
exceptions until each snapshot table becomes active when resume() is called on
each snapshot.

If you're using lvm2, for this patch to work properly you should update to
lvm2 version 2.02.01 or later and device-mapper version 1.02.02 or later.

Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Alasdair G Kergon and committed by
Linus Torvalds
aa14edeb cb82a6cd

+15 -12
+12 -11
drivers/md/dm-snap.c
··· 373 373 374 374 static void read_snapshot_metadata(struct dm_snapshot *s) 375 375 { 376 - if (s->have_metadata) 377 - return; 378 - 379 376 if (s->store.read_metadata(&s->store)) { 380 377 down_write(&s->lock); 381 378 s->valid = 0; 382 379 up_write(&s->lock); 383 380 } 384 - 385 - s->have_metadata = 1; 386 381 } 387 382 388 383 /* ··· 466 471 s->chunk_shift = ffs(chunk_size) - 1; 467 472 468 473 s->valid = 1; 469 - s->have_metadata = 0; 474 + s->active = 0; 470 475 s->last_percent = 0; 471 476 init_rwsem(&s->lock); 472 477 s->table = ti->table; ··· 501 506 goto bad5; 502 507 } 503 508 509 + /* Metadata must only be loaded into one table at once */ 510 + read_snapshot_metadata(s); 511 + 504 512 /* Add snapshot to the list of snapshots for this origin */ 513 + /* Exceptions aren't triggered till snapshot_resume() is called */ 505 514 if (register_snapshot(s)) { 506 515 r = -EINVAL; 507 516 ti->error = "Cannot register snapshot origin"; ··· 861 862 { 862 863 struct dm_snapshot *s = (struct dm_snapshot *) ti->private; 863 864 864 - read_snapshot_metadata(s); 865 + down_write(&s->lock); 866 + s->active = 1; 867 + up_write(&s->lock); 865 868 } 866 869 867 870 static int snapshot_status(struct dm_target *ti, status_type_t type, ··· 933 932 /* Do all the snapshots on this origin */ 934 933 list_for_each_entry (snap, snapshots, list) { 935 934 936 - /* Only deal with valid snapshots */ 937 - if (!snap->valid) 935 + /* Only deal with valid and active snapshots */ 936 + if (!snap->valid || !snap->active) 938 937 continue; 939 938 940 939 /* Nothing to do if writing beyond end of snapshot */ ··· 1105 1104 1106 1105 static struct target_type origin_target = { 1107 1106 .name = "snapshot-origin", 1108 - .version = {1, 0, 1}, 1107 + .version = {1, 1, 0}, 1109 1108 .module = THIS_MODULE, 1110 1109 .ctr = origin_ctr, 1111 1110 .dtr = origin_dtr, ··· 1116 1115 1117 1116 static struct target_type snapshot_target = { 1118 1117 .name = "snapshot", 1119 - .version = {1, 0, 1}, 1118 + .version = {1, 1, 0}, 1120 1119 .module = THIS_MODULE, 1121 1120 .ctr = snapshot_ctr, 1122 1121 .dtr = snapshot_dtr,
+3 -1
drivers/md/dm-snap.h
··· 99 99 100 100 /* You can't use a snapshot if this is 0 (e.g. if full) */ 101 101 int valid; 102 - int have_metadata; 102 + 103 + /* Origin writes don't trigger exceptions until this is set */ 104 + int active; 103 105 104 106 /* Used for display of table */ 105 107 char type;