diff --git a/cmd/bitrot.go b/cmd/bitrot.go index b4dbab01e..ab7d9e75a 100644 --- a/cmd/bitrot.go +++ b/cmd/bitrot.go @@ -128,14 +128,20 @@ func closeBitrotReaders(rs []io.ReaderAt) { } // Close all the writers. -func closeBitrotWriters(ws []io.Writer) { - for _, w := range ws { - if w != nil { - if bw, ok := w.(io.Closer); ok { - bw.Close() - } +func closeBitrotWriters(ws []io.Writer) []error { + errs := make([]error, len(ws)) + for i, w := range ws { + if w == nil { + errs[i] = errDiskNotFound + continue + } + if bw, ok := w.(io.Closer); ok { + errs[i] = bw.Close() + } else { + errs[i] = nil } } + return errs } // Returns hash sum for whole-bitrot, nil for streaming-bitrot. diff --git a/cmd/erasure-healing.go b/cmd/erasure-healing.go index d3d5b8de5..efe8b78e9 100644 --- a/cmd/erasure-healing.go +++ b/cmd/erasure-healing.go @@ -608,7 +608,7 @@ func (er *erasureObjects) healObject(ctx context.Context, bucket string, object // later to the final location. err = erasure.Heal(ctx, writers, readers, partSize, prefer) closeBitrotReaders(readers) - closeBitrotWriters(writers) + closeErrs := closeBitrotWriters(writers) if err != nil { return result, err } @@ -628,6 +628,13 @@ func (er *erasureObjects) healObject(ctx context.Context, bucket string, object continue } + // A non-nil stale disk which got error on Close() + if closeErrs[i] != nil { + outDatedDisks[i] = nil + disksToHealCount-- + continue + } + partsMetadata[i].DataDir = dstDataDir partsMetadata[i].AddObjectPart(partNumber, "", partSize, partActualSize, partModTime, partIdx, partChecksums) if len(inlineBuffers) > 0 && inlineBuffers[i] != nil { diff --git a/cmd/erasure-multipart.go b/cmd/erasure-multipart.go index c69400587..6c74a6998 100644 --- a/cmd/erasure-multipart.go +++ b/cmd/erasure-multipart.go @@ -668,10 +668,13 @@ func (er erasureObjects) PutObjectPart(ctx context.Context, bucket, object, uplo } n, err := erasure.Encode(ctx, toEncode, writers, buffer, writeQuorum) - closeBitrotWriters(writers) + closeErrs := closeBitrotWriters(writers) if err != nil { return pi, toObjectErr(err, bucket, object) } + if closeErr := reduceWriteQuorumErrs(ctx, closeErrs, objectOpIgnoredErrs, writeQuorum); closeErr != nil { + return pi, toObjectErr(closeErr, bucket, object) + } // Should return IncompleteBody{} error when reader has fewer bytes // than specified in request header. diff --git a/cmd/erasure-object.go b/cmd/erasure-object.go index 4422a5d47..37fcb9d4e 100644 --- a/cmd/erasure-object.go +++ b/cmd/erasure-object.go @@ -1178,11 +1178,15 @@ func (er erasureObjects) putMetacacheObject(ctx context.Context, key string, r * } n, erasureErr := erasure.Encode(ctx, data, writers, buffer, writeQuorum) - closeBitrotWriters(writers) + closeErrs := closeBitrotWriters(writers) if erasureErr != nil { return ObjectInfo{}, toObjectErr(erasureErr, minioMetaBucket, key) } + if closeErr := reduceWriteQuorumErrs(ctx, closeErrs, objectOpIgnoredErrs, writeQuorum); closeErr != nil { + return ObjectInfo{}, toObjectErr(closeErr, minioMetaBucket, key) + } + // Should return IncompleteBody{} error when reader has fewer bytes // than specified in request header. if n < data.Size() { @@ -1425,11 +1429,15 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st bugLogIf(ctx, err) } n, erasureErr := erasure.Encode(ctx, toEncode, writers, buffer, writeQuorum) - closeBitrotWriters(writers) + closeErrs := closeBitrotWriters(writers) if erasureErr != nil { return ObjectInfo{}, toObjectErr(erasureErr, bucket, object) } + if closeErr := reduceWriteQuorumErrs(ctx, closeErrs, objectOpIgnoredErrs, writeQuorum); closeErr != nil { + return ObjectInfo{}, toObjectErr(closeErr, bucket, object) + } + // Should return IncompleteBody{} error when reader has fewer bytes // than specified in request header. if n < data.Size() {