aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 /*