vfs: keep track of number of open RWHandles

This commit is contained in:
Nick Craig-Wood 2018-03-02 15:58:41 +00:00
parent 5e334eedd2
commit 9b011ce7e4
3 changed files with 52 additions and 1 deletions

View file

@ -21,6 +21,7 @@ type File struct {
mu sync.Mutex // protects the following mu sync.Mutex // protects the following
o fs.Object // NB o may be nil if file is being written o fs.Object // NB o may be nil if file is being written
leaf string // leaf name of the object leaf string // leaf name of the object
rwOpenCount int // number of open files on this handle
writers []Handle // writers for this file writers []Handle // writers for this file
readWriters int // how many RWFileHandle are open for writing readWriters int // how many RWFileHandle are open for writing
readWriterClosing bool // is a RWFileHandle currently cosing? readWriterClosing bool // is a RWFileHandle currently cosing?
@ -138,6 +139,31 @@ func (f *File) delWriter(h Handle, modifiedCacheFile bool) (lastWriterAndModifie
return return
} }
// addRWOpen should be called by ReadWriteHandle when they have
// actually opened the file for read or write.
func (f *File) addRWOpen() {
f.mu.Lock()
f.rwOpenCount++
f.mu.Unlock()
}
// delRWOpen should be called by ReadWriteHandle when they have closed
// an actually opene file for read or write.
func (f *File) delRWOpen() {
f.mu.Lock()
f.rwOpenCount--
f.mu.Unlock()
}
// rwOpens returns how many active open ReadWriteHandles there are.
// Note that file handles which are in pending open state aren't
// counted.
func (f *File) rwOpens() int {
f.mu.Lock()
defer f.mu.Unlock()
return f.rwOpenCount
}
// finishWriterClose resets the readWriterClosing flag // finishWriterClose resets the readWriterClosing flag
func (f *File) finishWriterClose() { func (f *File) finishWriterClose() {
f.mu.Lock() f.mu.Lock()

View file

@ -192,6 +192,7 @@ func (fh *RWFileHandle) openPending(truncate bool) (err error) {
} }
fh.File = fd fh.File = fd
fh.opened = true fh.opened = true
fh.file.addRWOpen()
fh.d.addObject(fh.file) // make sure the directory has this object in it now fh.d.addObject(fh.file) // make sure the directory has this object in it now
return nil return nil
} }
@ -246,7 +247,12 @@ func (fh *RWFileHandle) close() (err error) {
return ECLOSED return ECLOSED
} }
fh.closed = true fh.closed = true
defer fh.d.vfs.cache.close(fh.remote) defer func() {
if fh.opened {
fh.file.delRWOpen()
}
fh.d.vfs.cache.close(fh.remote)
}()
rdwrMode := fh.flags & accessModeMask rdwrMode := fh.flags & accessModeMask
writer := rdwrMode != os.O_RDONLY writer := rdwrMode != os.O_RDONLY

View file

@ -74,9 +74,15 @@ func TestRWFileHandleMethodsRead(t *testing.T) {
// Size // Size
assert.Equal(t, int64(16), fh.Size()) assert.Equal(t, int64(16), fh.Size())
// No opens yet
assert.Equal(t, 0, fh.file.rwOpens())
// Read 1 // Read 1
assert.Equal(t, "0", rwReadString(t, fh, 1)) assert.Equal(t, "0", rwReadString(t, fh, 1))
// Open after the read
assert.Equal(t, 1, fh.file.rwOpens())
// Read remainder // Read remainder
assert.Equal(t, "123456789abcdef", rwReadString(t, fh, 256)) assert.Equal(t, "123456789abcdef", rwReadString(t, fh, 256))
@ -101,6 +107,9 @@ func TestRWFileHandleMethodsRead(t *testing.T) {
assert.Equal(t, nil, fh.Close()) assert.Equal(t, nil, fh.Close())
assert.True(t, fh.closed) assert.True(t, fh.closed)
// No opens again
assert.Equal(t, 0, fh.file.rwOpens())
// Close again // Close again
assert.Equal(t, ECLOSED, fh.Close()) assert.Equal(t, ECLOSED, fh.Close())
} }
@ -266,6 +275,10 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
vfs, fh := rwHandleCreateWriteOnly(t, r) vfs, fh := rwHandleCreateWriteOnly(t, r)
defer cleanup(t, r, vfs) defer cleanup(t, r, vfs)
// 1 opens since we opened with O_CREATE and the file didn't
// exist in the cache
assert.Equal(t, 1, fh.file.rwOpens())
// String // String
assert.Equal(t, "file1 (rw)", fh.String()) assert.Equal(t, "file1 (rw)", fh.String())
assert.Equal(t, "<nil *RWFileHandle>", (*RWFileHandle)(nil).String()) assert.Equal(t, "<nil *RWFileHandle>", (*RWFileHandle)(nil).String())
@ -293,6 +306,9 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, 5, n) assert.Equal(t, 5, n)
// Open after the write
assert.Equal(t, 1, fh.file.rwOpens())
// Offset #2 // Offset #2
assert.Equal(t, int64(5), offset()) assert.Equal(t, int64(5), offset())
assert.Equal(t, int64(5), node.Size()) assert.Equal(t, int64(5), node.Size())
@ -323,6 +339,9 @@ func TestRWFileHandleMethodsWrite(t *testing.T) {
// Close // Close
assert.NoError(t, fh.Close()) assert.NoError(t, fh.Close())
// No opens again
assert.Equal(t, 0, fh.file.rwOpens())
// Check double close // Check double close
err = fh.Close() err = fh.Close()
assert.Equal(t, ECLOSED, err) assert.Equal(t, ECLOSED, err)