From 7afaac9c6643c61c9146ed90b53e6c0e22ea39d5 Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Wed, 22 Jul 2020 15:33:36 +0200 Subject: [PATCH] rbd: implement rbdVolume.isInUse() with go-ceph The new rbdVolume.isInUse() method will replace the rbdStatus() function. This removes one more rbd command execution in the DeleteVolume path. Signed-off-by: Niels de Vos --- internal/rbd/controllerserver.go | 4 ++-- internal/rbd/rbd_attach.go | 8 ++++---- internal/rbd/rbd_util.go | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/internal/rbd/controllerserver.go b/internal/rbd/controllerserver.go index aa86873a5..5de3d1b0b 100644 --- a/internal/rbd/controllerserver.go +++ b/internal/rbd/controllerserver.go @@ -613,12 +613,12 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol } defer cs.VolumeLocks.Release(rbdVol.RequestName) - found, _, err := rbdStatus(ctx, rbdVol, cr) + inUse, err := rbdVol.isInUse() if err != nil { klog.Errorf(util.Log(ctx, "failed getting information for image (%s): (%s)"), rbdVol, err) return nil, status.Error(codes.Internal, err.Error()) } - if found { + if inUse { klog.Errorf(util.Log(ctx, "rbd %s is still being used"), rbdVol) return nil, status.Errorf(codes.Internal, "rbd %s is still being used", rbdVol.RbdImageName) } diff --git a/internal/rbd/rbd_attach.go b/internal/rbd/rbd_attach.go index 3542f9660..b1623d73f 100644 --- a/internal/rbd/rbd_attach.go +++ b/internal/rbd/rbd_attach.go @@ -190,7 +190,7 @@ func attachRBDImage(ctx context.Context, volOptions *rbdVolume, cr *util.Credent Steps: rbdImageWatcherSteps, } - err = waitForrbdImage(ctx, backoff, volOptions, cr) + err = waitForrbdImage(ctx, backoff, volOptions) if err != nil { return "", err @@ -246,13 +246,13 @@ func createPath(ctx context.Context, volOpt *rbdVolume, cr *util.Credentials) (s return devicePath, nil } -func waitForrbdImage(ctx context.Context, backoff wait.Backoff, volOptions *rbdVolume, cr *util.Credentials) error { +func waitForrbdImage(ctx context.Context, backoff wait.Backoff, volOptions *rbdVolume) error { imagePath := volOptions.String() err := wait.ExponentialBackoff(backoff, func() (bool, error) { - used, rbdOutput, err := rbdStatus(ctx, volOptions, cr) + used, err := volOptions.isInUse() if err != nil { - return false, fmt.Errorf("fail to check rbd image status with: (%v), rbd output: (%s)", err, rbdOutput) + return false, fmt.Errorf("fail to check rbd image status: (%w)", err) } if (volOptions.DisableInUseChecks) && (used) { util.UsefulLog(ctx, "valid multi-node attach requested, ignoring watcher in-use result") diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index 47cd3f26c..6c1a3b0ec 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -275,6 +275,28 @@ func (rv *rbdVolume) open() (*librbd.Image, error) { return image, nil } +// isInUse checks if there is a watcher on the image. It returns true if there +// is a watcher on the image, otherwise returns false. +func (rv *rbdVolume) isInUse() (bool, error) { + image, err := rv.open() + if err != nil { + if errors.Is(err, ErrImageNotFound) || errors.Is(err, util.ErrPoolNotFound) { + return false, err + } + // any error should assume something else is using the image + return true, err + } + defer image.Close() + + watchers, err := image.ListWatchers() + if err != nil { + return false, err + } + + // because we opened the image, there is at least one watcher + return len(watchers) != 1, nil +} + // rbdStatus checks if there is watcher on the image. // It returns true if there is a watcher on the image, otherwise returns false. func rbdStatus(ctx context.Context, pOpts *rbdVolume, cr *util.Credentials) (bool, string, error) {