fix: make sure to avoid calling RenameData() on disconnected disks. (#14094)

Large clusters with multiple sets, or multi-pool setups at times might
fail and report unexpected "file not found" errors. This can become
a problem during startup sequence when some files need to be created
at multiple locations.

- This PR ensures that we nil the erasure writers such that they
  are skipped in RenameData() call.

- RenameData() doesn't need to "Access()" calls for `.minio.sys`
  folders they always exist.

- Make sure PutObject() never returns ObjectNotFound{} for any
  errors, make sure it always returns "WriteQuorum" when renameData()
  fails with ObjectNotFound{}. Return appropriate errors for all
  other cases.
This commit is contained in:
Harshavardhana
2022-01-12 18:49:01 -08:00
committed by GitHub
parent 04e669a6be
commit 38ccc4f672
7 changed files with 59 additions and 25 deletions

View File

@@ -1984,6 +1984,14 @@ func (s *xlStorage) Delete(ctx context.Context, volume string, path string, recu
return s.deleteFile(volumeDir, filePath, recursive)
}
func skipAccessChecks(volume string) bool {
switch volume {
case minioMetaTmpBucket, minioMetaBucket, minioMetaMultipartBucket:
return true
}
return false
}
// RenameData - rename source path to destination path atomically, metadata and data directory.
func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, fi FileInfo, dstVolume, dstPath string) (err error) {
defer func() {
@@ -2010,23 +2018,27 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
return err
}
// Stat a volume entry.
if err = Access(srcVolumeDir); err != nil {
if osIsNotExist(err) {
return errVolumeNotFound
} else if isSysErrIO(err) {
return errFaultyDisk
if !skipAccessChecks(srcVolume) {
// Stat a volume entry.
if err = Access(srcVolumeDir); err != nil {
if osIsNotExist(err) {
return errVolumeNotFound
} else if isSysErrIO(err) {
return errFaultyDisk
}
return err
}
return err
}
if err = Access(dstVolumeDir); err != nil {
if osIsNotExist(err) {
return errVolumeNotFound
} else if isSysErrIO(err) {
return errFaultyDisk
if !skipAccessChecks(dstVolume) {
if err = Access(dstVolumeDir); err != nil {
if osIsNotExist(err) {
return errVolumeNotFound
} else if isSysErrIO(err) {
return errFaultyDisk
}
return err
}
return err
}
srcFilePath := pathutil.Join(srcVolumeDir, pathJoin(srcPath, xlStorageFormatFile))
@@ -2237,7 +2249,8 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
s.deleteFile(dstVolumeDir, legacyDataPath, true)
}
s.deleteFile(dstVolumeDir, dstDataPath, false)
if err != errFileNotFound {
// Looks like srcFilePath is missing usually at .minio.sys/ ignore it.
if !errors.Is(err, errFileNotFound) {
logger.LogIf(ctx, err)
}
return osErrToFileErr(err)
@@ -2252,9 +2265,11 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
}
s.deleteFile(dstVolumeDir, dstFilePath, false)
if err != errFileNotFound {
// Looks like srcFilePath is missing usually at .minio.sys/ ignore it.
if !errors.Is(err, errFileNotFound) {
logger.LogIf(ctx, err)
}
return osErrToFileErr(err)
}