From b989917f75233642a4f3abe3dfcabe933cde4149 Mon Sep 17 00:00:00 2001 From: masahiro331 Date: Wed, 28 Dec 2022 11:01:56 +0900 Subject: [PATCH 1/4] feat(xfs): change xfs reader interface io.ReadSeeker to io.ReaderAt --- xfs/inode.go | 30 +++++------------------------ xfs/xfs.go | 54 +++++++++++++++++++++++++--------------------------- 2 files changed, 31 insertions(+), 53 deletions(-) diff --git a/xfs/inode.go b/xfs/inode.go index b2cf43f..148983e 100644 --- a/xfs/inode.go +++ b/xfs/inode.go @@ -10,7 +10,6 @@ import ( "golang.org/x/xerrors" "github.com/masahiro331/go-xfs-filesystem/log" - "github.com/masahiro331/go-xfs-filesystem/xfs/utils" ) var ( @@ -469,14 +468,9 @@ func (xfs *FileSystem) ParseInode(ino uint64) (*Inode, error) { } } - _, err := xfs.seekInode(ino) + buf, err := xfs.readInode(ino) if err != nil { - return nil, xerrors.Errorf("failed to seek inode: %w", err) - } - - buf, err := utils.ReadSector(xfs.r) - if err != nil { - return nil, xerrors.Errorf("failed to read sector: %w", err) + return nil, xerrors.Errorf("failed to read inode: %w", err) } r := bytes.NewReader(buf) @@ -543,11 +537,7 @@ func (xfs *FileSystem) parseBtreeBlock(r io.Reader) (*BtreeBlock, error) { func (xfs *FileSystem) parseBtreeNode(blockNumber int64, inode Inode) ([]BmbtKey, []BmbtPtr, error) { physicalBlockOffset := xfs.PrimaryAG.SuperBlock.BlockToPhysicalOffset(uint64(blockNumber)) - _, err := xfs.seekBlock(physicalBlockOffset) - if err != nil { - return nil, nil, xerrors.Errorf("failed to seek block: %w", err) - } - b, err := xfs.readBlock(1) + b, err := xfs.readBlockAt(physicalBlockOffset) if err != nil { return nil, nil, xerrors.Errorf("failed to read block: %w", err) } @@ -567,11 +557,7 @@ func (xfs *FileSystem) parseBtreeNode(blockNumber int64, inode Inode) ([]BmbtKey func (xfs *FileSystem) parseBtreeLeafNode(blockNumber int64) ([]BmbtRec, error) { physicalBlockOffset := xfs.PrimaryAG.SuperBlock.BlockToPhysicalOffset(uint64(blockNumber)) - _, err := xfs.seekBlock(physicalBlockOffset) - if err != nil { - return nil, xerrors.Errorf("failed to seek block: %w", err) - } - b, err := xfs.readBlock(1) + b, err := xfs.readBlockAt(physicalBlockOffset) if err != nil { return nil, xerrors.Errorf("failed to read block: %w", err) } @@ -726,13 +712,7 @@ func (xfs *FileSystem) parseDir2Block(bmbtIrec BmbtIrec) (*Dir2Block, error) { } physicalBlockOffset := xfs.PrimaryAG.SuperBlock.BlockToPhysicalOffset(bmbtIrec.StartBlock) - _, err := xfs.seekBlock(physicalBlockOffset) - if err != nil { - return nil, xerrors.Errorf("failed to seek block: %w", err) - } - - // TODO: add tests, If Block count greater than 2 - b, err := utils.ReadBlock(xfs.r) + b, err := xfs.readBlockAt(physicalBlockOffset) if err != nil { return nil, xerrors.Errorf("failed to read block: %w", err) } diff --git a/xfs/xfs.go b/xfs/xfs.go index c9d2b17..6d94c42 100644 --- a/xfs/xfs.go +++ b/xfs/xfs.go @@ -2,6 +2,7 @@ package xfs import ( "bytes" + "fmt" "io" "io/fs" "path" @@ -34,7 +35,7 @@ var ( // FileSystem is implemented io/fs FS interface type FileSystem struct { - r *io.SectionReader + r io.ReaderAt PrimaryAG AG AGs []AG @@ -228,39 +229,40 @@ func (xfs *FileSystem) Open(name string) (fs.File, error) { return nil, fs.ErrNotExist } -func (xfs *FileSystem) seekInode(n uint64) (int64, error) { +func (xfs *FileSystem) readInode(n uint64) ([]byte, error) { offset := int64(xfs.PrimaryAG.SuperBlock.InodeAbsOffset(n)) - off, err := xfs.r.Seek(offset, io.SeekStart) - if err != nil { - return 0, err - } - if off != offset { - return 0, xerrors.Errorf(ErrSeekOffsetFormat, off, offset) - } - return off, nil -} -func (xfs *FileSystem) seekBlock(n int64) (int64, error) { - offset := n * int64(xfs.PrimaryAG.SuperBlock.BlockSize) - off, err := xfs.r.Seek(offset, io.SeekStart) + buf := make([]byte, utils.SectorSize) + off, err := xfs.r.ReadAt(buf, offset) if err != nil { - return 0, err + return nil, err } - if off != offset { - return 0, xerrors.Errorf(ErrSeekOffsetFormat, off, offset) + if int64(off) != offset { + return nil, xerrors.Errorf(ErrReadSizeFormat, off, offset) } - return off, nil + return buf, nil } -func (xfs *FileSystem) readBlock(count uint32) ([]byte, error) { - buf := make([]byte, 0, xfs.PrimaryAG.SuperBlock.BlockSize*count) - for i := uint32(0); i < count; i++ { - b, err := utils.ReadBlock(xfs.r) +func (xfs *FileSystem) readBlockAt(n int64) ([]byte, error) { + + buf := make([]byte, 4096) + for i := 0; i < utils.BlockSize/utils.SectorSize; i++ { + offset := n*int64(xfs.PrimaryAG.SuperBlock.BlockSize) + int64(i*utils.SectorSize) + b := make([]byte, utils.SectorSize) + i, err := xfs.r.ReadAt(b, offset) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to read: %w", err) + } + if i != utils.SectorSize { + return nil, fmt.Errorf("failed to read sector invalid size expected(%d), actual(%d)", utils.SectorSize, i) } buf = append(buf, b...) } + + if len(buf) != utils.BlockSize { + return nil, fmt.Errorf("block size error, expected(%d), actual(%d)", utils.BlockSize, len(buf)) + } + return buf, nil } @@ -469,11 +471,7 @@ func (f *File) Read(buf []byte) (int, error) { } f.buffer.Write(make([]byte, f.blockSize)) } else { - _, err := f.fs.seekBlock(offset) - if err != nil { - return 0, xerrors.Errorf("failed to seek block: %w", err) - } - b, err := f.fs.readBlock(1) + b, err := f.fs.readBlockAt(offset) if err != nil { return 0, xerrors.Errorf("failed to read block: %w", err) } From 919db29df1b2994c97b174f2d61594df19528d83 Mon Sep 17 00:00:00 2001 From: masahiro331 Date: Thu, 29 Dec 2022 03:10:44 +0900 Subject: [PATCH 2/4] fix read block bytes... --- xfs/xfs.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/xfs/xfs.go b/xfs/xfs.go index 6d94c42..f3d8841 100644 --- a/xfs/xfs.go +++ b/xfs/xfs.go @@ -209,7 +209,6 @@ func (xfs *FileSystem) Open(name string) (fs.File, error) { if err != nil { return nil, xfs.wrapError(op, name, xerrors.Errorf("railed to read directory: %w", err)) } - for _, entry := range dirEntries { if !entry.IsDir() && entry.Name() == fileName { if dir, ok := entry.(dirEntry); ok { @@ -237,7 +236,7 @@ func (xfs *FileSystem) readInode(n uint64) ([]byte, error) { if err != nil { return nil, err } - if int64(off) != offset { + if int64(off) != utils.SectorSize { return nil, xerrors.Errorf(ErrReadSizeFormat, off, offset) } return buf, nil @@ -245,7 +244,7 @@ func (xfs *FileSystem) readInode(n uint64) ([]byte, error) { func (xfs *FileSystem) readBlockAt(n int64) ([]byte, error) { - buf := make([]byte, 4096) + var buf []byte for i := 0; i < utils.BlockSize/utils.SectorSize; i++ { offset := n*int64(xfs.PrimaryAG.SuperBlock.BlockSize) + int64(i*utils.SectorSize) b := make([]byte, utils.SectorSize) From 7431d5e7cb2260013fc4fd5c91ef30af9544747e Mon Sep 17 00:00:00 2001 From: masahiro331 Date: Thu, 29 Dec 2022 04:01:57 +0900 Subject: [PATCH 3/4] feat: change to thread_safe library --- xfs/ag.go | 12 ++++++++---- xfs/utils/utils.go | 21 +++++++++++++++++++++ xfs/xfs.go | 15 ++++----------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/xfs/ag.go b/xfs/ag.go index 9541b49..9718bea 100644 --- a/xfs/ag.go +++ b/xfs/ag.go @@ -125,17 +125,21 @@ func parseSuperBlock(r io.Reader) (SuperBlock, error) { return sb, nil } -func ParseAG(reader io.Reader) (*AG, error) { - r := io.LimitReader(reader, int64(utils.BlockSize)) - +func ParseAG(reader io.ReaderAt, offset int64) (*AG, error) { var ag AG var err error + buf, err := utils.ReadBlockAt(reader, offset) + if err != nil { + return nil, xerrors.Errorf("failed to read super block", err) + } + + r := bytes.NewReader(buf) ag.SuperBlock, err = parseSuperBlock(r) if err != nil { return nil, xerrors.Errorf("failed to parse super block: %w", err) } - buf, err := utils.ReadSector(r) + buf, err = utils.ReadSector(r) if err != nil { return nil, xerrors.Errorf("failed to create afg reader: %w", err) } diff --git a/xfs/utils/utils.go b/xfs/utils/utils.go index 523f7b3..d396f94 100644 --- a/xfs/utils/utils.go +++ b/xfs/utils/utils.go @@ -33,6 +33,27 @@ func ReadBlock(r io.Reader) ([]byte, error) { return buf, nil } +func ReadBlockAt(r io.ReaderAt, offset int64) ([]byte, error) { + buf := make([]byte, 0, BlockSize) + for i := 0; i < BlockSize/SectorSize; i++ { + b := make([]byte, SectorSize) + i, err := r.ReadAt(b, offset+int64(i)*SectorSize) + if err != nil { + return nil, xerrors.Errorf("failed to read: %w", err) + } + if i != 512 { + return nil, fmt.Errorf("failed to read sector invalid size expected(%d), actual(%d)", SectorSize, i) + } + buf = append(buf, b...) + } + + if len(buf) != BlockSize { + return nil, fmt.Errorf("block size error, expected(%d), actual(%d)", BlockSize, len(buf)) + } + + return buf, nil +} + func ReadSector(r io.Reader) ([]byte, error) { buf := make([]byte, SectorSize) i, err := r.Read(buf) diff --git a/xfs/xfs.go b/xfs/xfs.go index f3d8841..fcc245f 100644 --- a/xfs/xfs.go +++ b/xfs/xfs.go @@ -50,8 +50,8 @@ func Check(r io.Reader) bool { return true } -func NewFS(r io.SectionReader, cache Cache[string, any]) (*FileSystem, error) { - primaryAG, err := ParseAG(&r) +func NewFS(r io.ReaderAt, cache Cache[string, any]) (*FileSystem, error) { + primaryAG, err := ParseAG(r, 0) if err != nil { return nil, xerrors.Errorf("failed to parse primary allocation group: %w", err) } @@ -60,7 +60,7 @@ func NewFS(r io.SectionReader, cache Cache[string, any]) (*FileSystem, error) { cache = &mockCache[string, any]{} } fileSystem := FileSystem{ - r: &r, + r: r, PrimaryAG: *primaryAG, AGs: []AG{*primaryAG}, cache: cache, @@ -68,14 +68,7 @@ func NewFS(r io.SectionReader, cache Cache[string, any]) (*FileSystem, error) { AGSize := int64(primaryAG.SuperBlock.Agblocks) * int64(primaryAG.SuperBlock.BlockSize) for i := int64(1); i < int64(primaryAG.SuperBlock.Agcount); i++ { - n, err := r.Seek(AGSize*i, 0) - if err != nil { - return nil, xerrors.Errorf("failed to seek file: %w", err) - } - if n != AGSize*i { - return nil, xerrors.Errorf(ErrSeekOffsetFormat, n, AGSize*i) - } - ag, err := ParseAG(&r) + ag, err := ParseAG(r, AGSize*i) if err != nil { return nil, xerrors.Errorf("failed to parse allocation group %d: %w", i, err) } From 9c81996768fe2d9e48b3032ea7a750baa1ca78c5 Mon Sep 17 00:00:00 2001 From: masahiro331 Date: Thu, 29 Dec 2022 10:23:35 +0900 Subject: [PATCH 4/4] fix test --- xfs/inode_test.go | 7 +------ xfs/xfs_test.go | 24 ++++-------------------- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/xfs/inode_test.go b/xfs/inode_test.go index fc03f87..b28c476 100644 --- a/xfs/inode_test.go +++ b/xfs/inode_test.go @@ -2,7 +2,6 @@ package xfs import ( "fmt" - "io" "os" "strings" "testing" @@ -77,12 +76,8 @@ func TestParseInode(t *testing.T) { if err != nil { t.Fatal(err) } - info, err := f.Stat() - if err != nil { - t.Fatal(err) - } - fileSystem, err := NewFS(*io.NewSectionReader(f, 0, info.Size()), nil) + fileSystem, err := NewFS(f, nil) if err != nil { t.Fatal(err) } diff --git a/xfs/xfs_test.go b/xfs/xfs_test.go index 0b46ceb..ab7b62e 100644 --- a/xfs/xfs_test.go +++ b/xfs/xfs_test.go @@ -57,12 +57,8 @@ func TestFileSystemCheckFileExtents(t *testing.T) { if err != nil { t.Fatal(err) } - info, err := f.Stat() - if err != nil { - t.Fatal(err) - } - fileSystem, err := xfs.NewFS(*io.NewSectionReader(f, 0, info.Size()), nil) + fileSystem, err := xfs.NewFS(f, nil) if err != nil { t.Fatal(err) } @@ -137,12 +133,8 @@ func TestFileSystemCheckWalkDir(t *testing.T) { if err != nil { t.Fatal(err) } - info, err := f.Stat() - if err != nil { - t.Fatal(err) - } - fileSystem, err := xfs.NewFS(*io.NewSectionReader(f, 0, info.Size()), nil) + fileSystem, err := xfs.NewFS(f, nil) if err != nil { t.Fatal(err) } @@ -220,12 +212,8 @@ func TestFileSystemCheckReadDir(t *testing.T) { if err != nil { t.Fatal(err) } - info, err := f.Stat() - if err != nil { - t.Fatal(err) - } - fileSystem, err := xfs.NewFS(*io.NewSectionReader(f, 0, info.Size()), nil) + fileSystem, err := xfs.NewFS(f, nil) if err != nil { t.Fatal(err) } @@ -259,12 +247,8 @@ func TestFileSystemCheckReadFile(t *testing.T) { if err != nil { t.Fatal(err) } - info, err := f.Stat() - if err != nil { - t.Fatal(err) - } - fileSystem, err := xfs.NewFS(*io.NewSectionReader(f, 0, info.Size()), nil) + fileSystem, err := xfs.NewFS(f, nil) if err != nil { t.Fatal(err) }