From c9142fe35372cf69b7a56f334622a775a6b7c43f Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Thu, 7 May 2015 14:17:37 -0400 Subject: [PATCH] librbd: owner_lock should be held during flush request Flush might result in the cache writing out dirty objects, which would require that the owner_lock be held. Signed-off-by: Jason Dillaman --- src/librbd/internal.cc | 51 +++++++++++++++++++++++++++--------------- src/librbd/internal.h | 2 +- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 1642df7171a..91620e5a68f 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -735,7 +735,7 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, ldout(ictx->cct, 20) << "snap_create_helper " << ictx << " " << snap_name << dendl; - int r = ictx_check(ictx); + int r = ictx_check(ictx, true); if (r < 0) { return r; } @@ -835,7 +835,7 @@ int invoke_async_request(ImageCtx *ictx, const std::string& request_type, ldout(ictx->cct, 20) << "snap_remove_helper " << ictx << " " << snap_name << dendl; - int r = ictx_check(ictx); + int r = ictx_check(ictx, true); if (r < 0) { return r; } @@ -1442,10 +1442,10 @@ reprotect_and_return_err: } } - p_imctx->md_lock.get_write(); - r = ictx_refresh(p_imctx); - p_imctx->md_lock.put_write(); - + { + RWLock::RLocker owner_locker(p_imctx->owner_lock); + r = ictx_refresh(p_imctx); + } if (r == 0) { p_imctx->snap_lock.get_read(); r = p_imctx->is_snap_protected(p_imctx->snap_id, &snap_protected); @@ -2076,7 +2076,7 @@ reprotect_and_return_err: << size << dendl; ictx->snap_lock.put_read(); - int r = ictx_check(ictx); + int r = ictx_check(ictx, true); if (r < 0) { return r; } @@ -2217,7 +2217,7 @@ reprotect_and_return_err: return 0; } - int ictx_check(ImageCtx *ictx) + int ictx_check(ImageCtx *ictx, bool owner_locked) { CephContext *cct = ictx->cct; ldout(cct, 20) << "ictx_check " << ictx << dendl; @@ -2227,9 +2227,13 @@ reprotect_and_return_err: ictx->refresh_lock.Unlock(); if (needs_refresh) { - RWLock::WLocker l(ictx->md_lock); - - int r = ictx_refresh(ictx); + int r; + if (owner_locked) { + r = ictx_refresh(ictx); + } else { + RWLock::RLocker owner_lock(ictx->owner_lock); + r = ictx_refresh(ictx); + } if (r < 0) { lderr(cct) << "Error re-reading rbd header: " << cpp_strerror(-r) << dendl; @@ -2277,6 +2281,9 @@ reprotect_and_return_err: int ictx_refresh(ImageCtx *ictx) { + assert(ictx->owner_lock.is_locked()); + RWLock::WLocker md_locker(ictx->md_lock); + CephContext *cct = ictx->cct; bufferlist bl, bl2; @@ -2790,9 +2797,10 @@ reprotect_and_return_err: } } - ictx->md_lock.get_write(); - r = ictx_refresh(ictx); - ictx->md_lock.put_write(); + { + RWLock::RLocker owner_locker(ictx->owner_lock); + r = ictx_refresh(ictx); + } if (r < 0) goto err_close; @@ -2908,7 +2916,7 @@ reprotect_and_return_err: int r; // ictx_check also updates parent data - if ((r = ictx_check(ictx)) < 0) { + if ((r = ictx_check(ictx, true)) < 0) { lderr(cct) << "ictx_check failed" << dendl; return r; } @@ -2993,7 +3001,7 @@ reprotect_and_return_err: return -EINVAL; } - int r = ictx_check(ictx); + int r = ictx_check(ictx, true); if (r < 0) { return r; } @@ -3238,7 +3246,10 @@ reprotect_and_return_err: << " len = " << len << dendl; // ensure previous writes are visible to listsnaps - _flush(ictx); + { + RWLock::RLocker owner_locker(ictx->owner_lock); + _flush(ictx); + } int r = ictx_check(ictx); if (r < 0) @@ -3689,13 +3700,17 @@ reprotect_and_return_err: } ictx->user_flushed(); - r = _flush(ictx); + { + RWLock::RLocker owner_locker(ictx->owner_lock); + r = _flush(ictx); + } ictx->perfcounter->inc(l_librbd_flush); return r; } int _flush(ImageCtx *ictx) { + assert(ictx->owner_lock.is_locked()); CephContext *cct = ictx->cct; int r; // flush any outstanding writes diff --git a/src/librbd/internal.h b/src/librbd/internal.h index a8e70b9b01d..d738bb0e915 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -117,7 +117,7 @@ namespace librbd { int add_snap(ImageCtx *ictx, const char *snap_name); int rm_snap(ImageCtx *ictx, const char *snap_name, uint64_t snap_id); int refresh_parent(ImageCtx *ictx); - int ictx_check(ImageCtx *ictx); + int ictx_check(ImageCtx *ictx, bool owner_locked=false); int ictx_refresh(ImageCtx *ictx); int copy(ImageCtx *ictx, IoCtx& dest_md_ctx, const char *destname, ProgressContext &prog_ctx);