diff --git a/internal/rbd/nodeserver.go b/internal/rbd/nodeserver.go index 0c759e7a2879..ff2f8f9e7a74 100644 --- a/internal/rbd/nodeserver.go +++ b/internal/rbd/nodeserver.go @@ -599,7 +599,7 @@ func flattenImageBeforeMapping( if err != nil { return err } - depth, err = volOptions.getCloneDepth() + depth, err = volOptions.getCloneDepth(rbdHardMaxCloneDepth + 1) if err != nil { return err } diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index 774b23cb3efd..a5a16b7e00c2 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -698,11 +698,13 @@ func (ri *rbdImage) trashRemoveImage(ctx context.Context) error { } // getCloneDepth walks the parents of the image and returns the number of -// images in the chain. +// images in the chain. The `max` argument to the function is used to specify a +// limit of the depth to check. When `max` depth is reached, no further +// traversing of the depth is required. // // This function re-uses the ioctx of the image to open all images in the // chain. There is no need to open new ioctx's for every image. -func (ri *rbdImage) getCloneDepth() (uint, error) { +func (ri *rbdImage) getCloneDepth(max uint) (uint, error) { var ( depth uint info *librbd.ParentInfo @@ -732,6 +734,13 @@ func (ri *rbdImage) getCloneDepth() (uint, error) { // if there is a parent, count it to the depth depth++ + // if max (usually hard-limit) is reached, further traversing + // parents is not needed, some action (flattening) will be + // triggered regardless of deeper depth + if depth == max { + break + } + // open the parent image, so that the for-loop can continue // with checking for the parent of the parent image, err = librbd.OpenImageById(ri.ioctx, info.Image.ImageID, info.Snap.SnapName) @@ -820,7 +829,7 @@ func (ri *rbdImage) flattenRbdImage( // skip clone depth check if request is for force flatten if !forceFlatten { - depth, err = ri.getCloneDepth() + depth, err = ri.getCloneDepth(hardlimit) if err != nil { return err }