On Wed, 2025-07-23 at 11:43 -0400, Mike Snitzer wrote: > Use STATX_DIOALIGN and STATX_DIO_READ_ALIGN to get and store DIO > alignment attributes from underlying filesystem in associated > nfsd_file. This is done when the nfsd_file is first opened for > a regular file. > > Signed-off-by: Mike Snitzer <snitzer@xxxxxxxxxx> > --- > fs/nfsd/filecache.c | 32 ++++++++++++++++++++++++++++++++ > fs/nfsd/filecache.h | 4 ++++ > fs/nfsd/nfsfh.c | 4 ++++ > 3 files changed, 40 insertions(+) > > diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c > index 8581c131338b..5447dba6c5da 100644 > --- a/fs/nfsd/filecache.c > +++ b/fs/nfsd/filecache.c > @@ -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; > } > > @@ -1048,6 +1051,33 @@ nfsd_file_is_cached(struct inode *inode) > return ret; > } > > +static __be32 > +nfsd_file_getattr(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; > + > + 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 status; > +} > + > static __be32 > nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net, > struct svc_cred *cred, > @@ -1166,6 +1196,8 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net, > } > status = nfserrno(ret); > trace_nfsd_file_open(nf, status); > + if (status == nfs_ok) > + status = nfsd_file_getattr(fhp, nf); Doing a getattr alongside every open could be expensive in some configurations (like reexported NFS). We may want to skip doing this getattr this if O_DIRECT isn't is use. Is that possible? > } > } else > status = nfserr_jukebox; > diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h > index 24ddf60e8434..e3d6ca2b6030 100644 > --- a/fs/nfsd/filecache.h > +++ b/fs/nfsd/filecache.h > @@ -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); > diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c > index f4a3cc9e31e0..bdba2ba828a6 100644 > --- a/fs/nfsd/nfsfh.c > +++ b/fs/nfsd/nfsfh.c > @@ -677,8 +677,12 @@ __be32 fh_getattr(const struct svc_fh *fhp, struct kstat *stat) > .mnt = fhp->fh_export->ex_path.mnt, > .dentry = fhp->fh_dentry, > }; > + struct inode *inode = d_inode(p.dentry); > u32 request_mask = STATX_BASIC_STATS; > > + if (S_ISREG(inode->i_mode)) > + request_mask |= (STATX_DIOALIGN | STATX_DIO_READ_ALIGN); > + > if (fhp->fh_maxsize == NFS4_FHSIZE) > request_mask |= (STATX_BTIME | STATX_CHANGE_COOKIE); > -- Jeff Layton <jlayton@xxxxxxxxxx>