Skip to content

Commit

Permalink
fix(dir2block): support multi block entry
Browse files Browse the repository at this point in the history
  • Loading branch information
masahiro331 committed Jun 2, 2023
1 parent 5de2c34 commit 0642252
Showing 1 changed file with 22 additions and 30 deletions.
52 changes: 22 additions & 30 deletions xfs/inode.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,63 +741,55 @@ func (xfs *FileSystem) parseDir2Block(bmbtIrec BmbtIrec) ([]Dir2DataEntry, error

var buf []byte
for blockOffset := bmbtIrec.StartBlock; blockOffset < bmbtIrec.StartBlock+bmbtIrec.BlockCount; blockOffset++ {
blockData, err := xfs.readBlockFromLogicalBlockOffset(blockOffset)
physicalBlockOffset := xfs.PrimaryAG.SuperBlock.BlockToPhysicalOffset(blockOffset)
_, err := xfs.seekBlock(physicalBlockOffset)
if err != nil {
return nil, xerrors.Errorf("failed to read block from logical block offset: %w", err)
return nil, xerrors.Errorf("failed to seek block: %w", err)
}
blockData, err := utils.ReadBlock(xfs.r)
if err != nil {
return nil, xerrors.Errorf("failed to read block: %w", err)
}
buf = append(buf, blockData...)

// if the next block is not a leader, it is a continuation of the current block.
if blockOffset == bmbtIrec.StartBlock+bmbtIrec.BlockCount-1 &&
!xfs.nextBlockIsLeader(blockOffset) {
// if the next block is not a leader, it is a continuation of the previous block
if blockOffset != bmbtIrec.StartBlock+bmbtIrec.BlockCount-1 && // not last block
!xfs.nextBlockIsLeader(blockOffset) { // not leader
continue
}

magicBytes := binary.BigEndian.Uint32(blockData[:4])
reader := bytes.NewReader(blockData)
// if the next block is a leader, it is the last block of the directory
magicBytes := binary.BigEndian.Uint32(buf[:4])
reader := bytes.NewReader(buf)
if err := binary.Read(reader, binary.BigEndian, &block.Header); err != nil {
return nil, xerrors.Errorf("failed to parse dir3 data header error: %w", err)
}
switch magicBytes {
case XFS_DIR3_DATA_MAGIC:
if err := binary.Read(reader, binary.BigEndian, &block.Header); err != nil {
return nil, xerrors.Errorf("failed to parse dir3 data header error: %w", err)
}
entries, err := xfs.parseXDD3Block(reader)
if err != nil {
return nil, xerrors.Errorf("failed to parse XDD3 block: %w", err)
}
block.Entries = append(block.Entries, entries...)
buf = []byte{}

case XFS_DIR3_BLOCK_MAGIC:
if err := binary.Read(reader, binary.BigEndian, &block.Header); err != nil {
return nil, xerrors.Errorf("failed to parse dir3 block header error: %w", err)
}
entries, err := xfs.parseXDB3Block(reader)
if err != nil {
return nil, xerrors.Errorf("failed to parse XDB3 block: %w", err)
}
block.Entries = append(block.Entries, entries...)
buf = []byte{}
default:
return nil, xerrors.Errorf("unknown magic bytes: %x", magicBytes)
}

// reset buf
buf = []byte{}
}

return block.Entries, nil
}

func (xfs *FileSystem) readBlockFromLogicalBlockOffset(n uint64) ([]byte, error) {
physicalBlockOffset := xfs.PrimaryAG.SuperBlock.BlockToPhysicalOffset(n)
_, err := xfs.seekBlock(physicalBlockOffset)
if err != nil {
return nil, xerrors.Errorf("failed to seek block: %w", err)
}
blockData, err := utils.ReadBlock(xfs.r)
if err != nil {
return nil, xerrors.Errorf("failed to read block: %w", err)
}
return blockData, nil
}

func (xfs *FileSystem) nextBlockIsLeader(blockOffset uint64) bool {
physicalBlockOffset := xfs.PrimaryAG.SuperBlock.BlockToPhysicalOffset(blockOffset - 1)
physicalBlockOffset := xfs.PrimaryAG.SuperBlock.BlockToPhysicalOffset(blockOffset + 1)
xfs.seekBlock(physicalBlockOffset)
blockData, _ := utils.ReadBlock(xfs.r)

Expand Down

0 comments on commit 0642252

Please sign in to comment.