From be9d26f57443a52649c5c3d8f9034d9117ff36c5 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Tue, 14 Jul 2015 09:06:59 -0400 Subject: [PATCH] librbd: prevent concurrent image refreshes With multiple concurrent AIO requests, it's possible for multiple image refreshes to be scheduled. Signed-off-by: Jason Dillaman --- src/librbd/ImageCtx.cc | 2 +- src/librbd/ImageCtx.h | 3 +++ src/librbd/internal.cc | 32 ++++++++++++++++++++------------ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index f371658d75722..d93e149b24a82 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -88,7 +88,7 @@ public: readahead(), total_bytes_read(0), copyup_finisher(NULL), object_map(*this), aio_work_queue(NULL), op_work_queue(NULL), - asok_hook(new LibrbdAdminSocketHook(this)) + refresh_in_progress(false), asok_hook(new LibrbdAdminSocketHook(this)) { md_ctx.dup(p); data_ctx.dup(p); diff --git a/src/librbd/ImageCtx.h b/src/librbd/ImageCtx.h index 4fd1112e112d9..9e21e45493c32 100644 --- a/src/librbd/ImageCtx.h +++ b/src/librbd/ImageCtx.h @@ -136,6 +136,9 @@ namespace librbd { AioImageRequestWQ *aio_work_queue; ContextWQ *op_work_queue; + Cond refresh_cond; + bool refresh_in_progress; + // Configuration static const string METADATA_CONF_PREFIX; bool non_blocking_aio; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index a0c76070737da..763cee170dad0 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -2463,17 +2463,34 @@ reprotect_and_return_err: CephContext *cct = ictx->cct; ldout(cct, 20) << "ictx_check " << ictx << dendl; - ictx->refresh_lock.Lock(); - bool needs_refresh = ictx->last_refresh != ictx->refresh_seq; - ictx->refresh_lock.Unlock(); + bool needs_refresh = false; + int refresh_seq; + { + Mutex::Locker refresh_locker(ictx->refresh_lock); + while (ictx->refresh_in_progress) { + ictx->refresh_cond.Wait(ictx->refresh_lock); + } + + if (ictx->last_refresh != ictx->refresh_seq) { + ictx->refresh_in_progress = true; + needs_refresh = true; + refresh_seq = ictx->refresh_seq; + } + } if (needs_refresh) { int r = ictx_refresh(ictx); + + Mutex::Locker refresh_locker(ictx->refresh_lock); + ictx->refresh_in_progress = false; + ictx->refresh_cond.Signal(); + if (r < 0) { lderr(cct) << "Error re-reading rbd header: " << cpp_strerror(-r) << dendl; return r; } + ictx->last_refresh = refresh_seq; } return 0; } @@ -2524,10 +2541,6 @@ reprotect_and_return_err: ldout(cct, 20) << "ictx_refresh " << ictx << dendl; - ictx->refresh_lock.Lock(); - int refresh_seq = ictx->refresh_seq; - ictx->refresh_lock.Unlock(); - ::SnapContext new_snapc; bool new_snap = false; vector snap_names; @@ -2701,11 +2714,6 @@ reprotect_and_return_err: if (new_snap) { _flush(ictx); } - - ictx->refresh_lock.Lock(); - ictx->last_refresh = refresh_seq; - ictx->refresh_lock.Unlock(); - return 0; } -- 2.39.5