2
2
mirror of https://github.com/octoleo/restic.git synced 2024-12-22 10:58:55 +00:00

fuse: Report fuse.Attr.Blocks correctly

Fixes #4239.
This commit is contained in:
greatroar 2023-03-07 22:12:08 +01:00 committed by Michael Eischer
parent 593eb710b4
commit 4304e01ca2
5 changed files with 46 additions and 3 deletions

View File

@ -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

View File

@ -50,7 +50,7 @@ func (f *file) Attr(ctx context.Context, a *fuse.Attr) error {
a.Inode = f.inode a.Inode = f.inode
a.Mode = f.node.Mode a.Mode = f.node.Mode
a.Size = f.node.Size a.Size = f.node.Size
a.Blocks = (f.node.Size / blockSize) + 1 a.Blocks = (f.node.Size + blockSize - 1) / blockSize
a.BlockSize = blockSize a.BlockSize = blockSize
a.Nlink = uint32(f.node.Links) a.Nlink = uint32(f.node.Links)

View File

@ -8,6 +8,7 @@ import (
"context" "context"
"math/rand" "math/rand"
"os" "os"
"strings"
"testing" "testing"
"time" "time"
@ -216,6 +217,37 @@ func testTopUIDGID(t *testing.T, cfg Config, repo restic.Repository, uid, gid ui
rtest.Equals(t, uint32(0), attr.Gid) 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},
{41253, 81},
} {
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
err := n.Attr(context.TODO(), &a)
rtest.OK(t, err)
rtest.Equals(t, c.blocks, a.Blocks)
}
}
}
func TestInodeFromNode(t *testing.T) { func TestInodeFromNode(t *testing.T) {
node := &restic.Node{Name: "foo.txt", Type: "chardev", Links: 2} node := &restic.Node{Name: "foo.txt", Type: "chardev", Links: 2}
ino1 := inodeFromNode(1, node) ino1 := inodeFromNode(1, node)

View File

@ -42,7 +42,7 @@ func (l *link) Attr(ctx context.Context, a *fuse.Attr) error {
a.Nlink = uint32(l.node.Links) a.Nlink = uint32(l.node.Links)
a.Size = uint64(len(l.node.LinkTarget)) a.Size = uint64(len(l.node.LinkTarget))
a.Blocks = 1 + a.Size/blockSize a.Blocks = (a.Size + blockSize - 1) / blockSize
return nil return nil
} }

View File

@ -142,7 +142,7 @@ func (l *snapshotLink) Attr(ctx context.Context, a *fuse.Attr) error {
a.Inode = l.inode a.Inode = l.inode
a.Mode = os.ModeSymlink | 0777 a.Mode = os.ModeSymlink | 0777
a.Size = uint64(len(l.target)) 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.Uid = l.root.uid
a.Gid = l.root.gid a.Gid = l.root.gid
a.Atime = l.snapshot.Time a.Atime = l.snapshot.Time