123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- package mount
- import (
- "context"
- "fmt"
- "github.com/hanwen/go-fuse/v2/fuse"
- "github.com/seaweedfs/seaweedfs/weed/filer"
- "github.com/seaweedfs/seaweedfs/weed/glog"
- "github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
- "syscall"
- "time"
- )
- /**
- * Create and open a file
- *
- * If the file does not exist, first create it with the specified
- * mode, and then open it.
- *
- * If this method is not implemented or under Linux kernel
- * versions earlier than 2.6.15, the mknod() and open() methods
- * will be called instead.
- */
- func (wfs *WFS) Create(cancel <-chan struct{}, in *fuse.CreateIn, name string, out *fuse.CreateOut) (code fuse.Status) {
- // if implemented, need to use
- // inode := wfs.inodeToPath.Lookup(entryFullPath)
- // to ensure nlookup counter
- return fuse.ENOSYS
- }
- /** Create a file node
- *
- * This is called for creation of all non-directory, non-symlink
- * nodes. If the filesystem defines a create() method, then for
- * regular files that will be called instead.
- */
- func (wfs *WFS) Mknod(cancel <-chan struct{}, in *fuse.MknodIn, name string, out *fuse.EntryOut) (code fuse.Status) {
- if wfs.IsOverQuota {
- return fuse.Status(syscall.ENOSPC)
- }
- if s := checkName(name); s != fuse.OK {
- return s
- }
- dirFullPath, code := wfs.inodeToPath.GetPath(in.NodeId)
- if code != fuse.OK {
- return
- }
- entryFullPath := dirFullPath.Child(name)
- fileMode := toOsFileMode(in.Mode)
- now := time.Now().Unix()
- inode := wfs.inodeToPath.AllocateInode(entryFullPath, now)
- newEntry := &filer_pb.Entry{
- Name: name,
- IsDirectory: false,
- Attributes: &filer_pb.FuseAttributes{
- Mtime: now,
- Crtime: now,
- FileMode: uint32(fileMode),
- Uid: in.Uid,
- Gid: in.Gid,
- TtlSec: wfs.option.TtlSec,
- Rdev: in.Rdev,
- Inode: inode,
- },
- }
- err := wfs.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
- wfs.mapPbIdFromLocalToFiler(newEntry)
- defer wfs.mapPbIdFromFilerToLocal(newEntry)
- request := &filer_pb.CreateEntryRequest{
- Directory: string(dirFullPath),
- Entry: newEntry,
- Signatures: []int32{wfs.signature},
- SkipCheckParentDirectory: true,
- }
- glog.V(1).Infof("mknod: %v", request)
- if err := filer_pb.CreateEntry(client, request); err != nil {
- glog.V(0).Infof("mknod %s: %v", entryFullPath, err)
- return err
- }
- if err := wfs.metaCache.InsertEntry(context.Background(), filer.FromPbEntry(request.Directory, request.Entry)); err != nil {
- return fmt.Errorf("local mknod %s: %v", entryFullPath, err)
- }
- return nil
- })
- glog.V(3).Infof("mknod %s: %v", entryFullPath, err)
- if err != nil {
- return fuse.EIO
- }
- // this is to increase nlookup counter
- inode = wfs.inodeToPath.Lookup(entryFullPath, newEntry.Attributes.Crtime, false, false, inode, true)
- wfs.outputPbEntry(out, inode, newEntry)
- return fuse.OK
- }
- /** Remove a file */
- func (wfs *WFS) Unlink(cancel <-chan struct{}, header *fuse.InHeader, name string) (code fuse.Status) {
- dirFullPath, code := wfs.inodeToPath.GetPath(header.NodeId)
- if code != fuse.OK {
- if code == fuse.ENOENT {
- return fuse.OK
- }
- return code
- }
- entryFullPath := dirFullPath.Child(name)
- entry, code := wfs.maybeLoadEntry(entryFullPath)
- if code != fuse.OK {
- if code == fuse.ENOENT {
- return fuse.OK
- }
- return code
- }
- // first, ensure the filer store can correctly delete
- glog.V(3).Infof("remove file: %v", entryFullPath)
- isDeleteData := entry != nil && entry.HardLinkCounter <= 1
- err := filer_pb.Remove(wfs, string(dirFullPath), name, isDeleteData, false, false, false, []int32{wfs.signature})
- if err != nil {
- glog.V(0).Infof("remove %s: %v", entryFullPath, err)
- return fuse.OK
- }
- // then, delete meta cache
- if err = wfs.metaCache.DeleteEntry(context.Background(), entryFullPath); err != nil {
- glog.V(3).Infof("local DeleteEntry %s: %v", entryFullPath, err)
- return fuse.EIO
- }
- wfs.metaCache.DeleteEntry(context.Background(), entryFullPath)
- wfs.inodeToPath.RemovePath(entryFullPath)
- return fuse.OK
- }
|