[COMMIT osv master] zfs: avoid f_fsid sign extension when translating f_fsid to va_fsid

2 views
Skip to first unread message

Commit Bot

unread,
Apr 27, 2020, 9:36:14 PM4/27/20
to osv...@googlegroups.com, Waldemar Kozaczuk
From: Waldemar Kozaczuk <jwkoz...@gmail.com>
Committer: Waldemar Kozaczuk <jwkoz...@gmail.com>
Branch: master

zfs: avoid f_fsid sign extension when translating f_fsid to va_fsid

This would have been a cosmetic change except in future patches
we rely on full value of f_fsid field including higher 32 bits in order to
determine type of the file system.

Before this patch if lower 32 bits of f_fsid (stored as signed int)
represented negative number, it would lead to overwriting higher 32 bits
when translating to va_fsid in zfs_getattr() function.

For example if f_fsid was composed like this:

lower 32-bits: 0x9a16baf6
higher 32-bits: 0x06567a36

before this patch the resulting va_fsid would be translated as:
0xffffffff9a16baf6

where we lose the high 32 bits of f_fsid.

With this patch va_fsid would look like this:
0x06567a369a16baf6

This patch is loosely similar to the patch applied 3 years ago
to the original ZFS source tree in FreeBSD - https://github.com/freebsd/freebsd/commit/0a0bd3828b5387a70d59645d9aee559c60ca77a5

Signed-off-by: Waldemar Kozaczuk <jwkoz...@gmail.com>

---
diff --git a/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
--- a/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -2041,6 +2041,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap)
xoptattr_t *xoap = NULL;
sa_bulk_attr_t bulk[4];
int count = 0;
+ fsid_t *fsid;

ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
@@ -2068,8 +2069,8 @@ zfs_getattr(vnode_t *vp, vattr_t *vap)
#ifdef sun
vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev;
#else
- vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_fsid.__val[0] |
- ((dev_t) zp->z_zfsvfs->z_vfs->vfs_fsid.__val[1] << 32);
+ fsid = &zp->z_zfsvfs->z_vfs->vfs_fsid;
+ vap->va_fsid = ((uint32_t)fsid->__val[0]) | ((dev_t) ((uint32_t)fsid->__val[1]) << 32);
#endif
vap->va_nodeid = zp->z_id;
if ((vp->v_flags & VROOT) && zfs_show_ctldir(zp))
diff --git a/tests/tst-zfs-mount.cc b/tests/tst-zfs-mount.cc
--- a/tests/tst-zfs-mount.cc
+++ b/tests/tst-zfs-mount.cc
@@ -173,8 +173,8 @@ int main(int argc, char **argv)

printf("file size = %lld\n", s.st_size);

- report((((dev_t) st.f_fsid.__val[1] << 32) | st.f_fsid.__val[0]) == s.st_dev,
- "st_dev must be equals to f_fsid");
+ dev_t f_fsid = ((uint32_t)st.f_fsid.__val[0]) | ((dev_t) ((uint32_t)st.f_fsid.__val[1]) << 32);
+ report(f_fsid == s.st_dev, "st_dev must be equals to f_fsid");

report(close(fd) == 0, "close fd");

Reply all
Reply to author
Forward
0 new messages