diff options
author | Mike Snitzer <snitzer@redhat.com> | 2009-12-10 18:52:12 -0500 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2009-12-10 18:52:12 -0500 |
commit | fc56f6fbcca3672c63c93c65f45105faacfc13cb (patch) | |
tree | f50f42a461ef33f8617fbdb781879e6ae77b62c4 /drivers/md/dm-snap.c | |
parent | 985903bb3a6d98623360ab6c855417f638840029 (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>
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r-- | drivers/md/dm-snap.c | 74 |
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 | ||
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 | static struct workqueue_struct *ksnapd; | 109 | static struct workqueue_struct *ksnapd; |
101 | static void flush_queued_bios(struct work_struct *work); | 110 | static 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 | ||
725 | bad_origin: | 744 | bad_origin: |
726 | kfree(s); | 745 | dm_exception_store_destroy(s->store); |
727 | 746 | ||
728 | bad_snap: | 747 | bad_store: |
729 | dm_exception_store_destroy(store); | 748 | dm_put_device(ti, s->cow); |
730 | 749 | ||
731 | bad_args: | 750 | bad_cow: |
751 | kfree(s); | ||
752 | |||
753 | bad: | ||
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 | ||
845 | static void get_pending_exception(struct dm_snap_pending_exception *pe) | 869 | static 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, | |||
1038 | static void remap_exception(struct dm_snapshot *s, struct dm_exception *e, | 1062 | static 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 | /* |