diff options
author | Kevin Hilman <khilman@linaro.org> | 2015-11-10 17:21:38 -0800 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2015-11-10 17:21:38 -0800 |
commit | 4a1f99f55c4c78fd11a92dc83d9a6fa2a40d2215 (patch) | |
tree | b8641265314b7d716bc459120f3dc34f30d5e08a /drivers/block | |
parent | 38f4c09779a2d66df53abed78a77539d765aff59 (diff) | |
parent | bdf8cfb859e9cd265ec1696d9e007fac66e7aea7 (diff) |
Merge tag 'v3.10.93' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into linux-linaro-lsk-v3.10
This is the 3.10.93 stable release
# gpg: Signature made Mon Nov 9 10:13:39 2015 PST using RSA key ID 6092693E
# gpg: Good signature from "Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>"
* tag 'v3.10.93' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable: (24 commits)
Linux 3.10.93
xen: fix backport of previous kexec patch
IB/cm: Fix rb-tree duplicate free and use-after-free
mvsas: Fix NULL pointer dereference in mvs_slot_task_free
md/raid10: submit_bio_wait() returns 0 on success
md/raid1: submit_bio_wait() returns 0 on success
crypto: api - Only abort operations on fatal signal
module: Fix locking in symbol_put_addr()
xen-blkfront: check for null drvdata in blkback_changed (XenbusStateClosing)
xhci: handle no ping response error properly
dm btree: fix leak of bufio-backed block in btree_split_beneath error path
dm btree remove: fix a bug when rebalancing nodes after removal
Revert "ARM64: unwind: Fix PC calculation"
rbd: prevent kernel stack blow up on rbd map
rbd: don't leak parent_spec in rbd_dev_probe_parent()
rbd: require stable pages if message data CRCs are enabled
drm/nouveau/gem: return only valid domain when there's only one
mm: make sendfile(2) killable
ASoC: wm8904: Correct number of EQ registers
powerpc/rtas: Validate rtas.entry before calling enter_rtas()
...
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/rbd.c | 67 | ||||
-rw-r--r-- | drivers/block/xen-blkfront.c | 3 |
2 files changed, 41 insertions, 29 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 2fa22c24fa5d..85b31ba9d503 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -93,6 +93,8 @@ static int atomic_dec_return_safe(atomic_t *v) #define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */ +#define RBD_MAX_PARENT_CHAIN_LEN 16 + #define RBD_SNAP_DEV_NAME_PREFIX "snap_" #define RBD_MAX_SNAP_NAME_LEN \ (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) @@ -394,7 +396,7 @@ static ssize_t rbd_add(struct bus_type *bus, const char *buf, size_t count); static ssize_t rbd_remove(struct bus_type *bus, const char *buf, size_t count); -static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping); +static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth); static void rbd_spec_put(struct rbd_spec *spec); static struct bus_attribute rbd_bus_attrs[] = { @@ -3453,6 +3455,9 @@ static int rbd_init_disk(struct rbd_device *rbd_dev) blk_queue_io_opt(q, segment_size); blk_queue_merge_bvec(q, rbd_merge_bvec); + if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC)) + q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES; + disk->queue = q; q->queuedata = rbd_dev; @@ -4828,44 +4833,50 @@ out_err: return ret; } -static int rbd_dev_probe_parent(struct rbd_device *rbd_dev) +/* + * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() -> + * rbd_dev_image_probe() recursion depth, which means it's also the + * length of the already discovered part of the parent chain. + */ +static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth) { struct rbd_device *parent = NULL; - struct rbd_spec *parent_spec; - struct rbd_client *rbdc; int ret; if (!rbd_dev->parent_spec) return 0; - /* - * We need to pass a reference to the client and the parent - * spec when creating the parent rbd_dev. Images related by - * parent/child relationships always share both. - */ - parent_spec = rbd_spec_get(rbd_dev->parent_spec); - rbdc = __rbd_get_client(rbd_dev->rbd_client); - ret = -ENOMEM; - parent = rbd_dev_create(rbdc, parent_spec); - if (!parent) + if (++depth > RBD_MAX_PARENT_CHAIN_LEN) { + pr_info("parent chain is too long (%d)\n", depth); + ret = -EINVAL; goto out_err; + } - ret = rbd_dev_image_probe(parent, false); + parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec); + if (!parent) { + ret = -ENOMEM; + goto out_err; + } + + /* + * Images related by parent/child relationships always share + * rbd_client and spec/parent_spec, so bump their refcounts. + */ + __rbd_get_client(rbd_dev->rbd_client); + rbd_spec_get(rbd_dev->parent_spec); + + ret = rbd_dev_image_probe(parent, depth); if (ret < 0) goto out_err; + rbd_dev->parent = parent; atomic_set(&rbd_dev->parent_ref, 1); - return 0; + out_err: - if (parent) { - rbd_dev_unparent(rbd_dev); + rbd_dev_unparent(rbd_dev); + if (parent) rbd_dev_destroy(parent); - } else { - rbd_put_client(rbdc); - rbd_spec_put(parent_spec); - } - return ret; } @@ -4971,7 +4982,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev) * parent), initiate a watch on its header object before using that * object to get detailed information about the rbd image. */ -static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) +static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth) { int ret; int tmp; @@ -4992,7 +5003,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) if (ret) goto err_out_format; - if (mapping) { + if (!depth) { ret = rbd_dev_header_watch_sync(rbd_dev, true); if (ret) goto out_header_name; @@ -5009,7 +5020,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) if (ret) goto err_out_probe; - ret = rbd_dev_probe_parent(rbd_dev); + ret = rbd_dev_probe_parent(rbd_dev, depth); if (ret) goto err_out_probe; @@ -5020,7 +5031,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping) err_out_probe: rbd_dev_unprobe(rbd_dev); err_out_watch: - if (mapping) { + if (!depth) { tmp = rbd_dev_header_watch_sync(rbd_dev, false); if (tmp) rbd_warn(rbd_dev, "unable to tear down " @@ -5091,7 +5102,7 @@ static ssize_t rbd_add(struct bus_type *bus, rbdc = NULL; /* rbd_dev now owns this */ spec = NULL; /* rbd_dev now owns this */ - rc = rbd_dev_image_probe(rbd_dev, true); + rc = rbd_dev_image_probe(rbd_dev, 0); if (rc < 0) goto err_out_rbd_dev; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index ddd9a098bc67..ea7ed8600a7c 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1590,7 +1590,8 @@ static void blkback_changed(struct xenbus_device *dev, break; /* Missed the backend's Closing state -- fallthrough */ case XenbusStateClosing: - blkfront_closing(info); + if (info) + blkfront_closing(info); break; } } |