Skip to content

Commit

Permalink
librbd: prevent racing clone and snap unprotect
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
jdurgin committed Sep 18, 2012
1 parent e85a238 commit a112419
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/librbd/internal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -859,11 +859,29 @@ namespace librbd {
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:
Expand Down

0 comments on commit a112419

Please sign in to comment.