| From e69b8d414f948c242ad9f3eb2b7e24fba783dbbd Mon Sep 17 00:00:00 2001 |
| From: Ilya Dryomov <idryomov@redhat.com> |
| Date: Mon, 19 Jan 2015 12:06:14 +0300 |
| Subject: rbd: drop parent_ref in rbd_dev_unprobe() unconditionally |
| |
| From: Ilya Dryomov <idryomov@redhat.com> |
| |
| commit e69b8d414f948c242ad9f3eb2b7e24fba783dbbd upstream. |
| |
| This effectively reverts the last hunk of 392a9dad7e77 ("rbd: detect |
| when clone image is flattened"). |
| |
| The problem with parent_overlap != 0 condition is that it's possible |
| and completely valid to have an image with parent_overlap == 0 whose |
| parent state needs to be cleaned up on unmap. The next commit, which |
| drops the "clone image now standalone" logic, opens up another window |
| of opportunity to hit this, but even without it |
| |
| # cat parent-ref.sh |
| #!/bin/bash |
| rbd create --image-format 2 --size 1 foo |
| rbd snap create foo@snap |
| rbd snap protect foo@snap |
| rbd clone foo@snap bar |
| rbd resize --allow-shrink --size 0 bar |
| rbd resize --size 1 bar |
| DEV=$(rbd map bar) |
| rbd unmap $DEV |
| |
| leaves rbd_device/rbd_spec/etc and rbd_client along with ceph_client |
| hanging around. |
| |
| My thinking behind calling rbd_dev_parent_put() unconditionally is that |
| there shouldn't be any requests in flight at that point in time as we |
| are deep into unmap sequence. Hence, even if rbd_dev_unparent() caused |
| by flatten is delayed by in-flight requests, it will have finished by |
| the time we reach rbd_dev_unprobe() caused by unmap, thus turning |
| unconditional rbd_dev_parent_put() into a no-op. |
| |
| Fixes: http://tracker.ceph.com/issues/10352 |
| |
| Signed-off-by: Ilya Dryomov <idryomov@redhat.com> |
| Reviewed-by: Josh Durgin <jdurgin@redhat.com> |
| Reviewed-by: Alex Elder <elder@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/block/rbd.c | 5 +---- |
| 1 file changed, 1 insertion(+), 4 deletions(-) |
| |
| --- a/drivers/block/rbd.c |
| +++ b/drivers/block/rbd.c |
| @@ -5111,10 +5111,7 @@ static void rbd_dev_unprobe(struct rbd_d |
| { |
| struct rbd_image_header *header; |
| |
| - /* Drop parent reference unless it's already been done (or none) */ |
| - |
| - if (rbd_dev->parent_overlap) |
| - rbd_dev_parent_put(rbd_dev); |
| + rbd_dev_parent_put(rbd_dev); |
| |
| /* Free dynamic fields from the header, then zero it out */ |
| |