mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-14 07:48:41 +01:00
mount: check the creation time when the base has no inode
An entry without an inode or hard link id matched any replacement at the same path, so a stale handle could merge into a different file. Without an inode the merge now needs the same creation time. The filer keeps it across updates; only a synthesized base has neither and still merges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f44eeff31d
commit
2d719fb4ea
2 files changed
+20
-3
No files matched your search
@@ -354,6 +354,18 @@ func TestMergeContentEntry(t *testing.T) {
|
||||
t.Fatal("refused a truncate that shortened an unstamped base chunk")
|
||||
}
|
||||
|
||||
noInode := proto.Clone(base).(*filer_pb.Entry)
|
||||
noInode.Attributes.Inode, noInode.Attributes.Crtime = 0, 5
|
||||
sameFile := proto.Clone(noInode).(*filer_pb.Entry)
|
||||
sameFile.Chunks = append(sameFile.Chunks, stored.Chunks[2])
|
||||
if _, ok := mergeContentEntry(sameFile, noInode, local, local, -1); !ok {
|
||||
t.Fatal("refused an inode-less file with the same creation time")
|
||||
}
|
||||
sameFile.Attributes.Crtime = 6
|
||||
if _, ok := mergeContentEntry(sameFile, noInode, local, local, -1); ok {
|
||||
t.Fatal("merged into an inode-less replacement")
|
||||
}
|
||||
|
||||
empty := flushConditionEntry()
|
||||
inline := proto.Clone(empty).(*filer_pb.Entry)
|
||||
inline.Content = []byte("peer")
|
||||
|
||||
@@ -485,13 +485,18 @@ func mergeContentEntry(stored, base, local, sent *filer_pb.Entry, truncatedTo in
|
||||
return merged, true
|
||||
}
|
||||
|
||||
// sameContentFile reports whether stored is still the regular file base was.
|
||||
// sameContentFile reports whether stored is still the regular file base was:
|
||||
// the same inode, or for an entry without one, the same creation time. A
|
||||
// synthesized base with neither cannot tell.
|
||||
func sameContentFile(stored, base *filer_pb.Entry) bool {
|
||||
if stored == nil || base == nil || stored.IsDirectory || !bytes.Equal(stored.HardLinkId, base.HardLinkId) {
|
||||
return false
|
||||
}
|
||||
inode := base.GetAttributes().GetInode()
|
||||
return inode == 0 || stored.GetAttributes().GetInode() == inode
|
||||
if inode := base.GetAttributes().GetInode(); inode != 0 {
|
||||
return stored.GetAttributes().GetInode() == inode
|
||||
}
|
||||
crtime := base.GetAttributes().GetCrtime()
|
||||
return crtime == 0 || stored.GetAttributes().GetCrtime() == crtime
|
||||
}
|
||||
|
||||
// contentChunkKey identifies a chunk reference: truncation shrinks a chunk in
|
||||
|
||||
Reference in new issue
Block a user