aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r--drivers/md/dm-snap.c74
1 files changed, 49 insertions, 25 deletions
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 /*