Mapping an image with a long parent chain (e.g. image foo, whose parent is bar, whose parent is baz, etc) currently leads to a kernel stack overflow, due to the following recursion in the reply path: rbd_osd_req_callback() rbd_obj_request_complete() rbd_img_obj_callback() rbd_img_parent_read_callback() rbd_obj_request_complete() ... Limit the parent chain to 16 images, which is ~5K worth of stack. When the above recursion is eliminated, this limit can be lifted. Fixes: http://tracker.ceph.com/issues/12538
Unified · Split
| @@ -96,6 +96,8 @@ static int atomic_dec_return_safe(atomic_t *v) · 95 unmodified lines | |||
| 96 | #define RBD_MINORS_PER_MAJOR 256 | 96 | #define RBD_MINORS_PER_MAJOR 256 |
| 97 | #define RBD_SINGLE_MAJOR_PART_SHIFT 4 | 97 | #define RBD_SINGLE_MAJOR_PART_SHIFT 4 |
| 98 | 98 | ||
| 99 | #define RBD_MAX_PARENT_CHAIN_LEN 16 | ||
| 100 | |||
| 99 | #define RBD_SNAP_DEV_NAME_PREFIX "snap_" | 101 | #define RBD_SNAP_DEV_NAME_PREFIX "snap_" |
| 100 | #define RBD_MAX_SNAP_NAME_LEN \ | 102 | #define RBD_MAX_SNAP_NAME_LEN \ |
| 101 | (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) | 103 | (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) |
| @@ -426,7 +428,7 @@ static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf, · 324 unmodified lines | |||
| 426 | size_t count); | 428 | size_t count); |
| 427 | static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf, | 429 | static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf, |
| 428 | size_t count); | 430 | size_t count); |
| 429 | static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping); | 431 | static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth); |
| 430 | static void rbd_spec_put(struct rbd_spec *spec); | 432 | static void rbd_spec_put(struct rbd_spec *spec); |
| 431 | 433 | ||
| 432 | static int rbd_dev_id_to_minor(int dev_id) | 434 | static int rbd_dev_id_to_minor(int dev_id) |
| @@ -5131,7 +5133,12 @@ out_err: · 4698 unmodified lines | |||
| 5131 | return ret; | 5133 | return ret; |
| 5132 | } | 5134 | } |
| 5133 | 5135 | ||
| 5134 | static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) | 5136 | /* |
| 5137 | * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() -> | ||
| 5138 | * rbd_dev_image_probe() recursion depth, which means it's also the | ||
| 5139 | * length of the already discovered part of the parent chain. | ||
| 5140 | */ | ||
| 5141 | static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth) | ||
| 5135 | { | 5142 | { |
| 5136 | struct rbd_device *parent = NULL; | 5143 | struct rbd_device *parent = NULL; |
| 5137 | int ret; | 5144 | int ret; |
| @@ -5139,6 +5146,12 @@ static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) · 1 unmodified line | |||
| 5139 | if (!rbd_dev->parent_spec) | 5146 | if (!rbd_dev->parent_spec) |
| 5140 | return 0; | 5147 | return 0; |
| 5141 | 5148 | ||
| 5149 | if (++depth > RBD_MAX_PARENT_CHAIN_LEN) { | ||
| 5150 | pr_info("parent chain is too long (%d)\n", depth); | ||
| 5151 | ret = -EINVAL; | ||
| 5152 | goto out_err; | ||
| 5153 | } | ||
| 5154 | |||
| 5142 | parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec, | 5155 | parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec, |
| 5143 | NULL); | 5156 | NULL); |
| 5144 | if (!parent) { | 5157 | if (!parent) { |
| @@ -5153,7 +5166,7 @@ static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) · 8 unmodified lines | |||
| 5153 | __rbd_get_client(rbd_dev->rbd_client); | 5166 | __rbd_get_client(rbd_dev->rbd_client); |
| 5154 | rbd_spec_get(rbd_dev->parent_spec); | 5167 | rbd_spec_get(rbd_dev->parent_spec); |
| 5155 | 5168 | ||
| 5156 | ret = rbd_dev_image_probe(parent, false); | 5169 | ret = rbd_dev_image_probe(parent, depth); |
| 5157 | if (ret < 0) | 5170 | if (ret < 0) |
| 5158 | goto out_err; | 5171 | goto out_err; |
| 5159 | 5172 | ||
| @@ -5282,7 +5295,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev) · 122 unmodified lines | |||
| 5282 | * parent), initiate a watch on its header object before using that | 5295 | * parent), initiate a watch on its header object before using that |
| 5283 | * object to get detailed information about the rbd image. | 5296 | * object to get detailed information about the rbd image. |
| 5284 | */ | 5297 | */ |
| 5285 | static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) | 5298 | static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) |
| 5286 | { | 5299 | { |
| 5287 | int ret; | 5300 | int ret; |
| 5288 | 5301 | ||
| @@ -5300,7 +5313,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 11 unmodified lines | |||
| 5300 | if (ret) | 5313 | if (ret) |
| 5301 | goto err_out_format; | 5314 | goto err_out_format; |
| 5302 | 5315 | ||
| 5303 | if (mapping) { | 5316 | if (!depth) { |
| 5304 | ret = rbd_dev_header_watch_sync(rbd_dev); | 5317 | ret = rbd_dev_header_watch_sync(rbd_dev); |
| 5305 | if (ret) { | 5318 | if (ret) { |
| 5306 | if (ret == -ENOENT) | 5319 | if (ret == -ENOENT) |
| @@ -5321,7 +5334,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 14 unmodified lines | |||
| 5321 | * Otherwise this is a parent image, identified by pool, image | 5334 | * Otherwise this is a parent image, identified by pool, image |
| 5322 | * and snap ids - need to fill in names for those ids. | 5335 | * and snap ids - need to fill in names for those ids. |
| 5323 | */ | 5336 | */ |
| 5324 | if (mapping) | 5337 | if (!depth) |
| 5325 | ret = rbd_spec_fill_snap_id(rbd_dev); | 5338 | ret = rbd_spec_fill_snap_id(rbd_dev); |
| 5326 | else | 5339 | else |
| 5327 | ret = rbd_spec_fill_names(rbd_dev); | 5340 | ret = rbd_spec_fill_names(rbd_dev); |
| @@ -5343,12 +5356,12 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 15 unmodified lines | |||
| 5343 | * Need to warn users if this image is the one being | 5356 | * Need to warn users if this image is the one being |
| 5344 | * mapped and has a parent. | 5357 | * mapped and has a parent. |
| 5345 | */ | 5358 | */ |
| 5346 | if (mapping && rbd_dev->parent_spec) | 5359 | if (!depth && rbd_dev->parent_spec) |
| 5347 | rbd_warn(rbd_dev, | 5360 | rbd_warn(rbd_dev, |
| 5348 | "WARNING: kernel layering is EXPERIMENTAL!"); | 5361 | "WARNING: kernel layering is EXPERIMENTAL!"); |
| 5349 | } | 5362 | } |
| 5350 | 5363 | ||
| 5351 | ret = rbd_dev_probe_parent(rbd_dev); | 5364 | ret = rbd_dev_probe_parent(rbd_dev, depth); |
| 5352 | if (ret) | 5365 | if (ret) |
| 5353 | goto err_out_probe; | 5366 | goto err_out_probe; |
| 5354 | 5367 | ||
| @@ -5359,7 +5372,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) · 4 unmodified lines | |||
| 5359 | err_out_probe: | 5372 | err_out_probe: |
| 5360 | rbd_dev_unprobe(rbd_dev); | 5373 | rbd_dev_unprobe(rbd_dev); |
| 5361 | err_out_watch: | 5374 | err_out_watch: |
| 5362 | if (mapping) | 5375 | if (!depth) |
| 5363 | rbd_dev_header_unwatch_sync(rbd_dev); | 5376 | rbd_dev_header_unwatch_sync(rbd_dev); |
| 5364 | out_header_name: | 5377 | out_header_name: |
| 5365 | kfree(rbd_dev->header_name); | 5378 | kfree(rbd_dev->header_name); |
| @@ -5422,7 +5435,7 @@ static ssize_t do_rbd_add(struct bus_type *bus, · 56 unmodified lines | |||
| 5422 | spec = NULL; /* rbd_dev now owns this */ | 5435 | spec = NULL; /* rbd_dev now owns this */ |
| 5423 | rbd_opts = NULL; /* rbd_dev now owns this */ | 5436 | rbd_opts = NULL; /* rbd_dev now owns this */ |
| 5424 | 5437 | ||
| 5425 | rc = rbd_dev_image_probe(rbd_dev, true); | 5438 | rc = rbd_dev_image_probe(rbd_dev, 0); |
| 5426 | if (rc < 0) | 5439 | if (rc < 0) |
| 5427 | goto err_out_rbd_dev; | 5440 | goto err_out_rbd_dev; |
| 5428 | 5441 | ||