Repository navigation
Conversation
Two dir stat errors date from the clone refactor in juicedata#3397: - The cloned directories copy the dir stats of the source directories from the metadata engine, so changes still pending in this client (flushed once per second) were not copied, and existing dir stats are not recomputed, so the clone kept the stale stats; `juicefs fsck --sync-dir-stat` reported the clone. Clone now flushes the pending dir stats of this client before cloning a directory. Changes pending in other clients can still be missed; computing the stats of each cloned directory from the cloned entries would fix that too, but touches all engines. - Clone added the Length of the source to the parent's dir stat, which is 4096 for a directory and the length of the target path for a symlink, while the length in dir stats (juicedata#3302) counts regular files only (Mknod adds 0, Rename moves the length of regular files only). For the flush in Clone to see a change, doFlushDirStat now holds a new lock until the stats are written, as doFlushQuotas does (juicedata#7080): before, a flush that started while another one was writing found nothing to flush and returned at once, before that write. Only the callers of doFlushDirStat take the lock (the background flush, FlushSession and Clone), not updateDirStat. Add testCloneDirStats to testMeta.
angushe
force-pushed
the
clone-dir-stats
branch
from
October 23, 2026 07:46
a102abe to
db7bb80
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7744
This PR fixes two dir stat errors of
Clone, and makes the flush that the first fix uses wait for a flush in progress:The cloned directories copy the dir stats of the source directories from the metadata engine. Thus, the clone did not include the changes that this client did not flush yet. The clone kept the incorrect values. Now, before
Cloneclones a directory, it flushes the pending dir stats of this client.Cloneadded theLengthof the source to the dir stat of the parent. This value is 4096 for a directory, and the length of the target path for a symlink. But the length in the dir stats counts only regular files:Mknodadds 0, andRenamemoves the length only for regular files. Now,Cloneadds the length only for a regular file.A flush that starts while another flush writes the stats finds no pending changes, and returns at once, before that write. Then the clone can still copy the old values. Now,
doFlushDirStatholds a new lock,dirStatsFlushLock, until it has written the stats, asdoFlushQuotasdoes withquotasFlushLock(meta:Add mutex to doFlushQuotas to prevent concurrent execution #7080). Thus, the flush inClonewaits for a flush in progress.The change is in
pkg/meta/base.goandpkg/meta/quota.goonly, so all engines get it.Cost: only the callers of
doFlushDirStattake the new lock: the background flush (one time each second),FlushSessionandClone.updateDirStat, which each create, write and unlink calls, does not take it. We compared this PR with and without the lock:BenchmarkRedis/write, we ran fixed test binaries with 3000 iterations, 10 times each, in random order. The medians with and without the lock differ by 0.9%; two copies of the same binary differ by 0.5%.Cloneof a tree with 1111 directories takes the same time.The flush does not include the changes that are pending in other clients. A full fix calculates the stats of each cloned directory from the cloned entries, and does not copy them. This fix changes all three engines. If you prefer the full fix, I can do it.
Test: this PR adds
testCloneDirStatstotestMeta. The test does these steps:DirStatFlushPeriodto one hour for its session.dirStatsFlushLockand the pending dir stats, and does not write them yet.The results:
TestSQLiteClient,TestMemKVClientandTestRedisClientsuites also pass. We also ranpkg/metawithSKIP_NON_CORE=true, without the tests that need MySQL, PostgreSQL, TiKV or etcd: 76 tests pass and 6 skip, the same as without this PR.pkg/vfsandpkg/fspass too.-race,TestSQLiteClient,TestBadgerClientandTestRedisClientpass.TestMemKVClientreports a race intestClonein 2 of 10 runs, with and without this PR. TheDeleteSlicecallback writessli1del, and the test reads it aftertime.Sleep.fsckshows no warning, the clone has length 2097152, the parent has length 0, and the quota on the clone is consistent.This PR does not need #7745. But #7745 changes the lines next to this change at the end of
Clone, and it adds its test at the same location. Thus, the PR that you merge second needs a rebase. I will do the rebase.