Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull Ceph fixes from Sage Weil: "These paches from Ilya finally squash a race condition with layered images that he's been chasing for a while" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: rbd: drop parent_ref in rbd_dev_unprobe() unconditionally rbd: fix rbd_dev_parent_get() when parent_overlap == 0
This commit is contained in:
Коммит
884e00f37d
|
@ -2098,32 +2098,26 @@ static void rbd_dev_parent_put(struct rbd_device *rbd_dev)
|
|||
* If an image has a non-zero parent overlap, get a reference to its
|
||||
* parent.
|
||||
*
|
||||
* We must get the reference before checking for the overlap to
|
||||
* coordinate properly with zeroing the parent overlap in
|
||||
* rbd_dev_v2_parent_info() when an image gets flattened. We
|
||||
* drop it again if there is no overlap.
|
||||
*
|
||||
* Returns true if the rbd device has a parent with a non-zero
|
||||
* overlap and a reference for it was successfully taken, or
|
||||
* false otherwise.
|
||||
*/
|
||||
static bool rbd_dev_parent_get(struct rbd_device *rbd_dev)
|
||||
{
|
||||
int counter;
|
||||
int counter = 0;
|
||||
|
||||
if (!rbd_dev->parent_spec)
|
||||
return false;
|
||||
|
||||
counter = atomic_inc_return_safe(&rbd_dev->parent_ref);
|
||||
if (counter > 0 && rbd_dev->parent_overlap)
|
||||
return true;
|
||||
|
||||
/* Image was flattened, but parent is not yet torn down */
|
||||
down_read(&rbd_dev->header_rwsem);
|
||||
if (rbd_dev->parent_overlap)
|
||||
counter = atomic_inc_return_safe(&rbd_dev->parent_ref);
|
||||
up_read(&rbd_dev->header_rwsem);
|
||||
|
||||
if (counter < 0)
|
||||
rbd_warn(rbd_dev, "parent reference overflow");
|
||||
|
||||
return false;
|
||||
return counter > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4239,7 +4233,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
|||
*/
|
||||
if (rbd_dev->parent_overlap) {
|
||||
rbd_dev->parent_overlap = 0;
|
||||
smp_mb();
|
||||
rbd_dev_parent_put(rbd_dev);
|
||||
pr_info("%s: clone image has been flattened\n",
|
||||
rbd_dev->disk->disk_name);
|
||||
|
@ -4285,7 +4278,6 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
|
|||
* treat it specially.
|
||||
*/
|
||||
rbd_dev->parent_overlap = overlap;
|
||||
smp_mb();
|
||||
if (!overlap) {
|
||||
|
||||
/* A null parent_spec indicates it's the initial probe */
|
||||
|
@ -5114,10 +5106,7 @@ static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
|
|||
{
|
||||
struct rbd_image_header *header;
|
||||
|
||||
/* Drop parent reference unless it's already been done (or none) */
|
||||
|
||||
if (rbd_dev->parent_overlap)
|
||||
rbd_dev_parent_put(rbd_dev);
|
||||
rbd_dev_parent_put(rbd_dev);
|
||||
|
||||
/* Free dynamic fields from the header, then zero it out */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче