1
0
Fork 0
mirror of https://github.com/restic/restic.git synced 2025-03-09 00:00:02 +01:00

WIP: remember and log last non-fatal clone error

This commit is contained in:
Ivan Shapovalov 2024-12-05 18:12:33 +04:00
parent c6d28cb621
commit 0f82812b9a
2 changed files with 13 additions and 4 deletions

View file

@ -151,16 +151,20 @@ func doClone(srcName, destName string, method cloneMethod) (cloned bool, err err
// Clone performs a local possibly accelerated copy of srcName to destName.
// The cloned flag reports whether an accelerated copy (reflink) was performed.
func Clone(srcName, destName string) (cloned bool, err error) {
// The cloneErr value specifies the last non-fatal error during attempted
// accelerated copy.
func Clone(srcName, destName string) (cloned bool, err error, cloneErr error) {
for _, fn := range cloneMethods {
cloned, err = doClone(srcName, destName, fn)
// if a particular method is not supported, or we hit the cross-device limitation,
// "eat" the error and go to the next method or the fallback
if errors.Is(err, unix.EXDEV) || errors.Is(err, unix.ENOTSUP) {
cloneErr = err
continue
}
return cloned, err
return cloned, err, cloneErr
}
return doClone(srcName, destName, doCloneCopy)
cloned, err = doClone(srcName, destName, doCloneCopy)
return cloned, err, cloneErr
}

View file

@ -318,18 +318,23 @@ func (res *Restorer) restoreHardlinkAt(node *restic.Node, target, path, location
func (res *Restorer) restoreReflink(node *restic.Node, target, path, location string) error {
cloned := true
var cloneErr error
if !res.opts.DryRun {
var err error
if err = fs.Remove(path); err != nil && !errors.Is(err, os.ErrNotExist) {
return errors.Wrap(err, "RemoveNode")
}
cloned, err = fs.Clone(target, path)
cloned, err, cloneErr = fs.Clone(target, path)
if err != nil {
return errors.WithStack(err)
}
}
res.opts.Progress.AddClonedFile(location, node.Size, cloned)
if !cloned {
fmt.Fprintf(os.Stderr, "warning: could not reflink %v to %v: %v\n", target, path, cloneErr)
}
// reflinked files *do* have separate metadata
return res.restoreNodeMetadataTo(node, path, location)
}