From a1124193c213b981ae12ed8d8bf327684b270325 Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Tue, 28 Aug 2012 17:24:47 -0700 Subject: [PATCH] librbd: prevent racing clone and snap unprotect If the following sequence of events occured, a clone could be created of an unprotected snapshot: 1. A: begin clone - check that snap foo is protected 2. B: rbd unprotect snap foo 3. B: check that all pools have no clones of foo 4. B: unprotect snap foo 5. A: finish creating clone of foo, add it as a child To stop this from happening, check at the beginning and end of cloning that the parent snapshot is protected. If it is not, or checking protection status fails (possibly because the parent snapshot was removed), remove the clone and return an error. Signed-off-by: Josh Durgin --- src/librbd/internal.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 4d8b0a4ba463a..b394ddbcda839 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -859,11 +859,29 @@ reprotect_and_return_err: lderr(cct) << "couldn't add child: " << r << dendl; 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(); + + if (r < 0 || !snap_protected) { + // we lost the race with unprotect + r = -EINVAL; + goto err_remove_child; + } + ldout(cct, 2) << "done." << dendl; close_image(c_imctx); close_image(p_imctx); return 0; + err_remove_child: + remove_r = cls_client::remove_child(&c_ioctx, RBD_CHILDREN, pspec, + c_imctx->id); + if (remove_r < 0) { + lderr(cct) << "Error removing failed clone from list of children: " + << cpp_strerror(remove_r) << dendl; + } err_close_child: close_image(c_imctx); err_remove: -- 2.39.5