From 5ddf7898fa63b57f24efd327f678bad19d7e138d Mon Sep 17 00:00:00 2001 From: ningmingxiao Date: Wed, 11 Feb 2026 20:32:50 +0800 Subject: [PATCH 1/2] use filepath instead of path Signed-off-by: ningmingxiao --- registry/storage/driver/filesystem/driver.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/registry/storage/driver/filesystem/driver.go b/registry/storage/driver/filesystem/driver.go index f3dd447fe..f40dd32c6 100644 --- a/registry/storage/driver/filesystem/driver.go +++ b/registry/storage/driver/filesystem/driver.go @@ -9,7 +9,7 @@ import ( "io" "net/http" "os" - "path" + "path/filepath" "time" "github.com/distribution/distribution/v3/internal/uuid" @@ -194,7 +194,7 @@ func (d *driver) Reader(ctx context.Context, path string, offset int64) (io.Read func (d *driver) Writer(ctx context.Context, subPath string, append bool) (storagedriver.FileWriter, error) { fullPath := d.fullPath(subPath) - parentDir := path.Dir(fullPath) + parentDir := filepath.Dir(fullPath) if err := os.MkdirAll(parentDir, 0o777); err != nil { return nil, err } @@ -266,7 +266,7 @@ func (d *driver) List(ctx context.Context, subPath string) ([]string, error) { keys := make([]string, 0, len(fileNames)) for _, fileName := range fileNames { - keys = append(keys, path.Join(subPath, fileName)) + keys = append(keys, filepath.Join(subPath, fileName)) } return keys, nil @@ -282,7 +282,7 @@ func (d *driver) Move(ctx context.Context, sourcePath string, destPath string) e return storagedriver.PathNotFoundError{Path: sourcePath} } - if err := os.MkdirAll(path.Dir(dest), 0o777); err != nil { + if err := os.MkdirAll(filepath.Dir(dest), 0o777); err != nil { return err } @@ -318,7 +318,7 @@ func (d *driver) Walk(ctx context.Context, path string, f storagedriver.WalkFn, // fullPath returns the absolute path of a key within the Driver's storage. func (d *driver) fullPath(subPath string) string { - return path.Join(d.rootDirectory, subPath) + return filepath.Join(d.rootDirectory, subPath) } type fileInfo struct { From b4f2af3f60f386b3415f1ff24e07fbc4eb6b4217 Mon Sep 17 00:00:00 2001 From: ningmingxiao Date: Fri, 30 Jan 2026 18:53:43 +0800 Subject: [PATCH 2/2] fix: sync parent dir to ensure data is reliably stored Co-authored-by: Sebastiaan van Stijn Signed-off-by: ningmingxiao Signed-off-by: Sebastiaan van Stijn --- registry/storage/driver/filesystem/driver.go | 44 +++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/registry/storage/driver/filesystem/driver.go b/registry/storage/driver/filesystem/driver.go index f40dd32c6..1b72f32b9 100644 --- a/registry/storage/driver/filesystem/driver.go +++ b/registry/storage/driver/filesystem/driver.go @@ -164,7 +164,25 @@ func (d *driver) PutContent(ctx context.Context, subPath string, contents []byte dErr := d.Delete(ctx, tempPath) return errors.Join(err, dErr) } + return syncDir(filepath.Dir(d.fullPath(subPath))) +} +func syncDir(dir string) (retErr error) { + dirF, err := os.Open(dir) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil + } + return fmt.Errorf("sync dir: %w", err) + } + defer func() { + if err := dirF.Close(); err != nil { + retErr = errors.Join(retErr, fmt.Errorf("failed to close dir: %w", err)) + } + }() + if err := dirF.Sync(); err != nil { + return fmt.Errorf("sync dir: %w", err) + } return nil } @@ -389,24 +407,27 @@ func (fw *fileWriter) Size() int64 { return fw.size } -func (fw *fileWriter) Close() error { +func (fw *fileWriter) Close() (retErr error) { if fw.closed { return fmt.Errorf("already closed") } + fw.closed = true + defer func() { + if err := fw.file.Close(); err != nil { + retErr = errors.Join(retErr, err) + } + }() + + if fw.committed { + // Already flushed and synced + return nil + } if err := fw.bw.Flush(); err != nil { return err } - if err := fw.file.Sync(); err != nil { - return err - } - - if err := fw.file.Close(); err != nil { - return err - } - fw.closed = true - return nil + return fw.file.Sync() } func (fw *fileWriter) Cancel(ctx context.Context) error { @@ -415,7 +436,8 @@ func (fw *fileWriter) Cancel(ctx context.Context) error { } fw.cancelled = true - fw.file.Close() + fw.closed = true + _ = fw.file.Close() return os.Remove(fw.file.Name()) }