From a99f63cb4d8d1bcbdeba3c735947ca9992914d5c Mon Sep 17 00:00:00 2001 From: limd Date: Wed, 23 Sep 2020 11:26:01 +0800 Subject: [PATCH 1/8] 1.add S3 copy directory function 2.fixed the problem of empty directory when S3 deleted the directory --- weed/s3api/s3api_object_copy_handlers.go | 22 ++++++++++++++++------ weed/s3api/s3api_object_handlers.go | 7 ++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/weed/s3api/s3api_object_copy_handlers.go b/weed/s3api/s3api_object_copy_handlers.go index 99a852c0c..7c6d36f20 100644 --- a/weed/s3api/s3api_object_copy_handlers.go +++ b/weed/s3api/s3api_object_copy_handlers.go @@ -1,6 +1,7 @@ package s3api import ( + "crypto/md5" "fmt" "github.com/chrislusf/seaweedfs/weed/s3api/s3err" "net/http" @@ -82,7 +83,7 @@ type CopyPartResult struct { func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Request) { // https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjctsUsingRESTMPUapi.html // https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html - dstBucket, _ := getBucketAndObject(r) + dstBucket, dstObject := getBucketAndObject(r) // Copy source path. cpSrcPath, err := url.QueryUnescape(r.Header.Get("X-Amz-Copy-Source")) @@ -127,11 +128,20 @@ func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Req } defer dataReader.Close() - etag, errCode := s3a.putToFiler(r, dstUrl, dataReader) - - if errCode != s3err.ErrNone { - writeErrorResponse(w, errCode, r.URL) - return + var etag string + if strings.HasSuffix(srcObject, "/") { + if err := s3a.mkdir(s3a.option.BucketsPath, dstBucket+dstObject, nil); err != nil { + writeErrorResponse(w, s3err.ErrInternalError, r.URL) + return + } + etag = fmt.Sprintf("%x", md5.New().Sum(nil)) + } else { + _etag, errCode := s3a.putToFiler(r, dstUrl, dataReader) + etag = _etag + if errCode != s3err.ErrNone { + writeErrorResponse(w, errCode, r.URL) + return + } } setEtag(w, etag) diff --git a/weed/s3api/s3api_object_handlers.go b/weed/s3api/s3api_object_handlers.go index bb03048c8..cb85aa9fe 100644 --- a/weed/s3api/s3api_object_handlers.go +++ b/weed/s3api/s3api_object_handlers.go @@ -112,6 +112,12 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque bucket, object := getBucketAndObject(r) + response, _ := s3a.listFilerEntries(bucket, object, 1, "", "/") + if len(response.Contents) != 0 && strings.HasSuffix(r.URL.Path, "/") { + w.WriteHeader(http.StatusNoContent) + return + } + destUrl := fmt.Sprintf("http://%s%s/%s%s?recursive=true", s3a.option.Filer, s3a.option.BucketsPath, bucket, object) @@ -121,7 +127,6 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque } w.WriteHeader(http.StatusNoContent) }) - } // / ObjectIdentifier carries key name for the object to delete. From 1892677b22188cc2f5c4a495fd727fc9ed75b6b5 Mon Sep 17 00:00:00 2001 From: limd Date: Wed, 23 Sep 2020 13:15:06 +0800 Subject: [PATCH 2/8] fixed the problem of empty directory when S3 deleted the directory --- weed/s3api/s3api_object_handlers.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/weed/s3api/s3api_object_handlers.go b/weed/s3api/s3api_object_handlers.go index cb85aa9fe..994726565 100644 --- a/weed/s3api/s3api_object_handlers.go +++ b/weed/s3api/s3api_object_handlers.go @@ -183,6 +183,11 @@ func (s3a *S3ApiServer) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *h s3a.WithFilerClient(func(client filer_pb.SeaweedFilerClient) error { for _, object := range deleteObjects.Objects { + response, _ := s3a.listFilerEntries(bucket, object.ObjectName, 1, "", "/") + if len(response.Contents) != 0 && strings.HasSuffix(object.ObjectName, "/") { + continue + } + lastSeparator := strings.LastIndex(object.ObjectName, "/") parentDirectoryPath, entryName, isDeleteData, isRecursive := "/", object.ObjectName, true, true if lastSeparator > 0 && lastSeparator+1 < len(object.ObjectName) { From 8f9f29b7733471369e7d7b41d26a0da41a5fc1fd Mon Sep 17 00:00:00 2001 From: limd Date: Wed, 23 Sep 2020 13:33:13 +0800 Subject: [PATCH 3/8] fixed the problem of empty directory when S3 deleted the directory --- weed/s3api/s3api_object_handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weed/s3api/s3api_object_handlers.go b/weed/s3api/s3api_object_handlers.go index 994726565..c5f0dabf6 100644 --- a/weed/s3api/s3api_object_handlers.go +++ b/weed/s3api/s3api_object_handlers.go @@ -113,7 +113,7 @@ func (s3a *S3ApiServer) DeleteObjectHandler(w http.ResponseWriter, r *http.Reque bucket, object := getBucketAndObject(r) response, _ := s3a.listFilerEntries(bucket, object, 1, "", "/") - if len(response.Contents) != 0 && strings.HasSuffix(r.URL.Path, "/") { + if len(response.Contents) != 0 && strings.HasSuffix(object, "/") { w.WriteHeader(http.StatusNoContent) return } From d506080c36297f5b9320a292e5f9e0896bd3bccb Mon Sep 17 00:00:00 2001 From: limd Date: Wed, 23 Sep 2020 14:29:53 +0800 Subject: [PATCH 4/8] rollback --- weed/s3api/s3api_object_copy_handlers.go | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/weed/s3api/s3api_object_copy_handlers.go b/weed/s3api/s3api_object_copy_handlers.go index 7c6d36f20..99a852c0c 100644 --- a/weed/s3api/s3api_object_copy_handlers.go +++ b/weed/s3api/s3api_object_copy_handlers.go @@ -1,7 +1,6 @@ package s3api import ( - "crypto/md5" "fmt" "github.com/chrislusf/seaweedfs/weed/s3api/s3err" "net/http" @@ -83,7 +82,7 @@ type CopyPartResult struct { func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Request) { // https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjctsUsingRESTMPUapi.html // https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html - dstBucket, dstObject := getBucketAndObject(r) + dstBucket, _ := getBucketAndObject(r) // Copy source path. cpSrcPath, err := url.QueryUnescape(r.Header.Get("X-Amz-Copy-Source")) @@ -128,20 +127,11 @@ func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Req } defer dataReader.Close() - var etag string - if strings.HasSuffix(srcObject, "/") { - if err := s3a.mkdir(s3a.option.BucketsPath, dstBucket+dstObject, nil); err != nil { - writeErrorResponse(w, s3err.ErrInternalError, r.URL) - return - } - etag = fmt.Sprintf("%x", md5.New().Sum(nil)) - } else { - _etag, errCode := s3a.putToFiler(r, dstUrl, dataReader) - etag = _etag - if errCode != s3err.ErrNone { - writeErrorResponse(w, errCode, r.URL) - return - } + etag, errCode := s3a.putToFiler(r, dstUrl, dataReader) + + if errCode != s3err.ErrNone { + writeErrorResponse(w, errCode, r.URL) + return } setEtag(w, etag) From 9b21ec27e46ed68ef1daa4a94fd1a4b621ab39fe Mon Sep 17 00:00:00 2001 From: limd Date: Wed, 23 Sep 2020 18:35:37 +0800 Subject: [PATCH 5/8] mount: auto created dir set corrct umask fix bug --- weed/command/mount.go | 2 +- weed/command/mount_std.go | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/weed/command/mount.go b/weed/command/mount.go index 7bf59cdc7..a359e52ac 100644 --- a/weed/command/mount.go +++ b/weed/command/mount.go @@ -44,7 +44,7 @@ func init() { mountOptions.cacheSizeMB = cmdMount.Flag.Int64("cacheCapacityMB", 1000, "local file chunk cache capacity in MB (0 will disable cache)") mountOptions.dataCenter = cmdMount.Flag.String("dataCenter", "", "prefer to write to the data center") mountOptions.allowOthers = cmdMount.Flag.Bool("allowOthers", true, "allows other users to access the file system") - mountOptions.umaskString = cmdMount.Flag.String("umask", "022", "octal umask, e.g., 022, 0111") + mountOptions.umaskString = cmdMount.Flag.String("umask", "000", "octal umask, e.g., 022, 0111") mountOptions.nonempty = cmdMount.Flag.Bool("nonempty", false, "allows the mounting over a non-empty directory") mountCpuProfile = cmdMount.Flag.String("cpuprofile", "", "cpu profile output file") mountMemProfile = cmdMount.Flag.String("memprofile", "", "memory profile output file") diff --git a/weed/command/mount_std.go b/weed/command/mount_std.go index 3947a871a..e84eebada 100644 --- a/weed/command/mount_std.go +++ b/weed/command/mount_std.go @@ -12,6 +12,7 @@ import ( "runtime" "strconv" "strings" + "syscall" "time" "github.com/seaweedfs/fuse" @@ -91,9 +92,11 @@ func RunMount(option *MountOptions, umask os.FileMode) bool { // detect mount folder mode if *option.dirAutoCreate { - os.MkdirAll(dir, os.FileMode(0777) &^ umask) + oldMask := syscall.Umask(0) + os.MkdirAll(dir, os.ModePerm&^umask) + syscall.Umask(oldMask) } - mountMode := os.ModeDir | 0755 + mountMode := os.ModeDir | 0777 fileInfo, err := os.Stat(dir) if err == nil { mountMode = os.ModeDir | fileInfo.Mode() From 59e91e9c7eacbafa3bcdc835eb7b78395210a082 Mon Sep 17 00:00:00 2001 From: limd Date: Thu, 24 Sep 2020 10:25:45 +0800 Subject: [PATCH 6/8] mount: fix k8s pvc mount directory permission --- weed/command/mount_std.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/weed/command/mount_std.go b/weed/command/mount_std.go index e84eebada..cbac35351 100644 --- a/weed/command/mount_std.go +++ b/weed/command/mount_std.go @@ -12,7 +12,6 @@ import ( "runtime" "strconv" "strings" - "syscall" "time" "github.com/seaweedfs/fuse" @@ -92,9 +91,8 @@ func RunMount(option *MountOptions, umask os.FileMode) bool { // detect mount folder mode if *option.dirAutoCreate { - oldMask := syscall.Umask(0) - os.MkdirAll(dir, os.ModePerm&^umask) - syscall.Umask(oldMask) + os.MkdirAll(dir, os.FileMode(0777)&^umask) + os.Chmod(dir, os.FileMode(0777)&^umask) } mountMode := os.ModeDir | 0777 fileInfo, err := os.Stat(dir) From cbca14edc562889f866ec5b1228f44950c48dff5 Mon Sep 17 00:00:00 2001 From: limd Date: Thu, 24 Sep 2020 18:07:16 +0800 Subject: [PATCH 7/8] mount: fix k8s pvc and os mount directory permission bug --- weed/command/mount_std.go | 28 ---------------------------- weed/filesys/dir.go | 6 +++--- weed/filesys/wfs.go | 8 +++----- 3 files changed, 6 insertions(+), 36 deletions(-) diff --git a/weed/command/mount_std.go b/weed/command/mount_std.go index cbac35351..7c0f56d3a 100644 --- a/weed/command/mount_std.go +++ b/weed/command/mount_std.go @@ -7,7 +7,6 @@ import ( "fmt" "github.com/chrislusf/seaweedfs/weed/filesys/meta_cache" "os" - "os/user" "path" "runtime" "strconv" @@ -87,35 +86,11 @@ func RunMount(option *MountOptions, umask os.FileMode) bool { fuse.Unmount(dir) - uid, gid := uint32(0), uint32(0) - // detect mount folder mode if *option.dirAutoCreate { os.MkdirAll(dir, os.FileMode(0777)&^umask) - os.Chmod(dir, os.FileMode(0777)&^umask) } - mountMode := os.ModeDir | 0777 fileInfo, err := os.Stat(dir) - if err == nil { - mountMode = os.ModeDir | fileInfo.Mode() - uid, gid = util.GetFileUidGid(fileInfo) - fmt.Printf("mount point owner uid=%d gid=%d mode=%s\n", uid, gid, fileInfo.Mode()) - } else { - fmt.Printf("can not stat %s\n", dir) - return false - } - - if uid == 0 { - if u, err := user.Current(); err == nil { - if parsedId, pe := strconv.ParseUint(u.Uid, 10, 32); pe == nil { - uid = uint32(parsedId) - } - if parsedId, pe := strconv.ParseUint(u.Gid, 10, 32); pe == nil { - gid = uint32(parsedId) - } - fmt.Printf("current uid=%d gid=%d\n", uid, gid) - } - } // mapping uid, gid uidGidMapper, err := meta_cache.NewUidGidMapper(*option.uidMap, *option.gidMap) @@ -175,9 +150,6 @@ func RunMount(option *MountOptions, umask os.FileMode) bool { CacheSizeMB: *option.cacheSizeMB, DataCenter: *option.dataCenter, EntryCacheTtl: 3 * time.Second, - MountUid: uid, - MountGid: gid, - MountMode: mountMode, MountCtime: fileInfo.ModTime(), MountMtime: time.Now(), Umask: umask, diff --git a/weed/filesys/dir.go b/weed/filesys/dir.go index fd16d74b9..cef0d6e3b 100644 --- a/weed/filesys/dir.go +++ b/weed/filesys/dir.go @@ -82,9 +82,9 @@ func (dir *Dir) Getxattr(ctx context.Context, req *fuse.GetxattrRequest, resp *f func (dir *Dir) setRootDirAttributes(attr *fuse.Attr) { attr.Inode = 1 // filer2.FullPath(dir.Path).AsInode() attr.Valid = time.Hour - attr.Uid = dir.wfs.option.MountUid - attr.Gid = dir.wfs.option.MountGid - attr.Mode = dir.wfs.option.MountMode + attr.Uid = dir.entry.Attributes.Uid + attr.Gid = dir.entry.Attributes.Gid + attr.Mode = os.FileMode(dir.entry.Attributes.FileMode) attr.Crtime = dir.wfs.option.MountCtime attr.Ctime = dir.wfs.option.MountCtime attr.Mtime = dir.wfs.option.MountMtime diff --git a/weed/filesys/wfs.go b/weed/filesys/wfs.go index 0335d5d98..fa491138e 100644 --- a/weed/filesys/wfs.go +++ b/weed/filesys/wfs.go @@ -37,9 +37,6 @@ type Option struct { EntryCacheTtl time.Duration Umask os.FileMode - MountUid uint32 - MountGid uint32 - MountMode os.FileMode MountCtime time.Time MountMtime time.Time @@ -88,7 +85,7 @@ func NewSeaweedFileSystem(option *Option) *WFS { cacheUniqueId := util.Md5String([]byte(option.FilerGrpcAddress + option.FilerMountRootPath + util.Version()))[0:4] cacheDir := path.Join(option.CacheDir, cacheUniqueId) if option.CacheSizeMB > 0 { - os.MkdirAll(cacheDir, os.FileMode(0777) &^ option.Umask) + os.MkdirAll(cacheDir, os.FileMode(0777)&^option.Umask) wfs.chunkCache = chunk_cache.NewTieredChunkCache(256, cacheDir, option.CacheSizeMB) } @@ -99,7 +96,8 @@ func NewSeaweedFileSystem(option *Option) *WFS { wfs.metaCache.Shutdown() }) - wfs.root = &Dir{name: wfs.option.FilerMountRootPath, wfs: wfs} + entry, _ := filer_pb.GetEntry(wfs, util.FullPath(wfs.option.FilerMountRootPath)) + wfs.root = &Dir{name: wfs.option.FilerMountRootPath, wfs: wfs, entry: entry} wfs.fsNodeCache = newFsCache(wfs.root) return wfs From 48c578410fea2128f81356250b2cd9d56074d878 Mon Sep 17 00:00:00 2001 From: limd Date: Fri, 25 Sep 2020 09:18:52 +0800 Subject: [PATCH 8/8] mount: rollback default value --- weed/command/mount.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weed/command/mount.go b/weed/command/mount.go index a359e52ac..7bf59cdc7 100644 --- a/weed/command/mount.go +++ b/weed/command/mount.go @@ -44,7 +44,7 @@ func init() { mountOptions.cacheSizeMB = cmdMount.Flag.Int64("cacheCapacityMB", 1000, "local file chunk cache capacity in MB (0 will disable cache)") mountOptions.dataCenter = cmdMount.Flag.String("dataCenter", "", "prefer to write to the data center") mountOptions.allowOthers = cmdMount.Flag.Bool("allowOthers", true, "allows other users to access the file system") - mountOptions.umaskString = cmdMount.Flag.String("umask", "000", "octal umask, e.g., 022, 0111") + mountOptions.umaskString = cmdMount.Flag.String("umask", "022", "octal umask, e.g., 022, 0111") mountOptions.nonempty = cmdMount.Flag.Bool("nonempty", false, "allows the mounting over a non-empty directory") mountCpuProfile = cmdMount.Flag.String("cpuprofile", "", "cpu profile output file") mountMemProfile = cmdMount.Flag.String("memprofile", "", "memory profile output file")