fix: paths/local: Fix on-disk storage accounting in new reservations (#11825)

This commit is contained in:
Łukasz Magiera 2024-04-04 18:17:04 +02:00 committed by GitHub
parent a24028c3c0
commit fd64e38b39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 22 deletions

View File

@ -211,8 +211,6 @@ func (t *TreesTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done
} }
func (t *TreesTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask.TaskEngine) (*harmonytask.TaskID, error) { func (t *TreesTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask.TaskEngine) (*harmonytask.TaskID, error) {
// todo reserve storage
id := ids[0] id := ids[0]
return &id, nil return &id, nil
} }

View File

@ -61,24 +61,25 @@ type statExistingSectorForReservation struct {
ft storiface.SectorFileType ft storiface.SectorFileType
} }
func (p *path) stat(ls LocalStorage, newReserve ...statExistingSectorForReservation) (fsutil.FsStat, error) { func (p *path) stat(ls LocalStorage, newReserve ...statExistingSectorForReservation) (stat fsutil.FsStat, newResvOnDisk int64, err error) {
start := time.Now() start := time.Now()
stat, err := ls.Stat(p.local) stat, err = ls.Stat(p.local)
if err != nil { if err != nil {
return fsutil.FsStat{}, xerrors.Errorf("stat %s: %w", p.local, err) return fsutil.FsStat{}, 0, xerrors.Errorf("stat %s: %w", p.local, err)
} }
stat.Reserved = p.reserved stat.Reserved = p.reserved
var newReserveOnDisk int64
accountExistingFiles := func(id abi.SectorID, fileType storiface.SectorFileType) error { accountExistingFiles := func(id abi.SectorID, fileType storiface.SectorFileType) (int64, error) {
sp := p.sectorPath(id, fileType) sp := p.sectorPath(id, fileType)
used, err := ls.DiskUsage(sp) used, err := ls.DiskUsage(sp)
if err == os.ErrNotExist { if err == os.ErrNotExist {
p, ferr := tempFetchDest(sp, false) p, ferr := tempFetchDest(sp, false)
if ferr != nil { if ferr != nil {
return ferr return 0, ferr
} }
used, err = ls.DiskUsage(p) used, err = ls.DiskUsage(p)
@ -90,18 +91,19 @@ func (p *path) stat(ls LocalStorage, newReserve ...statExistingSectorForReservat
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
log.Warnf("getting disk usage of '%s': %+v", p.sectorPath(id, fileType), err) log.Warnf("getting disk usage of '%s': %+v", p.sectorPath(id, fileType), err)
} }
return nil return 0, nil
} }
stat.Reserved -= used return used, nil
return nil
} }
for id, ft := range p.reservations { for id, ft := range p.reservations {
for _, fileType := range ft.AllSet() { for _, fileType := range ft.AllSet() {
if err := accountExistingFiles(id, fileType); err != nil { onDisk, err := accountExistingFiles(id, fileType)
return fsutil.FsStat{}, err if err != nil {
return fsutil.FsStat{}, 0, err
} }
stat.Reserved -= onDisk
} }
} }
for _, reservation := range newReserve { for _, reservation := range newReserve {
@ -111,9 +113,11 @@ func (p *path) stat(ls LocalStorage, newReserve ...statExistingSectorForReservat
continue continue
} }
if err := accountExistingFiles(reservation.id, fileType); err != nil { onDisk, err := accountExistingFiles(reservation.id, fileType)
return fsutil.FsStat{}, err if err != nil {
return fsutil.FsStat{}, 0, err
} }
newReserveOnDisk += onDisk
} }
} }
@ -130,7 +134,7 @@ func (p *path) stat(ls LocalStorage, newReserve ...statExistingSectorForReservat
if p.maxStorage > 0 { if p.maxStorage > 0 {
used, err := ls.DiskUsage(p.local) used, err := ls.DiskUsage(p.local)
if err != nil { if err != nil {
return fsutil.FsStat{}, err return fsutil.FsStat{}, 0, err
} }
stat.Max = int64(p.maxStorage) stat.Max = int64(p.maxStorage)
@ -150,7 +154,7 @@ func (p *path) stat(ls LocalStorage, newReserve ...statExistingSectorForReservat
log.Warnw("slow storage stat", "took", time.Now().Sub(start), "reservations", len(p.reservations)) log.Warnw("slow storage stat", "took", time.Now().Sub(start), "reservations", len(p.reservations))
} }
return stat, err return stat, newReserveOnDisk, err
} }
func (p *path) sectorPath(sid abi.SectorID, fileType storiface.SectorFileType) string { func (p *path) sectorPath(sid abi.SectorID, fileType storiface.SectorFileType) string {
@ -198,7 +202,7 @@ func (st *Local) OpenPath(ctx context.Context, p string) error {
reservations: map[abi.SectorID]storiface.SectorFileType{}, reservations: map[abi.SectorID]storiface.SectorFileType{},
} }
fst, err := out.stat(st.localStorage) fst, _, err := out.stat(st.localStorage)
if err != nil { if err != nil {
return err return err
} }
@ -282,7 +286,7 @@ func (st *Local) Redeclare(ctx context.Context, filterId *storiface.ID, dropMiss
return xerrors.Errorf("unmarshalling storage metadata for %s: %w", p.local, err) return xerrors.Errorf("unmarshalling storage metadata for %s: %w", p.local, err)
} }
fst, err := p.stat(st.localStorage) fst, _, err := p.stat(st.localStorage)
if err != nil { if err != nil {
return err return err
} }
@ -408,7 +412,7 @@ func (st *Local) reportStorage(ctx context.Context) {
toReport := map[storiface.ID]storiface.HealthReport{} toReport := map[storiface.ID]storiface.HealthReport{}
for id, p := range st.paths { for id, p := range st.paths {
stat, err := p.stat(st.localStorage) stat, _, err := p.stat(st.localStorage)
r := storiface.HealthReport{Stat: stat} r := storiface.HealthReport{Stat: stat}
if err != nil { if err != nil {
r.Err = err.Error() r.Err = err.Error()
@ -449,14 +453,19 @@ func (st *Local) Reserve(ctx context.Context, sid storiface.SectorRef, ft storif
return nil, errPathNotFound return nil, errPathNotFound
} }
stat, err := p.stat(st.localStorage, statExistingSectorForReservation{sid.ID, fileType}) stat, resvOnDisk, err := p.stat(st.localStorage, statExistingSectorForReservation{sid.ID, fileType})
if err != nil { if err != nil {
return nil, xerrors.Errorf("getting local storage stat: %w", err) return nil, xerrors.Errorf("getting local storage stat: %w", err)
} }
overhead := int64(overheadTab[fileType]) * int64(ssize) / storiface.FSOverheadDen overhead := int64(overheadTab[fileType]) * int64(ssize) / storiface.FSOverheadDen
if stat.Available < overhead { if overhead-resvOnDisk < 0 {
log.Errorw("negative overhead vs on-disk data", "overhead", overhead, "on-disk", resvOnDisk, "id", id, "sector", sid, "fileType", fileType)
resvOnDisk = overhead
}
if stat.Available < overhead-resvOnDisk {
return nil, storiface.Err(storiface.ErrTempAllocateSpace, xerrors.Errorf("can't reserve %d bytes in '%s' (id:%s), only %d available", overhead, p.local, id, stat.Available)) return nil, storiface.Err(storiface.ErrTempAllocateSpace, xerrors.Errorf("can't reserve %d bytes in '%s' (id:%s), only %d available", overhead, p.local, id, stat.Available))
} }
@ -823,7 +832,8 @@ func (st *Local) FsStat(ctx context.Context, id storiface.ID) (fsutil.FsStat, er
return fsutil.FsStat{}, errPathNotFound return fsutil.FsStat{}, errPathNotFound
} }
return p.stat(st.localStorage) stat, _, err := p.stat(st.localStorage)
return stat, err
} }
func (st *Local) GenerateSingleVanillaProof(ctx context.Context, minerID abi.ActorID, si storiface.PostSectorChallenge, ppt abi.RegisteredPoStProof) ([]byte, error) { func (st *Local) GenerateSingleVanillaProof(ctx context.Context, minerID abi.ActorID, si storiface.PostSectorChallenge, ppt abi.RegisteredPoStProof) ([]byte, error) {