mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2025-09-19 05:19:23 +08:00
add open release, refactor
This commit is contained in:
16
weed/mount/filehandle.go
Normal file
16
weed/mount/filehandle.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package mount
|
||||||
|
|
||||||
|
import "github.com/hanwen/go-fuse/v2/fuse"
|
||||||
|
|
||||||
|
func (wfs *WFS) AcquireHandle(inode uint64, uid, gid uint32) (fileHandle *FileHandle, code fuse.Status) {
|
||||||
|
_, entry, status := wfs.maybeReadEntry(inode)
|
||||||
|
if status == fuse.OK {
|
||||||
|
fileHandle = wfs.fhmap.GetFileHandle(inode)
|
||||||
|
fileHandle.entry = entry
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wfs *WFS) ReleaseHandle(handleId FileHandleId) {
|
||||||
|
wfs.fhmap.ReleaseByHandle(handleId)
|
||||||
|
}
|
79
weed/mount/filehandle_map.go
Normal file
79
weed/mount/filehandle_map.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileHandleId uint64
|
||||||
|
|
||||||
|
type FileHandleToInode struct {
|
||||||
|
sync.RWMutex
|
||||||
|
nextFh FileHandleId
|
||||||
|
inode2fh map[uint64]*FileHandle
|
||||||
|
fh2inode map[FileHandleId]uint64
|
||||||
|
}
|
||||||
|
type FileHandle struct {
|
||||||
|
fh FileHandleId
|
||||||
|
counter int64
|
||||||
|
entry *filer_pb.Entry
|
||||||
|
inode uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFileHandleToInode() *FileHandleToInode {
|
||||||
|
return &FileHandleToInode{
|
||||||
|
inode2fh: make(map[uint64]*FileHandle),
|
||||||
|
fh2inode: make(map[FileHandleId]uint64),
|
||||||
|
nextFh: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *FileHandleToInode) GetFileHandle(inode uint64) *FileHandle {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
fh, found := i.inode2fh[inode]
|
||||||
|
if !found {
|
||||||
|
fh = &FileHandle{
|
||||||
|
fh: i.nextFh,
|
||||||
|
counter: 1,
|
||||||
|
inode: inode,
|
||||||
|
}
|
||||||
|
i.nextFh++
|
||||||
|
i.inode2fh[inode] = fh
|
||||||
|
i.fh2inode[fh.fh] = inode
|
||||||
|
} else {
|
||||||
|
fh.counter++
|
||||||
|
}
|
||||||
|
return fh
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *FileHandleToInode) ReleaseByInode(inode uint64) {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
fh, found := i.inode2fh[inode]
|
||||||
|
if found {
|
||||||
|
fh.counter--
|
||||||
|
if fh.counter <= 0 {
|
||||||
|
delete(i.inode2fh, inode)
|
||||||
|
delete(i.fh2inode, fh.fh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (i *FileHandleToInode) ReleaseByHandle(fh FileHandleId) {
|
||||||
|
i.Lock()
|
||||||
|
defer i.Unlock()
|
||||||
|
inode, found := i.fh2inode[fh]
|
||||||
|
if found {
|
||||||
|
fhHandle, fhFound := i.inode2fh[inode]
|
||||||
|
if !fhFound {
|
||||||
|
delete(i.fh2inode, fh)
|
||||||
|
} else {
|
||||||
|
fhHandle.counter--
|
||||||
|
if fhHandle.counter <= 0 {
|
||||||
|
delete(i.inode2fh, inode)
|
||||||
|
delete(i.fh2inode, fhHandle.fh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -37,7 +37,6 @@ func (i *InodeToPath) Lookup(path util.FullPath) uint64 {
|
|||||||
i.nextInodeId++
|
i.nextInodeId++
|
||||||
i.path2inode[path] = inode
|
i.path2inode[path] = inode
|
||||||
i.inode2path[inode] = &InodeEntry{path, 1}
|
i.inode2path[inode] = &InodeEntry{path, 1}
|
||||||
println("add", path, inode)
|
|
||||||
} else {
|
} else {
|
||||||
i.inode2path[inode].nlookup++
|
i.inode2path[inode].nlookup++
|
||||||
}
|
}
|
||||||
|
@@ -60,6 +60,7 @@ type WFS struct {
|
|||||||
root Directory
|
root Directory
|
||||||
signature int32
|
signature int32
|
||||||
inodeToPath *InodeToPath
|
inodeToPath *InodeToPath
|
||||||
|
fhmap *FileHandleToInode
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSeaweedFileSystem(option *Option) *WFS {
|
func NewSeaweedFileSystem(option *Option) *WFS {
|
||||||
@@ -68,6 +69,7 @@ func NewSeaweedFileSystem(option *Option) *WFS {
|
|||||||
option: option,
|
option: option,
|
||||||
signature: util.RandomInt32(),
|
signature: util.RandomInt32(),
|
||||||
inodeToPath: NewInodeToPath(),
|
inodeToPath: NewInodeToPath(),
|
||||||
|
fhmap: NewFileHandleToInode(),
|
||||||
}
|
}
|
||||||
|
|
||||||
wfs.root = Directory{
|
wfs.root = Directory{
|
||||||
|
@@ -4,65 +4,6 @@ import (
|
|||||||
"github.com/hanwen/go-fuse/v2/fuse"
|
"github.com/hanwen/go-fuse/v2/fuse"
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
|
||||||
* Read data
|
|
||||||
*
|
|
||||||
* Read should send exactly the number of bytes requested except
|
|
||||||
* on EOF or error, otherwise the rest of the data will be
|
|
||||||
* substituted with zeroes. An exception to this is when the file
|
|
||||||
* has been opened in 'direct_io' mode, in which case the return
|
|
||||||
* value of the read system call will reflect the return value of
|
|
||||||
* this operation.
|
|
||||||
*
|
|
||||||
* fi->fh will contain the value set by the open method, or will
|
|
||||||
* be undefined if the open method didn't set any value.
|
|
||||||
*
|
|
||||||
* Valid replies:
|
|
||||||
* fuse_reply_buf
|
|
||||||
* fuse_reply_iov
|
|
||||||
* fuse_reply_data
|
|
||||||
* fuse_reply_err
|
|
||||||
*
|
|
||||||
* @param req request handle
|
|
||||||
* @param ino the inode number
|
|
||||||
* @param size number of bytes to read
|
|
||||||
* @param off offset to read from
|
|
||||||
* @param fi file information
|
|
||||||
*/
|
|
||||||
func (wfs *WFS) Read(cancel <-chan struct{}, in *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) {
|
|
||||||
return nil, fuse.ENOSYS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write data
|
|
||||||
*
|
|
||||||
* Write should return exactly the number of bytes requested
|
|
||||||
* except on error. An exception to this is when the file has
|
|
||||||
* been opened in 'direct_io' mode, in which case the return value
|
|
||||||
* of the write system call will reflect the return value of this
|
|
||||||
* operation.
|
|
||||||
*
|
|
||||||
* Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
|
|
||||||
* expected to reset the setuid and setgid bits.
|
|
||||||
*
|
|
||||||
* fi->fh will contain the value set by the open method, or will
|
|
||||||
* be undefined if the open method didn't set any value.
|
|
||||||
*
|
|
||||||
* Valid replies:
|
|
||||||
* fuse_reply_write
|
|
||||||
* fuse_reply_err
|
|
||||||
*
|
|
||||||
* @param req request handle
|
|
||||||
* @param ino the inode number
|
|
||||||
* @param buf data to write
|
|
||||||
* @param size number of bytes to write
|
|
||||||
* @param off offset to write to
|
|
||||||
* @param fi file information
|
|
||||||
*/
|
|
||||||
func (wfs *WFS) Write(cancel <-chan struct{}, in *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
|
|
||||||
return 0, fuse.ENOSYS
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a file
|
* Open a file
|
||||||
*
|
*
|
||||||
@@ -120,49 +61,11 @@ func (wfs *WFS) Write(cancel <-chan struct{}, in *fuse.WriteIn, data []byte) (wr
|
|||||||
* @param fi file information
|
* @param fi file information
|
||||||
*/
|
*/
|
||||||
func (wfs *WFS) Open(cancel <-chan struct{}, in *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) {
|
func (wfs *WFS) Open(cancel <-chan struct{}, in *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) {
|
||||||
return fuse.ENOSYS
|
fileHandle, code := wfs.AcquireHandle(in.NodeId, in.Uid, in.Gid)
|
||||||
}
|
if code == fuse.OK {
|
||||||
|
out.Fh = uint64(fileHandle.fh)
|
||||||
/**
|
}
|
||||||
* Flush method
|
return code
|
||||||
*
|
|
||||||
* This is called on each close() of the opened file.
|
|
||||||
*
|
|
||||||
* Since file descriptors can be duplicated (dup, dup2, fork), for
|
|
||||||
* one open call there may be many flush calls.
|
|
||||||
*
|
|
||||||
* Filesystems shouldn't assume that flush will always be called
|
|
||||||
* after some writes, or that if will be called at all.
|
|
||||||
*
|
|
||||||
* fi->fh will contain the value set by the open method, or will
|
|
||||||
* be undefined if the open method didn't set any value.
|
|
||||||
*
|
|
||||||
* NOTE: the name of the method is misleading, since (unlike
|
|
||||||
* fsync) the filesystem is not forced to flush pending writes.
|
|
||||||
* One reason to flush data is if the filesystem wants to return
|
|
||||||
* write errors during close. However, such use is non-portable
|
|
||||||
* because POSIX does not require [close] to wait for delayed I/O to
|
|
||||||
* complete.
|
|
||||||
*
|
|
||||||
* If the filesystem supports file locking operations (setlk,
|
|
||||||
* getlk) it should remove all locks belonging to 'fi->owner'.
|
|
||||||
*
|
|
||||||
* If this request is answered with an error code of ENOSYS,
|
|
||||||
* this is treated as success and future calls to flush() will
|
|
||||||
* succeed automatically without being send to the filesystem
|
|
||||||
* process.
|
|
||||||
*
|
|
||||||
* Valid replies:
|
|
||||||
* fuse_reply_err
|
|
||||||
*
|
|
||||||
* @param req request handle
|
|
||||||
* @param ino the inode number
|
|
||||||
* @param fi file information
|
|
||||||
*
|
|
||||||
* [close]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
|
|
||||||
*/
|
|
||||||
func (wfs *WFS) Flush(cancel <-chan struct{}, in *fuse.FlushIn) fuse.Status {
|
|
||||||
return fuse.ENOSYS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,27 +94,5 @@ func (wfs *WFS) Flush(cancel <-chan struct{}, in *fuse.FlushIn) fuse.Status {
|
|||||||
* @param fi file information
|
* @param fi file information
|
||||||
*/
|
*/
|
||||||
func (wfs *WFS) Release(cancel <-chan struct{}, in *fuse.ReleaseIn) {
|
func (wfs *WFS) Release(cancel <-chan struct{}, in *fuse.ReleaseIn) {
|
||||||
}
|
wfs.ReleaseHandle(FileHandleId(in.Fh))
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronize file contents
|
|
||||||
*
|
|
||||||
* If the datasync parameter is non-zero, then only the user data
|
|
||||||
* should be flushed, not the meta data.
|
|
||||||
*
|
|
||||||
* If this request is answered with an error code of ENOSYS,
|
|
||||||
* this is treated as success and future calls to fsync() will
|
|
||||||
* succeed automatically without being send to the filesystem
|
|
||||||
* process.
|
|
||||||
*
|
|
||||||
* Valid replies:
|
|
||||||
* fuse_reply_err
|
|
||||||
*
|
|
||||||
* @param req request handle
|
|
||||||
* @param ino the inode number
|
|
||||||
* @param datasync flag indicating if only data should be flushed
|
|
||||||
* @param fi file information
|
|
||||||
*/
|
|
||||||
func (wfs *WFS) Fsync(cancel <-chan struct{}, in *fuse.FsyncIn) (code fuse.Status) {
|
|
||||||
return fuse.ENOSYS
|
|
||||||
}
|
}
|
||||||
|
34
weed/mount/weedfs_file_read.go
Normal file
34
weed/mount/weedfs_file_read.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hanwen/go-fuse/v2/fuse"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data
|
||||||
|
*
|
||||||
|
* Read should send exactly the number of bytes requested except
|
||||||
|
* on EOF or error, otherwise the rest of the data will be
|
||||||
|
* substituted with zeroes. An exception to this is when the file
|
||||||
|
* has been opened in 'direct_io' mode, in which case the return
|
||||||
|
* value of the read system call will reflect the return value of
|
||||||
|
* this operation.
|
||||||
|
*
|
||||||
|
* fi->fh will contain the value set by the open method, or will
|
||||||
|
* be undefined if the open method didn't set any value.
|
||||||
|
*
|
||||||
|
* Valid replies:
|
||||||
|
* fuse_reply_buf
|
||||||
|
* fuse_reply_iov
|
||||||
|
* fuse_reply_data
|
||||||
|
* fuse_reply_err
|
||||||
|
*
|
||||||
|
* @param req request handle
|
||||||
|
* @param ino the inode number
|
||||||
|
* @param size number of bytes to read
|
||||||
|
* @param off offset to read from
|
||||||
|
* @param fi file information
|
||||||
|
*/
|
||||||
|
func (wfs *WFS) Read(cancel <-chan struct{}, in *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) {
|
||||||
|
return nil, fuse.ENOSYS
|
||||||
|
}
|
70
weed/mount/weedfs_file_sync.go
Normal file
70
weed/mount/weedfs_file_sync.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hanwen/go-fuse/v2/fuse"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush method
|
||||||
|
*
|
||||||
|
* This is called on each close() of the opened file.
|
||||||
|
*
|
||||||
|
* Since file descriptors can be duplicated (dup, dup2, fork), for
|
||||||
|
* one open call there may be many flush calls.
|
||||||
|
*
|
||||||
|
* Filesystems shouldn't assume that flush will always be called
|
||||||
|
* after some writes, or that if will be called at all.
|
||||||
|
*
|
||||||
|
* fi->fh will contain the value set by the open method, or will
|
||||||
|
* be undefined if the open method didn't set any value.
|
||||||
|
*
|
||||||
|
* NOTE: the name of the method is misleading, since (unlike
|
||||||
|
* fsync) the filesystem is not forced to flush pending writes.
|
||||||
|
* One reason to flush data is if the filesystem wants to return
|
||||||
|
* write errors during close. However, such use is non-portable
|
||||||
|
* because POSIX does not require [close] to wait for delayed I/O to
|
||||||
|
* complete.
|
||||||
|
*
|
||||||
|
* If the filesystem supports file locking operations (setlk,
|
||||||
|
* getlk) it should remove all locks belonging to 'fi->owner'.
|
||||||
|
*
|
||||||
|
* If this request is answered with an error code of ENOSYS,
|
||||||
|
* this is treated as success and future calls to flush() will
|
||||||
|
* succeed automatically without being send to the filesystem
|
||||||
|
* process.
|
||||||
|
*
|
||||||
|
* Valid replies:
|
||||||
|
* fuse_reply_err
|
||||||
|
*
|
||||||
|
* @param req request handle
|
||||||
|
* @param ino the inode number
|
||||||
|
* @param fi file information
|
||||||
|
*
|
||||||
|
* [close]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
|
||||||
|
*/
|
||||||
|
func (wfs *WFS) Flush(cancel <-chan struct{}, in *fuse.FlushIn) fuse.Status {
|
||||||
|
return fuse.ENOSYS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize file contents
|
||||||
|
*
|
||||||
|
* If the datasync parameter is non-zero, then only the user data
|
||||||
|
* should be flushed, not the meta data.
|
||||||
|
*
|
||||||
|
* If this request is answered with an error code of ENOSYS,
|
||||||
|
* this is treated as success and future calls to fsync() will
|
||||||
|
* succeed automatically without being send to the filesystem
|
||||||
|
* process.
|
||||||
|
*
|
||||||
|
* Valid replies:
|
||||||
|
* fuse_reply_err
|
||||||
|
*
|
||||||
|
* @param req request handle
|
||||||
|
* @param ino the inode number
|
||||||
|
* @param datasync flag indicating if only data should be flushed
|
||||||
|
* @param fi file information
|
||||||
|
*/
|
||||||
|
func (wfs *WFS) Fsync(cancel <-chan struct{}, in *fuse.FsyncIn) (code fuse.Status) {
|
||||||
|
return fuse.ENOSYS
|
||||||
|
}
|
35
weed/mount/weedfs_file_write.go
Normal file
35
weed/mount/weedfs_file_write.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package mount
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hanwen/go-fuse/v2/fuse"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data
|
||||||
|
*
|
||||||
|
* Write should return exactly the number of bytes requested
|
||||||
|
* except on error. An exception to this is when the file has
|
||||||
|
* been opened in 'direct_io' mode, in which case the return value
|
||||||
|
* of the write system call will reflect the return value of this
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
|
||||||
|
* expected to reset the setuid and setgid bits.
|
||||||
|
*
|
||||||
|
* fi->fh will contain the value set by the open method, or will
|
||||||
|
* be undefined if the open method didn't set any value.
|
||||||
|
*
|
||||||
|
* Valid replies:
|
||||||
|
* fuse_reply_write
|
||||||
|
* fuse_reply_err
|
||||||
|
*
|
||||||
|
* @param req request handle
|
||||||
|
* @param ino the inode number
|
||||||
|
* @param buf data to write
|
||||||
|
* @param size number of bytes to write
|
||||||
|
* @param off offset to write to
|
||||||
|
* @param fi file information
|
||||||
|
*/
|
||||||
|
func (wfs *WFS) Write(cancel <-chan struct{}, in *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
|
||||||
|
return 0, fuse.ENOSYS
|
||||||
|
}
|
Reference in New Issue
Block a user