diff options
author | Alex Elder <elder@inktank.com> | 2012-08-31 18:29:52 -0400 |
---|---|---|
committer | Alex Elder <elder@inktank.com> | 2012-10-01 15:30:52 -0400 |
commit | 304f68086f8206da7c5930a9cb0207c91d1983a6 (patch) | |
tree | 915bdd3d884dd36fb62acd4e761e98191d001f98 | |
parent | 3fcf2581c2c3c910aa46f6d205e502a97243ca2c (diff) |
rbd: defer registering snapshot devices
When a new snapshot is found in an rbd device's updated snapshot
context, __rbd_add_snap_dev() is called to create and insert an
entry in the rbd devices list of snapshots. In addition, a Linux
device is registered to represent the snapshot.
For version 2 rbd images, it will be undesirable to initialize the
device right away. So in anticipation of that, this patch separates
the insertion of a snapshot entry in the snaps list from the
creation of devices for those snapshots.
To do this, create a new function rbd_dev_snaps_register() which
traverses the list of snapshots and calls rbd_register_snap_dev()
on any that have not yet been registered.
Rename rbd_dev_snap_devs_update() to be rbd_dev_snaps_update()
to better reflect that only the entry in the snaps list and not
the snapshot's device is affected by the function.
For now, call rbd_dev_snaps_register() immediately after each
call to rbd_dev_snaps_update().
Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r-- | drivers/block/rbd.c | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 48901b51f648..0d812603e6d5 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -204,7 +204,9 @@ static DEFINE_SPINLOCK(rbd_dev_list_lock); | |||
204 | static LIST_HEAD(rbd_client_list); /* clients */ | 204 | static LIST_HEAD(rbd_client_list); /* clients */ |
205 | static DEFINE_SPINLOCK(rbd_client_list_lock); | 205 | static DEFINE_SPINLOCK(rbd_client_list_lock); |
206 | 206 | ||
207 | static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev); | 207 | static int rbd_dev_snaps_update(struct rbd_device *rbd_dev); |
208 | static int rbd_dev_snaps_register(struct rbd_device *rbd_dev); | ||
209 | |||
208 | static void rbd_dev_release(struct device *dev); | 210 | static void rbd_dev_release(struct device *dev); |
209 | static ssize_t rbd_snap_add(struct device *dev, | 211 | static ssize_t rbd_snap_add(struct device *dev, |
210 | struct device_attribute *attr, | 212 | struct device_attribute *attr, |
@@ -1839,7 +1841,9 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) | |||
1839 | WARN_ON(strcmp(rbd_dev->header.object_prefix, h.object_prefix)); | 1841 | WARN_ON(strcmp(rbd_dev->header.object_prefix, h.object_prefix)); |
1840 | kfree(h.object_prefix); | 1842 | kfree(h.object_prefix); |
1841 | 1843 | ||
1842 | ret = rbd_dev_snap_devs_update(rbd_dev); | 1844 | ret = rbd_dev_snaps_update(rbd_dev); |
1845 | if (!ret) | ||
1846 | ret = rbd_dev_snaps_register(rbd_dev); | ||
1843 | 1847 | ||
1844 | up_write(&rbd_dev->header_rwsem); | 1848 | up_write(&rbd_dev->header_rwsem); |
1845 | 1849 | ||
@@ -2084,10 +2088,21 @@ static struct device_type rbd_snap_device_type = { | |||
2084 | .release = rbd_snap_dev_release, | 2088 | .release = rbd_snap_dev_release, |
2085 | }; | 2089 | }; |
2086 | 2090 | ||
2091 | static bool rbd_snap_registered(struct rbd_snap *snap) | ||
2092 | { | ||
2093 | bool ret = snap->dev.type == &rbd_snap_device_type; | ||
2094 | bool reg = device_is_registered(&snap->dev); | ||
2095 | |||
2096 | rbd_assert(!ret ^ reg); | ||
2097 | |||
2098 | return ret; | ||
2099 | } | ||
2100 | |||
2087 | static void __rbd_remove_snap_dev(struct rbd_snap *snap) | 2101 | static void __rbd_remove_snap_dev(struct rbd_snap *snap) |
2088 | { | 2102 | { |
2089 | list_del(&snap->node); | 2103 | list_del(&snap->node); |
2090 | device_unregister(&snap->dev); | 2104 | if (device_is_registered(&snap->dev)) |
2105 | device_unregister(&snap->dev); | ||
2091 | } | 2106 | } |
2092 | 2107 | ||
2093 | static int rbd_register_snap_dev(struct rbd_snap *snap, | 2108 | static int rbd_register_snap_dev(struct rbd_snap *snap, |
@@ -2100,6 +2115,8 @@ static int rbd_register_snap_dev(struct rbd_snap *snap, | |||
2100 | dev->parent = parent; | 2115 | dev->parent = parent; |
2101 | dev->release = rbd_snap_dev_release; | 2116 | dev->release = rbd_snap_dev_release; |
2102 | dev_set_name(dev, "snap_%s", snap->name); | 2117 | dev_set_name(dev, "snap_%s", snap->name); |
2118 | dout("%s: registering device for snapshot %s\n", __func__, snap->name); | ||
2119 | |||
2103 | ret = device_register(dev); | 2120 | ret = device_register(dev); |
2104 | 2121 | ||
2105 | return ret; | 2122 | return ret; |
@@ -2122,11 +2139,6 @@ static struct rbd_snap *__rbd_add_snap_dev(struct rbd_device *rbd_dev, | |||
2122 | 2139 | ||
2123 | snap->size = rbd_dev->header.snap_sizes[i]; | 2140 | snap->size = rbd_dev->header.snap_sizes[i]; |
2124 | snap->id = rbd_dev->header.snapc->snaps[i]; | 2141 | snap->id = rbd_dev->header.snapc->snaps[i]; |
2125 | if (device_is_registered(&rbd_dev->dev)) { | ||
2126 | ret = rbd_register_snap_dev(snap, &rbd_dev->dev); | ||
2127 | if (ret < 0) | ||
2128 | goto err; | ||
2129 | } | ||
2130 | 2142 | ||
2131 | return snap; | 2143 | return snap; |
2132 | 2144 | ||
@@ -2149,7 +2161,7 @@ err: | |||
2149 | * snapshot id, highest id first. (Snapshots in the rbd_dev's list | 2161 | * snapshot id, highest id first. (Snapshots in the rbd_dev's list |
2150 | * are also maintained in that order.) | 2162 | * are also maintained in that order.) |
2151 | */ | 2163 | */ |
2152 | static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev) | 2164 | static int rbd_dev_snaps_update(struct rbd_device *rbd_dev) |
2153 | { | 2165 | { |
2154 | struct ceph_snap_context *snapc = rbd_dev->header.snapc; | 2166 | struct ceph_snap_context *snapc = rbd_dev->header.snapc; |
2155 | const u32 snap_count = snapc->num_snaps; | 2167 | const u32 snap_count = snapc->num_snaps; |
@@ -2236,6 +2248,31 @@ static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev) | |||
2236 | return 0; | 2248 | return 0; |
2237 | } | 2249 | } |
2238 | 2250 | ||
2251 | /* | ||
2252 | * Scan the list of snapshots and register the devices for any that | ||
2253 | * have not already been registered. | ||
2254 | */ | ||
2255 | static int rbd_dev_snaps_register(struct rbd_device *rbd_dev) | ||
2256 | { | ||
2257 | struct rbd_snap *snap; | ||
2258 | int ret = 0; | ||
2259 | |||
2260 | dout("%s called\n", __func__); | ||
2261 | if (!device_is_registered(&rbd_dev->dev)) | ||
2262 | return 0; | ||
2263 | |||
2264 | list_for_each_entry(snap, &rbd_dev->snaps, node) { | ||
2265 | if (!rbd_snap_registered(snap)) { | ||
2266 | ret = rbd_register_snap_dev(snap, &rbd_dev->dev); | ||
2267 | if (ret < 0) | ||
2268 | break; | ||
2269 | } | ||
2270 | } | ||
2271 | dout("%s: returning %d\n", __func__, ret); | ||
2272 | |||
2273 | return ret; | ||
2274 | } | ||
2275 | |||
2239 | static int rbd_bus_add_dev(struct rbd_device *rbd_dev) | 2276 | static int rbd_bus_add_dev(struct rbd_device *rbd_dev) |
2240 | { | 2277 | { |
2241 | struct device *dev; | 2278 | struct device *dev; |
@@ -2585,7 +2622,10 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
2585 | goto err_out_bus; | 2622 | goto err_out_bus; |
2586 | 2623 | ||
2587 | /* no need to lock here, as rbd_dev is not registered yet */ | 2624 | /* no need to lock here, as rbd_dev is not registered yet */ |
2588 | rc = rbd_dev_snap_devs_update(rbd_dev); | 2625 | rc = rbd_dev_snaps_update(rbd_dev); |
2626 | if (rc) | ||
2627 | goto err_out_bus; | ||
2628 | rc = rbd_dev_snaps_register(rbd_dev); | ||
2589 | if (rc) | 2629 | if (rc) |
2590 | goto err_out_bus; | 2630 | goto err_out_bus; |
2591 | 2631 | ||