Fix: prevent panic when swap file creation fails (#7957)

* Fix: prevent panic when swap file creation fails

* weed mount: fix race condition in swap file initialization

Ensure thread-safe access to sf.file and other state in NewSwapFileChunk
and FreeResource by using sf.chunkTrackingLock consistently. Also
set sf.file to nil after closing to prevent reuse.

* weed mount: improve swap directory creation logic

- Check error for os.MkdirAll and log it if it fails.
- Use 0700 permissions for the swap directory for better security.
- Improve error logging context.

* weed mount: add unit tests for swap file creation

Add tests to verify:
- Concurrent initialization of the swap file.
- Correct directory permissions (0700).
- Automatic directory recreation if deleted.

* weed mount: fix thread-safety in swap file unit tests

Use atomic.Uint32 to track failures within goroutines in
TestSwapFile_NewSwapFileChunk_Concurrent to avoid unsafe calls to
t.Errorf from multiple goroutines.

* weed mount: simplify swap file creation logic

Refactor the directory check and retry logic for better readability and
to avoid re-using the main error variable for directory creation errors.
Remove redundant error logging.

* weed mount: improve error checking in swap file tests

Explicitly check if NewSwapFileChunk returns nil to provide more
informative failures.

* weed mount: update DirtyPages interface to return error

Propagate errors from SaveDataAt when swap file creation fails. This
prevents potential panics in the write path.

* weed mount: handle AddPage errors in write paths

Update ChunkedDirtyPages and PageWriter to propagate errors and update
WFS.Write and WFS.CopyFileRange to return fuse.EIO on failure.

* weed mount: update swap directory creation error message

Change "recreate" to "create/recreate" to better reflect that this path
is also taken during the initial creation of the swap directory.

---------

Co-authored-by: lixiang58 <lixiang58@lenovo.com>
Co-authored-by: Chris Lu <chris.lu@gmail.com>
This commit is contained in:
LeeXN
2026-01-04 17:12:37 +08:00
committed by GitHub
parent 0b5a65e00b
commit c909724bf1
9 changed files with 156 additions and 23 deletions

View File

@@ -2,10 +2,11 @@ package page_writer
import (
"fmt"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/util"
"sync"
"sync/atomic"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/util"
)
type LogicChunkIndex int
@@ -55,7 +56,7 @@ func NewUploadPipeline(writers *util.LimitedConcurrentExecutor, chunkSize int64,
return t
}
func (up *UploadPipeline) SaveDataAt(p []byte, off int64, isSequential bool, tsNs int64) (n int) {
func (up *UploadPipeline) SaveDataAt(p []byte, off int64, isSequential bool, tsNs int64) (n int, err error) {
up.chunksLock.Lock()
defer up.chunksLock.Unlock()
@@ -103,6 +104,9 @@ func (up *UploadPipeline) SaveDataAt(p []byte, off int64, isSequential bool, tsN
} else {
pageChunk = up.swapFile.NewSwapFileChunk(logicChunkIndex)
// fmt.Printf(" create file chunk %d\n", logicChunkIndex)
if pageChunk == nil {
return 0, fmt.Errorf("failed to create swap file chunk")
}
}
up.writableChunks[logicChunkIndex] = pageChunk
}