vfs: Implement Create support (#13)

* vfs: Implement Create support

Signed-off-by: Xuanwo <github@xuanwo.io>

* Format code

Signed-off-by: Xuanwo <github@xuanwo.io>
This commit is contained in:
Xuanwo 2021-07-16 14:37:12 +08:00 committed by GitHub
parent 0b64b1feef
commit a1d9d0c129
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 146 additions and 7 deletions

View File

@ -95,6 +95,11 @@ func fillAttrOut(i *vfs.Inode, out *fuse.AttrOut) fuse.Status {
return fuse.OK return fuse.OK
} }
func fillOpenOut(fh *vfs.FileHandle, out *fuse.OpenOut) fuse.Status {
out.Fh = fh.ID
return fuse.OK
}
func parseError(err error) fuse.Status { func parseError(err error) fuse.Status {
switch { switch {
case errors.Is(err, services.ErrObjectNotExist): case errors.Is(err, services.ErrObjectNotExist):
@ -303,7 +308,15 @@ func (fs *FS) Create(cancel <-chan struct{}, input *fuse.CreateIn, name string,
return fuse.EINVAL return fuse.EINVAL
} }
// Implement me i, fh, err := fs.fs.Create(ino.ID, name)
if err != nil {
fs.logger.Error("create", zap.Error(err))
return fuse.EAGAIN
}
fs.logger.Info("start fill open out")
fillOpenOut(fh, &out.OpenOut)
fs.logger.Info("start fill entry out")
fillEntryOut(i, &out.EntryOut)
return fuse.OK return fuse.OK
} }
@ -320,7 +333,12 @@ func (fs *FS) Open(cancel <-chan struct{}, input *fuse.OpenIn, out *fuse.OpenOut
return fuse.ENOENT return fuse.ENOENT
} }
panic("implement me") fh, err := fs.fs.CreateFileHandle(ino)
if err != nil {
fs.logger.Error("create file handle", zap.Error(err))
return
}
return fillOpenOut(fh, out)
} }
func (fs *FS) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) { func (fs *FS) Read(cancel <-chan struct{}, input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) {
@ -344,7 +362,12 @@ func (fs *FS) SetLkw(cancel <-chan struct{}, input *fuse.LkIn) (code fuse.Status
} }
func (fs *FS) Release(cancel <-chan struct{}, input *fuse.ReleaseIn) { func (fs *FS) Release(cancel <-chan struct{}, input *fuse.ReleaseIn) {
panic("implement me") err := fs.fs.DeleteFileHandle(input.Fh)
if err != nil {
fs.logger.Error("release",
zap.Uint64("file_handle", input.Fh),
zap.Error(err))
}
} }
func (fs *FS) Write(cancel <-chan struct{}, input *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) { func (fs *FS) Write(cancel <-chan struct{}, input *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
@ -356,7 +379,8 @@ func (fs *FS) CopyFileRange(cancel <-chan struct{}, input *fuse.CopyFileRangeIn)
} }
func (fs *FS) Flush(cancel <-chan struct{}, input *fuse.FlushIn) fuse.Status { func (fs *FS) Flush(cancel <-chan struct{}, input *fuse.FlushIn) fuse.Status {
panic("implement me") // FIXME: maybe we need to write data here.
return fuse.OK
} }
func (fs *FS) Fsync(cancel <-chan struct{}, input *fuse.FsyncIn) (code fuse.Status) { func (fs *FS) Fsync(cancel <-chan struct{}, input *fuse.FsyncIn) (code fuse.Status) {

View File

@ -2,9 +2,11 @@ package vfs
import ( import (
"errors" "errors"
"github.com/beyondstorage/beyond-fs/meta"
"github.com/beyondstorage/go-storage/v4/types"
"sync" "sync"
"github.com/beyondstorage/go-storage/v4/types"
"github.com/beyondstorage/beyond-fs/meta"
) )
type dirHandleMap struct { type dirHandleMap struct {

47
vfs/file.go Normal file
View File

@ -0,0 +1,47 @@
package vfs
import (
"sync"
"github.com/beyondstorage/beyond-fs/meta"
)
type fileHandleMap struct {
lock sync.Mutex
m map[uint64]*FileHandle
}
func newFileHandleMap() *fileHandleMap {
return &fileHandleMap{
m: make(map[uint64]*FileHandle),
}
}
func (fhm *fileHandleMap) Get(id uint64) *FileHandle {
fhm.lock.Lock()
defer fhm.lock.Unlock()
return fhm.m[id]
}
func (fhm *fileHandleMap) Set(id uint64, dh *FileHandle) {
fhm.lock.Lock()
defer fhm.lock.Unlock()
fhm.m[id] = dh
}
func (fhm *fileHandleMap) Delete(id uint64) {
fhm.lock.Lock()
defer fhm.lock.Unlock()
delete(fhm.m, id)
}
type FileHandle struct {
ID uint64
ino *Inode
fs *FS
meta meta.Service
}

View File

@ -1,7 +1,9 @@
package vfs package vfs
import ( import (
"bytes"
"fmt" "fmt"
"time"
_ "github.com/beyondstorage/go-service-fs/v3" _ "github.com/beyondstorage/go-service-fs/v3"
_ "github.com/beyondstorage/go-service-s3/v2" _ "github.com/beyondstorage/go-service-s3/v2"
@ -32,6 +34,7 @@ type FS struct {
meta meta.Service meta meta.Service
dhm *dirHandleMap dhm *dirHandleMap
fhm *fileHandleMap
logger *zap.Logger logger *zap.Logger
} }
@ -57,6 +60,7 @@ func NewFS(cfg *Config) (fs *FS, err error) {
meta: metaSrv, meta: metaSrv,
dhm: newDirHandleMap(), dhm: newDirHandleMap(),
fhm: newFileHandleMap(),
logger: cfg.Logger, logger: cfg.Logger,
} }
@ -71,6 +75,39 @@ func NewFS(cfg *Config) (fs *FS, err error) {
return fs, err return fs, err
} }
func (fs *FS) Create(parent uint64, name string) (ino *Inode, fh *FileHandle, err error) {
// FIXME: we need to handle file exists.
p, err := fs.GetInode(parent)
if err != nil {
return nil, nil, err
}
path := p.GetEntryPath(name)
_, err = fs.s.Write(path, bytes.NewReader([]byte{}), 0)
if err != nil {
fs.logger.Error("write", zap.String("path", path), zap.Error(err))
return nil, nil, err
}
o := fs.s.Create(path)
o.Path = path
o.Mode = types.ModeRead
o.SetContentLength(0)
o.SetLastModified(time.Now())
ino = newInode(parent, o)
err = fs.SetInode(ino)
if err != nil {
return
}
fh, err = fs.CreateFileHandle(ino)
if err != nil {
return
}
return
}
func (fs *FS) Delete(parent uint64, name string) (err error) { func (fs *FS) Delete(parent uint64, name string) (err error) {
ino, err := fs.GetEntry(parent, name) ino, err := fs.GetEntry(parent, name)
if err != nil { if err != nil {
@ -95,6 +132,26 @@ func (fs *FS) DeleteDir(path string) (err error) {
panic("implement me") panic("implement me")
} }
func (fs *FS) CreateFileHandle(ino *Inode) (fh *FileHandle, err error) {
fh = &FileHandle{
ID: NextHandle(),
ino: ino,
fs: fs,
meta: fs.meta,
}
fs.fhm.Set(fh.ID, fh)
return fh, nil
}
func (fs *FS) GetFileHandle(fhid uint64) (fh *FileHandle, err error) {
return fs.fhm.Get(fhid), nil
}
func (fs *FS) DeleteFileHandle(fhid uint64) (err error) {
fs.fhm.Delete(fhid)
return nil
}
func (fs *FS) CreateDirHandle(ino *Inode) (dh *DirHandle, err error) { func (fs *FS) CreateDirHandle(ino *Inode) (dh *DirHandle, err error) {
it, err := fs.s.List(ino.Path, pairs.WithListMode(types.ListModeDir)) it, err := fs.s.List(ino.Path, pairs.WithListMode(types.ListModeDir))
if err != nil { if err != nil {

View File

@ -1,10 +1,12 @@
package vfs package vfs
import ( import (
"github.com/beyondstorage/go-storage/v4/types" "fmt"
"os" "os"
"path" "path"
"time" "time"
"github.com/beyondstorage/go-storage/v4/types"
) )
//go:generate go run github.com/tinylib/msgp //go:generate go run github.com/tinylib/msgp
@ -27,6 +29,13 @@ func (ino *Inode) IsDir() bool {
return ino.Mode&uint32(os.ModeDir) != 0 return ino.Mode&uint32(os.ModeDir) != 0
} }
func (ino *Inode) GetEntryPath(name string) string {
if ino.Path == "" {
return name
}
return fmt.Sprintf("%s/%s", ino.Path, name)
}
func newInode(parent uint64, o *types.Object) *Inode { func newInode(parent uint64, o *types.Object) *Inode {
ino := &Inode{ ino := &Inode{
ID: NextInodeID(), ID: NextInodeID(),