diff options
author | Jakob Unterwurzacher | 2018-08-15 14:02:05 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2018-08-15 14:02:05 +0200 |
commit | 0e1cbb75fed40d658c72d7fb65c7b012b1b4d31d (patch) | |
tree | f9e57f295deb07faababe88df98de21123e7107b | |
parent | db4accf3a3397e2c5973aa99aae52a8f3e864e27 (diff) |
fsck: skip already-seen hard-linked files
We may hit files several times due to hard links.
Only check the contents once.
-rw-r--r-- | fsck.go | 21 |
1 files changed, 19 insertions, 2 deletions
@@ -26,6 +26,8 @@ type fsckObj struct { corruptListLock sync.Mutex // stop a running watchMitigatedCorruptions thread watchDone chan struct{} + // Inode numbers of hard-linked files (Nlink > 1) that we have already checked + seenInodes map[uint64]struct{} } func (ck *fsckObj) markCorrupt(path string) { @@ -109,6 +111,20 @@ func (ck *fsckObj) watchMitigatedCorruptionsRead(path string) { // Check file for corruption func (ck *fsckObj) file(path string) { tlog.Debug.Printf("ck.file %q\n", path) + attr, status := ck.fs.GetAttr(path, nil) + if !status.Ok() { + ck.markCorrupt(path) + fmt.Printf("fsck: error stating file %q: %v\n", path, status) + return + } + if attr.Nlink > 1 { + // Due to hard links, we may have already checked this file. + if _, ok := ck.seenInodes[attr.Ino]; ok { + tlog.Debug.Printf("ck.file : skipping %q (inode number %d already seen)\n", path, attr.Ino) + return + } + ck.seenInodes[attr.Ino] = struct{}{} + } ck.xattrs(path) f, status := ck.fs.Open(path, syscall.O_RDONLY, nil) if !status.Ok() { @@ -193,8 +209,9 @@ func fsck(args *argContainer) { fs := pfs.(*fusefrontend.FS) fs.MitigatedCorruptions = make(chan string) ck := fsckObj{ - fs: fs, - watchDone: make(chan struct{}), + fs: fs, + watchDone: make(chan struct{}), + seenInodes: make(map[uint64]struct{}), } ck.dir("") wipeKeys() |