Skip to content

Commit

Permalink
meta: delete hardlinks directly if there's already same entry in the …
Browse files Browse the repository at this point in the history
…trash (#3706)

* meta: delete hardlinks directly if there's already same entry in the trash

* add unit test
  • Loading branch information
SandyXSD committed Aug 23, 2023
1 parent cec00e2 commit 9219ccd
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 2 deletions.
22 changes: 21 additions & 1 deletion pkg/meta/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,26 @@ func testTrash(t *testing.T, m Meta) {
if st := m.Rename(ctx, 1, "f2", 1, "d", 0, &inode, attr); st != 0 {
t.Fatalf("rename f2 -> d: %s", st)
}
if st := m.Link(ctx, inode, 1, "l", attr); st != 0 || attr.Nlink != 2 {
t.Fatalf("link d -> l1: %s", st)
}
if st := m.Unlink(ctx, 1, "l"); st != 0 {
t.Fatalf("unlink l: %s", st)
}
// hardlink goes to the trash
if st := m.GetAttr(ctx, inode, attr); st != 0 || attr.Nlink != 2 {
t.Fatalf("getattr d(%d): %s, attr %+v", inode, st, attr)
}
if st := m.Link(ctx, inode, 1, "l", attr); st != 0 || attr.Nlink != 3 {
t.Fatalf("link d -> l1: %s", st)
}
if st := m.Unlink(ctx, 1, "l"); st != 0 {
t.Fatalf("unlink l: %s", st)
}
// hardlink is deleted directly
if st := m.GetAttr(ctx, inode, attr); st != 0 || attr.Nlink != 2 {
t.Fatalf("getattr d(%d): %s, attr %+v", inode, st, attr)
}
if st := m.Unlink(ctx, 1, "d"); st != 0 {
t.Fatalf("unlink d: %s", st)
}
Expand All @@ -1222,7 +1242,7 @@ func testTrash(t *testing.T, m Meta) {
if st := m.Readdir(ctx, TrashInode+1, 0, &entries); st != 0 {
t.Fatalf("readdir: %s", st)
}
if len(entries) != 8 {
if len(entries) != 9 {
t.Fatalf("entries: %d", len(entries))
}
ctx2 := NewContext(1000, 1, []uint32{1})
Expand Down
4 changes: 4 additions & 0 deletions pkg/meta/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,10 @@ func (m *redisMeta) doUnlink(ctx Context, parent Ino, name string) syscall.Errno
if ctx.Uid() != 0 && pattr.Mode&01000 != 0 && ctx.Uid() != pattr.Uid && ctx.Uid() != attr.Uid {
return syscall.EACCES
}
if trash > 0 && attr.Nlink > 1 && tx.HExists(ctx, m.entryKey(trash), m.trashEntry(parent, inode, name)).Val() {
trash = 0
defer func() { m.of.InvalidateChunk(inode, 0xFFFFFFFE) }()
}
attr.Ctime = now.Unix()
attr.Ctimensec = uint32(now.Nanosecond())
if trash == 0 {
Expand Down
5 changes: 5 additions & 0 deletions pkg/meta/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,11 @@ func (m *dbMeta) doUnlink(ctx Context, parent Ino, name string) syscall.Errno {
if ctx.Uid() != 0 && pn.Mode&01000 != 0 && ctx.Uid() != pn.Uid && ctx.Uid() != n.Uid {
return syscall.EACCES
}
if trash > 0 && n.Nlink > 1 {
if o, e := s.Get(&edge{Parent: trash, Name: []byte(m.trashEntry(parent, e.Inode, string(e.Name))), Inode: e.Inode, Type: e.Type}); e == nil && o {
trash = 0
}
}
n.Ctime = now
if trash == 0 {
n.Nlink--
Expand Down
9 changes: 8 additions & 1 deletion pkg/meta/tkv.go
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,11 @@ func (m *kvMeta) doUnlink(ctx Context, parent Ino, name string) syscall.Errno {
if _type == TypeDirectory {
return syscall.EPERM
}
rs := tx.gets(m.inodeKey(parent), m.inodeKey(inode))
keys := [][]byte{m.inodeKey(parent), m.inodeKey(inode)}
if trash > 0 {
keys = append(keys, m.entryKey(trash, m.trashEntry(parent, inode, name)))
}
rs := tx.gets(keys...)
if rs[0] == nil {
return syscall.ENOENT
}
Expand All @@ -1130,6 +1134,9 @@ func (m *kvMeta) doUnlink(ctx Context, parent Ino, name string) syscall.Errno {
if ctx.Uid() != 0 && pattr.Mode&01000 != 0 && ctx.Uid() != pattr.Uid && ctx.Uid() != attr.Uid {
return syscall.EACCES
}
if trash > 0 && attr.Nlink > 1 && rs[2] != nil {
trash = 0
}
attr.Ctime = now.Unix()
attr.Ctimensec = uint32(now.Nanosecond())
if trash == 0 {
Expand Down

0 comments on commit 9219ccd

Please sign in to comment.