diff options
author | Josh Durgin <josh.durgin@dreamhost.com> | 2012-04-23 23:46:51 -0700 |
---|---|---|
committer | Josh Durgin <josh.durgin@dreamhost.com> | 2012-04-24 08:57:31 -0700 |
commit | 7add136f907876a20aa2a68297c66b8259afd9a7 (patch) | |
tree | fbf19313f80f0769baf450daedf92d4a1fddd21d | |
parent | 3ef3ab8a15b4a80a340ac6039f395738223df759 (diff) | |
download | ceph-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.cc | 11 |
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; } |