From 4c585d826f38ff97d3a484a30eca0588c79396b4 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Wed, 4 Oct 2017 10:46:46 -0400 Subject: [PATCH] librbd: list_children should not attempt to refresh image The snap_lock is being held when this method is invoked, which can result in a deadlock. Fixes: http://tracker.ceph.com/issues/21670 Signed-off-by: Jason Dillaman --- src/librbd/api/Image.cc | 6 +----- src/librbd/internal.cc | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librbd/api/Image.cc b/src/librbd/api/Image.cc index 27049183b65..43eb592a7b6 100644 --- a/src/librbd/api/Image.cc +++ b/src/librbd/api/Image.cc @@ -54,10 +54,6 @@ int Image::list_children(I *ictx, const ParentSpec &parent_spec, PoolImageIds *pool_image_ids) { CephContext *cct = ictx->cct; - int r = ictx->state->refresh_if_required(); - if (r < 0) { - return r; - } // no children for non-layered or old format image if (!ictx->test_features(RBD_FEATURE_LAYERING, ictx->snap_lock)) { @@ -68,7 +64,7 @@ int Image::list_children(I *ictx, const ParentSpec &parent_spec, // search all pools for children depending on this snapshot librados::Rados rados(ictx->md_ctx); std::list > pools; - r = rados.pool_list2(pools); + int r = rados.pool_list2(pools); if (r < 0) { lderr(cct) << "error listing pools: " << cpp_strerror(r) << dendl; return r; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index acbe336629c..9b322997014 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -568,12 +568,17 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { CephContext *cct = ictx->cct; ldout(cct, 20) << "children flatten " << ictx->name << dendl; + int r = ictx->state->refresh_if_required(); + if (r < 0) { + return r; + } + RWLock::RLocker l(ictx->snap_lock); snap_t snap_id = ictx->get_snap_id(cls::rbd::UserSnapshotNamespace(), snap_name); ParentSpec parent_spec(ictx->md_ctx.get_id(), ictx->id, snap_id); map< pair, set > image_info; - int r = api::Image<>::list_children(ictx, parent_spec, &image_info); + r = api::Image<>::list_children(ictx, parent_spec, &image_info); if (r < 0) { return r; } @@ -645,11 +650,16 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { CephContext *cct = ictx->cct; ldout(cct, 20) << "children list " << ictx->name << dendl; + int r = ictx->state->refresh_if_required(); + if (r < 0) { + return r; + } + RWLock::RLocker l(ictx->snap_lock); ParentSpec parent_spec(ictx->md_ctx.get_id(), ictx->id, ictx->snap_id); map< pair, set > image_info; - int r = api::Image<>::list_children(ictx, parent_spec, &image_info); + r = api::Image<>::list_children(ictx, parent_spec, &image_info); if (r < 0) { return r; } -- 2.39.5