Commit fc56f6fbcca3672c63c93c65f45105faacfc13cb

Authored by Mike Snitzer
Committed by Alasdair G Kergon
1 parent 985903bb3a

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>

Showing 5 changed files with 78 additions and 57 deletions Side-by-side Diff

drivers/md/dm-exception-store.c
... ... @@ -172,7 +172,8 @@
172 172 }
173 173  
174 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 177 *error = "Chunk size is not a multiple of device blocksize";
177 178 return -EINVAL;
178 179 }
... ... @@ -190,6 +191,7 @@
190 191 }
191 192  
192 193 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
  194 + struct dm_snapshot *snap,
193 195 unsigned *args_used,
194 196 struct dm_exception_store **store)
195 197 {
... ... @@ -198,7 +200,7 @@
198 200 struct dm_exception_store *tmp_store;
199 201 char persistent;
200 202  
201   - if (argc < 3) {
  203 + if (argc < 2) {
202 204 ti->error = "Insufficient exception store arguments";
203 205 return -EINVAL;
204 206 }
... ... @@ -209,7 +211,7 @@
209 211 return -ENOMEM;
210 212 }
211 213  
212   - persistent = toupper(*argv[1]);
  214 + persistent = toupper(*argv[0]);
213 215 if (persistent == 'P')
214 216 type = get_type("P");
215 217 else if (persistent == 'N')
216 218  
217 219  
218 220  
219 221  
220 222  
... ... @@ -227,32 +229,23 @@
227 229 }
228 230  
229 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,
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);
  234 + r = set_chunk_size(tmp_store, argv[1], &ti->error);
240 235 if (r)
241   - goto bad_ctr;
  236 + goto bad;
242 237  
243 238 r = type->ctr(tmp_store, 0, NULL);
244 239 if (r) {
245 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 245 *store = tmp_store;
251 246 return 0;
252 247  
253   -bad_ctr:
254   - dm_put_device(ti, tmp_store->cow);
255   -bad_cow:
  248 +bad:
256 249 put_type(type);
257 250 bad_type:
258 251 kfree(tmp_store);
... ... @@ -263,7 +256,6 @@
263 256 void dm_exception_store_destroy(struct dm_exception_store *store)
264 257 {
265 258 store->type->dtr(store);
266   - dm_put_device(store->ti, store->cow);
267 259 put_type(store->type);
268 260 kfree(store);
269 261 }
drivers/md/dm-exception-store.h
... ... @@ -94,12 +94,12 @@
94 94 struct list_head list;
95 95 };
96 96  
  97 +struct dm_snapshot;
  98 +
97 99 struct dm_exception_store {
98 100 struct dm_exception_store_type *type;
99   - struct dm_target *ti;
  101 + struct dm_snapshot *snap;
100 102  
101   - struct dm_dev *cow;
102   -
103 103 /* Size of data blocks saved - must be a power of 2 */
104 104 unsigned chunk_size;
105 105 unsigned chunk_mask;
... ... @@ -109,6 +109,11 @@
109 109 };
110 110  
111 111 /*
  112 + * Obtain the cow device used by a given snapshot.
  113 + */
  114 +struct dm_dev *dm_snap_cow(struct dm_snapshot *snap);
  115 +
  116 +/*
112 117 * Funtions to manipulate consecutive chunks
113 118 */
114 119 # if defined(CONFIG_LBDAF) || (BITS_PER_LONG == 64)
... ... @@ -173,6 +178,7 @@
173 178 char **error);
174 179  
175 180 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
  181 + struct dm_snapshot *snap,
176 182 unsigned *args_used,
177 183 struct dm_exception_store **store);
178 184 void dm_exception_store_destroy(struct dm_exception_store *store);
drivers/md/dm-snap-persistent.c
... ... @@ -214,7 +214,7 @@
214 214 int metadata)
215 215 {
216 216 struct dm_io_region where = {
217   - .bdev = ps->store->cow->bdev,
  217 + .bdev = dm_snap_cow(ps->store->snap)->bdev,
218 218 .sector = ps->store->chunk_size * chunk,
219 219 .count = ps->store->chunk_size,
220 220 };
... ... @@ -294,7 +294,8 @@
294 294 */
295 295 if (!ps->store->chunk_size) {
296 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 299 ps->store->chunk_mask = ps->store->chunk_size - 1;
299 300 ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1;
300 301 chunk_size_supplied = 0;
... ... @@ -497,7 +498,7 @@
497 498 struct pstore *ps = get_info(store);
498 499  
499 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 504 * First chunk is the fixed header.
... ... @@ -596,7 +597,7 @@
596 597 struct pstore *ps = get_info(store);
597 598 uint32_t stride;
598 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 602 /* Is there enough room ? */
602 603 if (size < ((ps->next_free + 1) * store->chunk_size))
... ... @@ -733,8 +734,7 @@
733 734 case STATUSTYPE_INFO:
734 735 break;
735 736 case STATUSTYPE_TABLE:
736   - DMEMIT(" %s P %llu", store->cow->name,
737   - (unsigned long long)store->chunk_size);
  737 + DMEMIT(" P %llu", (unsigned long long)store->chunk_size);
738 738 }
739 739  
740 740 return sz;
drivers/md/dm-snap-transient.c
... ... @@ -39,7 +39,7 @@
39 39 struct dm_exception *e)
40 40 {
41 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 44 if (size < (tc->next_free + store->chunk_size))
45 45 return -1;
... ... @@ -65,7 +65,7 @@
65 65 sector_t *metadata_sectors)
66 66 {
67 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 69 *metadata_sectors = 0;
70 70 }
71 71  
... ... @@ -94,8 +94,7 @@
94 94 case STATUSTYPE_INFO:
95 95 break;
96 96 case STATUSTYPE_TABLE:
97   - DMEMIT(" %s N %llu", store->cow->name,
98   - (unsigned long long)store->chunk_size);
  97 + DMEMIT(" N %llu", (unsigned long long)store->chunk_size);
99 98 }
100 99  
101 100 return sz;
drivers/md/dm-snap.c
... ... @@ -59,7 +59,10 @@
59 59 struct rw_semaphore lock;
60 60  
61 61 struct dm_dev *origin;
  62 + struct dm_dev *cow;
62 63  
  64 + struct dm_target *ti;
  65 +
63 66 /* List of snapshots per Origin */
64 67 struct list_head list;
65 68  
... ... @@ -97,6 +100,12 @@
97 100 struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
98 101 };
99 102  
  103 +struct dm_dev *dm_snap_cow(struct dm_snapshot *s)
  104 +{
  105 + return s->cow;
  106 +}
  107 +EXPORT_SYMBOL(dm_snap_cow);
  108 +
100 109 static struct workqueue_struct *ksnapd;
101 110 static void flush_queued_bios(struct work_struct *work);
102 111  
... ... @@ -558,7 +567,7 @@
558 567 * Calculate based on the size of the original volume or
559 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 571 origin_dev_size = get_dev_size(s->origin->bdev);
563 572 max_buckets = calc_max_buckets();
564 573  
565 574  
566 575  
567 576  
568 577  
569 578  
570 579  
... ... @@ -596,45 +605,55 @@
596 605 struct dm_snapshot *s;
597 606 int i;
598 607 int r = -EINVAL;
599   - char *origin_path;
600   - struct dm_exception_store *store;
  608 + char *origin_path, *cow_path;
601 609 unsigned args_used;
602 610  
603 611 if (argc != 4) {
604 612 ti->error = "requires exactly 4 arguments";
605 613 r = -EINVAL;
606   - goto bad_args;
  614 + goto bad;
607 615 }
608 616  
609 617 origin_path = argv[0];
610 618 argv++;
611 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);
614 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);
  641 + if (r) {
615 642 ti->error = "Couldn't create exception store";
616 643 r = -EINVAL;
617   - goto bad_args;
  644 + goto bad_store;
618 645 }
619 646  
620 647 argv += args_used;
621 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 650 r = dm_get_device(ti, origin_path, 0, ti->len, FMODE_READ, &s->origin);
632 651 if (r) {
633 652 ti->error = "Cannot get origin device";
634 653 goto bad_origin;
635 654 }
636 655  
637   - s->store = store;
  656 + s->ti = ti;
638 657 s->valid = 1;
639 658 s->active = 0;
640 659 atomic_set(&s->pending_exceptions_count, 0);
641 660  
642 661  
... ... @@ -723,12 +742,15 @@
723 742 dm_put_device(ti, s->origin);
724 743  
725 744 bad_origin:
726   - kfree(s);
  745 + dm_exception_store_destroy(s->store);
727 746  
728   -bad_snap:
729   - dm_exception_store_destroy(store);
  747 +bad_store:
  748 + dm_put_device(ti, s->cow);
730 749  
731   -bad_args:
  750 +bad_cow:
  751 + kfree(s);
  752 +
  753 +bad:
732 754 return r;
733 755 }
734 756  
... ... @@ -777,6 +799,8 @@
777 799  
778 800 dm_exception_store_destroy(s->store);
779 801  
  802 + dm_put_device(ti, s->cow);
  803 +
780 804 kfree(s);
781 805 }
782 806  
... ... @@ -839,7 +863,7 @@
839 863  
840 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  
845 869 static void get_pending_exception(struct dm_snap_pending_exception *pe)
... ... @@ -977,7 +1001,7 @@
977 1001 src.sector = chunk_to_sector(s->store, pe->e.old_chunk);
978 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 1005 dest.sector = chunk_to_sector(s->store, pe->e.new_chunk);
982 1006 dest.count = src.count;
983 1007  
... ... @@ -1038,7 +1062,7 @@
1038 1062 static void remap_exception(struct dm_snapshot *s, struct dm_exception *e,
1039 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 1066 bio->bi_sector = chunk_to_sector(s->store,
1043 1067 dm_chunk_number(e->new_chunk) +
1044 1068 (chunk - e->old_chunk)) +
... ... @@ -1056,7 +1080,7 @@
1056 1080 struct dm_snap_pending_exception *pe = NULL;
1057 1081  
1058 1082 if (unlikely(bio_empty_barrier(bio))) {
1059   - bio->bi_bdev = s->store->cow->bdev;
  1083 + bio->bi_bdev = s->cow->bdev;
1060 1084 return DM_MAPIO_REMAPPED;
1061 1085 }
1062 1086  
... ... @@ -1200,7 +1224,7 @@
1200 1224 * to make private copies if the output is to
1201 1225 * make sense.
1202 1226 */
1203   - DMEMIT("%s", snap->origin->name);
  1227 + DMEMIT("%s %s", snap->origin->name, snap->cow->name);
1204 1228 snap->store->type->status(snap->store, type, result + sz,
1205 1229 maxlen - sz);
1206 1230 break;
... ... @@ -1240,7 +1264,7 @@
1240 1264 goto next_snapshot;
1241 1265  
1242 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 1268 goto next_snapshot;
1245 1269  
1246 1270 /*