allow renames() for inlined writes without data-dir (#18801)

data-dir not being present is okay, however we can still
rely on the `rename()` atomic call instead of relying on
write xl.meta write which may truncate the io.EOF.
This commit is contained in:
Harshavardhana 2024-02-20 07:05:57 -08:00 committed by GitHub
parent cb7dab17cb
commit c7f7c47388
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -2617,67 +2617,53 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
defer metaDataPoolPut(dstBuf) defer metaDataPoolPut(dstBuf)
if err != nil { if err != nil {
if legacyPreserved { if legacyPreserved {
// Any failed rename calls un-roll previous transaction.
s.deleteFile(dstVolumeDir, legacyDataPath, true, false) s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
} }
return 0, errFileCorrupt return 0, errFileCorrupt
} }
if srcDataPath != "" { if err = s.WriteAll(ctx, srcVolume, pathJoin(srcPath, xlStorageFormatFile), dstBuf); err != nil {
if err = s.WriteAll(ctx, srcVolume, pathJoin(srcPath, xlStorageFormatFile), dstBuf); err != nil { if legacyPreserved {
if legacyPreserved { s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
// Any failed rename calls un-roll previous transaction.
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
}
return 0, osErrToFileErr(err)
} }
diskHealthCheckOK(ctx, err) return 0, osErrToFileErr(err)
}
diskHealthCheckOK(ctx, err)
if srcDataPath != "" && len(fi.Data) == 0 && fi.Size > 0 {
// renameAll only for objects that have xl.meta not saved inline. // renameAll only for objects that have xl.meta not saved inline.
if len(fi.Data) == 0 && fi.Size > 0 { s.moveToTrash(dstDataPath, true, false)
s.moveToTrash(dstDataPath, true, false) if healing {
if healing { // If we are healing we should purge any legacyDataPath content,
// If we are healing we should purge any legacyDataPath content, // that was previously preserved during PutObject() call
// that was previously preserved during PutObject() call // on a versioned bucket.
// on a versioned bucket. s.moveToTrash(legacyDataPath, true, false)
s.moveToTrash(legacyDataPath, true, false)
}
if err = renameAll(srcDataPath, dstDataPath, dstVolumeDir); err != nil {
if legacyPreserved {
// Any failed rename calls un-roll previous transaction.
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
}
s.deleteFile(dstVolumeDir, dstDataPath, false, false)
return 0, osErrToFileErr(err)
}
} }
if err = renameAll(srcDataPath, dstDataPath, dstVolumeDir); err != nil {
// Commit meta-file
if err = renameAll(srcFilePath, dstFilePath, dstVolumeDir); err != nil {
if legacyPreserved { if legacyPreserved {
// Any failed rename calls un-roll previous transaction. // Any failed rename calls un-roll previous transaction.
s.deleteFile(dstVolumeDir, legacyDataPath, true, false) s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
} }
s.deleteFile(dstVolumeDir, dstFilePath, false, false) s.deleteFile(dstVolumeDir, dstDataPath, false, false)
return 0, osErrToFileErr(err) return 0, osErrToFileErr(err)
} }
}
// additionally only purge older data at the end of the transaction of new data-dir // Commit meta-file
// movement, this is to ensure that previous data references can co-exist for if err = renameAll(srcFilePath, dstFilePath, dstVolumeDir); err != nil {
// any recoverability. if legacyPreserved {
if oldDstDataPath != "" { // Any failed rename calls un-roll previous transaction.
s.moveToTrash(oldDstDataPath, true, false) s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
}
} else {
// Write meta-file directly, no data
if err = s.WriteAll(ctx, dstVolume, pathJoin(dstPath, xlStorageFormatFile), dstBuf); err != nil {
if legacyPreserved {
// Any failed rename calls un-roll previous transaction.
s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
}
s.deleteFile(dstVolumeDir, dstFilePath, false, false)
return 0, err
} }
s.deleteFile(dstVolumeDir, dstDataPath, false, false)
return 0, osErrToFileErr(err)
}
// additionally only purge older data at the end of the transaction of new data-dir
// movement, this is to ensure that previous data references can co-exist for
// any recoverability.
if oldDstDataPath != "" {
s.moveToTrash(oldDstDataPath, true, false)
} }
if srcVolume != minioMetaMultipartBucket { if srcVolume != minioMetaMultipartBucket {