summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-06-05 23:57:05 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-06-05 23:57:05 -0600
commit6a5b5b59345c6e57ba496c7d517902c339d2f0b8 (patch)
treee3428175ffd07791fad1406401fe1856e95e8555
parent5c02065e573ce42d9d83099b524566878ba61bdb (diff)
wip gather stripes
-rw-r--r--cmd/btrfs-fsck/main.go71
-rw-r--r--pkg/btrfs/btrfsitem/item_chunk.go16
-rw-r--r--pkg/btrfs/io2_fs.go4
-rw-r--r--pkg/btrfsmisc/print_tree.go6
4 files changed, 85 insertions, 12 deletions
diff --git a/cmd/btrfs-fsck/main.go b/cmd/btrfs-fsck/main.go
index 97b1571..2e47588 100644
--- a/cmd/btrfs-fsck/main.go
+++ b/cmd/btrfs-fsck/main.go
@@ -70,8 +70,14 @@ func Main(imgfilename string) (err error) {
fmt.Printf("Pass 1: ... walk chunk tree: error: %v\n", err)
}
+ type reconstructedStripe struct {
+ Size uint64
+ Addr btrfs.QualifiedPhysicalAddr
+ }
+ reconstructedChunks := make(map[btrfs.LogicalAddr][]reconstructedStripe)
for _, dev := range fs.Devices {
fmt.Printf("Pass 1: ... dev[%q] scanning for nodes\n", dev.Name())
+ superblock, _ := dev.Superblock()
foundNodes := make(map[btrfs.LogicalAddr][]btrfs.PhysicalAddr)
var lostAndFoundChunks []btrfs.SysChunk
if err := btrfsmisc.ScanForNodes(dev, superblock.Data, func(nodeRef *util.Ref[btrfs.PhysicalAddr, btrfs.Node], err error) {
@@ -150,8 +156,71 @@ func Main(imgfilename string) (err error) {
})
}
}
- fmt.Printf("Pass 1: ... dev[%q] reconstructed stripes: %#v\n", dev.Name(), stripes)
+ //fmt.Printf("Pass 1: ... dev[%q] reconstructed stripes: %#v\n", dev.Name(), stripes)
+ for _, stripe := range stripes {
+ reconstructedChunks[stripe.LAddr] = append(reconstructedChunks[stripe.LAddr], reconstructedStripe{
+ Size: stripe.Size,
+ Addr: btrfs.QualifiedPhysicalAddr{
+ Dev: superblock.Data.DevItem.DevUUID,
+ Addr: stripe.PAddr,
+ },
+ })
+ }
}
+ // FIXME(lukeshu): OK, so this just assumes that all the
+ // reconstructed stripes fit in one node, and that we can just
+ // store that node at the root node of the chunk tree. This
+ // isn't true in general, but it's true of my particular
+ // filesystem.
+ /*
+ reconstructedNode := &util.Ref[btrfs.LogicalAddr, btrfs.Node]{
+ File: fs,
+ Addr: superblock.Data.ChunkTree,
+ Data: btrfs.Node{
+ Size: superblock.Data.NodeSize,
+ Head: btrfs.NodeHeader{
+ MetadataUUID: superblock.Data.EffectiveMetadataUUID(),
+ Addr: superblock.Data.ChunkTree,
+ Flags: btrfs.NodeWritten,
+ //BackrefRef: ???,
+ //ChunkTreeUUID: ???,
+ Generation: superblock.Data.ChunkRootGeneration,
+ Owner: btrfs.CHUNK_TREE_OBJECTID,
+ Level: 0,
+ },
+ },
+ }
+ itemOff := superblock.Data.NodeSize - binstruct.StaticSize(btrfs.ItemHeader{})
+ for laddr, stripes := range reconstructedChunks {
+ stripeSize := stripes[0].Size
+ for i, stripe := range stripes {
+ if stripes.Size != stripeSize {
+ panic("mismatch")
+ }
+ }
+ itemSize := binstruct.StaticSize(btrfsitem.ChunkHeader) + (len(stripes) * binstruct.StaticSize(btrfsitem.ChunkStripe))
+ itemOff -= itemSize
+ reconstructedNode.Data.BodyLeaf = append(reconstructedNode.Data.BodyLeaf, btrfs.Item{
+ Head: btrfs.ItemHeader{
+ Key: TODO,
+ DataOffset: itemOff,
+ DataSize: itemSize,
+ },
+ Body: btrfsitem.Chunk{
+ Head: btrfsitem.ChunkHeader{
+ Size: stripeSize,
+ Owner: 2,
+ StripeLen:
+ Stripes: stripes,
+ },
+ })
+ }
+ reconstructedNode.Data.Head.NumItems = len(reconstructedNode.Data.BodyLeaf)
+ reconstructedNode.Data.Head.Checksum, err = reconstructedNode.Data.CalculateChecksum()
+ if err != nil {
+ fmt.Printf("Pass 1: ... new node checksum: error: %v\n", err)
+ }
+ */
fmt.Printf("\nPass 2: ?????????????????????????\n") ////////////////////////////////////////
/*
diff --git a/pkg/btrfs/btrfsitem/item_chunk.go b/pkg/btrfs/btrfsitem/item_chunk.go
index 4389a46..8ffc83b 100644
--- a/pkg/btrfs/btrfsitem/item_chunk.go
+++ b/pkg/btrfs/btrfsitem/item_chunk.go
@@ -7,8 +7,13 @@ import (
"lukeshu.com/btrfs-tools/pkg/btrfs/internal"
)
+// Maps logical address to physical.
type Chunk struct { // CHUNK_ITEM=228
- // Maps logical address to physical.
+ Head ChunkHeader
+ Stripes []ChunkStripe
+}
+
+type ChunkHeader struct {
Size uint64 `bin:"off=0x0, siz=0x8"` // size of chunk (bytes)
Owner internal.ObjID `bin:"off=0x8, siz=0x8"` // root referencing this chunk (2)
StripeLen uint64 `bin:"off=0x10, siz=0x8"` // stripe length
@@ -19,7 +24,6 @@ type Chunk struct { // CHUNK_ITEM=228
NumStripes uint16 `bin:"off=0x2c, siz=0x2"` // number of stripes
SubStripes uint16 `bin:"off=0x2e, siz=0x2"` // sub stripes
binstruct.End `bin:"off=0x30"`
- Stripes []ChunkStripe `bin:"-"`
}
type ChunkStripe struct {
@@ -30,12 +34,12 @@ type ChunkStripe struct {
}
func (chunk *Chunk) UnmarshalBinary(dat []byte) (int, error) {
- n, err := binstruct.UnmarshalWithoutInterface(dat, chunk)
+ n, err := binstruct.Unmarshal(dat, &chunk.Head)
if err != nil {
return n, err
}
chunk.Stripes = nil
- for i := 0; i < int(chunk.NumStripes); i++ {
+ for i := 0; i < int(chunk.Head.NumStripes); i++ {
var stripe ChunkStripe
_n, err := binstruct.Unmarshal(dat[n:], &stripe)
n += _n
@@ -48,8 +52,8 @@ func (chunk *Chunk) UnmarshalBinary(dat []byte) (int, error) {
}
func (chunk Chunk) MarshalBinary() ([]byte, error) {
- chunk.NumStripes = uint16(len(chunk.Stripes))
- ret, err := binstruct.MarshalWithoutInterface(chunk)
+ chunk.Head.NumStripes = uint16(len(chunk.Stripes))
+ ret, err := binstruct.Marshal(chunk.Head)
if err != nil {
return ret, err
}
diff --git a/pkg/btrfs/io2_fs.go b/pkg/btrfs/io2_fs.go
index ca67a9c..035019c 100644
--- a/pkg/btrfs/io2_fs.go
+++ b/pkg/btrfs/io2_fs.go
@@ -175,9 +175,9 @@ func (fs *FS) Resolve(laddr LogicalAddr) (paddrs map[QualifiedPhysicalAddr]struc
maxlen = math.MaxUint64
for _, chunk := range fs.chunks {
- if chunk.Key.Offset <= uint64(laddr) && uint64(laddr) < chunk.Key.Offset+uint64(chunk.Chunk.Size) {
+ if chunk.Key.Offset <= uint64(laddr) && uint64(laddr) < chunk.Key.Offset+uint64(chunk.Chunk.Head.Size) {
offsetWithinChunk := uint64(laddr) - chunk.Key.Offset
- maxlen = util.Min(maxlen, chunk.Chunk.Size-offsetWithinChunk)
+ maxlen = util.Min(maxlen, chunk.Chunk.Head.Size-offsetWithinChunk)
for _, stripe := range chunk.Chunk.Stripes {
paddrs[QualifiedPhysicalAddr{
Dev: stripe.DeviceUUID,
diff --git a/pkg/btrfsmisc/print_tree.go b/pkg/btrfsmisc/print_tree.go
index a771b65..3211d1d 100644
--- a/pkg/btrfsmisc/print_tree.go
+++ b/pkg/btrfsmisc/print_tree.go
@@ -159,11 +159,11 @@ func PrintTree(fs *btrfs.FS, root btrfs.LogicalAddr) error {
fmt.Printf("\t\tfree space bitmap\n")
case btrfsitem.Chunk:
fmt.Printf("\t\tlength %d owner %d stripe_len %d type %v\n",
- body.Size, body.Owner, body.StripeLen, body.Type)
+ body.Head.Size, body.Head.Owner, body.Head.StripeLen, body.Head.Type)
fmt.Printf("\t\tio_align %d io_width %d sector_size %d\n",
- body.IOOptimalAlign, body.IOOptimalWidth, body.IOMinSize)
+ body.Head.IOOptimalAlign, body.Head.IOOptimalWidth, body.Head.IOMinSize)
fmt.Printf("\t\tnum_stripes %d sub_stripes %d\n",
- body.NumStripes, body.SubStripes)
+ body.Head.NumStripes, body.Head.SubStripes)
for i, stripe := range body.Stripes {
fmt.Printf("\t\t\tstripe %d devid %d offset %d\n",
i, stripe.DeviceID, stripe.Offset)