Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: curio seal: Fix partial Finalize retry #11730

Merged
merged 2 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion curiosrc/ffi/sdr_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,12 +374,62 @@ func (sb *SealCalls) FinalizeSector(ctx context.Context, sector storiface.Sector
// * we truncate the temp file to the sector size
// * we move the temp file to the unsealed location

// move tree-d to temp file
// temp path in cache where we'll move tree-d before truncating
// it is in the cache directory so that we can use os.Rename to move it
// to unsealed (which may be on a different filesystem)
tempUnsealed := filepath.Join(sectorPaths.Cache, storiface.SectorName(sector.ID))

_, terr := os.Stat(tempUnsealed)
tempUnsealedExists := terr == nil

// First handle an edge case where we have already gone through this step,
// but ClearCache or later steps failed. In that case we'll see tree-d missing and unsealed present

if _, err := os.Stat(filepath.Join(sectorPaths.Cache, proofpaths.TreeDName)); err != nil {
if os.IsNotExist(err) {
// check that unsealed exists and is the right size
st, err := os.Stat(sectorPaths.Unsealed)
if err != nil {
if os.IsNotExist(err) {
if tempUnsealedExists {
// unsealed file does not exist, but temp unsealed file does
// so we can just resume where the previous attempt left off
goto retryUnsealedMove
}
return xerrors.Errorf("neither unsealed file nor temp-unsealed file exists")
}
return xerrors.Errorf("stat unsealed file: %w", err)
}
if st.Size() != int64(ssize) {
if tempUnsealedExists {
// unsealed file exists but is the wrong size, and temp unsealed file exists
// so we can just resume where the previous attempt left off with some cleanup

if err := os.Remove(sectorPaths.Unsealed); err != nil {
return xerrors.Errorf("removing unsealed file from last attempt: %w", err)
}

goto retryUnsealedMove
}
return xerrors.Errorf("unsealed file is not the right size: %d != %d and temp unsealed is missing", st.Size(), ssize)
}

// all good, just log that this edge case happened
log.Warnw("unsealed file exists but tree-d is missing, skipping move", "sector", sector.ID, "unsealed", sectorPaths.Unsealed, "cache", sectorPaths.Cache)
goto afterUnsealedMove
}
return xerrors.Errorf("stat tree-d file: %w", err)
}

// If the state in clean do the move

// move tree-d to temp file
if err := os.Rename(filepath.Join(sectorPaths.Cache, proofpaths.TreeDName), tempUnsealed); err != nil {
return xerrors.Errorf("moving tree-d to temp file: %w", err)
}

retryUnsealedMove:

// truncate sealed file to sector size
if err := os.Truncate(tempUnsealed, int64(ssize)); err != nil {
return xerrors.Errorf("truncating unsealed file to sector size: %w", err)
Expand All @@ -391,6 +441,7 @@ func (sb *SealCalls) FinalizeSector(ctx context.Context, sector storiface.Sector
}
}

afterUnsealedMove:
if err := ffi.ClearCache(uint64(ssize), sectorPaths.Cache); err != nil {
return xerrors.Errorf("clearing cache: %w", err)
}
Expand Down
12 changes: 9 additions & 3 deletions storage/paths/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,14 +476,18 @@ func (st *Local) AcquireSector(ctx context.Context, sid storiface.SectorRef, exi
var out storiface.SectorPaths
var storageIDs storiface.SectorPaths

// First find existing files
for _, fileType := range storiface.PathTypes {
if fileType&existing == 0 {
// also try to find existing sectors if we're allocating
if fileType&(existing|allocate) == 0 {
continue
}

si, err := st.index.StorageFindSector(ctx, sid.ID, fileType, ssize, false)
if err != nil {
log.Warnf("finding existing sector %d(t:%d) failed: %+v", sid, fileType, err)
if fileType&existing != 0 {
log.Warnf("finding existing sector %d(t:%d) failed: %+v", sid, fileType, err)
}
continue
}

Expand All @@ -501,11 +505,13 @@ func (st *Local) AcquireSector(ctx context.Context, sid storiface.SectorRef, exi
storiface.SetPathByType(&out, fileType, spath)
storiface.SetPathByType(&storageIDs, fileType, string(info.ID))

existing ^= fileType
existing = existing.Unset(fileType)
allocate = allocate.Unset(fileType)
break
}
}

// Then allocate for allocation requests
for _, fileType := range storiface.PathTypes {
if fileType&allocate == 0 {
continue
Expand Down
4 changes: 4 additions & 0 deletions storage/sealer/storiface/filetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ func (t SectorFileType) SubAllowed(allowTypes []string, denyTypes []string) Sect
return t & denyMask
}

func (t SectorFileType) Unset(toUnset SectorFileType) SectorFileType {
return t &^ toUnset
}

func (t SectorFileType) AnyAllowed(allowTypes []string, denyTypes []string) bool {
return t.SubAllowed(allowTypes, denyTypes) != t
}
Expand Down