summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Durgin <josh.durgin@dreamhost.com>2012-04-23 23:46:51 -0700
committerJosh Durgin <josh.durgin@dreamhost.com>2012-04-24 08:57:31 -0700
commit7add136f907876a20aa2a68297c66b8259afd9a7 (patch)
treefbf19313f80f0769baf450daedf92d4a1fddd21d
parent3ef3ab8a15b4a80a340ac6039f395738223df759 (diff)
downloadceph-7add136f907876a20aa2a68297c66b8259afd9a7.tar.gz
librbd: reset needs_refresh flag before re-reading header
This way we can't miss an update if we get a notify during ictx_refresh. Specifically, a race like this: Thread 1 Thread 2 Process 2 ictx_refresh() read_header() snap_create() notify() need_refresh = true process header... need_refresh = false If this happened, we would not re-read the header with the new snapshot, so the snapshot would not happen at the intended point in time, but only after we re-read the header again. Signed-off-by: Josh Durgin <josh.durgin@dreamhost.com>
-rw-r--r--src/librbd.cc11
1 files changed, 7 insertions, 4 deletions
diff --git a/src/librbd.cc b/src/librbd.cc
index 22789e0dead..ec538151454 100644
--- a/src/librbd.cc
+++ b/src/librbd.cc
@@ -1192,6 +1192,10 @@ int ictx_refresh(ImageCtx *ictx)
ldout(cct, 20) << "ictx_refresh " << ictx << dendl;
+ ictx->refresh_lock.Lock();
+ ictx->needs_refresh = false;
+ ictx->refresh_lock.Unlock();
+
int r = read_header(ictx->md_ctx, ictx->md_oid(), &(ictx->header), NULL);
if (r < 0) {
lderr(cct) << "Error reading header: " << cpp_strerror(-r) << dendl;
@@ -1239,6 +1243,9 @@ int ictx_refresh(ImageCtx *ictx)
if (!ictx->snapc.is_valid()) {
lderr(cct) << "image snap context is invalid!" << dendl;
+ ictx->refresh_lock.Lock();
+ ictx->needs_refresh = true;
+ ictx->refresh_lock.Unlock();
return -EIO;
}
@@ -1251,10 +1258,6 @@ int ictx_refresh(ImageCtx *ictx)
ictx->data_ctx.selfmanaged_snap_set_write_ctx(ictx->snapc.seq, ictx->snaps);
- ictx->refresh_lock.Lock();
- ictx->needs_refresh = false;
- ictx->refresh_lock.Unlock();
-
return 0;
}