use rename() safety for in-place 'xl.meta' updates (#20414)

This commit is contained in:
Poorna 2024-09-11 09:08:51 -07:00 committed by GitHub
parent a6d5287310
commit cdd7512a2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 47 additions and 6 deletions

View File

@ -45,6 +45,7 @@ import (
"github.com/minio/minio/internal/bucket/lifecycle"
"github.com/minio/minio/internal/cachevalue"
"github.com/minio/minio/internal/config/storageclass"
"github.com/minio/minio/internal/disk"
xioutil "github.com/minio/minio/internal/ioutil"
"github.com/minio/minio/internal/logger"
@ -1404,7 +1405,7 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F
return err
}
return s.WriteAll(ctx, volume, pathJoin(path, xlStorageFormatFile), buf)
return s.writeAllMeta(ctx, volume, pathJoin(path, xlStorageFormatFile), buf, true)
}
if opts.UndoWrite && opts.OldDataDir != "" {
@ -1459,7 +1460,7 @@ func (s *xlStorage) UpdateMetadata(ctx context.Context, volume, path string, fi
}
defer metaDataPoolPut(wbuf)
return s.writeAll(ctx, volume, pathJoin(path, xlStorageFormatFile), wbuf, !opts.NoPersistence, volumeDir)
return s.writeAllMeta(ctx, volume, pathJoin(path, xlStorageFormatFile), wbuf, !opts.NoPersistence)
}
// WriteMetadata - writes FileInfo metadata for path at `xl.meta`
@ -2210,7 +2211,8 @@ func (s *xlStorage) writeAllDirect(ctx context.Context, filePath string, fileSiz
return w.Close()
}
func (s *xlStorage) writeAll(ctx context.Context, volume string, path string, b []byte, sync bool, skipParent string) (err error) {
// writeAllMeta - writes all metadata to a temp file and then links it to the final destination.
func (s *xlStorage) writeAllMeta(ctx context.Context, volume string, path string, b []byte, sync bool) (err error) {
if contextCanceled(ctx) {
return ctx.Err()
}
@ -2225,6 +2227,26 @@ func (s *xlStorage) writeAll(ctx context.Context, volume string, path string, b
return err
}
tmpVolumeDir, err := s.getVolDir(minioMetaTmpBucket)
if err != nil {
return err
}
tmpFilePath := pathJoin(tmpVolumeDir, mustGetUUID())
defer func() {
if err != nil {
Remove(tmpFilePath)
}
}()
if err = s.writeAllInternal(ctx, tmpFilePath, b, sync, tmpVolumeDir); err != nil {
return err
}
return renameAll(tmpFilePath, filePath, volumeDir)
}
func (s *xlStorage) writeAllInternal(ctx context.Context, filePath string, b []byte, sync bool, skipParent string) (err error) {
flags := os.O_CREATE | os.O_WRONLY | os.O_TRUNC
var w *os.File
@ -2269,6 +2291,24 @@ func (s *xlStorage) writeAll(ctx context.Context, volume string, path string, b
return w.Close()
}
func (s *xlStorage) writeAll(ctx context.Context, volume string, path string, b []byte, sync bool, skipParent string) (err error) {
if contextCanceled(ctx) {
return ctx.Err()
}
volumeDir, err := s.getVolDir(volume)
if err != nil {
return err
}
filePath := pathJoin(volumeDir, path)
if err = checkPathLength(filePath); err != nil {
return err
}
return s.writeAllInternal(ctx, filePath, b, sync, skipParent)
}
func (s *xlStorage) WriteAll(ctx context.Context, volume string, path string, b []byte) (err error) {
// Specific optimization to avoid re-read from the drives for `format.json`
// in-case the caller is a network operation.

3
go.mod
View File

@ -94,7 +94,7 @@ require (
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948
golang.org/x/oauth2 v0.22.0
golang.org/x/sync v0.8.0
golang.org/x/sys v0.24.0
golang.org/x/sys v0.25.0
golang.org/x/term v0.23.0
golang.org/x/time v0.6.0
google.golang.org/api v0.194.0
@ -254,4 +254,5 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c // indirect
google.golang.org/grpc v1.65.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)

4
go.sum
View File

@ -781,8 +781,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=