summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Durgin <josh.durgin@inktank.com>2013-01-02 14:15:24 -0800
committerJosh Durgin <josh.durgin@inktank.com>2013-01-02 14:15:34 -0800
commitc4370ff03f8ab655a009cfd9ba3a0827d8c58b11 (patch)
tree1763bf1b9987cbe2f3fa181ffaaefd56ffc338c1
parente0858fa89903cf4055889c405f17515504e917a0 (diff)
downloadceph-c4370ff03f8ab655a009cfd9ba3a0827d8c58b11.tar.gz
librbd: establish watch before reading header
This eliminates a window in which a race could occur when we have an image open but no watch established. The previous fix (using assert_version) did not work well with resend operations. Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
-rw-r--r--src/librbd/internal.cc24
1 files changed, 14 insertions, 10 deletions
diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc
index b69e40bbbdb..0b788136b0d 100644
--- a/src/librbd/internal.cc
+++ b/src/librbd/internal.cc
@@ -1913,25 +1913,29 @@ reprotect_and_return_err:
if (r < 0)
return r;
- ictx->md_lock.Lock();
- r = ictx_refresh(ictx);
- ictx->md_lock.Unlock();
- if (r < 0)
- return r;
-
- _snap_set(ictx, ictx->snap_name.c_str());
-
if (!ictx->read_only) {
r = ictx->register_watch();
if (r < 0) {
lderr(ictx->cct) << "error registering a watch: " << cpp_strerror(r)
<< dendl;
- close_image(ictx);
- return r;
+ goto err_close;
}
}
+ ictx->md_lock.Lock();
+ r = ictx_refresh(ictx);
+ ictx->md_lock.Unlock();
+ if (r < 0)
+ goto err_close;
+
+ if ((r = _snap_set(ictx, ictx->snap_name.c_str())) < 0)
+ goto err_close;
+
return 0;
+
+ err_close:
+ close_image(ictx);
+ return r;
}
void close_image(ImageCtx *ictx)