From 9626a981bc34bd6a7a5f5d8c51ec70097bbe3320 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 19 Jun 2020 10:58:17 -0700 Subject: [PATCH] fix: Preserve old data appropriately (#9873) This PR fixes all the below scenarios and handles them correctly. - existing data/bucket is replaced with new content, no versioning enabled old structure vanishes. - existing data/bucket - enable versioning before uploading any data, once versioning enabled upload new content, old content is preserved. - suspend versioning on the bucket again, now upload content again the old content is purged since that is the default "null" version. Additionally sync data after xl.json -> xl.meta rename(), to avoid any surprises if there is a crash during this rename operation. --- cmd/xl-storage.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/cmd/xl-storage.go b/cmd/xl-storage.go index 86db8cf32..eca8f6a95 100644 --- a/cmd/xl-storage.go +++ b/cmd/xl-storage.go @@ -1231,6 +1231,10 @@ func (s *xlStorage) renameLegacyMetadata(volume, path string) error { srcFilePath := pathJoin(filePath, xlStorageFormatFileV1) dstFilePath := pathJoin(filePath, xlStorageFormatFile) + + // Renaming xl.json to xl.meta should be fully synced to disk. + defer globalSync() + if err = os.Rename(srcFilePath, dstFilePath); err != nil { switch { case isSysErrNotDir(err): @@ -2028,8 +2032,20 @@ func (s *xlStorage) RenameData(srcVolume, srcPath, dataDir, dstVolume, dstPath s } dstBuf, err := ioutil.ReadFile(dstFilePath) - if err != nil && !os.IsNotExist(err) { - return osErrToFileErr(err) + if err != nil { + if !os.IsNotExist(err) { + return osErrToFileErr(err) + } + err = s.renameLegacyMetadata(dstVolume, dstPath) + if err != nil && err != errFileNotFound { + return err + } + if err == nil { + dstBuf, err = ioutil.ReadFile(dstFilePath) + if err != nil && !os.IsNotExist(err) { + return osErrToFileErr(err) + } + } } var xlMeta xlMetaV2 @@ -2093,6 +2109,9 @@ func (s *xlStorage) RenameData(srcVolume, srcPath, dataDir, dstVolume, dstPath s return osErrToFileErr(err) } + // Sync all the directory operations. + globalSync() + for _, entry := range entries { if entry == xlStorageFormatFile { continue