fusefs: allow the server to specify st_blksize
If the server sets fuse_attr.blksize to a nonzero value in the response to FUSE_GETATTR, then the client should use that as the value for stat.st_blksize . Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
16bd2d47c7
commit
e7f73af118
@ -198,10 +198,12 @@ fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr,
|
||||
{
|
||||
struct mount *mp;
|
||||
struct fuse_vnode_data *fvdat;
|
||||
struct fuse_data *data;
|
||||
struct vattr *vp_cache_at;
|
||||
|
||||
mp = vnode_mount(vp);
|
||||
fvdat = VTOFUD(vp);
|
||||
data = fuse_get_mpdata(mp);
|
||||
|
||||
fuse_validity_2_bintime(attr_valid, attr_valid_nsec,
|
||||
&fvdat->attr_cache_timeout);
|
||||
@ -231,7 +233,10 @@ fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr,
|
||||
vap->va_mtime.tv_nsec = attr->mtimensec;
|
||||
vap->va_ctime.tv_sec = attr->ctime;
|
||||
vap->va_ctime.tv_nsec = attr->ctimensec;
|
||||
vap->va_blocksize = PAGE_SIZE;
|
||||
if (fuse_libabi_geq(data, 7, 9) && attr->blksize > 0)
|
||||
vap->va_blocksize = attr->blksize;
|
||||
else
|
||||
vap->va_blocksize = PAGE_SIZE;
|
||||
vap->va_type = IFTOVT(attr->mode);
|
||||
vap->va_bytes = attr->blocks * S_BLKSIZE;
|
||||
vap->va_flags = 0;
|
||||
|
@ -28,6 +28,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include <sys/param.h>
|
||||
}
|
||||
|
||||
#include "mockfs.hh"
|
||||
#include "utils.hh"
|
||||
|
||||
@ -130,6 +134,35 @@ TEST_F(Getattr, attr_cache_timeout)
|
||||
EXPECT_EQ(0, stat(FULLPATH, &sb));
|
||||
}
|
||||
|
||||
/*
|
||||
* If attr.blksize is zero, then the kernel should use a default value for
|
||||
* st_blksize
|
||||
*/
|
||||
TEST_F(Getattr, blksize_zero)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
const char RELPATH[] = "some_file.txt";
|
||||
const uint64_t ino = 42;
|
||||
struct stat sb;
|
||||
|
||||
expect_lookup(RELPATH, ino, S_IFREG | 0644, 1, 1, 0, 0);
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([](auto in) {
|
||||
return (in->header.opcode == FUSE_GETATTR &&
|
||||
in->header.nodeid == ino);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([](auto i __unused, auto out) {
|
||||
SET_OUT_HEADER_LEN(out, attr);
|
||||
out->body.attr.attr.mode = S_IFREG | 0644;
|
||||
out->body.attr.attr.ino = ino; // Must match nodeid
|
||||
out->body.attr.attr.blksize = 0;
|
||||
})));
|
||||
|
||||
ASSERT_EQ(0, stat(FULLPATH, &sb)) << strerror(errno);
|
||||
EXPECT_EQ((blksize_t)PAGE_SIZE, sb.st_blksize);
|
||||
}
|
||||
|
||||
TEST_F(Getattr, enoent)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
@ -179,6 +212,7 @@ TEST_F(Getattr, ok)
|
||||
out->body.attr.attr.uid = 10;
|
||||
out->body.attr.attr.gid = 11;
|
||||
out->body.attr.attr.rdev = 12;
|
||||
out->body.attr.attr.blksize = 12345;
|
||||
})));
|
||||
|
||||
ASSERT_EQ(0, stat(FULLPATH, &sb)) << strerror(errno);
|
||||
@ -194,6 +228,7 @@ TEST_F(Getattr, ok)
|
||||
EXPECT_EQ(10ul, sb.st_uid);
|
||||
EXPECT_EQ(11ul, sb.st_gid);
|
||||
EXPECT_EQ(12ul, sb.st_rdev);
|
||||
EXPECT_EQ((blksize_t)12345, sb.st_blksize);
|
||||
EXPECT_EQ(ino, sb.st_ino);
|
||||
EXPECT_EQ(S_IFREG | 0644, sb.st_mode);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user