]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
NFSD: filecache: add STATX_DIOALIGN and STATX_DIO_READ_ALIGN support
authorMike Snitzer <snitzer@kernel.org>
Mon, 29 Sep 2025 15:56:41 +0000 (11:56 -0400)
committerAnna Schumaker <anna.schumaker@oracle.com>
Tue, 30 Sep 2025 20:10:05 +0000 (16:10 -0400)
Use STATX_DIOALIGN and STATX_DIO_READ_ALIGN to get DIO alignment
attributes from the underlying filesystem and store them in the
associated nfsd_file. This is done when the nfsd_file is first
opened for each regular file.

Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: NeilBrown <neil@brown.name>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
fs/nfsd/filecache.c
fs/nfsd/filecache.h
fs/nfsd/trace.h
fs/nfsd/vfs.h
include/trace/misc/fs.h

index 732abf6b92a569336865985e61906e9263efeec7..7ca1dedf4e04a77dce06fd97ad24b2f149e9c632 100644 (file)
@@ -231,6 +231,9 @@ nfsd_file_alloc(struct net *net, struct inode *inode, unsigned char need,
        refcount_set(&nf->nf_ref, 1);
        nf->nf_may = need;
        nf->nf_mark = NULL;
+       nf->nf_dio_mem_align = 0;
+       nf->nf_dio_offset_align = 0;
+       nf->nf_dio_read_offset_align = 0;
        return nf;
 }
 
@@ -1069,6 +1072,35 @@ nfsd_file_is_cached(struct inode *inode)
        return ret;
 }
 
+static __be32
+nfsd_file_get_dio_attrs(const struct svc_fh *fhp, struct nfsd_file *nf)
+{
+       struct inode *inode = file_inode(nf->nf_file);
+       struct kstat stat;
+       __be32 status;
+
+       /* Currently only need to get DIO alignment info for regular files */
+       if (!S_ISREG(inode->i_mode))
+               return nfs_ok;
+
+       status = fh_getattr(fhp, &stat);
+       if (status != nfs_ok)
+               return status;
+
+       trace_nfsd_file_get_dio_attrs(inode, &stat);
+
+       if (stat.result_mask & STATX_DIOALIGN) {
+               nf->nf_dio_mem_align = stat.dio_mem_align;
+               nf->nf_dio_offset_align = stat.dio_offset_align;
+       }
+       if (stat.result_mask & STATX_DIO_READ_ALIGN)
+               nf->nf_dio_read_offset_align = stat.dio_read_offset_align;
+       else
+               nf->nf_dio_read_offset_align = nf->nf_dio_offset_align;
+
+       return nfs_ok;
+}
+
 static __be32
 nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
                     struct svc_cred *cred,
@@ -1187,6 +1219,8 @@ open_file:
                        }
                        status = nfserrno(ret);
                        trace_nfsd_file_open(nf, status);
+                       if (status == nfs_ok)
+                               status = nfsd_file_get_dio_attrs(fhp, nf);
                }
        } else
                status = nfserr_jukebox;
index 722b26c71e454a41ddf32baef6c5747fca0ec5a9..237a05c74211b09dedf2f062522aadc155fe513e 100644 (file)
@@ -54,6 +54,10 @@ struct nfsd_file {
        struct list_head        nf_gc;
        struct rcu_head         nf_rcu;
        ktime_t                 nf_birthtime;
+
+       u32                     nf_dio_mem_align;
+       u32                     nf_dio_offset_align;
+       u32                     nf_dio_read_offset_align;
 };
 
 int nfsd_file_cache_init(void);
index a664fdf1161e9afe9de59d4edd91762400a99350..6e2c8e2aab10a98ff35c504327ee0cdd69f63271 100644 (file)
@@ -1133,6 +1133,33 @@ TRACE_EVENT(nfsd_file_alloc,
        )
 );
 
+TRACE_EVENT(nfsd_file_get_dio_attrs,
+       TP_PROTO(
+               const struct inode *inode,
+               const struct kstat *stat
+       ),
+       TP_ARGS(inode, stat),
+       TP_STRUCT__entry(
+               __field(const void *, inode)
+               __field(unsigned long, mask)
+               __field(u32, mem_align)
+               __field(u32, offset_align)
+               __field(u32, read_offset_align)
+       ),
+       TP_fast_assign(
+               __entry->inode = inode;
+               __entry->mask = stat->result_mask;
+               __entry->mem_align = stat->dio_mem_align;
+               __entry->offset_align = stat->dio_offset_align;
+               __entry->read_offset_align = stat->dio_read_offset_align;
+       ),
+       TP_printk("inode=%p flags=%s mem_align=%u offset_align=%u read_offset_align=%u",
+               __entry->inode, show_statx_mask(__entry->mask),
+               __entry->mem_align, __entry->offset_align,
+               __entry->read_offset_align
+       )
+);
+
 TRACE_EVENT(nfsd_file_acquire,
        TP_PROTO(
                const struct svc_rqst *rqstp,
index eff04959606fe55c141ab4a2eed97c7e0716a5f5..fde3e0c11dbafb9a6c4942c806da2ed6467dcce2 100644 (file)
@@ -185,6 +185,10 @@ static inline __be32 fh_getattr(const struct svc_fh *fh, struct kstat *stat)
        u32 request_mask = STATX_BASIC_STATS;
        struct path p = {.mnt = fh->fh_export->ex_path.mnt,
                         .dentry = fh->fh_dentry};
+       struct inode *inode = d_inode(p.dentry);
+
+       if (S_ISREG(inode->i_mode))
+               request_mask |= (STATX_DIOALIGN | STATX_DIO_READ_ALIGN);
 
        if (fh->fh_maxsize == NFS4_FHSIZE)
                request_mask |= (STATX_BTIME | STATX_CHANGE_COOKIE);
index 0406ebe2a80a499dfcadb7e63db4d9e4a84d4d64..7ead1c61f0cb135bcf42dd45901102a74cf030f6 100644 (file)
                { ATTR_TIMES_SET,       "TIMES_SET" },  \
                { ATTR_TOUCH,           "TOUCH"},       \
                { ATTR_DELEG,           "DELEG"})
+
+#define show_statx_mask(flags)                                 \
+       __print_flags(flags, "|",                               \
+               { STATX_TYPE,           "TYPE" },               \
+               { STATX_MODE,           "MODE" },               \
+               { STATX_NLINK,          "NLINK" },              \
+               { STATX_UID,            "UID" },                \
+               { STATX_GID,            "GID" },                \
+               { STATX_ATIME,          "ATIME" },              \
+               { STATX_MTIME,          "MTIME" },              \
+               { STATX_CTIME,          "CTIME" },              \
+               { STATX_INO,            "INO" },                \
+               { STATX_SIZE,           "SIZE" },               \
+               { STATX_BLOCKS,         "BLOCKS" },             \
+               { STATX_BASIC_STATS,    "BASIC_STATS" },        \
+               { STATX_BTIME,          "BTIME" },              \
+               { STATX_MNT_ID,         "MNT_ID" },             \
+               { STATX_DIOALIGN,       "DIOALIGN" },           \
+               { STATX_MNT_ID_UNIQUE,  "MNT_ID_UNIQUE" },      \
+               { STATX_SUBVOL,         "SUBVOL" },             \
+               { STATX_WRITE_ATOMIC,   "WRITE_ATOMIC" },       \
+               { STATX_DIO_READ_ALIGN, "DIO_READ_ALIGN" })