From 8be8a8e41b3439517bfd5f73296fde768e56e972 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 11 May 2017 08:33:45 +0100 Subject: [PATCH] mountlib: on read only open of file, make open pending until first read This fixes a problem with Windows which seems fond of opening files just to read their attributes and closing them again. --- cmd/mountlib/read.go | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/cmd/mountlib/read.go b/cmd/mountlib/read.go index 2722e9760..7be50c88d 100644 --- a/cmd/mountlib/read.go +++ b/cmd/mountlib/read.go @@ -19,15 +19,12 @@ type ReadFileHandle struct { noSeek bool file *File hash *fs.MultiHasher + opened bool } func newReadFileHandle(f *File, o fs.Object) (*ReadFileHandle, error) { - r, err := o.Open() - if err != nil { - return nil, err - } - var hash *fs.MultiHasher + var err error if !f.d.fsys.noChecksum { hash, err = fs.NewMultiHasherTypes(o.Fs().Hashes()) if err != nil { @@ -37,7 +34,6 @@ func newReadFileHandle(f *File, o fs.Object) (*ReadFileHandle, error) { fh := &ReadFileHandle{ o: o, - r: fs.NewAccount(r, o).WithBuffer(), // account the transfer noSeek: f.d.fsys.noSeek, file: f, hash: hash, @@ -46,6 +42,21 @@ func newReadFileHandle(f *File, o fs.Object) (*ReadFileHandle, error) { return fh, nil } +// openPending opens the file if there is a pending open +// call with the lock held +func (fh *ReadFileHandle) openPending() (err error) { + if fh.opened { + return nil + } + r, err := fh.o.Open() + if err != nil { + return err + } + fh.r = fs.NewAccount(r, fh.o).WithBuffer() // account the transfer + fh.opened = true + return nil +} + // String converts it to printable func (fh *ReadFileHandle) String() string { if fh == nil { @@ -106,6 +117,10 @@ func (fh *ReadFileHandle) seek(offset int64, reopen bool) (err error) { func (fh *ReadFileHandle) Read(reqSize, reqOffset int64) (respData []byte, err error) { fh.mu.Lock() defer fh.mu.Unlock() + err = fh.openPending() // FIXME pending open could be more efficient in the presense of seek (and retried) + if err != nil { + return nil, err + } // fs.Debugf(fh.o, "ReadFileHandle.Read size %d offset %d", reqSize, reqOffset) if fh.closed { fs.Errorf(fh.o, "ReadFileHandle.Read error: %v", EBADF) @@ -220,6 +235,9 @@ func (fh *ReadFileHandle) close() error { func (fh *ReadFileHandle) Flush() error { fh.mu.Lock() defer fh.mu.Unlock() + if !fh.opened { + return nil + } // fs.Debugf(fh.o, "ReadFileHandle.Flush") if err := fh.checkHash(); err != nil { @@ -238,6 +256,9 @@ func (fh *ReadFileHandle) Flush() error { func (fh *ReadFileHandle) Release() error { fh.mu.Lock() defer fh.mu.Unlock() + if !fh.opened { + return nil + } if fh.closed { fs.Debugf(fh.o, "ReadFileHandle.Release nothing to do") return nil