filer: serialize inode index row updates in the filer

storeInodeIndex and removePathFromInodeIndex read-modify-write a shared
KV row; concurrent writes on one inode (hard links share an inode) could
overwrite each other and drop a path. Stripe-lock the row like the shell
backfill already does.
This commit is contained in:
Chris Lu committed 2026-10-22 02:33:32 -07:00
1 parent 44235b5def
commit ff4b43e0f1
1 file changed
+17
+17
View File
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"encoding/json"
"sort"
"sync"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/util"
@@ -13,6 +14,14 @@ import (
const inodeIndexKeyPrefix = "filer.inode.path."
const InodeIndexInitialGeneration uint64 = 1
// inodeRowLocks serializes the read-modify-write of one inode's index row so
// concurrent writers (hard links share an inode) cannot overwrite each other.
var inodeRowLocks [256]sync.Mutex
func inodeRowLock(inode uint64) *sync.Mutex {
return &inodeRowLocks[inode%uint64(len(inodeRowLocks))]
}
type inodeIndexEntry struct {
path util.FullPath
inode uint64
@@ -190,6 +199,10 @@ func (fsw *FilerStoreWrapper) storeInodeIndex(ctx context.Context, path util.Ful
return nil
}
lock := inodeRowLock(inode)
lock.Lock()
defer lock.Unlock()
record, err := fsw.lookupInodeIndex(ctx, inode)
if err != nil {
if err != ErrKvNotFound {
@@ -237,6 +250,10 @@ func (fsw *FilerStoreWrapper) removePathFromInodeIndex(ctx context.Context, path
return nil
}
lock := inodeRowLock(inode)
lock.Lock()
defer lock.Unlock()
record, err := fsw.lookupInodeIndex(ctx, inode)
if err != nil {
if err == ErrKvNotFound {