lib/model: Add option to disable fsync (#6588)

* lib/model: Add option to disable fsync

* Fix test

* Dont open stuff for no reason
This commit is contained in:
Audrius Butkevicius 2020-05-01 08:36:46 +01:00 committed by GitHub
parent 22242d51be
commit 782bd08aad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 17 deletions

View File

@ -58,6 +58,7 @@ type FolderConfiguration struct {
CopyOwnershipFromParent bool `xml:"copyOwnershipFromParent" json:"copyOwnershipFromParent"` CopyOwnershipFromParent bool `xml:"copyOwnershipFromParent" json:"copyOwnershipFromParent"`
RawModTimeWindowS int `xml:"modTimeWindowS" json:"modTimeWindowS"` RawModTimeWindowS int `xml:"modTimeWindowS" json:"modTimeWindowS"`
MaxConcurrentWrites int `xml:"maxConcurrentWrites" json:"maxConcurrentWrites" default:"2"` MaxConcurrentWrites int `xml:"maxConcurrentWrites" json:"maxConcurrentWrites" default:"2"`
DisableFsync bool `xml:"disableFsync" json:"disableFsync"`
cachedFilesystem fs.Filesystem cachedFilesystem fs.Filesystem
cachedModTimeWindow time.Duration cachedModTimeWindow time.Duration

View File

@ -1082,7 +1082,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, snap *db.Snapshot
"action": "update", "action": "update",
}) })
s := newSharedPullerState(file, f.fs, f.folderID, tempName, blocks, reused, f.IgnorePerms || file.NoPermissions, hasCurFile, curFile, !f.DisableSparseFiles) s := newSharedPullerState(file, f.fs, f.folderID, tempName, blocks, reused, f.IgnorePerms || file.NoPermissions, hasCurFile, curFile, !f.DisableSparseFiles, !f.DisableFsync)
l.Debugf("%v need file %s; copy %d, reused %v", f, file.Name, len(blocks), len(reused)) l.Debugf("%v need file %s; copy %d, reused %v", f, file.Name, len(blocks), len(reused))
@ -1581,6 +1581,7 @@ func (f *sendReceiveFolder) dbUpdaterRoutine(dbUpdateChan <-chan dbUpdateJob) {
// sync directories // sync directories
for dir := range changedDirs { for dir := range changedDirs {
delete(changedDirs, dir) delete(changedDirs, dir)
if !f.FolderConfiguration.DisableFsync {
fd, err := f.fs.Open(dir) fd, err := f.fs.Open(dir)
if err != nil { if err != nil {
l.Debugf("fsync %q failed: %v", dir, err) l.Debugf("fsync %q failed: %v", dir, err)
@ -1591,6 +1592,7 @@ func (f *sendReceiveFolder) dbUpdaterRoutine(dbUpdateChan <-chan dbUpdateJob) {
} }
fd.Close() fd.Close()
} }
}
// All updates to file/folder objects that originated remotely // All updates to file/folder objects that originated remotely
// (across the network) use this call to updateLocals // (across the network) use this call to updateLocals

View File

@ -1031,7 +1031,7 @@ func TestPullCtxCancel(t *testing.T) {
emptyState := func() pullBlockState { emptyState := func() pullBlockState {
return pullBlockState{ return pullBlockState{
sharedPullerState: newSharedPullerState(protocol.FileInfo{}, nil, f.folderID, "", nil, nil, false, false, protocol.FileInfo{}, false), sharedPullerState: newSharedPullerState(protocol.FileInfo{}, nil, f.folderID, "", nil, nil, false, false, protocol.FileInfo{}, false, false),
block: protocol.BlockInfo{}, block: protocol.BlockInfo{},
} }
} }

View File

@ -32,6 +32,7 @@ type sharedPullerState struct {
curFile protocol.FileInfo // The file as it exists now in our database curFile protocol.FileInfo // The file as it exists now in our database
sparse bool sparse bool
created time.Time created time.Time
fsync bool
// Mutable, must be locked for access // Mutable, must be locked for access
err error // The first error we hit err error // The first error we hit
@ -49,7 +50,7 @@ type sharedPullerState struct {
mut sync.RWMutex // Protects the above mut sync.RWMutex // Protects the above
} }
func newSharedPullerState(file protocol.FileInfo, fs fs.Filesystem, folderID, tempName string, blocks []protocol.BlockInfo, reused []int32, ignorePerms, hasCurFile bool, curFile protocol.FileInfo, sparse bool) *sharedPullerState { func newSharedPullerState(file protocol.FileInfo, fs fs.Filesystem, folderID, tempName string, blocks []protocol.BlockInfo, reused []int32, ignorePerms, hasCurFile bool, curFile protocol.FileInfo, sparse bool, fsync bool) *sharedPullerState {
return &sharedPullerState{ return &sharedPullerState{
file: file, file: file,
fs: fs, fs: fs,
@ -67,6 +68,7 @@ func newSharedPullerState(file protocol.FileInfo, fs fs.Filesystem, folderID, te
curFile: curFile, curFile: curFile,
mut: sync.NewRWMutex(), mut: sync.NewRWMutex(),
sparse: sparse, sparse: sparse,
fsync: fsync,
created: time.Now(), created: time.Now(),
} }
} }
@ -101,14 +103,16 @@ func (w *lockedWriterAt) WriteAt(p []byte, off int64) (n int, err error) {
// SyncClose ensures that no more writes are happening before going ahead and // SyncClose ensures that no more writes are happening before going ahead and
// syncing and closing the fd, thus needs to acquire a write-lock. // syncing and closing the fd, thus needs to acquire a write-lock.
func (w *lockedWriterAt) SyncClose() error { func (w *lockedWriterAt) SyncClose(fsync bool) error {
w.mut.Lock() w.mut.Lock()
defer w.mut.Unlock() defer w.mut.Unlock()
if fsync {
if err := w.fd.Sync(); err != nil { if err := w.fd.Sync(); err != nil {
// Sync() is nice if it works but not worth failing the // Sync() is nice if it works but not worth failing the
// operation over if it fails. // operation over if it fails.
l.Debugf("fsync failed: %v", err) l.Debugf("fsync failed: %v", err)
} }
}
return w.fd.Close() return w.fd.Close()
} }
@ -303,7 +307,7 @@ func (s *sharedPullerState) finalClose() (bool, error) {
} }
if s.writer != nil { if s.writer != nil {
if err := s.writer.SyncClose(); err != nil && s.err == nil { if err := s.writer.SyncClose(s.fsync); err != nil && s.err == nil {
// This is our error as we weren't errored before. // This is our error as we weren't errored before.
s.err = err s.err = err
} }