History

purge objects immediately with `x-minio-force-delete` in DeleteObject and DeleteBucket API (#15148)

Praveen raj Mani committed 4 years ago

Commit b49fc331 parent 00e235a20 files · +220 −79Browse files

Unified · Split

20 files
  1. cmd/background-newdisks-heal-ops.go +5 −1
  2. cmd/erasure-encode_test.go +4 −1
  3. cmd/erasure-healing-common_test.go +8 −2
  4. cmd/erasure-healing.go +4 −1
  5. cmd/erasure-healing_test.go +44 −11
  6. cmd/erasure-multipart.go +8 −2
  7. cmd/erasure-object.go +8 −2
  8. cmd/erasure-object_test.go +8 −2
  9. cmd/erasure-single-drive.go +16 −4
  10. cmd/format-erasure.go +4 −1
  11. cmd/naughty-disk_test.go +2 −2
  12. cmd/storage-datatypes.go +7 −0
  13. cmd/storage-interface.go +2 −2
  14. cmd/storage-rest-client.go +3 −2
  15. cmd/storage-rest-server.go +9 −2
  16. cmd/storage-rest_test.go +4 −1
  17. cmd/xl-storage-disk-id-check.go +6 −3
  18. cmd/xl-storage.go +50 −33
  19. cmd/xl-storage_test.go +24 −6
  20. cmd/xl-storage_windows_test.go +4 −1
cmd/background-newdisks-heal-ops.go+5−1
@@ -163,7 +163,11 @@ func (h *healingTracker) save(ctx context.Context) error { · 162 unmodified lines
163func (h *healingTracker) delete(ctx context.Context) error {163func (h *healingTracker) delete(ctx context.Context) error {
164 return h.disk.Delete(ctx, minioMetaBucket,164 return h.disk.Delete(ctx, minioMetaBucket,
165 pathJoin(bucketMetaPrefix, slashSeparator, healingTrackerFilename),165 pathJoin(bucketMetaPrefix, slashSeparator, healingTrackerFilename),
166 false)166 DeleteOptions{
167 Recursive: false,
168 Force: false,
169 },
170 )
167}171}
168 172
169func (h *healingTracker) isHealed(bucket string) bool {173func (h *healingTracker) isHealed(bucket string) bool {
cmd/erasure-encode_test.go+4−1
@@ -196,7 +196,10 @@ func benchmarkErasureEncode(data, parity, dataDown, parityDown int, size int64, · 195 unmodified lines
196 if disk == OfflineDisk {196 if disk == OfflineDisk {
197 continue197 continue
198 }198 }
199 disk.Delete(context.Background(), "testbucket", "object", false)199 disk.Delete(context.Background(), "testbucket", "object", DeleteOptions{
200 Recursive: false,
201 Force: false,
202 })
200 writers[i] = newBitrotWriter(disk, "testbucket", "object", erasure.ShardFileSize(size), DefaultBitrotAlgorithm, erasure.ShardSize())203 writers[i] = newBitrotWriter(disk, "testbucket", "object", erasure.ShardFileSize(size), DefaultBitrotAlgorithm, erasure.ShardSize())
201 }204 }
202 _, err := erasure.Encode(context.Background(), bytes.NewReader(content), writers, buffer, erasure.dataBlocks+1)205 _, err := erasure.Encode(context.Background(), bytes.NewReader(content), writers, buffer, erasure.dataBlocks+1)
cmd/erasure-healing-common_test.go+8−2
@@ -218,7 +218,10 @@ func TestListOnlineDisks(t *testing.T) { · 217 unmodified lines
218 // and check if that disk218 // and check if that disk
219 // appears in outDatedDisks.219 // appears in outDatedDisks.
220 tamperedIndex = index220 tamperedIndex = index
221 dErr := erasureDisks[index].Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), false)221 dErr := erasureDisks[index].Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), DeleteOptions{
222 Recursive: false,
223 Force: false,
224 })
222 if dErr != nil {225 if dErr != nil {
223 t.Fatalf("Failed to delete %s - %v", filepath.Join(object, "part.1"), dErr)226 t.Fatalf("Failed to delete %s - %v", filepath.Join(object, "part.1"), dErr)
224 }227 }
@@ -395,7 +398,10 @@ func TestListOnlineDisksSmallObjects(t *testing.T) { · 170 unmodified lines
395 // and check if that disk398 // and check if that disk
396 // appears in outDatedDisks.399 // appears in outDatedDisks.
397 tamperedIndex = index400 tamperedIndex = index
398 dErr := erasureDisks[index].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), false)401 dErr := erasureDisks[index].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), DeleteOptions{
402 Recursive: false,
403 Force: false,
404 })
399 if dErr != nil {405 if dErr != nil {
400 t.Fatalf("Failed to delete %s - %v", pathJoin(object, xlStorageFormatFile), dErr)406 t.Fatalf("Failed to delete %s - %v", pathJoin(object, xlStorageFormatFile), dErr)
401 }407 }
cmd/erasure-healing.go+4−1
@@ -655,7 +655,10 @@ func (er erasureObjects) healObjectDir(ctx context.Context, bucket, object strin · 654 unmodified lines
655 wg.Add(1)655 wg.Add(1)
656 go func(index int, disk StorageAPI) {656 go func(index int, disk StorageAPI) {
657 defer wg.Done()657 defer wg.Done()
658 _ = disk.Delete(ctx, bucket, object, false)658 _ = disk.Delete(ctx, bucket, object, DeleteOptions{
659 Recursive: false,
660 Force: false,
661 })
659 }(index, disk)662 }(index, disk)
660 }663 }
661 wg.Wait()664 wg.Wait()
cmd/erasure-healing_test.go+44−11
@@ -610,7 +610,10 @@ func TestHealCorrectQuorum(t *testing.T) { · 609 unmodified lines
610 }610 }
611 611
612 for i := 0; i < nfi.Erasure.ParityBlocks; i++ {612 for i := 0; i < nfi.Erasure.ParityBlocks; i++ {
613 erasureDisks[i].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), false)613 erasureDisks[i].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), DeleteOptions{
614 Recursive: false,
615 Force: false,
616 })
614 }617 }
615 618
616 // Try healing now, it should heal the content properly.619 // Try healing now, it should heal the content properly.
@@ -634,7 +637,10 @@ func TestHealCorrectQuorum(t *testing.T) { · 17 unmodified lines
634 }637 }
635 638
636 for i := 0; i < nfi.Erasure.ParityBlocks; i++ {639 for i := 0; i < nfi.Erasure.ParityBlocks; i++ {
637 erasureDisks[i].Delete(context.Background(), minioMetaBucket, pathJoin(cfgFile, xlStorageFormatFile), false)640 erasureDisks[i].Delete(context.Background(), minioMetaBucket, pathJoin(cfgFile, xlStorageFormatFile), DeleteOptions{
641 Recursive: false,
642 Force: false,
643 })
638 }644 }
639 645
640 // Try healing now, it should heal the content properly.646 // Try healing now, it should heal the content properly.
@@ -714,7 +720,10 @@ func TestHealObjectCorruptedPools(t *testing.T) { · 73 unmodified lines
714 er := set.sets[0]720 er := set.sets[0]
715 erasureDisks := er.getDisks()721 erasureDisks := er.getDisks()
716 firstDisk := erasureDisks[0]722 firstDisk := erasureDisks[0]
717 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), false)723 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), DeleteOptions{
724 Recursive: false,
725 Force: false,
726 })
718 if err != nil {727 if err != nil {
719 t.Fatalf("Failed to delete a file - %v", err)728 t.Fatalf("Failed to delete a file - %v", err)
720 }729 }
@@ -734,7 +743,10 @@ func TestHealObjectCorruptedPools(t *testing.T) { · 13 unmodified lines
734 t.Errorf("Expected xl.meta file to be present but stat failed - %v", err)743 t.Errorf("Expected xl.meta file to be present but stat failed - %v", err)
735 }744 }
736 745
737 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), false)746 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), DeleteOptions{
747 Recursive: false,
748 Force: false,
749 })
738 if err != nil {750 if err != nil {
739 t.Errorf("Failure during deleting part.1 - %v", err)751 t.Errorf("Failure during deleting part.1 - %v", err)
740 }752 }
@@ -761,7 +773,10 @@ func TestHealObjectCorruptedPools(t *testing.T) { · 20 unmodified lines
761 t.Fatalf("FileInfo not equal after healing: %v != %v", fi, nfi)773 t.Fatalf("FileInfo not equal after healing: %v != %v", fi, nfi)
762 }774 }
763 775
764 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), false)776 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), DeleteOptions{
777 Recursive: false,
778 Force: false,
779 })
765 if err != nil {780 if err != nil {
766 t.Errorf("Failure during deleting part.1 - %v", err)781 t.Errorf("Failure during deleting part.1 - %v", err)
767 }782 }
@@ -792,7 +807,10 @@ func TestHealObjectCorruptedPools(t *testing.T) { · 24 unmodified lines
792 // Test 4: checks if HealObject returns an error when xl.meta is not found807 // Test 4: checks if HealObject returns an error when xl.meta is not found
793 // in more than read quorum number of disks, to create a corrupted situation.808 // in more than read quorum number of disks, to create a corrupted situation.
794 for i := 0; i <= nfi.Erasure.DataBlocks; i++ {809 for i := 0; i <= nfi.Erasure.DataBlocks; i++ {
795 erasureDisks[i].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), false)810 erasureDisks[i].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), DeleteOptions{
811 Recursive: false,
812 Force: false,
813 })
796 }814 }
797 815
798 // Try healing now, expect to receive errFileNotFound.816 // Try healing now, expect to receive errFileNotFound.
@@ -884,7 +902,10 @@ func TestHealObjectCorruptedXLMeta(t *testing.T) { · 85 unmodified lines
884 t.Fatalf("Failed to getLatestFileInfo - %v", err)902 t.Fatalf("Failed to getLatestFileInfo - %v", err)
885 }903 }
886 904
887 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), false)905 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), DeleteOptions{
906 Recursive: false,
907 Force: false,
908 })
888 if err != nil {909 if err != nil {
889 t.Fatalf("Failed to delete a file - %v", err)910 t.Fatalf("Failed to delete a file - %v", err)
890 }911 }
@@ -936,7 +957,10 @@ func TestHealObjectCorruptedXLMeta(t *testing.T) { · 45 unmodified lines
936 // Test 3: checks if HealObject returns an error when xl.meta is not found957 // Test 3: checks if HealObject returns an error when xl.meta is not found
937 // in more than read quorum number of disks, to create a corrupted situation.958 // in more than read quorum number of disks, to create a corrupted situation.
938 for i := 0; i <= nfi2.Erasure.DataBlocks; i++ {959 for i := 0; i <= nfi2.Erasure.DataBlocks; i++ {
939 erasureDisks[i].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), false)960 erasureDisks[i].Delete(context.Background(), bucket, pathJoin(object, xlStorageFormatFile), DeleteOptions{
961 Recursive: false,
962 Force: false,
963 })
940 }964 }
941 965
942 // Try healing now, expect to receive errFileNotFound.966 // Try healing now, expect to receive errFileNotFound.
@@ -1033,7 +1057,10 @@ func TestHealObjectCorruptedParts(t *testing.T) { · 90 unmodified lines
1033 }1057 }
1034 1058
1035 // Test 1, remove part.11059 // Test 1, remove part.1
1036 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), false)1060 err = firstDisk.Delete(context.Background(), bucket, pathJoin(object, fi.DataDir, "part.1"), DeleteOptions{
1061 Recursive: false,
1062 Force: false,
1063 })
1037 if err != nil {1064 if err != nil {
1038 t.Fatalf("Failed to delete a file - %v", err)1065 t.Fatalf("Failed to delete a file - %v", err)
1039 }1066 }
@@ -1078,7 +1105,10 @@ func TestHealObjectCorruptedParts(t *testing.T) { · 38 unmodified lines
1078 t.Fatalf("Failed to write a file - %v", err)1105 t.Fatalf("Failed to write a file - %v", err)
1079 }1106 }
1080 1107
1081 err = secondDisk.Delete(context.Background(), bucket, object, true)1108 err = secondDisk.Delete(context.Background(), bucket, object, DeleteOptions{
1109 Recursive: true,
1110 Force: false,
1111 })
1082 if err != nil {1112 if err != nil {
1083 t.Fatalf("Failed to delete a file - %v", err)1113 t.Fatalf("Failed to delete a file - %v", err)
1084 }1114 }
@@ -1166,7 +1196,10 @@ func TestHealObjectErasure(t *testing.T) { · 81 unmodified lines
1166 }1196 }
1167 1197
1168 // Delete the whole object folder1198 // Delete the whole object folder
1169 err = firstDisk.Delete(context.Background(), bucket, object, true)1199 err = firstDisk.Delete(context.Background(), bucket, object, DeleteOptions{
1200 Recursive: true,
1201 Force: false,
1202 })
1170 if err != nil {1203 if err != nil {
1171 t.Fatalf("Failed to delete a file - %v", err)1204 t.Fatalf("Failed to delete a file - %v", err)
1172 }1205 }
cmd/erasure-multipart.go+8−2
@@ -91,7 +91,10 @@ func (er erasureObjects) removeObjectPart(bucket, object, uploadID, dataDir stri · 90 unmodified lines
91 // Ignoring failure to remove parts that weren't present in CompleteMultipartUpload91 // Ignoring failure to remove parts that weren't present in CompleteMultipartUpload
92 // requests. xl.meta is the authoritative source of truth on which parts constitute92 // requests. xl.meta is the authoritative source of truth on which parts constitute
93 // the object. The presence of parts that don't belong in the object doesn't affect correctness.93 // the object. The presence of parts that don't belong in the object doesn't affect correctness.
94 _ = storageDisks[index].Delete(context.TODO(), minioMetaMultipartBucket, curpartPath, false)94 _ = storageDisks[index].Delete(context.TODO(), minioMetaMultipartBucket, curpartPath, DeleteOptions{
95 Recursive: false,
96 Force: false,
97 })
95 return nil98 return nil
96 }, index)99 }, index)
97 }100 }
@@ -138,7 +141,10 @@ func (er erasureObjects) deleteAll(ctx context.Context, bucket, prefix string) { · 40 unmodified lines
138 wg.Add(1)141 wg.Add(1)
139 go func(disk StorageAPI) {142 go func(disk StorageAPI) {
140 defer wg.Done()143 defer wg.Done()
141 disk.Delete(ctx, bucket, prefix, true)144 disk.Delete(ctx, bucket, prefix, DeleteOptions{
145 Recursive: true,
146 Force: false,
147 })
142 }(disk)148 }(disk)
143 }149 }
144 wg.Wait()150 wg.Wait()
cmd/erasure-object.go+8−2
@@ -1367,8 +1367,14 @@ func (er erasureObjects) deletePrefix(ctx context.Context, bucket, prefix string · 1366 unmodified lines
1367 // Deletes1367 // Deletes
1368 // - The prefix and its children1368 // - The prefix and its children
1369 // - The prefix__XLDIR__1369 // - The prefix__XLDIR__
1370 defer disks[index].Delete(ctx, bucket, dirPrefix, true)1370 defer disks[index].Delete(ctx, bucket, dirPrefix, DeleteOptions{
1371 return disks[index].Delete(ctx, bucket, prefix, true)1371 Recursive: true,
1372 Force: true,
1373 })
1374 return disks[index].Delete(ctx, bucket, prefix, DeleteOptions{
1375 Recursive: true,
1376 Force: true,
1377 })
1372 }, index)1378 }, index)
1373 }1379 }
1374 for _, err := range g.Wait() {1380 for _, err := range g.Wait() {
cmd/erasure-object_test.go+8−2
@@ -528,7 +528,10 @@ func TestGetObjectNoQuorum(t *testing.T) { · 527 unmodified lines
528 files, _ := disk.ListDir(ctx, bucket, object, -1)528 files, _ := disk.ListDir(ctx, bucket, object, -1)
529 for _, file := range files {529 for _, file := range files {
530 if file != "xl.meta" {530 if file != "xl.meta" {
531 disk.Delete(ctx, bucket, pathJoin(object, file), true)531 disk.Delete(ctx, bucket, pathJoin(object, file), DeleteOptions{
532 Recursive: true,
533 Force: false,
534 })
532 }535 }
533 }536 }
534 }537 }
@@ -629,7 +632,10 @@ func TestHeadObjectNoQuorum(t *testing.T) { · 94 unmodified lines
629 files, _ := disk.ListDir(ctx, bucket, object, -1)632 files, _ := disk.ListDir(ctx, bucket, object, -1)
630 for _, file := range files {633 for _, file := range files {
631 if file != "xl.meta" {634 if file != "xl.meta" {
632 disk.Delete(ctx, bucket, pathJoin(object, file), true)635 disk.Delete(ctx, bucket, pathJoin(object, file), DeleteOptions{
636 Recursive: true,
637 Force: false,
638 })
633 }639 }
634 }640 }
635 }641 }
cmd/erasure-single-drive.go+16−4
@@ -1321,8 +1321,14 @@ func (es *erasureSingle) DeleteObjects(ctx context.Context, bucket string, objec · 1320 unmodified lines
1321 1321
1322func (es *erasureSingle) deletePrefix(ctx context.Context, bucket, prefix string) error {1322func (es *erasureSingle) deletePrefix(ctx context.Context, bucket, prefix string) error {
1323 dirPrefix := encodeDirObject(prefix)1323 dirPrefix := encodeDirObject(prefix)
1324 defer es.disk.Delete(ctx, bucket, dirPrefix, true)1324 defer es.disk.Delete(ctx, bucket, dirPrefix, DeleteOptions{
1325 return es.disk.Delete(ctx, bucket, prefix, true)1325 Recursive: true,
1326 Force: true,
1327 })
1328 return es.disk.Delete(ctx, bucket, prefix, DeleteOptions{
1329 Recursive: true,
1330 Force: true,
1331 })
1326}1332}
1327 1333
1328// DeleteObject - deletes an object, this call doesn't necessary reply1334// DeleteObject - deletes an object, this call doesn't necessary reply
@@ -1916,7 +1922,10 @@ func (es *erasureSingle) removeObjectPart(bucket, object, uploadID, dataDir stri · 587 unmodified lines
1916 // Ignoring failure to remove parts that weren't present in CompleteMultipartUpload1922 // Ignoring failure to remove parts that weren't present in CompleteMultipartUpload
1917 // requests. xl.meta is the authoritative source of truth on which parts constitute1923 // requests. xl.meta is the authoritative source of truth on which parts constitute
1918 // the object. The presence of parts that don't belong in the object doesn't affect correctness.1924 // the object. The presence of parts that don't belong in the object doesn't affect correctness.
1919 _ = storageDisks[index].Delete(context.TODO(), minioMetaMultipartBucket, curpartPath, false)1925 _ = storageDisks[index].Delete(context.TODO(), minioMetaMultipartBucket, curpartPath, DeleteOptions{
1926 Recursive: false,
1927 Force: false,
1928 })
1920 return nil1929 return nil
1921 }, index)1930 }, index)
1922 }1931 }
@@ -1954,7 +1963,10 @@ func (es *erasureSingle) cleanupStaleUploadsOnDisk(ctx context.Context, disk Sto · 31 unmodified lines
1954 }1963 }
1955 wait := es.deletedCleanupSleeper.Timer(ctx)1964 wait := es.deletedCleanupSleeper.Timer(ctx)
1956 if now.Sub(vi.Created) > expiry {1965 if now.Sub(vi.Created) > expiry {
1957 disk.Delete(ctx, minioMetaTmpBucket, tmpDir, true)1966 disk.Delete(ctx, minioMetaTmpBucket, tmpDir, DeleteOptions{
1967 Recursive: true,
1968 Force: false,
1969 })
1958 }1970 }
1959 wait()1971 wait()
1960 return nil1972 return nil
cmd/format-erasure.go+4−1
@@ -367,7 +367,10 @@ func saveFormatErasure(disk StorageAPI, format *formatErasureV3, heal bool) erro · 366 unmodified lines
367 tmpFormat := mustGetUUID()367 tmpFormat := mustGetUUID()
368 368
369 // Purge any existing temporary file, okay to ignore errors here.369 // Purge any existing temporary file, okay to ignore errors here.
370 defer disk.Delete(context.TODO(), minioMetaBucket, tmpFormat, false)370 defer disk.Delete(context.TODO(), minioMetaBucket, tmpFormat, DeleteOptions{
371 Recursive: false,
372 Force: false,
373 })
371 374
372 // write to unique file.375 // write to unique file.
373 if err = disk.WriteAll(context.TODO(), minioMetaBucket, tmpFormat, formatBytes); err != nil {376 if err = disk.WriteAll(context.TODO(), minioMetaBucket, tmpFormat, formatBytes); err != nil {
cmd/naughty-disk_test.go+2−2
@@ -221,11 +221,11 @@ func (d *naughtyDisk) CheckParts(ctx context.Context, volume string, path string · 220 unmodified lines
221 return d.disk.CheckParts(ctx, volume, path, fi)221 return d.disk.CheckParts(ctx, volume, path, fi)
222}222}
223 223
224func (d *naughtyDisk) Delete(ctx context.Context, volume string, path string, recursive bool) (err error) {224func (d *naughtyDisk) Delete(ctx context.Context, volume string, path string, deleteOpts DeleteOptions) (err error) {
225 if err := d.calcError(); err != nil {225 if err := d.calcError(); err != nil {
226 return err226 return err
227 }227 }
228 return d.disk.Delete(ctx, volume, path, recursive)228 return d.disk.Delete(ctx, volume, path, deleteOpts)
229}229}
230 230
231func (d *naughtyDisk) DeleteVersions(ctx context.Context, volume string, versions []FileInfoVersions) []error {231func (d *naughtyDisk) DeleteVersions(ctx context.Context, volume string, versions []FileInfoVersions) []error {
cmd/storage-datatypes.go+7−0
@@ -21,6 +21,13 @@ import ( · 20 unmodified lines
21 "time"21 "time"
22)22)
23 23
24// DeleteOptions represents the disk level delete options available for the APIs
25//msgp:ignore DeleteOptions
26type DeleteOptions struct {
27 Recursive bool
28 Force bool
29}
30
24//go:generate msgp -file=$GOFILE31//go:generate msgp -file=$GOFILE
25 32
26// DiskInfo is an extended type which returns current33// DiskInfo is an extended type which returns current
cmd/storage-interface.go+2−2
@@ -95,7 +95,7 @@ type StorageAPI interface { · 94 unmodified lines
95 ReadFileStream(ctx context.Context, volume, path string, offset, length int64) (io.ReadCloser, error)95 ReadFileStream(ctx context.Context, volume, path string, offset, length int64) (io.ReadCloser, error)
96 RenameFile(ctx context.Context, srcVolume, srcPath, dstVolume, dstPath string) error96 RenameFile(ctx context.Context, srcVolume, srcPath, dstVolume, dstPath string) error
97 CheckParts(ctx context.Context, volume string, path string, fi FileInfo) error97 CheckParts(ctx context.Context, volume string, path string, fi FileInfo) error
98 Delete(ctx context.Context, volume string, path string, recursive bool) (err error)98 Delete(ctx context.Context, volume string, path string, deleteOpts DeleteOptions) (err error)
99 VerifyFile(ctx context.Context, volume, path string, fi FileInfo) error99 VerifyFile(ctx context.Context, volume, path string, fi FileInfo) error
100 StatInfoFile(ctx context.Context, volume, path string, glob bool) (stat []StatInfo, err error)100 StatInfoFile(ctx context.Context, volume, path string, glob bool) (stat []StatInfo, err error)
101 101
@@ -223,7 +223,7 @@ func (p *unrecognizedDisk) CheckParts(ctx context.Context, volume string, path s · 121 unmodified lines
223 return errDiskNotFound223 return errDiskNotFound
224}224}
225 225
226func (p *unrecognizedDisk) Delete(ctx context.Context, volume string, path string, recursive bool) (err error) {226func (p *unrecognizedDisk) Delete(ctx context.Context, volume string, path string, deleteOpts DeleteOptions) (err error) {
227 return errDiskNotFound227 return errDiskNotFound
228}228}
229 229
cmd/storage-rest-client.go+3−2
@@ -581,11 +581,12 @@ func (client *storageRESTClient) ListDir(ctx context.Context, volume, dirPath st · 580 unmodified lines
581}581}
582 582
583// DeleteFile - deletes a file.583// DeleteFile - deletes a file.
584func (client *storageRESTClient) Delete(ctx context.Context, volume string, path string, recursive bool) error {584func (client *storageRESTClient) Delete(ctx context.Context, volume string, path string, deleteOpts DeleteOptions) error {
585 values := make(url.Values)585 values := make(url.Values)
586 values.Set(storageRESTVolume, volume)586 values.Set(storageRESTVolume, volume)
587 values.Set(storageRESTFilePath, path)587 values.Set(storageRESTFilePath, path)
588 values.Set(storageRESTRecursive, strconv.FormatBool(recursive))588 values.Set(storageRESTRecursive, strconv.FormatBool(deleteOpts.Recursive))
589 values.Set(storageRESTForceDelete, strconv.FormatBool(deleteOpts.Force))
589 590
590 respBody, err := client.call(ctx, storageRESTMethodDeleteFile, values, nil, -1)591 respBody, err := client.call(ctx, storageRESTMethodDeleteFile, values, nil, -1)
591 defer xhttp.DrainBody(respBody)592 defer xhttp.DrainBody(respBody)
cmd/storage-rest-server.go+9−2
@@ -652,8 +652,15 @@ func (s *storageRESTServer) DeleteFileHandler(w http.ResponseWriter, r *http.Req · 651 unmodified lines
652 s.writeErrorResponse(w, err)652 s.writeErrorResponse(w, err)
653 return653 return
654 }654 }
655 655 force, err := strconv.ParseBool(r.Form.Get(storageRESTForceDelete))
656 err = s.storage.Delete(r.Context(), volume, filePath, recursive)656 if err != nil {
657 s.writeErrorResponse(w, err)
658 return
659 }
660 err = s.storage.Delete(r.Context(), volume, filePath, DeleteOptions{
661 Recursive: recursive,
662 Force: force,
663 })
657 if err != nil {664 if err != nil {
658 s.writeErrorResponse(w, err)665 s.writeErrorResponse(w, err)
659 }666 }
cmd/storage-rest_test.go+4−1
@@ -383,7 +383,10 @@ func testStorageAPIDeleteFile(t *testing.T, storage StorageAPI) { · 382 unmodified lines
383 }383 }
384 384
385 for i, testCase := range testCases {385 for i, testCase := range testCases {
386 err := storage.Delete(context.Background(), testCase.volumeName, testCase.objectName, false)386 err := storage.Delete(context.Background(), testCase.volumeName, testCase.objectName, DeleteOptions{
387 Recursive: false,
388 Force: false,
389 })
387 expectErr := (err != nil)390 expectErr := (err != nil)
388 391
389 if expectErr != testCase.expectErr {392 if expectErr != testCase.expectErr {
cmd/xl-storage-disk-id-check.go+6−3
@@ -382,14 +382,14 @@ func (p *xlStorageDiskIDCheck) CheckParts(ctx context.Context, volume string, pa · 381 unmodified lines
382 return p.storage.CheckParts(ctx, volume, path, fi)382 return p.storage.CheckParts(ctx, volume, path, fi)
383}383}
384 384
385func (p *xlStorageDiskIDCheck) Delete(ctx context.Context, volume string, path string, recursive bool) (err error) {385func (p *xlStorageDiskIDCheck) Delete(ctx context.Context, volume string, path string, deleteOpts DeleteOptions) (err error) {
386 ctx, done, err := p.TrackDiskHealth(ctx, storageMetricDelete, volume, path)386 ctx, done, err := p.TrackDiskHealth(ctx, storageMetricDelete, volume, path)
387 if err != nil {387 if err != nil {
388 return err388 return err
389 }389 }
390 defer done(&err)390 defer done(&err)
391 391
392 return p.storage.Delete(ctx, volume, path, recursive)392 return p.storage.Delete(ctx, volume, path, deleteOpts)
393}393}
394 394
395// DeleteVersions deletes slice of versions, it can be same object395// DeleteVersions deletes slice of versions, it can be same object
@@ -768,7 +768,10 @@ func (p *xlStorageDiskIDCheck) monitorDiskStatus() { · 372 unmodified lines
768 if err != nil || len(b) != 10001 {768 if err != nil || len(b) != 10001 {
769 continue769 continue
770 }770 }
771 err = p.storage.Delete(context.Background(), minioMetaTmpBucket, fn, false)771 err = p.storage.Delete(context.Background(), minioMetaTmpBucket, fn, DeleteOptions{
772 Recursive: false,
773 Force: false,
774 })
772 if err == nil {775 if err == nil {
773 logger.Info("Able to read+write, bringing disk %s online.", p.storage.String())776 logger.Info("Able to read+write, bringing disk %s online.", p.storage.String())
774 atomic.StoreInt32(&p.health.status, diskHealthOK)777 atomic.StoreInt32(&p.health.status, diskHealthOK)
cmd/xl-storage.go+50−33
@@ -818,7 +818,7 @@ func (s *xlStorage) DeleteVol(ctx context.Context, volume string, forceDelete bo · 817 unmodified lines
818 }818 }
819 819
820 if forceDelete {820 if forceDelete {
821 err = s.moveToTrash(volumeDir, true)821 err = s.moveToTrash(volumeDir, true, true)
822 } else {822 } else {
823 err = Remove(volumeDir)823 err = Remove(volumeDir)
824 }824 }
@@ -903,7 +903,7 @@ func (s *xlStorage) deleteVersions(ctx context.Context, volume, path string, fis · 78 unmodified lines
903 if !isXL2V1Format(buf) {903 if !isXL2V1Format(buf) {
904 // Delete the meta file, if there are no more versions the904 // Delete the meta file, if there are no more versions the
905 // top level parent is automatically removed.905 // top level parent is automatically removed.
906 return s.deleteFile(volumeDir, pathJoin(volumeDir, path), true)906 return s.deleteFile(volumeDir, pathJoin(volumeDir, path), true, false)
907 }907 }
908 908
909 var xlMeta xlMetaV2909 var xlMeta xlMetaV2
@@ -939,7 +939,7 @@ func (s *xlStorage) deleteVersions(ctx context.Context, volume, path string, fis · 29 unmodified lines
939 if err = checkPathLength(filePath); err != nil {939 if err = checkPathLength(filePath); err != nil {
940 return err940 return err
941 }941 }
942 if err = s.moveToTrash(filePath, true); err != nil {942 if err = s.moveToTrash(filePath, true, false); err != nil {
943 if err != errFileNotFound {943 if err != errFileNotFound {
944 return err944 return err
945 }945 }
@@ -959,9 +959,9 @@ func (s *xlStorage) deleteVersions(ctx context.Context, volume, path string, fis · 13 unmodified lines
959 }959 }
960 960
961 // Move xl.meta to trash961 // Move xl.meta to trash
962 err = s.moveToTrash(pathJoin(volumeDir, path, xlStorageFormatFile), false)962 err = s.moveToTrash(pathJoin(volumeDir, path, xlStorageFormatFile), false, false)
963 if err == nil || err == errFileNotFound {963 if err == nil || err == errFileNotFound {
964 s.deleteFile(volumeDir, pathJoin(volumeDir, path), false)964 s.deleteFile(volumeDir, pathJoin(volumeDir, path), false, false)
965 }965 }
966 return err966 return err
967}967}
@@ -985,19 +985,36 @@ func (s *xlStorage) DeleteVersions(ctx context.Context, volume string, versions · 17 unmodified lines
985 return errs985 return errs
986}986}
987 987
988func (s *xlStorage) moveToTrash(filePath string, recursive bool) error {988func (s *xlStorage) moveToTrash(filePath string, recursive, force bool) error {
989 pathUUID := mustGetUUID()989 pathUUID := mustGetUUID()
990 targetPath := pathutil.Join(s.diskPath, minioMetaTmpDeletedBucket, pathUUID)
991
992 var renameFn func(source, target string) error
990 if recursive {993 if recursive {
991 return renameAll(filePath, pathutil.Join(s.diskPath, minioMetaTmpDeletedBucket, pathUUID))994 renameFn = renameAll
995 } else {
996 renameFn = Rename
997 }
998
999 if err := renameFn(filePath, targetPath); err != nil {
1000 return err
992 }1001 }
993 return Rename(filePath, pathutil.Join(s.diskPath, minioMetaTmpDeletedBucket, pathUUID))1002 // immediately purge the target
1003 if force {
1004 removeAll(targetPath)
1005 }
1006
1007 return nil
994}1008}
995 1009
996// DeleteVersion - deletes FileInfo metadata for path at `xl.meta`. forceDelMarker1010// DeleteVersion - deletes FileInfo metadata for path at `xl.meta`. forceDelMarker
997// will force creating a new `xl.meta` to create a new delete marker1011// will force creating a new `xl.meta` to create a new delete marker
998func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi FileInfo, forceDelMarker bool) error {1012func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi FileInfo, forceDelMarker bool) error {
999 if HasSuffix(path, SlashSeparator) {1013 if HasSuffix(path, SlashSeparator) {
1000 return s.Delete(ctx, volume, path, false)1014 return s.Delete(ctx, volume, path, DeleteOptions{
1015 Recursive: false,
1016 Force: false,
1017 })
1001 }1018 }
1002 1019
1003 buf, err := s.ReadAll(ctx, volume, pathJoin(path, xlStorageFormatFile))1020 buf, err := s.ReadAll(ctx, volume, pathJoin(path, xlStorageFormatFile))
@@ -1035,7 +1052,7 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F · 31 unmodified lines
1035 if !isXL2V1Format(buf) {1052 if !isXL2V1Format(buf) {
1036 // Delete the meta file, if there are no more versions the1053 // Delete the meta file, if there are no more versions the
1037 // top level parent is automatically removed.1054 // top level parent is automatically removed.
1038 return s.deleteFile(volumeDir, pathJoin(volumeDir, path), true)1055 return s.deleteFile(volumeDir, pathJoin(volumeDir, path), true, false)
1039 }1056 }
1040 1057
1041 var xlMeta xlMetaV21058 var xlMeta xlMetaV2
@@ -1065,7 +1082,7 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F · 23 unmodified lines
1065 if err = checkPathLength(filePath); err != nil {1082 if err = checkPathLength(filePath); err != nil {
1066 return err1083 return err
1067 }1084 }
1068 if err = s.moveToTrash(filePath, true); err != nil {1085 if err = s.moveToTrash(filePath, true, false); err != nil {
1069 if err != errFileNotFound {1086 if err != errFileNotFound {
1070 return err1087 return err
1071 }1088 }
@@ -1088,9 +1105,9 @@ func (s *xlStorage) DeleteVersion(ctx context.Context, volume, path string, fi F · 16 unmodified lines
1088 return err1105 return err
1089 }1106 }
1090 1107
1091 err = s.moveToTrash(filePath, false)1108 err = s.moveToTrash(filePath, false, false)
1092 if err == nil || err == errFileNotFound {1109 if err == nil || err == errFileNotFound {
1093 s.deleteFile(volumeDir, pathJoin(volumeDir, path), false)1110 s.deleteFile(volumeDir, pathJoin(volumeDir, path), false, false)
1094 }1111 }
1095 return err1112 return err
1096}1113}
@@ -2014,7 +2031,7 @@ func (s *xlStorage) CheckParts(ctx context.Context, volume string, path string, · 917 unmodified lines
2014// move up the tree, deleting empty parent directories until it finds one2031// move up the tree, deleting empty parent directories until it finds one
2015// with files in it. Returns nil for a non-empty directory even when2032// with files in it. Returns nil for a non-empty directory even when
2016// recursive is set to false.2033// recursive is set to false.
2017func (s *xlStorage) deleteFile(basePath, deletePath string, recursive bool) error {2034func (s *xlStorage) deleteFile(basePath, deletePath string, recursive, force bool) error {
2018 if basePath == "" || deletePath == "" {2035 if basePath == "" || deletePath == "" {
2019 return nil2036 return nil
2020 }2037 }
@@ -2027,7 +2044,7 @@ func (s *xlStorage) deleteFile(basePath, deletePath string, recursive bool) erro · 6 unmodified lines
2027 2044
2028 var err error2045 var err error
2029 if recursive {2046 if recursive {
2030 err = s.moveToTrash(deletePath, true)2047 err = s.moveToTrash(deletePath, true, force)
2031 } else {2048 } else {
2032 err = Remove(deletePath)2049 err = Remove(deletePath)
2033 }2050 }
@@ -2060,13 +2077,13 @@ func (s *xlStorage) deleteFile(basePath, deletePath string, recursive bool) erro · 26 unmodified lines
2060 2077
2061 // Delete parent directory obviously not recursively. Errors for2078 // Delete parent directory obviously not recursively. Errors for
2062 // parent directories shouldn't trickle down.2079 // parent directories shouldn't trickle down.
2063 s.deleteFile(basePath, deletePath, false)2080 s.deleteFile(basePath, deletePath, false, false)
2064 2081
2065 return nil2082 return nil
2066}2083}
2067 2084
2068// DeleteFile - delete a file at path.2085// DeleteFile - delete a file at path.
2069func (s *xlStorage) Delete(ctx context.Context, volume string, path string, recursive bool) (err error) {2086func (s *xlStorage) Delete(ctx context.Context, volume string, path string, deleteOpts DeleteOptions) (err error) {
2070 volumeDir, err := s.getVolDir(volume)2087 volumeDir, err := s.getVolDir(volume)
2071 if err != nil {2088 if err != nil {
2072 return err2089 return err
@@ -2092,7 +2109,7 @@ func (s *xlStorage) Delete(ctx context.Context, volume string, path string, recu · 19 unmodified lines
2092 }2109 }
2093 2110
2094 // Delete file and delete parent directory as well if it's empty.2111 // Delete file and delete parent directory as well if it's empty.
2095 return s.deleteFile(volumeDir, filePath, recursive)2112 return s.deleteFile(volumeDir, filePath, deleteOpts.Recursive, deleteOpts.Force)
2096}2113}
2097 2114
2098func skipAccessChecks(volume string) (ok bool) {2115func skipAccessChecks(volume string) (ok bool) {
@@ -2270,7 +2287,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 171 unmodified lines
2270 // legacy data dir means its old content, honor system umask.2287 // legacy data dir means its old content, honor system umask.
2271 if err = mkdirAll(legacyDataPath, 0o777); err != nil {2288 if err = mkdirAll(legacyDataPath, 0o777); err != nil {
2272 // any failed mkdir-calls delete them.2289 // any failed mkdir-calls delete them.
2273 s.deleteFile(dstVolumeDir, legacyDataPath, true)2290 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2274 return osErrToFileErr(err)2291 return osErrToFileErr(err)
2275 }2292 }
2276 2293
@@ -2282,7 +2299,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 5 unmodified lines
2282 2299
2283 if err = Rename(pathJoin(currentDataPath, entry), pathJoin(legacyDataPath, entry)); err != nil {2300 if err = Rename(pathJoin(currentDataPath, entry), pathJoin(legacyDataPath, entry)); err != nil {
2284 // Any failed rename calls un-roll previous transaction.2301 // Any failed rename calls un-roll previous transaction.
2285 s.deleteFile(dstVolumeDir, legacyDataPath, true)2302 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2286 2303
2287 return osErrToFileErr(err)2304 return osErrToFileErr(err)
2288 }2305 }
@@ -2327,7 +2344,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 38 unmodified lines
2327 if err = xlMeta.AddVersion(fi); err != nil {2344 if err = xlMeta.AddVersion(fi); err != nil {
2328 if legacyPreserved {2345 if legacyPreserved {
2329 // Any failed rename calls un-roll previous transaction.2346 // Any failed rename calls un-roll previous transaction.
2330 s.deleteFile(dstVolumeDir, legacyDataPath, true)2347 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2331 }2348 }
2332 return err2349 return err
2333 }2350 }
@@ -2338,7 +2355,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 4 unmodified lines
2338 logger.LogIf(ctx, err)2355 logger.LogIf(ctx, err)
2339 if legacyPreserved {2356 if legacyPreserved {
2340 // Any failed rename calls un-roll previous transaction.2357 // Any failed rename calls un-roll previous transaction.
2341 s.deleteFile(dstVolumeDir, legacyDataPath, true)2358 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2342 }2359 }
2343 return errFileCorrupt2360 return errFileCorrupt
2344 }2361 }
@@ -2347,7 +2364,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 2 unmodified lines
2347 if err = s.WriteAll(ctx, srcVolume, pathJoin(srcPath, xlStorageFormatFile), dstBuf); err != nil {2364 if err = s.WriteAll(ctx, srcVolume, pathJoin(srcPath, xlStorageFormatFile), dstBuf); err != nil {
2348 if legacyPreserved {2365 if legacyPreserved {
2349 // Any failed rename calls un-roll previous transaction.2366 // Any failed rename calls un-roll previous transaction.
2350 s.deleteFile(dstVolumeDir, legacyDataPath, true)2367 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2351 }2368 }
2352 return osErrToFileErr(err)2369 return osErrToFileErr(err)
2353 }2370 }
@@ -2355,19 +2372,19 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 1 unmodified line
2355 2372
2356 // renameAll only for objects that have xl.meta not saved inline.2373 // renameAll only for objects that have xl.meta not saved inline.
2357 if len(fi.Data) == 0 && fi.Size > 0 {2374 if len(fi.Data) == 0 && fi.Size > 0 {
2358 s.moveToTrash(dstDataPath, true)2375 s.moveToTrash(dstDataPath, true, false)
2359 if healing {2376 if healing {
2360 // If we are healing we should purge any legacyDataPath content,2377 // If we are healing we should purge any legacyDataPath content,
2361 // that was previously preserved during PutObject() call2378 // that was previously preserved during PutObject() call
2362 // on a versioned bucket.2379 // on a versioned bucket.
2363 s.moveToTrash(legacyDataPath, true)2380 s.moveToTrash(legacyDataPath, true, false)
2364 }2381 }
2365 if err = renameAll(srcDataPath, dstDataPath); err != nil {2382 if err = renameAll(srcDataPath, dstDataPath); err != nil {
2366 if legacyPreserved {2383 if legacyPreserved {
2367 // Any failed rename calls un-roll previous transaction.2384 // Any failed rename calls un-roll previous transaction.
2368 s.deleteFile(dstVolumeDir, legacyDataPath, true)2385 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2369 }2386 }
2370 s.deleteFile(dstVolumeDir, dstDataPath, false)2387 s.deleteFile(dstVolumeDir, dstDataPath, false, false)
2371 return osErrToFileErr(err)2388 return osErrToFileErr(err)
2372 }2389 }
2373 }2390 }
@@ -2376,9 +2393,9 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 2 unmodified lines
2376 if err = renameAll(srcFilePath, dstFilePath); err != nil {2393 if err = renameAll(srcFilePath, dstFilePath); err != nil {
2377 if legacyPreserved {2394 if legacyPreserved {
2378 // Any failed rename calls un-roll previous transaction.2395 // Any failed rename calls un-roll previous transaction.
2379 s.deleteFile(dstVolumeDir, legacyDataPath, true)2396 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2380 }2397 }
2381 s.deleteFile(dstVolumeDir, dstFilePath, false)2398 s.deleteFile(dstVolumeDir, dstFilePath, false, false)
2382 return osErrToFileErr(err)2399 return osErrToFileErr(err)
2383 }2400 }
2384 2401
@@ -2386,16 +2403,16 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f · 1 unmodified line
2386 // movement, this is to ensure that previous data references can co-exist for2403 // movement, this is to ensure that previous data references can co-exist for
2387 // any recoverability.2404 // any recoverability.
2388 if oldDstDataPath != "" {2405 if oldDstDataPath != "" {
2389 s.moveToTrash(oldDstDataPath, true)2406 s.moveToTrash(oldDstDataPath, true, false)
2390 }2407 }
2391 } else {2408 } else {
2392 // Write meta-file directly, no data2409 // Write meta-file directly, no data
2393 if err = s.WriteAll(ctx, dstVolume, pathJoin(dstPath, xlStorageFormatFile), dstBuf); err != nil {2410 if err = s.WriteAll(ctx, dstVolume, pathJoin(dstPath, xlStorageFormatFile), dstBuf); err != nil {
2394 if legacyPreserved {2411 if legacyPreserved {
2395 // Any failed rename calls un-roll previous transaction.2412 // Any failed rename calls un-roll previous transaction.
2396 s.deleteFile(dstVolumeDir, legacyDataPath, true)2413 s.deleteFile(dstVolumeDir, legacyDataPath, true, false)
2397 }2414 }
2398 s.deleteFile(dstVolumeDir, dstFilePath, false)2415 s.deleteFile(dstVolumeDir, dstFilePath, false, false)
2399 return err2416 return err
2400 }2417 }
2401 }2418 }
@@ -2484,7 +2501,7 @@ func (s *xlStorage) RenameFile(ctx context.Context, srcVolume, srcPath, dstVolum · 82 unmodified lines
2484 2501
2485 // Remove parent dir of the source file if empty2502 // Remove parent dir of the source file if empty
2486 parentDir := pathutil.Dir(srcFilePath)2503 parentDir := pathutil.Dir(srcFilePath)
2487 s.deleteFile(srcVolumeDir, parentDir, false)2504 s.deleteFile(srcVolumeDir, parentDir, false, false)
2488 2505
2489 return nil2506 return nil
2490}2507}
cmd/xl-storage_test.go+24−6
@@ -933,14 +933,20 @@ func TestXLStorageListDir(t *testing.T) { · 932 unmodified lines
933 t.Fatalf("Unable to initialize xlStorage, %s", err)933 t.Fatalf("Unable to initialize xlStorage, %s", err)
934 }934 }
935 935
936 if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", false); err != errVolumeAccessDenied {936 if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", DeleteOptions{
937 Recursive: false,
938 Force: false,
939 }); err != errVolumeAccessDenied {
937 t.Errorf("expected: %s, got: %s", errVolumeAccessDenied, err)940 t.Errorf("expected: %s, got: %s", errVolumeAccessDenied, err)
938 }941 }
939 }942 }
940 943
941 // TestXLStorage for delete on an removed disk.944 // TestXLStorage for delete on an removed disk.
942 // should fail with disk not found.945 // should fail with disk not found.
943 err = xlStorageDeletedStorage.Delete(context.Background(), "del-vol", "my-file", false)946 err = xlStorageDeletedStorage.Delete(context.Background(), "del-vol", "my-file", DeleteOptions{
947 Recursive: false,
948 Force: false,
949 })
944 if err != errDiskNotFound {950 if err != errDiskNotFound {
945 t.Errorf("Expected: \"Disk not found\", got \"%s\"", err)951 t.Errorf("Expected: \"Disk not found\", got \"%s\"", err)
946 }952 }
@@ -1029,7 +1035,10 @@ func TestXLStorageDeleteFile(t *testing.T) { · 82 unmodified lines
1029 }1035 }
1030 1036
1031 for i, testCase := range testCases {1037 for i, testCase := range testCases {
1032 if err = xlStorage.Delete(context.Background(), testCase.srcVol, testCase.srcPath, false); err != testCase.expectedErr {1038 if err = xlStorage.Delete(context.Background(), testCase.srcVol, testCase.srcPath, DeleteOptions{
1039 Recursive: false,
1040 Force: false,
1041 }); err != testCase.expectedErr {
1033 t.Errorf("TestXLStorage case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err)1042 t.Errorf("TestXLStorage case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err)
1034 }1043 }
1035 }1044 }
@@ -1054,7 +1063,10 @@ func TestXLStorageDeleteFile(t *testing.T) { · 18 unmodified lines
1054 t.Fatalf("Unable to initialize xlStorage, %s", err)1063 t.Fatalf("Unable to initialize xlStorage, %s", err)
1055 }1064 }
1056 1065
1057 if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", false); err != errVolumeAccessDenied {1066 if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", DeleteOptions{
1067 Recursive: false,
1068 Force: false,
1069 }); err != errVolumeAccessDenied {
1058 t.Errorf("expected: %s, got: %s", errVolumeAccessDenied, err)1070 t.Errorf("expected: %s, got: %s", errVolumeAccessDenied, err)
1059 }1071 }
1060 }1072 }
@@ -1072,7 +1084,10 @@ func TestXLStorageDeleteFile(t *testing.T) { · 11 unmodified lines
1072 1084
1073 // TestXLStorage for delete on an removed disk.1085 // TestXLStorage for delete on an removed disk.
1074 // should fail with disk not found.1086 // should fail with disk not found.
1075 err = xlStorageDeletedStorage.Delete(context.Background(), "del-vol", "my-file", false)1087 err = xlStorageDeletedStorage.Delete(context.Background(), "del-vol", "my-file", DeleteOptions{
1088 Recursive: false,
1089 Force: false,
1090 })
1076 if err != errDiskNotFound {1091 if err != errDiskNotFound {
1077 t.Errorf("Expected: \"Disk not found\", got \"%s\"", err)1092 t.Errorf("Expected: \"Disk not found\", got \"%s\"", err)
1078 }1093 }
@@ -1907,7 +1922,10 @@ func TestXLStorageVerifyFile(t *testing.T) { · 828 unmodified lines
1907 t.Fatal("expected to fail bitrot check")1922 t.Fatal("expected to fail bitrot check")
1908 }1923 }
1909 1924
1910 if err := storage.Delete(context.Background(), volName, fileName, false); err != nil {1925 if err := storage.Delete(context.Background(), volName, fileName, DeleteOptions{
1926 Recursive: false,
1927 Force: false,
1928 }); err != nil {
1911 t.Fatal(err)1929 t.Fatal(err)
1912 }1930 }
1913 1931
cmd/xl-storage_windows_test.go+4−1
@@ -70,7 +70,10 @@ func TestUNCPaths(t *testing.T) { · 69 unmodified lines
70 } else if err == nil && !test.pass {70 } else if err == nil && !test.pass {
71 t.Error(err)71 t.Error(err)
72 }72 }
73 fs.Delete(context.Background(), "voldir", test.objName, false)73 fs.Delete(context.Background(), "voldir", test.objName, DeleteOptions{
74 Recursive: false,
75 Force: false,
76 })
74 })77 })
75 }78 }
76}79}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t