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

count space and inodes usage for each directory #3257

Merged
merged 48 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
0b1f6df
count space and inodes usage for each directory
Hexilee Feb 20, 2023
6a0755e
adjust idents
Hexilee Feb 20, 2023
f19c5c8
adjust an ident
Hexilee Feb 20, 2023
c06eab3
revise
Hexilee Feb 20, 2023
79b8182
merge dirUsedSpaceKey and dirUsedInodesKey in tkv
Hexilee Feb 21, 2023
793c303
add storage structures
Hexilee Feb 21, 2023
618be58
implement doIncreDirUsage and doGetDirUsage for all meta engines
Hexilee Feb 21, 2023
348e32d
implement dirUsageBatch for baseMeta
Hexilee Feb 21, 2023
52ac44c
use increDirUsage in some IO call
Hexilee Feb 21, 2023
236e9a9
use increParentUsage in all meta engines
Hexilee Feb 22, 2023
b7cc826
merge from master
Hexilee Feb 22, 2023
b2ba498
fix nil attr bugs
Hexilee Feb 22, 2023
5827c1e
fix sql conflict
Hexilee Feb 22, 2023
bce8a5b
remove jfs.db
Hexilee Feb 22, 2023
c739730
remove jfs.db
Hexilee Feb 22, 2023
05c81c9
fix doIncreDirUsage for dbMeta
Hexilee Feb 22, 2023
cd65027
dirUsageBatch: commit blocking
Hexilee Feb 22, 2023
f6e02a0
increDirUsage directly if blocked
Hexilee Feb 22, 2023
d03d302
remove jfs.db
Hexilee Feb 22, 2023
d378b1a
try to sync dirUsage
Hexilee Feb 22, 2023
524d9b9
sync dir usage when necessary
Hexilee Feb 22, 2023
8f0f9ac
fix doGetDirUsage in sql
Hexilee Feb 22, 2023
06e6fad
implement doSyncDirUsage for tkv
Hexilee Feb 22, 2023
9d8e137
add logs
Hexilee Feb 23, 2023
eaf5e1a
use Lookup instead doLookup
Hexilee Feb 23, 2023
7fa6256
try to sync dirUsage in tkv
Hexilee Feb 23, 2023
a283b59
return attr from doUnlink
Hexilee Feb 23, 2023
d70b109
sync dirUsage table when necessary
Hexilee Feb 23, 2023
b93aea6
fix redis Truncate
Hexilee Feb 24, 2023
af44985
merge from main
Hexilee Feb 24, 2023
69c3e62
ignore flaky test
Hexilee Feb 24, 2023
d931e20
add GetDirUsage for Meta
Hexilee Feb 24, 2023
b350241
add unit tests and pass
Hexilee Feb 27, 2023
b0e82af
fix testRedisClient
Hexilee Feb 27, 2023
4f7e07d
fix tkv
Hexilee Feb 27, 2023
8598eae
remote jfs.db
Hexilee Feb 27, 2023
8f41325
add tryIncreDirUsage and mustIncreDirUsage
Hexilee Feb 27, 2023
2ff72f9
fix increParentUsage
Hexilee Feb 27, 2023
81e64d2
resolve comments
Hexilee Feb 27, 2023
9b173b0
sql: count usage outside of txn
Hexilee Feb 28, 2023
3b691c2
deal with err
Hexilee Feb 28, 2023
45239fe
replace channel with locked map in dir usage batch
Hexilee Feb 28, 2023
2fa5f09
remove dirUsageBatchSize
Hexilee Feb 28, 2023
24f08e4
remove tryIncreDirUsage
Hexilee Feb 28, 2023
f026466
remove dir usage when rmdir
Hexilee Feb 28, 2023
e11c030
review
davies Feb 28, 2023
e2c9942
fix redis txn panic
Hexilee Mar 1, 2023
022bfe1
fix sql txn panic
Hexilee Mar 1, 2023
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
142 changes: 134 additions & 8 deletions pkg/meta/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,19 @@ 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, rdev uint32, 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) syscall.Errno
doUnlink(ctx Context, parent Ino, name string, attr *Attr) syscall.Errno
doRmdir(ctx Context, parent Ino, name string) syscall.Errno
doReadlink(ctx Context, inode Ino) ([]byte, error)
doReaddir(ctx Context, inode Ino, plus uint8, entries *[]*Entry, limit int) syscall.Errno
doRename(ctx Context, parentSrc Ino, nameSrc string, parentDst Ino, nameDst string, flags uint32, inode *Ino, attr *Attr) syscall.Errno
doSetXattr(ctx Context, inode Ino, name string, value []byte, flags uint32) syscall.Errno
doRemoveXattr(ctx Context, inode Ino, name string) syscall.Errno
doGetParents(ctx Context, inode Ino) map[Ino]int
doRepair(ctx Context, inode Ino, attr *Attr) syscall.Errno

doGetParents(ctx Context, inode Ino) map[Ino]int
doUpdateDirStat(ctx Context, ino Ino, space int64, inodes int64) error
doGetDirStat(ctx Context, ino Ino) (space, inodes uint64, err error)

scanTrashSlices(Context, trashSliceScan) error
scanPendingSlices(Context, pendingSliceScan) error
scanPendingFiles(Context, pendingFileScan) error
Expand Down Expand Up @@ -111,6 +114,12 @@ type cchunk struct {
slices int
}

// stat of dir
type dirStat struct {
space int64
inodes int64
}

type baseMeta struct {
sync.Mutex
addr string
Expand All @@ -132,6 +141,8 @@ type baseMeta struct {
umounting bool
sesMu sync.Mutex

dirStatsLock sync.Mutex
dirStats map[Ino]dirStat
*fsStat

freeMu sync.Mutex
Expand Down Expand Up @@ -159,6 +170,7 @@ func newBaseMeta(addr string, conf *Config) *baseMeta {
dslices: make(chan Slice, conf.MaxDeletes*10240),
symlinks: &sync.Map{},
fsStat: new(fsStat),
dirStats: make(map[Ino]dirStat),
msgCallbacks: &msgCallbacks{
callbacks: make(map[uint32]MsgCallback),
},
Expand Down Expand Up @@ -230,6 +242,82 @@ func (m *baseMeta) checkRoot(inode Ino) Ino {
}
}

func (m *baseMeta) calcDirStat(ctx Context, ino Ino) (space, inodes uint64, err error) {
var entries []*Entry
if eno := m.en.doReaddir(ctx, ino, 1, &entries, -1); eno != 0 {
err = errors.Wrap(eno, "calc dir stat")
return
}
for _, e := range entries {
inodes += 1
var newSpace uint64
if e.Attr.Typ == TypeFile {
newSpace = e.Attr.Length
}
space += uint64(align4K(newSpace))
}
return
}

func (m *baseMeta) GetDirStat(ctx Context, inode Ino) (space, inodes uint64, err error) {
return m.en.doGetDirStat(ctx, m.checkRoot(inode))
}

func (m *baseMeta) updateDirStat(ctx Context, ino Ino, space int64, inodes int64) {
if inodes == 0 && space == 0 {
return
}
m.dirStatsLock.Lock()
defer m.dirStatsLock.Unlock()
event := m.dirStats[ino]
event.space += space
event.inodes += inodes
m.dirStats[ino] = event
}

func (m *baseMeta) updateParentStat(ctx Context, inode, parent Ino, space int64) {
if space == 0 {
return
}
m.updateStats(space, 0)
if parent > 0 {
m.updateDirStat(ctx, parent, space, 0)
} else {
go func() {
for p := range m.en.doGetParents(ctx, inode) {
m.updateDirStat(ctx, p, space, 0)
}
}()
}
}

func (m *baseMeta) flushDirStat() {
for {
time.Sleep(time.Second * 1)
m.doFlushDirStat()
}
}

func (m *baseMeta) doFlushDirStat() {
m.dirStatsLock.Lock()
if len(m.dirStats) == 0 {
m.dirStatsLock.Unlock()
return
}
stats := m.dirStats
m.dirStats = make(map[Ino]dirStat)
m.dirStatsLock.Unlock()
for ino, e := range stats {
if e.space == 0 && e.inodes == 0 {
continue
}
err := m.en.doUpdateDirStat(Background, ino, e.space, e.inodes)
if err != nil {
logger.Errorf("update dir stat failed: %v", err)
}
}
}

func (r *baseMeta) txLock(idx uint) {
r.txlocks[idx%nlocks].Lock()
}
Expand Down Expand Up @@ -317,6 +405,7 @@ func (m *baseMeta) NewSession() error {
go m.cleanupDeletedFiles()
go m.cleanupSlices()
go m.cleanupTrash()
go m.flushDirStat()
}
return nil
}
Expand Down Expand Up @@ -404,6 +493,7 @@ func (m *baseMeta) CloseSession() error {
if m.conf.ReadOnly {
return nil
}
m.doFlushDirStat()
m.sesMu.Lock()
m.umounting = true
m.sesMu.Unlock()
Expand Down Expand Up @@ -769,7 +859,11 @@ func (m *baseMeta) Mknod(ctx Context, parent Ino, name string, _type uint8, mode
if m.checkQuota(4<<10, 1) {
return syscall.ENOSPC
}
return m.en.doMknod(ctx, m.checkRoot(parent), name, _type, mode, cumask, rdev, path, inode, attr)
err := m.en.doMknod(ctx, m.checkRoot(parent), name, _type, mode, cumask, rdev, path, inode, attr)
if err == 0 {
m.updateDirStat(ctx, parent, align4K(0), 1)
}
return err
}

func (m *baseMeta) Create(ctx Context, parent Ino, name string, mode uint16, cumask uint16, flags uint32, inode *Ino, attr *Attr) syscall.Errno {
Expand Down Expand Up @@ -812,7 +906,14 @@ func (m *baseMeta) Link(ctx Context, inode, parent Ino, name string, attr *Attr)
defer m.timeit(time.Now())
parent = m.checkRoot(parent)
defer func() { m.of.InvalidateChunk(inode, invalidateAttrOnly) }()
return m.en.doLink(ctx, inode, parent, name, attr)
if attr == nil {
attr = &Attr{}
}
err := m.en.doLink(ctx, inode, parent, name, attr)
if err == 0 {
m.updateDirStat(ctx, parent, align4K(attr.Length), 1)
}
return err
}

func (m *baseMeta) ReadLink(ctx Context, inode Ino, path *[]byte) syscall.Errno {
Expand Down Expand Up @@ -842,7 +943,16 @@ func (m *baseMeta) Unlink(ctx Context, parent Ino, name string) syscall.Errno {
}

defer m.timeit(time.Now())
return m.en.doUnlink(ctx, m.checkRoot(parent), name)
var attr Attr
err := m.en.doUnlink(ctx, m.checkRoot(parent), name, &attr)
if err == 0 {
newSpace := -align4K(0)
if attr.Typ == TypeFile {
newSpace = -align4K(attr.Length)
}
m.updateDirStat(ctx, parent, newSpace, -1)
}
return err
}

func (m *baseMeta) Rmdir(ctx Context, parent Ino, name string) syscall.Errno {
Expand All @@ -860,7 +970,11 @@ func (m *baseMeta) Rmdir(ctx Context, parent Ino, name string) syscall.Errno {
}

defer m.timeit(time.Now())
return m.en.doRmdir(ctx, m.checkRoot(parent), name)
err := m.en.doRmdir(ctx, m.checkRoot(parent), name)
if err == 0 {
m.updateDirStat(ctx, parent, -align4K(0), -1)
}
return err
}

func (m *baseMeta) Rename(ctx Context, parentSrc Ino, nameSrc string, parentDst Ino, nameDst string, flags uint32, inode *Ino, attr *Attr) syscall.Errno {
Expand All @@ -885,7 +999,19 @@ func (m *baseMeta) Rename(ctx Context, parentSrc Ino, nameSrc string, parentDst
}

defer m.timeit(time.Now())
return m.en.doRename(ctx, m.checkRoot(parentSrc), nameSrc, m.checkRoot(parentDst), nameDst, flags, inode, attr)
if attr == nil {
attr = &Attr{}
}
err := m.en.doRename(ctx, m.checkRoot(parentSrc), nameSrc, m.checkRoot(parentDst), nameDst, flags, inode, attr)
if err == 0 {
diffSpace := align4K(0)
if attr.Typ == TypeFile {
diffSpace = align4K(attr.Length)
}
m.updateDirStat(ctx, parentSrc, -diffSpace, -1)
m.updateDirStat(ctx, parentDst, diffSpace, 1)
}
return err
}

func (m *baseMeta) Open(ctx Context, inode Ino, flags uint32, attr *Attr) syscall.Errno {
Expand Down Expand Up @@ -1444,7 +1570,7 @@ func (m *baseMeta) CleanupTrashBefore(ctx Context, edge time.Time, increProgress
if se.Attr.Typ == TypeDirectory {
st = m.en.doRmdir(ctx, e.Inode, string(se.Name))
} else {
st = m.en.doUnlink(ctx, e.Inode, string(se.Name))
st = m.en.doUnlink(ctx, e.Inode, string(se.Name), nil)
}
if st == 0 {
count++
Expand Down
Loading