From bffb17f8fbccd0cf1ef1bb38550df20442aa55ef Mon Sep 17 00:00:00 2001 From: Fangxin Lou Date: Fri, 7 Feb 2025 10:44:22 +0800 Subject: [PATCH] pass parent attr from emptyDir --- pkg/meta/base.go | 8 ++++---- pkg/meta/redis.go | 20 +++++++++++--------- pkg/meta/sql.go | 22 ++++++++++------------ pkg/meta/tkv.go | 20 +++++++++++--------- pkg/meta/utils.go | 6 +++++- 5 files changed, 41 insertions(+), 35 deletions(-) diff --git a/pkg/meta/base.go b/pkg/meta/base.go index 125d93e3f2ed..cf759163dde1 100644 --- a/pkg/meta/base.go +++ b/pkg/meta/base.go @@ -103,7 +103,7 @@ type engine interface { doLookup(ctx Context, parent Ino, name string, inode *Ino, attr *Attr) syscall.Errno doMknod(ctx Context, parent Ino, name string, _type uint8, mode, cumask uint16, path string, inode *Ino, attr *Attr) syscall.Errno doLink(ctx Context, inode, parent Ino, name string, attr *Attr) syscall.Errno - doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, skipCheckTrash ...bool) syscall.Errno + doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, pattr *Attr, skipCheckTrash ...bool) syscall.Errno doRmdir(ctx Context, parent Ino, name string, inode *Ino, skipCheckTrash ...bool) syscall.Errno doReadlink(ctx Context, inode Ino, noatime bool) (int64, []byte, error) doReaddir(ctx Context, inode Ino, plus uint8, entries *[]*Entry, limit int) syscall.Errno @@ -1344,7 +1344,7 @@ func (m *baseMeta) ReadLink(ctx Context, inode Ino, path *[]byte) syscall.Errno return 0 } -func (m *baseMeta) Unlink2(ctx Context, parent Ino, name string, entry *Entry, skipCheckTrash ...bool) syscall.Errno { +func (m *baseMeta) Unlink2(ctx Context, parent Ino, name string, entry *Entry, pattr *Attr, skipCheckTrash ...bool) syscall.Errno { if parent == RootInode && name == TrashName || isTrash(parent) && ctx.Uid() != 0 { return syscall.EPERM } @@ -1355,7 +1355,7 @@ func (m *baseMeta) Unlink2(ctx Context, parent Ino, name string, entry *Entry, s defer m.timeit("Unlink", time.Now()) parent = m.checkRoot(parent) var attr Attr - err := m.en.doUnlink(ctx, parent, name, &attr, entry, skipCheckTrash...) + err := m.en.doUnlink(ctx, parent, name, &attr, entry, pattr, skipCheckTrash...) if entry == nil && err == 0 { var diffLength uint64 if attr.Typ == TypeFile { @@ -1368,7 +1368,7 @@ func (m *baseMeta) Unlink2(ctx Context, parent Ino, name string, entry *Entry, s } func (m *baseMeta) Unlink(ctx Context, parent Ino, name string, skipCheckTrash ...bool) syscall.Errno { - return m.Unlink2(ctx, parent, name, nil, skipCheckTrash...) + return m.Unlink2(ctx, parent, name, nil, nil, skipCheckTrash...) } func (m *baseMeta) Rmdir(ctx Context, parent Ino, name string, skipCheckTrash ...bool) syscall.Errno { diff --git a/pkg/meta/redis.go b/pkg/meta/redis.go index 2687f9e54f58..112f4fe2f05c 100644 --- a/pkg/meta/redis.go +++ b/pkg/meta/redis.go @@ -1427,7 +1427,7 @@ func (m *redisMeta) doMknod(ctx Context, parent Ino, name string, _type uint8, m }, m.inodeKey(parent), m.entryKey(parent))) } -func (m *redisMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, skipCheckTrash ...bool) syscall.Errno { +func (m *redisMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, pattr *Attr, skipCheckTrash ...bool) syscall.Errno { var trash, inode Ino if !(len(skipCheckTrash) == 1 && skipCheckTrash[0]) { if st := m.checkTrash(parent, &trash); st != 0 { @@ -1469,13 +1469,15 @@ func (m *redisMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, e if rs[0] == nil { return redis.Nil } - var pattr Attr - m.parseAttr([]byte(rs[0].(string)), &pattr) - if pattr.Typ != TypeDirectory { - return syscall.ENOTDIR - } - if st := m.Access(ctx, parent, MODE_MASK_W|MODE_MASK_X, &pattr); st != 0 { - return st + if pattr == nil { + pattr = &Attr{} + m.parseAttr([]byte(rs[0].(string)), pattr) + if pattr.Typ != TypeDirectory { + return syscall.ENOTDIR + } + if st := m.Access(ctx, parent, MODE_MASK_W|MODE_MASK_X, pattr); st != 0 { + return st + } } if (pattr.Flags&FlagAppend) != 0 || (pattr.Flags&FlagImmutable) != 0 { return syscall.EPERM @@ -1519,7 +1521,7 @@ func (m *redisMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, e _, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error { pipe.HDel(ctx, m.entryKey(parent), name) if updateParent { - pipe.Set(ctx, m.inodeKey(parent), m.marshal(&pattr), 0) + pipe.Set(ctx, m.inodeKey(parent), m.marshal(pattr), 0) } if attr.Nlink > 0 { pipe.Set(ctx, m.inodeKey(inode), m.marshal(attr), 0) diff --git a/pkg/meta/sql.go b/pkg/meta/sql.go index 7e8fca3995f7..1c073464b070 100644 --- a/pkg/meta/sql.go +++ b/pkg/meta/sql.go @@ -1608,7 +1608,7 @@ func (m *dbMeta) doMknod(ctx Context, parent Ino, name string, _type uint8, mode })) } -func (m *dbMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, skipCheckTrash ...bool) syscall.Errno { +func (m *dbMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, pattr *Attr, skipCheckTrash ...bool) syscall.Errno { var trash Ino if !(len(skipCheckTrash) == 1 && skipCheckTrash[0]) { if st := m.checkTrash(parent, &trash); st != 0 { @@ -1622,7 +1622,7 @@ func (m *dbMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entr opened = false newSpace, newInode = 0, 0 var pn = node{Inode: parent} - if entry == nil { + if pattr == nil { ok, err := s.Get(&pn) if err != nil { return err @@ -1630,19 +1630,17 @@ func (m *dbMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entr if !ok { return syscall.ENOENT } - if pn.Type != TypeDirectory { + pattr = &Attr{} + m.parseAttr(&pn, pattr) + if pattr.Typ != TypeDirectory { return syscall.ENOTDIR } - var pattr Attr - m.parseAttr(&pn, &pattr) - - // Access is already checked in emptyDir call - if st := m.Access(ctx, parent, MODE_MASK_W|MODE_MASK_X, &pattr); st != 0 { + if st := m.Access(ctx, parent, MODE_MASK_W|MODE_MASK_X, pattr); st != 0 { return st } - if (pn.Flags&FlagAppend) != 0 || (pn.Flags&FlagImmutable) != 0 { - return syscall.EPERM - } + } + if (pattr.Flags&FlagAppend) != 0 || (pattr.Flags&FlagImmutable) != 0 { + return syscall.EPERM } var e = edge{Parent: parent, Name: []byte(name)} if entry == nil { @@ -1677,7 +1675,7 @@ func (m *dbMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entr now := time.Now().UnixNano() if ok { if entry == nil { - if ctx.Uid() != 0 && pn.Mode&01000 != 0 && ctx.Uid() != pn.Uid && ctx.Uid() != n.Uid { + if ctx.Uid() != 0 && pattr.Mode&01000 != 0 && ctx.Uid() != pattr.Uid && ctx.Uid() != n.Uid { return syscall.EACCES } } diff --git a/pkg/meta/tkv.go b/pkg/meta/tkv.go index aa4196981d28..f74fa0060e81 100644 --- a/pkg/meta/tkv.go +++ b/pkg/meta/tkv.go @@ -1246,7 +1246,7 @@ func (m *kvMeta) doMknod(ctx Context, parent Ino, name string, _type uint8, mode }, parent)) } -func (m *kvMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, skipCheckTrash ...bool) syscall.Errno { +func (m *kvMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entry *Entry, pattr *Attr, skipCheckTrash ...bool) syscall.Errno { var trash Ino if !(len(skipCheckTrash) == 1 && skipCheckTrash[0]) { if st := m.checkTrash(parent, &trash); st != 0 { @@ -1287,13 +1287,15 @@ func (m *kvMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entr if rs[0] == nil { return syscall.ENOENT } - var pattr Attr - m.parseAttr(rs[0], &pattr) - if pattr.Typ != TypeDirectory { - return syscall.ENOTDIR - } - if st := m.Access(ctx, parent, MODE_MASK_W|MODE_MASK_X, &pattr); st != 0 { - return st + if pattr == nil { + pattr = &Attr{} + m.parseAttr(rs[0], pattr) + if pattr.Typ != TypeDirectory { + return syscall.ENOTDIR + } + if st := m.Access(ctx, parent, MODE_MASK_W|MODE_MASK_X, pattr); st != 0 { + return st + } } if (pattr.Flags&FlagAppend) != 0 || (pattr.Flags&FlagImmutable) != 0 { return syscall.EPERM @@ -1338,7 +1340,7 @@ func (m *kvMeta) doUnlink(ctx Context, parent Ino, name string, attr *Attr, entr tx.delete(m.entryKey(parent, name)) if updateParent { - tx.set(m.inodeKey(parent), m.marshal(&pattr)) + tx.set(m.inodeKey(parent), m.marshal(pattr)) } if attr.Nlink > 0 { tx.set(m.inodeKey(inode), m.marshal(attr)) diff --git a/pkg/meta/utils.go b/pkg/meta/utils.go index e820a2d8cdc7..78e9fa89e0a8 100644 --- a/pkg/meta/utils.go +++ b/pkg/meta/utils.go @@ -259,6 +259,10 @@ func updateLocks(ls []plockRecord, nl plockRecord) []plockRecord { } func (m *baseMeta) emptyDir(ctx Context, inode Ino, skipCheckTrash bool, count *uint64, concurrent chan int) syscall.Errno { + var pattr Attr + if st := m.en.doGetAttr(ctx, inode, &pattr); st != 0 { + return st + } for { var entries []*Entry if st := m.en.doReaddir(ctx, inode, 0, &entries, 10000); st != 0 && st != syscall.ENOENT { @@ -303,7 +307,7 @@ func (m *baseMeta) emptyDir(ctx Context, inode Ino, skipCheckTrash bool, count * if count != nil { atomic.AddUint64(count, 1) } - if st := m.Unlink2(ctx, inode, string(e.Name), e, skipCheckTrash); st != 0 && st != syscall.ENOENT { + if st := m.Unlink2(ctx, inode, string(e.Name), e, &pattr, skipCheckTrash); st != 0 && st != syscall.ENOENT { ctx.Cancel() return st }