local: Add flag --no-preallocate - #3207

Some virtual filesystems (such as Google Drive File Stream) may
incorrectly set the actual file size equal to the preallocated space,
causing checksum and file size checks to fail.

This flag can be used to disable preallocation for local backends of
this type.
This commit is contained in:
David Sze 2021-01-31 15:25:24 -05:00 committed by Nick Craig-Wood
parent 92187a3b33
commit 2d7afe8690
2 changed files with 38 additions and 7 deletions

View File

@ -148,6 +148,17 @@ Windows/macOS and case sensitive for everything else. Use this flag
to override the default choice.`, to override the default choice.`,
Default: false, Default: false,
Advanced: true, Advanced: true,
}, {
Name: "no_preallocate",
Help: `Disable preallocation of disk space for transferred files
Preallocation of disk space helps prevent filesystem fragmentation.
However, some virtual filesystem layers (such as Google Drive File
Stream) may incorrectly set the actual file size equal to the
preallocated space, causing checksum and file size checks to fail.
Use this flag to disable preallocation.`,
Default: false,
Advanced: true,
}, { }, {
Name: "no_sparse", Name: "no_sparse",
Help: `Disable sparse files for multi-thread downloads Help: `Disable sparse files for multi-thread downloads
@ -191,6 +202,7 @@ type Options struct {
OneFileSystem bool `config:"one_file_system"` OneFileSystem bool `config:"one_file_system"`
CaseSensitive bool `config:"case_sensitive"` CaseSensitive bool `config:"case_sensitive"`
CaseInsensitive bool `config:"case_insensitive"` CaseInsensitive bool `config:"case_insensitive"`
NoPreAllocate bool `config:"no_preallocate"`
NoSparse bool `config:"no_sparse"` NoSparse bool `config:"no_sparse"`
NoSetModTime bool `config:"no_set_modtime"` NoSetModTime bool `config:"no_set_modtime"`
Enc encoder.MultiEncoder `config:"encoding"` Enc encoder.MultiEncoder `config:"encoding"`
@ -1127,10 +1139,12 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
return err return err
} }
} }
// Pre-allocate the file for performance reasons if !o.fs.opt.NoPreAllocate {
err = file.PreAllocate(src.Size(), f) // Pre-allocate the file for performance reasons
if err != nil { err = file.PreAllocate(src.Size(), f)
fs.Debugf(o, "Failed to pre-allocate: %v", err) if err != nil {
fs.Debugf(o, "Failed to pre-allocate: %v", err)
}
} }
out = f out = f
} else { } else {
@ -1217,9 +1231,11 @@ func (f *Fs) OpenWriterAt(ctx context.Context, remote string, size int64) (fs.Wr
return nil, err return nil, err
} }
// Pre-allocate the file for performance reasons // Pre-allocate the file for performance reasons
err = file.PreAllocate(size, out) if !f.opt.NoPreAllocate {
if err != nil { err = file.PreAllocate(size, out)
fs.Debugf(o, "Failed to pre-allocate: %v", err) if err != nil {
fs.Debugf(o, "Failed to pre-allocate: %v", err)
}
} }
if !f.opt.NoSparse && file.SetSparseImplemented { if !f.opt.NoSparse && file.SetSparseImplemented {
sparseWarning.Do(func() { sparseWarning.Do(func() {

View File

@ -447,6 +447,21 @@ to override the default choice.
- Type: bool - Type: bool
- Default: false - Default: false
#### --local-no-preallocate
Disable preallocation of disk space for transferred files
Preallocation of disk space helps prevent filesystem fragmentation.
However, some virtual filesystem layers (such as Google Drive File
Stream) may incorrectly set the actual file size equal to the
preallocated space, causing checksum and file size checks to fail.
Use this flag to disable preallocation.
- Config: no_preallocate
- Env Var: RCLONE_LOCAL_NO_PREALLOCATE
- Type: bool
- Default: false
#### --local-no-sparse #### --local-no-sparse
Disable sparse files for multi-thread downloads Disable sparse files for multi-thread downloads