error out by default beyond 10000 versions per object (#17803)

```
You've exceeded the limit on the number of versions you can create on this object
```
This commit is contained in:
Harshavardhana 2023-08-04 10:40:21 -07:00 committed by GitHub
parent e0329cfdbb
commit cb089dcb52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 266 additions and 223 deletions

View File

@ -190,6 +190,7 @@ const (
ErrMaximumExpires ErrMaximumExpires
ErrSlowDownRead ErrSlowDownRead
ErrSlowDownWrite ErrSlowDownWrite
ErrMaxVersionsExceeded
ErrInvalidPrefixMarker ErrInvalidPrefixMarker
ErrBadRequest ErrBadRequest
ErrKeyTooLongError ErrKeyTooLongError
@ -857,6 +858,11 @@ var errorCodes = errorCodeMap{
Description: "Resource requested is unwritable, please reduce your request rate", Description: "Resource requested is unwritable, please reduce your request rate",
HTTPStatusCode: http.StatusServiceUnavailable, HTTPStatusCode: http.StatusServiceUnavailable,
}, },
ErrMaxVersionsExceeded: {
Code: "MaxVersionsExceeded",
Description: "You've exceeded the limit on the number of versions you can create on this object",
HTTPStatusCode: http.StatusBadRequest,
},
ErrInvalidPrefixMarker: { ErrInvalidPrefixMarker: {
Code: "InvalidPrefixMarker", Code: "InvalidPrefixMarker",
Description: "Invalid marker prefix combination", Description: "Invalid marker prefix combination",
@ -2110,6 +2116,8 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
apiErr = ErrSlowDownRead apiErr = ErrSlowDownRead
case errErasureWriteQuorum: case errErasureWriteQuorum:
apiErr = ErrSlowDownWrite apiErr = ErrSlowDownWrite
case errMaxVersionsExceeded:
apiErr = ErrMaxVersionsExceeded
// SSE errors // SSE errors
case errInvalidEncryptionParameters: case errInvalidEncryptionParameters:
apiErr = ErrInvalidEncryptionParameters apiErr = ErrInvalidEncryptionParameters

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 MinIO, Inc. // Copyright (c) 2015-2023 MinIO, Inc.
// //
// This file is part of MinIO Object Storage stack // This file is part of MinIO Object Storage stack
// //
@ -24,6 +24,9 @@ import (
"github.com/minio/minio/internal/logger" "github.com/minio/minio/internal/logger"
) )
// errMaxVersionsExceeded return error beyond 10000 (default) versions per object
var errMaxVersionsExceeded = StorageErr("maximum versions exceeded, please delete few versions to proceed")
// errUnexpected - unexpected error, requires manual intervention. // errUnexpected - unexpected error, requires manual intervention.
var errUnexpected = StorageErr("unexpected error, please report this issue at https://github.com/minio/minio/issues") var errUnexpected = StorageErr("unexpected error, please report this issue at https://github.com/minio/minio/issues")

View File

@ -26,6 +26,7 @@ import (
"fmt" "fmt"
"io" "io"
"sort" "sort"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -37,9 +38,31 @@ import (
"github.com/minio/minio/internal/bucket/replication" "github.com/minio/minio/internal/bucket/replication"
xhttp "github.com/minio/minio/internal/http" xhttp "github.com/minio/minio/internal/http"
"github.com/minio/minio/internal/logger" "github.com/minio/minio/internal/logger"
"github.com/minio/pkg/env"
"github.com/tinylib/msgp/msgp" "github.com/tinylib/msgp/msgp"
) )
// Reject creating new versions when a single object is cross maxObjectVersions
var maxObjectVersions = 10000
func init() {
v := env.Get("_MINIO_OBJECT_MAX_VERSIONS", "")
if v != "" {
maxv, err := strconv.Atoi(v)
if err != nil {
logger.Info("invalid _MINIO_OBJECT_MAX_VERSIONS value: %s, defaulting to '10000'", v)
maxObjectVersions = 10000
} else {
if maxv < 10 {
logger.Info("invalid _MINIO_OBJECT_MAX_VERSIONS value: %s, minimum allowed is '10' defaulting to '10000'", v)
maxObjectVersions = 10000
} else {
maxObjectVersions = maxv
}
}
}
}
var ( var (
// XL header specifies the format // XL header specifies the format
xlHeader = [4]byte{'X', 'L', '2', ' '} xlHeader = [4]byte{'X', 'L', '2', ' '}
@ -1070,6 +1093,12 @@ func (x *xlMetaV2) addVersion(ver xlMetaV2Version) error {
if err != nil { if err != nil {
return err return err
} }
// returns error if we have exceeded maxObjectVersions
if len(x.versions)+1 > maxObjectVersions {
return errMaxVersionsExceeded
}
// Add space at the end. // Add space at the end.
// Will have -1 modtime, so it will be inserted there. // Will have -1 modtime, so it will be inserted there.
x.versions = append(x.versions, xlMetaV2ShallowVersion{header: xlMetaV2VersionHeader{ModTime: -1}}) x.versions = append(x.versions, xlMetaV2ShallowVersion{header: xlMetaV2VersionHeader{ModTime: -1}})

View File

@ -2211,6 +2211,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath string, f
errFileVersionNotFound, errFileVersionNotFound,
errDiskNotFound, errDiskNotFound,
errUnformattedDisk, errUnformattedDisk,
errMaxVersionsExceeded,
} }
if err != nil && !IsErr(err, ignoredErrs...) && !contextCanceled(ctx) { if err != nil && !IsErr(err, ignoredErrs...) && !contextCanceled(ctx) {
// Only log these errors if context is not yet canceled. // Only log these errors if context is not yet canceled.

View File

@ -17,21 +17,22 @@ For optimal production setup MinIO recommends Linux kernel version 4.x and later
## Limits of S3 API ## Limits of S3 API
| Item | Specification | | Item | Specification |
|:--------------------------------------------------------------------------------|:------------------------------------------------| |:--------------------------------------------------------------------------------|:--------------------------------------------------------------------------------|
| Maximum number of buckets | unlimited (we recommend not beyond 500000 buckets) | | Maximum number of buckets | unlimited (we recommend not beyond 500000 buckets) |
| Maximum number of objects per bucket | no-limit | | Maximum number of objects per bucket | no-limit |
| Maximum object size | 50 TiB | | Maximum object size | 50 TiB |
| Minimum object size | 0 B | | Minimum object size | 0 B |
| Maximum object size per PUT operation | 5 TiB | | Maximum object size per PUT operation | 5 TiB |
| Maximum number of parts per upload | 10,000 | | Maximum number of parts per upload | 10,000 |
| Part size range | 5 MiB to 5 TiB. Last part can be 0 B to 5 TiB | | Part size range | 5 MiB to 5 TiB. Last part can be 0 B to 5 TiB |
| Maximum number of parts returned per list parts request | 10000 | | Maximum number of parts returned per list parts request | 10000 |
| Maximum number of objects returned per list objects request | 1000 | | Maximum number of objects returned per list objects request | 1000 |
| Maximum number of multipart uploads returned per list multipart uploads request | 1000 | | Maximum number of multipart uploads returned per list multipart uploads request | 1000 |
| Maximum length for bucket names | 63 | | Maximum length for bucket names | 63 |
| Maximum length for object names | 1024 | | Maximum length for object names | 1024 |
| Maximum length for '/' separated object name segment | 255 | | Maximum length for '/' separated object name segment | 255 |
| Maximum number of versions per object | 10000 (can be configured to higher values but we do not recommend beyond 10000) |
## List of Amazon S3 API's not supported on MinIO ## List of Amazon S3 API's not supported on MinIO