diff options
author | Josh Durgin <josh.durgin@inktank.com> | 2013-01-02 14:15:24 -0800 |
---|---|---|
committer | Josh Durgin <josh.durgin@inktank.com> | 2013-01-02 14:15:34 -0800 |
commit | c4370ff03f8ab655a009cfd9ba3a0827d8c58b11 (patch) | |
tree | 1763bf1b9987cbe2f3fa181ffaaefd56ffc338c1 | |
parent | e0858fa89903cf4055889c405f17515504e917a0 (diff) | |
download | ceph-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.cc | 24 |
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) |