Skip to content

Commit

Permalink
Linux 4.11 compat: statx support
Browse files Browse the repository at this point in the history
Linux 4.11 added a new statx system call that allows us to expose crtime
as btime. We do this by caching crtime in the znode to match how atime,
ctime and mtime are cached in the inode.

statx also introduced a new way of reporting whether the immutable,
append and nodump bits have been set. It adds support for reporting
compression and encryption, but the semantics on other filesystems is
not just to report compression/encryption, but to allow it to be turned
on/off at the file level. We do not support that.

We could implement semantics where we refuse to allow user modification
of the bit, but we would need to do a dnode_hold() in zfs_znode_alloc()
to find out encryption/compression information. That would introduce
locking that will have a minor (although unmeasured) performance cost.
It also would be inferior to zdb, which reports far more detailed
information. We therefore omit reporting of encryption/compression
through statx in favor of recommending that users interested in such
information use zdb.

Signed-off-by: Richard Yao <ryao@gentoo.org>
Closes openzfs#8507
  • Loading branch information
ryao authored and Ryan Moeller committed Jul 26, 2021
1 parent 1b06b03 commit b440369
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
9 changes: 7 additions & 2 deletions include/os/linux/zfs/sys/zfs_znode_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,25 @@
#include <sys/list.h>
#include <sys/dmu.h>
#include <sys/sa.h>
#include <sys/time.h>
#include <sys/zfs_vfsops.h>
#include <sys/rrwlock.h>
#include <sys/zfs_sa.h>
#include <sys/zfs_stat.h>
#include <sys/zfs_rlock.h>


#ifdef __cplusplus
extern "C" {
#endif

#ifdef STATX_BTIME
#define ZNODE_OS_FIELDS \
inode_timespec_t z_btime; /* creation/birth time (cached) */ \
struct inode z_inode;

#else
#define ZNODE_OS_FIELDS \
struct inode z_inode;
#endif

/*
* Convert between znode pointers and inode pointers
Expand Down
24 changes: 23 additions & 1 deletion module/os/linux/zfs/zfs_znode.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,12 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
uint64_t z_uid, z_gid;
uint64_t atime[2], mtime[2], ctime[2];
uint64_t projid = ZFS_DEFAULT_PROJID;
#ifdef STATX_BTIME
uint64_t btime[2];
sa_bulk_attr_t bulk[12];
#else
sa_bulk_attr_t bulk[11];
#endif
int count = 0;

ASSERT(zfsvfs != NULL);
Expand Down Expand Up @@ -569,6 +574,9 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL, &atime, 16);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
#ifdef STATX_BTIME
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zfsvfs), NULL, &btime, 16);
#endif

if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || tmp_gen == 0 ||
(dmu_objset_projectquota_enabled(zfsvfs->z_os) &&
Expand Down Expand Up @@ -596,6 +604,9 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
ZFS_TIME_DECODE(&ip->i_atime, atime);
ZFS_TIME_DECODE(&ip->i_mtime, mtime);
ZFS_TIME_DECODE(&ip->i_ctime, ctime);
#ifdef STATX_BTIME
ZFS_TIME_DECODE(&zp->z_btime, btime);
#endif

ip->i_ino = zp->z_id;
zfs_znode_update_vfs(zp);
Expand Down Expand Up @@ -1169,13 +1180,18 @@ zfs_rezget(znode_t *zp)
uint64_t obj_num = zp->z_id;
uint64_t mode;
uint64_t links;
sa_bulk_attr_t bulk[10];
int err;
int count = 0;
uint64_t gen;
uint64_t z_uid, z_gid;
uint64_t atime[2], mtime[2], ctime[2];
uint64_t projid = ZFS_DEFAULT_PROJID;
#ifdef STATX_BTIME
uint64_t btime[2];
sa_bulk_attr_t bulk[11];
#else
sa_bulk_attr_t bulk[10];
#endif
znode_hold_t *zh;

/*
Expand Down Expand Up @@ -1244,6 +1260,9 @@ zfs_rezget(znode_t *zp)
&mtime, 16);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
&ctime, 16);
#ifdef STATX_BTIME
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zfsvfs), NULL, &btime, 16);
#endif

if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) {
zfs_znode_dmu_fini(zp);
Expand All @@ -1269,6 +1288,9 @@ zfs_rezget(znode_t *zp)
ZFS_TIME_DECODE(&ZTOI(zp)->i_atime, atime);
ZFS_TIME_DECODE(&ZTOI(zp)->i_mtime, mtime);
ZFS_TIME_DECODE(&ZTOI(zp)->i_ctime, ctime);
#ifdef STATX_BTIME
ZFS_TIME_DECODE(&zp->z_btime, btime);
#endif

if ((uint32_t)gen != ZTOI(zp)->i_generation) {
zfs_znode_dmu_fini(zp);
Expand Down
29 changes: 27 additions & 2 deletions module/os/linux/zfs/zpl_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
{
int error;
fstrans_cookie_t cookie;
struct inode *ip = path->dentry->d_inode;

cookie = spl_fstrans_mark();

Expand All @@ -386,10 +387,34 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
*/

#ifdef HAVE_USERNS_IOPS_GETATTR
error = -zfs_getattr_fast(user_ns, path->dentry->d_inode, stat);
error = -zfs_getattr_fast(user_ns, ip, stat);
#else
error = -zfs_getattr_fast(kcred->user_ns, path->dentry->d_inode, stat);
error = -zfs_getattr_fast(kcred->user_ns, ip, stat);
#endif

#ifdef STATX_BTIME
stat->btime = ITOZ(ip)->z_btime;
stat->result_mask |= STATX_BTIME;
#endif

#ifdef STATX_ATTR_IMMUTABLE
if (zfs_flags & ZFS_IMMUTABLE)
stat->attributes |= STATX_ATTR_IMMUTABLE;
stat->attributes_mask |= STATX_ATTR_IMMUTABLE;
#endif

#ifdef STATX_ATTR_APPEND
if (zfs_flags & ZFS_APPENDONLY)
stat->attributes |= STATX_ATTR_APPEND;
stat->attributes_mask |= STATX_ATTR_APPEND;
#endif

#ifdef STATX_ATTR_NODUMP
if (zfs_flags & ZFS_NODUMP)
stat->attributes |= STATX_ATTR_NODUMP;
stat->attributes_mask |= STATX_ATTR_NODUMP;
#endif

spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);

Expand Down

0 comments on commit b440369

Please sign in to comment.