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

cmd/clone: skip trash files #5109

Merged
merged 5 commits into from
Sep 2, 2024
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
14 changes: 9 additions & 5 deletions cmd/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ package cmd

import (
"fmt"
"github.com/juicedata/juicefs/pkg/meta"
"github.com/juicedata/juicefs/pkg/utils"
"github.com/urfave/cli/v2"
"os"
"path"
"path/filepath"
"runtime"
"strings"

"github.com/juicedata/juicefs/pkg/meta"
"github.com/juicedata/juicefs/pkg/utils"
"github.com/urfave/cli/v2"
)

func cmdClone() *cli.Command {
Expand Down Expand Up @@ -71,6 +70,10 @@ func clone(ctx *cli.Context) error {
if err != nil {
return fmt.Errorf("lookup inode for %s: %s", srcPath, err)
}
srcParentIno, err := utils.GetFileInode(filepath.Dir(srcAbsPath))
if err != nil {
return fmt.Errorf("lookup inode for %s: %s", filepath.Dir(srcAbsPath), err)
}
dst := ctx.Args().Get(1)
if strings.HasSuffix(dst, string(filepath.Separator)) {
dst = filepath.Join(dst, filepath.Base(srcPath))
Expand Down Expand Up @@ -112,11 +115,12 @@ func clone(ctx *cli.Context) error {
cmode |= meta.CLONE_MODE_PRESERVE_ATTR
}
headerSize := 4 + 4
contentSize := 8 + 8 + 1 + uint32(len(dstName)) + 2 + 1
contentSize := 8 + 8 + 8 + 1 + uint32(len(dstName)) + 2 + 1
wb := utils.NewBuffer(uint32(headerSize) + contentSize)
wb.Put32(meta.Clone)
wb.Put32(contentSize)
wb.Put64(srcIno)
wb.Put64(srcParentIno)
wb.Put64(dstParentIno)
wb.Put8(uint8(len(dstName)))
wb.Put([]byte(dstName))
Expand Down
9 changes: 4 additions & 5 deletions pkg/meta/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -2436,13 +2436,12 @@ func (m *baseMeta) ScanDeletedObject(ctx Context, tss trashSliceScan, pss pendin
return eg.Wait()
}

func (m *baseMeta) Clone(ctx Context, srcIno, parent Ino, name string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno {
if isTrash(parent) {
zhijian-pro marked this conversation as resolved.
Show resolved Hide resolved
return syscall.EPERM
}
if parent == RootInode && name == TrashName {
func (m *baseMeta) Clone(ctx Context, srcParentIno, srcIno, parent Ino, name string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno {

if isTrash(srcIno) || isTrash(srcParentIno) || isTrash(parent) || (parent == RootInode && name == TrashName) {
return syscall.EPERM
}

if m.conf.ReadOnly {
return syscall.EROFS
}
Expand Down
12 changes: 9 additions & 3 deletions pkg/meta/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package meta
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"reflect"
Expand Down Expand Up @@ -2663,7 +2664,7 @@ func testClone(t *testing.T, m Meta) {
var count, total uint64
var cmode uint8
cmode |= CLONE_MODE_PRESERVE_ATTR
if eno := m.Clone(Background, dir1, cloneDir, cloneDstName, cmode, 022, &count, &total); eno != 0 {
if eno := m.Clone(Background, cloneDir, dir1, cloneDir, cloneDstName, cmode, 022, &count, &total); eno != 0 {
t.Fatalf("clone: %s", eno)
}
var entries1 []*Entry
Expand Down Expand Up @@ -2711,7 +2712,7 @@ func testClone(t *testing.T, m Meta) {
if iused-iused2 != 8 {
t.Fatalf("added inodes: %d", iused-iused2)
}
if eno := m.Clone(Background, dir1, cloneDir, "no_preserve", 0, 022, &count, &total); eno != 0 {
if eno := m.Clone(Background, RootInode, dir1, cloneDir, "no_preserve", 0, 022, &count, &total); eno != 0 {
t.Fatalf("clone: %s", eno)
}
var d2 Ino
Expand Down Expand Up @@ -2840,7 +2841,12 @@ func testClone(t *testing.T, m Meta) {
if len(nodes) != 2 {
t.Fatalf("find detached nodes error: %v", nodes)
}

if eno := m.Clone(Background, RootInode, TrashInode, cloneDir, "xxx", 0, 022, &count, &total); !errors.Is(eno, syscall.EPERM) {
t.Fatalf("cloning trash files are not supported")
}
if eno := m.Clone(Background, TrashInode+1, 1000, cloneDir, "xxx", 0, 022, &count, &total); !errors.Is(eno, syscall.EPERM) {
t.Fatalf("cloning files in the trash is not supported")
}
}

func checkEntryTree(t *testing.T, m Meta, srcIno, dstIno Ino, walkFunc func(srcEntry, dstEntry *Entry, dstIno Ino)) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/meta/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ type Meta interface {
// GetTreeSummary returns a summary in tree structure
GetTreeSummary(ctx Context, root *TreeSummary, depth, topN uint8, strict bool, updateProgress func(count uint64, bytes uint64)) syscall.Errno
// Clone a file or directory
Clone(ctx Context, srcIno, dstParentIno Ino, dstName string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno
Clone(ctx Context, srcParentIno, srcIno, dstParentIno Ino, dstName string, cmode uint8, cumask uint16, count, total *uint64) syscall.Errno
// GetPaths returns all paths of an inode
GetPaths(ctx Context, inode Ino) []string
// Check integrity of an absolute path and repair it if asked
Expand Down
3 changes: 2 additions & 1 deletion pkg/vfs/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,14 +316,15 @@ func (v *VFS) handleInternalMsg(ctx meta.Context, cmd uint32, r *utils.Buffer, o
case meta.Clone:
done := make(chan struct{})
srcIno := Ino(r.Get64())
srcParentIno := Ino(r.Get64())
dstParentIno := Ino(r.Get64())
dstName := string(r.Get(int(r.Get8())))
umask := r.Get16()
cmode := r.Get8()
var count, total uint64
var eno syscall.Errno
go func() {
if eno = v.Meta.Clone(ctx, srcIno, dstParentIno, dstName, cmode, umask, &count, &total); eno != 0 {
if eno = v.Meta.Clone(ctx, srcParentIno, srcIno, dstParentIno, dstName, cmode, umask, &count, &total); eno != 0 {
logger.Errorf("clone failed srcIno:%d,dstParentIno:%d,dstName:%s,cmode:%d,umask:%d,eno:%v", srcIno, dstParentIno, dstName, cmode, umask, eno)
}
close(done)
Expand Down
Loading