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

feature: thread safe #1

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
12 changes: 8 additions & 4 deletions xfs/ag.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
30 changes: 5 additions & 25 deletions xfs/inode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down
7 changes: 1 addition & 6 deletions xfs/inode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package xfs

import (
"fmt"
"io"
"os"
"strings"
"testing"
Expand Down Expand Up @@ -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)
}
Expand Down
21 changes: 21 additions & 0 deletions xfs/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
70 changes: 30 additions & 40 deletions xfs/xfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package xfs

import (
"bytes"
"fmt"
"io"
"io/fs"
"path"
Expand Down Expand Up @@ -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

Expand All @@ -49,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)
}
Expand All @@ -59,22 +60,15 @@ 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,
}

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)
}
Expand Down Expand Up @@ -208,7 +202,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 {
Expand All @@ -228,39 +221,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) != utils.SectorSize {
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) {

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)
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
}

Expand Down Expand Up @@ -469,11 +463,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)
}
Expand Down
24 changes: 4 additions & 20 deletions xfs/xfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down