mirror of
https://github.com/versity/versitygw.git
synced 2026-05-01 17:55:42 +00:00
Merge pull request #2096 from versity/ben/enospc
feat: add new ErrNoSpaceLeftOnDevice API error for ENOSPC errors
This commit is contained in:
@@ -20,6 +20,9 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/versity/versitygw/s3err"
|
||||
)
|
||||
|
||||
// SideCar is a metadata storer that uses sidecar files to store metadata.
|
||||
@@ -71,12 +74,18 @@ func (s SideCar) StoreAttribute(_ *os.File, bucket, object, attribute string, va
|
||||
}
|
||||
err := os.MkdirAll(metadir, 0777)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return fmt.Errorf("failed to create metadata directory: %v", err)
|
||||
}
|
||||
|
||||
attr := filepath.Join(metadir, attribute)
|
||||
tempfile, err := os.CreateTemp(metadir, attribute)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return fmt.Errorf("failed to create temporary file: %v", err)
|
||||
}
|
||||
defer os.Remove(tempfile.Name())
|
||||
@@ -84,6 +93,9 @@ func (s SideCar) StoreAttribute(_ *os.File, bucket, object, attribute string, va
|
||||
_, err = tempfile.Write(value)
|
||||
if err != nil {
|
||||
tempfile.Close()
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return fmt.Errorf("failed to write attribute: %v", err)
|
||||
}
|
||||
|
||||
@@ -176,6 +188,9 @@ func (s SideCar) RenameObject(bucket, oldObject, newObject string) error {
|
||||
newPath := filepath.Join(s.dir, bucket, newObject)
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(newPath), 0777); err != nil {
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return fmt.Errorf("create parent for renamed metadata: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ func (x XattrMeta) StoreAttribute(f *os.File, bucket, object, attribute string,
|
||||
if errors.Is(err, syscall.EROFS) {
|
||||
return s3err.GetAPIError(s3err.ErrMethodNotAllowed)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -64,6 +67,9 @@ func (x XattrMeta) StoreAttribute(f *os.File, bucket, object, attribute string,
|
||||
if errors.Is(err, syscall.EROFS) {
|
||||
return s3err.GetAPIError(s3err.ErrMethodNotAllowed)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -1989,6 +1989,9 @@ func (p *Posix) CompleteMultipartUploadWithCopy(ctx context.Context, input *s3.C
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return res, "", s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return res, "", s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return res, "", fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
@@ -2044,6 +2047,9 @@ func (p *Posix) CompleteMultipartUploadWithCopy(ctx context.Context, input *s3.C
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return res, "", s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return res, "", s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return res, "", fmt.Errorf("copy part %v: %v", part.PartNumber, err)
|
||||
}
|
||||
}
|
||||
@@ -2877,6 +2883,9 @@ func (p *Posix) UploadPartWithPostFunc(ctx context.Context, input *s3.UploadPart
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return nil, fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
@@ -2989,6 +2998,9 @@ func (p *Posix) UploadPartWithPostFunc(ctx context.Context, input *s3.UploadPart
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return nil, s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
// Return the error itself, if it's an 's3err.APIError'
|
||||
if _, ok := err.(s3err.APIError); ok {
|
||||
return nil, err
|
||||
@@ -3253,6 +3265,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput)
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return s3response.CopyPartResult{}, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3response.CopyPartResult{}, s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return s3response.CopyPartResult{}, fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
@@ -3298,6 +3313,9 @@ func (p *Posix) UploadPartCopy(ctx context.Context, upi *s3.UploadPartCopyInput)
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return s3response.CopyPartResult{}, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3response.CopyPartResult{}, s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return s3response.CopyPartResult{}, fmt.Errorf("copy part data: %w", err)
|
||||
}
|
||||
|
||||
@@ -3494,6 +3512,9 @@ func (p *Posix) PutObjectWithPostFunc(ctx context.Context, po s3response.PutObje
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return s3response.PutObjectOutput{}, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3response.PutObjectOutput{}, s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return s3response.PutObjectOutput{}, err
|
||||
}
|
||||
|
||||
@@ -3622,6 +3643,9 @@ func (p *Posix) PutObjectWithPostFunc(ctx context.Context, po s3response.PutObje
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return s3response.PutObjectOutput{}, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3response.PutObjectOutput{}, s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
return s3response.PutObjectOutput{}, fmt.Errorf("open temp file: %w", err)
|
||||
}
|
||||
defer f.cleanup()
|
||||
@@ -3646,6 +3670,9 @@ func (p *Posix) PutObjectWithPostFunc(ctx context.Context, po s3response.PutObje
|
||||
if errors.Is(err, syscall.EDQUOT) {
|
||||
return s3response.PutObjectOutput{}, s3err.GetAPIError(s3err.ErrQuotaExceeded)
|
||||
}
|
||||
if errors.Is(err, syscall.ENOSPC) {
|
||||
return s3response.PutObjectOutput{}, s3err.GetAPIError(s3err.ErrNoSpaceLeftOnDevice)
|
||||
}
|
||||
// Return the error itself, if it's an 's3err.APIError'
|
||||
if _, ok := err.(s3err.APIError); ok {
|
||||
return s3response.PutObjectOutput{}, err
|
||||
|
||||
@@ -199,6 +199,7 @@ const (
|
||||
ErrQuotaExceeded
|
||||
ErrVersioningNotConfigured
|
||||
ErrACLsDisabled
|
||||
ErrNoSpaceLeftOnDevice
|
||||
|
||||
// Admin api errors
|
||||
ErrAdminAccessDenied
|
||||
@@ -904,6 +905,11 @@ var errorCodeResponse = map[ErrorCode]APIError{
|
||||
Description: "Access control lists are disabled at the gateway level",
|
||||
HTTPStatusCode: http.StatusBadRequest,
|
||||
},
|
||||
ErrNoSpaceLeftOnDevice: {
|
||||
Code: "InsufficientStorage",
|
||||
Description: "No space left on device.",
|
||||
HTTPStatusCode: http.StatusInsufficientStorage,
|
||||
},
|
||||
|
||||
// Admin api errors
|
||||
ErrAdminAccessDenied: {
|
||||
|
||||
Reference in New Issue
Block a user