ignore swapped drives instead of throwing errors (#13655)
- add checks such that swapped disks are detected and ignored - never used for normal operations. - implement `unrecognizedDisk` to be ignored with all operations returning `errDiskNotFound`. - also add checks such that we do not load unexpected disks while connecting automatically. - additionally humanize the values when printing the errors. Bonus: fixes handling of non-quorum situations in getLatestFileInfo(), that does not work when 2 drives are down, currently this function would return errors incorrectly.
This commit is contained in:
@@ -86,46 +86,163 @@ type StorageAPI interface {
|
||||
SetDiskLoc(poolIdx, setIdx, diskIdx int) // Set location indexes.
|
||||
}
|
||||
|
||||
// storageReader is an io.Reader view of a disk
|
||||
type storageReader struct {
|
||||
storage StorageAPI
|
||||
volume, path string
|
||||
offset int64
|
||||
type unrecognizedDisk struct {
|
||||
storage StorageAPI
|
||||
}
|
||||
|
||||
func (r *storageReader) Read(p []byte) (n int, err error) {
|
||||
nn, err := r.storage.ReadFile(context.TODO(), r.volume, r.path, r.offset, p, nil)
|
||||
r.offset += nn
|
||||
n = int(nn)
|
||||
func (p *unrecognizedDisk) WalkDir(ctx context.Context, opts WalkDirOptions, wr io.Writer) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
if err == io.ErrUnexpectedEOF && nn > 0 {
|
||||
err = io.EOF
|
||||
func (p *unrecognizedDisk) String() string {
|
||||
return p.storage.String()
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) IsOnline() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) LastConn() time.Time {
|
||||
return p.storage.LastConn()
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) IsLocal() bool {
|
||||
return p.storage.IsLocal()
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) Endpoint() Endpoint {
|
||||
return p.storage.Endpoint()
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) Hostname() string {
|
||||
return p.storage.Hostname()
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) Healing() *healingTracker {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) NSScanner(ctx context.Context, cache dataUsageCache, updates chan<- dataUsageEntry) (dataUsageCache, error) {
|
||||
return dataUsageCache{}, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) GetDiskLoc() (poolIdx, setIdx, diskIdx int) {
|
||||
return -1, -1, -1
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) SetDiskLoc(poolIdx, setIdx, diskIdx int) {
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) Close() error {
|
||||
return p.storage.Close()
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) GetDiskID() (string, error) {
|
||||
return "", errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) SetDiskID(id string) {
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) DiskInfo(ctx context.Context) (info DiskInfo, err error) {
|
||||
return info, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) MakeVolBulk(ctx context.Context, volumes ...string) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) MakeVol(ctx context.Context, volume string) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) ListVols(ctx context.Context) ([]VolInfo, error) {
|
||||
return nil, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) StatVol(ctx context.Context, volume string) (vol VolInfo, err error) {
|
||||
return vol, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) DeleteVol(ctx context.Context, volume string, forceDelete bool) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) ListDir(ctx context.Context, volume, dirPath string, count int) ([]string, error) {
|
||||
return nil, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) ReadFile(ctx context.Context, volume string, path string, offset int64, buf []byte, verifier *BitrotVerifier) (n int64, err error) {
|
||||
return 0, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) AppendFile(ctx context.Context, volume string, path string, buf []byte) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) CreateFile(ctx context.Context, volume, path string, size int64, reader io.Reader) error {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) ReadFileStream(ctx context.Context, volume, path string, offset, length int64) (io.ReadCloser, error) {
|
||||
return nil, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) RenameFile(ctx context.Context, srcVolume, srcPath, dstVolume, dstPath string) error {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) RenameData(ctx context.Context, srcVolume, srcPath string, fi FileInfo, dstVolume, dstPath string) error {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) CheckParts(ctx context.Context, volume string, path string, fi FileInfo) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) Delete(ctx context.Context, volume string, path string, recursive bool) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
// DeleteVersions deletes slice of versions, it can be same object
|
||||
// or multiple objects.
|
||||
func (p *unrecognizedDisk) DeleteVersions(ctx context.Context, volume string, versions []FileInfoVersions) (errs []error) {
|
||||
errs = make([]error, len(versions))
|
||||
|
||||
for i := range errs {
|
||||
errs[i] = errDiskNotFound
|
||||
}
|
||||
return
|
||||
return errs
|
||||
}
|
||||
|
||||
// storageWriter is a io.Writer view of a disk.
|
||||
type storageWriter struct {
|
||||
storage StorageAPI
|
||||
volume, path string
|
||||
func (p *unrecognizedDisk) VerifyFile(ctx context.Context, volume, path string, fi FileInfo) error {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (w *storageWriter) Write(p []byte) (n int, err error) {
|
||||
err = w.storage.AppendFile(context.TODO(), w.volume, w.path, p)
|
||||
if err == nil {
|
||||
n = len(p)
|
||||
}
|
||||
return
|
||||
func (p *unrecognizedDisk) WriteAll(ctx context.Context, volume string, path string, b []byte) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
// StorageWriter returns a new io.Writer which appends data to the file
|
||||
// at the given disk, volume and path.
|
||||
func StorageWriter(storage StorageAPI, volume, path string) io.Writer {
|
||||
return &storageWriter{storage, volume, path}
|
||||
func (p *unrecognizedDisk) DeleteVersion(ctx context.Context, volume, path string, fi FileInfo, forceDelMarker bool) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
// StorageReader returns a new io.Reader which reads data to the file
|
||||
// at the given disk, volume, path and offset.
|
||||
func StorageReader(storage StorageAPI, volume, path string, offset int64) io.Reader {
|
||||
return &storageReader{storage, volume, path, offset}
|
||||
func (p *unrecognizedDisk) UpdateMetadata(ctx context.Context, volume, path string, fi FileInfo) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) WriteMetadata(ctx context.Context, volume, path string, fi FileInfo) (err error) {
|
||||
return errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) ReadVersion(ctx context.Context, volume, path, versionID string, readData bool) (fi FileInfo, err error) {
|
||||
return fi, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) ReadAll(ctx context.Context, volume string, path string) (buf []byte, err error) {
|
||||
return nil, errDiskNotFound
|
||||
}
|
||||
|
||||
func (p *unrecognizedDisk) StatInfoFile(ctx context.Context, volume, path string, glob bool) (stat []StatInfo, err error) {
|
||||
return nil, errDiskNotFound
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user