mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
Merge pull request #2105 from Woellchen/current_and_parent_dot_directories
Return artificial . and .. directories
This commit is contained in:
commit
0a5388744c
|
@ -5,15 +5,18 @@ package command
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
||||
|
||||
"github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
|
||||
|
||||
"github.com/seaweedfs/fuse"
|
||||
|
@ -49,6 +52,21 @@ func runMount(cmd *Command, args []string) bool {
|
|||
return RunMount(&mountOptions, os.FileMode(umask))
|
||||
}
|
||||
|
||||
func getParentInode(mountDir string) (uint64, error) {
|
||||
parentDir := filepath.Clean(filepath.Join(mountDir, ".."))
|
||||
fi, err := os.Stat(parentDir)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
stat, ok := fi.Sys().(*syscall.Stat_t)
|
||||
if !ok {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return stat.Ino, nil
|
||||
}
|
||||
|
||||
func RunMount(option *MountOptions, umask os.FileMode) bool {
|
||||
|
||||
filers := strings.Split(*option.filer, ",")
|
||||
|
@ -85,13 +103,19 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
|
|||
|
||||
filerMountRootPath := *option.filerMountRootPath
|
||||
dir := util.ResolvePath(*option.dir)
|
||||
chunkSizeLimitMB := *mountOptions.chunkSizeLimitMB
|
||||
parentInode, err := getParentInode(dir)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to retrieve inode for parent directory of %s: %v", dir, err)
|
||||
return true
|
||||
}
|
||||
|
||||
fmt.Printf("This is SeaweedFS version %s %s %s\n", util.Version(), runtime.GOOS, runtime.GOARCH)
|
||||
if dir == "" {
|
||||
fmt.Printf("Please specify the mount directory via \"-dir\"")
|
||||
return false
|
||||
}
|
||||
|
||||
chunkSizeLimitMB := *mountOptions.chunkSizeLimitMB
|
||||
if chunkSizeLimitMB <= 0 {
|
||||
fmt.Printf("Please specify a reasonable buffer size.")
|
||||
return false
|
||||
|
@ -199,6 +223,7 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
|
|||
MountMode: mountMode,
|
||||
MountCtime: fileInfo.ModTime(),
|
||||
MountMtime: time.Now(),
|
||||
MountParentInode: parentInode,
|
||||
Umask: umask,
|
||||
VolumeServerAccess: *mountOptions.volumeServerAccess,
|
||||
Cipher: cipher,
|
||||
|
|
|
@ -54,28 +54,27 @@ func (dir *Dir) Id() uint64 {
|
|||
|
||||
func (dir *Dir) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||
|
||||
// https://github.com/bazil/fuse/issues/196
|
||||
attr.Valid = time.Second
|
||||
|
||||
if dir.FullPath() == dir.wfs.option.FilerMountRootPath {
|
||||
dir.setRootDirAttributes(attr)
|
||||
glog.V(3).Infof("root dir Attr %s, attr: %+v", dir.FullPath(), attr)
|
||||
return nil
|
||||
}
|
||||
|
||||
entry, err := dir.maybeLoadEntry()
|
||||
if err != nil {
|
||||
glog.V(3).Infof("dir Attr %s, err: %+v", dir.FullPath(), err)
|
||||
return err
|
||||
}
|
||||
|
||||
// https://github.com/bazil/fuse/issues/196
|
||||
attr.Valid = time.Second
|
||||
attr.Inode = dir.Id()
|
||||
attr.Mode = os.FileMode(entry.Attributes.FileMode) | os.ModeDir
|
||||
attr.Mtime = time.Unix(entry.Attributes.Mtime, 0)
|
||||
attr.Crtime = time.Unix(entry.Attributes.Crtime, 0)
|
||||
attr.Ctime = time.Unix(entry.Attributes.Crtime, 0)
|
||||
attr.Atime = time.Unix(entry.Attributes.Mtime, 0)
|
||||
attr.Gid = entry.Attributes.Gid
|
||||
attr.Uid = entry.Attributes.Uid
|
||||
|
||||
if dir.FullPath() == dir.wfs.option.FilerMountRootPath {
|
||||
attr.BlockSize = blockSize
|
||||
}
|
||||
|
||||
glog.V(4).Infof("dir Attr %s, attr: %+v", dir.FullPath(), attr)
|
||||
|
||||
return nil
|
||||
|
@ -93,20 +92,6 @@ func (dir *Dir) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *f
|
|||
return getxattr(entry, req, resp)
|
||||
}
|
||||
|
||||
func (dir *Dir) setRootDirAttributes(attr *fuse.Attr) {
|
||||
// attr.Inode = 1 // filer2.FullPath(dir.Path).AsInode()
|
||||
attr.Valid = time.Second
|
||||
attr.Inode = dir.Id()
|
||||
attr.Uid = dir.wfs.option.MountUid
|
||||
attr.Gid = dir.wfs.option.MountGid
|
||||
attr.Mode = dir.wfs.option.MountMode
|
||||
attr.Crtime = dir.wfs.option.MountCtime
|
||||
attr.Ctime = dir.wfs.option.MountCtime
|
||||
attr.Mtime = dir.wfs.option.MountMtime
|
||||
attr.Atime = dir.wfs.option.MountMtime
|
||||
attr.BlockSize = blockSize
|
||||
}
|
||||
|
||||
func (dir *Dir) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
||||
// fsync works at OS level
|
||||
// write the file chunks to the filerGrpcAddress
|
||||
|
@ -375,6 +360,28 @@ func (dir *Dir) ReadDirAll(ctx context.Context) (ret []fuse.Dirent, err error) {
|
|||
glog.Errorf("list meta cache: %v", listErr)
|
||||
return nil, fuse.EIO
|
||||
}
|
||||
|
||||
// create proper . and .. directories
|
||||
ret = append(ret, fuse.Dirent{
|
||||
Inode: dirPath.AsInode(),
|
||||
Name: ".",
|
||||
Type: fuse.DT_Dir,
|
||||
})
|
||||
|
||||
// return the correct parent inode for the mount root
|
||||
var inode uint64
|
||||
if string(dirPath) == dir.wfs.option.FilerMountRootPath {
|
||||
inode = dir.wfs.option.MountParentInode
|
||||
} else {
|
||||
inode = util.FullPath(dir.parent.FullPath()).AsInode()
|
||||
}
|
||||
|
||||
ret = append(ret, fuse.Dirent{
|
||||
Inode: inode,
|
||||
Name: "..",
|
||||
Type: fuse.DT_Dir,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,6 @@ package filesys
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
||||
"github.com/chrislusf/seaweedfs/weed/wdclient"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
@ -14,6 +11,10 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
||||
"github.com/chrislusf/seaweedfs/weed/wdclient"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/chrislusf/seaweedfs/weed/util/grace"
|
||||
|
@ -51,6 +52,7 @@ type Option struct {
|
|||
MountMode os.FileMode
|
||||
MountCtime time.Time
|
||||
MountMtime time.Time
|
||||
MountParentInode uint64
|
||||
|
||||
VolumeServerAccess string // how to access volume servers
|
||||
Cipher bool // whether encrypt data on volume server
|
||||
|
|
|
@ -113,6 +113,21 @@ func (wfs *WFS) maybeLoadEntry(dir, name string) (entry *filer_pb.Entry, err err
|
|||
fullpath := util.NewFullPath(dir, name)
|
||||
// glog.V(3).Infof("read entry cache miss %s", fullpath)
|
||||
|
||||
// return a valid entry for the mount root
|
||||
if string(fullpath) == wfs.option.FilerMountRootPath {
|
||||
return &filer_pb.Entry{
|
||||
Name: wfs.option.FilerMountRootPath,
|
||||
IsDirectory: true,
|
||||
Attributes: &filer_pb.FuseAttributes{
|
||||
Mtime: wfs.option.MountMtime.Unix(),
|
||||
FileMode: uint32(wfs.option.MountMode),
|
||||
Uid: wfs.option.MountUid,
|
||||
Gid: wfs.option.MountGid,
|
||||
Crtime: wfs.option.MountCtime.Unix(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// read from async meta cache
|
||||
meta_cache.EnsureVisited(wfs.metaCache, wfs, util.FullPath(dir))
|
||||
cachedEntry, cacheErr := wfs.metaCache.FindEntry(context.Background(), fullpath)
|
||||
|
|
Loading…
Reference in a new issue