aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorJonathan Brassow <jbrassow@redhat.com>2009-04-02 14:55:31 -0400
committerAlasdair G Kergon <agk@redhat.com>2009-04-02 14:55:31 -0400
commit493df71c6420b211a68ae82b889c1e8a5fe701be (patch)
tree2738295190c1b3c5f72d85059aae3c96f162afa6 /drivers/md
parent7513c2a761d69d2a93f17146b3563527d3618ba0 (diff)
dm exception store: introduce registry
Move exception stores into a registry. Signed-off-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-exception-store.c162
-rw-r--r--drivers/md/dm-exception-store.h19
-rw-r--r--drivers/md/dm-snap-persistent.c67
-rw-r--r--drivers/md/dm-snap-transient.c65
-rw-r--r--drivers/md/dm-snap.c41
-rw-r--r--drivers/md/dm-snap.h2
6 files changed, 307 insertions, 49 deletions
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index dccbfb0e010f..8912a3637cae 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -14,6 +14,168 @@
14 14
15#define DM_MSG_PREFIX "snapshot exception stores" 15#define DM_MSG_PREFIX "snapshot exception stores"
16 16
17static LIST_HEAD(_exception_store_types);
18static DEFINE_SPINLOCK(_lock);
19
20static struct dm_exception_store_type *__find_exception_store_type(const char *name)
21{
22 struct dm_exception_store_type *type;
23
24 list_for_each_entry(type, &_exception_store_types, list)
25 if (!strcmp(name, type->name))
26 return type;
27
28 return NULL;
29}
30
31static struct dm_exception_store_type *_get_exception_store_type(const char *name)
32{
33 struct dm_exception_store_type *type;
34
35 spin_lock(&_lock);
36
37 type = __find_exception_store_type(name);
38
39 if (type && !try_module_get(type->module))
40 type = NULL;
41
42 spin_unlock(&_lock);
43
44 return type;
45}
46
47/*
48 * get_type
49 * @type_name
50 *
51 * Attempt to retrieve the dm_exception_store_type by name. If not already
52 * available, attempt to load the appropriate module.
53 *
54 * Exstore modules are named "dm-exstore-" followed by the 'type_name'.
55 * Modules may contain multiple types.
56 * This function will first try the module "dm-exstore-<type_name>",
57 * then truncate 'type_name' on the last '-' and try again.
58 *
59 * For example, if type_name was "clustered-shared", it would search
60 * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'.
61 *
62 * 'dm-exception-store-<type_name>' is too long of a name in my
63 * opinion, which is why I've chosen to have the files
64 * containing exception store implementations be 'dm-exstore-<type_name>'.
65 * If you want your module to be autoloaded, you will follow this
66 * naming convention.
67 *
68 * Returns: dm_exception_store_type* on success, NULL on failure
69 */
70static struct dm_exception_store_type *get_type(const char *type_name)
71{
72 char *p, *type_name_dup;
73 struct dm_exception_store_type *type;
74
75 type = _get_exception_store_type(type_name);
76 if (type)
77 return type;
78
79 type_name_dup = kstrdup(type_name, GFP_KERNEL);
80 if (!type_name_dup) {
81 DMERR("No memory left to attempt load for \"%s\"", type_name);
82 return NULL;
83 }
84
85 while (request_module("dm-exstore-%s", type_name_dup) ||
86 !(type = _get_exception_store_type(type_name))) {
87 p = strrchr(type_name_dup, '-');
88 if (!p)
89 break;
90 p[0] = '\0';
91 }
92
93 if (!type)
94 DMWARN("Module for exstore type \"%s\" not found.", type_name);
95
96 kfree(type_name_dup);
97
98 return type;
99}
100
101static void put_type(struct dm_exception_store_type *type)
102{
103 spin_lock(&_lock);
104 module_put(type->module);
105 spin_unlock(&_lock);
106}
107
108int dm_exception_store_type_register(struct dm_exception_store_type *type)
109{
110 int r = 0;
111
112 spin_lock(&_lock);
113 if (!__find_exception_store_type(type->name))
114 list_add(&type->list, &_exception_store_types);
115 else
116 r = -EEXIST;
117 spin_unlock(&_lock);
118
119 return r;
120}
121EXPORT_SYMBOL(dm_exception_store_type_register);
122
123int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
124{
125 spin_lock(&_lock);
126
127 if (!__find_exception_store_type(type->name)) {
128 spin_unlock(&_lock);
129 return -EINVAL;
130 }
131
132 list_del(&type->list);
133
134 spin_unlock(&_lock);
135
136 return 0;
137}
138EXPORT_SYMBOL(dm_exception_store_type_unregister);
139
140int dm_exception_store_create(const char *type_name,
141 struct dm_exception_store **store)
142{
143 int r = 0;
144 struct dm_exception_store_type *type;
145 struct dm_exception_store *tmp_store;
146
147 tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL);
148 if (!tmp_store)
149 return -ENOMEM;
150
151 type = get_type(type_name);
152 if (!type) {
153 kfree(tmp_store);
154 return -EINVAL;
155 }
156
157 tmp_store->type = type;
158
159 r = type->ctr(tmp_store, 0, NULL);
160 if (r) {
161 put_type(type);
162 kfree(tmp_store);
163 return r;
164 }
165
166 *store = tmp_store;
167 return 0;
168}
169EXPORT_SYMBOL(dm_exception_store_create);
170
171void dm_exception_store_destroy(struct dm_exception_store *store)
172{
173 store->type->dtr(store);
174 put_type(store->type);
175 kfree(store);
176}
177EXPORT_SYMBOL(dm_exception_store_destroy);
178
17int dm_exception_store_init(void) 179int dm_exception_store_init(void)
18{ 180{
19 int r; 181 int r;
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index aed1f1172f9e..31377150080e 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -39,6 +39,9 @@ struct dm_snap_exception {
39 */ 39 */
40struct dm_exception_store; 40struct dm_exception_store;
41struct dm_exception_store_type { 41struct dm_exception_store_type {
42 const char *name;
43 struct module *module;
44
42 int (*ctr) (struct dm_exception_store *store, 45 int (*ctr) (struct dm_exception_store *store,
43 unsigned argc, char **argv); 46 unsigned argc, char **argv);
44 47
@@ -85,10 +88,13 @@ struct dm_exception_store_type {
85 void (*fraction_full) (struct dm_exception_store *store, 88 void (*fraction_full) (struct dm_exception_store *store,
86 sector_t *numerator, 89 sector_t *numerator,
87 sector_t *denominator); 90 sector_t *denominator);
91
92 /* For internal device-mapper use only. */
93 struct list_head list;
88}; 94};
89 95
90struct dm_exception_store { 96struct dm_exception_store {
91 struct dm_exception_store_type type; 97 struct dm_exception_store_type *type;
92 98
93 struct dm_snapshot *snap; 99 struct dm_snapshot *snap;
94 100
@@ -138,6 +144,13 @@ static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
138 144
139# endif 145# endif
140 146
147int dm_exception_store_type_register(struct dm_exception_store_type *type);
148int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
149
150int dm_exception_store_create(const char *type_name,
151 struct dm_exception_store **store);
152void dm_exception_store_destroy(struct dm_exception_store *store);
153
141int dm_exception_store_init(void); 154int dm_exception_store_init(void);
142void dm_exception_store_exit(void); 155void dm_exception_store_exit(void);
143 156
@@ -150,8 +163,4 @@ void dm_persistent_snapshot_exit(void);
150int dm_transient_snapshot_init(void); 163int dm_transient_snapshot_init(void);
151void dm_transient_snapshot_exit(void); 164void dm_transient_snapshot_exit(void);
152 165
153int dm_create_persistent(struct dm_exception_store *store);
154
155int dm_create_transient(struct dm_exception_store *store);
156
157#endif /* _LINUX_DM_EXCEPTION_STORE */ 166#endif /* _LINUX_DM_EXCEPTION_STORE */
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index 0bbbe3b7431e..e85b7a186a13 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -478,7 +478,7 @@ static void persistent_fraction_full(struct dm_exception_store *store,
478 *denominator = get_dev_size(store->snap->cow->bdev); 478 *denominator = get_dev_size(store->snap->cow->bdev);
479} 479}
480 480
481static void persistent_destroy(struct dm_exception_store *store) 481static void persistent_dtr(struct dm_exception_store *store)
482{ 482{
483 struct pstore *ps = get_info(store); 483 struct pstore *ps = get_info(store);
484 484
@@ -656,7 +656,8 @@ static void persistent_drop_snapshot(struct dm_exception_store *store)
656 DMWARN("write header failed"); 656 DMWARN("write header failed");
657} 657}
658 658
659int dm_create_persistent(struct dm_exception_store *store) 659static int persistent_ctr(struct dm_exception_store *store,
660 unsigned argc, char **argv)
660{ 661{
661 struct pstore *ps; 662 struct pstore *ps;
662 663
@@ -683,23 +684,69 @@ int dm_create_persistent(struct dm_exception_store *store)
683 return -ENOMEM; 684 return -ENOMEM;
684 } 685 }
685 686
686 store->type.dtr = persistent_destroy;
687 store->type.read_metadata = persistent_read_metadata;
688 store->type.prepare_exception = persistent_prepare_exception;
689 store->type.commit_exception = persistent_commit_exception;
690 store->type.drop_snapshot = persistent_drop_snapshot;
691 store->type.fraction_full = persistent_fraction_full;
692
693 store->context = ps; 687 store->context = ps;
694 688
695 return 0; 689 return 0;
696} 690}
697 691
692static int persistent_status(struct dm_exception_store *store,
693 status_type_t status, char *result,
694 unsigned int maxlen)
695{
696 int sz = 0;
697
698 return sz;
699}
700
701static struct dm_exception_store_type _persistent_type = {
702 .name = "persistent",
703 .module = THIS_MODULE,
704 .ctr = persistent_ctr,
705 .dtr = persistent_dtr,
706 .read_metadata = persistent_read_metadata,
707 .prepare_exception = persistent_prepare_exception,
708 .commit_exception = persistent_commit_exception,
709 .drop_snapshot = persistent_drop_snapshot,
710 .fraction_full = persistent_fraction_full,
711 .status = persistent_status,
712};
713
714static struct dm_exception_store_type _persistent_compat_type = {
715 .name = "P",
716 .module = THIS_MODULE,
717 .ctr = persistent_ctr,
718 .dtr = persistent_dtr,
719 .read_metadata = persistent_read_metadata,
720 .prepare_exception = persistent_prepare_exception,
721 .commit_exception = persistent_commit_exception,
722 .drop_snapshot = persistent_drop_snapshot,
723 .fraction_full = persistent_fraction_full,
724 .status = persistent_status,
725};
726
698int dm_persistent_snapshot_init(void) 727int dm_persistent_snapshot_init(void)
699{ 728{
700 return 0; 729 int r;
730
731 r = dm_exception_store_type_register(&_persistent_type);
732 if (r) {
733 DMERR("Unable to register persistent exception store type");
734 return r;
735 }
736
737 r = dm_exception_store_type_register(&_persistent_compat_type);
738 if (r) {
739 DMERR("Unable to register old-style persistent exception "
740 "store type");
741 dm_exception_store_type_unregister(&_persistent_type);
742 return r;
743 }
744
745 return r;
701} 746}
702 747
703void dm_persistent_snapshot_exit(void) 748void dm_persistent_snapshot_exit(void)
704{ 749{
750 dm_exception_store_type_unregister(&_persistent_type);
751 dm_exception_store_type_unregister(&_persistent_compat_type);
705} 752}
diff --git a/drivers/md/dm-snap-transient.c b/drivers/md/dm-snap-transient.c
index b558176ff020..51bc4a78ce9a 100644
--- a/drivers/md/dm-snap-transient.c
+++ b/drivers/md/dm-snap-transient.c
@@ -23,7 +23,7 @@ struct transient_c {
23 sector_t next_free; 23 sector_t next_free;
24}; 24};
25 25
26static void transient_destroy(struct dm_exception_store *store) 26static void transient_dtr(struct dm_exception_store *store)
27{ 27{
28 kfree(store->context); 28 kfree(store->context);
29} 29}
@@ -67,17 +67,11 @@ static void transient_fraction_full(struct dm_exception_store *store,
67 *denominator = get_dev_size(store->snap->cow->bdev); 67 *denominator = get_dev_size(store->snap->cow->bdev);
68} 68}
69 69
70int dm_create_transient(struct dm_exception_store *store) 70static int transient_ctr(struct dm_exception_store *store,
71 unsigned argc, char **argv)
71{ 72{
72 struct transient_c *tc; 73 struct transient_c *tc;
73 74
74 store->type.dtr = transient_destroy;
75 store->type.read_metadata = transient_read_metadata;
76 store->type.prepare_exception = transient_prepare_exception;
77 store->type.commit_exception = transient_commit_exception;
78 store->type.drop_snapshot = NULL;
79 store->type.fraction_full = transient_fraction_full;
80
81 tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL); 75 tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
82 if (!tc) 76 if (!tc)
83 return -ENOMEM; 77 return -ENOMEM;
@@ -88,11 +82,62 @@ int dm_create_transient(struct dm_exception_store *store)
88 return 0; 82 return 0;
89} 83}
90 84
85static int transient_status(struct dm_exception_store *store,
86 status_type_t status, char *result,
87 unsigned maxlen)
88{
89 int sz = 0;
90
91 return sz;
92}
93
94static struct dm_exception_store_type _transient_type = {
95 .name = "transient",
96 .module = THIS_MODULE,
97 .ctr = transient_ctr,
98 .dtr = transient_dtr,
99 .read_metadata = transient_read_metadata,
100 .prepare_exception = transient_prepare_exception,
101 .commit_exception = transient_commit_exception,
102 .fraction_full = transient_fraction_full,
103 .status = transient_status,
104};
105
106static struct dm_exception_store_type _transient_compat_type = {
107 .name = "N",
108 .module = THIS_MODULE,
109 .ctr = transient_ctr,
110 .dtr = transient_dtr,
111 .read_metadata = transient_read_metadata,
112 .prepare_exception = transient_prepare_exception,
113 .commit_exception = transient_commit_exception,
114 .fraction_full = transient_fraction_full,
115 .status = transient_status,
116};
117
91int dm_transient_snapshot_init(void) 118int dm_transient_snapshot_init(void)
92{ 119{
93 return 0; 120 int r;
121
122 r = dm_exception_store_type_register(&_transient_type);
123 if (r) {
124 DMWARN("Unable to register transient exception store type");
125 return r;
126 }
127
128 r = dm_exception_store_type_register(&_transient_compat_type);
129 if (r) {
130 DMWARN("Unable to register old-style transient "
131 "exception store type");
132 dm_exception_store_type_unregister(&_transient_type);
133 return r;
134 }
135
136 return r;
94} 137}
95 138
96void dm_transient_snapshot_exit(void) 139void dm_transient_snapshot_exit(void)
97{ 140{
141 dm_exception_store_type_unregister(&_transient_type);
142 dm_exception_store_type_unregister(&_transient_compat_type);
98} 143}
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index dabd58e9aafc..be698f3a4ae4 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -610,8 +610,6 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
610 if (r) 610 if (r)
611 goto bad3; 611 goto bad3;
612 612
613 s->type = persistent;
614
615 s->valid = 1; 613 s->valid = 1;
616 s->active = 0; 614 s->active = 0;
617 atomic_set(&s->pending_exceptions_count, 0); 615 atomic_set(&s->pending_exceptions_count, 0);
@@ -626,19 +624,15 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
626 goto bad3; 624 goto bad3;
627 } 625 }
628 626
629 s->store.snap = s; 627 r = dm_exception_store_create(argv[2], &s->store);
630
631 if (persistent == 'P')
632 r = dm_create_persistent(&s->store);
633 else
634 r = dm_create_transient(&s->store);
635
636 if (r) { 628 if (r) {
637 ti->error = "Couldn't create exception store"; 629 ti->error = "Couldn't create exception store";
638 r = -EINVAL; 630 r = -EINVAL;
639 goto bad4; 631 goto bad4;
640 } 632 }
641 633
634 s->store->snap = s;
635
642 r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client); 636 r = dm_kcopyd_client_create(SNAPSHOT_PAGES, &s->kcopyd_client);
643 if (r) { 637 if (r) {
644 ti->error = "Could not create kcopyd client"; 638 ti->error = "Could not create kcopyd client";
@@ -665,7 +659,8 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
665 spin_lock_init(&s->tracked_chunk_lock); 659 spin_lock_init(&s->tracked_chunk_lock);
666 660
667 /* Metadata must only be loaded into one table at once */ 661 /* Metadata must only be loaded into one table at once */
668 r = s->store.type.read_metadata(&s->store, dm_add_exception, (void *)s); 662 r = s->store->type->read_metadata(s->store, dm_add_exception,
663 (void *)s);
669 if (r < 0) { 664 if (r < 0) {
670 ti->error = "Failed to read snapshot metadata"; 665 ti->error = "Failed to read snapshot metadata";
671 goto bad_load_and_register; 666 goto bad_load_and_register;
@@ -700,7 +695,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
700 dm_kcopyd_client_destroy(s->kcopyd_client); 695 dm_kcopyd_client_destroy(s->kcopyd_client);
701 696
702 bad5: 697 bad5:
703 s->store.type.dtr(&s->store); 698 s->store->type->dtr(s->store);
704 699
705 bad4: 700 bad4:
706 exit_exception_table(&s->pending, pending_cache); 701 exit_exception_table(&s->pending, pending_cache);
@@ -725,7 +720,7 @@ static void __free_exceptions(struct dm_snapshot *s)
725 exit_exception_table(&s->pending, pending_cache); 720 exit_exception_table(&s->pending, pending_cache);
726 exit_exception_table(&s->complete, exception_cache); 721 exit_exception_table(&s->complete, exception_cache);
727 722
728 s->store.type.dtr(&s->store); 723 s->store->type->dtr(s->store);
729} 724}
730 725
731static void snapshot_dtr(struct dm_target *ti) 726static void snapshot_dtr(struct dm_target *ti)
@@ -820,8 +815,8 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
820 else if (err == -ENOMEM) 815 else if (err == -ENOMEM)
821 DMERR("Invalidating snapshot: Unable to allocate exception."); 816 DMERR("Invalidating snapshot: Unable to allocate exception.");
822 817
823 if (s->store.type.drop_snapshot) 818 if (s->store->type->drop_snapshot)
824 s->store.type.drop_snapshot(&s->store); 819 s->store->type->drop_snapshot(s->store);
825 820
826 s->valid = 0; 821 s->valid = 0;
827 822
@@ -943,8 +938,8 @@ static void copy_callback(int read_err, unsigned long write_err, void *context)
943 938
944 else 939 else
945 /* Update the metadata if we are persistent */ 940 /* Update the metadata if we are persistent */
946 s->store.type.commit_exception(&s->store, &pe->e, 941 s->store->type->commit_exception(s->store, &pe->e,
947 commit_callback, pe); 942 commit_callback, pe);
948} 943}
949 944
950/* 945/*
@@ -1010,7 +1005,7 @@ __find_pending_exception(struct dm_snapshot *s,
1010 atomic_set(&pe->ref_count, 0); 1005 atomic_set(&pe->ref_count, 0);
1011 pe->started = 0; 1006 pe->started = 0;
1012 1007
1013 if (s->store.type.prepare_exception(&s->store, &pe->e)) { 1008 if (s->store->type->prepare_exception(s->store, &pe->e)) {
1014 free_pending_exception(pe); 1009 free_pending_exception(pe);
1015 return NULL; 1010 return NULL;
1016 } 1011 }
@@ -1149,11 +1144,11 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
1149 if (!snap->valid) 1144 if (!snap->valid)
1150 snprintf(result, maxlen, "Invalid"); 1145 snprintf(result, maxlen, "Invalid");
1151 else { 1146 else {
1152 if (snap->store.type.fraction_full) { 1147 if (snap->store->type->fraction_full) {
1153 sector_t numerator, denominator; 1148 sector_t numerator, denominator;
1154 snap->store.type.fraction_full(&snap->store, 1149 snap->store->type->fraction_full(snap->store,
1155 &numerator, 1150 &numerator,
1156 &denominator); 1151 &denominator);
1157 snprintf(result, maxlen, "%llu/%llu", 1152 snprintf(result, maxlen, "%llu/%llu",
1158 (unsigned long long)numerator, 1153 (unsigned long long)numerator,
1159 (unsigned long long)denominator); 1154 (unsigned long long)denominator);
@@ -1169,9 +1164,9 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
1169 * to make private copies if the output is to 1164 * to make private copies if the output is to
1170 * make sense. 1165 * make sense.
1171 */ 1166 */
1172 snprintf(result, maxlen, "%s %s %c %llu", 1167 snprintf(result, maxlen, "%s %s %s %llu",
1173 snap->origin->name, snap->cow->name, 1168 snap->origin->name, snap->cow->name,
1174 snap->type, 1169 snap->store->type->name,
1175 (unsigned long long)snap->chunk_size); 1170 (unsigned long long)snap->chunk_size);
1176 break; 1171 break;
1177 } 1172 }
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index d9e62b43cf85..627be0f52c32 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -61,7 +61,7 @@ struct dm_snapshot {
61 spinlock_t pe_lock; 61 spinlock_t pe_lock;
62 62
63 /* The on disk metadata handler */ 63 /* The on disk metadata handler */
64 struct dm_exception_store store; 64 struct dm_exception_store *store;
65 65
66 struct dm_kcopyd_client *kcopyd_client; 66 struct dm_kcopyd_client *kcopyd_client;
67 67