NFSD: filecache: add STATX_DIOALIGN and STATX_DIO_READ_ALIGN support

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>
pull/1354/merge
Mike Snitzer 2025-09-29 11:56:41 -04:00 committed by Anna Schumaker
parent ffe381923d
commit d11f6cd1bb
5 changed files with 91 additions and 0 deletions

View 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;

View 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);

View 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,

View 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);

View File

@ -141,3 +141,25 @@
{ 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" })