Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix sync: copying times, owner and mode not follow link #4151

Merged
merged 4 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ func (j *juiceFS) readDirSorted(dirname string, followLink bool) ([]*mEntry, sys
}

func (j *juiceFS) Chtimes(key string, mtime time.Time) error {
f, err := j.jfs.Open(ctx, j.path(key), 0)
f, err := j.jfs.Lopen(ctx, j.path(key), 0)
if err != 0 {
return err
}
Expand All @@ -318,7 +318,7 @@ func (j *juiceFS) Chmod(key string, mode os.FileMode) error {
func (j *juiceFS) Chown(key string, owner, group string) error {
uid := utils.LookupUser(owner)
gid := utils.LookupGroup(group)
f, err := j.jfs.Open(ctx, j.path(key), 0)
f, err := j.jfs.Lopen(ctx, j.path(key), 0)
if err != 0 {
return err
}
Expand Down
13 changes: 11 additions & 2 deletions pkg/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,16 @@ func (fs *FileSystem) StatFS(ctx meta.Context) (totalspace uint64, availspace ui
return
}

func (fs *FileSystem) Open(ctx meta.Context, path string, flags uint32) (f *File, err syscall.Errno) {
// open file without following symlink
func (fs *FileSystem) Lopen(ctx meta.Context, path string, flags uint32) (f *File, err syscall.Errno) {
return fs.open(ctx, path, flags, false)
}

func (fs *FileSystem) Open(ctx meta.Context, path string, flags uint32) (*File, syscall.Errno) {
return fs.open(ctx, path, flags, true)
}

func (fs *FileSystem) open(ctx meta.Context, path string, flags uint32, followLink bool) (f *File, err syscall.Errno) {
_, task := trace.NewTask(context.TODO(), "Open")
defer task.End()
l := vfs.NewLogContext(ctx)
Expand All @@ -356,7 +365,7 @@ func (fs *FileSystem) Open(ctx meta.Context, path string, flags uint32) (f *File
defer func() { fs.log(l, "Lookup (%s): %s", path, errstr(err)) }()
}
var fi *FileStat
fi, err = fs.resolve(ctx, path, true)
fi, err = fs.resolve(ctx, path, followLink)
if err != 0 {
return
}
Expand Down
8 changes: 1 addition & 7 deletions pkg/object/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"sort"
"strconv"
"strings"
"time"

"github.com/juicedata/juicefs/pkg/utils"
)
Expand Down Expand Up @@ -322,11 +321,6 @@ func (d *filestore) List(prefix, marker, delimiter string, limit int64, followLi
return objs, nil
}

func (d *filestore) Chtimes(key string, mtime time.Time) error {
p := d.path(key)
return os.Chtimes(p, mtime, mtime)
}

func (d *filestore) Chmod(key string, mode os.FileMode) error {
p := d.path(key)
return os.Chmod(p, mode)
Expand All @@ -336,7 +330,7 @@ func (d *filestore) Chown(key string, owner, group string) error {
p := d.path(key)
uid := utils.LookupUser(owner)
gid := utils.LookupGroup(group)
return os.Chown(p, uid, gid)
return os.Lchown(p, uid, gid)
}

func newDisk(root, accesskey, secretkey, token string) (ObjectStorage, error) {
Expand Down
22 changes: 22 additions & 0 deletions pkg/object/file_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ package object
import (
"os"
"syscall"
"time"

"github.com/juicedata/juicefs/pkg/utils"
"github.com/pkg/sftp"
"golang.org/x/sys/unix"
)

func getOwnerGroup(info os.FileInfo) (string, string) {
Expand All @@ -39,3 +41,23 @@ func getOwnerGroup(info os.FileInfo) (string, string) {
}
return owner, group
}

func (d *filestore) Chtimes(key string, mtime time.Time) error {
p := d.path(key)
return lchtimes(p, mtime, mtime)
}

func lchtimes(name string, atime time.Time, mtime time.Time) error {
var utimes [2]unix.Timeval
set := func(i int, t time.Time) {
if !t.IsZero() {
utimes[i] = unix.NsecToTimeval(t.UnixNano())
}
}
set(0, atime)
set(1, mtime)
if e := unix.Lutimes(name, utimes[0:]); e != nil {
return &os.PathError{Op: "lchtimes", Path: name, Err: e}
}
return nil
}
10 changes: 9 additions & 1 deletion pkg/object/file_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package object

import "os"
import (
"os"
"time"
)

func getOwnerGroup(info os.FileInfo) (string, string) {
return "", ""
Expand All @@ -29,3 +32,8 @@ func lookupUser(name string) int {
func lookupGroup(name string) int {
return 0
}

func (d *filestore) Chtimes(key string, mtime time.Time) error {
p := d.path(key)
return os.Chtimes(p, mtime, mtime)
}
14 changes: 8 additions & 6 deletions pkg/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,14 @@ func needCopyPerms(o1, o2 object.Object) bool {
return f2.Mode() != f1.Mode() || f2.Owner() != f1.Owner() || f2.Group() != f1.Group()
}

func copyPerms(dst object.ObjectStorage, obj object.Object) {
func copyPerms(dst object.ObjectStorage, obj object.Object, config *Config) {
start := time.Now()
key := obj.Key()
fi := obj.(object.File)
if err := dst.(object.FileSystem).Chmod(key, fi.Mode()); err != nil {
logger.Warnf("Chmod %s to %o: %s", key, fi.Mode(), err)
if !fi.IsSymlink() || !config.Links {
if err := dst.(object.FileSystem).Chmod(key, fi.Mode()); err != nil {
logger.Warnf("Chmod %s to %o: %s", key, fi.Mode(), err)
}
}
if err := dst.(object.FileSystem).Chown(key, fi.Owner(), fi.Group()); err != nil {
logger.Warnf("Chown %s to (%s,%s): %s", key, fi.Owner(), fi.Group(), err)
Expand Down Expand Up @@ -554,7 +556,7 @@ func worker(tasks <-chan object.Object, src, dst object.ObjectStorage, config *C
if config.Dry {
logger.Debugf("Will copy permissions for %s", key)
} else {
copyPerms(dst, obj)
copyPerms(dst, obj, config)
}
copied.Increment()
case markChecksum:
Expand All @@ -573,7 +575,7 @@ func worker(tasks <-chan object.Object, src, dst object.ObjectStorage, config *C
} else if config.Perms {
if o, e := dst.Head(key); e == nil {
if needCopyPerms(obj, o) {
copyPerms(dst, obj)
copyPerms(dst, obj, config)
copied.Increment()
} else {
skipped.Increment()
Expand Down Expand Up @@ -618,7 +620,7 @@ func worker(tasks <-chan object.Object, src, dst object.ObjectStorage, config *C
}
}
if config.Perms {
copyPerms(dst, obj)
copyPerms(dst, obj, config)
}
copied.Increment()
} else {
Expand Down