diff --git a/internal/cephfs/core/clone.go b/internal/cephfs/core/clone.go index 6ec18db9481..3f0fa2d655f 100644 --- a/internal/cephfs/core/clone.go +++ b/internal/cephfs/core/clone.go @@ -28,16 +28,17 @@ import ( // cephFSCloneState describes the status of the clone. type cephFSCloneState struct { - state admin.CloneState - errno string - errorMsg string + state admin.CloneState + progressReport admin.CloneProgressReport + errno string + errorMsg string } // CephFSCloneError indicates that fetching the clone state returned an error. -var CephFSCloneError = cephFSCloneState{} +var CephFSCloneError = &cephFSCloneState{} // ToError checks the state of the clone if it's not cephFSCloneComplete. -func (cs cephFSCloneState) ToError() error { +func (cs *cephFSCloneState) ToError() error { switch cs.state { case admin.CloneComplete: return nil @@ -54,6 +55,14 @@ func (cs cephFSCloneState) ToError() error { return nil } +func (cs *cephFSCloneState) GetProgressReport() admin.CloneProgressReport { + return admin.CloneProgressReport{ + PercentageCloned: cs.progressReport.PercentageCloned, + AmountCloned: cs.progressReport.AmountCloned, + FilesCloned: cs.progressReport.FilesCloned, + } +} + // CreateCloneFromSubvolume creates a clone from a subvolume. func (s *subVolumeClient) CreateCloneFromSubvolume( ctx context.Context, @@ -87,7 +96,7 @@ func (s *subVolumeClient) CreateCloneFromSubvolume( return err } - var cloneState cephFSCloneState + var cloneState *cephFSCloneState cloneState, err = s.GetCloneState(ctx) if err != nil { log.ErrorLog(ctx, "failed to get clone state: %v", err) @@ -157,7 +166,7 @@ func (s *subVolumeClient) CreateCloneFromSnapshot( } } }() - var cloneState cephFSCloneState + var cloneState *cephFSCloneState // avoid err variable shadowing cloneState, err = s.GetCloneState(ctx) if err != nil { @@ -182,7 +191,7 @@ func (s *subVolumeClient) CreateCloneFromSnapshot( } // GetCloneState returns the clone state of the subvolume. -func (s *subVolumeClient) GetCloneState(ctx context.Context) (cephFSCloneState, error) { +func (s *subVolumeClient) GetCloneState(ctx context.Context) (*cephFSCloneState, error) { fsa, err := s.conn.GetFSAdmin() if err != nil { log.ErrorLog( @@ -209,10 +218,11 @@ func (s *subVolumeClient) GetCloneState(ctx context.Context) (cephFSCloneState, errStr = failure.ErrStr } - state := cephFSCloneState{ - state: cs.State, - errno: errno, - errorMsg: errStr, + state := &cephFSCloneState{ + state: cs.State, + progressReport: cs.ProgressReport, + errno: errno, + errorMsg: errStr, } return state, nil diff --git a/internal/cephfs/core/clone_test.go b/internal/cephfs/core/clone_test.go index 1cf9cd6c26b..2e4cc7c8535 100644 --- a/internal/cephfs/core/clone_test.go +++ b/internal/cephfs/core/clone_test.go @@ -28,11 +28,11 @@ import ( func TestCloneStateToError(t *testing.T) { t.Parallel() errorState := make(map[cephFSCloneState]error) - errorState[cephFSCloneState{fsa.CloneComplete, "", ""}] = nil - errorState[CephFSCloneError] = cerrors.ErrInvalidClone - errorState[cephFSCloneState{fsa.CloneInProgress, "", ""}] = cerrors.ErrCloneInProgress - errorState[cephFSCloneState{fsa.ClonePending, "", ""}] = cerrors.ErrClonePending - errorState[cephFSCloneState{fsa.CloneFailed, "", ""}] = cerrors.ErrCloneFailed + errorState[cephFSCloneState{fsa.CloneComplete, fsa.CloneProgressReport{}, "", ""}] = nil + errorState[*CephFSCloneError] = cerrors.ErrInvalidClone + errorState[cephFSCloneState{fsa.CloneInProgress, fsa.CloneProgressReport{}, "", ""}] = cerrors.ErrCloneInProgress + errorState[cephFSCloneState{fsa.ClonePending, fsa.CloneProgressReport{}, "", ""}] = cerrors.ErrClonePending + errorState[cephFSCloneState{fsa.CloneFailed, fsa.CloneProgressReport{}, "", ""}] = cerrors.ErrCloneFailed for state, err := range errorState { require.ErrorIs(t, state.ToError(), err) diff --git a/internal/cephfs/core/volume.go b/internal/cephfs/core/volume.go index 25b281ee325..dd53b2a76c9 100644 --- a/internal/cephfs/core/volume.go +++ b/internal/cephfs/core/volume.go @@ -75,7 +75,7 @@ type SubVolumeClient interface { // CreateCloneFromSubVolume creates a clone from the subvolume. CreateCloneFromSubvolume(ctx context.Context, parentvolOpt *SubVolume) error // GetCloneState returns the clone state of the subvolume. - GetCloneState(ctx context.Context) (cephFSCloneState, error) + GetCloneState(ctx context.Context) (*cephFSCloneState, error) // CreateCloneFromSnapshot creates a clone from the subvolume snapshot. CreateCloneFromSnapshot(ctx context.Context, snap Snapshot) error // CleanupSnapshotFromSubvolume removes the snapshot from the subvolume. diff --git a/internal/cephfs/store/fsjournal.go b/internal/cephfs/store/fsjournal.go index 3e3c676e5df..0a6dfd88854 100644 --- a/internal/cephfs/store/fsjournal.go +++ b/internal/cephfs/store/fsjournal.go @@ -128,7 +128,18 @@ func CheckVolExists(ctx context.Context, } err = cloneState.ToError() if errors.Is(err, cerrors.ErrCloneInProgress) { - return nil, err + progressReport := cloneState.GetProgressReport() + // append progress report only if the progress report parameters are present. + if progressReport.PercentageCloned != "" { + err = fmt.Errorf("%w. progress report: percentage cloned=%s, amount cloned=%s, files cloned=%s", + err, + progressReport.PercentageCloned, + progressReport.AmountCloned, + progressReport.FilesCloned) + log.UsefulLog(ctx, err.Error()) + + return nil, err + } } if errors.Is(err, cerrors.ErrClonePending) { return nil, err