diff --git a/internal/feature/registry.go b/internal/feature/registry.go index 7fe7da965..41d0aca9e 100644 --- a/internal/feature/registry.go +++ b/internal/feature/registry.go @@ -8,6 +8,7 @@ const ( BackendErrorRedesign FlagName = "backend-error-redesign" DeviceIDForHardlinks FlagName = "device-id-for-hardlinks" ExplicitS3AnonymousAuth FlagName = "explicit-s3-anonymous-auth" + FilehandleBasedBackup FlagName = "filehandle-based-backup" SafeForgetKeepTags FlagName = "safe-forget-keep-tags" ) @@ -15,6 +16,7 @@ func init() { Flag.SetFlags(map[FlagName]FlagDesc{ BackendErrorRedesign: {Type: Beta, Description: "enforce timeouts for stuck HTTP requests and use new backend error handling design."}, DeviceIDForHardlinks: {Type: Alpha, Description: "store deviceID only for hardlinks to reduce metadata changes for example when using btrfs subvolumes. Will be removed in a future restic version after repository format 3 is available"}, + FilehandleBasedBackup: {Type: Beta, Description: "`backup` uses filehandles to atomically collect file metadata on Linux/macOS/Windows"}, ExplicitS3AnonymousAuth: {Type: Beta, Description: "forbid anonymous S3 authentication unless `-o s3.unsafe-anonymous-auth=true` is set"}, SafeForgetKeepTags: {Type: Beta, Description: "prevent deleting all snapshots if the tag passed to `forget --keep-tags tagname` does not exist"}, }) diff --git a/internal/fs/fs_local.go b/internal/fs/fs_local.go index 062ee47e4..573c14316 100644 --- a/internal/fs/fs_local.go +++ b/internal/fs/fs_local.go @@ -3,10 +3,15 @@ package fs import ( "os" "path/filepath" + "runtime" + "github.com/restic/restic/internal/feature" "github.com/restic/restic/internal/restic" ) +// testOverwriteUseFd controls whether a fd based metadata handle is used when set. +var testOverwriteUseFd *bool + // Local is the local file system. Most methods are just passed on to the stdlib. type Local struct{} @@ -243,7 +248,11 @@ func (f *fdLocalFile) MakeReadable() error { } func buildLocalFile(name string, flag int, metadataOnly bool) (File, error) { - useFd := true // FIXME + useFd := runtime.GOOS == "linux" || runtime.GOOS == "windows" || runtime.GOOS == "darwin" + useFd = useFd && feature.Flag.Enabled(feature.FilehandleBasedBackup) + if testOverwriteUseFd != nil { + useFd = *testOverwriteUseFd + } if useFd { return newFdLocalFile(name, flag, metadataOnly) }