mirror of
https://github.com/minio/minio.git
synced 2025-04-04 20:00:31 -04:00
fix: deleteVersions causing xl.meta to have empty Versions[] slice (#14483)
This is a side-affect of the optimization done in PR #13544 which causes a certain type of delete operations on given object versions can cause lastVersion indication to be skipped, which leads to an `xl.meta` where Versions[] slice is empty while the entire file is intact by itself. This PR tries to ensure that such files are visible and deletable by regular means of listing as null 'delete-marker' and also avoid the situation where this potential issue might arise.
This commit is contained in:
parent
bbc914e174
commit
b0c84e3de7
@ -23,6 +23,7 @@ import (
|
|||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
@ -2427,7 +2428,9 @@ func (a adminAPIHandlers) InspectDataHandler(w http.ResponseWriter, r *http.Requ
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
logger.LogIf(ctx, err)
|
if !errors.Is(err, errFileNotFound) {
|
||||||
|
logger.LogIf(ctx, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createHostAnonymizerForFSMode() map[string]string {
|
func createHostAnonymizerForFSMode() map[string]string {
|
||||||
|
@ -83,7 +83,10 @@ func commonTime(modTimes []time.Time) (modTime time.Time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Beginning of unix time is treated as sentinel value here.
|
// Beginning of unix time is treated as sentinel value here.
|
||||||
var timeSentinel = time.Unix(0, 0).UTC()
|
var (
|
||||||
|
timeSentinel = time.Unix(0, 0).UTC()
|
||||||
|
timeSentinel1970 = time.Unix(0, 1).UTC() // 1970 used for special cases when xlmeta.version == 0
|
||||||
|
)
|
||||||
|
|
||||||
// Boot modTimes up to disk count, setting the value to time sentinel.
|
// Boot modTimes up to disk count, setting the value to time sentinel.
|
||||||
func bootModtimes(diskCount int) []time.Time {
|
func bootModtimes(diskCount int) []time.Time {
|
||||||
|
@ -128,6 +128,86 @@ func TestErasureDeleteObjectBasic(t *testing.T) {
|
|||||||
removeRoots(fsDirs)
|
removeRoots(fsDirs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteObjectsVersioned(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
obj, fsDirs, err := prepareErasure(ctx, 16)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to initialize 'Erasure' object layer.", err)
|
||||||
|
}
|
||||||
|
// Remove all dirs.
|
||||||
|
for _, dir := range fsDirs {
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
type testCaseType struct {
|
||||||
|
bucket string
|
||||||
|
object string
|
||||||
|
}
|
||||||
|
|
||||||
|
bucketName := "bucket"
|
||||||
|
testCases := []testCaseType{
|
||||||
|
{bucketName, "dir/obj1"},
|
||||||
|
{bucketName, "dir/obj1"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = obj.MakeBucketWithLocation(ctx, bucketName, BucketOptions{
|
||||||
|
VersioningEnabled: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
names := make([]ObjectToDelete, len(testCases))
|
||||||
|
for i, testCase := range testCases {
|
||||||
|
objInfo, err := obj.PutObject(ctx, testCase.bucket, testCase.object,
|
||||||
|
mustGetPutObjReader(t, bytes.NewReader([]byte("abcd")), int64(len("abcd")), "", ""), ObjectOptions{
|
||||||
|
Versioned: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Erasure Object upload failed: <ERROR> %s", err)
|
||||||
|
}
|
||||||
|
names[i] = ObjectToDelete{
|
||||||
|
ObjectV: ObjectV{
|
||||||
|
ObjectName: objInfo.Name,
|
||||||
|
VersionID: objInfo.VersionID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
names = append(names, ObjectToDelete{
|
||||||
|
ObjectV: ObjectV{
|
||||||
|
ObjectName: "dir/obj1",
|
||||||
|
VersionID: mustGetUUID(), // add a non-existent UUID.
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
_, delErrs := obj.DeleteObjects(ctx, bucketName, names, ObjectOptions{
|
||||||
|
Versioned: true,
|
||||||
|
})
|
||||||
|
for i := range delErrs {
|
||||||
|
if delErrs[i] != nil {
|
||||||
|
t.Errorf("Failed to remove object `%v` with the error: `%v`", names[i], delErrs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range testCases {
|
||||||
|
_, statErr := obj.GetObjectInfo(ctx, test.bucket, test.object, ObjectOptions{
|
||||||
|
VersionID: names[i].ObjectV.VersionID,
|
||||||
|
})
|
||||||
|
switch statErr.(type) {
|
||||||
|
case VersionNotFound:
|
||||||
|
default:
|
||||||
|
t.Fatalf("Object %s is not removed", test.bucket+SlashSeparator+test.object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = ioutil.ReadFile(pathJoin(fsDirs[0], bucketName, "dir/obj1", "xl.meta")); err == nil {
|
||||||
|
t.Fatalf("xl.meta still present after removal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestErasureDeleteObjectsErasureSet(t *testing.T) {
|
func TestErasureDeleteObjectsErasureSet(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -191,6 +191,16 @@ func (e *metaCacheEntry) fileInfo(bucket string) (FileInfo, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
if e.cached != nil {
|
if e.cached != nil {
|
||||||
|
if len(e.cached.versions) == 0 {
|
||||||
|
// This special case is needed to handle xlMeta.versions == 0
|
||||||
|
return FileInfo{
|
||||||
|
Volume: bucket,
|
||||||
|
Name: e.name,
|
||||||
|
Deleted: true,
|
||||||
|
IsLatest: true,
|
||||||
|
ModTime: timeSentinel1970,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
return e.cached.ToFileInfo(bucket, e.name, "")
|
return e.cached.ToFileInfo(bucket, e.name, "")
|
||||||
}
|
}
|
||||||
return getFileInfo(e.metadata, bucket, e.name, "", false)
|
return getFileInfo(e.metadata, bucket, e.name, "", false)
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/zeebo/xxh3"
|
"github.com/zeebo/xxh3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,7 +59,19 @@ func getAllFileInfoVersions(xlMetaBuf []byte, volume, path string) (FileInfoVers
|
|||||||
}
|
}
|
||||||
versions, err = xlMeta.ListVersions(volume, path)
|
versions, err = xlMeta.ListVersions(volume, path)
|
||||||
}
|
}
|
||||||
if err != nil || len(versions) == 0 {
|
if err == nil && len(versions) == 0 {
|
||||||
|
// This special case is needed to handle len(xlMeta.versions) == 0
|
||||||
|
versions = []FileInfo{
|
||||||
|
{
|
||||||
|
Volume: volume,
|
||||||
|
Name: path,
|
||||||
|
Deleted: true,
|
||||||
|
IsLatest: true,
|
||||||
|
ModTime: timeSentinel1970,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
return FileInfoVersions{}, err
|
return FileInfoVersions{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,11 +90,33 @@ func getFileInfo(xlMetaBuf []byte, volume, path, versionID string, data bool) (F
|
|||||||
if buf, data := isIndexedMetaV2(xlMetaBuf); buf != nil {
|
if buf, data := isIndexedMetaV2(xlMetaBuf); buf != nil {
|
||||||
inData = data
|
inData = data
|
||||||
fi, err = buf.ToFileInfo(volume, path, versionID)
|
fi, err = buf.ToFileInfo(volume, path, versionID)
|
||||||
|
if len(buf) != 0 && errors.Is(err, errFileNotFound) {
|
||||||
|
// This special case is needed to handle len(xlMeta.versions) == 0
|
||||||
|
return FileInfo{
|
||||||
|
Volume: volume,
|
||||||
|
Name: path,
|
||||||
|
VersionID: versionID,
|
||||||
|
Deleted: true,
|
||||||
|
IsLatest: true,
|
||||||
|
ModTime: timeSentinel1970,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var xlMeta xlMetaV2
|
var xlMeta xlMetaV2
|
||||||
if err := xlMeta.LoadOrConvert(xlMetaBuf); err != nil {
|
if err := xlMeta.LoadOrConvert(xlMetaBuf); err != nil {
|
||||||
return FileInfo{}, err
|
return FileInfo{}, err
|
||||||
}
|
}
|
||||||
|
if len(xlMeta.versions) == 0 {
|
||||||
|
// This special case is needed to handle len(xlMeta.versions) == 0
|
||||||
|
return FileInfo{
|
||||||
|
Volume: volume,
|
||||||
|
Name: path,
|
||||||
|
VersionID: versionID,
|
||||||
|
Deleted: true,
|
||||||
|
IsLatest: true,
|
||||||
|
ModTime: timeSentinel1970,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
inData = xlMeta.data
|
inData = xlMeta.data
|
||||||
fi, err = xlMeta.ToFileInfo(volume, path, versionID)
|
fi, err = xlMeta.ToFileInfo(volume, path, versionID)
|
||||||
}
|
}
|
||||||
|
@ -1150,7 +1150,7 @@ func (x *xlMetaV2) sortByModTime() {
|
|||||||
// DeleteVersion deletes the version specified by version id.
|
// DeleteVersion deletes the version specified by version id.
|
||||||
// returns to the caller which dataDir to delete, also
|
// returns to the caller which dataDir to delete, also
|
||||||
// indicates if this is the last version.
|
// indicates if this is the last version.
|
||||||
func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, bool, error) {
|
func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, error) {
|
||||||
// This is a situation where versionId is explicitly
|
// This is a situation where versionId is explicitly
|
||||||
// specified as "null", as we do not save "null"
|
// specified as "null", as we do not save "null"
|
||||||
// string it is considered empty. But empty also
|
// string it is considered empty. But empty also
|
||||||
@ -1164,7 +1164,7 @@ func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, bool, error) {
|
|||||||
if fi.VersionID != "" {
|
if fi.VersionID != "" {
|
||||||
uv, err = uuid.Parse(fi.VersionID)
|
uv, err = uuid.Parse(fi.VersionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, errFileVersionNotFound
|
return "", errFileVersionNotFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1179,7 +1179,7 @@ func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, bool, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
if !ventry.Valid() {
|
if !ventry.Valid() {
|
||||||
return "", false, errors.New("internal error: invalid version entry generated")
|
return "", errors.New("internal error: invalid version entry generated")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateVersion := false
|
updateVersion := false
|
||||||
@ -1225,18 +1225,18 @@ func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, bool, error) {
|
|||||||
case LegacyType:
|
case LegacyType:
|
||||||
ver, err := x.getIdx(i)
|
ver, err := x.getIdx(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", err
|
||||||
}
|
}
|
||||||
x.versions = append(x.versions[:i], x.versions[i+1:]...)
|
x.versions = append(x.versions[:i], x.versions[i+1:]...)
|
||||||
if fi.Deleted {
|
if fi.Deleted {
|
||||||
err = x.addVersion(ventry)
|
err = x.addVersion(ventry)
|
||||||
}
|
}
|
||||||
return ver.ObjectV1.DataDir, len(x.versions) == 0, err
|
return ver.ObjectV1.DataDir, err
|
||||||
case DeleteType:
|
case DeleteType:
|
||||||
if updateVersion {
|
if updateVersion {
|
||||||
ver, err := x.getIdx(i)
|
ver, err := x.getIdx(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", err
|
||||||
}
|
}
|
||||||
if len(ver.DeleteMarker.MetaSys) == 0 {
|
if len(ver.DeleteMarker.MetaSys) == 0 {
|
||||||
ver.DeleteMarker.MetaSys = make(map[string][]byte)
|
ver.DeleteMarker.MetaSys = make(map[string][]byte)
|
||||||
@ -1258,26 +1258,26 @@ func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, bool, error) {
|
|||||||
ver.DeleteMarker.MetaSys[k] = []byte(v)
|
ver.DeleteMarker.MetaSys[k] = []byte(v)
|
||||||
}
|
}
|
||||||
err = x.setIdx(i, *ver)
|
err = x.setIdx(i, *ver)
|
||||||
return "", len(x.versions) == 0, err
|
return "", err
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
x.versions = append(x.versions[:i], x.versions[i+1:]...)
|
x.versions = append(x.versions[:i], x.versions[i+1:]...)
|
||||||
if fi.MarkDeleted && (fi.VersionPurgeStatus().Empty() || (fi.VersionPurgeStatus() != Complete)) {
|
if fi.MarkDeleted && (fi.VersionPurgeStatus().Empty() || (fi.VersionPurgeStatus() != Complete)) {
|
||||||
err = x.addVersion(ventry)
|
err = x.addVersion(ventry)
|
||||||
}
|
}
|
||||||
return "", len(x.versions) == 0, err
|
return "", err
|
||||||
case ObjectType:
|
case ObjectType:
|
||||||
if updateVersion && !fi.Deleted {
|
if updateVersion && !fi.Deleted {
|
||||||
ver, err := x.getIdx(i)
|
ver, err := x.getIdx(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", err
|
||||||
}
|
}
|
||||||
ver.ObjectV2.MetaSys[VersionPurgeStatusKey] = []byte(fi.ReplicationState.VersionPurgeStatusInternal)
|
ver.ObjectV2.MetaSys[VersionPurgeStatusKey] = []byte(fi.ReplicationState.VersionPurgeStatusInternal)
|
||||||
for k, v := range fi.ReplicationState.ResetStatusesMap {
|
for k, v := range fi.ReplicationState.ResetStatusesMap {
|
||||||
ver.ObjectV2.MetaSys[k] = []byte(v)
|
ver.ObjectV2.MetaSys[k] = []byte(v)
|
||||||
}
|
}
|
||||||
err = x.setIdx(i, *ver)
|
err = x.setIdx(i, *ver)
|
||||||
return "", len(x.versions) == 0, err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1288,7 +1288,7 @@ func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, bool, error) {
|
|||||||
}
|
}
|
||||||
ver, err := x.getIdx(i)
|
ver, err := x.getIdx(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", false, err
|
return "", err
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case fi.ExpireRestored:
|
case fi.ExpireRestored:
|
||||||
@ -1314,16 +1314,16 @@ func (x *xlMetaV2) DeleteVersion(fi FileInfo) (string, bool, error) {
|
|||||||
if x.SharedDataDirCount(ver.ObjectV2.VersionID, ver.ObjectV2.DataDir) > 0 {
|
if x.SharedDataDirCount(ver.ObjectV2.VersionID, ver.ObjectV2.DataDir) > 0 {
|
||||||
// Found that another version references the same dataDir
|
// Found that another version references the same dataDir
|
||||||
// we shouldn't remove it, and only remove the version instead
|
// we shouldn't remove it, and only remove the version instead
|
||||||
return "", len(x.versions) == 0, nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return uuid.UUID(ver.ObjectV2.DataDir).String(), len(x.versions) == 0, err
|
return uuid.UUID(ver.ObjectV2.DataDir).String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.Deleted {
|
if fi.Deleted {
|
||||||
err = x.addVersion(ventry)
|
err = x.addVersion(ventry)
|
||||||
return "", false, err
|
return "", err
|
||||||
}
|
}
|
||||||
return "", false, errFileVersionNotFound
|
return "", errFileVersionNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
// xlMetaDataDirDecoder is a shallow decoder for decoding object datadir only.
|
// xlMetaDataDirDecoder is a shallow decoder for decoding object datadir only.
|
||||||
|
@ -366,7 +366,7 @@ func TestDeleteVersionWithSharedDataDir(t *testing.T) {
|
|||||||
count := len(testCases)
|
count := len(testCases)
|
||||||
for i := 4; i < len(testCases); i++ {
|
for i := 4; i < len(testCases); i++ {
|
||||||
tc := testCases[i]
|
tc := testCases[i]
|
||||||
dataDir, _, err := xl.DeleteVersion(fileInfos[i])
|
dataDir, err := xl.DeleteVersion(fileInfos[i])
|
||||||
failOnErr(count+1, err)
|
failOnErr(count+1, err)
|
||||||
if dataDir != tc.expectedDataDir {
|
if dataDir != tc.expectedDataDir {
|
||||||
t.Fatalf("Expected %s but got %s", tc.expectedDataDir, dataDir)
|
t.Fatalf("Expected %s but got %s", tc.expectedDataDir, dataDir)
|
||||||
|
@ -433,7 +433,7 @@ func BenchmarkXlMetaV2Shallow(b *testing.B) {
|
|||||||
// Update a random version.
|
// Update a random version.
|
||||||
fi.VersionID = ids[rng.Intn(size)]
|
fi.VersionID = ids[rng.Intn(size)]
|
||||||
// Delete...
|
// Delete...
|
||||||
_, _, err = xl.DeleteVersion(fi)
|
_, err = xl.DeleteVersion(fi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ func TestFreeVersion(t *testing.T) {
|
|||||||
tierfi.TransitionedObjName = mustGetUUID()
|
tierfi.TransitionedObjName = mustGetUUID()
|
||||||
tierfi.TransitionTier = "MINIOTIER-1"
|
tierfi.TransitionTier = "MINIOTIER-1"
|
||||||
var err error
|
var err error
|
||||||
_, _, err = xl.DeleteVersion(tierfi)
|
_, err = xl.DeleteVersion(tierfi)
|
||||||
fatalErr(err)
|
fatalErr(err)
|
||||||
report()
|
report()
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ func TestFreeVersion(t *testing.T) {
|
|||||||
newtierfi.TransitionStatus = ""
|
newtierfi.TransitionStatus = ""
|
||||||
newtierfi.SetTierFreeVersionID(fvIDs[1])
|
newtierfi.SetTierFreeVersionID(fvIDs[1])
|
||||||
report()
|
report()
|
||||||
_, _, err = xl.DeleteVersion(newtierfi)
|
_, err = xl.DeleteVersion(newtierfi)
|
||||||
report()
|
report()
|
||||||
fatalErr(err)
|
fatalErr(err)
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ func TestFreeVersion(t *testing.T) {
|
|||||||
freefi := newtierfi
|
freefi := newtierfi
|
||||||
for _, fvID := range fvIDs {
|
for _, fvID := range fvIDs {
|
||||||
freefi.VersionID = fvID
|
freefi.VersionID = fvID
|
||||||
_, _, err = xl.DeleteVersion(freefi)
|
_, err = xl.DeleteVersion(freefi)
|
||||||
fatalErr(err)
|
fatalErr(err)
|
||||||
}
|
}
|
||||||
report()
|
report()
|
||||||
|
@ -880,22 +880,15 @@ func (s *xlStorage) deleteVersions(ctx context.Context, volume, path string, fis
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
dataDir string
|
|
||||||
lastVersion bool
|
|
||||||
updated bool
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, fi := range fis {
|
for _, fi := range fis {
|
||||||
dataDir, lastVersion, err = xlMeta.DeleteVersion(fi)
|
dataDir, err := xlMeta.DeleteVersion(fi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !fi.Deleted && (err == errFileNotFound || err == errFileVersionNotFound) {
|
if !fi.Deleted && (err == errFileNotFound || err == errFileVersionNotFound) {
|
||||||
// Ignore these since
|
// Ignore these since they do not exist
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
updated = true
|
|
||||||
if dataDir != "" {
|
if dataDir != "" {
|
||||||
versionID := fi.VersionID
|
versionID := fi.VersionID
|
||||||
if versionID == "" {
|
if versionID == "" {
|
||||||
@ -918,11 +911,8 @@ func (s *xlStorage) deleteVersions(ctx context.Context, volume, path string, fis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastVersion := len(xlMeta.versions) == 0
|
||||||
if !lastVersion {
|
if !lastVersion {
|
||||||
if !updated {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buf, err = xlMeta.AppendTo(metaDataPoolGet())
|
buf, err = xlMeta.AppendTo(metaDataPoolGet())
|
||||||
defer metaDataPoolPut(buf)
|
defer metaDataPoolPut(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -933,12 +923,7 @@ func (s *xlStorage) deleteVersions(ctx context.Context, volume, path string, fis
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Move xl.meta to trash
|
// Move xl.meta to trash
|
||||||
filePath := pathJoin(volumeDir, path, xlStorageFormatFile)
|
err = s.moveToTrash(pathJoin(volumeDir, path, xlStorageFormatFile), false)
|
||||||
if err = checkPathLength(filePath); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.moveToTrash(filePath, false)
|
|
||||||
if err == nil || err == errFileNotFound {
|
if err == nil || err == errFileNotFound {
|
||||||
s.deleteFile(volumeDir, pathJoin(volumeDir, path), false)
|
s.deleteFile(volumeDir, pathJoin(volumeDir, path), false)
|
||||||
}
|
}
|
||||||
@ -1021,7 +1006,7 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dataDir, lastVersion, err := xlMeta.DeleteVersion(fi)
|
dataDir, err := xlMeta.DeleteVersion(fi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1046,7 +1031,7 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !lastVersion {
|
if len(xlMeta.versions) != 0 {
|
||||||
buf, err = xlMeta.AppendTo(metaDataPoolGet())
|
buf, err = xlMeta.AppendTo(metaDataPoolGet())
|
||||||
defer metaDataPoolPut(buf)
|
defer metaDataPoolPut(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,9 +7,9 @@ x-minio-common: &minio-common
|
|||||||
expose:
|
expose:
|
||||||
- "9000"
|
- "9000"
|
||||||
- "9001"
|
- "9001"
|
||||||
environment:
|
# environment:
|
||||||
MINIO_ROOT_USER: minio
|
# MINIO_ROOT_USER: minioadmin
|
||||||
MINIO_ROOT_PASSWORD: minio123
|
# MINIO_ROOT_PASSWORD: minioadmin
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
|
Loading…
x
Reference in New Issue
Block a user