chrislu
3 years ago
8 changed files with 242 additions and 126 deletions
-
16weed/mount/filehandle.go
-
79weed/mount/filehandle_map.go
-
1weed/mount/inode_to_path.go
-
2weed/mount/weedfs.go
-
129weed/mount/weedfs_file_io.go
-
34weed/mount/weedfs_file_read.go
-
70weed/mount/weedfs_file_sync.go
-
35weed/mount/weedfs_file_write.go
@ -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) |
|||
} |
@ -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) |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
@ -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 |
|||
} |
@ -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 |
|||
} |
@ -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 |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue