shell: volume.fsck must not skip the system-log subtree (#9764)

shell: only skip system-log subtree in fs.meta.save, not fsck/verify

The SystemLogDir skip lived in the shared BFS traversal, so volume.fsck
built its in-use set without the /topic/.system/log chunks and flagged
every referenced log needle as orphan. -reallyDeleteFromVolume would then
delete live log data and leave dangling filer entries. Gate the skip
behind a flag that only fs.meta.save sets.
This commit is contained in:
Chris Lu
2026-06-01 09:54:22 -07:00
committed by GitHub
parent 80dd3b2621
commit f9ee49b03e
3 changed files with 15 additions and 7 deletions
+13 -5
View File
@@ -102,7 +102,7 @@ func (c *commandFsMetaSave) Do(args []string, commandEnv *CommandEnv, writer io.
cipherKey = util.GenCipherKey()
}
err = doTraverseBfsAndSaving(commandEnv, writer, path, *verbose, func(ctx context.Context, entry *filer_pb.FullEntry, outputChan chan interface{}) (err error) {
err = doTraverseBfsAndSaving(commandEnv, writer, path, *verbose, true, func(ctx context.Context, entry *filer_pb.FullEntry, outputChan chan interface{}) (err error) {
if !entry.Entry.IsDirectory {
ext := filepath.Ext(entry.Entry.Name)
if encrypted, encErr := util.Encrypt([]byte(entry.Entry.Name), cipherKey); encErr == nil {
@@ -147,7 +147,12 @@ func (c *commandFsMetaSave) Do(args []string, commandEnv *CommandEnv, writer io.
}
func doTraverseBfsAndSaving(filerClient filer_pb.FilerClient, writer io.Writer, path string, verbose bool, genFn func(ctx context.Context, entry *filer_pb.FullEntry, outputChan chan interface{}) error, saveFn func(outputChan chan interface{}) error) error {
// skipSystemLog excludes the metadata-log subtree (SystemLogDir) from the
// traversal. fs.meta.save sets it so the export doesn't carry the whole change
// log; volume.fsck and fs.verify must leave it false so the live log-file
// chunks are accounted for — otherwise fsck reports them as orphans and could
// delete referenced needles.
func doTraverseBfsAndSaving(filerClient filer_pb.FilerClient, writer io.Writer, path string, verbose bool, skipSystemLog bool, genFn func(ctx context.Context, entry *filer_pb.FullEntry, outputChan chan interface{}) error, saveFn func(outputChan chan interface{}) error) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -199,11 +204,14 @@ func doTraverseBfsAndSaving(filerClient filer_pb.FilerClient, writer io.Writer,
}
defer cancel()
systemLogChildPrefix := filer.SystemLogDir + "/"
err := filer_pb.TraverseBfs(ctx, filerClient, util.FullPath(path), func(parentPath util.FullPath, entry *filer_pb.Entry) error {
parent := string(parentPath)
if parent == filer.SystemLogDir || strings.HasPrefix(parent, filer.SystemLogDir+"/") {
return nil
if skipSystemLog {
parent := string(parentPath)
if parent == filer.SystemLogDir || strings.HasPrefix(parent, systemLogChildPrefix) {
return nil
}
}
protoMessage := &filer_pb.FullEntry{
+1 -1
View File
@@ -280,7 +280,7 @@ func (c *commandFsVerify) verifyEntry(path string, chunks []*filer_pb.FileChunk,
func (c *commandFsVerify) verifyTraverseBfs(path string) (fileCount uint64, errCount uint64, err error) {
timeNowAtSec := time.Now().Unix()
return fileCount, errCount, doTraverseBfsAndSaving(c.env, c.writer, path, false,
return fileCount, errCount, doTraverseBfsAndSaving(c.env, c.writer, path, false, false,
func(ctx context.Context, entry *filer_pb.FullEntry, outputChan chan interface{}) (err error) {
if c.modifyTimeAgoAtSec > 0 {
if entry.Entry.Attributes != nil && c.modifyTimeAgoAtSec < timeNowAtSec-entry.Entry.Attributes.Mtime {
+1 -1
View File
@@ -297,7 +297,7 @@ func (c *commandVolumeFsck) collectFilerFileIdAndPaths(dataNodeVolumeIdToVInfo m
}
}()
return doTraverseBfsAndSaving(c.env, c.writer, c.getCollectFilerFilePath(), false,
return doTraverseBfsAndSaving(c.env, c.writer, c.getCollectFilerFilePath(), false, false,
func(ctx context.Context, entry *filer_pb.FullEntry, outputChan chan interface{}) (err error) {
if *c.verbose && entry.Entry.IsDirectory {
fmt.Fprintf(c.writer, "checking directory %s\n", util.NewFullPath(entry.Dir, entry.Entry.Name))