mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-11 16:57:45 +02:00
filer: fail writes when the existing-entry lookup fails (#11699)
* filer: fail writes when the existing-entry lookup fails CreateEntry only returned a FindEntry error for exclusive creates; a regular write treated a transient store error as "entry not found" and, on upsert stores, replaced the entry without loading its old chunks — leaving them out of the cleanup process. Return any lookup error except ErrNotFound for both paths. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * filer: test that a lookup failure fails a regular write Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
4bf5e92b64
commit
c3d13c60e9
2 files changed
+28
-3
No files matched your search
+3
-3
@@ -339,9 +339,9 @@ func (f *Filer) CreateEntry(ctx context.Context, entry *Entry, existing *Entry,
|
||||
if oldEntry == nil {
|
||||
var findErr error
|
||||
oldEntry, findErr = f.FindEntry(ctx, entry.FullPath)
|
||||
if o_excl && findErr != nil && !errors.Is(findErr, filer_pb.ErrNotFound) {
|
||||
// An exclusive create cannot decide whether the path exists when
|
||||
// the lookup itself failed; proceeding would upsert over it.
|
||||
if findErr != nil && !errors.Is(findErr, filer_pb.ErrNotFound) {
|
||||
// A create cannot decide whether the path exists when the lookup
|
||||
// itself failed; proceeding would upsert over it.
|
||||
return fmt.Errorf("find entry %s: %w", entry.FullPath, findErr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,3 +265,28 @@ func TestUpdateEntryBackfillsMissingLegacyInode(t *testing.T) {
|
||||
assert.NotZero(t, stored.Attr.Inode)
|
||||
assert.NotEqual(t, uint64(1), stored.Attr.Inode)
|
||||
}
|
||||
|
||||
// A transient store error must fail the write instead of being mistaken for a
|
||||
// missing entry: on upsert stores proceeding would replace the entry without
|
||||
// loading the old chunks, orphaning them from cleanup.
|
||||
func TestCreateEntryFailsWhenLookupErrors(t *testing.T) {
|
||||
f, store := newTestFilerWithStubStore()
|
||||
path := util.FullPath("/dir/file.txt")
|
||||
require.NoError(t, store.InsertEntry(context.Background(), &Entry{
|
||||
FullPath: path,
|
||||
Content: []byte("existing"),
|
||||
}))
|
||||
store.findErr = errors.New("transient store failure")
|
||||
|
||||
entry := &Entry{
|
||||
FullPath: path,
|
||||
Attr: Attr{Mode: 0o644},
|
||||
Content: []byte("overwrite"),
|
||||
}
|
||||
require.Error(t, f.CreateEntry(context.Background(), entry, nil, false, false, nil, false, f.MaxFilenameLength))
|
||||
|
||||
store.findErr = nil
|
||||
stored, findErr := store.FindEntry(context.Background(), path)
|
||||
require.NoError(t, findErr)
|
||||
assert.Equal(t, "existing", string(stored.Content))
|
||||
}
|
||||
Reference in new issue
Block a user