diff --git a/include/os/linux/zfs/sys/zfs_znode_impl.h b/include/os/linux/zfs/sys/zfs_znode_impl.h index be211c5b51..0a6273442b 100644 --- a/include/os/linux/zfs/sys/zfs_znode_impl.h +++ b/include/os/linux/zfs/sys/zfs_znode_impl.h @@ -36,21 +36,21 @@ #include #include #include +#include #include #include #include #include #include - #ifdef __cplusplus extern "C" { #endif #define ZNODE_OS_FIELDS \ + inode_timespec_t z_btime; /* creation/birth time (cached) */ \ struct inode z_inode; - /* * Convert between znode pointers and inode pointers */ diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c index 3c6d68fc6b..c841cc0fc8 100644 --- a/module/os/linux/zfs/zfs_znode.c +++ b/module/os/linux/zfs/zfs_znode.c @@ -525,9 +525,9 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz, uint64_t tmp_gen; uint64_t links; uint64_t z_uid, z_gid; - uint64_t atime[2], mtime[2], ctime[2]; + uint64_t atime[2], mtime[2], ctime[2], btime[2]; uint64_t projid = ZFS_DEFAULT_PROJID; - sa_bulk_attr_t bulk[11]; + sa_bulk_attr_t bulk[12]; int count = 0; ASSERT(zfsvfs != NULL); @@ -569,6 +569,7 @@ 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); + SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zfsvfs), NULL, &btime, 16); if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || tmp_gen == 0 || (dmu_objset_projectquota_enabled(zfsvfs->z_os) && @@ -596,6 +597,7 @@ 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); + ZFS_TIME_DECODE(&zp->z_btime, btime); ip->i_ino = zp->z_id; zfs_znode_update_vfs(zp); @@ -1169,12 +1171,12 @@ zfs_rezget(znode_t *zp) uint64_t obj_num = zp->z_id; uint64_t mode; uint64_t links; - sa_bulk_attr_t bulk[10]; + sa_bulk_attr_t bulk[11]; int err; int count = 0; uint64_t gen; uint64_t z_uid, z_gid; - uint64_t atime[2], mtime[2], ctime[2]; + uint64_t atime[2], mtime[2], ctime[2], btime[2]; uint64_t projid = ZFS_DEFAULT_PROJID; znode_hold_t *zh; @@ -1244,6 +1246,7 @@ zfs_rezget(znode_t *zp) &mtime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16); + SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zfsvfs), NULL, &btime, 16); if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) { zfs_znode_dmu_fini(zp); @@ -1269,6 +1272,7 @@ 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); + ZFS_TIME_DECODE(&zp->z_btime, btime); if ((uint32_t)gen != ZTOI(zp)->i_generation) { zfs_znode_dmu_fini(zp); diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c index 98c2fb3a0c..24a8b036bf 100644 --- a/module/os/linux/zfs/zpl_inode.c +++ b/module/os/linux/zfs/zpl_inode.c @@ -378,18 +378,46 @@ 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; + znode_t *zp __maybe_unused = ITOZ(ip); cookie = spl_fstrans_mark(); /* - * XXX request_mask and query_flags currently ignored. + * XXX query_flags currently ignored. */ #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 + if (request_mask & STATX_BTIME) { + stat->btime = zp->z_btime; + stat->result_mask |= STATX_BTIME; + } +#endif + +#ifdef STATX_ATTR_IMMUTABLE + if (zp->z_pflags & ZFS_IMMUTABLE) + stat->attributes |= STATX_ATTR_IMMUTABLE; + stat->attributes_mask |= STATX_ATTR_IMMUTABLE; +#endif + +#ifdef STATX_ATTR_APPEND + if (zp->z_pflags & ZFS_APPENDONLY) + stat->attributes |= STATX_ATTR_APPEND; + stat->attributes_mask |= STATX_ATTR_APPEND; +#endif + +#ifdef STATX_ATTR_NODUMP + if (zp->z_pflags & ZFS_NODUMP) + stat->attributes |= STATX_ATTR_NODUMP; + stat->attributes_mask |= STATX_ATTR_NODUMP; +#endif + spl_fstrans_unmark(cookie); ASSERT3S(error, <=, 0);