mirror of
https://github.com/minio/minio.git
synced 2025-11-25 12:06:10 -05:00
xl: Introduce new blocking writer to make CreateFile atomic. (#1362)
Creates a new write closer that must be released by the read consumer. This is necessary so that while commiting the underlying writers in erasure coding we need to make sure we reply success only if we have committed to disk. This in turn also fixes plethora of bugs related to subsequent PutObject() races with namespace locking. This patch also enables most of the tests, other than ListObjects paging which has some issues still. Fixes #1358, #1360
This commit is contained in:
committed by
Harshavardhana
parent
cab6805f09
commit
57f35c2bcc
@@ -113,10 +113,7 @@ func (xl XL) getFileQuorumVersionMap(volume, path string) map[int]int64 {
|
||||
|
||||
// WriteErasure reads predefined blocks, encodes them and writes to
|
||||
// configured storage disks.
|
||||
func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
xl.lockNS(volume, path, false)
|
||||
defer xl.unlockNS(volume, path, false)
|
||||
|
||||
func (xl XL) writeErasure(volume, path string, reader *io.PipeReader, bwriter *blockingWriteCloser) {
|
||||
// Get available quorum for existing file path.
|
||||
_, higherVersion := xl.getQuorumDisks(volume, path)
|
||||
// Increment to have next higher version.
|
||||
@@ -147,6 +144,7 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
// Remove previous temp writers for any failure.
|
||||
xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...)
|
||||
reader.CloseWithError(errWriteQuorum)
|
||||
bwriter.Release(errWriteQuorum)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -165,6 +163,7 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
// Remove previous temp writers for any failure.
|
||||
xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...)
|
||||
reader.CloseWithError(errWriteQuorum)
|
||||
bwriter.Release(errWriteQuorum)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -185,6 +184,7 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
// Remove all temp writers.
|
||||
xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...)
|
||||
reader.CloseWithError(err)
|
||||
bwriter.Release(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -200,6 +200,7 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
// Remove all temp writers.
|
||||
xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...)
|
||||
reader.CloseWithError(err)
|
||||
bwriter.Release(err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -209,6 +210,7 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
// Remove all temp writers upon error.
|
||||
xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...)
|
||||
reader.CloseWithError(err)
|
||||
bwriter.Release(err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -223,6 +225,7 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
// Remove all temp writers upon error.
|
||||
xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...)
|
||||
reader.CloseWithError(err)
|
||||
bwriter.Release(err)
|
||||
return
|
||||
}
|
||||
if sha512Writers[index] != nil {
|
||||
@@ -272,10 +275,15 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
// Remove temporary files.
|
||||
xl.cleanupCreateFileOps(volume, path, append(writers, metadataWriters...)...)
|
||||
reader.CloseWithError(err)
|
||||
bwriter.Release(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Lock right before commit to disk.
|
||||
xl.lockNS(volume, path, false)
|
||||
defer xl.unlockNS(volume, path, false)
|
||||
|
||||
// Close all writers and metadata writers in routines.
|
||||
for index, writer := range writers {
|
||||
if writer == nil {
|
||||
@@ -291,6 +299,9 @@ func (xl XL) writeErasure(volume, path string, reader *io.PipeReader) {
|
||||
metadataWriters[index].Close()
|
||||
}
|
||||
|
||||
// Release the blocking writer.
|
||||
bwriter.Release(nil)
|
||||
|
||||
// Close the pipe reader and return.
|
||||
reader.Close()
|
||||
return
|
||||
@@ -308,9 +319,12 @@ func (xl XL) CreateFile(volume, path string) (writeCloser io.WriteCloser, err er
|
||||
// Initialize pipe for data pipe line.
|
||||
pipeReader, pipeWriter := io.Pipe()
|
||||
|
||||
// Start erasure encoding in routine, reading data block by block from pipeReader.
|
||||
go xl.writeErasure(volume, path, pipeReader)
|
||||
// Initialize a new blocking writer closer.
|
||||
blockingWriter := newBlockingWriteCloser(pipeWriter)
|
||||
|
||||
// Return the piped writer, caller should start writing to this.
|
||||
return pipeWriter, nil
|
||||
// Start erasure encoding in routine, reading data block by block from pipeReader.
|
||||
go xl.writeErasure(volume, path, pipeReader, blockingWriter)
|
||||
|
||||
// Return the blocking writer, caller should start writing to this.
|
||||
return blockingWriter, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user