From: Josh Durgin Date: Sun, 30 Dec 2012 04:35:15 +0000 (-0800) Subject: librbd: fix race between unprotect and clone X-Git-Tag: v0.56~1^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d0a14d110db7ce13342af0995d7eb4d5e7798653;p=ceph.git librbd: fix race between unprotect and clone Clone needs to actually re-read the header to make sure the image is still protected before returning. Additionally, it needs to consider the image protected *only* if the protection status is protected - unprotecting does not count. I thought I'd already fixed this, but can't find the commit. Signed-off-by: Josh Durgin --- diff --git a/src/librbd/ImageCtx.cc b/src/librbd/ImageCtx.cc index fb9212e187ed..80f19d235501 100644 --- a/src/librbd/ImageCtx.cc +++ b/src/librbd/ImageCtx.cc @@ -327,7 +327,7 @@ namespace librbd { map::const_iterator it = snaps_by_name.find(in_snap_name); if (it != snaps_by_name.end()) { *is_protected = - (it->second.protection_status != RBD_PROTECTION_STATUS_UNPROTECTED); + (it->second.protection_status == RBD_PROTECTION_STATUS_PROTECTED); return 0; } return -ENOENT; diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 53ce19c65fc6..ee8966cb40e2 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -963,10 +963,15 @@ reprotect_and_return_err: goto err_close_child; } - p_imctx->snap_lock.Lock(); - r = p_imctx->is_snap_protected(p_imctx->snap_name, &snap_protected); - p_imctx->snap_lock.Unlock(); + p_imctx->md_lock.Lock(); + r = ictx_refresh(p_imctx); + p_imctx->md_lock.Unlock(); + if (r == 0) { + p_imctx->snap_lock.Lock(); + r = p_imctx->is_snap_protected(p_imctx->snap_name, &snap_protected); + p_imctx->snap_lock.Unlock(); + } if (r < 0 || !snap_protected) { // we lost the race with unprotect r = -EINVAL;