Skip to content

Commit

Permalink
fuse: Report fuse.Attr.Blocks correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
greatroar committed Mar 7, 2023
1 parent a7786c6 commit 8aa104f
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 3 deletions.
11 changes: 11 additions & 0 deletions changelog/unreleased/issue-4239
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Bugfix: Correct number of blocks reported in mount point

Restic mount points incorrectly reported the number of 512-byte (POSIX
standard) blocks for files and links, due to a rounding bug. In particular,
empty files were reported as taking one block instead of zero.

The rounding is now fixed: the number of blocks reported is the file size
(or link target size), divided by 512 and rounded up to a whole number.

https://github.com/restic/restic/issues/4239
https://github.com/restic/restic/pull/4240
2 changes: 1 addition & 1 deletion internal/fuse/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (f *file) Attr(ctx context.Context, a *fuse.Attr) error {
a.Inode = f.inode
a.Mode = f.node.Mode
a.Size = f.node.Size
a.Blocks = (f.node.Size / blockSize) + 1
a.Blocks = (f.node.Size + blockSize - 1) / blockSize
a.BlockSize = blockSize
a.Nlink = uint32(f.node.Links)

Expand Down
31 changes: 31 additions & 0 deletions internal/fuse/fuse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"math/rand"
"os"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -216,6 +217,36 @@ func testTopUIDGID(t *testing.T, cfg Config, repo restic.Repository, uid, gid ui
rtest.Equals(t, uint32(0), attr.Gid)
}

// Test reporting of fuse.Attr.Blocks in multiples of 512.
func TestBlocks(t *testing.T) {
root := &Root{}

for _, c := range []struct {
size, blocks uint64
}{
{0, 0},
{1, 1},
{511, 1},
{512, 1},
{513, 2},
{1024, 2},
{1025, 3},
{6982535, 13638},
} {
target := strings.Repeat("x", int(c.size))

for _, n := range []fs.Node{
&file{root: root, node: &restic.Node{Size: uint64(c.size)}},
&link{root: root, node: &restic.Node{LinkTarget: target}},
&snapshotLink{root: root, snapshot: &restic.Snapshot{}, target: target},
} {
var a fuse.Attr
n.Attr(context.TODO(), &a)
rtest.Equals(t, c.blocks, a.Blocks)
}
}
}

func TestInodeFromNode(t *testing.T) {
node := &restic.Node{Name: "foo.txt", Type: "chardev", Links: 2}
ino1 := inodeFromNode(1, node)
Expand Down
2 changes: 1 addition & 1 deletion internal/fuse/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (l *link) Attr(ctx context.Context, a *fuse.Attr) error {

a.Nlink = uint32(l.node.Links)
a.Size = uint64(len(l.node.LinkTarget))
a.Blocks = 1 + a.Size/blockSize
a.Blocks = (a.Size + blockSize - 1) / blockSize

return nil
}
2 changes: 1 addition & 1 deletion internal/fuse/snapshots_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (l *snapshotLink) Attr(ctx context.Context, a *fuse.Attr) error {
a.Inode = l.inode
a.Mode = os.ModeSymlink | 0777
a.Size = uint64(len(l.target))
a.Blocks = 1 + a.Size/blockSize
a.Blocks = (a.Size + blockSize - 1) / blockSize
a.Uid = l.root.uid
a.Gid = l.root.gid
a.Atime = l.snapshot.Time
Expand Down

0 comments on commit 8aa104f

Please sign in to comment.