diff options
Diffstat (limited to 'drivers/md/dm-snap.c')
| -rw-r--r-- | drivers/md/dm-snap.c | 29 |
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 87727d84dbba..f3759dd7828e 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -373,16 +373,11 @@ static inline ulong round_up(ulong n, ulong size) | |||
| 373 | 373 | ||
| 374 | static void read_snapshot_metadata(struct dm_snapshot *s) | 374 | static void read_snapshot_metadata(struct dm_snapshot *s) |
| 375 | { | 375 | { |
| 376 | if (s->have_metadata) | ||
| 377 | return; | ||
| 378 | |||
| 379 | if (s->store.read_metadata(&s->store)) { | 376 | if (s->store.read_metadata(&s->store)) { |
| 380 | down_write(&s->lock); | 377 | down_write(&s->lock); |
| 381 | s->valid = 0; | 378 | s->valid = 0; |
| 382 | up_write(&s->lock); | 379 | up_write(&s->lock); |
| 383 | } | 380 | } |
| 384 | |||
| 385 | s->have_metadata = 1; | ||
| 386 | } | 381 | } |
| 387 | 382 | ||
| 388 | /* | 383 | /* |
| @@ -471,7 +466,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 471 | s->chunk_shift = ffs(chunk_size) - 1; | 466 | s->chunk_shift = ffs(chunk_size) - 1; |
| 472 | 467 | ||
| 473 | s->valid = 1; | 468 | s->valid = 1; |
| 474 | s->have_metadata = 0; | 469 | s->active = 0; |
| 475 | s->last_percent = 0; | 470 | s->last_percent = 0; |
| 476 | init_rwsem(&s->lock); | 471 | init_rwsem(&s->lock); |
| 477 | s->table = ti->table; | 472 | s->table = ti->table; |
| @@ -506,7 +501,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 506 | goto bad5; | 501 | goto bad5; |
| 507 | } | 502 | } |
| 508 | 503 | ||
| 504 | /* Metadata must only be loaded into one table at once */ | ||
| 505 | read_snapshot_metadata(s); | ||
| 506 | |||
| 509 | /* Add snapshot to the list of snapshots for this origin */ | 507 | /* Add snapshot to the list of snapshots for this origin */ |
| 508 | /* Exceptions aren't triggered till snapshot_resume() is called */ | ||
| 510 | if (register_snapshot(s)) { | 509 | if (register_snapshot(s)) { |
| 511 | r = -EINVAL; | 510 | r = -EINVAL; |
| 512 | ti->error = "Cannot register snapshot origin"; | 511 | ti->error = "Cannot register snapshot origin"; |
| @@ -793,6 +792,9 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
| 793 | if (!s->valid) | 792 | if (!s->valid) |
| 794 | return -EIO; | 793 | return -EIO; |
| 795 | 794 | ||
| 795 | if (unlikely(bio_barrier(bio))) | ||
| 796 | return -EOPNOTSUPP; | ||
| 797 | |||
| 796 | /* | 798 | /* |
| 797 | * Write to snapshot - higher level takes care of RW/RO | 799 | * Write to snapshot - higher level takes care of RW/RO |
| 798 | * flags so we should only get this if we are | 800 | * flags so we should only get this if we are |
| @@ -862,7 +864,9 @@ static void snapshot_resume(struct dm_target *ti) | |||
| 862 | { | 864 | { |
| 863 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; | 865 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; |
| 864 | 866 | ||
| 865 | read_snapshot_metadata(s); | 867 | down_write(&s->lock); |
| 868 | s->active = 1; | ||
| 869 | up_write(&s->lock); | ||
| 866 | } | 870 | } |
| 867 | 871 | ||
| 868 | static int snapshot_status(struct dm_target *ti, status_type_t type, | 872 | static int snapshot_status(struct dm_target *ti, status_type_t type, |
| @@ -932,8 +936,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
| 932 | /* Do all the snapshots on this origin */ | 936 | /* Do all the snapshots on this origin */ |
| 933 | list_for_each_entry (snap, snapshots, list) { | 937 | list_for_each_entry (snap, snapshots, list) { |
| 934 | 938 | ||
| 935 | /* Only deal with valid snapshots */ | 939 | /* Only deal with valid and active snapshots */ |
| 936 | if (!snap->valid) | 940 | if (!snap->valid || !snap->active) |
| 937 | continue; | 941 | continue; |
| 938 | 942 | ||
| 939 | /* Nothing to do if writing beyond end of snapshot */ | 943 | /* Nothing to do if writing beyond end of snapshot */ |
| @@ -1057,6 +1061,9 @@ static int origin_map(struct dm_target *ti, struct bio *bio, | |||
| 1057 | struct dm_dev *dev = (struct dm_dev *) ti->private; | 1061 | struct dm_dev *dev = (struct dm_dev *) ti->private; |
| 1058 | bio->bi_bdev = dev->bdev; | 1062 | bio->bi_bdev = dev->bdev; |
| 1059 | 1063 | ||
| 1064 | if (unlikely(bio_barrier(bio))) | ||
| 1065 | return -EOPNOTSUPP; | ||
| 1066 | |||
| 1060 | /* Only tell snapshots if this is a write */ | 1067 | /* Only tell snapshots if this is a write */ |
| 1061 | return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; | 1068 | return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; |
| 1062 | } | 1069 | } |
| @@ -1104,7 +1111,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, | |||
| 1104 | 1111 | ||
| 1105 | static struct target_type origin_target = { | 1112 | static struct target_type origin_target = { |
| 1106 | .name = "snapshot-origin", | 1113 | .name = "snapshot-origin", |
| 1107 | .version = {1, 0, 1}, | 1114 | .version = {1, 1, 0}, |
| 1108 | .module = THIS_MODULE, | 1115 | .module = THIS_MODULE, |
| 1109 | .ctr = origin_ctr, | 1116 | .ctr = origin_ctr, |
| 1110 | .dtr = origin_dtr, | 1117 | .dtr = origin_dtr, |
| @@ -1115,7 +1122,7 @@ static struct target_type origin_target = { | |||
| 1115 | 1122 | ||
| 1116 | static struct target_type snapshot_target = { | 1123 | static struct target_type snapshot_target = { |
| 1117 | .name = "snapshot", | 1124 | .name = "snapshot", |
| 1118 | .version = {1, 0, 1}, | 1125 | .version = {1, 1, 0}, |
| 1119 | .module = THIS_MODULE, | 1126 | .module = THIS_MODULE, |
| 1120 | .ctr = snapshot_ctr, | 1127 | .ctr = snapshot_ctr, |
| 1121 | .dtr = snapshot_dtr, | 1128 | .dtr = snapshot_dtr, |
