diff --git a/internal/rbd/clone.go b/internal/rbd/clone.go index 72a3c326a..a72093377 100644 --- a/internal/rbd/clone.go +++ b/internal/rbd/clone.go @@ -127,7 +127,7 @@ func (rv *rbdVolume) checkCloneImage(ctx context.Context, parentVol *rbdVolume) func (rv *rbdVolume) generateTempClone() *rbdVolume { tempClone := rbdVolume{} - tempClone.conn = rv.conn + tempClone.conn = rv.conn.Copy() // The temp clone image need to have deep flatten feature f := []string{librbd.FeatureNameLayering, librbd.FeatureNameDeepFlatten} tempClone.imageFeatureSet = librbd.FeatureSetFromNames(f) diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index cefdd2232..8769877a6 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -496,7 +496,7 @@ func (rv *rbdVolume) getCloneDepth(ctx context.Context) (uint, error) { vol.Pool = rv.Pool vol.Monitors = rv.Monitors vol.RbdImageName = rv.RbdImageName - vol.conn = rv.conn + vol.conn = rv.conn.Copy() err := vol.openIoctx() if err != nil { @@ -666,7 +666,7 @@ func (rv *rbdVolume) checkImageChainHasFeature(ctx context.Context, feature uint vol.RadosNamespace = rv.RadosNamespace vol.Monitors = rv.Monitors vol.RbdImageName = rv.RbdImageName - vol.conn = rv.conn + vol.conn = rv.conn.Copy() err := vol.openIoctx() if err != nil { diff --git a/internal/util/conn_pool.go b/internal/util/conn_pool.go index 6ed19963b..89d03379e 100644 --- a/internal/util/conn_pool.go +++ b/internal/util/conn_pool.go @@ -168,6 +168,22 @@ func (cp *ConnPool) Get(monitors, user, keyfile string) (*rados.Conn, error) { return conn, nil } +// Copy adds an extra reference count to the used ConnEntry and returns the +// *rados.Conn if it was found. +func (cp *ConnPool) Copy(conn *rados.Conn) *rados.Conn { + cp.lock.Lock() + defer cp.lock.Unlock() + + for _, ce := range cp.conns { + if ce.conn == conn { + ce.get() + return ce.conn + } + } + + return nil +} + // Put reduces the reference count of the rados.Conn object that was returned with // ConnPool.Get(). func (cp *ConnPool) Put(conn *rados.Conn) { diff --git a/internal/util/connection.go b/internal/util/connection.go index 1917e2dac..b25e35a6d 100644 --- a/internal/util/connection.go +++ b/internal/util/connection.go @@ -68,6 +68,22 @@ func (cc *ClusterConnection) Destroy() { } } +// Copy creates a copy of the ClusterConnection. This is needed when an other +// object needs to use the existing connection. +// It is required to call Destroy() once the (copied) connection is not used +// anymore. +func (cc *ClusterConnection) Copy() *ClusterConnection { + if cc.conn == nil { + return nil + } + + c := ClusterConnection{} + c.discardOnZeroedWriteSameDisabled = cc.discardOnZeroedWriteSameDisabled + c.conn = connPool.Copy(cc.conn) + + return &c +} + func (cc *ClusterConnection) GetIoctx(pool string) (*rados.IOContext, error) { if cc.conn == nil { return nil, errors.New("cluster is not connected yet")