Browse Source

Merge pull request #2105 from Woellchen/current_and_parent_dot_directories

Return artificial . and .. directories
pull/2112/head
Chris Lu 4 years ago
committed by GitHub
parent
commit
0a5388744c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 29
      weed/command/mount_std.go
  2. 55
      weed/filesys/dir.go
  3. 18
      weed/filesys/wfs.go
  4. 15
      weed/filesys/xattr.go

29
weed/command/mount_std.go

@ -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,

55
weed/filesys/dir.go

@ -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
} }

18
weed/filesys/wfs.go

@ -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
MountGid uint32
MountMode os.FileMode
MountCtime time.Time
MountMtime time.Time
MountUid uint32
MountGid uint32
MountMode os.FileMode
MountCtime 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

15
weed/filesys/xattr.go

@ -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…
Cancel
Save