Skip to content

Commit

Permalink
meta: improve performance of statfs (#5161)
Browse files Browse the repository at this point in the history
Co-authored-by: Sandy Xu <[email protected]>
  • Loading branch information
davies and SandyXSD authored Sep 18, 2024
1 parent c8ac20f commit 7ac8f01
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 33 deletions.
49 changes: 21 additions & 28 deletions pkg/meta/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,31 +623,16 @@ func (m *baseMeta) StatFS(ctx Context, ino Ino, totalspace, availspace, iused, i
return st
}
ino = m.checkRoot(ino)
if ino == RootInode {
return 0
}
if st := m.Access(ctx, ino, MODE_MASK_R&MODE_MASK_X, nil); st != 0 {
return st
}
var usage *Quota
var attr Attr
for root := ino; root >= RootInode; root = attr.Parent {
if st := m.GetAttr(ctx, root, &attr); st != 0 {
return st
}
if root == RootInode {
attr.Parent = 0
}
q, err := m.en.doGetQuota(ctx, root)
if err != nil {
return errno(err)
}
if q == nil {
continue
var usage, quota *Quota
for ino >= RootInode {
ino, quota = m.getQuotaParent(ctx, ino)
if quota == nil {
break
}
q := quota.snap()
q.sanitize()
if usage == nil {
usage = q
usage = &q
}
if q.MaxSpace > 0 {
ls := uint64(q.MaxSpace - q.UsedSpace)
Expand All @@ -661,12 +646,20 @@ func (m *baseMeta) StatFS(ctx Context, ino Ino, totalspace, availspace, iused, i
*iavail = li
}
}
if ino == RootInode {
break
}
if parent, st := m.getDirParent(ctx, ino); st != 0 {
logger.Warnf("Get directory parent of inode %d: %s", ino, st)
break
} else {
ino = parent
}
}
if usage == nil {
return 0
if usage != nil {
*totalspace = uint64(usage.UsedSpace) + *availspace
*iused = uint64(usage.UsedInodes)
}
*totalspace = uint64(usage.UsedSpace) + *availspace
*iused = uint64(usage.UsedInodes)
return 0
}

Expand Down Expand Up @@ -1313,12 +1306,12 @@ func (m *baseMeta) Rename(ctx Context, parentSrc Ino, nameSrc string, parentDst
parentDst = m.checkRoot(parentDst)
var quotaSrc, quotaDst Ino
if !isTrash(parentSrc) {
quotaSrc = m.getQuotaParent(ctx, parentSrc)
quotaSrc, _ = m.getQuotaParent(ctx, parentSrc)
}
if parentSrc == parentDst {
quotaDst = quotaSrc
} else {
quotaDst = m.getQuotaParent(ctx, parentDst)
quotaDst, _ = m.getQuotaParent(ctx, parentDst)
}
var space, inodes int64
if quotaSrc != quotaDst {
Expand Down
5 changes: 4 additions & 1 deletion pkg/meta/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,7 @@ func testMetaClient(t *testing.T, m Meta) {
}, false, false); err != nil {
t.Fatalf("set quota: %s", err)
}
base.loadQuotas()
if st := m.StatFS(ctx, RootInode, &totalspace, &availspace, &iused, &iavail); st != 0 {
t.Fatalf("statfs: %s", st)
}
Expand All @@ -852,6 +853,7 @@ func testMetaClient(t *testing.T, m Meta) {
}, false, false); err != nil {
t.Fatalf("set quota: %s", err)
}
base.loadQuotas()
if st := m.StatFS(ctx, RootInode, &totalspace, &availspace, &iused, &iavail); st != 0 {
t.Fatalf("statfs: %s", st)
}
Expand All @@ -867,6 +869,7 @@ func testMetaClient(t *testing.T, m Meta) {
}, false, false); err != nil {
t.Fatalf("set quota: %s", err)
}
base.loadQuotas()
if st := m.StatFS(ctx, RootInode, &totalspace, &availspace, &iused, &iavail); st != 0 {
t.Fatalf("statfs: %s", st)
}
Expand All @@ -882,7 +885,7 @@ func testMetaClient(t *testing.T, m Meta) {
}, false, false); err != nil {
t.Fatalf("set quota: %s", err)
}

base.loadQuotas()
if st := m.StatFS(ctx, RootInode, &totalspace, &availspace, &iused, &iavail); st != 0 {
t.Fatalf("statfs: %s", st)
}
Expand Down
19 changes: 15 additions & 4 deletions pkg/meta/quota.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ func (q *Quota) update(space, inodes int64) {
atomic.AddInt64(&q.newInodes, inodes)
}

func (q *Quota) snap() Quota {
return Quota{
MaxSpace: atomic.LoadInt64(&q.MaxSpace),
MaxInodes: atomic.LoadInt64(&q.MaxInodes),
UsedSpace: atomic.LoadInt64(&q.UsedSpace),
UsedInodes: atomic.LoadInt64(&q.UsedInodes),
newSpace: atomic.LoadInt64(&q.newSpace),
newInodes: atomic.LoadInt64(&q.newInodes),
}
}

// not thread safe
func (q *Quota) sanitize() {
if q.UsedSpace < 0 {
Expand Down Expand Up @@ -283,9 +294,9 @@ func (m *baseMeta) getDirParent(ctx Context, inode Ino) (Ino, syscall.Errno) {
}

// get inode of the first parent (or myself) with quota
func (m *baseMeta) getQuotaParent(ctx Context, inode Ino) Ino {
func (m *baseMeta) getQuotaParent(ctx Context, inode Ino) (Ino, *Quota) {
if !m.getFormat().DirStats {
return 0
return 0, nil
}
var q *Quota
var st syscall.Errno
Expand All @@ -294,7 +305,7 @@ func (m *baseMeta) getQuotaParent(ctx Context, inode Ino) Ino {
q = m.dirQuotas[inode]
m.quotaMu.RUnlock()
if q != nil {
return inode
return inode, q
}
if inode <= RootInode {
break
Expand All @@ -305,7 +316,7 @@ func (m *baseMeta) getQuotaParent(ctx Context, inode Ino) Ino {
break
}
}
return 0
return 0, nil
}

func (m *baseMeta) checkDirQuota(ctx Context, inode Ino, space, inodes int64) bool {
Expand Down

0 comments on commit 7ac8f01

Please sign in to comment.