Since the post-snap create header update runs asynchrously
in a finalizer callback, it's possible that the snapshot
is not immediately visible. Also, if a proxied snap create
message is replayed, it's possible for the client to receive
a EEXISTS error.
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
::encode(ResponseMessage(r), *out);
if (r == 0) {
+ // increment now to avoid race due to the delayed notification
+ Mutex::Locker lictx(m_image_ctx.refresh_lock);
+ ++m_image_ctx.refresh_seq;
+
// cannot notify within a notificiation
FunctionContext *ctx = new FunctionContext(
boost::bind(&ImageWatcher::finalize_header_update, this));
if (r < 0)
return r;
+ {
+ RWLock::RLocker l(ictx->snap_lock);
+ if (ictx->get_snap_id(snap_name) != CEPH_NOSNAP) {
+ return -EEXIST;
+ }
+ }
+
bool lock_owner = false;
while (ictx->image_watcher->is_lock_supported()) {
r = prepare_image_update(ictx);
}
r = ictx->image_watcher->notify_snap_create(snap_name);
- if (r != -ETIMEDOUT) {
+ if (r == -EEXIST) {
+ return 0;
+ } else if (r != -ETIMEDOUT) {
return r;
}
ldout(ictx->cct, 5) << "snap_create timed out notifying lock owner" << dendl;