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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
||||||
|
|
||||||
"github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
|
"github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
|
||||||
|
|
||||||
"github.com/seaweedfs/fuse"
|
"github.com/seaweedfs/fuse"
|
||||||
|
@ -49,6 +52,21 @@ func runMount(cmd *Command, args []string) bool {
|
||||||
return RunMount(&mountOptions, os.FileMode(umask))
|
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 {
|
func RunMount(option *MountOptions, umask os.FileMode) bool {
|
||||||
|
|
||||||
filers := strings.Split(*option.filer, ",")
|
filers := strings.Split(*option.filer, ",")
|
||||||
|
@ -85,13 +103,19 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
|
||||||
|
|
||||||
filerMountRootPath := *option.filerMountRootPath
|
filerMountRootPath := *option.filerMountRootPath
|
||||||
dir := util.ResolvePath(*option.dir)
|
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)
|
fmt.Printf("This is SeaweedFS version %s %s %s\n", util.Version(), runtime.GOOS, runtime.GOARCH)
|
||||||
if dir == "" {
|
if dir == "" {
|
||||||
fmt.Printf("Please specify the mount directory via \"-dir\"")
|
fmt.Printf("Please specify the mount directory via \"-dir\"")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunkSizeLimitMB := *mountOptions.chunkSizeLimitMB
|
||||||
if chunkSizeLimitMB <= 0 {
|
if chunkSizeLimitMB <= 0 {
|
||||||
fmt.Printf("Please specify a reasonable buffer size.")
|
fmt.Printf("Please specify a reasonable buffer size.")
|
||||||
return false
|
return false
|
||||||
|
@ -199,6 +223,7 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
|
||||||
MountMode: mountMode,
|
MountMode: mountMode,
|
||||||
MountCtime: fileInfo.ModTime(),
|
MountCtime: fileInfo.ModTime(),
|
||||||
MountMtime: time.Now(),
|
MountMtime: time.Now(),
|
||||||
|
MountParentInode: parentInode,
|
||||||
Umask: umask,
|
Umask: umask,
|
||||||
VolumeServerAccess: *mountOptions.volumeServerAccess,
|
VolumeServerAccess: *mountOptions.volumeServerAccess,
|
||||||
Cipher: cipher,
|
Cipher: cipher,
|
||||||
|
|
|
@ -54,28 +54,27 @@ func (dir *Dir) Id() uint64 {
|
||||||
|
|
||||||
func (dir *Dir) Attr(ctx context.Context, attr *fuse.Attr) error {
|
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()
|
entry, err := dir.maybeLoadEntry()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(3).Infof("dir Attr %s,err: %+v", dir.FullPath(), err)
|
glog.V(3).Infof("dir Attr %s, err: %+v", dir.FullPath(), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/bazil/fuse/issues/196
|
||||||
|
attr.Valid = time.Second
|
||||||
attr.Inode = dir.Id()
|
attr.Inode = dir.Id()
|
||||||
attr.Mode = os.FileMode(entry.Attributes.FileMode) | os.ModeDir
|
attr.Mode = os.FileMode(entry.Attributes.FileMode) | os.ModeDir
|
||||||
attr.Mtime = time.Unix(entry.Attributes.Mtime, 0)
|
attr.Mtime = time.Unix(entry.Attributes.Mtime, 0)
|
||||||
attr.Crtime = time.Unix(entry.Attributes.Crtime, 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.Gid = entry.Attributes.Gid
|
||||||
attr.Uid = entry.Attributes.Uid
|
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)
|
glog.V(4).Infof("dir Attr %s, attr: %+v", dir.FullPath(), attr)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -93,20 +92,6 @@ func (dir *Dir) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *f
|
||||||
return getxattr(entry, req, resp)
|
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 {
|
func (dir *Dir) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
||||||
// fsync works at OS level
|
// fsync works at OS level
|
||||||
// write the file chunks to the filerGrpcAddress
|
// 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)
|
glog.Errorf("list meta cache: %v", listErr)
|
||||||
return nil, fuse.EIO
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,6 @@ package filesys
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chrislusf/seaweedfs/weed/filer"
|
|
||||||
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
|
||||||
"github.com/chrislusf/seaweedfs/weed/wdclient"
|
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
@ -14,6 +11,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/filer"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/storage/types"
|
||||||
|
"github.com/chrislusf/seaweedfs/weed/wdclient"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
"github.com/chrislusf/seaweedfs/weed/util/grace"
|
"github.com/chrislusf/seaweedfs/weed/util/grace"
|
||||||
|
@ -46,11 +47,12 @@ type Option struct {
|
||||||
DataCenter string
|
DataCenter string
|
||||||
Umask os.FileMode
|
Umask os.FileMode
|
||||||
|
|
||||||
MountUid uint32
|
MountUid uint32
|
||||||
MountGid uint32
|
MountGid uint32
|
||||||
MountMode os.FileMode
|
MountMode os.FileMode
|
||||||
MountCtime time.Time
|
MountCtime time.Time
|
||||||
MountMtime time.Time
|
MountMtime time.Time
|
||||||
|
MountParentInode uint64
|
||||||
|
|
||||||
VolumeServerAccess string // how to access volume servers
|
VolumeServerAccess string // how to access volume servers
|
||||||
Cipher bool // whether encrypt data on volume server
|
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)
|
fullpath := util.NewFullPath(dir, name)
|
||||||
// glog.V(3).Infof("read entry cache miss %s", fullpath)
|
// 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
|
// read from async meta cache
|
||||||
meta_cache.EnsureVisited(wfs.metaCache, wfs, util.FullPath(dir))
|
meta_cache.EnsureVisited(wfs.metaCache, wfs, util.FullPath(dir))
|
||||||
cachedEntry, cacheErr := wfs.metaCache.FindEntry(context.Background(), fullpath)
|
cachedEntry, cacheErr := wfs.metaCache.FindEntry(context.Background(), fullpath)
|
||||||
|
|
Loading…
Reference in a new issue