add a sector check command
This commit is contained in:
parent
d15d9b0fb9
commit
663b3f4f21
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
"github.com/filecoin-project/lotus/extern/sector-storage/fsutil"
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
"github.com/filecoin-project/lotus/extern/sector-storage/stores"
|
||||||
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
"github.com/filecoin-project/lotus/extern/sector-storage/storiface"
|
||||||
|
"github.com/filecoin-project/specs-storage/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StorageMiner is a low-level interface to the Filecoin network storage miner node
|
// StorageMiner is a low-level interface to the Filecoin network storage miner node
|
||||||
@ -116,6 +117,8 @@ type StorageMiner interface {
|
|||||||
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
|
// LOTUS_BACKUP_BASE_PATH environment variable set to some path, and that
|
||||||
// the path specified when calling CreateBackup is within the base path
|
// the path specified when calling CreateBackup is within the base path
|
||||||
CreateBackup(ctx context.Context, fpath string) error
|
CreateBackup(ctx context.Context, fpath string) error
|
||||||
|
|
||||||
|
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef) (map[abi.SectorNumber]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SealRes struct {
|
type SealRes struct {
|
||||||
|
@ -363,6 +363,8 @@ type StorageMinerStruct struct {
|
|||||||
PiecesGetCIDInfo func(ctx context.Context, payloadCid cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"`
|
PiecesGetCIDInfo func(ctx context.Context, payloadCid cid.Cid) (*piecestore.CIDInfo, error) `perm:"read"`
|
||||||
|
|
||||||
CreateBackup func(ctx context.Context, fpath string) error `perm:"admin"`
|
CreateBackup func(ctx context.Context, fpath string) error `perm:"admin"`
|
||||||
|
|
||||||
|
CheckProvable func(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef) (map[abi.SectorNumber]string, error) `perm:"admin"`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1510,6 +1512,10 @@ func (c *StorageMinerStruct) CreateBackup(ctx context.Context, fpath string) err
|
|||||||
return c.Internal.CreateBackup(ctx, fpath)
|
return c.Internal.CreateBackup(ctx, fpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *StorageMinerStruct) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef) (map[abi.SectorNumber]string, error) {
|
||||||
|
return c.Internal.CheckProvable(ctx, pp, sectors)
|
||||||
|
}
|
||||||
|
|
||||||
// WorkerStruct
|
// WorkerStruct
|
||||||
|
|
||||||
func (w *WorkerStruct) Version(ctx context.Context) (build.Version, error) {
|
func (w *WorkerStruct) Version(ctx context.Context) (build.Version, error) {
|
||||||
|
@ -10,11 +10,14 @@ import (
|
|||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
"github.com/filecoin-project/lotus/api/apibstore"
|
"github.com/filecoin-project/lotus/api/apibstore"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
lcli "github.com/filecoin-project/lotus/cli"
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
|
"github.com/filecoin-project/specs-storage/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
var provingCmd = &cli.Command{
|
var provingCmd = &cli.Command{
|
||||||
@ -25,6 +28,7 @@ var provingCmd = &cli.Command{
|
|||||||
provingDeadlinesCmd,
|
provingDeadlinesCmd,
|
||||||
provingDeadlineInfoCmd,
|
provingDeadlineInfoCmd,
|
||||||
provingFaultsCmd,
|
provingFaultsCmd,
|
||||||
|
provingCheckProvableCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,3 +375,101 @@ var provingDeadlineInfoCmd = &cli.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var provingCheckProvableCmd = &cli.Command{
|
||||||
|
Name: "check",
|
||||||
|
Usage: "Check sectors provable",
|
||||||
|
ArgsUsage: "<deadlineIdx>",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "only-bad",
|
||||||
|
Usage: "print only bad sectors",
|
||||||
|
Value: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 1 {
|
||||||
|
return xerrors.Errorf("must pass deadline index")
|
||||||
|
}
|
||||||
|
|
||||||
|
dlIdx, err := strconv.ParseUint(cctx.Args().Get(0), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("could not parse deadline index: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
api, closer, err := lcli.GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
sapi, scloser, err := lcli.GetStorageMinerAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer scloser()
|
||||||
|
|
||||||
|
ctx := lcli.ReqContext(cctx)
|
||||||
|
|
||||||
|
addr, err := sapi.ActorAddress(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mid, err := address.IDFromAddress(addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := api.StateMinerInfo(ctx, addr, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pf, err := info.SealProofType.RegisteredWindowPoStProof()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
partitions, err := api.StateMinerPartitions(ctx, addr, dlIdx, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
|
||||||
|
_, _ = fmt.Fprintln(tw, "deadline\tpartition\tsector\tstatus")
|
||||||
|
|
||||||
|
for parIdx, par := range partitions {
|
||||||
|
sectors := make(map[abi.SectorNumber]struct{})
|
||||||
|
|
||||||
|
sectorInfos, err := api.StateMinerSectors(ctx, addr, &par.AllSectors, types.EmptyTSK)
|
||||||
|
|
||||||
|
var tocheck []storage.SectorRef
|
||||||
|
for _, info := range sectorInfos {
|
||||||
|
sectors[info.SectorNumber] = struct{}{}
|
||||||
|
tocheck = append(tocheck, storage.SectorRef{
|
||||||
|
ProofType: info.SealProof,
|
||||||
|
ID: abi.SectorID{
|
||||||
|
Miner: abi.ActorID(mid),
|
||||||
|
Number: info.SectorNumber,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
bad, err := sapi.CheckProvable(ctx, pf, tocheck)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for s := range sectors {
|
||||||
|
if err, exist := bad[s]; exist {
|
||||||
|
_, _ = fmt.Fprintf(tw, "%d\t%d\t%d\t%s\n", dlIdx, parIdx, s, color.RedString("bad")+fmt.Sprintf(" (%s)", err))
|
||||||
|
} else if !cctx.Bool("only-bad") {
|
||||||
|
_, _ = fmt.Fprintf(tw, "%d\t%d\t%d\t%s\n", dlIdx, parIdx, s, color.GreenString("good"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tw.Flush()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
18
extern/sector-storage/faults.go
vendored
18
extern/sector-storage/faults.go
vendored
@ -16,12 +16,12 @@ import (
|
|||||||
|
|
||||||
// FaultTracker TODO: Track things more actively
|
// FaultTracker TODO: Track things more actively
|
||||||
type FaultTracker interface {
|
type FaultTracker interface {
|
||||||
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef) ([]abi.SectorID, error)
|
CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef) (map[abi.SectorID]string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckProvable returns unprovable sectors
|
// CheckProvable returns unprovable sectors
|
||||||
func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef) ([]abi.SectorID, error) {
|
func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storage.SectorRef) (map[abi.SectorID]string, error) {
|
||||||
var bad []abi.SectorID
|
var bad = make(map[abi.SectorID]string)
|
||||||
|
|
||||||
ssize, err := pp.SectorSize()
|
ssize, err := pp.SectorSize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -41,20 +41,20 @@ func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof,
|
|||||||
|
|
||||||
if !locked {
|
if !locked {
|
||||||
log.Warnw("CheckProvable Sector FAULT: can't acquire read lock", "sector", sector)
|
log.Warnw("CheckProvable Sector FAULT: can't acquire read lock", "sector", sector)
|
||||||
bad = append(bad, sector.ID)
|
bad[sector.ID] = fmt.Sprint("can't acquire read lock")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lp, _, err := m.localStore.AcquireSector(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove)
|
lp, _, err := m.localStore.AcquireSector(ctx, sector, storiface.FTSealed|storiface.FTCache, storiface.FTNone, storiface.PathStorage, storiface.AcquireMove)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnw("CheckProvable Sector FAULT: acquire sector in checkProvable", "sector", sector, "error", err)
|
log.Warnw("CheckProvable Sector FAULT: acquire sector in checkProvable", "sector", sector, "error", err)
|
||||||
bad = append(bad, sector.ID)
|
bad[sector.ID] = fmt.Sprintf("acquire sector failed: %s", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if lp.Sealed == "" || lp.Cache == "" {
|
if lp.Sealed == "" || lp.Cache == "" {
|
||||||
log.Warnw("CheckProvable Sector FAULT: cache an/or sealed paths not found", "sector", sector, "sealed", lp.Sealed, "cache", lp.Cache)
|
log.Warnw("CheckProvable Sector FAULT: cache and/or sealed paths not found", "sector", sector, "sealed", lp.Sealed, "cache", lp.Cache)
|
||||||
bad = append(bad, sector.ID)
|
bad[sector.ID] = fmt.Sprintf("cache and/or sealed paths not found, cache %q, sealed %q", lp.Cache, lp.Sealed)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,14 +70,14 @@ func (m *Manager) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof,
|
|||||||
st, err := os.Stat(p)
|
st, err := os.Stat(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnw("CheckProvable Sector FAULT: sector file stat error", "sector", sector, "sealed", lp.Sealed, "cache", lp.Cache, "file", p, "err", err)
|
log.Warnw("CheckProvable Sector FAULT: sector file stat error", "sector", sector, "sealed", lp.Sealed, "cache", lp.Cache, "file", p, "err", err)
|
||||||
bad = append(bad, sector.ID)
|
bad[sector.ID] = fmt.Sprintf("%s", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if sz != 0 {
|
if sz != 0 {
|
||||||
if st.Size() != int64(ssize)*sz {
|
if st.Size() != int64(ssize)*sz {
|
||||||
log.Warnw("CheckProvable Sector FAULT: sector file is wrong size", "sector", sector, "sealed", lp.Sealed, "cache", lp.Cache, "file", p, "size", st.Size(), "expectSize", int64(ssize)*sz)
|
log.Warnw("CheckProvable Sector FAULT: sector file is wrong size", "sector", sector, "sealed", lp.Sealed, "cache", lp.Cache, "file", p, "size", st.Size(), "expectSize", int64(ssize)*sz)
|
||||||
bad = append(bad, sector.ID)
|
bad[sector.ID] = fmt.Sprintf("%s is wrong size (got %d, expect %d)", p, st.Size(), int64(ssize)*sz)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||||
"github.com/filecoin-project/lotus/storage"
|
"github.com/filecoin-project/lotus/storage"
|
||||||
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
"github.com/filecoin-project/lotus/storage/sectorblocks"
|
||||||
|
sto "github.com/filecoin-project/specs-storage/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StorageMinerAPI struct {
|
type StorageMinerAPI struct {
|
||||||
@ -543,4 +544,18 @@ func (sm *StorageMinerAPI) CreateBackup(ctx context.Context, fpath string) error
|
|||||||
return backup(sm.DS, fpath)
|
return backup(sm.DS, fpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *StorageMinerAPI) CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []sto.SectorRef) (map[abi.SectorNumber]string, error) {
|
||||||
|
bad, err := sm.StorageMgr.CheckProvable(ctx, pp, sectors)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var out = make(map[abi.SectorNumber]string)
|
||||||
|
for sid, err := range bad {
|
||||||
|
out[sid.Number] = err
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
var _ api.StorageMiner = &StorageMinerAPI{}
|
var _ api.StorageMiner = &StorageMinerAPI{}
|
||||||
|
@ -212,14 +212,13 @@ func (s *WindowPoStScheduler) checkSectors(ctx context.Context, check bitfield.B
|
|||||||
Number: info.SectorNumber,
|
Number: info.SectorNumber,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bad, err := s.faultTracker.CheckProvable(ctx, s.proofType, tocheck)
|
bad, err := s.faultTracker.CheckProvable(ctx, s.proofType, tocheck)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return bitfield.BitField{}, xerrors.Errorf("checking provable sectors: %w", err)
|
return bitfield.BitField{}, xerrors.Errorf("checking provable sectors: %w", err)
|
||||||
}
|
}
|
||||||
for _, id := range bad {
|
for id := range bad {
|
||||||
delete(sectors, id.Number)
|
delete(sectors, id.Number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user