aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/rbd.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 8b6091b6d5cb..9717e20f3477 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1929,6 +1929,11 @@ static void rbd_dev_parent_put(struct rbd_device *rbd_dev)
1929 * If an image has a non-zero parent overlap, get a reference to its 1929 * If an image has a non-zero parent overlap, get a reference to its
1930 * parent. 1930 * parent.
1931 * 1931 *
1932 * We must get the reference before checking for the overlap to
1933 * coordinate properly with zeroing the parent overlap in
1934 * rbd_dev_v2_parent_info() when an image gets flattened. We
1935 * drop it again if there is no overlap.
1936 *
1932 * Returns true if the rbd device has a parent with a non-zero 1937 * Returns true if the rbd device has a parent with a non-zero
1933 * overlap and a reference for it was successfully taken, or 1938 * overlap and a reference for it was successfully taken, or
1934 * false otherwise. 1939 * false otherwise.
@@ -3782,8 +3787,26 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
3782 end = reply_buf + ret; 3787 end = reply_buf + ret;
3783 ret = -ERANGE; 3788 ret = -ERANGE;
3784 ceph_decode_64_safe(&p, end, pool_id, out_err); 3789 ceph_decode_64_safe(&p, end, pool_id, out_err);
3785 if (pool_id == CEPH_NOPOOL) 3790 if (pool_id == CEPH_NOPOOL) {
3791 /*
3792 * Either the parent never existed, or we have
3793 * record of it but the image got flattened so it no
3794 * longer has a parent. When the parent of a
3795 * layered image disappears we immediately set the
3796 * overlap to 0. The effect of this is that all new
3797 * requests will be treated as if the image had no
3798 * parent.
3799 */
3800 if (rbd_dev->parent_overlap) {
3801 rbd_dev->parent_overlap = 0;
3802 smp_mb();
3803 rbd_dev_parent_put(rbd_dev);
3804 pr_info("%s: clone image has been flattened\n",
3805 rbd_dev->disk->disk_name);
3806 }
3807
3786 goto out; /* No parent? No problem. */ 3808 goto out; /* No parent? No problem. */
3809 }
3787 3810
3788 /* The ceph file layout needs to fit pool id in 32 bits */ 3811 /* The ceph file layout needs to fit pool id in 32 bits */
3789 3812
@@ -4633,7 +4656,10 @@ static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
4633{ 4656{
4634 struct rbd_image_header *header; 4657 struct rbd_image_header *header;
4635 4658
4636 rbd_dev_parent_put(rbd_dev); 4659 /* Drop parent reference unless it's already been done (or none) */
4660
4661 if (rbd_dev->parent_overlap)
4662 rbd_dev_parent_put(rbd_dev);
4637 4663
4638 /* Free dynamic fields from the header, then zero it out */ 4664 /* Free dynamic fields from the header, then zero it out */
4639 4665