aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2009-12-10 18:52:12 -0500
committerAlasdair G Kergon <agk@redhat.com>2009-12-10 18:52:12 -0500
commitfc56f6fbcca3672c63c93c65f45105faacfc13cb (patch)
treef50f42a461ef33f8617fbdb781879e6ae77b62c4
parent985903bb3a6d98623360ab6c855417f638840029 (diff)
dm snapshot: move cow ref from exception store to snap core
Store the reference to the snapshot cow device in the core snapshot code instead of each exception store. It can be accessed through the new function dm_snap_cow(). Exception stores should each now maintain a reference to their parent snapshot struct. This is cleaner and makes part of the forthcoming snapshot merge code simpler. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> Reviewed-by: Jonathan Brassow <jbrassow@redhat.com> Cc: Mikulas Patocka <mpatocka@redhat.com>
-rw-r--r--drivers/md/dm-exception-store.c30
-rw-r--r--drivers/md/dm-exception-store.h12
-rw-r--r--drivers/md/dm-snap-persistent.c12
-rw-r--r--drivers/md/dm-snap-transient.c7
-rw-r--r--drivers/md/dm-snap.c74
5 files changed, 78 insertions, 57 deletions
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 205215968ff1..2b7907b6dd09 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -172,7 +172,8 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
172 } 172 }
173 173
174 /* Validate the chunk size against the device block size */ 174 /* Validate the chunk size against the device block size */
175 if (chunk_size % (bdev_logical_block_size(store->cow->bdev) >> 9)) { 175 if (chunk_size %
176 (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9)) {
176 *error = "Chunk size is not a multiple of device blocksize"; 177 *error = "Chunk size is not a multiple of device blocksize";
177 return -EINVAL; 178 return -EINVAL;
178 } 179 }
@@ -190,6 +191,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
190} 191}
191 192
192int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 193int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
194 struct dm_snapshot *snap,
193 unsigned *args_used, 195 unsigned *args_used,
194 struct dm_exception_store **store) 196 struct dm_exception_store **store)
195{ 197{
@@ -198,7 +200,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
198 struct dm_exception_store *tmp_store; 200 struct dm_exception_store *tmp_store;
199 char persistent; 201 char persistent;
200 202
201 if (argc < 3) { 203 if (argc < 2) {
202 ti->error = "Insufficient exception store arguments"; 204 ti->error = "Insufficient exception store arguments";
203 return -EINVAL; 205 return -EINVAL;
204 } 206 }
@@ -209,7 +211,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
209 return -ENOMEM; 211 return -ENOMEM;
210 } 212 }
211 213
212 persistent = toupper(*argv[1]); 214 persistent = toupper(*argv[0]);
213 if (persistent == 'P') 215 if (persistent == 'P')
214 type = get_type("P"); 216 type = get_type("P");
215 else if (persistent == 'N') 217 else if (persistent == 'N')
@@ -227,32 +229,23 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
227 } 229 }
228 230
229 tmp_store->type = type; 231 tmp_store->type = type;
230 tmp_store->ti = ti; 232 tmp_store->snap = snap;
231 233
232 r = dm_get_device(ti, argv[0], 0, 0, 234 r = set_chunk_size(tmp_store, argv[1], &ti->error);
233 FMODE_READ | FMODE_WRITE, &tmp_store->cow);
234 if (r) {
235 ti->error = "Cannot get COW device";
236 goto bad_cow;
237 }
238
239 r = set_chunk_size(tmp_store, argv[2], &ti->error);
240 if (r) 235 if (r)
241 goto bad_ctr; 236 goto bad;
242 237
243 r = type->ctr(tmp_store, 0, NULL); 238 r = type->ctr(tmp_store, 0, NULL);
244 if (r) { 239 if (r) {
245 ti->error = "Exception store type constructor failed"; 240 ti->error = "Exception store type constructor failed";
246 goto bad_ctr; 241 goto bad;
247 } 242 }
248 243
249 *args_used = 3; 244 *args_used = 2;
250 *store = tmp_store; 245 *store = tmp_store;
251 return 0; 246 return 0;
252 247
253bad_ctr: 248bad:
254 dm_put_device(ti, tmp_store->cow);
255bad_cow:
256 put_type(type); 249 put_type(type);
257bad_type: 250bad_type:
258 kfree(tmp_store); 251 kfree(tmp_store);
@@ -263,7 +256,6 @@ EXPORT_SYMBOL(dm_exception_store_create);
263void dm_exception_store_destroy(struct dm_exception_store *store) 256void dm_exception_store_destroy(struct dm_exception_store *store)
264{ 257{
265 store->type->dtr(store); 258 store->type->dtr(store);
266 dm_put_device(store->ti, store->cow);
267 put_type(store->type); 259 put_type(store->type);
268 kfree(store); 260 kfree(store);
269} 261}
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index 366c8b1fca37..bb8874653de1 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -94,11 +94,11 @@ struct dm_exception_store_type {
94 struct list_head list; 94 struct list_head list;
95}; 95};
96 96
97struct dm_snapshot;
98
97struct dm_exception_store { 99struct dm_exception_store {
98 struct dm_exception_store_type *type; 100 struct dm_exception_store_type *type;
99 struct dm_target *ti; 101 struct dm_snapshot *snap;
100
101 struct dm_dev *cow;
102 102
103 /* Size of data blocks saved - must be a power of 2 */ 103 /* Size of data blocks saved - must be a power of 2 */
104 unsigned chunk_size; 104 unsigned chunk_size;
@@ -109,6 +109,11 @@ struct dm_exception_store {
109}; 109};
110 110
111/* 111/*
112 * Obtain the cow device used by a given snapshot.
113 */
114struct dm_dev *dm_snap_cow(struct dm_snapshot *snap);
115
116/*
112 * Funtions to manipulate consecutive chunks 117 * Funtions to manipulate consecutive chunks
113 */ 118 */
114# if defined(CONFIG_LBDAF) || (BITS_PER_LONG == 64) 119# if defined(CONFIG_LBDAF) || (BITS_PER_LONG == 64)
@@ -173,6 +178,7 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
173 char **error); 178 char **error);
174 179
175int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 180int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
181 struct dm_snapshot *snap,
176 unsigned *args_used, 182 unsigned *args_used,
177 struct dm_exception_store **store); 183 struct dm_exception_store **store);
178void dm_exception_store_destroy(struct dm_exception_store *store); 184void dm_exception_store_destroy(struct dm_exception_store *store);
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index 767065f6c5f3..157999ebd236 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -214,7 +214,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw,
214 int metadata) 214 int metadata)
215{ 215{
216 struct dm_io_region where = { 216 struct dm_io_region where = {
217 .bdev = ps->store->cow->bdev, 217 .bdev = dm_snap_cow(ps->store->snap)->bdev,
218 .sector = ps->store->chunk_size * chunk, 218 .sector = ps->store->chunk_size * chunk,
219 .count = ps->store->chunk_size, 219 .count = ps->store->chunk_size,
220 }; 220 };
@@ -294,7 +294,8 @@ static int read_header(struct pstore *ps, int *new_snapshot)
294 */ 294 */
295 if (!ps->store->chunk_size) { 295 if (!ps->store->chunk_size) {
296 ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS, 296 ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
297 bdev_logical_block_size(ps->store->cow->bdev) >> 9); 297 bdev_logical_block_size(dm_snap_cow(ps->store->snap)->
298 bdev) >> 9);
298 ps->store->chunk_mask = ps->store->chunk_size - 1; 299 ps->store->chunk_mask = ps->store->chunk_size - 1;
299 ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1; 300 ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1;
300 chunk_size_supplied = 0; 301 chunk_size_supplied = 0;
@@ -497,7 +498,7 @@ static void persistent_usage(struct dm_exception_store *store,
497 struct pstore *ps = get_info(store); 498 struct pstore *ps = get_info(store);
498 499
499 *sectors_allocated = ps->next_free * store->chunk_size; 500 *sectors_allocated = ps->next_free * store->chunk_size;
500 *total_sectors = get_dev_size(store->cow->bdev); 501 *total_sectors = get_dev_size(dm_snap_cow(store->snap)->bdev);
501 502
502 /* 503 /*
503 * First chunk is the fixed header. 504 * First chunk is the fixed header.
@@ -596,7 +597,7 @@ static int persistent_prepare_exception(struct dm_exception_store *store,
596 struct pstore *ps = get_info(store); 597 struct pstore *ps = get_info(store);
597 uint32_t stride; 598 uint32_t stride;
598 chunk_t next_free; 599 chunk_t next_free;
599 sector_t size = get_dev_size(store->cow->bdev); 600 sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
600 601
601 /* Is there enough room ? */ 602 /* Is there enough room ? */
602 if (size < ((ps->next_free + 1) * store->chunk_size)) 603 if (size < ((ps->next_free + 1) * store->chunk_size))
@@ -733,8 +734,7 @@ static unsigned persistent_status(struct dm_exception_store *store,
733 case STATUSTYPE_INFO: 734 case STATUSTYPE_INFO:
734 break; 735 break;
735 case STATUSTYPE_TABLE: 736 case STATUSTYPE_TABLE:
736 DMEMIT(" %s P %llu", store->cow->name, 737 DMEMIT(" P %llu", (unsigned long long)store->chunk_size);
737 (unsigned long long)store->chunk_size);
738 } 738 }
739 739
740 return sz; 740 return sz;
diff --git a/drivers/md/dm-snap-transient.c b/drivers/md/dm-snap-transient.c
index 245a50c7337e..a0898a66a2f8 100644
--- a/drivers/md/dm-snap-transient.c
+++ b/drivers/md/dm-snap-transient.c
@@ -39,7 +39,7 @@ static int transient_prepare_exception(struct dm_exception_store *store,
39 struct dm_exception *e) 39 struct dm_exception *e)
40{ 40{
41 struct transient_c *tc = store->context; 41 struct transient_c *tc = store->context;
42 sector_t size = get_dev_size(store->cow->bdev); 42 sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
43 43
44 if (size < (tc->next_free + store->chunk_size)) 44 if (size < (tc->next_free + store->chunk_size))
45 return -1; 45 return -1;
@@ -65,7 +65,7 @@ static void transient_usage(struct dm_exception_store *store,
65 sector_t *metadata_sectors) 65 sector_t *metadata_sectors)
66{ 66{
67 *sectors_allocated = ((struct transient_c *) store->context)->next_free; 67 *sectors_allocated = ((struct transient_c *) store->context)->next_free;
68 *total_sectors = get_dev_size(store->cow->bdev); 68 *total_sectors = get_dev_size(dm_snap_cow(store->snap)->bdev);
69 *metadata_sectors = 0; 69 *metadata_sectors = 0;
70} 70}
71 71
@@ -94,8 +94,7 @@ static unsigned transient_status(struct dm_exception_store *store,
94 case STATUSTYPE_INFO: 94 case STATUSTYPE_INFO:
95 break; 95 break;
96 case STATUSTYPE_TABLE: 96 case STATUSTYPE_TABLE:
97 DMEMIT(" %s N %llu", store->cow->name, 97 DMEMIT(" N %llu", (unsigned long long)store->chunk_size);
98 (unsigned long long)store->chunk_size);
99 } 98 }
100 99
101 return sz; 100 return sz;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 8bd77cbd7e45..dc500a6f6232 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -59,6 +59,9 @@ struct dm_snapshot {
59 struct rw_semaphore lock; 59 struct rw_semaphore lock;
60 60
61 struct dm_dev *origin; 61 struct dm_dev *origin;
62 struct dm_dev *cow;
63
64 struct dm_target *ti;
62 65
63 /* List of snapshots per Origin */ 66 /* List of snapshots per Origin */
64 struct list_head list; 67 struct list_head list;
@@ -97,6 +100,12 @@ struct dm_snapshot {
97 struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; 100 struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
98}; 101};
99 102
103struct dm_dev *dm_snap_cow(struct dm_snapshot *s)
104{
105 return s->cow;
106}
107EXPORT_SYMBOL(dm_snap_cow);
108
100static struct workqueue_struct *ksnapd; 109static struct workqueue_struct *ksnapd;
101static void flush_queued_bios(struct work_struct *work); 110static void flush_queued_bios(struct work_struct *work);
102 111
@@ -558,7 +567,7 @@ static int init_hash_tables(struct dm_snapshot *s)
558 * Calculate based on the size of the original volume or 567 * Calculate based on the size of the original volume or
559 * the COW volume... 568 * the COW volume...
560 */ 569 */
561 cow_dev_size = get_dev_size(s->store->cow->bdev); 570 cow_dev_size = get_dev_size(s->cow->bdev);
562 origin_dev_size = get_dev_size(s->origin->bdev); 571 origin_dev_size = get_dev_size(s->origin->bdev);
563 max_buckets = calc_max_buckets(); 572 max_buckets = calc_max_buckets();
564 573
@@ -596,45 +605,55 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
596 struct dm_snapshot *s; 605 struct dm_snapshot *s;
597 int i; 606 int i;
598 int r = -EINVAL; 607 int r = -EINVAL;
599 char *origin_path; 608 char *origin_path, *cow_path;
600 struct dm_exception_store *store;
601 unsigned args_used; 609 unsigned args_used;
602 610
603 if (argc != 4) { 611 if (argc != 4) {
604 ti->error = "requires exactly 4 arguments"; 612 ti->error = "requires exactly 4 arguments";
605 r = -EINVAL; 613 r = -EINVAL;
606 goto bad_args; 614 goto bad;
607 } 615 }
608 616
609 origin_path = argv[0]; 617 origin_path = argv[0];
610 argv++; 618 argv++;
611 argc--; 619 argc--;
612 620
613 r = dm_exception_store_create(ti, argc, argv, &args_used, &store); 621 s = kmalloc(sizeof(*s), GFP_KERNEL);
622 if (!s) {
623 ti->error = "Cannot allocate snapshot context private "
624 "structure";
625 r = -ENOMEM;
626 goto bad;
627 }
628
629 cow_path = argv[0];
630 argv++;
631 argc--;
632
633 r = dm_get_device(ti, cow_path, 0, 0,
634 FMODE_READ | FMODE_WRITE, &s->cow);
635 if (r) {
636 ti->error = "Cannot get COW device";
637 goto bad_cow;
638 }
639
640 r = dm_exception_store_create(ti, argc, argv, s, &args_used, &s->store);
614 if (r) { 641 if (r) {
615 ti->error = "Couldn't create exception store"; 642 ti->error = "Couldn't create exception store";
616 r = -EINVAL; 643 r = -EINVAL;
617 goto bad_args; 644 goto bad_store;
618 } 645 }
619 646
620 argv += args_used; 647 argv += args_used;
621 argc -= args_used; 648 argc -= args_used;
622 649
623 s = kmalloc(sizeof(*s), GFP_KERNEL);
624 if (!s) {
625 ti->error = "Cannot allocate snapshot context private "
626 "structure";
627 r = -ENOMEM;
628 goto bad_snap;
629 }
630
631 r = dm_get_device(ti, origin_path, 0, ti->len, FMODE_READ, &s->origin); 650 r = dm_get_device(ti, origin_path, 0, ti->len, FMODE_READ, &s->origin);
632 if (r) { 651 if (r) {
633 ti->error = "Cannot get origin device"; 652 ti->error = "Cannot get origin device";
634 goto bad_origin; 653 goto bad_origin;
635 } 654 }
636 655
637 s->store = store; 656 s->ti = ti;
638 s->valid = 1; 657 s->valid = 1;
639 s->active = 0; 658 s->active = 0;
640 atomic_set(&s->pending_exceptions_count, 0); 659 atomic_set(&s->pending_exceptions_count, 0);
@@ -723,12 +742,15 @@ bad_hash_tables:
723 dm_put_device(ti, s->origin); 742 dm_put_device(ti, s->origin);
724 743
725bad_origin: 744bad_origin:
726 kfree(s); 745 dm_exception_store_destroy(s->store);
727 746
728bad_snap: 747bad_store:
729 dm_exception_store_destroy(store); 748 dm_put_device(ti, s->cow);
730 749
731bad_args: 750bad_cow:
751 kfree(s);
752
753bad:
732 return r; 754 return r;
733} 755}
734 756
@@ -777,6 +799,8 @@ static void snapshot_dtr(struct dm_target *ti)
777 799
778 dm_exception_store_destroy(s->store); 800 dm_exception_store_destroy(s->store);
779 801
802 dm_put_device(ti, s->cow);
803
780 kfree(s); 804 kfree(s);
781} 805}
782 806
@@ -839,7 +863,7 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
839 863
840 s->valid = 0; 864 s->valid = 0;
841 865
842 dm_table_event(s->store->ti->table); 866 dm_table_event(s->ti->table);
843} 867}
844 868
845static void get_pending_exception(struct dm_snap_pending_exception *pe) 869static void get_pending_exception(struct dm_snap_pending_exception *pe)
@@ -977,7 +1001,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
977 src.sector = chunk_to_sector(s->store, pe->e.old_chunk); 1001 src.sector = chunk_to_sector(s->store, pe->e.old_chunk);
978 src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector); 1002 src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector);
979 1003
980 dest.bdev = s->store->cow->bdev; 1004 dest.bdev = s->cow->bdev;
981 dest.sector = chunk_to_sector(s->store, pe->e.new_chunk); 1005 dest.sector = chunk_to_sector(s->store, pe->e.new_chunk);
982 dest.count = src.count; 1006 dest.count = src.count;
983 1007
@@ -1038,7 +1062,7 @@ __find_pending_exception(struct dm_snapshot *s,
1038static void remap_exception(struct dm_snapshot *s, struct dm_exception *e, 1062static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
1039 struct bio *bio, chunk_t chunk) 1063 struct bio *bio, chunk_t chunk)
1040{ 1064{
1041 bio->bi_bdev = s->store->cow->bdev; 1065 bio->bi_bdev = s->cow->bdev;
1042 bio->bi_sector = chunk_to_sector(s->store, 1066 bio->bi_sector = chunk_to_sector(s->store,
1043 dm_chunk_number(e->new_chunk) + 1067 dm_chunk_number(e->new_chunk) +
1044 (chunk - e->old_chunk)) + 1068 (chunk - e->old_chunk)) +
@@ -1056,7 +1080,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
1056 struct dm_snap_pending_exception *pe = NULL; 1080 struct dm_snap_pending_exception *pe = NULL;
1057 1081
1058 if (unlikely(bio_empty_barrier(bio))) { 1082 if (unlikely(bio_empty_barrier(bio))) {
1059 bio->bi_bdev = s->store->cow->bdev; 1083 bio->bi_bdev = s->cow->bdev;
1060 return DM_MAPIO_REMAPPED; 1084 return DM_MAPIO_REMAPPED;
1061 } 1085 }
1062 1086
@@ -1200,7 +1224,7 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
1200 * to make private copies if the output is to 1224 * to make private copies if the output is to
1201 * make sense. 1225 * make sense.
1202 */ 1226 */
1203 DMEMIT("%s", snap->origin->name); 1227 DMEMIT("%s %s", snap->origin->name, snap->cow->name);
1204 snap->store->type->status(snap->store, type, result + sz, 1228 snap->store->type->status(snap->store, type, result + sz,
1205 maxlen - sz); 1229 maxlen - sz);
1206 break; 1230 break;
@@ -1240,7 +1264,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
1240 goto next_snapshot; 1264 goto next_snapshot;
1241 1265
1242 /* Nothing to do if writing beyond end of snapshot */ 1266 /* Nothing to do if writing beyond end of snapshot */
1243 if (bio->bi_sector >= dm_table_get_size(snap->store->ti->table)) 1267 if (bio->bi_sector >= dm_table_get_size(snap->ti->table))
1244 goto next_snapshot; 1268 goto next_snapshot;
1245 1269
1246 /* 1270 /*