--- /dev/null
+From 1f2c6651f69c14d0d3a9cfbda44ea101b02160ba Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Sun, 11 Oct 2015 19:38:00 +0200
+Subject: rbd: don't leak parent_spec in rbd_dev_probe_parent()
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 1f2c6651f69c14d0d3a9cfbda44ea101b02160ba upstream.
+
+Currently we leak parent_spec and trigger a "parent reference
+underflow" warning if rbd_dev_create() in rbd_dev_probe_parent() fails.
+The problem is we take the !parent out_err branch and that only drops
+refcounts; parent_spec that would've been freed had we called
+rbd_dev_unparent() remains and triggers rbd_warn() in
+rbd_dev_parent_put() - at that point we have parent_spec != NULL and
+parent_ref == 0, so counter ends up being -1 after the decrement.
+
+Redo rbd_dev_probe_parent() to fix this.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+[idryomov@gmail.com: backport to < 4.2: rbd_dev->opts]
+Reviewed-by: Alex Elder <elder@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/rbd.c | 35 +++++++++++++++--------------------
+ 1 file changed, 15 insertions(+), 20 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -4834,41 +4834,36 @@ out_err:
+ static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
+ {
+ 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)
++ 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, false);
+ 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;
+ }
+
--- /dev/null
+From 6d69bb536bac0d403d83db1ca841444981b280cd Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Sun, 11 Oct 2015 19:38:00 +0200
+Subject: rbd: prevent kernel stack blow up on rbd map
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 6d69bb536bac0d403d83db1ca841444981b280cd upstream.
+
+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
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Josh Durgin <jdurgin@redhat.com>
+[idryomov@gmail.com: backport to 3.10: rbd_dev->opts, context]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/block/rbd.c | 29 +++++++++++++++++++++--------
+ 1 file changed, 21 insertions(+), 8 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -93,6 +93,8 @@ static int atomic_dec_return_safe(atomic
+
+ #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 *
+ 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[] = {
+@@ -4831,7 +4833,12 @@ 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;
+ int ret;
+@@ -4839,6 +4846,12 @@ static int rbd_dev_probe_parent(struct r
+ if (!rbd_dev->parent_spec)
+ return 0;
+
++ if (++depth > RBD_MAX_PARENT_CHAIN_LEN) {
++ pr_info("parent chain is too long (%d)\n", depth);
++ ret = -EINVAL;
++ goto out_err;
++ }
++
+ parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec);
+ if (!parent) {
+ ret = -ENOMEM;
+@@ -4852,7 +4865,7 @@ static int rbd_dev_probe_parent(struct r
+ __rbd_get_client(rbd_dev->rbd_client);
+ rbd_spec_get(rbd_dev->parent_spec);
+
+- ret = rbd_dev_image_probe(parent, false);
++ ret = rbd_dev_image_probe(parent, depth);
+ if (ret < 0)
+ goto out_err;
+
+@@ -4969,7 +4982,7 @@ static void rbd_dev_image_release(struct
+ * 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;
+@@ -4990,7 +5003,7 @@ static int rbd_dev_image_probe(struct rb
+ 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;
+@@ -5007,7 +5020,7 @@ static int rbd_dev_image_probe(struct rb
+ 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;
+
+@@ -5018,7 +5031,7 @@ static int rbd_dev_image_probe(struct rb
+ 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 "
+@@ -5089,7 +5102,7 @@ static ssize_t rbd_add(struct bus_type *
+ 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;
+
--- /dev/null
+From bae818ee1577c27356093901a0ea48f672eda514 Mon Sep 17 00:00:00 2001
+From: Ronny Hegewald <ronny.hegewald@online.de>
+Date: Thu, 15 Oct 2015 18:50:46 +0000
+Subject: rbd: require stable pages if message data CRCs are enabled
+
+From: Ronny Hegewald <ronny.hegewald@online.de>
+
+commit bae818ee1577c27356093901a0ea48f672eda514 upstream.
+
+rbd requires stable pages, as it performs a crc of the page data before
+they are send to the OSDs.
+
+But since kernel 3.9 (patch 1d1d1a767206fbe5d4c69493b7e6d2a8d08cc0a0
+"mm: only enforce stable page writes if the backing device requires
+it") it is not assumed anymore that block devices require stable pages.
+
+This patch sets the necessary flag to get stable pages back for rbd.
+
+In a ceph installation that provides multiple ext4 formatted rbd
+devices "bad crc" messages appeared regularly (ca 1 message every 1-2
+minutes on every OSD that provided the data for the rbd) in the
+OSD-logs before this patch. After this patch this messages are pretty
+much gone (only ca 1-2 / month / OSD).
+
+Signed-off-by: Ronny Hegewald <Ronny.Hegewald@online.de>
+[idryomov@gmail.com: require stable pages only in crc case, changelog]
+[idryomov@gmail.com: backport to 3.9-3.17: context]
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/rbd.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -3453,6 +3453,9 @@ static int rbd_init_disk(struct rbd_devi
+ 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;