5.10.220-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 232/770 NFSD: Update the NFSv2 ACL GETATTR result encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 8d2009a10b3abaa12a39deb4876b215714993fe8 ]
--- fs/nfsd/nfs2acl.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-)
fs/nfsd/nfs2acl.c +2 -22
@@ -277,19 +277,6 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -static int nfsaclsvc_encode_attrstatres (struct svc_rqst *rqstp,__be32 *p) -{ -struct nfsd_attrstat *resp = rqstp->rq_resp; - - *p++ = resp->status; -if (resp->status != nfs_ok) - goto out; - - p =nfs2svc_encode_fattr (rqstp, p, &resp->fh, &resp->stat); -out: -return xdr_ressize_check (rqstp, p); -} -/* ACCESS */ static int nfsaclsvc_encode_accessres (struct svc_rqst *rqstp,__be32 *p) {
@@ -317,13 +304,6 @@ static void nfsaclsvc_release_getacl(struct svc_rqst *rqstp)posix_acl_release (resp->acl_default); } -static void nfsaclsvc_release_attrstat (struct svc_rqst *rqstp) -{ -struct nfsd_attrstat *resp = rqstp->rq_resp; - -fh_put (&resp->fh); -} -static void nfsaclsvc_release_access (struct svc_rqst *rqstp) {struct nfsd3_accessres *resp = rqstp->rq_resp;
@@ -374,8 +354,8 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = { [ACLPROC2_GETATTR] = { .pc_func = nfsacld_proc_getattr, .pc_decode = nfssvc_decode_fhandleargs, - .pc_encode = nfsaclsvc_encode_attrstatres, - .pc_release = nfsaclsvc_release_attrstat, + .pc_encode = nfssvc_encode_attrstatres, + .pc_release = nfssvc_release_attrstat, .pc_argsize = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd_attrstat), .pc_cachetype = RC_NOCACHE,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 233/770 NFSD: Update the NFSv2 ACL ACCESS result encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 07f5c2963c04b11603e9667f89bb430c132e9cc1 ]
--- fs/nfsd/nfs2acl.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
fs/nfsd/nfs2acl.c +12 -7
@@ -280,16 +280,21 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)/* ACCESS */ static int nfsaclsvc_encode_accessres (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd3_accessres *resp = rqstp->rq_resp; - *p++ = resp->status; -if (resp->status != nfs_ok) - goto out; +if (!svcxdr_encode_stat (xdr, resp->status)) +return 0 ; +switch (resp->status) { +case nfs_ok: +if (!svcxdr_encode_fattr (rqstp, xdr, &resp->fh, &resp->stat)) +return 0 ; +if (xdr_stream_encode_u32 (xdr, resp->access) <0 ) +return 0 ; +break ; + } - p =nfs2svc_encode_fattr (rqstp, p, &resp->fh, &resp->stat); - *p++ =htonl (resp->access); -out: -return xdr_ressize_check (rqstp, p); +return 1 ; }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 234/770 NFSD: Clean up after updating NFSv2 ACL encoders
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 83d0b84572775a29f800de67a1b9b642a5376bc3 ]
--- fs/nfsd/nfsxdr.c | 64 ------------------------------------------------ fs/nfsd/xdr.h | 1 - 2 files changed, 65 deletions(-)
fs/nfsd/nfsxdr.c +0 -64
@@ -201,64 +201,6 @@ svcxdr_decode_sattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,return true; } -static __be32 * -encode_fattr (struct svc_rqst *rqstp,__be32 *p,struct svc_fh *fhp, -struct kstat *stat) -{ -struct user_namespace *userns =nfsd_user_namespace (rqstp); -struct dentry *dentry = fhp->fh_dentry; -int type; -struct timespec64 time; -u32 f; - - type = (stat->mode &S_IFMT ); - - *p++ =htonl (nfs_ftypes[type >>12 ]); - *p++ =htonl ((u32 ) stat->mode); - *p++ =htonl ((u32 ) stat->nlink); - *p++ =htonl ((u32 )from_kuid_munged (userns, stat->uid)); - *p++ =htonl ((u32 )from_kgid_munged (userns, stat->gid)); - -if (S_ISLNK (type) && stat->size >NFS_MAXPATHLEN ) { - *p++ =htonl (NFS_MAXPATHLEN ); - }else { - *p++ =htonl ((u32 ) stat->size); - } - *p++ =htonl ((u32 ) stat->blksize); -if (S_ISCHR (type) ||S_ISBLK (type)) - *p++ =htonl (new_encode_dev (stat->rdev)); -else - *p++ =htonl (0xffffffff ); - *p++ =htonl ((u32 ) stat->blocks); -switch (fsid_source (fhp)) { -default : -case FSIDSOURCE_DEV : - *p++ =htonl (new_encode_dev (stat->dev)); -break ; -case FSIDSOURCE_FSID : - *p++ =htonl ((u32 ) fhp->fh_export->ex_fsid); -break ; -case FSIDSOURCE_UUID : - f = ((u32 *)fhp->fh_export->ex_uuid)[0 ]; - f ^= ((u32 *)fhp->fh_export->ex_uuid)[1 ]; - f ^= ((u32 *)fhp->fh_export->ex_uuid)[2 ]; - f ^= ((u32 *)fhp->fh_export->ex_uuid)[3 ]; - *p++ =htonl (f); -break ; - } - *p++ =htonl ((u32 ) stat->ino); - *p++ =htonl ((u32 ) stat->atime.tv_sec); - *p++ =htonl (stat->atime.tv_nsec ? stat->atime.tv_nsec /1000 :0 ); - time = stat->mtime; -lease_get_mtime (d_inode (dentry), &time); - *p++ =htonl ((u32 ) time.tv_sec); - *p++ =htonl (time.tv_nsec ? time.tv_nsec /1000 :0 ); - *p++ =htonl ((u32 ) stat->ctime.tv_sec); - *p++ =htonl (stat->ctime.tv_nsec ? stat->ctime.tv_nsec /1000 :0 ); - -return p; -} -/** * svcxdr_encode_fattr - Encode NFSv2 file attributes * @rqstp: Context of a completed RPC transaction
@@ -328,12 +270,6 @@ svcxdr_encode_fattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,return true; } -/* Helper function for NFSv2 ACL code */ -__be32 *nfs2svc_encode_fattr (struct svc_rqst *rqstp,__be32 *p,struct svc_fh *fhp,struct kstat *stat) -{ -return encode_fattr (rqstp, p, fhp, stat); -} -/* * XDR decode functions */
fs/nfsd/xdr.h +0 -1
@@ -168,7 +168,6 @@ void nfssvc_release_diropres(struct svc_rqst *rqstp);void nfssvc_release_readres (struct svc_rqst *rqstp);/* Helper functions for NFSv2 ACL code */ -__be32 *nfs2svc_encode_fattr (struct svc_rqst *rqstp,__be32 *p,struct svc_fh *fhp,struct kstat *stat);bool svcxdr_decode_fhandle (struct xdr_stream *xdr,struct svc_fh *fhp);bool svcxdr_encode_stat (struct xdr_stream *xdr,__be32 status); bool svcxdr_encode_fattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 235/770 NFSD: Update the NFSv3 GETACL result encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 20798dfe249a01ad1b12eec7dbc572db5003244a ]
--- fs/nfsd/nfs3acl.c | 33 +++++++++++++++++++-------------- fs/nfsd/nfs3xdr.c | 23 +++++++++++++++++++++-- fs/nfsd/xdr3.h | 3 +++ 3 files changed, 43 insertions(+), 16 deletions(-)
fs/nfsd/nfs3acl.c +19 -14
@@ -166,22 +166,25 @@ static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)/* GETACL */ static int nfs3svc_encode_getaclres (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd3_getaclres *resp = rqstp->rq_resp;struct dentry *dentry = resp->fh.fh_dentry; +struct kvec *head = rqstp->rq_res.head; +struct inode *inode =d_inode (dentry); +unsigned int base; +int n; +int w; - *p++ = resp->status; - p =nfs3svc_encode_post_op_attr (rqstp, p, &resp->fh); -if (resp->status ==0 && dentry &&d_really_is_positive (dentry)) { -struct inode *inode =d_inode (dentry); -struct kvec *head = rqstp->rq_res.head; -unsigned int base; -int n; -int w; - - *p++ =htonl (resp->mask); -if (!xdr_ressize_check (rqstp, p)) +if (!svcxdr_encode_nfsstat3 (xdr, resp->status)) +return 0 ; +switch (resp->status) { +case nfs_ok: +if (!svcxdr_encode_post_op_attr (rqstp, xdr, &resp->fh))return 0 ; - base = (char *)p - (char *)head->iov_base; +if (xdr_stream_encode_u32 (xdr, resp->mask) <0 ) +return 0 ; + + base = (char *)xdr->p - (char *)head->iov_base; rqstp->rq_res.page_len = w = nfsacl_size( (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
@@ -202,9 +205,11 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) NFS_ACL_DEFAULT);if (n <=0 )return 0 ; - }else -if (!xdr_ressize_check (rqstp, p)) +break ; +default : +if (!svcxdr_encode_post_op_attr (rqstp, xdr, &resp->fh))return 0 ; + }return 1 ; }
fs/nfsd/nfs3xdr.c +21 -2
@@ -107,7 +107,16 @@ svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)return true; } -static bool +/** +* svcxdr_encode_nfsstat3 - Encode an NFSv3 status code +* @xdr: XDR stream +* @status: status value to encode +* +* Return values: +* %false: Send buffer space was exhausted +* %true: Success +*/ +bool svcxdr_encode_nfsstat3 (struct xdr_stream *xdr,__be32 status) {__be32 *p;
@@ -464,7 +473,17 @@ svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)return svcxdr_encode_wcc_attr (xdr, fhp); } -static bool +/** +* svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes +* @rqstp: Context of a completed RPC transaction +* @xdr: XDR stream +* @fhp: File handle to encode +* +* Return values: +* %false: Send buffer space was exhausted +* %true: Success +*/ +bool svcxdr_encode_post_op_attr (struct svc_rqst *rqstp,struct xdr_stream *xdr,const struct svc_fh *fhp) {
fs/nfsd/xdr3.h +3 -0
@@ -308,5 +308,8 @@ int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,__be32 *nfs3svc_encode_post_op_attr (struct svc_rqst *rqstp,__be32 *p,struct svc_fh *fhp);bool svcxdr_decode_nfs_fh3 (struct xdr_stream *xdr,struct svc_fh *fhp); +bool svcxdr_encode_nfsstat3 (struct xdr_stream *xdr,__be32 status); +bool svcxdr_encode_post_op_attr (struct svc_rqst *rqstp,struct xdr_stream *xdr, +const struct svc_fh *fhp);#endif /* _LINUX_NFSD_XDR3_H */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 236/770 NFSD: Update the NFSv3 SETACL result encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 15e432bf0cfd1e6aebfa9ffd4e0cc2ff4f3ae2db ]
--- fs/nfsd/nfs3acl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/nfs3acl.c +3 -3
@@ -217,11 +217,11 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)/* SETACL */ static int nfs3svc_encode_setaclres (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd3_attrstat *resp = rqstp->rq_resp; - *p++ = resp->status; - p =nfs3svc_encode_post_op_attr (rqstp, p, &resp->fh); -return xdr_ressize_check (rqstp, p); +return svcxdr_encode_nfsstat3 (xdr, resp->status) && +svcxdr_encode_post_op_attr (rqstp, xdr, &resp->fh); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 237/770 NFSD: Clean up after updating NFSv3 ACL encoders
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 1416f435303d81070c6bcf5a4a9b4ed0f7a9f013 ]
--- fs/nfsd/nfs3xdr.c | 86 ----------------------------------------------- fs/nfsd/xdr3.h | 2 -- 2 files changed, 88 deletions(-)
fs/nfsd/nfs3xdr.c +0 -86
@@ -48,13 +48,6 @@ static const u32 nfs3_ftypes[] = {* Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6) */ -static __be32 * -encode_time3 (__be32 *p,struct timespec64 *time) -{ - *p++ =htonl ((u32 ) time->tv_sec); *p++ =htonl (time->tv_nsec); -return p; -} -static __be32 *encode_nfstime3 (__be32 *p,const struct timespec64 *time) {
@@ -396,54 +389,6 @@ svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,return true; } -static __be32 *encode_fsid (__be32 *p,struct svc_fh *fhp) -{ -u64 f; -switch (fsid_source (fhp)) { -default : -case FSIDSOURCE_DEV : - p =xdr_encode_hyper (p, (u64 )huge_encode_dev - (fhp->fh_dentry->d_sb->s_dev)); -break ; -case FSIDSOURCE_FSID : - p =xdr_encode_hyper (p, (u64 ) fhp->fh_export->ex_fsid); -break ; -case FSIDSOURCE_UUID : - f = ((u64 *)fhp->fh_export->ex_uuid)[0 ]; - f ^= ((u64 *)fhp->fh_export->ex_uuid)[1 ]; - p =xdr_encode_hyper (p, f); -break ; - } -return p; -} - -static __be32 * -encode_fattr3 (struct svc_rqst *rqstp,__be32 *p,struct svc_fh *fhp, -struct kstat *stat) -{ -struct user_namespace *userns =nfsd_user_namespace (rqstp); - *p++ =htonl (nfs3_ftypes[(stat->mode &S_IFMT ) >>12 ]); - *p++ =htonl ((u32) (stat->mode &S_IALLUGO )); - *p++ =htonl ((u32 ) stat->nlink); - *p++ =htonl ((u32 )from_kuid_munged (userns, stat->uid)); - *p++ =htonl ((u32 )from_kgid_munged (userns, stat->gid)); -if (S_ISLNK (stat->mode) && stat->size >NFS3_MAXPATHLEN ) { - p =xdr_encode_hyper (p, (u64 )NFS3_MAXPATHLEN ); - }else { - p =xdr_encode_hyper (p, (u64 ) stat->size); - } - p =xdr_encode_hyper (p, ((u64 )stat->blocks) <<9 ); - *p++ =htonl ((u32 )MAJOR (stat->rdev)); - *p++ =htonl ((u32 )MINOR (stat->rdev)); - p =encode_fsid (p, fhp); - p =xdr_encode_hyper (p, stat->ino); - p =encode_time3 (p, &stat->atime); - p =encode_time3 (p, &stat->mtime); - p =encode_time3 (p, &stat->ctime); - -return p; -} -static bool svcxdr_encode_wcc_attr (struct xdr_stream *xdr,const struct svc_fh *fhp) {
@@ -512,37 +457,6 @@ svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr,return xdr_stream_encode_item_absent (xdr) >0 ; } -/* -* Encode post-operation attributes. -* The inode may be NULL if the call failed because of a stale file -* handle. In this case, no attributes are returned. -*/ -static __be32 * -encode_post_op_attr (struct svc_rqst *rqstp,__be32 *p,struct svc_fh *fhp) -{ -struct dentry *dentry = fhp->fh_dentry; -if (!fhp->fh_no_wcc && dentry &&d_really_is_positive (dentry)) { -__be32 err; -struct kstat stat; - - err =fh_getattr (fhp, &stat); -if (!err) { - *p++ = xdr_one;/* attributes follow */ -lease_get_mtime (d_inode (dentry), &stat.mtime); -return encode_fattr3 (rqstp, p, fhp, &stat); - } - } - *p++ = xdr_zero; -return p; -} - -/* Helper for NFSv3 ACLs */ -__be32 * -nfs3svc_encode_post_op_attr (struct svc_rqst *rqstp,__be32 *p,struct svc_fh *fhp) -{ -return encode_post_op_attr (rqstp, p, fhp); -} -/* * Encode weak cache consistency data */
fs/nfsd/xdr3.h +0 -2
@@ -305,8 +305,6 @@ int nfs3svc_encode_entry3(void *data, const char *name, int namlen,int nfs3svc_encode_entryplus3 (void *data,const char *name,int namlen,loff_t offset,u64 ino,unsigned int d_type);/* Helper functions for NFSv3 ACL code */ -__be32 *nfs3svc_encode_post_op_attr (struct svc_rqst *rqstp,__be32 *p, -struct svc_fh *fhp);bool svcxdr_decode_nfs_fh3 (struct xdr_stream *xdr,struct svc_fh *fhp);bool svcxdr_encode_nfsstat3 (struct xdr_stream *xdr,__be32 status); bool svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 238/770 NFSD: Add a tracepoint to record directory entry encoding
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 6019ce0742ca55d3e45279a19b07d1542747a098 ]
Enable watching the progress of directory encoding to capture the timing of any issues with reading or encoding a directory. The new tracepoint captures dirent encoding for all NFS versions.
For example, here's what a few NFSv4 directory entries might look like:
nfsd-989 [002] 468.596265: nfsd_dirent: fh_hash=0x5d162594 ino=2 name=. nfsd-989 [002] 468.596267: nfsd_dirent: fh_hash=0x5d162594 ino=1 name=.. nfsd-989 [002] 468.596299: nfsd_dirent: fh_hash=0x5d162594 ino=3827 name=zlib.c nfsd-989 [002] 468.596325: nfsd_dirent: fh_hash=0x5d162594 ino=3811 name=xdiff nfsd-989 [002] 468.596351: nfsd_dirent: fh_hash=0x5d162594 ino=3810 name=xdiff-interface.h nfsd-989 [002] 468.596377: nfsd_dirent: fh_hash=0x5d162594 ino=3809 name=xdiff-interface.c
--- fs/nfsd/trace.h | 24 ++++++++++++++++++++++++ fs/nfsd/vfs.c | 9 ++++++--- 2 files changed, 30 insertions(+), 3 deletions(-)
fs/nfsd/trace.h +24 -0
@@ -391,6 +391,30 @@ DEFINE_EVENT(nfsd_err_class, nfsd_##name, \DEFINE_NFSD_ERR_EVENT (read_err);DEFINE_NFSD_ERR_EVENT (write_err); +TRACE_EVENT (nfsd_dirent, + TP_PROTO(struct svc_fh *fhp, + u64 ino, + const char *name, + int namlen), +TP_ARGS (fhp, ino, name, namlen), +TP_STRUCT__entry ( + __field(u32, fh_hash) + __field(u64, ino) + __field(int, len) + __dynamic_array(unsigned char, name, namlen) + ), +TP_fast_assign ( + __entry->fh_hash = fhp ? knfsd_fh_hash(&fhp->fh_handle) : 0; + __entry->ino = ino; + __entry->len = namlen; + memcpy(__get_str(name), name, namlen); + __assign_str(name, name); + ), +TP_printk ("fh_hash=0x%08x ino=%llu name=%.*s" , + __entry->fh_hash, __entry->ino, + __entry->len,__get_str (name)) +) +#include "state.h" #include "filecache.h" #include "vfs.h"
fs/nfsd/vfs.c +6 -3
@@ -1979,8 +1979,9 @@ static int nfsd_buffered_filldir(struct dir_context *ctx, const char *name,return 0 ; } -static __be32 nfsd_buffered_readdir (struct file *file,nfsd_filldir_t func, -struct readdir_cd *cdp,loff_t *offsetp) +static __be32 nfsd_buffered_readdir (struct file *file,struct svc_fh *fhp, +nfsd_filldir_t func,struct readdir_cd *cdp, +loff_t *offsetp) {struct buffered_dirent *de;int host_err;
@@ -2026,6 +2027,8 @@ static __be32 nfsd_buffered_readdir(struct file *file, nfsd_filldir_t func,if (cdp->err != nfs_ok)break ; +trace_nfsd_dirent (fhp, de->ino, de->name, de->namlen); + reclen =ALIGN (sizeof (*de) + de->namlen,sizeof (u64)); size -= reclen;
@@ -2073,7 +2076,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp, goto out_close; } - err =nfsd_buffered_readdir (file, func, cdp, offsetp); + err =nfsd_buffered_readdir (file, fhp, func, cdp, offsetp);if (err == nfserr_eof || err == nfserr_toosmall) err = nfs_ok;/* can still be found in ->err */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 239/770 NFSD: Clean up NFSDDBG_FACILITY macro
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 219a170502b3d597c52eeec088aee8fbf7b90da5 ]
These are no longer needed because there are no dprintk() call sites in these files.
--- fs/nfsd/nfs3xdr.c | 3 --- fs/nfsd/nfsxdr.c | 2 -- 2 files changed, 5 deletions(-)
fs/nfsd/nfs3xdr.c +0 -3
@@ -14,9 +14,6 @@#include "netns.h" #include "vfs.h" -#define NFSDDBG_FACILITY NFSDDBG_XDR - -/* * Force construction of an empty post-op attr */
fs/nfsd/nfsxdr.c +0 -2
@@ -9,8 +9,6 @@#include "xdr.h" #include "auth.h" -#define NFSDDBG_FACILITY NFSDDBG_XDR -/* * Mapping of S_IF* types to NFS file types */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 240/770 nfsd: helper for laundromat expiry calculations
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit 7f7e7a4006f74b031718055a0751c70c2e3d5e7e ]
We do this same logic repeatedly, and it's easy to get the sense of the comparison wrong.
--- fs/nfsd/nfs4state.c | 49 +++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 22 deletions(-)
fs/nfsd/nfs4state.c +27 -22
@@ -5385,6 +5385,22 @@ static bool clients_still_reclaiming(struct nfsd_net *nn)return true; } +struct laundry_time { +time64_t cutoff; +time64_t new_timeo; +}; + +static bool state_expired (struct laundry_time *lt,time64_t last_refresh) +{ +time64_t time_remaining; + +if (last_refresh < lt->cutoff) +return true; + time_remaining = last_refresh - lt->cutoff; + lt->new_timeo =min (lt->new_timeo, time_remaining); +return false; +} +static time64_t nfs4_laundromat (struct nfsd_net *nn) {
@@ -5394,14 +5410,16 @@ nfs4_laundromat(struct nfsd_net *nn)struct nfs4_ol_stateid *stp;struct nfsd4_blocked_lock *nbl;struct list_head *pos, *next, reaplist; -time64_t cutoff =ktime_get_boottime_seconds () - nn->nfsd4_lease; -time64_t t, new_timeo = nn->nfsd4_lease; +struct laundry_time lt = { + .cutoff =ktime_get_boottime_seconds () - nn->nfsd4_lease, + .new_timeo = nn->nfsd4_lease + };struct nfs4_cpntf_state *cps;copy_stateid_t *cps_t;int i;if (clients_still_reclaiming (nn)) { - new_timeo =0 ; + lt.new_timeo =0 ; goto out; }nfsd4_end_grace (nn);
@@ -5411,7 +5429,7 @@ nfs4_laundromat(struct nfsd_net *nn)idr_for_each_entry (&nn->s2s_cp_stateids, cps_t, i) { cps = container_of(cps_t, struct nfs4_cpntf_state, cp_stateid);if (cps->cp_stateid.sc_type ==NFS4_COPYNOTIFY_STID && - cps->cpntf_time < cutoff) +state_expired (<, cps->cpntf_time))_free_cpntf_state_locked (nn, cps); }spin_unlock (&nn->s2s_cp_lock);
@@ -5419,11 +5437,8 @@ nfs4_laundromat(struct nfsd_net *nn)spin_lock (&nn->client_lock);list_for_each_safe (pos, next, &nn->client_lru) { clp = list_entry(pos, struct nfs4_client, cl_lru); -if (clp->cl_time > cutoff) { - t = clp->cl_time - cutoff; - new_timeo =min (new_timeo, t); +if (!state_expired (<, clp->cl_time))break ; - }if (mark_client_expired_locked (clp)) {trace_nfsd_clid_expired (&clp->cl_clientid);continue ;
@@ -5440,11 +5455,8 @@ nfs4_laundromat(struct nfsd_net *nn)spin_lock (&state_lock);list_for_each_safe (pos, next, &nn->del_recall_lru) { dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); -if (dp->dl_time > cutoff) { - t = dp->dl_time - cutoff; - new_timeo =min (new_timeo, t); +if (!state_expired (<, dp->dl_time))break ; - }WARN_ON (!unhash_delegation_locked (dp));list_add (&dp->dl_recall_lru, &reaplist); }
@@ -5460,11 +5472,8 @@ nfs4_laundromat(struct nfsd_net *nn)while (!list_empty (&nn->close_lru)) { oo = list_first_entry(&nn->close_lru, struct nfs4_openowner, oo_close_lru); -if (oo->oo_time > cutoff) { - t = oo->oo_time - cutoff; - new_timeo =min (new_timeo, t); +if (!state_expired (<, oo->oo_time))break ; - }list_del_init (&oo->oo_close_lru); stp = oo->oo_last_closed_stid; oo->oo_last_closed_stid =NULL ;
@@ -5490,11 +5499,8 @@ nfs4_laundromat(struct nfsd_net *nn)while (!list_empty (&nn->blocked_locks_lru)) { nbl =list_first_entry (&nn->blocked_locks_lru, struct nfsd4_blocked_lock, nbl_lru); -if (nbl->nbl_time > cutoff) { - t = nbl->nbl_time - cutoff; - new_timeo =min (new_timeo, t); +if (!state_expired (<, nbl->nbl_time))break ; - }list_move (&nbl->nbl_lru, &reaplist);list_del_init (&nbl->nbl_list); }
@@ -5507,8 +5513,7 @@ nfs4_laundromat(struct nfsd_net *nn)free_blocked_lock (nbl); } out: - new_timeo =max_t (time64_t, new_timeo,NFSD_LAUNDROMAT_MINTIMEOUT ); -return new_timeo; +return max_t (time64_t, lt.new_timeo,NFSD_LAUNDROMAT_MINTIMEOUT ); }static struct workqueue_struct *laundry_wq;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 241/770 nfsd: Log client tracking type log message as info instead of warning
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Menzel <[email protected]>
[ Upstream commit f988a7b71d1e66e63f79cd59c763875347943a7a ]
printk(), by default, uses the log level warning, which leaves the user reading
NFSD: Using UMH upcall client tracking operations.
wondering what to do about it (dmesg --level=warn).
Several client tracking methods are tried, and expected to fail. That’s why a message is printed only on success. It might be interesting for users to know the chosen method, so use info-level instead of debug-level.
--- fs/nfsd/nfs4recover.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/nfsd/nfs4recover.c +4 -4
@@ -626,7 +626,7 @@ nfsd4_legacy_tracking_init(struct net *net) status =nfsd4_load_reboot_recovery_data (net);if (status) goto err; -printk ("NFSD: Using legacy client tracking operations.\n" ); +pr_info ("NFSD: Using legacy client tracking operations.\n" );return 0 ; err:
@@ -1030,7 +1030,7 @@ nfsd4_init_cld_pipe(struct net *net) status =__nfsd4_init_cld_pipe (net);if (!status) -printk ("NFSD: Using old nfsdcld client tracking operations.\n" ); +pr_info ("NFSD: Using old nfsdcld client tracking operations.\n" );return status; }
@@ -1607,7 +1607,7 @@ nfsd4_cld_tracking_init(struct net *net)nfs4_release_reclaim (nn); goto err_remove; }else -printk ("NFSD: Using nfsdcld client tracking operations.\n" ); +pr_info ("NFSD: Using nfsdcld client tracking operations.\n" );return 0 ; err_remove:
@@ -1866,7 +1866,7 @@ nfsd4_umh_cltrack_init(struct net *net) ret =nfsd4_umh_cltrack_upcall ("init" ,NULL , grace_start,NULL );kfree (grace_start);if (!ret) -printk ("NFSD: Using UMH upcall client tracking operations.\n" ); +pr_info ("NFSD: Using UMH upcall client tracking operations.\n" );return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 242/770 nfsd: Fix typo "accesible"
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Ribalda <[email protected]>
[ Upstream commit 34a624931b8c12b435b5009edc5897e4630107bc ]
Trivial fix.
--- fs/nfsd/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/Kconfig +3 -3
@@ -99,7 +99,7 @@ config NFSD_BLOCKLAYOUT help This option enables support for the exporting pNFS block layouts in the kernel's NFS server. The pNFS block layout enables NFS - clients to directly perform I/O to block devices accesible to both + clients to directly perform I/O to block devices accessible to both the server and the clients. See RFC 5663 for more details. If unsure, say N.
@@ -113,7 +113,7 @@ config NFSD_SCSILAYOUT help This option enables support for the exporting pNFS SCSI layouts in the kernel's NFS server. The pNFS SCSI layout enables NFS - clients to directly perform I/O to SCSI devices accesible to both + clients to directly perform I/O to SCSI devices accessible to both the server and the clients. See draft-ietf-nfsv4-scsi-layout for more details.
@@ -127,7 +127,7 @@ config NFSD_FLEXFILELAYOUT This option enables support for the exporting pNFS Flex File layouts in the kernel's NFS server. The pNFS Flex File layout enables NFS clients to directly perform I/O to NFSv3 devices - accesible to both the server and the clients. See + accessible to both the server and the clients. See draft-ietf-nfsv4-flex-files for more details. Warning, this server implements the bare minimum functionality
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 243/770 nfsd: COPY with length 0 should copy to end of file
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit 792a5112aa90e59c048b601c6382fe3498d75db7 ]
Quoted 1 line
A count of 0 (zero) requests that all bytes from ca_src_offset through EOF be copied to the destination.
--- fs/nfsd/nfs4proc.c | 3 +++ 1 file changed, 3 insertions(+)
fs/nfsd/nfs4proc.c +3 -0
@@ -1380,6 +1380,9 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)u64 src_pos = copy->cp_src_pos;u64 dst_pos = copy->cp_dst_pos; +/* See RFC 7862 p.67: */ +if (bytes_total ==0 ) + bytes_total =ULLONG_MAX ; do { if (kthread_should_stop()) break;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 244/770 nfsd: dont ignore high bits of copy count
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit e7a833e9cc6c3b58fe94f049d2b40943cba07086 ]
Note size_t is 32-bit on a 32-bit architecture, but cp_count is defined by the protocol to be 64 bit, so we could be turning a large copy into a 0-length copy here.
--- fs/nfsd/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -1376,7 +1376,7 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)struct file *dst = copy->nf_dst->nf_file;struct file *src = copy->nf_src->nf_file;ssize_t bytes_copied =0 ; -size_t bytes_total = copy->cp_count; +u64 bytes_total = copy->cp_count;u64 src_pos = copy->cp_src_pos;u64 dst_pos = copy->cp_dst_pos;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 245/770 nfsd: report client confirmation status in "info" file
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 472d155a0631bd1a09b5c0c275a254e65605d683 ]
mountd can now monitor clients appearing and disappearing in /proc/fs/nfsd/clients, and will log these events, in liu of the logging of mount/unmount events for NFSv3.
Currently it cannot distinguish between unconfirmed clients (which might be transient and totally uninteresting) and confirmed clients.
So add a "status: " line which reports either "confirmed" or "unconfirmed", and use fsnotify to report that the info file has been modified.
This requires a bit of infrastructure to keep the dentry for the "info" file. There is no need to take a counted reference as the dentry must remain around until the client is removed.
--- fs/nfsd/nfs4state.c | 19 +++++++++++++++---- fs/nfsd/nfsctl.c | 14 ++++++++------ fs/nfsd/nfsd.h | 4 +++- fs/nfsd/state.h | 4 ++++ 4 files changed, 30 insertions(+), 11 deletions(-)
fs/nfsd/nfs4state.c +15 -4
@@ -43,6 +43,7 @@#include <linux/sunrpc/addr.h> #include <linux/jhash.h> #include <linux/string_helpers.h> +#include <linux/fsnotify.h> #include "xdr4.h" #include "xdr4cb.h" #include "vfs.h"
@@ -2370,6 +2371,10 @@ static int client_info_show(struct seq_file *m, void *v)memcpy (&clid, &clp->cl_clientid,sizeof (clid));seq_printf (m,"clientid: 0x%llx\n" , clid);seq_printf (m,"address: \"%pISpc\"\n" , (struct sockaddr *)&clp->cl_addr); +if (test_bit (NFSD4_CLIENT_CONFIRMED , &clp->cl_flags)) +seq_puts (m,"status: confirmed\n" ); +else +seq_puts (m,"status: unconfirmed\n" );seq_printf (m,"name: " );seq_quote_mem (m, clp->cl_name.data, clp->cl_name.len);seq_printf (m,"\nminor version: %d\n" , clp->cl_minorversion);
@@ -2724,6 +2729,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name,int ret;struct net *net =SVC_NET (rqstp);struct nfsd_net *nn =net_generic (net, nfsd_net_id); +struct dentry *dentries[ARRAY_SIZE (client_files)]; clp =alloc_client (name);if (clp ==NULL )
@@ -2743,9 +2749,11 @@ static struct nfs4_client *create_client(struct xdr_netobj name,memcpy (&clp->cl_addr, sa,sizeof (struct sockaddr_storage )); clp->cl_cb_session =NULL ; clp->net = net; - clp->cl_nfsd_dentry =nfsd_client_mkdir (nn, &clp->cl_nfsdfs, - clp->cl_clientid.cl_id - nn->clientid_base, - client_files); + clp->cl_nfsd_dentry =nfsd_client_mkdir ( + nn, &clp->cl_nfsdfs, + clp->cl_clientid.cl_id - nn->clientid_base, + client_files, dentries); + clp->cl_nfsd_info_dentry = dentries[0 ];if (!clp->cl_nfsd_dentry) {free_client (clp);return NULL ;
@@ -2820,7 +2828,10 @@ move_to_confirmed(struct nfs4_client *clp)list_move (&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);rb_erase (&clp->cl_namenode, &nn->unconf_name_tree);add_clp_to_name_tree (clp, &nn->conf_name_tree); -set_bit (NFSD4_CLIENT_CONFIRMED , &clp->cl_flags); +if (!test_and_set_bit (NFSD4_CLIENT_CONFIRMED , &clp->cl_flags) && + clp->cl_nfsd_dentry && + clp->cl_nfsd_info_dentry) +fsnotify_dentry (clp->cl_nfsd_info_dentry,FS_MODIFY );renew_client_locked (clp); }
fs/nfsd/nfsctl.c +8 -6
@@ -1270,7 +1270,8 @@ static void nfsdfs_remove_files(struct dentry *root)/* XXX: cut'n'paste from simple_fill_super; figure out if we could share * code instead. */ static int nfsdfs_create_files (struct dentry *root, -const struct tree_descr *files) +const struct tree_descr *files, +struct dentry **fdentries) {struct inode *dir =d_inode (root);struct inode *inode;
@@ -1279,8 +1280,6 @@ static int nfsdfs_create_files(struct dentry *root,inode_lock (dir);for (i =0 ; files->name && files->name[0 ]; i++, files++) { -if (!files->name) -continue ; dentry =d_alloc_name (root, files->name);if (!dentry) goto out;
@@ -1294,6 +1293,8 @@ static int nfsdfs_create_files(struct dentry *root, inode->i_private =__get_nfsdfs_client (dir);d_add (dentry, inode);fsnotify_create (dir, dentry); +if (fdentries) + fdentries[i] = dentry; }inode_unlock (dir);return 0 ;
@@ -1305,8 +1306,9 @@ static int nfsdfs_create_files(struct dentry *root,/* on success, returns positive number unique to that client. */ struct dentry *nfsd_client_mkdir (struct nfsd_net *nn, -struct nfsdfs_client *ncl,u32 id, -const struct tree_descr *files) +struct nfsdfs_client *ncl,u32 id, +const struct tree_descr *files, +struct dentry **fdentries) {struct dentry *dentry;char name[11 ];
@@ -1317,7 +1319,7 @@ struct dentry *nfsd_client_mkdir(struct nfsd_net *nn, dentry =nfsd_mkdir (nn->nfsd_client_dir, ncl, name);if (IS_ERR (dentry))/* XXX: tossing errors? */ return NULL ; - ret =nfsdfs_create_files (dentry, files); + ret =nfsdfs_create_files (dentry, files, fdentries);if (ret) {nfsd_client_rmdir (dentry);return NULL ;
fs/nfsd/nfsd.h +3 -1
@@ -106,7 +106,9 @@ struct nfsdfs_client {struct nfsdfs_client *get_nfsdfs_client (struct inode *);struct dentry *nfsd_client_mkdir (struct nfsd_net *nn, -struct nfsdfs_client *ncl,u32 id,const struct tree_descr *); +struct nfsdfs_client *ncl,u32 id, +const struct tree_descr *, +struct dentry **fdentries);void nfsd_client_rmdir (struct dentry *dentry);
fs/nfsd/state.h +4 -0
@@ -371,6 +371,10 @@ struct nfs4_client {/* debugging info directory under nfsd/clients/ : */ struct dentry *cl_nfsd_dentry; +/* 'info' file within that directory. Ref is not counted, +* but will remain valid iff cl_nfsd_dentry != NULL +*/ +struct dentry *cl_nfsd_info_dentry;/* for nfs41 callbacks */ /* We currently support a single back channel with a single slot */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 246/770 SUNRPC: Export svc_xprt_received()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 7dcfbd86adc45f6d6b37278efd22530cf80ab474 ]
Prepare svc_xprt_received() to be called from transport code instead of from generic RPC server code.
--- include/linux/sunrpc/svc_xprt.h | 1 + include/trace/events/sunrpc.h | 1 + net/sunrpc/svc_xprt.c | 13 +++++++++---- 3 files changed, 11 insertions(+), 4 deletions(-)
include/linux/sunrpc/svc_xprt.h +1 -0
@@ -130,6 +130,7 @@ void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,int svc_create_xprt (struct svc_serv *,const char *,struct net *,const int ,const unsigned short ,int ,const struct cred *); +void svc_xprt_received (struct svc_xprt *xprt);void svc_xprt_do_enqueue (struct svc_xprt *xprt);void svc_xprt_enqueue (struct svc_xprt *xprt);void svc_xprt_put (struct svc_xprt *xprt);
include/trace/events/sunrpc.h +1 -0
@@ -1756,6 +1756,7 @@ DECLARE_EVENT_CLASS(svc_xprt_event, ), \ TP_ARGS(xprt)) +DEFINE_SVC_XPRT_EVENT (received);DEFINE_SVC_XPRT_EVENT (no_write_space);DEFINE_SVC_XPRT_EVENT (close);DEFINE_SVC_XPRT_EVENT (detach);
net/sunrpc/svc_xprt.c +9 -4
@@ -233,21 +233,25 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,return xprt; } -/* -* svc_xprt_received conditionally queues the transport for processing -* by another thread. The caller must hold the XPT_BUSY bit and must +/** +* svc_xprt_received - start next receiver thread +* @xprt: controlling transport +* +* The caller must hold the XPT_BUSY bit and must * not thereafter touch transport data. * * Note: XPT_DATA only gets cleared when a read-attempt finds no (or * insufficient) data. */ -static void svc_xprt_received (struct svc_xprt *xprt) +void svc_xprt_received (struct svc_xprt *xprt) {if (!test_bit (XPT_BUSY , &xprt->xpt_flags)) {WARN_ONCE (1 ,"xprt=0x%p already busy!" , xprt);return ; } +trace_svc_xprt_received (xprt); +/* As soon as we clear busy, the xprt could be closed and * 'put', so we need a reference to call svc_enqueue_xprt with: */
@@ -257,6 +261,7 @@ static void svc_xprt_received(struct svc_xprt *xprt) xprt->xpt_server->sv_ops->svo_enqueue_xprt (xprt);svc_xprt_put (xprt); } +EXPORT_SYMBOL_GPL (svc_xprt_received);void svc_add_new_perm_xprt (struct svc_serv *serv,struct svc_xprt *new) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 247/770 UAPI: nfsfh.h: Replace one-element array with flexible-array member
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo A. R. Silva <[email protected]>
[ Upstream commit c0a744dcaa29e9537e8607ae9c965ad936124a4d ]
There is a regular need in the kernel to provide a way to declare having a dynamically sized set of trailing elements in a structure. Kernel code should always use “flexible array members”[1] for these cases. The older style of one-element or zero-length arrays should no longer be used[2].
Use an anonymous union with a couple of anonymous structs in order to keep userspace unchanged:
$ pahole -C nfs_fhbase_new fs/nfsd/nfsfh.o
struct nfs_fhbase_new {
union {
struct {
__u8 fb_version_aux; /* 0 1 */
__u8 fb_auth_type_aux; /* 1 1 */
__u8 fb_fsid_type_aux; /* 2 1 */
__u8 fb_fileid_type_aux; /* 3 1 */
__u32 fb_auth[1]; /* 4 4 */
}; /* 0 8 */
struct {
__u8 fb_version; /* 0 1 */
__u8 fb_auth_type; /* 1 1 */
__u8 fb_fsid_type; /* 2 1 */
__u8 fb_fileid_type; /* 3 1 */
__u32 fb_auth_flex[0]; /* 4 0 */
}; /* 0 4 */
}; /* 0 8 */ /* size: 8, cachelines: 1, members: 1 */
/* last cacheline: 8 bytes */
};Also, this helps with the ongoing efforts to enable -Warray-bounds by fixing the following warnings:
fs/nfsd/nfsfh.c: In function ‘nfsd_set_fh_dentry’:fs/nfsd/nfsfh.c:191:41: warning: array subscript 1 is above array bounds of ‘__u32[1]’ {aka ‘unsigned int[1]’} [-Warray-bounds]
191 | ntohl((__force __be32)fh->fh_fsid[1])));
| ~~~~~~~~~~~^~~./include/linux/kdev_t.h:12:46: note: in definition of macro ‘MKDEV’
12 | #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
| ^~./include/uapi/linux/byteorder/little_endian.h:40:26: note: in expansion of macro ‘__swab32’
40 | #define __be32_to_cpu(x) __swab32((__force __u32)(__be32)(x))
| ^~~~~~~~
./include/linux/byteorder/generic.h:136:21: note: in expansion of macro ‘__be32_to_cpu’
136 | #define ___ntohl(x) __be32_to_cpu(x)
| ^~~~~~~~~~~~~
./include/linux/byteorder/generic.h:140:18: note: in expansion of macro ‘___ntohl’
140 | #define ntohl(x) ___ntohl(x)
| ^~~~~~~~
fs/nfsd/nfsfh.c:191:8: note: in expansion of macro ‘ntohl’
191 | ntohl((__force __be32)fh->fh_fsid[1])));
| ^~~~~
fs/nfsd/nfsfh.c:192:32: warning: array subscript 2 is above array bounds of ‘__u32[1]’ {aka ‘unsigned int[1]’} [-Warray-bounds]
192 | fh->fh_fsid[1] = fh->fh_fsid[2];
| ~~~~~~~~~~~^~~
fs/nfsd/nfsfh.c:192:15: warning: array subscript 1 is above array bounds of ‘__u32[1]’ {aka ‘unsigned int[1]’} [-Warray-bounds]
192 | fh->fh_fsid[1] = fh->fh_fsid[2];
| ~~~~~~~~~~~^~~[1] https://en.wikipedia.org/wiki/Flexible_array_member
[2] https://www.kernel.org/doc/html/v5.10/process/deprecated.html#zero-length-and-one-element-arrays
--- include/uapi/linux/nfsd/nfsfh.h | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
include/uapi/linux/nfsd/nfsfh.h +19 -8
@@ -64,13 +64,24 @@ struct nfs_fhbase_old {* in include/linux/exportfs.h for currently registered values. */ struct nfs_fhbase_new { -__u8 fb_version;/* == 1, even => nfs_fhbase_old */ -__u8 fb_auth_type; -__u8 fb_fsid_type; -__u8 fb_fileid_type; -__u32 fb_auth[1 ]; -/* __u32 fb_fsid[0]; floating */ -/* __u32 fb_fileid[0]; floating */ +union { +struct { +__u8 fb_version_aux;/* == 1, even => nfs_fhbase_old */ +__u8 fb_auth_type_aux; +__u8 fb_fsid_type_aux; +__u8 fb_fileid_type_aux; +__u32 fb_auth[1 ]; +/* __u32 fb_fsid[0]; floating */ +/* __u32 fb_fileid[0]; floating */ + }; +struct { +__u8 fb_version;/* == 1, even => nfs_fhbase_old */ +__u8 fb_auth_type; +__u8 fb_fsid_type; +__u8 fb_fileid_type; +__u32 fb_auth_flex[];/* flexible-array member */ + }; + }; };struct knfsd_fh {
@@ -97,7 +108,7 @@ struct knfsd_fh {#define fh_fsid_type fh_base.fh_new.fb_fsid_type#define fh_auth_type fh_base.fh_new.fb_auth_type#define fh_fileid_type fh_base.fh_new.fb_fileid_type -#define fh_fsid fh_base.fh_new.fb_auth +#define fh_fsid fh_base.fh_new.fb_auth_flex/* Do not use, provided for userspace compatiblity. */ #define fh_auth fh_base.fh_new.fb_auth
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 248/770 NFSD: Use DEFINE_SPINLOCK() for spinlock
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guobin Huang <[email protected]>
[ Upstream commit b73ac6808b0f7994a05ebc38571e2e9eaf98a0f4 ]
spinlock can be initialized automatically with DEFINE_SPINLOCK() rather than explicitly calling spin_lock_init().
--- fs/nfsd/nfssvc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
fs/nfsd/nfssvc.c +1 -2
@@ -84,7 +84,7 @@ DEFINE_MUTEX(nfsd_mutex);* version 4.1 DRC caches. * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage. */ -spinlock_t nfsd_drc_lock; +DEFINE_SPINLOCK (nfsd_drc_lock);unsigned long nfsd_drc_max_mem;unsigned long nfsd_drc_mem_used;
@@ -563,7 +563,6 @@ static void set_max_drc(void) nfsd_drc_max_mem = (nr_free_buffer_pages () >>NFSD_DRC_SIZE_SHIFT ) *PAGE_SIZE ; nfsd_drc_mem_used =0 ; -spin_lock_init (&nfsd_drc_lock);dprintk ("%s nfsd_drc_max_mem %lu \n" , __func__, nfsd_drc_max_mem); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 249/770 fsnotify: allow fsnotify_{peek,remove}_first_event with empty queue
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 6f73171e192366ff7c98af9fb50615ef9615f8a7 ]
Current code has an assumtion that fsnotify_notify_queue_is_empty() is called to verify that queue is not empty before trying to peek or remove an event from queue.
Remove this assumption by moving the fsnotify_notify_queue_is_empty() into the functions, allow them to return NULL value and check return value by all callers.
This is a prep patch for multi event queues.
--- fs/notify/fanotify/fanotify_user.c | 26 +++++++++++------- fs/notify/inotify/inotify_user.c | 5 ++-- fs/notify/notification.c | 42 ++++++++++++++---------------- include/linux/fsnotify_backend.h | 8 +++++- 4 files changed, 44 insertions(+), 37 deletions(-)
fs/notify/fanotify/fanotify_user.c +16 -10
@@ -100,24 +100,30 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group, {size_t event_size =FAN_EVENT_METADATA_LEN ;struct fanotify_event *event =NULL ; +struct fsnotify_event *fsn_event;unsigned int fid_mode =FAN_GROUP_FLAG (group,FANOTIFY_FID_BITS );pr_debug ("%s: group=%p count=%zd\n" , __func__, group, count);spin_lock (&group->notification_lock); -if (fsnotify_notify_queue_is_empty (group)) + fsn_event =fsnotify_peek_first_event (group); +if (!fsn_event) goto out; -if (fid_mode) { - event_size +=fanotify_event_info_len (fid_mode, -FANOTIFY_E (fsnotify_peek_first_event (group))); - } + event =FANOTIFY_E (fsn_event); +if (fid_mode) + event_size +=fanotify_event_info_len (fid_mode, event);if (event_size > count) { event =ERR_PTR (-EINVAL ); goto out; } - event =FANOTIFY_E (fsnotify_remove_first_event (group)); + +/* +* Held the notification_lock the whole time, so this is the +* same event we peeked above. +*/ +fsnotify_remove_first_event (group);if (fanotify_is_perm_event (event->mask))FANOTIFY_PERM (event)->state =FAN_EVENT_REPORTED ; out:
@@ -573,6 +579,7 @@ static ssize_t fanotify_write(struct file *file, const char __user *buf, size_tstatic int fanotify_release (struct inode *ignored,struct file *file) {struct fsnotify_group *group = file->private_data; +struct fsnotify_event *fsn_event;/* * Stop new events from arriving in the notification queue. since
@@ -601,13 +608,12 @@ static int fanotify_release(struct inode *ignored, struct file *file)* dequeue them and set the response. They will be freed once the * response is consumed and fanotify_get_response() returns. */ -while (!fsnotify_notify_queue_is_empty (group)) { -struct fanotify_event *event; +while ((fsn_event =fsnotify_remove_first_event (group))) { +struct fanotify_event *event =FANOTIFY_E (fsn_event); - event =FANOTIFY_E (fsnotify_remove_first_event (group));if (!(event->mask &FANOTIFY_PERM_EVENTS )) {spin_unlock (&group->notification_lock); -fsnotify_destroy_event (group, &event->fse); +fsnotify_destroy_event (group, fsn_event); }else {finish_permission_event (group,FANOTIFY_PERM (event),FAN_ALLOW );
fs/notify/inotify/inotify_user.c +2 -3
@@ -146,10 +146,9 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,size_t event_size =sizeof (struct inotify_event );struct fsnotify_event *event; -if (fsnotify_notify_queue_is_empty (group)) -return NULL ; - event =fsnotify_peek_first_event (group); +if (!event) +return NULL ;pr_debug ("%s: group=%p event=%p\n" , __func__, group, event);
fs/notify/notification.c +19 -23
65 lines not on this page · raw message
include/linux/fsnotify_backend.h +7 -1
@@ -495,7 +495,13 @@ static inline void fsnotify_queue_overflow(struct fsnotify_group *group)fsnotify_add_event (group, group->overflow_event,NULL ); } -/* true if the group notification queue is empty */ +static inline bool fsnotify_notify_queue_is_empty (struct fsnotify_group *group) +{ +assert_spin_locked (&group->notification_lock); + +return list_empty (&group->notification_list); +} +extern bool fsnotify_notify_queue_is_empty (struct fsnotify_group *group);/* return, but do not dequeue the first event on the notification queue */ extern struct fsnotify_event *fsnotify_peek_first_event (struct fsnotify_group *group);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 250/770 Revert "fanotify: limit number of event merge attempts"
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
Temporarily revert commit ad3ea16746cc ("fanotify: limit number of event merge attempts") to enable subsequent upstream commits to apply and build cleanly.
Stable-dep-of: 8988f11abb82 ("fanotify: reduce event objectid to 29-bit hash")
--- fs/notify/fanotify/fanotify.c | 6 ------ 1 file changed, 6 deletions(-)
fs/notify/fanotify/fanotify.c +0 -6
@@ -129,15 +129,11 @@ static bool fanotify_should_merge(struct fsnotify_event *old_fsn,return false; } -/* Limit event merges to limit CPU overhead per event */ -#define FANOTIFY_MAX_MERGE_EVENTS 128 -/* and the list better be locked by something too! */ static int fanotify_merge (struct list_head *list,struct fsnotify_event *event) {struct fsnotify_event *test_event;struct fanotify_event *new; -int i =0 ;pr_debug ("%s: list=%p event=%p\n" , __func__, list, event); new =FANOTIFY_E (event);
@@ -151,8 +147,6 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)return 0 ;list_for_each_entry_reverse (test_event, list, list) { -if (++i >FANOTIFY_MAX_MERGE_EVENTS ) -break ;if (fanotify_should_merge (test_event, event)) {FANOTIFY_E (test_event)->mask |= new->mask;return 1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 251/770 fanotify: reduce event objectid to 29-bit hash
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 8988f11abb820bacfcc53d498370bfb30f792ec4 ]
objectid is only used by fanotify backend and it is just an optimization for event merge before comparing all fields in event.
Move the objectid member from common struct fsnotify_event into struct fanotify_event and reduce it to 29-bit hash to cram it together with the 3-bit event type.
Events of different types are never merged, so the combination of event type and hash form a 32-bit key for fast compare of events.
This reduces the size of events by one pointer and paves the way for adding hashed queue support for fanotify.
--- fs/notify/fanotify/fanotify.c | 25 ++++++++++++------------- fs/notify/fanotify/fanotify.h | 16 +++++++++++++--- fs/notify/inotify/inotify_fsnotify.c | 2 +- fs/notify/inotify/inotify_user.c | 2 +- include/linux/fsnotify_backend.h | 5 +---- 5 files changed, 28 insertions(+), 22 deletions(-)
fs/notify/fanotify/fanotify.c +12 -13
@@ -88,16 +88,12 @@ static bool fanotify_name_event_equal(struct fanotify_name_event *fne1,return fanotify_info_equal (info1, info2); } -static bool fanotify_should_merge (struct fsnotify_event *old_fsn, -struct fsnotify_event *new_fsn) +static bool fanotify_should_merge (struct fanotify_event *old, +struct fanotify_event *new) { -struct fanotify_event *old, *new; +pr_debug ("%s: old=%p new=%p\n" , __func__, old, new); -pr_debug ("%s: old=%p new=%p\n" , __func__, old_fsn, new_fsn); - old =FANOTIFY_E (old_fsn); - new =FANOTIFY_E (new_fsn); - -if (old_fsn->objectid != new_fsn->objectid || +if (old->hash != new->hash || old->type != new->type || old->pid != new->pid)return false;
@@ -133,10 +129,9 @@ static bool fanotify_should_merge(struct fsnotify_event *old_fsn,static int fanotify_merge (struct list_head *list,struct fsnotify_event *event) {struct fsnotify_event *test_event; -struct fanotify_event *new; +struct fanotify_event *old, *new =FANOTIFY_E (event);pr_debug ("%s: list=%p event=%p\n" , __func__, list, event); - new =FANOTIFY_E (event);/* * Don't merge a permission event with any other event so that we know
@@ -147,8 +142,9 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)return 0 ;list_for_each_entry_reverse (test_event, list, list) { -if (fanotify_should_merge (test_event, event)) { -FANOTIFY_E (test_event)->mask |= new->mask; + old =FANOTIFY_E (test_event); +if (fanotify_should_merge (old, new)) { + old->mask |= new->mask;return 1 ; } }
@@ -533,6 +529,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,struct mem_cgroup *old_memcg;struct inode *child =NULL ;bool name_event = false; +unsigned int hash =0 ;if ((fid_mode &FAN_REPORT_DIR_FID ) && dirid) {/*
@@ -600,8 +597,10 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,* Use the victim inode instead of the watching inode as the id for * event queue, so event reported on parent is merged with event * reported on child when both directory and child watches exist. +* Hash object id for queue merge. */ -fanotify_init_event (event, (unsigned long )id, mask); + hash =hash_ptr (id,FANOTIFY_EVENT_HASH_BITS ); +fanotify_init_event (event, hash, mask);if (FAN_GROUP_FLAG (group,FAN_REPORT_TID )) event->pid =get_pid (task_pid (current));else
fs/notify/fanotify/fanotify.h +13 -3
@@ -135,19 +135,29 @@ enum fanotify_event_type {FANOTIFY_EVENT_TYPE_PATH ,FANOTIFY_EVENT_TYPE_PATH_PERM ,FANOTIFY_EVENT_TYPE_OVERFLOW ,/* struct fanotify_event */ + __FANOTIFY_EVENT_TYPE_NUM }; +#define FANOTIFY_EVENT_TYPE_BITS \ + (ilog2(__FANOTIFY_EVENT_TYPE_NUM - 1) + 1) +#define FANOTIFY_EVENT_HASH_BITS \ + (32 - FANOTIFY_EVENT_TYPE_BITS) +struct fanotify_event {struct fsnotify_event fse;u32 mask; -enum fanotify_event_type type; +struct { +unsigned int type :FANOTIFY_EVENT_TYPE_BITS ; +unsigned int hash :FANOTIFY_EVENT_HASH_BITS ; + };struct pid *pid; };static inline void fanotify_init_event (struct fanotify_event *event, -unsigned long id,u32 mask) +unsigned int hash,u32 mask) { -fsnotify_init_event (&event->fse, id); +fsnotify_init_event (&event->fse); + event->hash = hash; event->mask = mask; event->pid =NULL ; }
fs/notify/inotify/inotify_fsnotify.c +1 -1
@@ -114,7 +114,7 @@ int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask, mask &= ~IN_ISDIR ; fsn_event = &event->fse; -fsnotify_init_event (fsn_event,0 ); +fsnotify_init_event (fsn_event); event->mask = mask; event->wd = wd; event->sync_cookie = cookie;
fs/notify/inotify/inotify_user.c +1 -1
@@ -641,7 +641,7 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events)return ERR_PTR (-ENOMEM ); } group->overflow_event = &oevent->fse; -fsnotify_init_event (group->overflow_event,0 ); +fsnotify_init_event (group->overflow_event); oevent->mask =FS_Q_OVERFLOW ; oevent->wd =-1 ; oevent->sync_cookie =0 ;
include/linux/fsnotify_backend.h +1 -4
@@ -167,7 +167,6 @@ struct fsnotify_ops {*/ struct fsnotify_event {struct list_head list; -unsigned long objectid;/* identifier for queue merges */ };/*
@@ -582,11 +581,9 @@ extern void fsnotify_put_mark(struct fsnotify_mark *mark);extern void fsnotify_finish_user_wait (struct fsnotify_iter_info *iter_info);extern bool fsnotify_prepare_user_wait (struct fsnotify_iter_info *iter_info); -static inline void fsnotify_init_event (struct fsnotify_event *event, -unsigned long objectid) +static inline void fsnotify_init_event (struct fsnotify_event *event) {INIT_LIST_HEAD (&event->list); - event->objectid = objectid; }#else
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 252/770 fanotify: mix event info and pid into merge key hash
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 7e3e5c6943994943eb76cab2d3a1806bc10b9045 ]
Improve the merge key hash by mixing more values relevant for merge.
For example, all FAN_CREATE name events in the same dir used to have the same merge key based on the dir inode. With this change the created file name is mixed into the merge key.
The object id that was used as merge key is redundant to the event info so it is no longer mixed into the hash.
Permission events are not hashed, so no need to hash their info.
--- fs/notify/fanotify/fanotify.c | 87 ++++++++++++++++++++++++----------- fs/notify/fanotify/fanotify.h | 5 ++ 2 files changed, 66 insertions(+), 26 deletions(-)
fs/notify/fanotify/fanotify.c +61 -26
@@ -14,6 +14,7 @@#include <linux/audit.h> #include <linux/sched/mm.h> #include <linux/statfs.h> +#include <linux/stringhash.h> #include "fanotify.h"
@@ -22,12 +23,24 @@ static bool fanotify_path_equal(struct path *p1, struct path *p2)return p1->mnt == p2->mnt && p1->dentry == p2->dentry; } +static unsigned int fanotify_hash_path (const struct path *path) +{ +return hash_ptr (path->dentry,FANOTIFY_EVENT_HASH_BITS ) ^ +hash_ptr (path->mnt,FANOTIFY_EVENT_HASH_BITS ); +} +static inline bool fanotify_fsid_equal (__kernel_fsid_t *fsid1,__kernel_fsid_t *fsid2) {return fsid1->val[0 ] == fsid2->val[0 ] && fsid1->val[1 ] == fsid2->val[1 ]; } +static unsigned int fanotify_hash_fsid (__kernel_fsid_t *fsid) +{ +return hash_32 (fsid->val[0 ],FANOTIFY_EVENT_HASH_BITS ) ^ +hash_32 (fsid->val[1 ],FANOTIFY_EVENT_HASH_BITS ); +} +static bool fanotify_fh_equal (struct fanotify_fh *fh1,struct fanotify_fh *fh2) {
@@ -38,6 +51,16 @@ static bool fanotify_fh_equal(struct fanotify_fh *fh1, !memcmp (fanotify_fh_buf (fh1),fanotify_fh_buf (fh2), fh1->len); } +static unsigned int fanotify_hash_fh (struct fanotify_fh *fh) +{ +long salt = (long )fh->type | (long )fh->len <<8 ; + +/* +* full_name_hash() works long by long, so it handles fh buf optimally. +*/ +return full_name_hash ((void *)salt,fanotify_fh_buf (fh), fh->len); +} +static bool fanotify_fid_event_equal (struct fanotify_fid_event *ffe1,struct fanotify_fid_event *ffe2) {
@@ -325,7 +348,8 @@ static int fanotify_encode_fh_len(struct inode *inode)* Return 0 on failure to encode. */ static int fanotify_encode_fh (struct fanotify_fh *fh,struct inode *inode, -unsigned int fh_len,gfp_t gfp) +unsigned int fh_len,unsigned int *hash, +gfp_t gfp) {int dwords, type =0 ;char *ext_buf =NULL ;
@@ -368,6 +392,9 @@ static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, fh->type = type; fh->len = fh_len; +/* Mix fh into event merge key */ + *hash ^=fanotify_hash_fh (fh); +return FANOTIFY_FH_HDR_LEN + fh_len; out_err:
@@ -421,6 +448,7 @@ static struct inode *fanotify_dfid_inode(u32 event_mask, const void *data, }static struct fanotify_event *fanotify_alloc_path_event (const struct path *path, +unsigned int *hash,gfp_t gfp) {struct fanotify_path_event *pevent;
@@ -431,6 +459,7 @@ static struct fanotify_event *fanotify_alloc_path_event(const struct path *path, pevent->fae.type =FANOTIFY_EVENT_TYPE_PATH ; pevent->path = *path; + *hash ^=fanotify_hash_path (path);path_get (path);return &pevent->fae;
@@ -456,6 +485,7 @@ static struct fanotify_event *fanotify_alloc_perm_event(const struct path *path,static struct fanotify_event *fanotify_alloc_fid_event (struct inode *id,__kernel_fsid_t *fsid, +unsigned int *hash,gfp_t gfp) {struct fanotify_fid_event *ffe;
@@ -466,16 +496,18 @@ static struct fanotify_event *fanotify_alloc_fid_event(struct inode *id, ffe->fae.type =FANOTIFY_EVENT_TYPE_FID ; ffe->fsid = *fsid; + *hash ^=fanotify_hash_fsid (fsid);fanotify_encode_fh (&ffe->object_fh, id,fanotify_encode_fh_len (id), - gfp); + hash, gfp);return &ffe->fae; }static struct fanotify_event *fanotify_alloc_name_event (struct inode *id,__kernel_fsid_t *fsid, -const struct qstr *file_name, +const struct qstr *name,struct inode *child, +unsigned int *hash,gfp_t gfp) {struct fanotify_name_event *fne;
@@ -488,24 +520,30 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id, size =sizeof (*fne) +FANOTIFY_FH_HDR_LEN + dir_fh_len;if (child_fh_len) size +=FANOTIFY_FH_HDR_LEN + child_fh_len; -if (file_name) - size += file_name->len +1 ; +if (name) + size += name->len +1 ; fne =kmalloc (size, gfp);if (!fne)return NULL ; fne->fae.type =FANOTIFY_EVENT_TYPE_FID_NAME ; fne->fsid = *fsid; + *hash ^=fanotify_hash_fsid (fsid); info = &fne->info;fanotify_info_init (info); dfh =fanotify_info_dir_fh (info); - info->dir_fh_totlen =fanotify_encode_fh (dfh, id, dir_fh_len,0 ); + info->dir_fh_totlen =fanotify_encode_fh (dfh, id, dir_fh_len, hash,0 );if (child_fh_len) { ffh =fanotify_info_file_fh (info); - info->file_fh_totlen =fanotify_encode_fh (ffh, child, child_fh_len,0 ); + info->file_fh_totlen =fanotify_encode_fh (ffh, child, + child_fh_len, hash,0 ); + } +if (name) { +long salt = name->len; + +fanotify_info_copy_name (info, name); + *hash ^=full_name_hash ((void *)salt, name->name, name->len); } -if (file_name) -fanotify_info_copy_name (info, file_name); pr_debug("%s: ino=%lu size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n", __func__, id->i_ino, size, dir_fh_len, child_fh_len,
@@ -530,6 +568,8 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,struct inode *child =NULL ;bool name_event = false;unsigned int hash =0 ; +bool ondir = mask &FAN_ONDIR ; +struct pid *pid;if ((fid_mode &FAN_REPORT_DIR_FID ) && dirid) {/*
@@ -537,8 +577,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,* report the child fid for events reported on a non-dir child * in addition to reporting the parent fid and maybe child name. */ -if ((fid_mode &FAN_REPORT_FID ) && - id != dirid && !(mask &FAN_ONDIR )) +if ((fid_mode &FAN_REPORT_FID ) && id != dirid && !ondir) child = id; id = dirid;
@@ -559,8 +598,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,if (!(fid_mode &FAN_REPORT_NAME )) { name_event = !!child; file_name =NULL ; - }else if ((mask &ALL_FSNOTIFY_DIRENT_EVENTS ) || - !(mask &FAN_ONDIR )) { + }else if ((mask &ALL_FSNOTIFY_DIRENT_EVENTS ) || !ondir) { name_event = true; } }
@@ -583,28 +621,25 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, event =fanotify_alloc_perm_event (path, gfp); }else if (name_event && (file_name || child)) { event =fanotify_alloc_name_event (id, fsid, file_name, child, - gfp); + &hash, gfp); }else if (fid_mode) { - event =fanotify_alloc_fid_event (id, fsid, gfp); + event =fanotify_alloc_fid_event (id, fsid, &hash, gfp); }else { - event =fanotify_alloc_path_event (path, gfp); + event =fanotify_alloc_path_event (path, &hash, gfp); }if (!event) goto out; -/* -* Use the victim inode instead of the watching inode as the id for -* event queue, so event reported on parent is merged with event -* reported on child when both directory and child watches exist. -* Hash object id for queue merge. -*/ - hash =hash_ptr (id,FANOTIFY_EVENT_HASH_BITS ); -fanotify_init_event (event, hash, mask);if (FAN_GROUP_FLAG (group,FAN_REPORT_TID )) - event->pid =get_pid (task_pid (current)); + pid =get_pid (task_pid (current));else - event->pid =get_pid (task_tgid (current)); + pid =get_pid (task_tgid (current)); + +/* Mix event info, FAN_ONDIR flag and pid into event merge key */ + hash ^=hash_long ((unsigned long )pid | ondir,FANOTIFY_EVENT_HASH_BITS ); +fanotify_init_event (event, hash, mask); + event->pid = pid; out:set_active_memcg (old_memcg);
fs/notify/fanotify/fanotify.h +5 -0
@@ -115,6 +115,11 @@ static inline void fanotify_info_init(struct fanotify_info *info) info->name_len =0 ; } +static inline unsigned int fanotify_info_len (struct fanotify_info *info) +{ +return info->dir_fh_totlen + info->file_fh_totlen + info->name_len; +} +static inline void fanotify_info_copy_name (struct fanotify_info *info,const struct qstr *name) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 253/770 fsnotify: use hash table for faster events merge
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 94e00d28a680dff18805ca472b191364347d2234 ]
In order to improve event merge performance, hash events in a 128 size hash table by the event merge key.
The fanotify_event size grows by two pointers, but we just reduced its size by removing the objectid member, so overall its size is increased by one pointer.
Permission events and overflow event are not merged so they are also not hashed.
--- fs/notify/fanotify/fanotify.c | 40 +++++++++++++++++++++++----- fs/notify/fanotify/fanotify.h | 25 +++++++++++++++++ fs/notify/fanotify/fanotify_user.c | 39 +++++++++++++++++++++++++++ fs/notify/inotify/inotify_fsnotify.c | 7 ++--- fs/notify/notification.c | 22 ++++++++++----- include/linux/fsnotify_backend.h | 10 ++++--- 6 files changed, 123 insertions(+), 20 deletions(-)
fs/notify/fanotify/fanotify.c +33 -7
@@ -149,12 +149,15 @@ static bool fanotify_should_merge(struct fanotify_event *old, }/* and the list better be locked by something too! */ -static int fanotify_merge (struct list_head *list,struct fsnotify_event *event) +static int fanotify_merge (struct fsnotify_group *group, +struct fsnotify_event *event) { -struct fsnotify_event *test_event;struct fanotify_event *old, *new =FANOTIFY_E (event); +unsigned int bucket =fanotify_event_hash_bucket (group, new); +struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket]; -pr_debug ("%s: list=%p event=%p\n" , __func__, list, event); +pr_debug ("%s: group=%p event=%p bucket=%u\n" , __func__, + group, event, bucket);/* * Don't merge a permission event with any other event so that we know
@@ -164,8 +167,7 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)if (fanotify_is_perm_event (new->mask))return 0 ; -list_for_each_entry_reverse (test_event, list, list) { - old =FANOTIFY_E (test_event); +hlist_for_each_entry (old, hlist, merge_list) {if (fanotify_should_merge (old, new)) { old->mask |= new->mask;return 1 ;
@@ -203,8 +205,11 @@ static int fanotify_get_response(struct fsnotify_group *group,return ret; }/* Event not yet reported? Just remove it. */ -if (event->state ==FAN_EVENT_INIT ) +if (event->state ==FAN_EVENT_INIT ) {fsnotify_remove_queued_event (group, &event->fae.fse); +/* Permission events are not supposed to be hashed */ +WARN_ON_ONCE (!hlist_unhashed (&event->fae.merge_list)); + }/* * Event may be also answered in case signal delivery raced * with wakeup. In that case we have nothing to do besides
@@ -679,6 +684,24 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)return fsid; } +/* +* Add an event to hash table for faster merge. +*/ +static void fanotify_insert_event (struct fsnotify_group *group, +struct fsnotify_event *fsn_event) +{ +struct fanotify_event *event =FANOTIFY_E (fsn_event); +unsigned int bucket =fanotify_event_hash_bucket (group, event); +struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket]; + +assert_spin_locked (&group->notification_lock); + +pr_debug ("%s: group=%p event=%p bucket=%u\n" , __func__, + group, event, bucket); + +hlist_add_head (&event->merge_list, hlist); +} + static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, const void *data, int data_type, struct inode *dir,
@@ -749,7 +772,9 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, } fsn_event = &event->fse; - ret =fsnotify_add_event (group, fsn_event, fanotify_merge); + ret =fsnotify_add_event (group, fsn_event, fanotify_merge, +fanotify_is_hashed_event (mask) ? + fanotify_insert_event :NULL );if (ret) {/* Permission events shouldn't be merged */ BUG_ON (ret ==1 && mask &FANOTIFY_PERM_EVENTS );
@@ -772,6 +797,7 @@ static void fanotify_free_group_priv(struct fsnotify_group *group) {struct user_struct *user; +kfree (group->fanotify_data.merge_hash); user = group->fanotify_data.user;atomic_dec (&user->fanotify_listeners);free_uid (user);
fs/notify/fanotify/fanotify.h +25 -0
@@ -3,6 +3,7 @@#include <linux/path.h> #include <linux/slab.h> #include <linux/exportfs.h> +#include <linux/hashtable.h> extern struct kmem_cache *fanotify_mark_cache;extern struct kmem_cache *fanotify_fid_event_cachep;
@@ -150,6 +151,7 @@ enum fanotify_event_type {struct fanotify_event {struct fsnotify_event fse; +struct hlist_node merge_list;/* List for hashed merge */ u32 mask;struct {unsigned int type :FANOTIFY_EVENT_TYPE_BITS ;
@@ -162,6 +164,7 @@ static inline void fanotify_init_event(struct fanotify_event *event, unsigned int hash, u32 mask) {fsnotify_init_event (&event->fse); +INIT_HLIST_NODE (&event->merge_list); event->hash = hash; event->mask = mask; event->pid =NULL ;
@@ -299,3 +302,25 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event)else return NULL ; } + +/* +* Use 128 size hash table to speed up events merge. +*/ +#define FANOTIFY_HTABLE_BITS (7) +#define FANOTIFY_HTABLE_SIZE (1 << FANOTIFY_HTABLE_BITS) +#define FANOTIFY_HTABLE_MASK (FANOTIFY_HTABLE_SIZE - 1) + +/* +* Permission events and overflow event do not get merged - don't hash them. +*/ +static inline bool fanotify_is_hashed_event (u32 mask) +{ +return !fanotify_is_perm_event (mask) && !(mask &FS_Q_OVERFLOW ); +} + +static inline unsigned int fanotify_event_hash_bucket ( +struct fsnotify_group *group, +struct fanotify_event *event) +{ +return event->hash &FANOTIFY_HTABLE_MASK ; +}
fs/notify/fanotify/fanotify_user.c +39 -0
@@ -89,6 +89,23 @@ static int fanotify_event_info_len(unsigned int fid_mode,return info_len; } +/* +* Remove an hashed event from merge hash table. +*/ +static void fanotify_unhash_event (struct fsnotify_group *group, +struct fanotify_event *event) +{ +assert_spin_locked (&group->notification_lock); + +pr_debug ("%s: group=%p event=%p bucket=%u\n" , __func__, + group, event,fanotify_event_hash_bucket (group, event)); + +if (WARN_ON_ONCE (hlist_unhashed (&event->merge_list))) +return ; + +hlist_del_init (&event->merge_list); +} +/* * Get an fanotify notification event if one exists and is small * enough to fit in "count". Return an error pointer if the count
@@ -126,6 +143,8 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group,fsnotify_remove_first_event (group);if (fanotify_is_perm_event (event->mask))FANOTIFY_PERM (event)->state =FAN_EVENT_REPORTED ; +if (fanotify_is_hashed_event (event->mask)) +fanotify_unhash_event (group, event); out:spin_unlock (&group->notification_lock);return event;
@@ -925,6 +944,20 @@ static struct fsnotify_event *fanotify_alloc_overflow_event(void)return &oevent->fse; } +static struct hlist_head *fanotify_alloc_merge_hash (void ) +{ +struct hlist_head *hash; + + hash =kmalloc (sizeof (struct hlist_head ) <<FANOTIFY_HTABLE_BITS , +GFP_KERNEL_ACCOUNT ); +if (!hash) +return NULL ; + +__hash_init (hash,FANOTIFY_HTABLE_SIZE ); + +return hash; +} +/* fanotify syscalls */ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) {
@@ -993,6 +1026,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)atomic_inc (&user->fanotify_listeners); group->memcg =get_mem_cgroup_from_mm (current->mm); + group->fanotify_data.merge_hash =fanotify_alloc_merge_hash (); +if (!group->fanotify_data.merge_hash) { + fd = -ENOMEM ; + goto out_destroy_group; + } + group->overflow_event =fanotify_alloc_overflow_event ();if (unlikely (!group->overflow_event)) { fd = -ENOMEM ;
fs/notify/inotify/inotify_fsnotify.c +4 -3
@@ -46,9 +46,10 @@ static bool event_compare(struct fsnotify_event *old_fsn,return false; } -static int inotify_merge (struct list_head *list, -struct fsnotify_event *event) +static int inotify_merge (struct fsnotify_group *group, +struct fsnotify_event *event) { +struct list_head *list = &group->notification_list;struct fsnotify_event *last_event; last_event = list_entry(list->prev, struct fsnotify_event, list);
@@ -122,7 +123,7 @@ int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask,if (len)strcpy (event->name, name->name); - ret =fsnotify_add_event (group, fsn_event, inotify_merge); + ret =fsnotify_add_event (group, fsn_event, inotify_merge,NULL );if (ret) {/* Our event wasn't used in the end. Free it. */ fsnotify_destroy_event (group, fsn_event);
fs/notify/notification.c +15 -7
@@ -68,16 +68,22 @@ void fsnotify_destroy_event(struct fsnotify_group *group, }/* -* Add an event to the group notification queue. The group can later pull this -* event off the queue to deal with. The function returns 0 if the event was -* added to the queue, 1 if the event was merged with some other queued event, +* Try to add an event to the notification queue. +* The group can later pull this event off the queue to deal with. +* The group can use the @merge hook to merge the event with a queued event. +* The group can use the @insert hook to insert the event into hash table. +* The function returns: +* 0 if the event was added to a queue +* 1 if the event was merged with some other queued event * 2 if the event was not queued - either the queue of events has overflown -* or the group is shutting down. +* or the group is shutting down. */ int fsnotify_add_event (struct fsnotify_group *group,struct fsnotify_event *event, -int (*merge)(struct list_head *, -struct fsnotify_event *)) +int (*merge)(struct fsnotify_group *, +struct fsnotify_event *), +void (*insert)(struct fsnotify_group *, +struct fsnotify_event *)) {int ret =0 ;struct list_head *list = &group->notification_list;
@@ -104,7 +110,7 @@ int fsnotify_add_event(struct fsnotify_group *group, }if (!list_empty (list) && merge) { - ret =merge (list, event); + ret =merge (group, event);if (ret) {spin_unlock (&group->notification_lock);return ret;
@@ -114,6 +120,8 @@ int fsnotify_add_event(struct fsnotify_group *group, queue: group->q_len++;list_add_tail (&event->list, list); +if (insert) +insert (group, event);spin_unlock (&group->notification_lock);wake_up (&group->notification_waitq);
include/linux/fsnotify_backend.h +7 -3
@@ -233,6 +233,8 @@ struct fsnotify_group {#endif #ifdef CONFIG_FANOTIFY struct fanotify_group_private_data { + /* Hash table of events for merge */ + struct hlist_head *merge_hash; /* allows a group to block waiting for a userspace response */ struct list_head access_list; wait_queue_head_t access_waitq;
@@ -486,12 +488,14 @@ extern void fsnotify_destroy_event(struct fsnotify_group *group,/* attach the event to the group notification queue */ extern int fsnotify_add_event (struct fsnotify_group *group,struct fsnotify_event *event, -int (*merge)(struct list_head *, -struct fsnotify_event *)); +int (*merge)(struct fsnotify_group *, +struct fsnotify_event *), +void (*insert)(struct fsnotify_group *, +struct fsnotify_event *));/* Queue overflow event to a notification group */ static inline void fsnotify_queue_overflow (struct fsnotify_group *group) { -fsnotify_add_event (group, group->overflow_event,NULL ); +fsnotify_add_event (group, group->overflow_event,NULL ,NULL ); }static inline bool fsnotify_notify_queue_is_empty (struct fsnotify_group *group)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 254/770 fanotify: limit number of event merge attempts
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit b8cd0ee8cda68a888a317991c1e918a8cba1a568 ]
Event merges are expensive when event queue size is large, so limit the linear search to 128 merge tests.
In combination with 128 size hash table, there is a potential to merge with up to 16K events in the hashed queue.
--- fs/notify/fanotify/fanotify.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/notify/fanotify/fanotify.c +6 -0
@@ -148,6 +148,9 @@ static bool fanotify_should_merge(struct fanotify_event *old,return false; } +/* Limit event merges to limit CPU overhead per event */ +#define FANOTIFY_MAX_MERGE_EVENTS 128 +/* and the list better be locked by something too! */ static int fanotify_merge (struct fsnotify_group *group,struct fsnotify_event *event)
@@ -155,6 +158,7 @@ static int fanotify_merge(struct fsnotify_group *group,struct fanotify_event *old, *new =FANOTIFY_E (event);unsigned int bucket =fanotify_event_hash_bucket (group, new);struct hlist_head *hlist = &group->fanotify_data.merge_hash[bucket]; +int i =0 ;pr_debug ("%s: group=%p event=%p bucket=%u\n" , __func__, group, event, bucket);
@@ -168,6 +172,8 @@ static int fanotify_merge(struct fsnotify_group *group,return 0 ;hlist_for_each_entry (old, hlist, merge_list) { +if (++i >FANOTIFY_MAX_MERGE_EVENTS ) +break ;if (fanotify_should_merge (old, new)) { old->mask |= new->mask;return 1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 255/770 fanotify: configurable limits via sysfs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 5b8fea65d197f408bb00b251c70d842826d6b70b ]
fanotify has some hardcoded limits. The only APIs to escape those limits are FAN_UNLIMITED_QUEUE and FAN_UNLIMITED_MARKS.
Allow finer grained tuning of the system limits via sysfs tunables under /proc/sys/fs/fanotify, similar to tunables under /proc/sys/fs/inotify, with some minor differences.
- max_queued_events - global system tunable for group queue size limit. Like the inotify tunable with the same name, it defaults to 16384 and applies on initialization of a new group.
- max_user_marks - user ns tunable for marks limit per user. Like the inotify tunable named max_user_watches, on a machine with sufficient RAM and it defaults to 1048576 in init userns and can be further limited per containing user ns.
- max_user_groups - user ns tunable for number of groups per user. Like the inotify tunable named max_user_instances, it defaults to 128 in init userns and can be further limited per containing user ns.
The slightly different tunable names used for fanotify are derived from the "group" and "mark" terminology used in the fanotify man pages and throughout the code.
Considering the fact that the default value for max_user_instances was increased in kernel v5.10 from 8192 to 1048576, leaving the legacy fanotify limit of 8192 marks per group in addition to the max_user_marks limit makes little sense, so the per group marks limit has been removed.
Note that when a group is initialized with FAN_UNLIMITED_MARKS, its own marks are not accounted in the per user marks account, so in effect the limit of max_user_marks is only for the collection of groups that are not initialized with FAN_UNLIMITED_MARKS.
--- fs/notify/fanotify/fanotify.c | 16 ++-- fs/notify/fanotify/fanotify_user.c | 123 ++++++++++++++++++++++++----- fs/notify/group.c | 1 - fs/notify/mark.c | 4 - include/linux/fanotify.h | 3 + include/linux/fsnotify_backend.h | 6 +- include/linux/sched/user.h | 3 - include/linux/user_namespace.h | 4 + kernel/sysctl.c | 12 ++- kernel/ucount.c | 4 + 10 files changed, 137 insertions(+), 39 deletions(-)
fs/notify/fanotify/fanotify.c +11 -5
@@ -801,12 +801,10 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,static void fanotify_free_group_priv (struct fsnotify_group *group) { -struct user_struct *user; -kfree (group->fanotify_data.merge_hash); - user = group->fanotify_data.user; -atomic_dec (&user->fanotify_listeners); -free_uid (user); +if (group->fanotify_data.ucounts) +dec_ucount (group->fanotify_data.ucounts, +UCOUNT_FANOTIFY_GROUPS ); }static void fanotify_free_path_event (struct fanotify_event *event)
@@ -862,6 +860,13 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event) } } +static void fanotify_freeing_mark (struct fsnotify_mark *mark, +struct fsnotify_group *group) +{ +if (!FAN_GROUP_FLAG (group,FAN_UNLIMITED_MARKS )) +dec_ucount (group->fanotify_data.ucounts,UCOUNT_FANOTIFY_MARKS ); +} +static void fanotify_free_mark (struct fsnotify_mark *fsn_mark) {kmem_cache_free (fanotify_mark_cache, fsn_mark);
@@ -871,5 +876,6 @@ const struct fsnotify_ops fanotify_fsnotify_ops = { .handle_event = fanotify_handle_event, .free_group_priv = fanotify_free_group_priv, .free_event = fanotify_free_event, + .freeing_mark = fanotify_freeing_mark, .free_mark = fanotify_free_mark, };
fs/notify/fanotify/fanotify_user.c +103 -20
195 lines not on this page · raw message
fs/notify/group.c +0 -1
@@ -122,7 +122,6 @@ static struct fsnotify_group *__fsnotify_alloc_group(/* set to 0 when there a no external references to this group */ refcount_set (&group->refcnt,1 ); -atomic_set (&group->num_marks,0 );atomic_set (&group->user_waits,0 );spin_lock_init (&group->notification_lock);
fs/notify/mark.c +0 -4
@@ -391,8 +391,6 @@ void fsnotify_detach_mark(struct fsnotify_mark *mark)list_del_init (&mark->g_list);spin_unlock (&mark->lock); -atomic_dec (&group->num_marks); -/* Drop mark reference acquired in fsnotify_add_mark_locked() */ fsnotify_put_mark (mark); }
@@ -656,7 +654,6 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, mark->flags |=FSNOTIFY_MARK_FLAG_ALIVE |FSNOTIFY_MARK_FLAG_ATTACHED ;list_add (&mark->g_list, &group->marks_list); -atomic_inc (&group->num_marks);fsnotify_get_mark (mark);/* for g_list */ spin_unlock (&mark->lock);
@@ -674,7 +671,6 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, FSNOTIFY_MARK_FLAG_ATTACHED);list_del_init (&mark->g_list);spin_unlock (&mark->lock); -atomic_dec (&group->num_marks);fsnotify_put_mark (mark);return ret;
include/linux/fanotify.h +3 -0
@@ -2,8 +2,11 @@#ifndef _LINUX_FANOTIFY_H#define _LINUX_FANOTIFY_H +#include <linux/sysctl.h> #include <uapi/linux/fanotify.h> +extern struct ctl_table fanotify_table[];/* for sysctl */ +#define FAN_GROUP_FLAG (group, flag) \ ((group)->fanotify_data.flags & (flag))
include/linux/fsnotify_backend.h +1 -5
@@ -206,9 +206,6 @@ struct fsnotify_group {/* stores all fastpath marks assoc with this group so they can be cleaned on unregister */ struct mutex mark_mutex;/* protect marks_list */ -atomic_t num_marks;/* 1 for each mark and 1 for not being -* past the point of no return when freeing -* a group */ atomic_t user_waits;/* Number of tasks waiting for user * response */ struct list_head marks_list;/* all inode marks for this group */
@@ -240,8 +237,7 @@ struct fsnotify_group {wait_queue_head_t access_waitq;int flags;/* flags from fanotify_init() */ int f_flags;/* event_f_flags from fanotify_init() */ -unsigned int max_marks; - struct user_struct *user; + struct ucounts *ucounts; } fanotify_data;#endif /* CONFIG_FANOTIFY */ };
include/linux/sched/user.h +0 -3
@@ -14,9 +14,6 @@ struct user_struct {refcount_t __count;/* reference count */ atomic_t processes;/* How many processes does this user have? */ atomic_t sigpending;/* How many pending signals does this user have? */ -#ifdef CONFIG_FANOTIFY -atomic_t fanotify_listeners; -#endif #ifdef CONFIG_EPOLL atomic_long_t epoll_watches;/* The number of file descriptors currently watched */ #endif
include/linux/user_namespace.h +4 -0
@@ -49,6 +49,10 @@ enum ucount_type {#ifdef CONFIG_INOTIFY_USER UCOUNT_INOTIFY_INSTANCES, UCOUNT_INOTIFY_WATCHES, +#endif +#ifdef CONFIG_FANOTIFY +UCOUNT_FANOTIFY_GROUPS , +UCOUNT_FANOTIFY_MARKS , #endif UCOUNT_COUNTS, };
kernel/sysctl.c +11 -1
@@ -142,6 +142,9 @@ static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);#ifdef CONFIG_INOTIFY_USER #include <linux/inotify.h> #endif +#ifdef CONFIG_FANOTIFY +#include <linux/fanotify.h> +#endif #ifdef CONFIG_PROC_SYSCTL
@@ -3330,7 +3333,14 @@ static struct ctl_table fs_table[] = { .mode = 0555, .child = inotify_table, }, -#endif +#endif +#ifdef CONFIG_FANOTIFY + { + .procname = "fanotify", + .mode = 0555, + .child = fanotify_table, + }, +#endif #ifdef CONFIG_EPOLL { .procname = "epoll",
kernel/ucount.c +4 -0
@@ -73,6 +73,10 @@ static struct ctl_table user_table[] = {#ifdef CONFIG_INOTIFY_USER UCOUNT_ENTRY("max_inotify_instances"), UCOUNT_ENTRY("max_inotify_watches"), +#endif +#ifdef CONFIG_FANOTIFY + UCOUNT_ENTRY("max_fanotify_groups"), + UCOUNT_ENTRY("max_fanotify_marks"),#endif { } };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 256/770 fanotify: support limited functionality for unprivileged users
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 7cea2a3c505e87a9d6afc78be4a7f7be636a73a7 ]
Add limited support for unprivileged fanotify groups.
An unprivileged users is not allowed to get an open file descriptor in the event nor the process pid of another process. An unprivileged user cannot request permission events, cannot set mount/filesystem marks and cannot request unlimited queue/marks.
This enables the limited functionality similar to inotify when watching a set of files and directories for OPEN/ACCESS/MODIFY/CLOSE events, without requiring SYS_CAP_ADMIN privileges.
The FAN_REPORT_DFID_NAME init flag, provide a method for an unprivileged listener watching a set of directories (with FAN_EVENT_ON_CHILD) to monitor all changes inside those directories.
This typically requires that the listener keeps a map of watched directory fid to dirfd (O_PATH), where fid is obtained with name_to_handle_at() before starting to watch for changes.
When getting an event, the reported fid of the parent should be resolved to dirfd and fstatsat(2) with dirfd and name should be used to query the state of the filesystem entry.
--- fs/notify/fanotify/fanotify_user.c | 29 ++++++++++++++++++++++++-- fs/notify/fdinfo.c | 3 ++- include/linux/fanotify.h | 33 +++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 8 deletions(-)
fs/notify/fanotify/fanotify_user.c +27 -2
@@ -419,6 +419,14 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, metadata.reserved =0 ; metadata.mask = event->mask &FANOTIFY_OUTGOING_EVENTS ; metadata.pid =pid_vnr (event->pid); +/* +* For an unprivileged listener, event->pid can be used to identify the +* events generated by the listener process itself, without disclosing +* the pids of other processes. +*/ +if (!capable (CAP_SYS_ADMIN ) && +task_tgid (current) != event->pid) + metadata.pid =0 ;if (path && path->mnt && path->dentry) { fd =create_fd (group, path, &f);
@@ -1036,8 +1044,16 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)pr_debug ("%s: flags=%x event_f_flags=%x\n" , __func__, flags, event_f_flags); -if (!capable (CAP_SYS_ADMIN )) -return -EPERM ; +if (!capable (CAP_SYS_ADMIN )) { +/* +* An unprivileged user can setup an fanotify group with +* limited functionality - an unprivileged group is limited to +* notification events with file handles and it cannot use +* unlimited queue/marks. +*/ +if ((flags &FANOTIFY_ADMIN_INIT_FLAGS ) || !fid_mode) +return -EPERM ; + }#ifdef CONFIG_AUDITSYSCALL if (flags & ~(FANOTIFY_INIT_FLAGS |FAN_ENABLE_AUDIT ))
@@ -1306,6 +1322,15 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, goto fput_and_out; group = f.file->private_data; +/* +* An unprivileged user is not allowed to watch a mount point nor +* a filesystem. +*/ + ret = -EPERM ; +if (!capable (CAP_SYS_ADMIN ) && + mark_type !=FAN_MARK_INODE ) + goto fput_and_out; +/* * group->priority == FS_PRIO_0 == FAN_CLASS_NOTIF. These are not * allowed to set permissions events.
fs/notify/fdinfo.c +2 -1
@@ -137,7 +137,8 @@ void fanotify_show_fdinfo(struct seq_file *m, struct file *f)struct fsnotify_group *group = f->private_data;seq_printf (m,"fanotify flags:%x event-flags:%x\n" , - group->fanotify_data.flags, group->fanotify_data.f_flags); + group->fanotify_data.flags, + group->fanotify_data.f_flags);show_fdinfo (m, f, fanotify_fdinfo); }
include/linux/fanotify.h +28 -5
@@ -18,15 +18,38 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */* these constant, the programs may break if re-compiled with new uapi headers * and then run on an old kernel. */ -#define FANOTIFY_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \ + +/* Group classes where permission events are allowed */ +#define FANOTIFY_PERM_CLASSES (FAN_CLASS_CONTENT | \ FAN_CLASS_PRE_CONTENT) +#define FANOTIFY_CLASS_BITS (FAN_CLASS_NOTIF | FANOTIFY_PERM_CLASSES) +#define FANOTIFY_FID_BITS (FAN_REPORT_FID | FAN_REPORT_DFID_NAME) -#define FANOTIFY_INIT_FLAGS (FANOTIFY_CLASS_BITS | FANOTIFY_FID_BITS | \ - FAN_REPORT_TID | \ - FAN_CLOEXEC | FAN_NONBLOCK | \ - FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS) +/* +* fanotify_init() flags that require CAP_SYS_ADMIN. +* We do not allow unprivileged groups to request permission events. +* We do not allow unprivileged groups to get other process pid in events. +* We do not allow unprivileged groups to use unlimited resources. +*/ +#define FANOTIFY_ADMIN_INIT_FLAGS (FANOTIFY_PERM_CLASSES | \ + FAN_REPORT_TID | \ + FAN_UNLIMITED_QUEUE | \ + FAN_UNLIMITED_MARKS) + +/* +* fanotify_init() flags that are allowed for user without CAP_SYS_ADMIN. +* FAN_CLASS_NOTIF is the only class we allow for unprivileged group. +* We do not allow unprivileged groups to get file descriptors in events, +* so one of the flags for reporting file handles is required. +*/ +#define FANOTIFY_USER_INIT_FLAGS (FAN_CLASS_NOTIF | \ + FANOTIFY_FID_BITS | \ + FAN_CLOEXEC | FAN_NONBLOCK) + +#define FANOTIFY_INIT_FLAGS (FANOTIFY_ADMIN_INIT_FLAGS | \ + FANOTIFY_USER_INIT_FLAGS)#define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \ FAN_MARK_FILESYSTEM)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 257/770 fanotify_user: use upper_32_bits() to verify mask
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
[ Upstream commit 22d483b99863202e3631ff66fa0f3c2302c0f96f ]
I don't see an obvious reason why the upper 32 bit check needs to be open-coded this way. Switch to upper_32_bits() which is more idiomatic and should conceptually be the same check.
--- fs/notify/fanotify/fanotify_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/notify/fanotify/fanotify_user.c +1 -1
@@ -1268,7 +1268,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, __func__, fanotify_fd, flags, dfd, pathname, mask);/* we only use the lower 32 bits as of right now. */ -if (mask & ((__u64 )0xffffffff <<32 )) +if (upper_32_bits (mask))return -EINVAL ;if (flags & ~FANOTIFY_MARK_FLAGS )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 258/770 nfsd: remove unused function
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiapeng Chong <[email protected]>
[ Upstream commit 363f8dd5eecd6c67fe9840ef6065440f0ee7df3a ]
Fix the following clang warning:
fs/nfsd/nfs4state.c:6276:1: warning: unused function 'end_offset' [-Wunused-function].
--- fs/nfsd/nfs4state.c | 9 --------- 1 file changed, 9 deletions(-)
fs/nfsd/nfs4state.c +0 -9
@@ -6336,15 +6336,6 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,return status; } -static inline u64 -end_offset (u64 start,u64 len) -{ -u64 end; - - end = start + len; -return end >= start ? end:NFS4_MAX_UINT64 ; -} -/* last octet in a range */ static inline u64 last_byte_offset (u64 start,u64 len)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 259/770 nfsd: removed unused argument in nfsd_startup_generic()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vasily Averin <[email protected]>
[ Upstream commit 70c5307564035c160078401f541c397d77b95415 ]
Since commit 501cb1849f86 ("nfsd: rip out the raparms cache") nrservs is not used in nfsd_startup_generic()
--- fs/nfsd/nfssvc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/nfsd/nfssvc.c +4 -4
@@ -308,7 +308,7 @@ static int nfsd_init_socks(struct net *net, const struct cred *cred)static int nfsd_users =0 ; -static int nfsd_startup_generic (int nrservs) +static int nfsd_startup_generic (void ) {int ret;
@@ -374,7 +374,7 @@ void nfsd_reset_boot_verifier(struct nfsd_net *nn)write_sequnlock (&nn->boot_lock); } -static int nfsd_startup_net (int nrservs,struct net *net,const struct cred *cred) +static int nfsd_startup_net (struct net *net,const struct cred *cred) {struct nfsd_net *nn =net_generic (net, nfsd_net_id);int ret;
@@ -382,7 +382,7 @@ static int nfsd_startup_net(int nrservs, struct net *net, const struct cred *creif (nn->nfsd_net_up)return 0 ; - ret =nfsd_startup_generic (nrservs); + ret =nfsd_startup_generic ();if (ret)return ret; ret =nfsd_init_socks (net, cred);
@@ -790,7 +790,7 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred) nfsd_up_before = nn->nfsd_net_up; - error =nfsd_startup_net (nrservs, net, cred); + error =nfsd_startup_net (net, cred);if (error) goto out_destroy; error = nn->nfsd_serv->sv_ops->svo_setup(nn->nfsd_serv,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 260/770 nfsd: hash nfs4_files by inode number
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit f9b60e2209213fdfcc504ba25a404977c5d08b77 ]
The nfs4_file structure is per-filehandle, not per-inode, because the spec requires open and other state to be per filehandle.
But it will turn out to be convenient for nfs4_files associated with the same inode to be hashed to the same bucket, so let's hash on the inode instead of the filehandle.
Filehandle aliasing is rare, so that shouldn't have much performance impact.
(If you have a ton of exported filesystems, though, and all of them have a root with inode number 2, could that get you an overlong hash chain? Perhaps this (and the v4 open file cache) should be hashed on the inode pointer instead.)
--- fs/nfsd/nfs4state.c | 27 ++++++++++++--------------- fs/nfsd/state.h | 1 - 2 files changed, 12 insertions(+), 16 deletions(-)
fs/nfsd/nfs4state.c +12 -15
@@ -554,14 +554,12 @@ static unsigned int ownerstr_hashval(struct xdr_netobj *ownername)#define FILE_HASH_BITS 8#define FILE_HASH_SIZE (1 << FILE_HASH_BITS) -static unsigned int nfsd_fh_hashval (struct knfsd_fh *fh) +static unsigned int file_hashval (struct svc_fh *fh) { -return jhash2 (fh->fh_base.fh_pad,XDR_QUADLEN (fh->fh_size),0 ); -} +struct inode *inode =d_inode (fh->fh_dentry); -static unsigned int file_hashval (struct knfsd_fh *fh) -{ -return nfsd_fh_hashval (fh) & (FILE_HASH_SIZE -1 ); +/* XXX: why not (here & in file cache) use inode? */ +return (unsigned int )hash_long (inode->i_ino,FILE_HASH_BITS ); }static struct hlist_head file_hashtbl[FILE_HASH_SIZE ];
@@ -4106,7 +4104,7 @@ static struct nfs4_file *nfsd4_alloc_file(void) }/* OPEN Share state helper functions */ -static void nfsd4_init_file (struct knfsd_fh *fh,unsigned int hashval, +static void nfsd4_init_file (struct svc_fh *fh,unsigned int hashval,struct nfs4_file *fp) {lockdep_assert_held (&state_lock);
@@ -4116,7 +4114,7 @@ static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval,INIT_LIST_HEAD (&fp->fi_stateids);INIT_LIST_HEAD (&fp->fi_delegations);INIT_LIST_HEAD (&fp->fi_clnt_odstate); -fh_copy_shallow (&fp->fi_fhandle, fh); +fh_copy_shallow (&fp->fi_fhandle, &fh->fh_handle); fp->fi_deleg_file =NULL ; fp->fi_had_conflict = false; fp->fi_share_deny =0 ;
@@ -4460,13 +4458,13 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net)/* search file_hashtbl[] for file */ static struct nfs4_file * -find_file_locked (struct knfsd_fh *fh,unsigned int hashval) +find_file_locked (struct svc_fh *fh,unsigned int hashval) {struct nfs4_file *fp;hlist_for_each_entry_rcu (fp, &file_hashtbl[hashval], fi_hash,lockdep_is_held (&state_lock)) { -if (fh_match (&fp->fi_fhandle, fh)) { +if (fh_match (&fp->fi_fhandle, &fh->fh_handle)) {if (refcount_inc_not_zero (&fp->fi_ref))return fp; }
@@ -4474,8 +4472,7 @@ find_file_locked(struct knfsd_fh *fh, unsigned int hashval)return NULL ; } -struct nfs4_file * -find_file (struct knfsd_fh *fh) +static struct nfs4_file *find_file (struct svc_fh *fh) {struct nfs4_file *fp;unsigned int hashval =file_hashval (fh);
@@ -4487,7 +4484,7 @@ find_file(struct knfsd_fh *fh) }static struct nfs4_file * -find_or_add_file (struct nfs4_file *new,struct knfsd_fh *fh) +find_or_add_file (struct nfs4_file *new,struct svc_fh *fh) {struct nfs4_file *fp;unsigned int hashval =file_hashval (fh);
@@ -4519,7 +4516,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)struct nfs4_file *fp;__be32 ret = nfs_ok; - fp =find_file (¤t_fh->fh_handle); + fp =find_file (current_fh);if (!fp)return ret;/* Check for conflicting share reservations */
@@ -5208,7 +5205,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf* and check for delegations in the process of being recalled. * If not found, create the nfs4_file struct */ - fp =find_or_add_file (open->op_file, ¤t_fh->fh_handle); + fp =find_or_add_file (open->op_file, current_fh);if (fp != open->op_file) { status =nfs4_check_deleg (cl, open, &dp);if (status)
fs/nfsd/state.h +0 -1
@@ -669,7 +669,6 @@ extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name struct xdr_netobj princhash, struct nfsd_net *nn);extern bool nfs4_has_reclaimed_state (struct xdr_netobj name,struct nfsd_net *nn); -struct nfs4_file *find_file (struct knfsd_fh *fh);void put_nfs4_file (struct nfs4_file *fi);extern void nfs4_put_copy (struct nfsd4_copy *copy); extern struct nfsd4_copy *
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 261/770 nfsd: track filehandle aliasing in nfs4_files
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit a0ce48375a367222989c2618fe68bf34db8c7bb7 ]
It's unusual but possible for multiple filehandles to point to the same file. In that case, we may end up with multiple nfs4_files referencing the same inode.
For delegation purposes it will turn out to be useful to flag those cases.
--- fs/nfsd/nfs4state.c | 37 ++++++++++++++++++++++++++++--------- fs/nfsd/state.h | 2 ++ 2 files changed, 30 insertions(+), 9 deletions(-)
fs/nfsd/nfs4state.c +28 -9
@@ -4120,6 +4120,8 @@ static void nfsd4_init_file(struct svc_fh *fh, unsigned int hashval, fp->fi_share_deny =0 ;memset (fp->fi_fds,0 ,sizeof (fp->fi_fds));memset (fp->fi_access,0 ,sizeof (fp->fi_access)); + fp->fi_aliased = false; + fp->fi_inode =d_inode (fh->fh_dentry);#ifdef CONFIG_NFSD_PNFS INIT_LIST_HEAD (&fp->fi_lo_states);atomic_set (&fp->fi_lo_recalls,0 );
@@ -4472,6 +4474,31 @@ find_file_locked(struct svc_fh *fh, unsigned int hashval)return NULL ; } +static struct nfs4_file *insert_file (struct nfs4_file *new,struct svc_fh *fh, +unsigned int hashval) +{ +struct nfs4_file *fp; +struct nfs4_file *ret =NULL ; +bool alias_found = false; + +spin_lock (&state_lock); +hlist_for_each_entry_rcu (fp, &file_hashtbl[hashval], fi_hash, +lockdep_is_held (&state_lock)) { +if (fh_match (&fp->fi_fhandle, &fh->fh_handle)) { +if (refcount_inc_not_zero (&fp->fi_ref)) + ret = fp; + }else if (d_inode (fh->fh_dentry) == fp->fi_inode) + fp->fi_aliased = alias_found = true; + } +if (likely (ret ==NULL )) { +nfsd4_init_file (fh, hashval, new); + new->fi_aliased = alias_found; + ret = new; + } +spin_unlock (&state_lock); +return ret; +} +static struct nfs4_file *find_file (struct svc_fh *fh) {struct nfs4_file *fp;
@@ -4495,15 +4522,7 @@ find_or_add_file(struct nfs4_file *new, struct svc_fh *fh)if (fp)return fp; -spin_lock (&state_lock); - fp =find_file_locked (fh, hashval); -if (likely (fp ==NULL )) { -nfsd4_init_file (fh, hashval, new); - fp = new; - } -spin_unlock (&state_lock); - -return fp; +return insert_file (new, fh, hashval); }/*
fs/nfsd/state.h +2 -0
@@ -516,6 +516,8 @@ struct nfs4_clnt_odstate {*/ struct nfs4_file {refcount_t fi_ref; +struct inode * fi_inode; +bool fi_aliased;spinlock_t fi_lock;struct hlist_node fi_hash;/* hash on fi_fhandle */ struct list_head fi_stateids;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 262/770 nfsd: reshuffle some code
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit ebd9d2c2f5a7ebaaed2d7bb4dee148755f46033d ]
No change in behavior, I'm just moving some code around to avoid forward references in a following patch.
(To do someday: figure out how to split up nfs4state.c. It's big and disorganized.)
--- fs/nfsd/nfs4state.c | 235 ++++++++++++++++++++++---------------------- 1 file changed, 118 insertions(+), 117 deletions(-)
fs/nfsd/nfs4state.c +118 -117
@@ -354,6 +354,124 @@ static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = { .release = nfsd4_cb_notify_lock_release, }; +/* +* We store the NONE, READ, WRITE, and BOTH bits separately in the +* st_{access,deny}_bmap field of the stateid, in order to track not +* only what share bits are currently in force, but also what +* combinations of share bits previous opens have used. This allows us +* to enforce the recommendation of rfc 3530 14.2.19 that the server +* return an error if the client attempt to downgrade to a combination +* of share bits not explicable by closing some of its previous opens. +* +* XXX: This enforcement is actually incomplete, since we don't keep +* track of access/deny bit combinations; so, e.g., we allow: +* +* OPEN allow read, deny write +* OPEN allow both, deny none +* DOWNGRADE allow read, deny none +* +* which we should reject. +*/ +static unsigned int +bmap_to_share_mode (unsigned long bmap) +{ +int i; +unsigned int access =0 ; + +for (i =1 ; i <4 ; i++) { +if (test_bit (i, &bmap)) + access |= i; + } +return access; +} + +/* set share access for a given stateid */ +static inline void +set_access (u32 access,struct nfs4_ol_stateid *stp) +{ +unsigned char mask =1 << access; + +WARN_ON_ONCE (access >NFS4_SHARE_ACCESS_BOTH ); + stp->st_access_bmap |= mask; +} + +/* clear share access for a given stateid */ +static inline void +clear_access (u32 access,struct nfs4_ol_stateid *stp) +{ +unsigned char mask =1 << access; + +WARN_ON_ONCE (access >NFS4_SHARE_ACCESS_BOTH ); + stp->st_access_bmap &= ~mask; +} + +/* test whether a given stateid has access */ +static inline bool +test_access (u32 access,struct nfs4_ol_stateid *stp) +{ +unsigned char mask =1 << access; + +return (bool )(stp->st_access_bmap & mask); +} + +/* set share deny for a given stateid */ +static inline void +set_deny (u32 deny,struct nfs4_ol_stateid *stp) +{ +unsigned char mask =1 << deny; + +WARN_ON_ONCE (deny >NFS4_SHARE_DENY_BOTH ); + stp->st_deny_bmap |= mask; +} + +/* clear share deny for a given stateid */ +static inline void +clear_deny (u32 deny,struct nfs4_ol_stateid *stp) +{ +unsigned char mask =1 << deny; + +WARN_ON_ONCE (deny >NFS4_SHARE_DENY_BOTH ); + stp->st_deny_bmap &= ~mask; +} + +/* test whether a given stateid is denying specific access */ +static inline bool +test_deny (u32 deny,struct nfs4_ol_stateid *stp) +{ +unsigned char mask =1 << deny; + +return (bool )(stp->st_deny_bmap & mask); +} + +static int nfs4_access_to_omode (u32 access) +{ +switch (access &NFS4_SHARE_ACCESS_BOTH ) { +case NFS4_SHARE_ACCESS_READ : +return O_RDONLY ; +case NFS4_SHARE_ACCESS_WRITE : +return O_WRONLY ; +case NFS4_SHARE_ACCESS_BOTH : +return O_RDWR ; + } +WARN_ON_ONCE (1 ); +return O_RDONLY ; +} + +static inline int +access_permit_read (struct nfs4_ol_stateid *stp) +{ +return test_access (NFS4_SHARE_ACCESS_READ , stp) || +test_access (NFS4_SHARE_ACCESS_BOTH , stp) || +test_access (NFS4_SHARE_ACCESS_WRITE , stp); +} + +static inline int +access_permit_write (struct nfs4_ol_stateid *stp) +{ +return test_access (NFS4_SHARE_ACCESS_WRITE , stp) || +test_access (NFS4_SHARE_ACCESS_BOTH , stp); +} +static inline struct nfs4_stateowner *nfs4_get_stateowner (struct nfs4_stateowner *sop) {
@@ -1167,108 +1285,6 @@ static unsigned int clientstr_hashval(struct xdr_netobj name)return opaque_hashval (name.data,8 ) &CLIENT_HASH_MASK ; } -/* -* We store the NONE, READ, WRITE, and BOTH bits separately in the -* st_{access,deny}_bmap field of the stateid, in order to track not -* only what share bits are currently in force, but also what -* combinations of share bits previous opens have used. This allows us -* to enforce the recommendation of rfc 3530 14.2.19 that the server -* return an error if the client attempt to downgrade to a combination -* of share bits not explicable by closing some of its previous opens. -* -* XXX: This enforcement is actually incomplete, since we don't keep -* track of access/deny bit combinations; so, e.g., we allow: -* -* OPEN allow read, deny write -* OPEN allow both, deny none -* DOWNGRADE allow read, deny none -* -* which we should reject. -*/ -static unsigned int -bmap_to_share_mode (unsigned long bmap) { -int i; -unsigned int access =0 ; - -for (i =1 ; i <4 ; i++) { -if (test_bit (i, &bmap)) - access |= i; - } -return access; -} - -/* set share access for a given stateid */ -static inline void -set_access (u32 access,struct nfs4_ol_stateid *stp) -{ -unsigned char mask =1 << access; - -WARN_ON_ONCE (access >NFS4_SHARE_ACCESS_BOTH ); - stp->st_access_bmap |= mask; -} - -/* clear share access for a given stateid */ -static inline void -clear_access (u32 access,struct nfs4_ol_stateid *stp) -{ -unsigned char mask =1 << access; - -WARN_ON_ONCE (access >NFS4_SHARE_ACCESS_BOTH ); - stp->st_access_bmap &= ~mask; -} - -/* test whether a given stateid has access */ -static inline bool -test_access (u32 access,struct nfs4_ol_stateid *stp) -{ -unsigned char mask =1 << access; - -return (bool )(stp->st_access_bmap & mask); -} - -/* set share deny for a given stateid */ -static inline void -set_deny (u32 deny,struct nfs4_ol_stateid *stp) -{ -unsigned char mask =1 << deny; - -WARN_ON_ONCE (deny >NFS4_SHARE_DENY_BOTH ); - stp->st_deny_bmap |= mask; -} - -/* clear share deny for a given stateid */ -static inline void -clear_deny (u32 deny,struct nfs4_ol_stateid *stp) -{ -unsigned char mask =1 << deny; - -WARN_ON_ONCE (deny >NFS4_SHARE_DENY_BOTH ); - stp->st_deny_bmap &= ~mask; -} - -/* test whether a given stateid is denying specific access */ -static inline bool -test_deny (u32 deny,struct nfs4_ol_stateid *stp) -{ -unsigned char mask =1 << deny; - -return (bool )(stp->st_deny_bmap & mask); -} - -static int nfs4_access_to_omode (u32 access) -{ -switch (access &NFS4_SHARE_ACCESS_BOTH ) { -case NFS4_SHARE_ACCESS_READ : -return O_RDONLY ; -case NFS4_SHARE_ACCESS_WRITE : -return O_WRONLY ; -case NFS4_SHARE_ACCESS_BOTH : -return O_RDWR ; - } -WARN_ON_ONCE (1 ); -return O_RDONLY ; -} -/* * A stateid that had a deny mode associated with it is being released * or downgraded. Recalculate the deny mode on the file.
@@ -5565,21 +5581,6 @@ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stid *stp)return nfs_ok; } -static inline int -access_permit_read (struct nfs4_ol_stateid *stp) -{ -return test_access (NFS4_SHARE_ACCESS_READ , stp) || -test_access (NFS4_SHARE_ACCESS_BOTH , stp) || -test_access (NFS4_SHARE_ACCESS_WRITE , stp); -} - -static inline int -access_permit_write (struct nfs4_ol_stateid *stp) -{ -return test_access (NFS4_SHARE_ACCESS_WRITE , stp) || -test_access (NFS4_SHARE_ACCESS_BOTH , stp); -} -static __be32 nfs4_check_openmode (struct nfs4_ol_stateid *stp,int flags) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 263/770 nfsd: grant read delegations to clients holding writes
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit aba2072f452346d56a462718bcde93d697383148 ]
It's OK to grant a read delegation to a client that holds a write, as long as it's the only client holding the write.
We originally tried to do this in commit 94415b06eb8a ("nfsd4: a client's own opens needn't prevent delegations"), which had to be reverted in commit 6ee65a773096 ("Revert "nfsd4: a client's own opens needn't prevent delegations"").
--- fs/locks.c | 3 ++ fs/nfsd/nfs4state.c | 82 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 14 deletions(-)
fs/locks.c +3 -0
@@ -1808,6 +1808,9 @@ check_conflicting_open(struct file *filp, const long arg, int flags)if (flags &FL_LAYOUT )return 0 ; +if (flags &FL_DELEG ) +/* We leave these checks to the caller */ +return 0 ;if (arg ==F_RDLCK )return inode_is_open_for_write (inode) ? -EAGAIN :0 ;
fs/nfsd/nfs4state.c +68 -14
106 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 264/770 nfsd: Fix fall-through warnings for Clang
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo A. R. Silva <[email protected]>
[ Upstream commit 76c50eb70d8e1133eaada0013845619c36345fbc ]
In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple warnings by explicitly adding a couple of break statements instead of just letting the code fall through to the next case.
--- fs/nfsd/nfs4state.c | 1 + fs/nfsd/nfsctl.c | 1 + 2 files changed, 2 insertions(+)
fs/nfsd/nfs4state.c +1 -0
@@ -3161,6 +3161,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out_nolock; } new->cl_mach_cred = true; +break ;case SP4_NONE :break ;default :/* checked by xdr code */
fs/nfsd/nfsctl.c +1 -0
@@ -1169,6 +1169,7 @@ static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode) inode->i_fop = &simple_dir_operations; inode->i_op = &simple_dir_inode_operations;inc_nlink (inode); +break ;default :break ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 265/770 NFSv4.2: Remove ifdef CONFIG_NFSD from NFSv4.2 client SSC code.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit d9092b4bb2109502eb8972021a3f74febc931a63 ]
The client SSC code should not depend on any of the CONFIG_NFSD config. This patch removes all CONFIG_NFSD from NFSv4.2 client SSC code and simplifies the config of CONFIG_NFS_V4_2_SSC_HELPER, NFSD_V4_2_INTER_SSC.
--- fs/Kconfig | 4 ++-- fs/nfs/nfs4file.c | 4 ---- fs/nfs/super.c | 4 ---- fs/nfsd/Kconfig | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-)
fs/Kconfig +2 -2
@@ -334,8 +334,8 @@ config NFS_COMMON default y config NFS_V4_2_SSC_HELPER - tristate - default y if NFS_V4=y || NFS_FS=y + bool + default y if NFS_V4_2 source "net/sunrpc/Kconfig" source "fs/ceph/Kconfig"
fs/nfs/nfs4file.c +0 -4
@@ -430,9 +430,7 @@ static const struct nfs4_ssc_client_ops nfs4_ssc_clnt_ops_tbl = {*/ void nfs42_ssc_register_ops (void ) { -#ifdef CONFIG_NFSD_V4 nfs42_ssc_register (&nfs4_ssc_clnt_ops_tbl); -#endif }/**
@@ -443,9 +441,7 @@ void nfs42_ssc_register_ops(void)*/ void nfs42_ssc_unregister_ops (void ) { -#ifdef CONFIG_NFSD_V4 nfs42_ssc_unregister (&nfs4_ssc_clnt_ops_tbl); -#endif }#endif /* CONFIG_NFS_V4_2 */
fs/nfs/super.c +0 -4
@@ -116,16 +116,12 @@ static void unregister_nfs4_fs(void)#ifdef CONFIG_NFS_V4_2 static void nfs_ssc_register_ops (void ) { -#ifdef CONFIG_NFSD_V4 nfs_ssc_register (&nfs_ssc_clnt_ops_tbl); -#endif }static void nfs_ssc_unregister_ops (void ) { -#ifdef CONFIG_NFSD_V4 nfs_ssc_unregister (&nfs_ssc_clnt_ops_tbl); -#endif }#endif /* CONFIG_NFS_V4_2 */
fs/nfsd/Kconfig +1 -1
@@ -138,7 +138,7 @@ config NFSD_FLEXFILELAYOUT config NFSD_V4_2_INTER_SSC bool "NFSv4.2 inter server to server COPY" - depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2 + depends on NFSD_V4 && NFS_V4_2 help This option enables support for NFSv4.2 inter server to server copy where the destination server calls the NFSv4.2
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 266/770 NFS: fix nfs_fetch_iversion()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
[ Upstream commit b876d708316bf9b6b9678eb2beb289b93cfe6369 ]
The change attribute is always set by all NFS client versions so get rid of the open-coded version.
--- fs/nfs/export.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-)
fs/nfs/export.c +4 -11
@@ -171,17 +171,10 @@ static u64 nfs_fetch_iversion(struct inode *inode) {struct nfs_server *server =NFS_SERVER (inode); -/* Is this the right call?: */ -nfs_revalidate_inode (server, inode); -/* -* Also, note we're ignoring any returned error. That seems to be -* the practice for cache consistency information elsewhere in -* the server, but I'm not sure why. -*/ -if (server->nfs_client->rpc_ops->version >=4 ) -return inode_peek_iversion_raw (inode); -else -return time_to_chattr (&inode->i_ctime); +if (nfs_check_cache_invalid (inode,NFS_INO_INVALID_CHANGE | +NFS_INO_REVAL_PAGECACHE )) +__nfs_revalidate_inode (server, inode); +return inode_peek_iversion_raw (inode); }const struct export_operations nfs_export_ops = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 267/770 fanotify: fix permission model of unprivileged group
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit a8b98c808eab3ec8f1b5a64be967b0f4af4cae43 ]
Reporting event->pid should depend on the privileges of the user that initialized the group, not the privileges of the user reading the events.
Use an internal group flag FANOTIFY_UNPRIV to record the fact that the group was initialized by an unprivileged user.
To be on the safe side, the premissions to setup filesystem and mount marks now require that both the user that initialized the group and the user setting up the mark have CAP_SYS_ADMIN.
--- fs/notify/fanotify/fanotify_user.c | 30 ++++++++++++++++++++++++------ fs/notify/fdinfo.c | 2 +- include/linux/fanotify.h | 4 ++++ 3 files changed, 29 insertions(+), 7 deletions(-)
fs/notify/fanotify/fanotify_user.c +24 -6
@@ -424,11 +424,18 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,* events generated by the listener process itself, without disclosing * the pids of other processes. */ -if (!capable (CAP_SYS_ADMIN ) && +if (FAN_GROUP_FLAG (group,FANOTIFY_UNPRIV ) &&task_tgid (current) != event->pid) metadata.pid =0 ; -if (path && path->mnt && path->dentry) { +/* +* For now, fid mode is required for an unprivileged listener and +* fid mode does not report fd in events. Keep this check anyway +* for safety in case fid mode requirement is relaxed in the future +* to allow unprivileged listener to get events with no fd and no fid. +*/ +if (!FAN_GROUP_FLAG (group,FANOTIFY_UNPRIV ) && + path && path->mnt && path->dentry) { fd =create_fd (group, path, &f);if (fd <0 )return fd;
@@ -1040,6 +1047,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)int f_flags, fd;unsigned int fid_mode = flags &FANOTIFY_FID_BITS ;unsigned int class = flags &FANOTIFY_CLASS_BITS ; +unsigned int internal_flags =0 ;pr_debug ("%s: flags=%x event_f_flags=%x\n" , __func__, flags, event_f_flags);
@@ -1053,6 +1061,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)*/ if ((flags &FANOTIFY_ADMIN_INIT_FLAGS ) || !fid_mode)return -EPERM ; + +/* +* Setting the internal flag FANOTIFY_UNPRIV on the group +* prevents setting mount/filesystem marks on this group and +* prevents reporting pid and open fd in events. +*/ + internal_flags |=FANOTIFY_UNPRIV ; }#ifdef CONFIG_AUDITSYSCALL
@@ -1105,7 +1120,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) goto out_destroy_group; } - group->fanotify_data.flags = flags; + group->fanotify_data.flags = flags | internal_flags; group->memcg =get_mem_cgroup_from_mm (current->mm); group->fanotify_data.merge_hash =fanotify_alloc_merge_hash ();
@@ -1323,11 +1338,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, group = f.file->private_data;/* -* An unprivileged user is not allowed to watch a mount point nor -* a filesystem. +* An unprivileged user is not allowed to setup mount nor filesystem +* marks. This also includes setting up such marks by a group that +* was initialized by an unprivileged user. */ ret = -EPERM ; -if (!capable (CAP_SYS_ADMIN ) && +if ((!capable (CAP_SYS_ADMIN ) || +FAN_GROUP_FLAG (group,FANOTIFY_UNPRIV )) && mark_type !=FAN_MARK_INODE ) goto fput_and_out;
@@ -1478,6 +1495,7 @@ static int __init fanotify_user_setup(void) max_marks =clamp (max_marks,FANOTIFY_OLD_DEFAULT_MAX_MARKS ,FANOTIFY_DEFAULT_MAX_USER_MARKS ); +BUILD_BUG_ON (FANOTIFY_INIT_FLAGS &FANOTIFY_INTERNAL_GROUP_FLAGS );BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) !=10 );BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_MARK_FLAGS ) !=9 );
fs/notify/fdinfo.c +1 -1
@@ -137,7 +137,7 @@ void fanotify_show_fdinfo(struct seq_file *m, struct file *f)struct fsnotify_group *group = f->private_data;seq_printf (m,"fanotify flags:%x event-flags:%x\n" , - group->fanotify_data.flags, + group->fanotify_data.flags &FANOTIFY_INIT_FLAGS , group->fanotify_data.f_flags);show_fdinfo (m, f, fanotify_fdinfo);
include/linux/fanotify.h +4 -0
@@ -51,6 +51,10 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_INIT_FLAGS (FANOTIFY_ADMIN_INIT_FLAGS | \ FANOTIFY_USER_INIT_FLAGS) +/* Internal group flags */ +#define FANOTIFY_UNPRIV 0x80000000 +#define FANOTIFY_INTERNAL_GROUP_FLAGS (FANOTIFY_UNPRIV) +#define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \ FAN_MARK_FILESYSTEM)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 268/770 NFSD: Add an RPC authflavor tracepoint display helper
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 87b2394d60c32c158ebb96ace4abee883baf1239 ]
To be used in subsequent patches.
--- fs/nfsd/trace.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
fs/nfsd/trace.h +16 -0
@@ -841,6 +841,22 @@ DEFINE_NFSD_CB_EVENT(setup);DEFINE_NFSD_CB_EVENT (state);DEFINE_NFSD_CB_EVENT (shutdown); +TRACE_DEFINE_ENUM (RPC_AUTH_NULL ); +TRACE_DEFINE_ENUM (RPC_AUTH_UNIX ); +TRACE_DEFINE_ENUM (RPC_AUTH_GSS ); +TRACE_DEFINE_ENUM (RPC_AUTH_GSS_KRB5 ); +TRACE_DEFINE_ENUM (RPC_AUTH_GSS_KRB5I ); +TRACE_DEFINE_ENUM (RPC_AUTH_GSS_KRB5P ); + +#define show_nfsd_authflavor (val) \ + __print_symbolic(val, \ + { RPC_AUTH_NULL, "none" }, \ + { RPC_AUTH_UNIX, "sys" }, \ + { RPC_AUTH_GSS, "gss" }, \ + { RPC_AUTH_GSS_KRB5, "krb5" }, \ + { RPC_AUTH_GSS_KRB5I, "krb5i" }, \ + { RPC_AUTH_GSS_KRB5P, "krb5p" }) + TRACE_EVENT(nfsd_cb_setup_err, TP_PROTO( const struct nfs4_client *clp,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 269/770 NFSD: Add nfsd_clid_cred_mismatch tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 27787733ef44332fce749aa853f2749d141982b0 ]
Record when a client tries to establish a lease record but uses an unexpected credential. This is often a sign of a configuration problem.
--- fs/nfsd/nfs4state.c | 14 ++++++++++---- fs/nfsd/trace.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-)
fs/nfsd/nfs4state.c +10 -4
@@ -3203,6 +3203,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (!creds_match) {/* case 3 */ if (client_has_state (conf)) { status = nfserr_clid_inuse; +trace_nfsd_clid_cred_mismatch (conf, rqstp); goto out; } goto out_new;
@@ -3447,9 +3448,10 @@ nfsd4_create_session(struct svc_rqst *rqstp, goto out_free_conn; } }else if (unconf) { + status = nfserr_clid_inuse;if (!same_creds (&unconf->cl_cred, &rqstp->rq_cred) || !rpc_cmp_addr (sa, (struct sockaddr *) &unconf->cl_addr)) { - status = nfserr_clid_inuse; +trace_nfsd_clid_cred_mismatch (unconf, rqstp); goto out_free_conn; } status = nfserr_wrong_cred;
@@ -4008,7 +4010,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (clp_used_exchangeid (conf)) goto out;if (!same_creds (&conf->cl_cred, &rqstp->rq_cred)) { -trace_nfsd_clid_inuse_err (conf); +trace_nfsd_clid_cred_mismatch (conf, rqstp); goto out; } }
@@ -4066,10 +4068,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,* Nevertheless, RFC 7530 recommends INUSE for this case: */ status = nfserr_clid_inuse; -if (unconf && !same_creds (&unconf->cl_cred, &rqstp->rq_cred)) +if (unconf && !same_creds (&unconf->cl_cred, &rqstp->rq_cred)) { +trace_nfsd_clid_cred_mismatch (unconf, rqstp); goto out; -if (conf && !same_creds (&conf->cl_cred, &rqstp->rq_cred)) + } +if (conf && !same_creds (&conf->cl_cred, &rqstp->rq_cred)) { +trace_nfsd_clid_cred_mismatch (conf, rqstp); goto out; + }/* cases below refer to rfc 3530 section 14.2.34: */ if (!unconf || !same_verf (&confirm, &unconf->cl_confirm)) {if (conf &&same_verf (&confirm, &conf->cl_confirm)) {
fs/nfsd/trace.h +28 -0
@@ -536,6 +536,34 @@ DEFINE_EVENT(nfsd_net_class, nfsd_##name, \DEFINE_NET_EVENT (grace_start);DEFINE_NET_EVENT (grace_complete); +TRACE_EVENT (nfsd_clid_cred_mismatch, +TP_PROTO ( + const struct nfs4_client *clp, + const struct svc_rqst *rqstp + ), +TP_ARGS (clp, rqstp), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __field(unsigned long, cl_flavor) + __field(unsigned long, new_flavor) + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) + ), +TP_fast_assign ( + __entry->cl_boot = clp->cl_clientid.cl_boot; + __entry->cl_id = clp->cl_clientid.cl_id; + __entry->cl_flavor = clp->cl_cred.cr_flavor; + __entry->new_flavor = rqstp->rq_cred.cr_flavor; + memcpy(__entry->addr, &rqstp->rq_xprt->xpt_remote, + sizeof(struct sockaddr_in6)); + ), +TP_printk ("client %08x:%08x flavor=%s, conflict=%s from addr=%pISpc" , + __entry->cl_boot, __entry->cl_id, +show_nfsd_authflavor (__entry->cl_flavor), +show_nfsd_authflavor (__entry->new_flavor), __entry->addr + ) +) + TRACE_EVENT(nfsd_clid_inuse_err, TP_PROTO(const struct nfs4_client *clp), TP_ARGS(clp),
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 270/770 NFSD: Add nfsd_clid_verf_mismatch tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 744ea54c869cebe41fbad5f53f8a8ca5d93a5c97 ]
Record when a client presents a different boot verifier than the one we know about. Typically this is a sign the client has rebooted, but sometimes it signals a conflicting client ID, which the client's administrator will need to address.
--- fs/nfsd/nfs4state.c | 11 ++++++++--- fs/nfsd/trace.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-)
fs/nfsd/nfs4state.c +8 -3
@@ -3213,6 +3213,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out_copy; }/* case 5, client reboot */ +trace_nfsd_clid_verf_mismatch (conf, rqstp, &verf); conf =NULL ; goto out_new; }
@@ -4018,9 +4019,13 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (unconf)unhash_client_locked (unconf);/* We need to handle only case 1: probable callback update */ -if (conf &&same_verf (&conf->cl_verifier, &clverifier)) { -copy_clid (new, conf); -gen_confirm (new, nn); +if (conf) { +if (same_verf (&conf->cl_verifier, &clverifier)) { +copy_clid (new, conf); +gen_confirm (new, nn); + }else +trace_nfsd_clid_verf_mismatch (conf, rqstp, + &clverifier); } new->cl_minorversion =0 ;gen_callback (new, setclid, rqstp);
fs/nfsd/trace.h +32 -0
@@ -564,6 +564,38 @@ TRACE_EVENT(nfsd_clid_cred_mismatch, ) ) +TRACE_EVENT (nfsd_clid_verf_mismatch, +TP_PROTO ( + const struct nfs4_client *clp, + const struct svc_rqst *rqstp, + const nfs4_verifier *verf + ), +TP_ARGS (clp, rqstp, verf), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __array(unsigned char, cl_verifier, NFS4_VERIFIER_SIZE) + __array(unsigned char, new_verifier, NFS4_VERIFIER_SIZE) + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) + ), +TP_fast_assign ( + __entry->cl_boot = clp->cl_clientid.cl_boot; + __entry->cl_id = clp->cl_clientid.cl_id; + memcpy(__entry->cl_verifier, (void *)&clp->cl_verifier, + NFS4_VERIFIER_SIZE); + memcpy(__entry->new_verifier, (void *)verf, + NFS4_VERIFIER_SIZE); +memcpy (__entry->addr, &rqstp->rq_xprt->xpt_remote, + sizeof(struct sockaddr_in6)); + ), +TP_printk ("client %08x:%08x verf=0x%s, updated=0x%s from addr=%pISpc" , + __entry->cl_boot, __entry->cl_id, +__print_hex_str (__entry->cl_verifier,NFS4_VERIFIER_SIZE ), +__print_hex_str (__entry->new_verifier,NFS4_VERIFIER_SIZE ), + __entry->addr + ) +); + TRACE_EVENT(nfsd_clid_inuse_err, TP_PROTO(const struct nfs4_client *clp), TP_ARGS(clp),
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 271/770 NFSD: Remove trace_nfsd_clid_inuse_err
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 0bfaacac57e64aa342f865b8ddcab06ca59a6f83 ]
This tracepoint has been replaced by nfsd_clid_cred_mismatch and nfsd_clid_verf_mismatch, and can simply be removed.
--- fs/nfsd/trace.h | 24 ------------------------ 1 file changed, 24 deletions(-)
fs/nfsd/trace.h +0 -24
@@ -596,30 +596,6 @@ TRACE_EVENT(nfsd_clid_verf_mismatch, ) ); -TRACE_EVENT (nfsd_clid_inuse_err, - TP_PROTO(const struct nfs4_client *clp), -TP_ARGS (clp), -TP_STRUCT__entry ( - __field(u32, cl_boot) - __field(u32, cl_id) - __array(unsigned char, addr, sizeof(struct sockaddr_in6)) - __field(unsigned int, namelen) - __dynamic_array(unsigned char, name, clp->cl_name.len) - ), -TP_fast_assign ( - __entry->cl_boot = clp->cl_clientid.cl_boot; - __entry->cl_id = clp->cl_clientid.cl_id; - memcpy(__entry->addr, &clp->cl_addr, - sizeof(struct sockaddr_in6)); - __entry->namelen = clp->cl_name.len; -memcpy (__get_dynamic_array (name), clp->cl_name.data, - clp->cl_name.len); - ), -TP_printk ("nfs4_clientid %.*s already in use by %pISpc, client %08x:%08x" , - __entry->namelen,__get_str (name), __entry->addr, - __entry->cl_boot, __entry->cl_id) -) -/* * from fs/nfsd/filecache.h */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 272/770 NFSD: Add nfsd_clid_confirmed tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 7e3b32ace6094aadfa2e1e54ca4c6bbfd07646af ]
This replaces a dprintk call site in order to get greater visibility on when client IDs are confirmed or re-used. Simple example:
nfsd-995 [000] 126.622975: nfsd_compound: xid=0x3a34e2b1 opcnt=1
nfsd-995 [000] 126.623005: nfsd_cb_args: addr=192.168.2.51:45901 client 60958e3b:9213ef0e prog=1073741824 ident=1
nfsd-995 [000] 126.623007: nfsd_compound_status: op=1/1 OP_SETCLIENTID status=0
nfsd-996 [001] 126.623142: nfsd_compound: xid=0x3b34e2b1 opcnt=1
>>>> nfsd-996 [001] 126.623146: nfsd_clid_confirmed: client 60958e3b:9213ef0e
nfsd-996 [001] 126.623148: nfsd_cb_probe: addr=192.168.2.51:45901 client 60958e3b:9213ef0e state=UNKNOWN
nfsd-996 [001] 126.623154: nfsd_compound_status: op=1/1 OP_SETCLIENTID_CONFIRM status=0--- fs/nfsd/nfs4state.c | 10 +++++----- fs/nfsd/trace.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-)
fs/nfsd/nfs4state.c +5 -5
@@ -2838,14 +2838,14 @@ move_to_confirmed(struct nfs4_client *clp)lockdep_assert_held (&nn->client_lock); -dprintk ("NFSD: move_to_confirm nfs4_client %p\n" , clp);list_move (&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);rb_erase (&clp->cl_namenode, &nn->unconf_name_tree);add_clp_to_name_tree (clp, &nn->conf_name_tree); -if (!test_and_set_bit (NFSD4_CLIENT_CONFIRMED , &clp->cl_flags) && - clp->cl_nfsd_dentry && - clp->cl_nfsd_info_dentry) -fsnotify_dentry (clp->cl_nfsd_info_dentry,FS_MODIFY ); +if (!test_and_set_bit (NFSD4_CLIENT_CONFIRMED , &clp->cl_flags)) { +trace_nfsd_clid_confirmed (&clp->cl_clientid); +if (clp->cl_nfsd_dentry && clp->cl_nfsd_info_dentry) +fsnotify_dentry (clp->cl_nfsd_info_dentry,FS_MODIFY ); + }renew_client_locked (clp); }
fs/nfsd/trace.h +1 -0
@@ -511,6 +511,7 @@ DEFINE_EVENT(nfsd_clientid_class, nfsd_clid_##name, \ TP_PROTO(const clientid_t *clid), \ TP_ARGS(clid)) +DEFINE_CLIENTID_EVENT(confirmed); DEFINE_CLIENTID_EVENT(expired); DEFINE_CLIENTID_EVENT(purged); DEFINE_CLIENTID_EVENT(renew);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 273/770 NFSD: Add nfsd_clid_reclaim_complete tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit cee8aa074281e5269d8404be2b6388bb29ea8efc ]
--- fs/nfsd/nfs4state.c | 1 + fs/nfsd/trace.h | 1 + 2 files changed, 2 insertions(+)
fs/nfsd/nfs4state.c +1 -0
@@ -3981,6 +3981,7 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, goto out; status = nfs_ok; +trace_nfsd_clid_reclaim_complete (&clp->cl_clientid);nfsd4_client_record_create (clp);inc_reclaim_complete (clp); out:
fs/nfsd/trace.h +1 -0
@@ -511,6 +511,7 @@ DEFINE_EVENT(nfsd_clientid_class, nfsd_clid_##name, \ TP_PROTO(const clientid_t *clid), \ TP_ARGS(clid)) +DEFINE_CLIENTID_EVENT(reclaim_complete); DEFINE_CLIENTID_EVENT(confirmed); DEFINE_CLIENTID_EVENT(expired); DEFINE_CLIENTID_EVENT(purged);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 274/770 NFSD: Add nfsd_clid_destroyed tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c41a9b7a906fb872f8b2b1a34d2a1d5ef7f94adb ]
Record client-requested termination of client IDs.
--- fs/nfsd/nfs4state.c | 1 + fs/nfsd/trace.h | 1 + 2 files changed, 2 insertions(+)
fs/nfsd/nfs4state.c +1 -0
@@ -3939,6 +3939,7 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, status = nfserr_wrong_cred; goto out; } +trace_nfsd_clid_destroyed (&clp->cl_clientid);unhash_client_locked (clp); out:spin_unlock (&nn->client_lock);
fs/nfsd/trace.h +1 -0
@@ -513,6 +513,7 @@ DEFINE_EVENT(nfsd_clientid_class, nfsd_clid_##name, \DEFINE_CLIENTID_EVENT (reclaim_complete);DEFINE_CLIENTID_EVENT (confirmed); +DEFINE_CLIENTID_EVENT (destroyed);DEFINE_CLIENTID_EVENT (expired);DEFINE_CLIENTID_EVENT (purged);DEFINE_CLIENTID_EVENT (renew);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 275/770 NFSD: Add a couple more nfsd_clid_expired call sites
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 2958d2ee71021b6c44212ec6c2a39cc71d9cd4a9 ]
Improve observation of NFSv4 lease expiry.
--- fs/nfsd/nfs4state.c | 9 ++++++--- fs/nfsd/trace.h | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-)
fs/nfsd/nfs4state.c +6 -3
@@ -2687,6 +2687,8 @@ static void force_expire_client(struct nfs4_client *clp)struct nfsd_net *nn =net_generic (clp->net, nfsd_net_id);bool already_expired; +trace_nfsd_clid_admin_expired (&clp->cl_clientid); +spin_lock (&nn->client_lock); clp->cl_time =0 ;spin_unlock (&nn->client_lock);
@@ -3233,6 +3235,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, status =mark_client_expired_locked (conf);if (status) goto out; +trace_nfsd_clid_replaced (&conf->cl_clientid); } new->cl_minorversion = cstate->minorversion; new->cl_spo_must_allow.u.words[0 ] = exid->spo_must_allow[0 ];
@@ -3472,6 +3475,7 @@ nfsd4_create_session(struct svc_rqst *rqstp, old =NULL ; goto out_free_conn; } +trace_nfsd_clid_replaced (&old->cl_clientid); }move_to_confirmed (unconf); conf = unconf;
@@ -4112,6 +4116,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, old =NULL ; goto out; } +trace_nfsd_clid_replaced (&old->cl_clientid); }move_to_confirmed (unconf); conf = unconf;
@@ -5550,10 +5555,8 @@ nfs4_laundromat(struct nfsd_net *nn) clp = list_entry(pos, struct nfs4_client, cl_lru);if (!state_expired (<, clp->cl_time))break ; -if (mark_client_expired_locked (clp)) { -trace_nfsd_clid_expired (&clp->cl_clientid); +if (mark_client_expired_locked (clp))continue ; - }list_add (&clp->cl_lru, &reaplist); }spin_unlock (&nn->client_lock);
fs/nfsd/trace.h +2 -1
@@ -514,7 +514,8 @@ DEFINE_EVENT(nfsd_clientid_class, nfsd_clid_##name, \DEFINE_CLIENTID_EVENT (reclaim_complete);DEFINE_CLIENTID_EVENT (confirmed);DEFINE_CLIENTID_EVENT (destroyed); -DEFINE_CLIENTID_EVENT (expired); +DEFINE_CLIENTID_EVENT (admin_expired); +DEFINE_CLIENTID_EVENT (replaced);DEFINE_CLIENTID_EVENT (purged);DEFINE_CLIENTID_EVENT (renew);DEFINE_CLIENTID_EVENT (stale);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 276/770 NFSD: Add tracepoints for SETCLIENTID edge cases
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 237f91c85acef206a33bc02f3c4e856128fd7994 ]
--- fs/nfsd/nfs4state.c | 19 ++++++++----------- fs/nfsd/trace.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 11 deletions(-)
fs/nfsd/nfs4state.c +8 -11
@@ -4008,11 +4008,9 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, new =create_client (clname, rqstp, &clverifier);if (new ==NULL )return nfserr_jukebox; -/* Cases below refer to rfc 3530 section 14.2.33: */ spin_lock (&nn->client_lock); conf =find_confirmed_client_by_name (&clname, nn);if (conf &&client_has_state (conf)) { -/* case 0: */ status = nfserr_clid_inuse;if (clp_used_exchangeid (conf)) goto out;
@@ -4024,7 +4022,6 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, unconf =find_unconfirmed_client_by_name (&clname, nn);if (unconf)unhash_client_locked (unconf); -/* We need to handle only case 1: probable callback update */ if (conf) {if (same_verf (&conf->cl_verifier, &clverifier)) {copy_clid (new, conf);
@@ -4032,7 +4029,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, }else trace_nfsd_clid_verf_mismatch (conf, rqstp, &clverifier); - } + }else +trace_nfsd_clid_fresh (new); new->cl_minorversion =0 ;gen_callback (new, setclid, rqstp);add_to_unconfirmed (new);
@@ -4045,12 +4043,13 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,spin_unlock (&nn->client_lock);if (new)free_client (new); -if (unconf) +if (unconf) { +trace_nfsd_clid_expire_unconf (&unconf->cl_clientid);expire_client (unconf); + }return status; } - __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
@@ -4087,21 +4086,19 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,trace_nfsd_clid_cred_mismatch (conf, rqstp); goto out; } -/* cases below refer to rfc 3530 section 14.2.34: */ if (!unconf || !same_verf (&confirm, &unconf->cl_confirm)) {if (conf &&same_verf (&confirm, &conf->cl_confirm)) { -/* case 2: probable retransmit */ status = nfs_ok; - }else /* case 4: client hasn't noticed we rebooted yet? */ + }else status = nfserr_stale_clientid; goto out; } status = nfs_ok; -if (conf) {/* case 1: callback update */ +if (conf) { old = unconf;unhash_client_locked (old);nfsd4_change_callback (conf, &unconf->cl_cb_conn); - }else {/* case 3: normal case; new or rebooted client */ + }else { old =find_confirmed_client_by_name (&unconf->cl_name, nn);if (old) { status = nfserr_clid_inuse;
fs/nfsd/trace.h +37 -0
@@ -511,6 +511,7 @@ DEFINE_EVENT(nfsd_clientid_class, nfsd_clid_##name, \ TP_PROTO(const clientid_t *clid), \ TP_ARGS(clid)) +DEFINE_CLIENTID_EVENT(expire_unconf); DEFINE_CLIENTID_EVENT(reclaim_complete); DEFINE_CLIENTID_EVENT(confirmed); DEFINE_CLIENTID_EVENT(destroyed);
@@ -600,6 +601,42 @@ TRACE_EVENT(nfsd_clid_verf_mismatch, ) ); +DECLARE_EVENT_CLASS (nfsd_clid_class, + TP_PROTO(const struct nfs4_client *clp), +TP_ARGS (clp), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) + __field(unsigned long, flavor) + __array(unsigned char, verifier, NFS4_VERIFIER_SIZE) +__dynamic_array (char, name, clp->cl_name.len +1 ) + ), +TP_fast_assign ( + __entry->cl_boot = clp->cl_clientid.cl_boot; + __entry->cl_id = clp->cl_clientid.cl_id; + memcpy(__entry->addr, &clp->cl_addr, + sizeof(struct sockaddr_in6)); + __entry->flavor = clp->cl_cred.cr_flavor; + memcpy(__entry->verifier, (void *)&clp->cl_verifier, + NFS4_VERIFIER_SIZE); + memcpy(__get_str(name), clp->cl_name.data, clp->cl_name.len); + __get_str(name)[clp->cl_name.len] = '\0'; + ), +TP_printk ("addr=%pISpc name='%s' verifier=0x%s flavor=%s client=%08x:%08x" , + __entry->addr,__get_str (name), +__print_hex_str (__entry->verifier,NFS4_VERIFIER_SIZE ), +show_nfsd_authflavor (__entry->flavor), + __entry->cl_boot, __entry->cl_id) +); + +#define DEFINE_CLID_EVENT (name) \ +DEFINE_EVENT(nfsd_clid_class, nfsd_clid_##name, \ + TP_PROTO(const struct nfs4_client *clp), \ + TP_ARGS(clp)) + +DEFINE_CLID_EVENT (fresh); +/* * from fs/nfsd/filecache.h */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 277/770 NFSD: Add tracepoints for EXCHANGEID edge cases
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit e8f80c5545ec5794644b48537449e48b009d608d ]
Some of the most common cases are traced. Enough infrastructure is now in place that more can be added later, as needed.
--- fs/nfsd/nfs4state.c | 12 +++++++++--- fs/nfsd/trace.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-)
fs/nfsd/nfs4state.c +9 -3
@@ -3200,6 +3200,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, }/* case 6 */ exid->flags |=EXCHGID4_FLAG_CONFIRMED_R ; +trace_nfsd_clid_confirmed_r (conf); goto out_copy; }if (!creds_match) {/* case 3 */
@@ -3212,6 +3213,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, }if (verfs_match) {/* case 2 */ conf->cl_exchange_flags |=EXCHGID4_FLAG_CONFIRMED_R ; +trace_nfsd_clid_confirmed_r (conf); goto out_copy; }/* case 5, client reboot */
@@ -3225,11 +3227,13 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out; } - unconf =find_unconfirmed_client_by_name (&exid->clname, nn); + unconf =find_unconfirmed_client_by_name (&exid->clname, nn);if (unconf)/* case 4, possible retry or client restart */ unhash_client_locked (unconf); -/* case 1 (normal case) */ +/* case 1, new owner ID */ +trace_nfsd_clid_fresh (new); + out_new:if (conf) { status =mark_client_expired_locked (conf);
@@ -3259,8 +3263,10 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, out_nolock:if (new)expire_client (new); -if (unconf) +if (unconf) { +trace_nfsd_clid_expire_unconf (&unconf->cl_clientid);expire_client (unconf); + }return status; }
fs/nfsd/trace.h +1 -0
@@ -636,6 +636,7 @@ DEFINE_EVENT(nfsd_clid_class, nfsd_clid_##name, \ TP_ARGS(clp))DEFINE_CLID_EVENT (fresh); +DEFINE_CLID_EVENT (confirmed_r);/* * from fs/nfsd/filecache.h
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 278/770 NFSD: Constify @fh argument of knfsd_fh_hash()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 1736aec82a15cb5d4b3bbe0b2fbae0ede66b1a1a ]
Enable knfsd_fh_hash() to be invoked in functions where the filehandle pointer is a const.
--- fs/nfsd/nfsfh.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
fs/nfsd/nfsfh.h +2 -5
@@ -225,15 +225,12 @@ static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)* returns a crc32 hash for the filehandle that is compatible with * the one displayed by "wireshark". */ - -static inline u32 -knfsd_fh_hash (struct knfsd_fh *fh) +static inline u32 knfsd_fh_hash (const struct knfsd_fh *fh) {return ~crc32_le (0xFFFFFFFF , (unsigned char *)&fh->fh_base, fh->fh_size); }#else -static inline u32 -knfsd_fh_hash (struct knfsd_fh *fh) +static inline u32 knfsd_fh_hash (const struct knfsd_fh *fh) {return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 279/770 NFSD: Capture every CB state transition
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 8476c69a7fa0f1f9705ec0caa4e97c08b5045779 ]
We were missing one.
As a clean-up, add a helper that sets the new CB state and fires a tracepoint. The tracepoint fires only when the state changes, to help reduce trace log noise.
--- fs/nfsd/nfs4callback.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
fs/nfsd/nfs4callback.c +15 -13
@@ -945,20 +945,26 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *creturn 0 ; } +static void nfsd4_mark_cb_state (struct nfs4_client *clp,int newstate) +{ +if (clp->cl_cb_state != newstate) { + clp->cl_cb_state = newstate; +trace_nfsd_cb_state (clp); + } +} +static void nfsd4_mark_cb_down (struct nfs4_client *clp,int reason) {if (test_bit (NFSD4_CLIENT_CB_UPDATE , &clp->cl_flags))return ; - clp->cl_cb_state =NFSD4_CB_DOWN ; -trace_nfsd_cb_state (clp); +nfsd4_mark_cb_state (clp,NFSD4_CB_DOWN ); }static void nfsd4_mark_cb_fault (struct nfs4_client *clp,int reason) {if (test_bit (NFSD4_CLIENT_CB_UPDATE , &clp->cl_flags))return ; - clp->cl_cb_state =NFSD4_CB_FAULT ; -trace_nfsd_cb_state (clp); +nfsd4_mark_cb_state (clp,NFSD4_CB_FAULT ); }static void nfsd4_cb_probe_done (struct rpc_task *task,void *calldata)
@@ -968,10 +974,8 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)trace_nfsd_cb_done (clp, task->tk_status);if (task->tk_status)nfsd4_mark_cb_down (clp, task->tk_status); -else { - clp->cl_cb_state =NFSD4_CB_UP ; -trace_nfsd_cb_state (clp); - } +else +nfsd4_mark_cb_state (clp,NFSD4_CB_UP ); }static void nfsd4_cb_probe_release (void *calldata)
@@ -995,8 +999,7 @@ static const struct rpc_call_ops nfsd4_cb_probe_ops = {*/ void nfsd4_probe_callback (struct nfs4_client *clp) { - clp->cl_cb_state =NFSD4_CB_UNKNOWN ; -trace_nfsd_cb_state (clp); +nfsd4_mark_cb_state (clp,NFSD4_CB_UNKNOWN );set_bit (NFSD4_CLIENT_CB_UPDATE , &clp->cl_flags);nfsd4_run_cb (&clp->cl_cb_null); }
@@ -1009,11 +1012,10 @@ void nfsd4_probe_callback_sync(struct nfs4_client *clp)void nfsd4_change_callback (struct nfs4_client *clp,struct nfs4_cb_conn *conn) { - clp->cl_cb_state =NFSD4_CB_UNKNOWN ; +nfsd4_mark_cb_state (clp,NFSD4_CB_UNKNOWN );spin_lock (&clp->cl_lock);memcpy (&clp->cl_cb_conn, conn,sizeof (struct nfs4_cb_conn ));spin_unlock (&clp->cl_lock); -trace_nfsd_cb_state (clp); }/*
@@ -1345,7 +1347,7 @@ nfsd4_run_cb_work(struct work_struct *work)* Don't send probe messages for 4.1 or later. */ if (!cb->cb_ops && clp->cl_minorversion) { - clp->cl_cb_state =NFSD4_CB_UP ; +nfsd4_mark_cb_state (clp,NFSD4_CB_UP );nfsd41_destroy_cb (cb);return ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 280/770 NFSD: Drop TRACE_DEFINE_ENUM for NFSD4_CB_<state> macros
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 167145cc64ce4b4b177e636829909a6b14004f9e ]
TRACE_DEFINE_ENUM() is necessary for enum {} but not for C macros.
--- fs/nfsd/trace.h | 5 ----- 1 file changed, 5 deletions(-)
fs/nfsd/trace.h +0 -5
@@ -877,11 +877,6 @@ TRACE_EVENT(nfsd_cb_nodelegs, TP_printk("client %08x:%08x", __entry->cl_boot, __entry->cl_id) ) -TRACE_DEFINE_ENUM (NFSD4_CB_UP ); -TRACE_DEFINE_ENUM (NFSD4_CB_UNKNOWN ); -TRACE_DEFINE_ENUM (NFSD4_CB_DOWN ); -TRACE_DEFINE_ENUM (NFSD4_CB_FAULT ); -#define show_cb_state (val) \ __print_symbolic(val, \ { NFSD4_CB_UP, "UP" }, \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 281/770 NFSD: Add cb_lost tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 806d65b617d89be887fe68bfa051f78143669cd7 ]
Provide more clarity about when the callback channel is in trouble.
--- fs/nfsd/nfs4state.c | 2 ++ fs/nfsd/trace.h | 1 + 2 files changed, 3 insertions(+)
fs/nfsd/nfs4state.c +2 -0
@@ -1763,6 +1763,8 @@ static void nfsd4_conn_lost(struct svc_xpt_user *u) struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user);struct nfs4_client *clp = c->cn_session->se_client; +trace_nfsd_cb_lost (clp); +spin_lock (&clp->cl_lock);if (!list_empty (&c->cn_persession)) {list_del (&c->cn_persession);
fs/nfsd/trace.h +1 -0
@@ -912,6 +912,7 @@ DEFINE_EVENT(nfsd_cb_class, nfsd_cb_##name, \DEFINE_NFSD_CB_EVENT (setup);DEFINE_NFSD_CB_EVENT (state); +DEFINE_NFSD_CB_EVENT (lost);DEFINE_NFSD_CB_EVENT (shutdown);TRACE_DEFINE_ENUM (RPC_AUTH_NULL );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 282/770 NFSD: Adjust cb_shutdown tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit b200f0e35338b052976b6c5759e4f77a3013e6f6 ]
Show when the upper layer requested a shutdown. RPC tracepoints can already show when rpc_shutdown_client() is called.
--- fs/nfsd/nfs4callback.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/nfsd/nfs4callback.c +3 -1
@@ -1233,6 +1233,9 @@ void nfsd4_destroy_callback_queue(void)/* must be called under the state lock */ void nfsd4_shutdown_callback (struct nfs4_client *clp) { +if (clp->cl_cb_state !=NFSD4_CB_UNKNOWN ) +trace_nfsd_cb_shutdown (clp); +set_bit (NFSD4_CLIENT_CB_KILL , &clp->cl_flags);/* * Note this won't actually result in a null callback;
@@ -1278,7 +1281,6 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)* kill the old client: */ if (clp->cl_cb_client) { -trace_nfsd_cb_shutdown (clp);rpc_shutdown_client (clp->cl_cb_client); clp->cl_cb_client =NULL ;put_cred (clp->cl_cb_cred);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 283/770 NFSD: Enhance the nfsd_cb_setup tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 9f57c6062bf3ce2c6ab9ba60040b34e8134ef259 ]
Display the transport protocol and authentication flavor so admins can see what they might be getting wrong.
--- fs/nfsd/nfs4callback.c | 3 ++- fs/nfsd/trace.h | 27 ++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-)
fs/nfsd/nfs4callback.c +2 -1
@@ -941,7 +941,8 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c clp->cl_cb_conn.cb_xprt = conn->cb_xprt; clp->cl_cb_client = client; clp->cl_cb_cred = cred; -trace_nfsd_cb_setup (clp); +trace_nfsd_cb_setup (clp,rpc_peeraddr2str (client,RPC_DISPLAY_NETID ), + args.authflavor);return 0 ; }
fs/nfsd/trace.h +26 -1
@@ -910,7 +910,6 @@ DEFINE_EVENT(nfsd_cb_class, nfsd_cb_##name, \ TP_PROTO(const struct nfs4_client *clp), \ TP_ARGS(clp)) -DEFINE_NFSD_CB_EVENT(setup); DEFINE_NFSD_CB_EVENT(state); DEFINE_NFSD_CB_EVENT(lost); DEFINE_NFSD_CB_EVENT(shutdown);
@@ -931,6 +930,32 @@ TRACE_DEFINE_ENUM(RPC_AUTH_GSS_KRB5P); { RPC_AUTH_GSS_KRB5I, "krb5i" }, \ { RPC_AUTH_GSS_KRB5P, "krb5p" }) +TRACE_EVENT (nfsd_cb_setup, + TP_PROTO(const struct nfs4_client *clp, + const char *netid, + rpc_authflavor_t authflavor + ), +TP_ARGS (clp, netid, authflavor), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __field(unsigned long, authflavor) + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) + __array(unsigned char, netid, 8) + ), +TP_fast_assign ( + __entry->cl_boot = clp->cl_clientid.cl_boot; + __entry->cl_id = clp->cl_clientid.cl_id; + strlcpy(__entry->netid, netid, sizeof(__entry->netid)); + __entry->authflavor = authflavor; +memcpy (__entry->addr, &clp->cl_cb_conn.cb_addr, + sizeof(struct sockaddr_in6)); + ), +TP_printk ("addr=%pISpc client %08x:%08x proto=%s flavor=%s" , + __entry->addr, __entry->cl_boot, __entry->cl_id, + __entry->netid,show_nfsd_authflavor (__entry->authflavor)) +); + TRACE_EVENT(nfsd_cb_setup_err, TP_PROTO( const struct nfs4_client *clp,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 284/770 NFSD: Add an nfsd_cb_lm_notify tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 2cde7f8118f0fea29ad73ddcf28817f95adeffd5 ]
When the server kicks off a CB_LM_NOTIFY callback, record its arguments so we can better observe asynchronous locking behavior. For example:
nfsd-998 [002] 1471.705873: nfsd_cb_notify_lock: addr=192.168.2.51:0 client 6092a47c:35a43fc1 fh_hash=0x8950b23a
--- fs/nfsd/nfs4state.c | 4 +++- fs/nfsd/trace.h | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-)
fs/nfsd/nfs4state.c +3 -1
@@ -6494,8 +6494,10 @@ nfsd4_lm_notify(struct file_lock *fl) }spin_unlock (&nn->blocked_locks_lock); -if (queue) +if (queue) { +trace_nfsd_cb_notify_lock (lo, nbl);nfsd4_run_cb (&nbl->nbl_cb); + } }static const struct lock_manager_operations nfsd_posix_mng_ops = {
fs/nfsd/trace.h +26 -0
@@ -1027,6 +1027,32 @@ TRACE_EVENT(nfsd_cb_done, __entry->status) ); +TRACE_EVENT (nfsd_cb_notify_lock, +TP_PROTO ( + const struct nfs4_lockowner *lo, + const struct nfsd4_blocked_lock *nbl + ), +TP_ARGS (lo, nbl), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __field(u32, fh_hash) + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) + ), +TP_fast_assign ( + const struct nfs4_client *clp = lo->lo_owner.so_client; + + __entry->cl_boot = clp->cl_clientid.cl_boot; + __entry->cl_id = clp->cl_clientid.cl_id; + __entry->fh_hash = knfsd_fh_hash(&nbl->nbl_fh); +memcpy (__entry->addr, &clp->cl_cb_conn.cb_addr, + sizeof(struct sockaddr_in6)); + ), +TP_printk ("addr=%pISpc client %08x:%08x fh_hash=0x%08x" , + __entry->addr, __entry->cl_boot, __entry->cl_id, + __entry->fh_hash) +); +#endif /* _NFSD_TRACE_H */ #undef TRACE_INCLUDE_PATH
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 285/770 NFSD: Add an nfsd_cb_offload tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 87512386e951ee28ba2e7ef32b843ac97621d371 ]
Record the arguments of CB_OFFLOAD callbacks so we can better observe asynchronous copy-offload behavior. For example:
nfsd-995 [008] 7721.934222: nfsd_cb_offload:
addr=192.168.2.51:0 client 6092a47c:35a43fc1 fh_hash=0x8739113a
count=116528 status=0--- fs/nfsd/nfs4proc.c | 2 ++ fs/nfsd/trace.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+)
fs/nfsd/nfs4proc.c +2 -0
@@ -1489,6 +1489,8 @@ static int nfsd4_do_async_copy(void *data)memcpy (&cb_copy->fh, ©->fh,sizeof (copy->fh));nfsd4_init_cb (&cb_copy->cp_cb, cb_copy->cp_clp, &nfsd4_cb_offload_ops,NFSPROC4_CLNT_CB_OFFLOAD ); +trace_nfsd_cb_offload (copy->cp_clp, ©->cp_res.cb_stateid, + ©->fh, copy->cp_count, copy->nfserr);nfsd4_run_cb (&cb_copy->cp_cb); out:if (!copy->cp_intra)
fs/nfsd/trace.h +36 -0
@@ -1053,6 +1053,42 @@ TRACE_EVENT(nfsd_cb_notify_lock, __entry->fh_hash) ); +TRACE_EVENT (nfsd_cb_offload, +TP_PROTO ( + const struct nfs4_client *clp, + const stateid_t *stp, + const struct knfsd_fh *fh, + u64 count, + __be32 status + ), +TP_ARGS (clp, stp, fh, count, status), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __field(u32, si_id) + __field(u32, si_generation) + __field(u32, fh_hash) + __field(int, status) + __field(u64, count) + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) + ), +TP_fast_assign ( + __entry->cl_boot = stp->si_opaque.so_clid.cl_boot; + __entry->cl_id = stp->si_opaque.so_clid.cl_id; + __entry->si_id = stp->si_opaque.so_id; + __entry->si_generation = stp->si_generation; + __entry->fh_hash = knfsd_fh_hash(fh); + __entry->status = be32_to_cpu(status); + __entry->count = count; + memcpy(__entry->addr, &clp->cl_cb_conn.cb_addr, + sizeof(struct sockaddr_in6)); + ), +TP_printk ("addr=%pISpc client %08x:%08x stateid %08x:%08x fh_hash=0x%08x count=%llu status=%d" , + __entry->addr, __entry->cl_boot, __entry->cl_id, + __entry->si_id, __entry->si_generation, + __entry->fh_hash, __entry->count, __entry->status) +); +#endif /* _NFSD_TRACE_H */ #undef TRACE_INCLUDE_PATH
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 286/770 NFSD: Replace the nfsd_deleg_break tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 17d76ddf76e4972411402743eea7243d9a46f4f9 ]
Renamed so it can be enabled as a set with the other nfsd_cb_ tracepoints. And, consistent with those tracepoints, report the address of the client, the client ID the server has given it, and the state ID being recalled.
--- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/trace.h | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-)
fs/nfsd/nfs4state.c +1 -1
@@ -4675,7 +4675,7 @@ nfsd_break_deleg_cb(struct file_lock *fl)struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;struct nfs4_file *fp = dp->dl_stid.sc_file; -trace_nfsd_deleg_break (&dp->dl_stid.sc_stateid); +trace_nfsd_cb_recall (&dp->dl_stid);/* * We don't want the locks code to timeout the lease for us;
fs/nfsd/trace.h +31 -1
@@ -459,7 +459,6 @@ DEFINE_STATEID_EVENT(layout_recall_release);DEFINE_STATEID_EVENT (open);DEFINE_STATEID_EVENT (deleg_read); -DEFINE_STATEID_EVENT (deleg_break);DEFINE_STATEID_EVENT (deleg_recall); DECLARE_EVENT_CLASS(nfsd_stateseqid_class,
@@ -1027,6 +1026,37 @@ TRACE_EVENT(nfsd_cb_done, __entry->status) ); +TRACE_EVENT (nfsd_cb_recall, +TP_PROTO ( + const struct nfs4_stid *stid + ), +TP_ARGS (stid), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __field(u32, si_id) + __field(u32, si_generation) + __array(unsigned char, addr, sizeof(struct sockaddr_in6)) + ), +TP_fast_assign ( + const stateid_t *stp = &stid->sc_stateid; + const struct nfs4_client *clp = stid->sc_client; + + __entry->cl_boot = stp->si_opaque.so_clid.cl_boot; + __entry->cl_id = stp->si_opaque.so_clid.cl_id; + __entry->si_id = stp->si_opaque.so_id; + __entry->si_generation = stp->si_generation; + if (clp) + memcpy(__entry->addr, &clp->cl_cb_conn.cb_addr, + sizeof(struct sockaddr_in6)); + else + memset(__entry->addr, 0, sizeof(struct sockaddr_in6)); + ), +TP_printk ("addr=%pISpc client %08x:%08x stateid %08x:%08x" , + __entry->addr, __entry->cl_boot, __entry->cl_id, + __entry->si_id, __entry->si_generation) +); + TRACE_EVENT(nfsd_cb_notify_lock, TP_PROTO( const struct nfs4_lockowner *lo,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 287/770 NFSD: Add an nfsd_cb_probe tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 4ade892ae1c35527584decb7fa026553d53cd03f ]
Record a tracepoint event when the server performs a callback probe. This event can be enabled as a group with other nfsd_cb tracepoints.
--- fs/nfsd/nfs4callback.c | 1 + fs/nfsd/trace.h | 1 + 2 files changed, 2 insertions(+)
fs/nfsd/nfs4callback.c +1 -0
@@ -1000,6 +1000,7 @@ static const struct rpc_call_ops nfsd4_cb_probe_ops = {*/ void nfsd4_probe_callback (struct nfs4_client *clp) { +trace_nfsd_cb_probe (clp);nfsd4_mark_cb_state (clp,NFSD4_CB_UNKNOWN );set_bit (NFSD4_CLIENT_CB_UPDATE , &clp->cl_flags);nfsd4_run_cb (&clp->cl_cb_null);
fs/nfsd/trace.h +1 -0
@@ -910,6 +910,7 @@ DEFINE_EVENT(nfsd_cb_class, nfsd_cb_##name, \ TP_ARGS(clp))DEFINE_NFSD_CB_EVENT (state); +DEFINE_NFSD_CB_EVENT (probe);DEFINE_NFSD_CB_EVENT (lost);DEFINE_NFSD_CB_EVENT (shutdown);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 288/770 NFSD: Remove the nfsd_cb_work and nfsd_cb_done tracepoints
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 1d2bf65983a137121c165a7e69b2885572954915 ]
Clean up: These are noise in properly working systems. If you really need to observe the operation of the callback mechanism, use the sunrpc:rpc\* tracepoints along with the workqueue tracepoints.
--- fs/nfsd/nfs4callback.c | 5 ----- fs/nfsd/trace.h | 48 ------------------------------------------ 2 files changed, 53 deletions(-)
fs/nfsd/nfs4callback.c +0 -5
@@ -972,7 +972,6 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) { struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); -trace_nfsd_cb_done (clp, task->tk_status);if (task->tk_status)nfsd4_mark_cb_down (clp, task->tk_status);else
@@ -1174,8 +1173,6 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)struct nfsd4_callback *cb = calldata;struct nfs4_client *clp = cb->cb_clp; -trace_nfsd_cb_done (clp, task->tk_status); -if (!nfsd4_cb_sequence_done (task, cb))return ;
@@ -1328,8 +1325,6 @@ nfsd4_run_cb_work(struct work_struct *work)struct rpc_clnt *clnt;int flags; -trace_nfsd_cb_work (clp, cb->cb_msg.rpc_proc->p_name); -if (cb->cb_need_restart) { cb->cb_need_restart = false; }else {
fs/nfsd/trace.h +0 -48
54 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 289/770 NFSD: Update nfsd_cb_args tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit d6cbe98ff32aef795462a309ef048cfb89d1a11d ]
Clean-up: Re-order the display of IP address and client ID to be consistent with other _cb_ tracepoints.
--- fs/nfsd/trace.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/trace.h +3 -3
@@ -857,9 +857,9 @@ TRACE_EVENT(nfsd_cb_args,memcpy (__entry->addr, &conn->cb_addr,sizeof (struct sockaddr_in6 )); ), -TP_printk ("client %08x:%08x callback addr=%pISpc prog=%u ident=%u" , - __entry->cl_boot, __entry->cl_id, - __entry->addr, __entry->prog, __entry->ident) +TP_printk ("addr=%pISpc client %08x:%08x prog=%u ident=%u" , + __entry->addr, __entry->cl_boot, __entry->cl_id, + __entry->prog, __entry->ident) ); TRACE_EVENT(nfsd_cb_nodelegs,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 290/770 nfsd: Prevent truncation of an unlinked inode from blocking access to its directory
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Hsiang Huang <[email protected]>
[ Upstream commit e5d74a2d0ee67ae00edad43c3d7811016e4d2e21 ]
Truncation of an unlinked inode may take a long time for I/O waiting, and it doesn't have to prevent access to the directory. Thus, let truncation occur outside the directory's mutex, just like do_unlinkat() does.
--- fs/nfsd/vfs.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/nfsd/vfs.c +5 -0
@@ -1870,6 +1870,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, {struct dentry *dentry, *rdentry;struct inode *dirp; +struct inode *rinode;__be32 err;int host_err;
@@ -1898,6 +1899,8 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, host_err = -ENOENT ; goto out_drop_write; } + rinode =d_inode (rdentry); +ihold (rinode);if (!type) type =d_inode (rdentry)->i_mode &S_IFMT ;
@@ -1913,6 +1916,8 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,if (!host_err) host_err =commit_metadata (fhp);dput (rdentry); +fh_unlock (fhp); +iput (rinode);/* truncate the inode here */ out_drop_write:fh_drop_write (fhp);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 291/770 nfsd: move some commit_metadata()s outside the inode lock
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit eeeadbb9bd5652c47bb9b31aa9ad8b4f1b4aa8b3 ]
The commit may be time-consuming and there's no need to hold the lock for it.
More of these are possible, these were just some easy ones.
--- fs/nfsd/vfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/nfsd/vfs.c +3 -2
@@ -1626,9 +1626,9 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, host_err =vfs_symlink (d_inode (dentry), dnew, path); err =nfserrno (host_err); +fh_unlock (fhp);if (!err) err =nfserrno (commit_metadata (fhp)); -fh_unlock (fhp);fh_drop_write (fhp);
@@ -1693,6 +1693,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,if (d_really_is_negative (dold)) goto out_dput; host_err =vfs_link (dold, dirp, dnew,NULL ); +fh_unlock (ffhp);if (!host_err) { err =nfserrno (commit_metadata (ffhp));if (!err)
@@ -1913,10 +1914,10 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, host_err =vfs_rmdir (dirp, rdentry); } +fh_unlock (fhp);if (!host_err) host_err =commit_metadata (fhp);dput (rdentry); -fh_unlock (fhp);iput (rinode);/* truncate the inode here */ out_drop_write:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 292/770 NFSD add vfs_fsync after async copy is done
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Olga Kornievskaia <[email protected]>
[ Upstream commit eac0b17a77fbd763d305a5eaa4fd1119e5a0fe0d ]
Currently, the server does all copies as NFS_UNSTABLE. For synchronous copies linux client will append a COMMIT to the COPY compound but for async copies it does not (because COMMIT needs to be done after all bytes are copied and not as a reply to the COPY operation).
However, in order to save the client doing a COMMIT as a separate rpc, the server can reply back with NFS_FILE_SYNC copy. This patch proposed to add vfs_fsync() call at the end of the async copy.
--- fs/nfsd/nfs4proc.c | 15 ++++++++++++++- fs/nfsd/xdr4.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-)
fs/nfsd/nfs4proc.c +14 -1
@@ -1366,7 +1366,8 @@ static const struct nfsd4_callback_ops nfsd4_cb_offload_ops = {static void nfsd4_init_copy_res (struct nfsd4_copy *copy,bool sync) { - copy->cp_res.wr_stable_how =NFS_UNSTABLE ; + copy->cp_res.wr_stable_how = + copy->committed ?NFS_FILE_SYNC :NFS_UNSTABLE ; copy->cp_synchronous = sync;gen_boot_verifier (©->cp_res.wr_verifier, copy->cp_clp->net); }
@@ -1375,10 +1376,12 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy) {struct file *dst = copy->nf_dst->nf_file;struct file *src = copy->nf_src->nf_file; +errseq_t since;ssize_t bytes_copied =0 ;u64 bytes_total = copy->cp_count;u64 src_pos = copy->cp_src_pos;u64 dst_pos = copy->cp_dst_pos; +__be32 status;/* See RFC 7862 p.67: */ if (bytes_total ==0 )
@@ -1395,6 +1398,16 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy) src_pos += bytes_copied; dst_pos += bytes_copied; }while (bytes_total >0 && !copy->cp_synchronous); +/* for a non-zero asynchronous copy do a commit of data */ +if (!copy->cp_synchronous && copy->cp_res.wr_bytes_written >0 ) { + since =READ_ONCE (dst->f_wb_err); + status =vfs_fsync_range (dst, copy->cp_dst_pos, + copy->cp_res.wr_bytes_written,0 ); +if (!status) + status =filemap_check_wb_err (dst->f_mapping, since); +if (!status) + copy->committed = true; + }return bytes_copied; }
fs/nfsd/xdr4.h +1 -0
@@ -567,6 +567,7 @@ struct nfsd4_copy {struct vfsmount *ss_mnt;struct nfs_fh c_fh;nfs4_stateid stateid; +bool committed; };struct nfsd4_seek {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 293/770 NFSD: delay unmount sources export after inter-server copy completed.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit f4e44b393389c77958f7c58bf4415032b4cda15b ]
Currently the source's export is mounted and unmounted on every inter-server copy operation. This patch is an enhancement to delay the unmount of the source export for a certain period of time to eliminate the mount and unmount overhead on subsequent copy operations.
After a copy operation completes, a work entry is added to the delayed unmount list with an expiration time. This list is serviced by the laundromat thread to unmount the export of the expired entries. Each time the export is being used again, its expiration time is extended and the entry is re-inserted to the tail of the list.
The unmount task and the mount operation of the copy request are synced to make sure the export is not unmounted while it's being used.
--- fs/nfsd/netns.h | 6 ++ fs/nfsd/nfs4proc.c | 135 ++++++++++++++++++++++++++++++++++++++-- fs/nfsd/nfs4state.c | 71 +++++++++++++++++++++ fs/nfsd/nfsd.h | 4 ++ fs/nfsd/nfssvc.c | 3 + include/linux/nfs_ssc.h | 14 +++++ 6 files changed, 229 insertions(+), 4 deletions(-)
fs/nfsd/netns.h +6 -0
@@ -176,6 +176,12 @@ struct nfsd_net {unsigned int longest_chain_cachesize;struct shrinker nfsd_reply_cache_shrinker; + +/* tracking server-to-server copy mounts */ +spinlock_t nfsd_ssc_lock; +struct list_head nfsd_ssc_mount_list; +wait_queue_head_t nfsd_ssc_waitq; +/* utsname taken from the process that starts the server */ char nfsd_name[UNX_MAXNODENAME +1 ]; };
fs/nfsd/nfs4proc.c +131 -4
171 lines not on this page · raw message
fs/nfsd/nfs4state.c +71 -0
95 lines not on this page · raw message
fs/nfsd/nfsd.h +4 -0
@@ -484,6 +484,10 @@ static inline bool nfsd_attrs_supported(u32 minorversion, const u32 *bmval)extern int nfsd4_is_junction (struct dentry *dentry);extern int register_cld_notifier (void );extern void unregister_cld_notifier (void ); +#ifdef CONFIG_NFSD_V4_2_INTER_SSC +extern void nfsd4_ssc_init_umount_work (struct nfsd_net *nn); +#endif +#else /* CONFIG_NFSD_V4 */ static inline int nfsd4_is_junction (struct dentry *dentry) {
fs/nfsd/nfssvc.c +3 -0
@@ -403,6 +403,9 @@ static int nfsd_startup_net(struct net *net, const struct cred *cred)if (ret) goto out_filecache; +#ifdef CONFIG_NFSD_V4_2_INTER_SSC +nfsd4_ssc_init_umount_work (nn); +#endif nn->nfsd_net_up = true;return 0 ;
include/linux/nfs_ssc.h +14 -0
@@ -8,6 +8,7 @@*/ #include <linux/nfs_fs.h> +#include <linux/sunrpc/svc.h> extern struct nfs_ssc_client_ops_tbl nfs_ssc_client_tbl;
@@ -52,6 +53,19 @@ static inline void nfs42_ssc_close(struct file *filep)if (nfs_ssc_client_tbl.ssc_nfs4_ops) (*nfs_ssc_client_tbl.ssc_nfs4_ops->sco_close)(filep); } + +struct nfsd4_ssc_umount_item { +struct list_head nsui_list; +bool nsui_busy; +/* +* nsui_refcnt inited to 2, 1 on list and 1 for consumer. Entry +* is removed when refcnt drops to 1 and nsui_expire expires. +*/ +refcount_t nsui_refcnt; +unsigned long nsui_expire; +struct vfsmount *nsui_vfsmount; +char nsui_ipaddr[RPC_MAX_ADDRBUFLEN ]; +};#endif /*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 294/770 nfsd: move fsnotify on client creation outside spinlock
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit 934bd07fae7e55232845f909f78873ab8678ca74 ]
This was causing a "sleeping function called from invalid context" warning.
I don't think we need the set_and_test_bit() here; clients move from unconfirmed to confirmed only once, under the client_lock.
The (conf == unconf) is a way to check whether we're in that confirming case, hopefully that's not too obscure.
--- fs/nfsd/nfs4state.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
fs/nfsd/nfs4state.c +6 -5
@@ -2846,11 +2846,8 @@ move_to_confirmed(struct nfs4_client *clp)list_move (&clp->cl_idhash, &nn->conf_id_hashtbl[idhashval]);rb_erase (&clp->cl_namenode, &nn->unconf_name_tree);add_clp_to_name_tree (clp, &nn->conf_name_tree); -if (!test_and_set_bit (NFSD4_CLIENT_CONFIRMED , &clp->cl_flags)) { -trace_nfsd_clid_confirmed (&clp->cl_clientid); -if (clp->cl_nfsd_dentry && clp->cl_nfsd_info_dentry) -fsnotify_dentry (clp->cl_nfsd_info_dentry,FS_MODIFY ); - } +set_bit (NFSD4_CLIENT_CONFIRMED , &clp->cl_flags); +trace_nfsd_clid_confirmed (&clp->cl_clientid);renew_client_locked (clp); }
@@ -3509,6 +3506,8 @@ nfsd4_create_session(struct svc_rqst *rqstp,/* cache solo and embedded create sessions under the client_lock */ nfsd4_cache_create_session (cr_ses, cs_slot, status);spin_unlock (&nn->client_lock); +if (conf == unconf) +fsnotify_dentry (conf->cl_nfsd_info_dentry,FS_MODIFY );/* init connection and backchannel */ nfsd4_init_conn (rqstp, conn, new);nfsd4_put_session (new);
@@ -4129,6 +4128,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, }get_client_locked (conf);spin_unlock (&nn->client_lock); +if (conf == unconf) +fsnotify_dentry (conf->cl_nfsd_info_dentry,FS_MODIFY );nfsd4_probe_callback (conf);spin_lock (&nn->client_lock);put_client_renew_locked (conf);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 295/770 nfsd4: Expose the callback address and state of each NFS4 client
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Wysochanski <[email protected]>
[ Upstream commit 3518c8666f15cdd5d38878005dab1d589add1c19 ]
In addition to the client's address, display the callback channel state and address in the 'info' file.
--- fs/nfsd/nfs4state.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
fs/nfsd/nfs4state.c +17 -0
@@ -2376,6 +2376,21 @@ static void seq_quote_mem(struct seq_file *m, char *data, int len)seq_printf (m,"\"" ); } +static const char *cb_state2str (int state) +{ +switch (state) { +case NFSD4_CB_UP : +return "UP" ; +case NFSD4_CB_UNKNOWN : +return "UNKNOWN" ; +case NFSD4_CB_DOWN : +return "DOWN" ; +case NFSD4_CB_FAULT : +return "FAULT" ; + } +return "UNDEFINED" ; +} +static int client_info_show (struct seq_file *m,void *v) {struct inode *inode = m->private;
@@ -2404,6 +2419,8 @@ static int client_info_show(struct seq_file *m, void *v)seq_printf (m,"\nImplementation time: [%lld, %ld]\n" , clp->cl_nii_time.tv_sec, clp->cl_nii_time.tv_nsec); } +seq_printf (m,"callback state: %s\n" ,cb_state2str (clp->cl_cb_state)); +seq_printf (m,"callback address: %pISpc\n" , &clp->cl_cb_conn.cb_addr);drop_client (clp);return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 296/770 nfsd: fix kernel test robot warning in SSC code
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit f47dc2d3013c65631bf8903becc7d88dc9d9966e ]
Fix by initializing pointer nfsd4_ssc_umount_item with NULL instead of 0. Replace return value of nfsd4_ssc_setup_dul with __be32 instead of int.
--- fs/nfsd/nfs4proc.c | 4 ++-- fs/nfsd/nfs4state.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/nfs4proc.c +2 -2
@@ -1178,7 +1178,7 @@ extern void nfs_sb_deactive(struct super_block *sb);/* * setup a work entry in the ssc delayed unmount list. */ -static int nfsd4_ssc_setup_dul (struct nfsd_net *nn,char *ipaddr, +static __be32 nfsd4_ssc_setup_dul (struct nfsd_net *nn,char *ipaddr,struct nfsd4_ssc_umount_item **retwork,struct vfsmount **ss_mnt) {struct nfsd4_ssc_umount_item *ni =0 ;
@@ -1395,7 +1395,7 @@ nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,bool found = false;long timeout;struct nfsd4_ssc_umount_item *tmp; -struct nfsd4_ssc_umount_item *ni =0 ; +struct nfsd4_ssc_umount_item *ni =NULL ;struct nfsd_net *nn =net_generic (dst->nf_net, nfsd_net_id);nfs42_ssc_close (src->nf_file);
fs/nfsd/nfs4state.c +1 -1
@@ -5556,7 +5556,7 @@ EXPORT_SYMBOL_GPL(nfsd4_ssc_init_umount_work);*/ static void nfsd4_ssc_shutdown_umount (struct nfsd_net *nn) { -struct nfsd4_ssc_umount_item *ni =0 ; +struct nfsd4_ssc_umount_item *ni =NULL ;struct nfsd4_ssc_umount_item *tmp;spin_lock (&nn->nfsd_ssc_lock);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 297/770 NFSD: Fix error return code in nfsd4_interssc_connect()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wei Yongjun <[email protected]>
[ Upstream commit 54185267e1fe476875e649bb18e1c4254c123305 ]
'status' has been overwritten to 0 after nfsd4_ssc_setup_dul(), this cause 0 will be return in vfs_kern_mount() error case. Fix to return nfserr_nodev in this error.
--- fs/nfsd/nfs4proc.c | 1 + 1 file changed, 1 insertion(+)
fs/nfsd/nfs4proc.c +1 -0
@@ -1326,6 +1326,7 @@ nfsd4_interssc_connect(struct nl4_server *nss, struct svc_rqst *rqstp, ss_mnt =vfs_kern_mount (type,SB_KERNMOUNT , dev_name, raw_data);module_put (type->owner);if (IS_ERR (ss_mnt)) { + status = nfserr_nodev;if (work)nfsd4_ssc_cancel_dul_work (nn, work); goto out_free_devname;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 298/770 nfsd: rpc_peeraddr2str needs rcu lock
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit 05570a2b01117209b500e1989ce8f1b0524c489f ]
I'm not even sure cl_xprt can change here, but we're getting "suspicious RCU usage" warnings, and other rpc_peeraddr2str callers are taking the rcu lock.
--- fs/nfsd/nfs4callback.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfsd/nfs4callback.c +2 -0
@@ -941,8 +941,10 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c clp->cl_cb_conn.cb_xprt = conn->cb_xprt; clp->cl_cb_client = client; clp->cl_cb_cred = cred; +rcu_read_lock ();trace_nfsd_cb_setup (clp,rpc_peeraddr2str (client,RPC_DISPLAY_NETID ), args.authflavor); +rcu_read_unlock ();return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 299/770 lockd: Remove stale comments
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 99cdf57b33e68df7afc876739c93a11f0b1ba807 ]
--- include/linux/lockd/xdr.h | 6 ------ include/linux/lockd/xdr4.h | 7 +------ 2 files changed, 1 insertion(+), 12 deletions(-)
include/linux/lockd/xdr.h +0 -6
@@ -109,11 +109,5 @@ int nlmsvc_decode_shareargs(struct svc_rqst *, __be32 *);int nlmsvc_encode_shareres (struct svc_rqst *,__be32 *);int nlmsvc_decode_notify (struct svc_rqst *,__be32 *);int nlmsvc_decode_reboot (struct svc_rqst *,__be32 *); -/* -int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); -int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); -int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *); -int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *); -*/ #endif /* LOCKD_XDR_H */
include/linux/lockd/xdr4.h +1 -6
@@ -37,12 +37,7 @@ int nlm4svc_decode_shareargs(struct svc_rqst *, __be32 *);int nlm4svc_encode_shareres (struct svc_rqst *,__be32 *);int nlm4svc_decode_notify (struct svc_rqst *,__be32 *);int nlm4svc_decode_reboot (struct svc_rqst *,__be32 *); -/* -int nlmclt_encode_testargs(struct rpc_rqst *, u32 *, struct nlm_args *); -int nlmclt_encode_lockargs(struct rpc_rqst *, u32 *, struct nlm_args *); -int nlmclt_encode_cancargs(struct rpc_rqst *, u32 *, struct nlm_args *); -int nlmclt_encode_unlockargs(struct rpc_rqst *, u32 *, struct nlm_args *); -*/ +extern const struct rpc_version nlm_version4;#endif /* LOCKD_XDR4_H */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 300/770 lockd: Create a simplified .vs_dispatch method for NLM requests
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit a9ad1a8090f58b2ed1774dd0f4c7cdb8210a3793 ]
To enable xdr_stream-based encoding and decoding, create a bespoke RPC dispatch function for the lockd service.
--- fs/lockd/svc.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
fs/lockd/svc.c +43 -0
@@ -766,6 +766,46 @@ static void __exit exit_nlm(void)module_init (init_nlm);module_exit (exit_nlm); +/** +* nlmsvc_dispatch - Process an NLM Request +* @rqstp: incoming request +* @statp: pointer to location of accept_stat field in RPC Reply buffer +* +* Return values: +* %0: Processing complete; do not send a Reply +* %1: Processing complete; send Reply in rqstp->rq_res +*/ +static int nlmsvc_dispatch (struct svc_rqst *rqstp,__be32 *statp) +{ +const struct svc_procedure *procp = rqstp->rq_procinfo; +struct kvec *argv = rqstp->rq_arg.head; +struct kvec *resv = rqstp->rq_res.head; + +svcxdr_init_decode (rqstp); +if (!procp->pc_decode (rqstp, argv->iov_base)) + goto out_decode_err; + + *statp = procp->pc_func (rqstp); +if (*statp == rpc_drop_reply) +return 0 ; +if (*statp != rpc_success) +return 1 ; + +svcxdr_init_encode (rqstp); +if (!procp->pc_encode (rqstp, resv->iov_base + resv->iov_len)) + goto out_encode_err; + +return 1 ; + +out_decode_err: + *statp = rpc_garbage_args; +return 1 ; + +out_encode_err: + *statp = rpc_system_err; +return 1 ; +} +/* * Define NLM program and procedures */
@@ -775,6 +815,7 @@ static const struct svc_version nlmsvc_version1 = { .vs_nproc = 17, .vs_proc = nlmsvc_procedures, .vs_count = nlmsvc_version1_count, + .vs_dispatch = nlmsvc_dispatch, .vs_xdrsize = NLMSVC_XDRSIZE, };static unsigned int nlmsvc_version3_count[24 ];
@@ -783,6 +824,7 @@ static const struct svc_version nlmsvc_version3 = { .vs_nproc = 24, .vs_proc = nlmsvc_procedures, .vs_count = nlmsvc_version3_count, + .vs_dispatch = nlmsvc_dispatch, .vs_xdrsize = NLMSVC_XDRSIZE, };#ifdef CONFIG_LOCKD_V4
@@ -792,6 +834,7 @@ static const struct svc_version nlmsvc_version4 = { .vs_nproc = 24, .vs_proc = nlmsvc_procedures4, .vs_count = nlmsvc_version4_count, + .vs_dispatch = nlmsvc_dispatch, .vs_xdrsize = NLMSVC_XDRSIZE, };#endif
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 301/770 lockd: Common NLM XDR helpers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit a6a63ca5652ea05637ecfe349f9e895031529556 ]
Add a .h file containing xdr_stream-based XDR helpers common to both NLMv3 and NLMv4.
--- fs/lockd/svcxdr.h | 151 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 fs/lockd/svcxdr.h
fs/lockd/svcxdr.h new file +151 -0
@@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Encode/decode NLM basic data types +* +* Basic NLMv3 XDR data types are not defined in an IETF standards +* document. X/Open has a description of these data types that +* is useful. See Chapter 10 of "Protocols for Interworking: +* XNFS, Version 3W". +* +* Basic NLMv4 XDR data types are defined in Appendix II.1.4 of +* RFC 1813: "NFS Version 3 Protocol Specification". +* +* Author: Chuck Lever <[email protected]> +* +* Copyright (c) 2020, Oracle and/or its affiliates. +*/ + +#ifndef _LOCKD_SVCXDR_H_ +#define _LOCKD_SVCXDR_H_ + +static inline bool +svcxdr_decode_stats (struct xdr_stream *xdr,__be32 *status) +{ +__be32 *p; + + p =xdr_inline_decode (xdr,XDR_UNIT ); +if (!p) +return false; + *status = *p; + +return true; +} + +static inline bool +svcxdr_encode_stats (struct xdr_stream *xdr,__be32 status) +{ +__be32 *p; + + p =xdr_reserve_space (xdr,XDR_UNIT ); +if (!p) +return false; + *p = status; + +return true; +} + +static inline bool +svcxdr_decode_string (struct xdr_stream *xdr,char **data,unsigned int *data_len) +{ +__be32 *p; +u32 len; + +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return false; +if (len >NLM_MAXSTRLEN ) +return false; + p =xdr_inline_decode (xdr, len); +if (!p) +return false; + *data_len = len; + *data = (char *)p; + +return true; +} + +/* +* NLM cookies are defined by specification to be a variable-length +* XDR opaque no longer than 1024 bytes. However, this implementation +* limits their length to 32 bytes, and treats zero-length cookies +* specially. +*/ +static inline bool +svcxdr_decode_cookie (struct xdr_stream *xdr,struct nlm_cookie *cookie) +{ +__be32 *p; +u32 len; + +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return false; +if (len >NLM_MAXCOOKIELEN ) +return false; +if (!len) + goto out_hpux; + + p =xdr_inline_decode (xdr, len); +if (!p) +return false; + cookie->len = len; +memcpy (cookie->data, p, len); + +return true; + +/* apparently HPUX can return empty cookies */ +out_hpux: + cookie->len =4 ; +memset (cookie->data,0 ,4 ); +return true; +} + +static inline bool +svcxdr_encode_cookie (struct xdr_stream *xdr,const struct nlm_cookie *cookie) +{ +__be32 *p; + +if (xdr_stream_encode_u32 (xdr, cookie->len) <0 ) +return false; + p =xdr_reserve_space (xdr, cookie->len); +if (!p) +return false; +memcpy (p, cookie->data, cookie->len); + +return true; +} + +static inline bool +svcxdr_decode_owner (struct xdr_stream *xdr,struct xdr_netobj *obj) +{ +__be32 *p; +u32 len; + +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return false; +if (len >XDR_MAX_NETOBJ ) +return false; + p =xdr_inline_decode (xdr, len); +if (!p) +return false; + obj->len = len; + obj->data = (u8 *)p; + +return true; +} + +static inline bool +svcxdr_encode_owner (struct xdr_stream *xdr,const struct xdr_netobj *obj) +{ +unsigned int quadlen =XDR_QUADLEN (obj->len); +__be32 *p; + +if (xdr_stream_encode_u32 (xdr, obj->len) <0 ) +return false; + p =xdr_reserve_space (xdr, obj->len); +if (!p) +return false; + p[quadlen -1 ] =0 ;/* XDR pad */ +memcpy (p, obj->data, obj->len); + +return true; +} + +#endif /* _LOCKD_SVCXDR_H_ */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 302/770 lockd: Update the NLMv1 void argument decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit cc1029b51273da5b342683e9ae14ab4eeaa15997 ]
--- fs/lockd/xdr.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
fs/lockd/xdr.c +10 -7
@@ -19,6 +19,8 @@#include <uapi/linux/nfs2.h> +#include "svcxdr.h" +#define NLMDBG_FACILITY NLMDBG_XDR
@@ -178,8 +180,15 @@ nlm_encode_testres(__be32 *p, struct nlm_res *resp)/* -* First, the server side XDR functions +* Decode Call arguments */ + +int +nlmsvc_decode_void (struct svc_rqst *rqstp,__be32 *p) +{ +return 1 ; +} +int nlmsvc_decode_testargs (struct svc_rqst *rqstp,__be32 *p) {
@@ -339,12 +348,6 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)return xdr_argsize_check (rqstp, p); } -int -nlmsvc_decode_void (struct svc_rqst *rqstp,__be32 *p) -{ -return xdr_argsize_check (rqstp, p); -} -int nlmsvc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 303/770 lockd: Update the NLMv1 TEST arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 2fd0c67aabcf0f8821450b00ee511faa0b7761bf ]
--- fs/lockd/xdr.c | 72 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 6 deletions(-)
fs/lockd/xdr.c +66 -6
@@ -98,6 +98,33 @@ nlm_decode_fh(__be32 *p, struct nfs_fh *f)return p +XDR_QUADLEN (NFS2_FHSIZE ); } +/* +* NLM file handles are defined by specification to be a variable-length +* XDR opaque no longer than 1024 bytes. However, this implementation +* constrains their length to exactly the length of an NFSv2 file +* handle. +*/ +static bool +svcxdr_decode_fhandle (struct xdr_stream *xdr,struct nfs_fh *fh) +{ +__be32 *p; +u32 len; + +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return false; +if (len !=NFS2_FHSIZE ) +return false; + + p =xdr_inline_decode (xdr, len); +if (!p) +return false; + fh->size =NFS2_FHSIZE ; +memcpy (fh->data, p, len); +memset (fh->data +NFS2_FHSIZE ,0 ,sizeof (fh->data) -NFS2_FHSIZE ); + +return true; +} +/* * Encode and decode owner handle */
@@ -143,6 +170,38 @@ nlm_decode_lock(__be32 *p, struct nlm_lock *lock)return p; } +static bool +svcxdr_decode_lock (struct xdr_stream *xdr,struct nlm_lock *lock) +{ +struct file_lock *fl = &lock->fl; +s32 start, len, end; + +if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) +return false; +if (!svcxdr_decode_fhandle (xdr, &lock->fh)) +return false; +if (!svcxdr_decode_owner (xdr, &lock->oh)) +return false; +if (xdr_stream_decode_u32 (xdr, &lock->svid) <0 ) +return false; +if (xdr_stream_decode_u32 (xdr, &start) <0 ) +return false; +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return false; + +locks_init_lock (fl); + fl->fl_flags =FL_POSIX ; + fl->fl_type =F_RDLCK ; + end = start + len -1 ; + fl->fl_start =s32_to_loff_t (start); +if (len ==0 || end <0 ) + fl->fl_end =OFFSET_MAX ; +else + fl->fl_end =s32_to_loff_t (end); + +return true; +} +/* * Encode result of a TEST/TEST_MSG call */
@@ -192,19 +251,20 @@ nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p)int nlmsvc_decode_testargs (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp; -u32 exclusive; +u32 exclusive; -if (!(p =nlm_decode_cookie (p, &argp->cookie))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; - - exclusive =ntohl (*p++); -if (!(p =nlm_decode_lock (p, &argp->lock))) +if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) +return 0 ; +if (!svcxdr_decode_lock (xdr, &argp->lock))return 0 ;if (exclusive) argp->lock.fl.fl_type =F_WRLCK ; -return xdr_argsize_check (rqstp, p); +return 1 ; }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 304/770 lockd: Update the NLMv1 LOCK arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c1adb8c672ca2b085c400695ef064547d77eda29 ]
--- fs/lockd/xdr.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-)
fs/lockd/xdr.c +23 -18
@@ -267,35 +267,40 @@ nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -int -nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_res *resp = rqstp->rq_resp; - -if (!(p =nlm_encode_testres (p, resp))) -return 0 ; -return xdr_ressize_check (rqstp, p); -} -int nlmsvc_decode_lockargs (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp; -u32 exclusive; +u32 exclusive; -if (!(p =nlm_decode_cookie (p, &argp->cookie))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; - argp->block =ntohl (*p++); - exclusive =ntohl (*p++); -if (!(p =nlm_decode_lock (p, &argp->lock))) +if (xdr_stream_decode_bool (xdr, &argp->block) <0 ) +return 0 ; +if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) +return 0 ; +if (!svcxdr_decode_lock (xdr, &argp->lock))return 0 ;if (exclusive) argp->lock.fl.fl_type =F_WRLCK ; - argp->reclaim =ntohl (*p++); - argp->state =ntohl (*p++); +if (xdr_stream_decode_bool (xdr, &argp->reclaim) <0 ) +return 0 ; +if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) +return 0 ; argp->monitor =1 ;/* monitor client by default */ -return xdr_argsize_check (rqstp, p); +return 1 ; +} + +int +nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +{ +struct nlm_res *resp = rqstp->rq_resp; + +if (!(p =nlm_encode_testres (p, resp))) +return 0 ; +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 305/770 lockd: Update the NLMv1 CANCEL arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit f4e08f3ac8c4945ea54a740e3afcf44b34e7cf44 ]
--- fs/lockd/xdr.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-)
fs/lockd/xdr.c +19 -15
@@ -294,30 +294,34 @@ nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_cancargs (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_res *resp = rqstp->rq_resp; +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_args *argp = rqstp->rq_argp; +u32 exclusive; -if (!(p =nlm_encode_testres (p, resp))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; -return xdr_ressize_check (rqstp, p); +if (xdr_stream_decode_bool (xdr, &argp->block) <0 ) +return 0 ; +if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) +return 0 ; +if (!svcxdr_decode_lock (xdr, &argp->lock)) +return 0 ; +if (exclusive) + argp->lock.fl.fl_type =F_WRLCK ; + +return 1 ; }int -nlmsvc_decode_cancargs (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_args *argp = rqstp->rq_argp; -u32 exclusive; +struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm_decode_cookie (p, &argp->cookie))) -return 0 ; - argp->block =ntohl (*p++); - exclusive =ntohl (*p++); -if (!(p =nlm_decode_lock (p, &argp->lock))) +if (!(p =nlm_encode_testres (p, resp)))return 0 ; -if (exclusive) - argp->lock.fl.fl_type =F_WRLCK ; -return xdr_argsize_check (rqstp, p); +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 306/770 lockd: Update the NLMv1 UNLOCK arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c27045d302b022ed11d24a2653bceb6af56c6327 ]
--- fs/lockd/xdr.c | 53 +++++++++++++------------------------------------- 1 file changed, 13 insertions(+), 40 deletions(-)
fs/lockd/xdr.c +13 -40
@@ -140,36 +140,6 @@ nlm_encode_oh(__be32 *p, struct xdr_netobj *oh)return xdr_encode_netobj (p, oh); } -static __be32 * -nlm_decode_lock (__be32 *p,struct nlm_lock *lock) -{ -struct file_lock *fl = &lock->fl; -s32 start, len, end; - -if (!(p =xdr_decode_string_inplace (p, &lock->caller, - &lock->len, -NLM_MAXSTRLEN )) - || !(p =nlm_decode_fh (p, &lock->fh)) - || !(p =nlm_decode_oh (p, &lock->oh))) -return NULL ; - lock->svid =ntohl (*p++); - -locks_init_lock (fl); - fl->fl_flags =FL_POSIX ; - fl->fl_type =F_RDLCK ;/* as good as anything else */ - start =ntohl (*p++); - len =ntohl (*p++); - end = start + len -1 ; - - fl->fl_start =s32_to_loff_t (start); - -if (len ==0 || end <0 ) - fl->fl_end =OFFSET_MAX ; -else - fl->fl_end =s32_to_loff_t (end); -return p; -} -static bool svcxdr_decode_lock (struct xdr_stream *xdr,struct nlm_lock *lock) {
@@ -315,25 +285,28 @@ nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_res *resp = rqstp->rq_resp; +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_args *argp = rqstp->rq_argp; -if (!(p =nlm_encode_testres (p, resp))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; -return xdr_ressize_check (rqstp, p); +if (!svcxdr_decode_lock (xdr, &argp->lock)) +return 0 ; + argp->lock.fl.fl_type =F_UNLCK ; + +return 1 ; }int -nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_args *argp = rqstp->rq_argp; +struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm_decode_cookie (p, &argp->cookie)) - || !(p =nlm_decode_lock (p, &argp->lock))) +if (!(p =nlm_encode_testres (p, resp)))return 0 ; - argp->lock.fl.fl_type =F_UNLCK ; -return xdr_argsize_check (rqstp, p); +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 307/770 lockd: Update the NLMv1 nlm_res arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 16ddcabe6240c4fb01c97f6fce6c35ddf8626ad5 ]
--- fs/lockd/xdr.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
fs/lockd/xdr.c +14 -11
@@ -299,6 +299,20 @@ nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } +int +nlmsvc_decode_res (struct svc_rqst *rqstp,__be32 *p) +{ +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_res *resp = rqstp->rq_argp; + +if (!svcxdr_decode_cookie (xdr, &resp->cookie)) +return 0 ; +if (!svcxdr_decode_stats (xdr, &resp->status)) +return 0 ; + +return 1 ; +} +int nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -379,17 +393,6 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)return xdr_argsize_check (rqstp, p); } -int -nlmsvc_decode_res (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_res *resp = rqstp->rq_argp; - -if (!(p =nlm_decode_cookie (p, &resp->cookie))) -return 0 ; - resp->status = *p++; -return xdr_argsize_check (rqstp, p); -} -int nlmsvc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 308/770 lockd: Update the NLMv1 SM_NOTIFY arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 137e05e2f735f696e117553f7fa5ef8fb09953e1 ]
--- fs/lockd/xdr.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-)
fs/lockd/xdr.c +26 -13
@@ -313,6 +313,32 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p)return 1 ; } +int +nlmsvc_decode_reboot (struct svc_rqst *rqstp,__be32 *p) +{ +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_reboot *argp = rqstp->rq_argp; +u32 len; + +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return 0 ; +if (len >SM_MAXSTRLEN ) +return 0 ; + p =xdr_inline_decode (xdr, len); +if (!p) +return 0 ; + argp->len = len; + argp->mon = (char *)p; +if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) +return 0 ; + p =xdr_inline_decode (xdr,SM_PRIV_SIZE ); +if (!p) +return 0 ; +memcpy (&argp->priv.data, p,sizeof (argp->priv.data)); + +return 1 ; +} +int nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -380,19 +406,6 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)return xdr_argsize_check (rqstp, p); } -int -nlmsvc_decode_reboot (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_reboot *argp = rqstp->rq_argp; - -if (!(p =xdr_decode_string_inplace (p, &argp->mon, &argp->len,SM_MAXSTRLEN ))) -return 0 ; - argp->state =ntohl (*p++); -memcpy (&argp->priv.data, p,sizeof (argp->priv.data)); - p +=XDR_QUADLEN (SM_PRIV_SIZE ); -return xdr_argsize_check (rqstp, p); -} -int nlmsvc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 309/770 lockd: Update the NLMv1 SHARE arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 890939e1266b9adf3b0acd5e0385b39813cb8f11 ]
--- fs/lockd/xdr.c | 96 ++++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 70 deletions(-)
fs/lockd/xdr.c +26 -70
@@ -21,8 +21,6 @@#include "svcxdr.h" -#define NLMDBG_FACILITY NLMDBG_XDR -static inline loff_t s32_to_loff_t (__s32 offset)
@@ -46,33 +44,6 @@ loff_t_to_s32(loff_t offset)/* * XDR functions for basic NLM types */ -static __be32 *nlm_decode_cookie (__be32 *p,struct nlm_cookie *c) -{ -unsigned int len; - - len =ntohl (*p++); - -if (len==0 ) - { - c->len=4 ; -memset (c->data,0 ,4 );/* hockeypux brain damage */ - } -else if (len<=NLM_MAXCOOKIELEN ) - { - c->len=len; -memcpy (c->data, p, len); - p+=XDR_QUADLEN (len); - } -else - { -dprintk ("lockd: bad cookie size %d (only cookies under " -"%d bytes are supported.)\n" , - len,NLM_MAXCOOKIELEN ); -return NULL ; - } -return p; -} -static inline __be32 *nlm_encode_cookie (__be32 *p,struct nlm_cookie *c) {
@@ -82,22 +53,6 @@ nlm_encode_cookie(__be32 *p, struct nlm_cookie *c)return p; } -static __be32 * -nlm_decode_fh (__be32 *p,struct nfs_fh *f) -{ -unsigned int len; - -if ((len =ntohl (*p++)) !=NFS2_FHSIZE ) { -dprintk ("lockd: bad fhandle size %d (should be %d)\n" , - len,NFS2_FHSIZE ); -return NULL ; - } - f->size =NFS2_FHSIZE ; -memset (f->data,0 ,sizeof (f->data)); -memcpy (f->data, p,NFS2_FHSIZE ); -return p +XDR_QUADLEN (NFS2_FHSIZE ); -} -/* * NLM file handles are defined by specification to be a variable-length * XDR opaque no longer than 1024 bytes. However, this implementation
@@ -128,12 +83,6 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)/* * Encode and decode owner handle */ -static inline __be32 * -nlm_decode_oh (__be32 *p,struct xdr_netobj *oh) -{ -return xdr_decode_netobj (p, oh); -} -static inline __be32 *nlm_encode_oh (__be32 *p,struct xdr_netobj *oh) {
@@ -339,35 +288,42 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -int -nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_res *resp = rqstp->rq_resp; - -if (!(p =nlm_encode_testres (p, resp))) -return 0 ; -return xdr_ressize_check (rqstp, p); -} -int nlmsvc_decode_shareargs (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;struct nlm_lock *lock = &argp->lock;memset (lock,0 ,sizeof (*lock));locks_init_lock (&lock->fl); - lock->svid = ~(u32 )0 ; + lock->svid = ~(u32 )0 ; -if (!(p =nlm_decode_cookie (p, &argp->cookie)) - || !(p =xdr_decode_string_inplace (p, &lock->caller, - &lock->len,NLM_MAXSTRLEN )) - || !(p =nlm_decode_fh (p, &lock->fh)) - || !(p =nlm_decode_oh (p, &lock->oh))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; - argp->fsm_mode =ntohl (*p++); - argp->fsm_access =ntohl (*p++); -return xdr_argsize_check (rqstp, p); +if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) +return 0 ; +if (!svcxdr_decode_fhandle (xdr, &lock->fh)) +return 0 ; +if (!svcxdr_decode_owner (xdr, &lock->oh)) +return 0 ; +/* XXX: Range checks are missing in the original code */ +if (xdr_stream_decode_u32 (xdr, &argp->fsm_mode) <0 ) +return 0 ; +if (xdr_stream_decode_u32 (xdr, &argp->fsm_access) <0 ) +return 0 ; + +return 1 ; +} + +int +nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +{ +struct nlm_res *resp = rqstp->rq_resp; + +if (!(p =nlm_encode_testres (p, resp))) +return 0 ; +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 310/770 lockd: Update the NLMv1 FREE_ALL arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 14e105256b9dcdf50a003e2e9a0da77e06770a4b ]
--- fs/lockd/xdr.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
fs/lockd/xdr.c +15 -13
@@ -316,6 +316,21 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } +int +nlmsvc_decode_notify (struct svc_rqst *rqstp,__be32 *p) +{ +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_args *argp = rqstp->rq_argp; +struct nlm_lock *lock = &argp->lock; + +if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) +return 0 ; +if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) +return 0 ; + +return 1 ; +} +int nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -349,19 +364,6 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)return xdr_ressize_check (rqstp, p); } -int -nlmsvc_decode_notify (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_args *argp = rqstp->rq_argp; -struct nlm_lock *lock = &argp->lock; - -if (!(p =xdr_decode_string_inplace (p, &lock->caller, - &lock->len,NLM_MAXSTRLEN ))) -return 0 ; - argp->state =ntohl (*p++); -return xdr_argsize_check (rqstp, p); -} -int nlmsvc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 311/770 lockd: Update the NLMv1 void results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit e26ec898b68b2ab64f379ba0fc0a615b2ad41f40 ]
--- fs/lockd/xdr.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
fs/lockd/xdr.c +11 -6
@@ -331,6 +331,17 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p)return 1 ; } + +/* +* Encode Reply results +*/ + +int +nlmsvc_encode_void (struct svc_rqst *rqstp,__be32 *p) +{ +return 1 ; +} +int nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -363,9 +374,3 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p) *p++ = resp->status;return xdr_ressize_check (rqstp, p); } - -int -nlmsvc_encode_void (struct svc_rqst *rqstp,__be32 *p) -{ -return xdr_ressize_check (rqstp, p); -}
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 312/770 lockd: Update the NLMv1 TEST results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit adf98a4850b9ede9fc174c78a885845fb08499a5 ]
--- fs/lockd/xdr.c | 74 ++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 39 deletions(-)
fs/lockd/xdr.c +35 -39
@@ -80,15 +80,6 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)return true; } -/* -* Encode and decode owner handle -*/ -static inline __be32 * -nlm_encode_oh (__be32 *p,struct xdr_netobj *oh) -{ -return xdr_encode_netobj (p, oh); -} -static bool svcxdr_decode_lock (struct xdr_stream *xdr,struct nlm_lock *lock) {
@@ -121,39 +112,44 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)return true; } -/* -* Encode result of a TEST/TEST_MSG call -*/ -static __be32 * -nlm_encode_testres (__be32 *p,struct nlm_res *resp) +static bool +svcxdr_encode_holder (struct xdr_stream *xdr,const struct nlm_lock *lock) { -s32 start, len; - -if (!(p =nlm_encode_cookie (p, &resp->cookie))) -return NULL ; - *p++ = resp->status; +const struct file_lock *fl = &lock->fl; +s32 start, len; -if (resp->status == nlm_lck_denied) { -struct file_lock *fl = &resp->lock.fl; - - *p++ = (fl->fl_type ==F_RDLCK )? xdr_zero : xdr_one; - *p++ =htonl (resp->lock.svid); - -/* Encode owner handle. */ -if (!(p =xdr_encode_netobj (p, &resp->lock.oh))) -return NULL ; +/* exclusive */ +if (xdr_stream_encode_bool (xdr, fl->fl_type !=F_RDLCK ) <0 ) +return false; +if (xdr_stream_encode_u32 (xdr, lock->svid) <0 ) +return false; +if (!svcxdr_encode_owner (xdr, &lock->oh)) +return false; + start =loff_t_to_s32 (fl->fl_start); +if (fl->fl_end ==OFFSET_MAX ) + len =0 ; +else + len =loff_t_to_s32 (fl->fl_end - fl->fl_start +1 ); +if (xdr_stream_encode_u32 (xdr, start) <0 ) +return false; +if (xdr_stream_encode_u32 (xdr, len) <0 ) +return false; - start =loff_t_to_s32 (fl->fl_start); -if (fl->fl_end ==OFFSET_MAX ) - len =0 ; -else - len =loff_t_to_s32 (fl->fl_end - fl->fl_start +1 ); +return true; +} - *p++ =htonl (start); - *p++ =htonl (len); +static bool +svcxdr_encode_testrply (struct xdr_stream *xdr,const struct nlm_res *resp) +{ +if (!svcxdr_encode_stats (xdr, resp->status)) +return false; +switch (resp->status) { +case nlm_lck_denied: +if (!svcxdr_encode_holder (xdr, &resp->lock)) +return false; } -return p; +return true; }
@@ -345,11 +341,11 @@ nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p)int nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm_encode_testres (p, resp))) -return 0 ; -return xdr_ressize_check (rqstp, p); +return svcxdr_encode_cookie (xdr, &resp->cookie) && +svcxdr_encode_testrply (xdr, resp); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 313/770 lockd: Update the NLMv1 nlm_res results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit e96735a6980574ecbdb24c760b8d294095e47074 ]
--- fs/lockd/xdr.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
fs/lockd/xdr.c +6 -7
@@ -349,24 +349,23 @@ nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_res (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm_encode_cookie (p, &resp->cookie))) -return 0 ; - *p++ = resp->status; - *p++ = xdr_zero;/* sequence argument */ -return xdr_ressize_check (rqstp, p); +return svcxdr_encode_cookie (xdr, &resp->cookie) && +svcxdr_encode_stats (xdr, resp->status); }int -nlmsvc_encode_res (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) {struct nlm_res *resp = rqstp->rq_resp;if (!(p =nlm_encode_cookie (p, &resp->cookie)))return 0 ; *p++ = resp->status; + *p++ = xdr_zero;/* sequence argument */ return xdr_ressize_check (rqstp, p); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 314/770 lockd: Update the NLMv1 SHARE results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 529ca3a116e8978575fec061a71fa6865a344891 ]
--- fs/lockd/xdr.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-)
fs/lockd/xdr.c +9 -16
@@ -41,18 +41,6 @@ loff_t_to_s32(loff_t offset)return res; } -/* -* XDR functions for basic NLM types -*/ -static inline __be32 * -nlm_encode_cookie (__be32 *p,struct nlm_cookie *c) -{ - *p++ =htonl (c->len); -memcpy (p, c->data, c->len); - p+=XDR_QUADLEN (c->len); -return p; -} -/* * NLM file handles are defined by specification to be a variable-length * XDR opaque no longer than 1024 bytes. However, this implementation
@@ -361,11 +349,16 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p)int nlmsvc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm_encode_cookie (p, &resp->cookie))) +if (!svcxdr_encode_cookie (xdr, &resp->cookie))return 0 ; - *p++ = resp->status; - *p++ = xdr_zero;/* sequence argument */ -return xdr_ressize_check (rqstp, p); +if (!svcxdr_encode_stats (xdr, resp->status)) +return 0 ; +/* sequence */ +if (xdr_stream_encode_u32 (xdr,0 ) <0 ) +return 0 ; + +return 1 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 315/770 lockd: Update the NLMv4 void arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 7956521aac58e434a05cf3c68c1b66c1312e5649 ]
--- fs/lockd/xdr4.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
fs/lockd/xdr4.c +10 -7
@@ -18,6 +18,8 @@#include <linux/sunrpc/stats.h> #include <linux/lockd/lockd.h> +#include "svcxdr.h" +#define NLMDBG_FACILITY NLMDBG_XDR static inline loff_t
@@ -175,8 +177,15 @@ nlm4_encode_testres(__be32 *p, struct nlm_res *resp)/* -* First, the server side XDR functions +* Decode Call arguments */ + +int +nlm4svc_decode_void (struct svc_rqst *rqstp,__be32 *p) +{ +return 1 ; +} +int nlm4svc_decode_testargs (struct svc_rqst *rqstp,__be32 *p) {
@@ -336,12 +345,6 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)return xdr_argsize_check (rqstp, p); } -int -nlm4svc_decode_void (struct svc_rqst *rqstp,__be32 *p) -{ -return xdr_argsize_check (rqstp, p); -} -int nlm4svc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 316/770 lockd: Update the NLMv4 TEST arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 345b4159a075b15dc4ae70f1db90fa8abf85d2e7 ]
--- fs/lockd/xdr4.c | 72 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 6 deletions(-)
fs/lockd/xdr4.c +66 -6
@@ -96,6 +96,32 @@ nlm4_decode_fh(__be32 *p, struct nfs_fh *f)return p +XDR_QUADLEN (f->size); } +/* +* NLM file handles are defined by specification to be a variable-length +* XDR opaque no longer than 1024 bytes. However, this implementation +* limits their length to the size of an NFSv3 file handle. +*/ +static bool +svcxdr_decode_fhandle (struct xdr_stream *xdr,struct nfs_fh *fh) +{ +__be32 *p; +u32 len; + +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return false; +if (len >NFS_MAXFHSIZE ) +return false; + + p =xdr_inline_decode (xdr, len); +if (!p) +return false; + fh->size = len; +memcpy (fh->data, p, len); +memset (fh->data + len,0 ,sizeof (fh->data) - len); + +return true; +} +/* * Encode and decode owner handle */
@@ -135,6 +161,39 @@ nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)return p; } +static bool +svcxdr_decode_lock (struct xdr_stream *xdr,struct nlm_lock *lock) +{ +struct file_lock *fl = &lock->fl; +u64 len, start; +s64 end; + +if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) +return false; +if (!svcxdr_decode_fhandle (xdr, &lock->fh)) +return false; +if (!svcxdr_decode_owner (xdr, &lock->oh)) +return false; +if (xdr_stream_decode_u32 (xdr, &lock->svid) <0 ) +return false; +if (xdr_stream_decode_u64 (xdr, &start) <0 ) +return false; +if (xdr_stream_decode_u64 (xdr, &len) <0 ) +return false; + +locks_init_lock (fl); + fl->fl_flags =FL_POSIX ; + fl->fl_type =F_RDLCK ; + end = start + len -1 ; + fl->fl_start =s64_to_loff_t (start); +if (len ==0 || end <0 ) + fl->fl_end =OFFSET_MAX ; +else + fl->fl_end =s64_to_loff_t (end); + +return true; +} +/* * Encode result of a TEST/TEST_MSG call */
@@ -189,19 +248,20 @@ nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p)int nlm4svc_decode_testargs (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp; -u32 exclusive; +u32 exclusive; -if (!(p =nlm4_decode_cookie (p, &argp->cookie))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; - - exclusive =ntohl (*p++); -if (!(p =nlm4_decode_lock (p, &argp->lock))) +if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) +return 0 ; +if (!svcxdr_decode_lock (xdr, &argp->lock))return 0 ;if (exclusive) argp->lock.fl.fl_type =F_WRLCK ; -return xdr_argsize_check (rqstp, p); +return 1 ; }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 317/770 lockd: Update the NLMv4 LOCK arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 0e5977af4fdc277984fca7d8c2e0c880935775a0 ]
--- fs/lockd/xdr4.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-)
fs/lockd/xdr4.c +23 -18
@@ -264,35 +264,40 @@ nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -int -nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_res *resp = rqstp->rq_resp; - -if (!(p =nlm4_encode_testres (p, resp))) -return 0 ; -return xdr_ressize_check (rqstp, p); -} -int nlm4svc_decode_lockargs (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp; -u32 exclusive; +u32 exclusive; -if (!(p =nlm4_decode_cookie (p, &argp->cookie))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; - argp->block =ntohl (*p++); - exclusive =ntohl (*p++); -if (!(p =nlm4_decode_lock (p, &argp->lock))) +if (xdr_stream_decode_bool (xdr, &argp->block) <0 ) +return 0 ; +if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) +return 0 ; +if (!svcxdr_decode_lock (xdr, &argp->lock))return 0 ;if (exclusive) argp->lock.fl.fl_type =F_WRLCK ; - argp->reclaim =ntohl (*p++); - argp->state =ntohl (*p++); +if (xdr_stream_decode_bool (xdr, &argp->reclaim) <0 ) +return 0 ; +if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) +return 0 ; argp->monitor =1 ;/* monitor client by default */ -return xdr_argsize_check (rqstp, p); +return 1 ; +} + +int +nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +{ +struct nlm_res *resp = rqstp->rq_resp; + +if (!(p =nlm4_encode_testres (p, resp))) +return 0 ; +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 318/770 lockd: Update the NLMv4 CANCEL arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 1e1f38dcf3c031715191e1fd26f70a0affca4dbd ]
--- fs/lockd/xdr4.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-)
fs/lockd/xdr4.c +18 -15
@@ -291,30 +291,33 @@ nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_cancargs (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_res *resp = rqstp->rq_resp; +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_args *argp = rqstp->rq_argp; +u32 exclusive; -if (!(p =nlm4_encode_testres (p, resp))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; -return xdr_ressize_check (rqstp, p); +if (xdr_stream_decode_bool (xdr, &argp->block) <0 ) +return 0 ; +if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) +return 0 ; +if (!svcxdr_decode_lock (xdr, &argp->lock)) +return 0 ; +if (exclusive) + argp->lock.fl.fl_type =F_WRLCK ; +return 1 ; }int -nlm4svc_decode_cancargs (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_args *argp = rqstp->rq_argp; -u32 exclusive; +struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm4_decode_cookie (p, &argp->cookie))) -return 0 ; - argp->block =ntohl (*p++); - exclusive =ntohl (*p++); -if (!(p =nlm4_decode_lock (p, &argp->lock))) +if (!(p =nlm4_encode_testres (p, resp)))return 0 ; -if (exclusive) - argp->lock.fl.fl_type =F_WRLCK ; -return xdr_argsize_check (rqstp, p); +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 319/770 lockd: Update the NLMv4 UNLOCK arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit d76d8c25cea794f65615f3a2324052afa4b5f900 ]
--- fs/lockd/xdr4.c | 53 ++++++++++++------------------------------------- 1 file changed, 13 insertions(+), 40 deletions(-)
fs/lockd/xdr4.c +13 -40
@@ -131,36 +131,6 @@ nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)return xdr_decode_netobj (p, oh); } -static __be32 * -nlm4_decode_lock (__be32 *p,struct nlm_lock *lock) -{ -struct file_lock *fl = &lock->fl; -__u64 len, start; -__s64 end; - -if (!(p =xdr_decode_string_inplace (p, &lock->caller, - &lock->len,NLM_MAXSTRLEN )) - || !(p =nlm4_decode_fh (p, &lock->fh)) - || !(p =nlm4_decode_oh (p, &lock->oh))) -return NULL ; - lock->svid =ntohl (*p++); - -locks_init_lock (fl); - fl->fl_flags =FL_POSIX ; - fl->fl_type =F_RDLCK ;/* as good as anything else */ - p =xdr_decode_hyper (p, &start); - p =xdr_decode_hyper (p, &len); - end = start + len -1 ; - - fl->fl_start =s64_to_loff_t (start); - -if (len ==0 || end <0 ) - fl->fl_end =OFFSET_MAX ; -else - fl->fl_end =s64_to_loff_t (end); -return p; -} -static bool svcxdr_decode_lock (struct xdr_stream *xdr,struct nlm_lock *lock) {
@@ -311,25 +281,28 @@ nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_unlockargs (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_res *resp = rqstp->rq_resp; +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_args *argp = rqstp->rq_argp; -if (!(p =nlm4_encode_testres (p, resp))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; -return xdr_ressize_check (rqstp, p); +if (!svcxdr_decode_lock (xdr, &argp->lock)) +return 0 ; + argp->lock.fl.fl_type =F_UNLCK ; + +return 1 ; }int -nlm4svc_decode_unlockargs (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) { -struct nlm_args *argp = rqstp->rq_argp; +struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm4_decode_cookie (p, &argp->cookie)) - || !(p =nlm4_decode_lock (p, &argp->lock))) +if (!(p =nlm4_encode_testres (p, resp)))return 0 ; - argp->lock.fl.fl_type =F_UNLCK ; -return xdr_argsize_check (rqstp, p); +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 320/770 lockd: Update the NLMv4 nlm_res arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit b4c24b5a41da63e5f3a9b6ea56cbe2a1efe49579 ]
--- fs/lockd/xdr4.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-)
fs/lockd/xdr4.c +14 -11
@@ -295,6 +295,20 @@ nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } +int +nlm4svc_decode_res (struct svc_rqst *rqstp,__be32 *p) +{ +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_res *resp = rqstp->rq_argp; + +if (!svcxdr_decode_cookie (xdr, &resp->cookie)) +return 0 ; +if (!svcxdr_decode_stats (xdr, &resp->status)) +return 0 ; + +return 1 ; +} +int nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -375,17 +389,6 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)return xdr_argsize_check (rqstp, p); } -int -nlm4svc_decode_res (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_res *resp = rqstp->rq_argp; - -if (!(p =nlm4_decode_cookie (p, &resp->cookie))) -return 0 ; - resp->status = *p++; -return xdr_argsize_check (rqstp, p); -} -int nlm4svc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 321/770 lockd: Update the NLMv4 SM_NOTIFY arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit bc3665fd718b325cfff3abd383b00d1a87e028dc ]
--- fs/lockd/xdr4.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-)
fs/lockd/xdr4.c +26 -13
@@ -309,6 +309,32 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p)return 1 ; } +int +nlm4svc_decode_reboot (struct svc_rqst *rqstp,__be32 *p) +{ +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_reboot *argp = rqstp->rq_argp; +u32 len; + +if (xdr_stream_decode_u32 (xdr, &len) <0 ) +return 0 ; +if (len >SM_MAXSTRLEN ) +return 0 ; + p =xdr_inline_decode (xdr, len); +if (!p) +return 0 ; + argp->len = len; + argp->mon = (char *)p; +if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) +return 0 ; + p =xdr_inline_decode (xdr,SM_PRIV_SIZE ); +if (!p) +return 0 ; +memcpy (&argp->priv.data, p,sizeof (argp->priv.data)); + +return 1 ; +} +int nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -376,19 +402,6 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)return xdr_argsize_check (rqstp, p); } -int -nlm4svc_decode_reboot (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_reboot *argp = rqstp->rq_argp; - -if (!(p =xdr_decode_string_inplace (p, &argp->mon, &argp->len,SM_MAXSTRLEN ))) -return 0 ; - argp->state =ntohl (*p++); -memcpy (&argp->priv.data, p,sizeof (argp->priv.data)); - p +=XDR_QUADLEN (SM_PRIV_SIZE ); -return xdr_argsize_check (rqstp, p); -} -int nlm4svc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 322/770 lockd: Update the NLMv4 SHARE arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 7cf96b6d0104b12aa30961901879e428884b1695 ]
--- fs/lockd/xdr4.c | 99 +++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 73 deletions(-)
fs/lockd/xdr4.c +26 -73
@@ -42,37 +42,6 @@ loff_t_to_s64(loff_t offset)return res; } -/* -* XDR functions for basic NLM types -*/ -static __be32 * -nlm4_decode_cookie (__be32 *p,struct nlm_cookie *c) -{ -unsigned int len; - - len =ntohl (*p++); - -if (len==0 ) - { - c->len=4 ; -memset (c->data,0 ,4 );/* hockeypux brain damage */ - } -else if (len<=NLM_MAXCOOKIELEN ) - { - c->len=len; -memcpy (c->data, p, len); - p+=XDR_QUADLEN (len); - } -else - { -dprintk ("lockd: bad cookie size %d (only cookies under " -"%d bytes are supported.)\n" , - len,NLM_MAXCOOKIELEN ); -return NULL ; - } -return p; -} -static __be32 *nlm4_encode_cookie (__be32 *p,struct nlm_cookie *c) {
@@ -82,20 +51,6 @@ nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)return p; } -static __be32 * -nlm4_decode_fh (__be32 *p,struct nfs_fh *f) -{ -memset (f->data,0 ,sizeof (f->data)); - f->size =ntohl (*p++); -if (f->size >NFS_MAXFHSIZE ) { -dprintk ("lockd: bad fhandle size %d (should be <=%d)\n" , - f->size,NFS_MAXFHSIZE ); -return NULL ; - } -memcpy (f->data, p, f->size); -return p +XDR_QUADLEN (f->size); -} -/* * NLM file handles are defined by specification to be a variable-length * XDR opaque no longer than 1024 bytes. However, this implementation
@@ -122,15 +77,6 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)return true; } -/* -* Encode and decode owner handle -*/ -static __be32 * -nlm4_decode_oh (__be32 *p,struct xdr_netobj *oh) -{ -return xdr_decode_netobj (p, oh); -} -static bool svcxdr_decode_lock (struct xdr_stream *xdr,struct nlm_lock *lock) {
@@ -335,35 +281,42 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -int -nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_res *resp = rqstp->rq_resp; - -if (!(p =nlm4_encode_testres (p, resp))) -return 0 ; -return xdr_ressize_check (rqstp, p); -} -int nlm4svc_decode_shareargs (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;struct nlm_lock *lock = &argp->lock;memset (lock,0 ,sizeof (*lock));locks_init_lock (&lock->fl); - lock->svid = ~(u32 )0 ; + lock->svid = ~(u32 )0 ; -if (!(p =nlm4_decode_cookie (p, &argp->cookie)) - || !(p =xdr_decode_string_inplace (p, &lock->caller, - &lock->len,NLM_MAXSTRLEN )) - || !(p =nlm4_decode_fh (p, &lock->fh)) - || !(p =nlm4_decode_oh (p, &lock->oh))) +if (!svcxdr_decode_cookie (xdr, &argp->cookie))return 0 ; - argp->fsm_mode =ntohl (*p++); - argp->fsm_access =ntohl (*p++); -return xdr_argsize_check (rqstp, p); +if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) +return 0 ; +if (!svcxdr_decode_fhandle (xdr, &lock->fh)) +return 0 ; +if (!svcxdr_decode_owner (xdr, &lock->oh)) +return 0 ; +/* XXX: Range checks are missing in the original code */ +if (xdr_stream_decode_u32 (xdr, &argp->fsm_mode) <0 ) +return 0 ; +if (xdr_stream_decode_u32 (xdr, &argp->fsm_access) <0 ) +return 0 ; + +return 1 ; +} + +int +nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +{ +struct nlm_res *resp = rqstp->rq_resp; + +if (!(p =nlm4_encode_testres (p, resp))) +return 0 ; +return xdr_ressize_check (rqstp, p); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 323/770 lockd: Update the NLMv4 FREE_ALL arguments decoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 3049e974a7c7cfa0c15fb807f4a3e75b2ab8517a ]
--- fs/lockd/xdr4.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
fs/lockd/xdr4.c +15 -13
@@ -309,6 +309,21 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } +int +nlm4svc_decode_notify (struct svc_rqst *rqstp,__be32 *p) +{ +struct xdr_stream *xdr = &rqstp->rq_arg_stream; +struct nlm_args *argp = rqstp->rq_argp; +struct nlm_lock *lock = &argp->lock; + +if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) +return 0 ; +if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) +return 0 ; + +return 1 ; +} +int nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -342,19 +357,6 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)return xdr_ressize_check (rqstp, p); } -int -nlm4svc_decode_notify (struct svc_rqst *rqstp,__be32 *p) -{ -struct nlm_args *argp = rqstp->rq_argp; -struct nlm_lock *lock = &argp->lock; - -if (!(p =xdr_decode_string_inplace (p, &lock->caller, - &lock->len,NLM_MAXSTRLEN ))) -return 0 ; - argp->state =ntohl (*p++); -return xdr_argsize_check (rqstp, p); -} -int nlm4svc_encode_void (struct svc_rqst *rqstp,__be32 *p) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 324/770 lockd: Update the NLMv4 void results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit ec757e423b4fcd6e5ea4405d1e8243c040458d78 ]
--- fs/lockd/xdr4.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
fs/lockd/xdr4.c +11 -6
@@ -324,6 +324,17 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p)return 1 ; } + +/* +* Encode Reply results +*/ + +int +nlm4svc_encode_void (struct svc_rqst *rqstp,__be32 *p) +{ +return 1 ; +} +int nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) {
@@ -356,9 +367,3 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p) *p++ = resp->status;return xdr_ressize_check (rqstp, p); } - -int -nlm4svc_encode_void (struct svc_rqst *rqstp,__be32 *p) -{ -return xdr_ressize_check (rqstp, p); -}
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 325/770 lockd: Update the NLMv4 TEST results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 1beef1473ccaa70a2d54f9e76fba5f534931ea23 ]
--- fs/lockd/xdr4.c | 74 ++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 38 deletions(-)
fs/lockd/xdr4.c +36 -38
@@ -20,8 +20,6 @@#include "svcxdr.h" -#define NLMDBG_FACILITY NLMDBG_XDR -static inline loff_t s64_to_loff_t (__s64 offset) {
@@ -110,44 +108,44 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)return true; } -/* -* Encode result of a TEST/TEST_MSG call -*/ -static __be32 * -nlm4_encode_testres (__be32 *p,struct nlm_res *resp) +static bool +svcxdr_encode_holder (struct xdr_stream *xdr,const struct nlm_lock *lock) { -s64 start, len; +const struct file_lock *fl = &lock->fl; +s64 start, len; -dprintk ("xdr: before encode_testres (p %p resp %p)\n" , p, resp); -if (!(p =nlm4_encode_cookie (p, &resp->cookie))) -return NULL ; - *p++ = resp->status; +/* exclusive */ +if (xdr_stream_encode_bool (xdr, fl->fl_type !=F_RDLCK ) <0 ) +return false; +if (xdr_stream_encode_u32 (xdr, lock->svid) <0 ) +return false; +if (!svcxdr_encode_owner (xdr, &lock->oh)) +return false; + start =loff_t_to_s64 (fl->fl_start); +if (fl->fl_end ==OFFSET_MAX ) + len =0 ; +else + len =loff_t_to_s64 (fl->fl_end - fl->fl_start +1 ); +if (xdr_stream_encode_u64 (xdr, start) <0 ) +return false; +if (xdr_stream_encode_u64 (xdr, len) <0 ) +return false; + +return true; +} -if (resp->status == nlm_lck_denied) { -struct file_lock *fl = &resp->lock.fl; - - *p++ = (fl->fl_type ==F_RDLCK )? xdr_zero : xdr_one; - *p++ =htonl (resp->lock.svid); - -/* Encode owner handle. */ -if (!(p =xdr_encode_netobj (p, &resp->lock.oh))) -return NULL ; - - start =loff_t_to_s64 (fl->fl_start); -if (fl->fl_end ==OFFSET_MAX ) - len =0 ; -else - len =loff_t_to_s64 (fl->fl_end - fl->fl_start +1 ); - - p =xdr_encode_hyper (p, start); - p =xdr_encode_hyper (p, len); -dprintk ("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n" , - resp->status, (int )resp->lock.svid, fl->fl_type, - (long long )fl->fl_start, (long long )fl->fl_end); +static bool +svcxdr_encode_testrply (struct xdr_stream *xdr,const struct nlm_res *resp) +{ +if (!svcxdr_encode_stats (xdr, resp->status)) +return false; +switch (resp->status) { +case nlm_lck_denied: +if (!svcxdr_encode_holder (xdr, &resp->lock)) +return false; } -dprintk ("xdr: after encode_testres (p %p resp %p)\n" , p, resp); -return p; +return true; }
@@ -338,11 +336,11 @@ nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p)int nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm4_encode_testres (p, resp))) -return 0 ; -return xdr_ressize_check (rqstp, p); +return svcxdr_encode_cookie (xdr, &resp->cookie) && +svcxdr_encode_testrply (xdr, resp); }int
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 326/770 lockd: Update the NLMv4 nlm_res results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 447c14d48968d0d4c2733c3f8052cb63aa1deb38 ]
--- fs/lockd/xdr4.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
fs/lockd/xdr4.c +6 -7
@@ -344,24 +344,23 @@ nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_res (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm4_encode_cookie (p, &resp->cookie))) -return 0 ; - *p++ = resp->status; - *p++ = xdr_zero;/* sequence argument */ -return xdr_ressize_check (rqstp, p); +return svcxdr_encode_cookie (xdr, &resp->cookie) && +svcxdr_encode_stats (xdr, resp->status); }int -nlm4svc_encode_res (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) {struct nlm_res *resp = rqstp->rq_resp;if (!(p =nlm4_encode_cookie (p, &resp->cookie)))return 0 ; *p++ = resp->status; + *p++ = xdr_zero;/* sequence argument */ return xdr_ressize_check (rqstp, p); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 327/770 lockd: Update the NLMv4 SHARE results encoder to use struct xdr_stream
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 0ff5b50ab1f7f39862d0cdf6803978d31b27f25e ]
--- fs/lockd/xdr4.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
fs/lockd/xdr4.c +9 -13
@@ -40,15 +40,6 @@ loff_t_to_s64(loff_t offset)return res; } -static __be32 * -nlm4_encode_cookie (__be32 *p,struct nlm_cookie *c) -{ - *p++ =htonl (c->len); -memcpy (p, c->data, c->len); - p+=XDR_QUADLEN (c->len); -return p; -} -/* * NLM file handles are defined by specification to be a variable-length * XDR opaque no longer than 1024 bytes. However, this implementation
@@ -356,11 +347,16 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p)int nlm4svc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) { +struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; -if (!(p =nlm4_encode_cookie (p, &resp->cookie))) +if (!svcxdr_encode_cookie (xdr, &resp->cookie))return 0 ; - *p++ = resp->status; - *p++ = xdr_zero;/* sequence argument */ -return xdr_ressize_check (rqstp, p); +if (!svcxdr_encode_stats (xdr, resp->status)) +return 0 ; +/* sequence */ +if (xdr_stream_encode_u32 (xdr,0 ) <0 ) +return 0 ; + +return 1 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 328/770 nfsd: remove redundant assignment to pointer this
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Colin Ian King <[email protected]>
[ Upstream commit e34c0ce9136a0fe96f0f547898d14c44f3c9f147 ]
The pointer 'this' is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed.
Addresses-Coverity: ("Unused value")
--- fs/nfsd/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -3369,7 +3369,7 @@ bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) {struct nfsd4_compoundres *resp = rqstp->rq_resp;struct nfsd4_compoundargs *argp = rqstp->rq_argp; -struct nfsd4_op *this = &argp->ops[resp->opcnt -1 ]; +struct nfsd4_op *this;struct nfsd4_compound_state *cstate = &resp->cstate;struct nfs4_op_map *allow = &cstate->clp->cl_spo_must_allow;u32 opiter;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 329/770 NFSD: Prevent a possible oops in the nfs_dirent() tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 7b08cf62b1239a4322427d677ea9363f0ab677c6 ]
The double copy of the string is a mistake, plus __assign_str() uses strlen(), which is wrong to do on a string that isn't guaranteed to be NUL-terminated.
--- fs/nfsd/trace.h | 1 - 1 file changed, 1 deletion(-)
fs/nfsd/trace.h +0 -1
@@ -408,7 +408,6 @@ TRACE_EVENT(nfsd_dirent, __entry->ino = ino; __entry->len = namlen;memcpy (__get_str (name), name, namlen); -__assign_str (name, name); ), TP_printk("fh_hash=0x%08x ino=%llu name=%.*s", __entry->fh_hash, __entry->ino,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 330/770 nfsd: fix NULL dereference in nfs3svc_encode_getaclres
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit ab1016d39cc052064e32f25ad18ef8767a0ee3b8 ]
In error cases the dentry may be NULL.
Before 20798dfe249a, the encoder also checked dentry and d_really_is_positive(dentry), but that looks like overkill to me--zero status should be enough to guarantee a positive dentry.
This isn't the first time we've seen an error-case NULL dereference hidden in the initialization of a local variable in an xdr encoder. But I went back through the other recent rewrites and didn't spot any similar bugs.
--- fs/nfsd/nfs3acl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nfsd/nfs3acl.c +2 -1
@@ -170,7 +170,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)struct nfsd3_getaclres *resp = rqstp->rq_resp;struct dentry *dentry = resp->fh.fh_dentry;struct kvec *head = rqstp->rq_res.head; -struct inode *inode =d_inode (dentry); +struct inode *inode;unsigned int base;int n;int w;
@@ -179,6 +179,7 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p)return 0 ;switch (resp->status) {case nfs_ok: + inode =d_inode (dentry);if (!svcxdr_encode_post_op_attr (rqstp, xdr, &resp->fh))return 0 ;if (xdr_stream_encode_u32 (xdr, resp->mask) <0 )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 331/770 kernel/pid.c: remove static qualifier from pidfd_create()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Bobrowski <[email protected]>
[ Upstream commit c576e0fcd6188d0edb50b0fb83f853433ef4819b ]
With the idea of returning pidfds from the fanotify API, we need to expose a mechanism for creating pidfds. We drop the static qualifier from pidfd_create() and add its declaration to linux/pid.h so that the pidfd_create() helper can be called from other kernel subsystems i.e. fanotify.
--- include/linux/pid.h | 1 + kernel/pid.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-)
include/linux/pid.h +1 -0
@@ -78,6 +78,7 @@ struct file;extern struct pid *pidfd_pid (const struct file *file);struct pid *pidfd_get_pid (unsigned int fd,unsigned int *flags); +int pidfd_create (struct pid *pid,unsigned int flags);static inline struct pid *get_pid (struct pid *pid) {
kernel/pid.c +3 -1
@@ -550,10 +550,12 @@ struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags)* Note, that this function can only be called after the fd table has * been unshared to avoid leaking the pidfd to the new process. * +* This symbol should not be explicitly exported to loadable modules. +* * Return: On success, a cloexec pidfd is returned. * On error, a negative errno number will be returned. */ -static int pidfd_create (struct pid *pid,unsigned int flags) +int pidfd_create (struct pid *pid,unsigned int flags) {int fd;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 332/770 kernel/pid.c: implement additional checks upon pidfd_create() parameters
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Bobrowski <[email protected]>
[ Upstream commit 490b9ba881e2c6337bb09b68010803ae98e59f4a ]
By adding the pidfd_create() declaration to linux/pid.h, we effectively expose this function to the rest of the kernel. In order to avoid any unintended behavior, or set false expectations upon this function, ensure that constraints are forced upon each of the passed parameters. This includes the checking of whether the passed struct pid is a thread-group leader as pidfd creation is currently limited to such pid types.
--- kernel/pid.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
kernel/pid.c +7 -4
@@ -559,6 +559,12 @@ int pidfd_create(struct pid *pid, unsigned int flags) {int fd; +if (!pid || !pid_has_task (pid,PIDTYPE_TGID )) +return -EINVAL ; + +if (flags & ~(O_NONBLOCK |O_RDWR |O_CLOEXEC )) +return -EINVAL ; + fd =anon_inode_getfd ("[pidfd]" , &pidfd_fops,get_pid (pid), flags |O_RDWR |O_CLOEXEC );if (fd <0 )
@@ -598,10 +604,7 @@ SYSCALL_DEFINE2(pidfd_open, pid_t, pid, unsigned int, flags)if (!p)return -ESRCH ; -if (pid_has_task (p,PIDTYPE_TGID )) - fd =pidfd_create (p, flags); -else - fd = -EINVAL ; + fd =pidfd_create (p, flags);put_pid (p);return fd;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 333/770 fanotify: minor cosmetic adjustments to fid labels
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Bobrowski <[email protected]>
[ Upstream commit d3424c9bac893bd06f38a20474cd622881d384ca ]
With the idea to support additional info record types in the future i.e. fanotify_event_info_pidfd, it's a good idea to rename some of the labels assigned to some of the existing fid related functions, parameters, etc which more accurately represent the intent behind their usage.
For example, copy_info_to_user() was defined with a generic function label, which arguably reads as being supportive of different info record types, however the parameter list for this function is explicitly tailored towards the creation and copying of the fanotify_event_info_fid records. This same point applies to the macro defined as FANOTIFY_INFO_HDR_LEN.
With fanotify_event_info_len(), we change the parameter label so that the function implies that it can be extended to calculate the length for additional info record types.
--- fs/notify/fanotify/fanotify_user.c | 33 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-)
fs/notify/fanotify/fanotify_user.c +19 -14
@@ -104,7 +104,7 @@ struct kmem_cache *fanotify_path_event_cachep __read_mostly;struct kmem_cache *fanotify_perm_event_cachep__read_mostly ;#define FANOTIFY_EVENT_ALIGN 4 -#define FANOTIFY_INFO_HDR_LEN \ +#define FANOTIFY_FID_INFO_HDR_LEN \ (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle))static int fanotify_fid_info_len (int fh_len,int name_len)
@@ -114,10 +114,11 @@ static int fanotify_fid_info_len(int fh_len, int name_len)if (name_len) info_len += name_len +1 ; -return roundup (FANOTIFY_INFO_HDR_LEN + info_len,FANOTIFY_EVENT_ALIGN ); +return roundup (FANOTIFY_FID_INFO_HDR_LEN + info_len, +FANOTIFY_EVENT_ALIGN ); } -static int fanotify_event_info_len (unsigned int fid_mode, +static int fanotify_event_info_len (unsigned int info_mode,struct fanotify_event *event) {struct fanotify_info *info =fanotify_event_info (event);
@@ -128,7 +129,8 @@ static int fanotify_event_info_len(unsigned int fid_mode,if (dir_fh_len) { info_len +=fanotify_fid_info_len (dir_fh_len, info->name_len); - }else if ((fid_mode &FAN_REPORT_NAME ) && (event->mask &FAN_ONDIR )) { + }else if ((info_mode &FAN_REPORT_NAME ) && + (event->mask &FAN_ONDIR )) {/* * With group flag FAN_REPORT_NAME, if name was not recorded in * event on a directory, we will report the name ".".
@@ -303,9 +305,10 @@ static int process_access_response(struct fsnotify_group *group,return -ENOENT ; } -static int copy_info_to_user (__kernel_fsid_t *fsid,struct fanotify_fh *fh, -int info_type,const char *name,size_t name_len, -char __user *buf,size_t count) +static int copy_fid_info_to_user (__kernel_fsid_t *fsid,struct fanotify_fh *fh, +int info_type,const char *name, +size_t name_len, +char __user *buf,size_t count) {struct fanotify_event_info_fid info = { };struct file_handle handle = { };
@@ -463,10 +466,11 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,if (fanotify_event_dir_fh_len (event)) { info_type = info->name_len ?FAN_EVENT_INFO_TYPE_DFID_NAME :FAN_EVENT_INFO_TYPE_DFID ; - ret =copy_info_to_user (fanotify_event_fsid (event), -fanotify_info_dir_fh (info), - info_type,fanotify_info_name (info), - info->name_len, buf, count); + ret =copy_fid_info_to_user (fanotify_event_fsid (event), +fanotify_info_dir_fh (info), + info_type, +fanotify_info_name (info), + info->name_len, buf, count);if (ret <0 ) goto out_close_fd;
@@ -512,9 +516,10 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, info_type =FAN_EVENT_INFO_TYPE_FID ; } - ret =copy_info_to_user (fanotify_event_fsid (event), -fanotify_event_object_fh (event), - info_type, dot, dot_len, buf, count); + ret =copy_fid_info_to_user (fanotify_event_fsid (event), +fanotify_event_object_fh (event), + info_type, dot, dot_len, + buf, count);if (ret <0 ) goto out_close_fd;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 334/770 fanotify: introduce a generic info record copying helper
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Bobrowski <[email protected]>
[ Upstream commit 0aca67bb7f0d8c997dfef8ff0bfeb0afb361f0e6 ]
The copy_info_records_to_user() helper allows for the separation of info record copying routines/conditionals from copy_event_to_user(), which reduces the overall clutter within this function. This becomes especially true as we start introducing additional info records in the future i.e. struct fanotify_event_info_pidfd. On success, this helper returns the total amount of bytes that have been copied into the user supplied buffer and on error, a negative value is returned to the caller.
The newly defined macro FANOTIFY_INFO_MODES can be used to obtain info record types that have been enabled for a specific notification group. This macro becomes useful in the subsequent patch when the FAN_REPORT_PIDFD initialization flag is introduced.
--- fs/notify/fanotify/fanotify_user.c | 151 ++++++++++++++++------------- include/linux/fanotify.h | 2 + 2 files changed, 88 insertions(+), 65 deletions(-)
fs/notify/fanotify/fanotify_user.c +86 -65
@@ -173,7 +173,7 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group,size_t event_size =FAN_EVENT_METADATA_LEN ;struct fanotify_event *event =NULL ;struct fsnotify_event *fsn_event; -unsigned int fid_mode =FAN_GROUP_FLAG (group,FANOTIFY_FID_BITS ); +unsigned int info_mode =FAN_GROUP_FLAG (group,FANOTIFY_INFO_MODES );pr_debug ("%s: group=%p count=%zd\n" , __func__, group, count);
@@ -183,8 +183,8 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group, goto out; event =FANOTIFY_E (fsn_event); -if (fid_mode) - event_size +=fanotify_event_info_len (fid_mode, event); +if (info_mode) + event_size +=fanotify_event_info_len (info_mode, event);if (event_size > count) { event =ERR_PTR (-EINVAL );
@@ -401,68 +401,17 @@ static int copy_fid_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh,return info_len; } -static ssize_t copy_event_to_user (struct fsnotify_group *group, -struct fanotify_event *event, -char __user *buf,size_t count) +static int copy_info_records_to_user (struct fanotify_event *event, +struct fanotify_info *info, +unsigned int info_mode, +char __user *buf,size_t count) { -struct fanotify_event_metadata metadata; -struct path *path =fanotify_event_path (event); -struct fanotify_info *info =fanotify_event_info (event); -unsigned int fid_mode =FAN_GROUP_FLAG (group,FANOTIFY_FID_BITS ); -struct file *f =NULL ; -int ret, fd =FAN_NOFD ; -int info_type =0 ; - -pr_debug ("%s: group=%p event=%p\n" , __func__, group, event); - - metadata.event_len =FAN_EVENT_METADATA_LEN + -fanotify_event_info_len (fid_mode, event); - metadata.metadata_len =FAN_EVENT_METADATA_LEN ; - metadata.vers =FANOTIFY_METADATA_VERSION ; - metadata.reserved =0 ; - metadata.mask = event->mask &FANOTIFY_OUTGOING_EVENTS ; - metadata.pid =pid_vnr (event->pid); -/* -* For an unprivileged listener, event->pid can be used to identify the -* events generated by the listener process itself, without disclosing -* the pids of other processes. -*/ -if (FAN_GROUP_FLAG (group,FANOTIFY_UNPRIV ) && -task_tgid (current) != event->pid) - metadata.pid =0 ; - -/* -* For now, fid mode is required for an unprivileged listener and -* fid mode does not report fd in events. Keep this check anyway -* for safety in case fid mode requirement is relaxed in the future -* to allow unprivileged listener to get events with no fd and no fid. -*/ -if (!FAN_GROUP_FLAG (group,FANOTIFY_UNPRIV ) && - path && path->mnt && path->dentry) { - fd =create_fd (group, path, &f); -if (fd <0 ) -return fd; - } - metadata.fd = fd; +int ret, total_bytes =0 , info_type =0 ; +unsigned int fid_mode = info_mode &FANOTIFY_FID_BITS ; - ret = -EFAULT ;/* -* Sanity check copy size in case get_one_event() and -* event_len sizes ever get out of sync. +* Event info records order is as follows: dir fid + name, child fid. */ -if (WARN_ON_ONCE (metadata.event_len > count)) - goto out_close_fd; - -if (copy_to_user (buf, &metadata,FAN_EVENT_METADATA_LEN )) - goto out_close_fd; - - buf +=FAN_EVENT_METADATA_LEN ; - count -=FAN_EVENT_METADATA_LEN ; - -if (fanotify_is_perm_event (event->mask)) -FANOTIFY_PERM (event)->fd = fd; - -/* Event info records order is: dir fid + name, child fid */ if (fanotify_event_dir_fh_len (event)) { info_type = info->name_len ?FAN_EVENT_INFO_TYPE_DFID_NAME :FAN_EVENT_INFO_TYPE_DFID ;
@@ -472,10 +421,11 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,fanotify_info_name (info), info->name_len, buf, count);if (ret <0 ) - goto out_close_fd; +return ret; buf += ret; count -= ret; + total_bytes += ret; }if (fanotify_event_object_fh_len (event)) {
@@ -492,8 +442,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, (event->mask & FAN_ONDIR)) {/* * With group flag FAN_REPORT_NAME, if name was not -* recorded in an event on a directory, report the -* name "." with info type DFID_NAME. +* recorded in an event on a directory, report the name +* "." with info type DFID_NAME. */ info_type =FAN_EVENT_INFO_TYPE_DFID_NAME ; dot ="." ;
@@ -521,10 +471,81 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, info_type, dot, dot_len, buf, count);if (ret <0 ) - goto out_close_fd; +return ret; buf += ret; count -= ret; + total_bytes += ret; + } + +return total_bytes; +} + +static ssize_t copy_event_to_user (struct fsnotify_group *group, +struct fanotify_event *event, +char __user *buf,size_t count) +{ +struct fanotify_event_metadata metadata; +struct path *path =fanotify_event_path (event); +struct fanotify_info *info =fanotify_event_info (event); +unsigned int info_mode =FAN_GROUP_FLAG (group,FANOTIFY_INFO_MODES ); +struct file *f =NULL ; +int ret, fd =FAN_NOFD ; + +pr_debug ("%s: group=%p event=%p\n" , __func__, group, event); + + metadata.event_len =FAN_EVENT_METADATA_LEN + +fanotify_event_info_len (info_mode, event); + metadata.metadata_len =FAN_EVENT_METADATA_LEN ; + metadata.vers =FANOTIFY_METADATA_VERSION ; + metadata.reserved =0 ; + metadata.mask = event->mask &FANOTIFY_OUTGOING_EVENTS ; + metadata.pid =pid_vnr (event->pid); +/* +* For an unprivileged listener, event->pid can be used to identify the +* events generated by the listener process itself, without disclosing +* the pids of other processes. +*/ +if (FAN_GROUP_FLAG (group,FANOTIFY_UNPRIV ) && +task_tgid (current) != event->pid) + metadata.pid =0 ; + +/* +* For now, fid mode is required for an unprivileged listener and +* fid mode does not report fd in events. Keep this check anyway +* for safety in case fid mode requirement is relaxed in the future +* to allow unprivileged listener to get events with no fd and no fid. +*/ +if (!FAN_GROUP_FLAG (group,FANOTIFY_UNPRIV ) && + path && path->mnt && path->dentry) { + fd =create_fd (group, path, &f); +if (fd <0 ) +return fd; + } + metadata.fd = fd; + + ret = -EFAULT ; +/* +* Sanity check copy size in case get_one_event() and +* event_len sizes ever get out of sync. +*/ +if (WARN_ON_ONCE (metadata.event_len > count)) + goto out_close_fd; + +if (copy_to_user (buf, &metadata,FAN_EVENT_METADATA_LEN )) + goto out_close_fd; + + buf +=FAN_EVENT_METADATA_LEN ; + count -=FAN_EVENT_METADATA_LEN ; + +if (fanotify_is_perm_event (event->mask)) +FANOTIFY_PERM (event)->fd = fd; + +if (info_mode) { + ret =copy_info_records_to_user (event, info, info_mode, + buf, count); +if (ret <0 ) + goto out_close_fd; }if (f)
include/linux/fanotify.h +2 -0
@@ -27,6 +27,8 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_FID_BITS (FAN_REPORT_FID | FAN_REPORT_DFID_NAME) +#define FANOTIFY_INFO_MODES (FANOTIFY_FID_BITS) +/* * fanotify_init() flags that require CAP_SYS_ADMIN. * We do not allow unprivileged groups to request permission events.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 335/770 fanotify: add pidfd support to the fanotify API
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Bobrowski <[email protected]>
[ Upstream commit af579beb666aefb17e9a335c12c788c92932baf1 ]
Introduce a new flag FAN_REPORT_PIDFD for fanotify_init(2) which allows userspace applications to control whether a pidfd information record containing a pidfd is to be returned alongside the generic event metadata for each event.
If FAN_REPORT_PIDFD is enabled for a notification group, an additional struct fanotify_event_info_pidfd object type will be supplied alongside the generic struct fanotify_event_metadata for a single event. This functionality is analogous to that of FAN_REPORT_FID in terms of how the event structure is supplied to a userspace application. Usage of FAN_REPORT_PIDFD with FAN_REPORT_FID/FAN_REPORT_DFID_NAME is permitted, and in this case a struct fanotify_event_info_pidfd object will likely follow any struct fanotify_event_info_fid object.
Currently, the usage of the FAN_REPORT_TID flag is not permitted along with FAN_REPORT_PIDFD as the pidfd API currently only supports the creation of pidfds for thread-group leaders. Additionally, usage of the FAN_REPORT_PIDFD flag is limited to privileged processes only i.e. event listeners that are running with the CAP_SYS_ADMIN capability. Attempting to supply the FAN_REPORT_TID initialization flags with FAN_REPORT_PIDFD or creating a notification group without CAP_SYS_ADMIN will result with -EINVAL being returned to the caller.
In the event of a pidfd creation error, there are two types of error values that can be reported back to the listener. There is FAN_NOPIDFD, which will be reported in cases where the process responsible for generating the event has terminated prior to the event listener being able to read the event. Then there is FAN_EPIDFD, which will be reported when a more generic pidfd creation error has occurred when fanotify calls pidfd_create().
--- fs/notify/fanotify/fanotify_user.c | 85 ++++++++++++++++++++++++++++-- include/linux/fanotify.h | 3 +- include/uapi/linux/fanotify.h | 13 +++++ 3 files changed, 96 insertions(+), 5 deletions(-)
fs/notify/fanotify/fanotify_user.c +81 -4
@@ -1,6 +1,7 @@// SPDX-License-Identifier: GPL-2.0 #include <linux/fanotify.h> #include <linux/fcntl.h> +#include <linux/fdtable.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/anon_inodes.h>
@@ -106,6 +107,8 @@ struct kmem_cache *fanotify_perm_event_cachep __read_mostly;#define FANOTIFY_EVENT_ALIGN 4#define FANOTIFY_FID_INFO_HDR_LEN \ (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle)) +#define FANOTIFY_PIDFD_INFO_HDR_LEN \ + sizeof(struct fanotify_event_info_pidfd)static int fanotify_fid_info_len (int fh_len,int name_len) {
@@ -138,6 +141,9 @@ static int fanotify_event_info_len(unsigned int info_mode, dot_len =1 ; } +if (info_mode &FAN_REPORT_PIDFD ) + info_len +=FANOTIFY_PIDFD_INFO_HDR_LEN ; +if (fh_len) info_len +=fanotify_fid_info_len (fh_len, dot_len);
@@ -401,13 +407,34 @@ static int copy_fid_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh,return info_len; } +static int copy_pidfd_info_to_user (int pidfd, +char __user *buf, +size_t count) +{ +struct fanotify_event_info_pidfd info = { }; +size_t info_len =FANOTIFY_PIDFD_INFO_HDR_LEN ; + +if (WARN_ON_ONCE (info_len > count)) +return -EFAULT ; + + info.hdr.info_type =FAN_EVENT_INFO_TYPE_PIDFD ; + info.hdr.len = info_len; + info.pidfd = pidfd; + +if (copy_to_user (buf, &info, info_len)) +return -EFAULT ; + +return info_len; +} +static int copy_info_records_to_user (struct fanotify_event *event,struct fanotify_info *info, -unsigned int info_mode, +unsigned int info_mode,int pidfd,char __user *buf,size_t count) {int ret, total_bytes =0 , info_type =0 ;unsigned int fid_mode = info_mode &FANOTIFY_FID_BITS ; +unsigned int pidfd_mode = info_mode &FAN_REPORT_PIDFD ;/* * Event info records order is as follows: dir fid + name, child fid.
@@ -478,6 +505,16 @@ static int copy_info_records_to_user(struct fanotify_event *event, total_bytes += ret; } +if (pidfd_mode) { + ret =copy_pidfd_info_to_user (pidfd, buf, count); +if (ret <0 ) +return ret; + + buf += ret; + count -= ret; + total_bytes += ret; + } +return total_bytes; }
@@ -489,8 +526,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,struct path *path =fanotify_event_path (event);struct fanotify_info *info =fanotify_event_info (event);unsigned int info_mode =FAN_GROUP_FLAG (group,FANOTIFY_INFO_MODES ); +unsigned int pidfd_mode = info_mode &FAN_REPORT_PIDFD ;struct file *f =NULL ; -int ret, fd =FAN_NOFD ; +int ret, pidfd =FAN_NOPIDFD , fd =FAN_NOFD ;pr_debug ("%s: group=%p event=%p\n" , __func__, group, event);
@@ -524,6 +562,33 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, } metadata.fd = fd; +if (pidfd_mode) { +/* +* Complain if the FAN_REPORT_PIDFD and FAN_REPORT_TID mutual +* exclusion is ever lifted. At the time of incoporating pidfd +* support within fanotify, the pidfd API only supported the +* creation of pidfds for thread-group leaders. +*/ +WARN_ON_ONCE (FAN_GROUP_FLAG (group,FAN_REPORT_TID )); + +/* +* The PIDTYPE_TGID check for an event->pid is performed +* preemptively in an attempt to catch out cases where the event +* listener reads events after the event generating process has +* already terminated. Report FAN_NOPIDFD to the event listener +* in those cases, with all other pidfd creation errors being +* reported as FAN_EPIDFD. +*/ +if (metadata.pid ==0 || + !pid_has_task (event->pid,PIDTYPE_TGID )) { + pidfd =FAN_NOPIDFD ; + }else { + pidfd =pidfd_create (event->pid,0 ); +if (pidfd <0 ) + pidfd =FAN_EPIDFD ; + } + } + ret = -EFAULT ;/* * Sanity check copy size in case get_one_event() and
@@ -542,7 +607,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,FANOTIFY_PERM (event)->fd = fd;if (info_mode) { - ret =copy_info_records_to_user (event, info, info_mode, + ret =copy_info_records_to_user (event, info, info_mode, pidfd, buf, count);if (ret <0 ) goto out_close_fd;
@@ -558,6 +623,10 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,put_unused_fd (fd);fput (f); } + +if (pidfd >=0 ) +close_fd (pidfd); +return ret; }
@@ -1103,6 +1172,14 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)#endif return -EINVAL ; +/* +* A pidfd can only be returned for a thread-group leader; thus +* FAN_REPORT_PIDFD and FAN_REPORT_TID need to remain mutually +* exclusive. +*/ +if ((flags &FAN_REPORT_PIDFD ) && (flags &FAN_REPORT_TID )) +return -EINVAL ; +if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS )return -EINVAL ;
@@ -1522,7 +1599,7 @@ static int __init fanotify_user_setup(void) FANOTIFY_DEFAULT_MAX_USER_MARKS);BUILD_BUG_ON (FANOTIFY_INIT_FLAGS &FANOTIFY_INTERNAL_GROUP_FLAGS ); -BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) !=10 ); +BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) !=11 );BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_MARK_FLAGS ) !=9 ); fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
include/linux/fanotify.h +2 -1
@@ -27,7 +27,7 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_FID_BITS (FAN_REPORT_FID | FAN_REPORT_DFID_NAME) -#define FANOTIFY_INFO_MODES (FANOTIFY_FID_BITS) +#define FANOTIFY_INFO_MODES (FANOTIFY_FID_BITS | FAN_REPORT_PIDFD)/* * fanotify_init() flags that require CAP_SYS_ADMIN.
@@ -37,6 +37,7 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */*/ #define FANOTIFY_ADMIN_INIT_FLAGS (FANOTIFY_PERM_CLASSES | \ FAN_REPORT_TID | \ + FAN_REPORT_PIDFD | \ FAN_UNLIMITED_QUEUE | \ FAN_UNLIMITED_MARKS)
include/uapi/linux/fanotify.h +13 -0
@@ -51,6 +51,7 @@#define FAN_ENABLE_AUDIT 0x00000040/* Flags to determine fanotify event format */ +#define FAN_REPORT_PIDFD 0x00000080/* Report pidfd for event->pid */ #define FAN_REPORT_TID 0x00000100/* event->pid is thread id */ #define FAN_REPORT_FID 0x00000200/* Report unique file id */ #define FAN_REPORT_DIR_FID 0x00000400/* Report unique directory id */
@@ -123,6 +124,7 @@ struct fanotify_event_metadata {#define FAN_EVENT_INFO_TYPE_FID 1#define FAN_EVENT_INFO_TYPE_DFID_NAME 2#define FAN_EVENT_INFO_TYPE_DFID 3 +#define FAN_EVENT_INFO_TYPE_PIDFD 4/* Variable length info record following event metadata */ struct fanotify_event_info_header {
@@ -148,6 +150,15 @@ struct fanotify_event_info_fid {unsigned char handle[0 ]; }; +/* +* This structure is used for info records of type FAN_EVENT_INFO_TYPE_PIDFD. +* It holds a pidfd for the pid that was responsible for generating an event. +*/ +struct fanotify_event_info_pidfd { +struct fanotify_event_info_header hdr; +__s32 pidfd; +}; +struct fanotify_response {__s32 fd;__u32 response;
@@ -160,6 +171,8 @@ struct fanotify_response {/* No fd set in event */ #define FAN_NOFD -1 +#define FAN_NOPIDFD FAN_NOFD +#define FAN_EPIDFD -2/* Helper functions to deal with fanotify_event_metadata buffers */ #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 336/770 fsnotify: replace igrab() with ihold() on attach connector
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 09ddbe69c9925b42cb9529f60678c25b241d8b18 ]
We must have a reference on inode, so ihold is cheaper.
--- fs/notify/mark.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
fs/notify/mark.c +5 -2
@@ -493,8 +493,11 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, conn->fsid.val[0 ] = conn->fsid.val[1 ] =0 ; conn->flags =0 ; } -if (conn->type ==FSNOTIFY_OBJ_TYPE_INODE ) - inode =igrab (fsnotify_conn_inode (conn)); +if (conn->type ==FSNOTIFY_OBJ_TYPE_INODE ) { + inode =fsnotify_conn_inode (conn); +ihold (inode); + } +/* * cmpxchg() provides the barrier so that readers of *connp can see * only initialized structure
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 337/770 fsnotify: count s_fsnotify_inode_refs for attached connectors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 11fa333b58ba1518e7c69fafb6513a0117f8fe33 ]
Instead of incrementing s_fsnotify_inode_refs when detaching connector from inode, increment it earlier when attaching connector to inode. Next patch is going to use s_fsnotify_inode_refs to count all objects with attached connectors.
--- fs/notify/mark.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
fs/notify/mark.c +18 -11
@@ -169,6 +169,21 @@ static void fsnotify_connector_destroy_workfn(struct work_struct *work) } } +static void fsnotify_get_inode_ref (struct inode *inode) +{ +ihold (inode); +atomic_long_inc (&inode->i_sb->s_fsnotify_inode_refs); +} + +static void fsnotify_put_inode_ref (struct inode *inode) +{ +struct super_block *sb = inode->i_sb; + +iput (inode); +if (atomic_long_dec_and_test (&sb->s_fsnotify_inode_refs)) +wake_up_var (&sb->s_fsnotify_inode_refs); +} +static void *fsnotify_detach_connector_from_object (struct fsnotify_mark_connector *conn,unsigned int *type)
@@ -182,7 +197,6 @@ static void *fsnotify_detach_connector_from_object(if (conn->type ==FSNOTIFY_OBJ_TYPE_INODE ) { inode =fsnotify_conn_inode (conn); inode->i_fsnotify_mask =0 ; -atomic_long_inc (&inode->i_sb->s_fsnotify_inode_refs); }else if (conn->type ==FSNOTIFY_OBJ_TYPE_VFSMOUNT ) {fsnotify_conn_mount (conn)->mnt_fsnotify_mask =0 ; }else if (conn->type ==FSNOTIFY_OBJ_TYPE_SB ) {
@@ -209,19 +223,12 @@ static void fsnotify_final_mark_destroy(struct fsnotify_mark *mark)/* Drop object reference originally held by a connector */ static void fsnotify_drop_object (unsigned int type,void *objp) { -struct inode *inode; -struct super_block *sb; -if (!objp)return ;/* Currently only inode references are passed to be dropped */ if (WARN_ON_ONCE (type !=FSNOTIFY_OBJ_TYPE_INODE ))return ; - inode = objp; - sb = inode->i_sb; -iput (inode); -if (atomic_long_dec_and_test (&sb->s_fsnotify_inode_refs)) -wake_up_var (&sb->s_fsnotify_inode_refs); +fsnotify_put_inode_ref (objp); }void fsnotify_put_mark (struct fsnotify_mark *mark)
@@ -495,7 +502,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, }if (conn->type ==FSNOTIFY_OBJ_TYPE_INODE ) { inode =fsnotify_conn_inode (conn); -ihold (inode); +fsnotify_get_inode_ref (inode); }/*
@@ -505,7 +512,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,if (cmpxchg (connp,NULL , conn)) {/* Someone else created list structure for us */ if (inode) -iput (inode); +fsnotify_put_inode_ref (inode);kmem_cache_free (fsnotify_mark_connector_cachep, conn); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 338/770 fsnotify: count all objects with attached connectors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit ec44610fe2b86daef70f3f53f47d2a2542d7094f ]
Rename s_fsnotify_inode_refs to s_fsnotify_connectors and count all objects with attached connectors, not only inodes with attached connectors.
This will be used to optimize fsnotify() calls on sb without any type of marks.
--- fs/notify/fsnotify.c | 6 +++--- fs/notify/fsnotify.h | 15 +++++++++++++++ fs/notify/mark.c | 24 +++++++++++++++++++++--- include/linux/fs.h | 7 +++++-- 4 files changed, 44 insertions(+), 8 deletions(-)
fs/notify/fsnotify.c +3 -3
@@ -87,15 +87,15 @@ static void fsnotify_unmount_inodes(struct super_block *sb)if (iput_inode)iput (iput_inode); -/* Wait for outstanding inode references from connectors */ -wait_var_event (&sb->s_fsnotify_inode_refs, - !atomic_long_read (&sb->s_fsnotify_inode_refs)); }void fsnotify_sb_delete (struct super_block *sb) {fsnotify_unmount_inodes (sb);fsnotify_clear_marks_by_sb (sb); +/* Wait for outstanding object references from connectors */ +wait_var_event (&sb->s_fsnotify_connectors, + !atomic_long_read (&sb->s_fsnotify_connectors)); }/*
fs/notify/fsnotify.h +15 -0
@@ -27,6 +27,21 @@ static inline struct super_block *fsnotify_conn_sb( return container_of(conn->obj, struct super_block, s_fsnotify_marks); } +static inline struct super_block *fsnotify_connector_sb ( +struct fsnotify_mark_connector *conn) +{ +switch (conn->type) { +case FSNOTIFY_OBJ_TYPE_INODE : +return fsnotify_conn_inode (conn)->i_sb; +case FSNOTIFY_OBJ_TYPE_VFSMOUNT : +return fsnotify_conn_mount (conn)->mnt.mnt_sb; +case FSNOTIFY_OBJ_TYPE_SB : +return fsnotify_conn_sb (conn); +default : +return NULL ; + } +} +/* destroy all events sitting in this groups notification queue */ extern void fsnotify_flush_notify (struct fsnotify_group *group);
fs/notify/mark.c +21 -3
@@ -172,7 +172,7 @@ static void fsnotify_connector_destroy_workfn(struct work_struct *work)static void fsnotify_get_inode_ref (struct inode *inode) {ihold (inode); -atomic_long_inc (&inode->i_sb->s_fsnotify_inode_refs); +atomic_long_inc (&inode->i_sb->s_fsnotify_connectors); }static void fsnotify_put_inode_ref (struct inode *inode)
@@ -180,8 +180,24 @@ static void fsnotify_put_inode_ref(struct inode *inode)struct super_block *sb = inode->i_sb;iput (inode); -if (atomic_long_dec_and_test (&sb->s_fsnotify_inode_refs)) -wake_up_var (&sb->s_fsnotify_inode_refs); +if (atomic_long_dec_and_test (&sb->s_fsnotify_connectors)) +wake_up_var (&sb->s_fsnotify_connectors); +} + +static void fsnotify_get_sb_connectors (struct fsnotify_mark_connector *conn) +{ +struct super_block *sb =fsnotify_connector_sb (conn); + +if (sb) +atomic_long_inc (&sb->s_fsnotify_connectors); +} + +static void fsnotify_put_sb_connectors (struct fsnotify_mark_connector *conn) +{ +struct super_block *sb =fsnotify_connector_sb (conn); + +if (sb &&atomic_long_dec_and_test (&sb->s_fsnotify_connectors)) +wake_up_var (&sb->s_fsnotify_connectors); } static void *fsnotify_detach_connector_from_object(
@@ -203,6 +219,7 @@ static void *fsnotify_detach_connector_from_object(fsnotify_conn_sb (conn)->s_fsnotify_mask =0 ; } +fsnotify_put_sb_connectors (conn);rcu_assign_pointer (*(conn->obj),NULL ); conn->obj =NULL ; conn->type =FSNOTIFY_OBJ_TYPE_DETACHED ;
@@ -504,6 +521,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, inode =fsnotify_conn_inode (conn);fsnotify_get_inode_ref (inode); } +fsnotify_get_sb_connectors (conn);/* * cmpxchg() provides the barrier so that readers of *connp can see
include/linux/fs.h +5 -2
@@ -1512,8 +1512,11 @@ struct super_block {/* Number of inodes with nlink == 0 but still referenced */ atomic_long_t s_remove_count; -/* Pending fsnotify inode refs */ -atomic_long_t s_fsnotify_inode_refs; +/* +* Number of inode/mount/sb objects that are being watched, note that +* inodes objects are currently double-accounted. +*/ +atomic_long_t s_fsnotify_connectors;/* Being remounted read-only */ int s_readonly_remount;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 339/770 fsnotify: optimize the case of no marks of any type
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit e43de7f0862b8598cd1ef440e3b4701cd107ea40 ]
Add a simple check in the inline helpers to avoid calling fsnotify() and __fsnotify_parent() in case there are no marks of any type (inode/sb/mount) for an inode's sb, so there can be no objects of any type interested in the event.
--- include/linux/fsnotify.h | 9 +++++++++ 1 file changed, 9 insertions(+)
include/linux/fsnotify.h +9 -0
@@ -30,6 +30,9 @@ static inline void fsnotify_name(struct inode *dir, __u32 mask,struct inode *child, const struct qstr *name, u32 cookie) { + if (atomic_long_read(&dir->i_sb->s_fsnotify_connectors) == 0) + return; +fsnotify (mask ,child ,FSNOTIFY_EVENT_INODE ,dir ,name ,NULL ,cookie ); }
@@ -41,6 +44,9 @@ static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry,static inline void fsnotify_inode (struct inode *inode,__u32 mask) { +if (atomic_long_read (&inode->i_sb->s_fsnotify_connectors) ==0 ) +return ; +if (S_ISDIR (inode->i_mode)) mask |=FS_ISDIR ;
@@ -53,6 +59,9 @@ static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, {struct inode *inode =d_inode (dentry); +if (atomic_long_read (&inode->i_sb->s_fsnotify_connectors) ==0 ) +return 0 ; +if (S_ISDIR (inode->i_mode)) { mask |=FS_ISDIR ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 340/770 NFSD: Clean up splice actor
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c7e0b781b73c2e26e442ed71397cc2bc5945a732 ]
A few useful observations:
- The value in @size is never modified.
- splice_desc.len is an unsigned int, and so is xdr_buf.page_len. An implicit cast to size_t is unnecessary.
- The computation of .page_len is the same in all three arms of the "if" statement, so hoist it out to make it clear that the operation is an unconditional invariant.
The resulting function is 18 bytes shorter on my system (-Os).
--- fs/nfsd/vfs.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
fs/nfsd/vfs.c +3 -8
@@ -854,26 +854,21 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,struct svc_rqst *rqstp = sd->u.data;struct page **pp = rqstp->rq_next_page;struct page *page = buf->page; -size_t size; - - size = sd->len;if (rqstp->rq_res.page_len ==0 ) {get_page (page);put_page (*rqstp->rq_next_page); *(rqstp->rq_next_page++) = page; rqstp->rq_res.page_base = buf->offset; - rqstp->rq_res.page_len = size; }else if (page != pp[-1 ]) {get_page (page);if (*rqstp->rq_next_page)put_page (*rqstp->rq_next_page); *(rqstp->rq_next_page++) = page; - rqstp->rq_res.page_len += size; - }else - rqstp->rq_res.page_len += size; + } + rqstp->rq_res.page_len += sd->len; -return size; +return sd->len; } static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 341/770 SUNRPC: Add svc_rqst_replace_page() API
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 2f0f88f42f2eab0421ed37d7494de9124fdf0d34 ]
Replacing a page in rq_pages[] requires a get_page(), which is a bus-locked operation, and a put_page(), which can be even more costly.
To reduce the cost of replacing a page in rq_pages[], batch the put_page() operations by collecting "freed" pages in a pagevec, and then release those pages when the pagevec is full. This pagevec is also emptied when each RPC completes.
--- include/linux/sunrpc/svc.h | 4 ++++ net/sunrpc/svc.c | 21 +++++++++++++++++++++ net/sunrpc/svc_xprt.c | 3 +++ 3 files changed, 28 insertions(+)
include/linux/sunrpc/svc.h +4 -0
@@ -19,6 +19,7 @@#include <linux/sunrpc/svcauth.h> #include <linux/wait.h> #include <linux/mm.h> +#include <linux/pagevec.h> /* statistics for svc_pool structures */ struct svc_pool_stats {
@@ -256,6 +257,7 @@ struct svc_rqst {struct page * *rq_next_page;/* next reply page to use */ struct page * *rq_page_end;/* one past the last page */ +struct pagevec rq_pvec;struct kvec rq_vec[RPCSVC_MAXPAGES ];/* generally useful.. */ struct bio_vec rq_bvec[RPCSVC_MAXPAGES ];
@@ -502,6 +504,8 @@ struct svc_rqst *svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node);struct svc_rqst *svc_prepare_thread (struct svc_serv *serv,struct svc_pool *pool,int node); +void svc_rqst_replace_page (struct svc_rqst *rqstp, +struct page *page);void svc_rqst_free (struct svc_rqst *);void svc_exit_thread (struct svc_rqst *);unsigned int svc_pool_map_get (void );
net/sunrpc/svc.c +21 -0
@@ -842,6 +842,27 @@ svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrser }EXPORT_SYMBOL_GPL (svc_set_num_threads_sync); +/** +* svc_rqst_replace_page - Replace one page in rq_pages[] +* @rqstp: svc_rqst with pages to replace +* @page: replacement page +* +* When replacing a page in rq_pages, batch the release of the +* replaced pages to avoid hammering the page allocator. +*/ +void svc_rqst_replace_page (struct svc_rqst *rqstp,struct page *page) +{ +if (*rqstp->rq_next_page) { +if (!pagevec_space (&rqstp->rq_pvec)) +__pagevec_release (&rqstp->rq_pvec); +pagevec_add (&rqstp->rq_pvec, *rqstp->rq_next_page); + } + +get_page (page); + *(rqstp->rq_next_page++) = page; +} +EXPORT_SYMBOL_GPL (svc_rqst_replace_page); +/* * Called from a server thread as it's exiting. Caller must hold the "service * mutex" for the service.
net/sunrpc/svc_xprt.c +3 -0
@@ -525,6 +525,7 @@ static void svc_xprt_release(struct svc_rqst *rqstp)kfree (rqstp->rq_deferred); rqstp->rq_deferred =NULL ; +pagevec_release (&rqstp->rq_pvec);svc_free_res_pages (rqstp); rqstp->rq_res.page_len =0 ; rqstp->rq_res.page_base =0 ;
@@ -651,6 +652,8 @@ static int svc_alloc_arg(struct svc_rqst *rqstp)int pages;int i; +pagevec_init (&rqstp->rq_pvec); +/* now allocate needed pages. If we get a failure, sleep briefly */ pages = (serv->sv_max_mesg +2 *PAGE_SIZE ) >>PAGE_SHIFT ;if (pages >RPCSVC_MAXPAGES ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 342/770 NFSD: Batch release pages during splice read
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 496d83cf0f2fa70cfe256c2499e2d3523d3868f3 ]
Large splice reads call put_page() repeatedly. put_page() is relatively expensive to call, so replace it with the new svc_rqst_replace_page() helper to help amortize that cost.
--- fs/nfsd/vfs.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
fs/nfsd/vfs.c +2 -7
@@ -856,15 +856,10 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,struct page *page = buf->page;if (rqstp->rq_res.page_len ==0 ) { -get_page (page); -put_page (*rqstp->rq_next_page); - *(rqstp->rq_next_page++) = page; +svc_rqst_replace_page (rqstp, page); rqstp->rq_res.page_base = buf->offset; }else if (page != pp[-1 ]) { -get_page (page); -if (*rqstp->rq_next_page) -put_page (*rqstp->rq_next_page); - *(rqstp->rq_next_page++) = page; +svc_rqst_replace_page (rqstp, page); } rqstp->rq_res.page_len += sd->len;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 343/770 NFSD: remove vanity comments
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit ea49dc79002c416a9003f3204bc14f846a0dbcae ]
Including one's name in copyright claims is appropriate. Including it in random comments is just vanity. After 2 decades, it is time for these to be gone.
--- fs/nfsd/vfs.c | 1 - include/uapi/linux/nfsd/nfsfh.h | 1 - 2 files changed, 2 deletions(-)
fs/nfsd/vfs.c +0 -1
@@ -244,7 +244,6 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,* returned. Otherwise the covered directory is returned. * NOTE: this mountpoint crossing is not supported properly by all * clients and is explicitly disallowed for NFSv3 -* NeilBrown <[email protected]> */ __be32 nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
include/uapi/linux/nfsd/nfsfh.h +0 -1
@@ -33,7 +33,6 @@ struct nfs_fhbase_old {/* * This is the new flexible, extensible style NFSv2/v3/v4 file handle. -* by Neil Brown <[email protected]> - March 2000 * * The file handle starts with a sequence of four-byte words. * The first word contains a version number (1) and three descriptor bytes
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 344/770 sysctl: introduce new proc handler proc_dobool
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jia He <[email protected]>
[ Upstream commit a2071573d6346819cc4e5787b4206f2184985160 ]
This is to let bool variable could be correctly displayed in big/little endian sysctl procfs. sizeof(bool) is arch dependent, proc_dobool should work in all arches.
--- include/linux/sysctl.h | 2 ++ kernel/sysctl.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)
include/linux/sysctl.h +2 -0
@@ -55,6 +55,8 @@ typedef int proc_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos);int proc_dostring (struct ctl_table *,int ,void *,size_t *,loff_t *); +int proc_dobool (struct ctl_table *table,int write,void *buffer, +size_t *lenp,loff_t *ppos);int proc_dointvec (struct ctl_table *,int ,void *,size_t *,loff_t *);int proc_douintvec (struct ctl_table *,int ,void *,size_t *,loff_t *);int proc_dointvec_minmax (struct ctl_table *,int ,void *,size_t *,loff_t *);
kernel/sysctl.c +42 -0
66 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 345/770 lockd: change the proc_handler for nsm_use_hostnames
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jia He <[email protected]>
[ Upstream commit d02a3a2cb25d384005a6e3446a445013342024b7 ]
nsm_use_hostnames is a module parameter and it will be exported to sysctl procfs. This is to let user sometimes change it from userspace. But the minimal unit for sysctl procfs read/write it sizeof(int).
In big endian system, the converting from/to bool to/from int will cause error for proc items.
This patch use a new proc_handler proc_dobool to fix it.
--- fs/lockd/svc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/lockd/svc.c +1 -1
@@ -584,7 +584,7 @@ static struct ctl_table nlm_sysctls[] = { .data = &nsm_use_hostnames, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dobool, }, { .procname = "nsm_local_state",
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 346/770 nlm: minor nlm_lookup_file argument change
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit 2dc6f19e4f438d4c14987cb17aee38aaf7304e7f ]
It'll come in handy to get the whole nlm_lock.
--- fs/lockd/svc4proc.c | 3 ++- fs/lockd/svcproc.c | 2 +- fs/lockd/svcsubs.c | 15 ++++++++------- include/linux/lockd/lockd.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-)
fs/lockd/svc4proc.c +2 -1
@@ -40,7 +40,8 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,/* Obtain file pointer. Not used by FREE_ALL call. */ if (filp !=NULL ) { -if ((error =nlm_lookup_file (rqstp, &file, &lock->fh)) !=0 ) + error =nlm_lookup_file (rqstp, &file, lock); +if (error) goto no_locks; *filp = file;
fs/lockd/svcproc.c +1 -1
@@ -69,7 +69,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,/* Obtain file pointer. Not used by FREE_ALL call. */ if (filp !=NULL ) { - error =cast_status (nlm_lookup_file (rqstp, &file, &lock->fh)); + error =cast_status (nlm_lookup_file (rqstp, &file, lock));if (error !=0 ) goto no_locks; *filp = file;
fs/lockd/svcsubs.c +8 -7
@@ -82,31 +82,31 @@ static inline unsigned int file_hash(struct nfs_fh *f)*/ __be32 nlm_lookup_file (struct svc_rqst *rqstp,struct nlm_file **result, -struct nfs_fh *f) +struct nlm_lock *lock) {struct nlm_file *file;unsigned int hash;__be32 nfserr; -nlm_debug_print_fh ("nlm_lookup_file" , f); +nlm_debug_print_fh ("nlm_lookup_file" , &lock->fh); - hash =file_hash (f); + hash =file_hash (&lock->fh);/* Lock file table */ mutex_lock (&nlm_file_mutex);hlist_for_each_entry (file, &nlm_files[hash], f_list) -if (!nfs_compare_fh (&file->f_handle, f)) +if (!nfs_compare_fh (&file->f_handle, &lock->fh)) goto found; -nlm_debug_print_fh ("creating file for" , f); +nlm_debug_print_fh ("creating file for" , &lock->fh); nfserr = nlm_lck_denied_nolocks; file =kzalloc (sizeof (*file),GFP_KERNEL );if (!file) goto out_unlock; -memcpy (&file->f_handle, f,sizeof (struct nfs_fh )); +memcpy (&file->f_handle, &lock->fh,sizeof (struct nfs_fh ));mutex_init (&file->f_mutex);INIT_HLIST_NODE (&file->f_list);INIT_LIST_HEAD (&file->f_blocks);
@@ -117,7 +117,8 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,* We have to make sure we have the right credential to open * the file. */ -if ((nfserr = nlmsvc_ops->fopen (rqstp, f, &file->f_file)) !=0 ) { + nfserr = nlmsvc_ops->fopen (rqstp, &lock->fh, &file->f_file); +if (nfserr) {dprintk ("lockd: open failed (error %d)\n" , nfserr); goto out_free; }
include/linux/lockd/lockd.h +1 -1
@@ -286,7 +286,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);* File handling for the server personality */ __be32 nlm_lookup_file (struct svc_rqst *,struct nlm_file **, -struct nfs_fh *); +struct nlm_lock *);void nlm_release_file (struct nlm_file *);void nlmsvc_release_lockowner (struct nlm_lock *);void nlmsvc_mark_resources (struct net *);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 347/770 nlm: minor refactoring
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit a81041b7d8f08c4e1014173c5483a0f18724a576 ]
Make this lookup slightly more concise, and prepare for changing how we look this up in a following patch.
--- fs/lockd/svclock.c | 16 ++++++++-------- fs/lockd/svcsubs.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-)
fs/lockd/svclock.c +8 -8
@@ -474,8 +474,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,__be32 ret; dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", - locks_inode(file->f_file)->i_sb->s_id, - locks_inode(file->f_file)->i_ino, + nlmsvc_file_inode(file)->i_sb->s_id, + nlmsvc_file_inode(file)->i_ino, lock->fl.fl_type, lock->fl.fl_pid, (long long)lock->fl.fl_start, (long long)lock->fl.fl_end,
@@ -581,8 +581,8 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,struct nlm_lockowner *test_owner;dprintk ("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n" , -locks_inode (file->f_file)->i_sb->s_id, -locks_inode (file->f_file)->i_ino, +nlmsvc_file_inode (file)->i_sb->s_id, +nlmsvc_file_inode (file)->i_ino, lock->fl.fl_type, (long long )lock->fl.fl_start, (long long )lock->fl.fl_end);
@@ -644,8 +644,8 @@ nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)int error;dprintk ("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n" , -locks_inode (file->f_file)->i_sb->s_id, -locks_inode (file->f_file)->i_ino, +nlmsvc_file_inode (file)->i_sb->s_id, +nlmsvc_file_inode (file)->i_ino, lock->fl.fl_pid, (long long )lock->fl.fl_start, (long long )lock->fl.fl_end);
@@ -673,8 +673,8 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *lint status =0 ;dprintk ("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n" , -locks_inode (file->f_file)->i_sb->s_id, -locks_inode (file->f_file)->i_ino, +nlmsvc_file_inode (file)->i_sb->s_id, +nlmsvc_file_inode (file)->i_ino, lock->fl.fl_pid, (long long )lock->fl.fl_start, (long long )lock->fl.fl_end);
fs/lockd/svcsubs.c +2 -2
@@ -45,7 +45,7 @@ static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)static inline void nlm_debug_print_file (char *msg,struct nlm_file *file) { -struct inode *inode =locks_inode (file->f_file); +struct inode *inode =nlmsvc_file_inode (file);dprintk ("lockd: %s %s/%ld\n" , msg, inode->i_sb->s_id, inode->i_ino);
@@ -416,7 +416,7 @@ nlmsvc_match_sb(void *datap, struct nlm_file *file) {struct super_block *sb = datap; -return sb ==locks_inode (file->f_file)->i_sb; +return sb ==nlmsvc_file_inode (file)->i_sb; }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 348/770 lockd: update nlm_lookup_file reexport comment
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit b661601a9fdf1af8516e1100de8bba84bd41cca4 ]
Update comment to reflect that we *do* allow reexport, whether it's a good idea or not....
--- fs/lockd/svcsubs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/lockd/svcsubs.c +3 -2
@@ -111,8 +111,9 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,INIT_HLIST_NODE (&file->f_list);INIT_LIST_HEAD (&file->f_blocks); -/* Open the file. Note that this must not sleep for too long, else -* we would lock up lockd:-) So no NFS re-exports, folks. +/* +* Open the file. Note that if we're reexporting, for example, +* this could block the lockd thread for a while. * * We have to make sure we have the right credential to open * the file.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 349/770 Keep read and write fds with each nlm_file
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit 7f024fcd5c97dc70bb9121c80407cf3cf9be7159 ]
We shouldn't really be using a read-only file descriptor to take a write lock.
Most filesystems will put up with it. But NFS, for example, won't.
--- fs/lockd/svc4proc.c | 4 +- fs/lockd/svclock.c | 25 ++++++--- fs/lockd/svcproc.c | 4 +- fs/lockd/svcsubs.c | 102 +++++++++++++++++++++++++----------- fs/nfsd/lockd.c | 8 ++- include/linux/lockd/bind.h | 3 +- include/linux/lockd/lockd.h | 9 +++- 7 files changed, 111 insertions(+), 44 deletions(-)
fs/lockd/svc4proc.c +3 -1
@@ -40,13 +40,15 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,/* Obtain file pointer. Not used by FREE_ALL call. */ if (filp !=NULL ) { +int mode =lock_to_openmode (&lock->fl); + error =nlm_lookup_file (rqstp, &file, lock);if (error) goto no_locks; *filp = file;/* Set up the missing parts of the file_lock structure */ - lock->fl.fl_file = file->f_file; + lock->fl.fl_file = file->f_file[mode]; lock->fl.fl_pid = current->tgid; lock->fl.fl_lmops = &nlmsvc_lock_operations;nlmsvc_locks_init_private (&lock->fl, host, (pid_t )lock->svid);
fs/lockd/svclock.c +19 -6
@@ -471,6 +471,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, {struct nlm_block *block =NULL ;int error; +int mode;__be32 ret; dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
@@ -524,7 +525,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,if (!wait) lock->fl.fl_flags &= ~FL_SLEEP ; - error =vfs_lock_file (file->f_file,F_SETLK , &lock->fl,NULL ); + mode =lock_to_openmode (&lock->fl); + error =vfs_lock_file (file->f_file[mode],F_SETLK , &lock->fl,NULL ); lock->fl.fl_flags &= ~FL_SLEEP ;dprintk ("lockd: vfs_lock_file returned %d\n" , error);
@@ -577,6 +579,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_lock *conflock, struct nlm_cookie *cookie) { int error; +int mode;__be32 ret;struct nlm_lockowner *test_owner;
@@ -595,7 +598,8 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,/* If there's a conflicting lock, remember to clean up the test lock */ test_owner = (struct nlm_lockowner *)lock->fl.fl_owner; - error =vfs_test_lock (file->f_file, &lock->fl); + mode =lock_to_openmode (&lock->fl); + error =vfs_test_lock (file->f_file[mode], &lock->fl);if (error) {/* We can't currently deal with deferred test requests */ if (error ==FILE_LOCK_DEFERRED )
@@ -641,7 +645,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,__be32 nlmsvc_unlock (struct net *net,struct nlm_file *file,struct nlm_lock *lock) { -int error; +int error =0 ; dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n", nlmsvc_file_inode(file)->i_sb->s_id,
@@ -654,7 +658,12 @@ nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)nlmsvc_cancel_blocked (net, file, lock); lock->fl.fl_type =F_UNLCK ; - error =vfs_lock_file (file->f_file,F_SETLK , &lock->fl,NULL ); +if (file->f_file[O_RDONLY ]) + error =vfs_lock_file (file->f_file[O_RDONLY ],F_SETLK , + &lock->fl,NULL ); +if (file->f_file[O_WRONLY ]) + error =vfs_lock_file (file->f_file[O_WRONLY ],F_SETLK , + &lock->fl,NULL );return (error <0 )? nlm_lck_denied_nolocks : nlm_granted; }
@@ -671,6 +680,7 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *l {struct nlm_block *block;int status =0 ; +int mode; dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n", nlmsvc_file_inode(file)->i_sb->s_id,
@@ -686,7 +696,8 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *l block =nlmsvc_lookup_block (file, lock);mutex_unlock (&file->f_mutex);if (block !=NULL ) { -vfs_cancel_lock (block->b_file->f_file, + mode =lock_to_openmode (&lock->fl); +vfs_cancel_lock (block->b_file->f_file[mode], &block->b_call->a_args.lock.fl); status =nlmsvc_unlink_block (block);nlmsvc_release_block (block);
@@ -803,6 +814,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) {struct nlm_file *file = block->b_file;struct nlm_lock *lock = &block->b_call->a_args.lock; +int mode;int error;loff_t fl_start, fl_end;
@@ -828,7 +840,8 @@ nlmsvc_grant_blocked(struct nlm_block *block) lock->fl.fl_flags |=FL_SLEEP ; fl_start = lock->fl.fl_start; fl_end = lock->fl.fl_end; - error =vfs_lock_file (file->f_file,F_SETLK , &lock->fl,NULL ); + mode =lock_to_openmode (&lock->fl); + error =vfs_lock_file (file->f_file[mode],F_SETLK , &lock->fl,NULL ); lock->fl.fl_flags &= ~FL_SLEEP ; lock->fl.fl_start = fl_start; lock->fl.fl_end = fl_end;
fs/lockd/svcproc.c +3 -1
@@ -55,6 +55,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,struct nlm_host *host =NULL ;struct nlm_file *file =NULL ;struct nlm_lock *lock = &argp->lock; +int mode;__be32 error =0 ;/* nfsd callbacks must have been installed for this procedure */
@@ -75,7 +76,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, *filp = file;/* Set up the missing parts of the file_lock structure */ - lock->fl.fl_file = file->f_file; + mode =lock_to_openmode (&lock->fl); + lock->fl.fl_file = file->f_file[mode]; lock->fl.fl_pid = current->tgid; lock->fl.fl_lmops = &nlmsvc_lock_operations;nlmsvc_locks_init_private (&lock->fl, host, (pid_t )lock->svid);
fs/lockd/svcsubs.c +71 -31
183 lines not on this page · raw message
fs/nfsd/lockd.c +6 -2
@@ -25,9 +25,11 @@* Note: we hold the dentry use count while the file is open. */ static __be32 -nlm_fopen (struct svc_rqst *rqstp,struct nfs_fh *f,struct file **filp) +nlm_fopen (struct svc_rqst *rqstp,struct nfs_fh *f,struct file **filp, +int mode) {__be32 nfserr; +int access;struct svc_fh fh;/* must initialize before using! but maxsize doesn't matter */
@@ -36,7 +38,9 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)memcpy ((char *)&fh.fh_handle.fh_base, f->data, f->size); fh.fh_export =NULL ; - nfserr =nfsd_open (rqstp, &fh,S_IFREG ,NFSD_MAY_LOCK , filp); + access = (mode ==O_WRONLY ) ?NFSD_MAY_WRITE :NFSD_MAY_READ ; + access |=NFSD_MAY_LOCK ; + nfserr =nfsd_open (rqstp, &fh,S_IFREG , access, filp);fh_put (&fh);/* We return nlm error codes as nlm doesn't know * about nfsd, but nfsd does know about nlm..
include/linux/lockd/bind.h +2 -1
@@ -27,7 +27,8 @@ struct rpc_task;struct nlmsvc_binding {__be32 (*fopen)(struct svc_rqst *,struct nfs_fh *, -struct file **); +struct file **, +int mode);void (*fclose)(struct file *); };
include/linux/lockd/lockd.h +7 -2
@@ -10,6 +10,8 @@#ifndef LINUX_LOCKD_LOCKD_H #define LINUX_LOCKD_LOCKD_H +/* XXX: a lot of this should really be under fs/lockd. */ +#include <linux/in.h> #include <linux/in6.h> #include <net/ipv6.h>
@@ -154,7 +156,8 @@ struct nlm_rqst {struct nlm_file {struct hlist_node f_list;/* linked list */ struct nfs_fh f_handle;/* NFS file handle */ -struct file * f_file;/* VFS file pointer */ +struct file * f_file[2 ];/* VFS file pointers, +indexed by O_ flags */ struct nlm_share * f_shares;/* DOS shares */ struct list_head f_blocks;/* blocked locks */ unsigned int f_locks;/* guesstimate # of locks */
@@ -267,6 +270,7 @@ typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);/* * Server-side lock handling */ +int lock_to_openmode (struct file_lock *);__be32 nlmsvc_lock (struct svc_rqst *,struct nlm_file *,struct nlm_host *,struct nlm_lock *,int ,struct nlm_cookie *,int );
@@ -301,7 +305,8 @@ int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr);static inline struct inode *nlmsvc_file_inode (struct nlm_file *file) { -return locks_inode (file->f_file); +return locks_inode (file->f_file[O_RDONLY ] ? + file->f_file[O_RDONLY ] : file->f_file[O_WRONLY ]); }static inline int __nlm_privileged_request4 (const struct sockaddr *sap)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 350/770 nfs: dont atempt blocking locks on nfs reexports
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit f657f8eef3ff870552c9fd2839e0061046f44618 ]
NFS implements blocking locks by blocking inside its lock method. In the reexport case, this blocks the nfs server thread, which could lead to deadlocks since an nfs server thread might be required to unlock the conflicting lock. It also causes a crash, since the nfs server thread assumes it can free the lock when its lm_notify lock callback is called.
Ideal would be to make the nfs lock method return without blocking in this case, but for now it works just not to attempt blocking locks. The difference is just that the original client will have to poll (as it does in the v4.0 case) instead of getting a callback when the lock's available.
--- fs/nfs/export.c | 2 +- fs/nfsd/nfs4state.c | 8 ++++++-- include/linux/exportfs.h | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-)
fs/nfs/export.c +1 -1
@@ -184,5 +184,5 @@ const struct export_operations nfs_export_ops = { .fetch_iversion = nfs_fetch_iversion, .flags =EXPORT_OP_NOWCC |EXPORT_OP_NOSUBTREECHK |EXPORT_OP_CLOSE_BEFORE_UNLINK |EXPORT_OP_REMOTE_FS | - EXPORT_OP_NOATOMIC_ATTR, + EXPORT_OP_NOATOMIC_ATTR|EXPORT_OP_SYNC_LOCKS, };
fs/nfsd/nfs4state.c +6 -2
@@ -6878,6 +6878,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,struct nfsd4_blocked_lock *nbl =NULL ;struct file_lock *file_lock =NULL ;struct file_lock *conflock =NULL ; +struct super_block *sb;__be32 status =0 ;int lkflg;int err;
@@ -6899,6 +6900,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,dprintk ("NFSD: nfsd4_lock: permission denied!\n" );return status; } + sb = cstate->current_fh.fh_dentry->d_sb;if (lock->lk_is_new) {if (nfsd4_has_session (cstate))
@@ -6947,7 +6949,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, fp = lock_stp->st_stid.sc_file;switch (lock->lk_type) {case NFS4_READW_LT : -if (nfsd4_has_session (cstate)) +if (nfsd4_has_session (cstate) && + !(sb->s_export_op->flags &EXPORT_OP_SYNC_LOCKS )) fl_flags |=FL_SLEEP ; fallthrough;case NFS4_READ_LT :
@@ -6959,7 +6962,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, fl_type =F_RDLCK ;break ;case NFS4_WRITEW_LT : -if (nfsd4_has_session (cstate)) +if (nfsd4_has_session (cstate) && + !(sb->s_export_op->flags &EXPORT_OP_SYNC_LOCKS )) fl_flags |=FL_SLEEP ; fallthrough;case NFS4_WRITE_LT :
include/linux/exportfs.h +2 -0
@@ -221,6 +221,8 @@ struct export_operations {#define EXPORT_OP_NOATOMIC_ATTR (0x10)/* Filesystem cannot supply atomic attribute updates */ +#define EXPORT_OP_SYNC_LOCKS (0x20)/* Filesystem can't do +asychronous blocking locks */ unsigned long flags; };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 351/770 lockd: dont attempt blocking locks on nfs reexports
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit b840be2f00c0bc00d993f8f76e251052b83e4382 ]
As in the v4 case, it doesn't work well to block waiting for a lock on an nfs filesystem.
As in the v4 case, that means we're depending on the client to poll. It's probably incorrect to depend on that, but I *think* clients do poll in practice. In any case, it's an improvement over hanging the lockd thread indefinitely as we currently are.
--- fs/lockd/svclock.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
fs/lockd/svclock.c +10 -3
@@ -31,6 +31,7 @@#include <linux/lockd/nlm.h> #include <linux/lockd/lockd.h> #include <linux/kthread.h> +#include <linux/exportfs.h> #define NLMDBG_FACILITY NLMDBG_SVCLOCK
@@ -470,18 +471,24 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_cookie *cookie, int reclaim) {struct nlm_block *block =NULL ; +struct inode *inode =nlmsvc_file_inode (file);int error;int mode; +int async_block =0 ;__be32 ret;dprintk ("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n" , -nlmsvc_file_inode (file)->i_sb->s_id, -nlmsvc_file_inode (file)->i_ino, + inode->i_sb->s_id, inode->i_ino, lock->fl.fl_type, lock->fl.fl_pid, (long long )lock->fl.fl_start, (long long )lock->fl.fl_end, wait); +if (inode->i_sb->s_export_op->flags &EXPORT_OP_SYNC_LOCKS ) { + async_block = wait; + wait =0 ; + } +/* Lock file against concurrent access */ mutex_lock (&file->f_mutex);/* Get existing block (in case client is busy-waiting)
@@ -542,7 +549,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,*/ if (wait)break ; - ret = nlm_lck_denied; + ret = async_block ? nlm_lck_blocked : nlm_lck_denied; goto out;case FILE_LOCK_DEFERRED :if (wait)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 352/770 nfs: dont allow reexport reclaims
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Bruce Fields <[email protected]>
[ Upstream commit bb0a55bb7148a49e549ee992200860e7a040d3a5 ]
In the reexport case, nfsd is currently passing along locks with the reclaim bit set. The client sends a new lock request, which is granted if there's currently no conflict--even if it's possible a conflicting lock could have been briefly held in the interim.
We don't currently have any way to safely grant reclaim, so for now let's just deny them all.
I'm doing this by passing the reclaim bit to nfs and letting it fail the call, with the idea that eventually the client might be able to do something more forgiving here.
--- fs/nfs/file.c | 3 +++ fs/nfsd/nfs4state.c | 3 +++ fs/nfsd/nfsproc.c | 1 + include/linux/errno.h | 1 + include/linux/fs.h | 1 + 5 files changed, 9 insertions(+)
fs/nfs/file.c +3 -0
@@ -798,6 +798,9 @@ int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)nfs_inc_stats (inode,NFSIOS_VFSLOCK ); +if (fl->fl_flags &FL_RECLAIM ) +return -ENOGRACE ; +/* No mandatory locks over NFS */ if (__mandatory_lock (inode) && fl->fl_type !=F_UNLCK ) goto out_err;
fs/nfsd/nfs4state.c +3 -0
@@ -6946,6 +6946,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (!locks_in_grace (net) && lock->lk_reclaim) goto out; +if (lock->lk_reclaim) + fl_flags |=FL_RECLAIM ; + fp = lock_stp->st_stid.sc_file;switch (lock->lk_type) {case NFS4_READW_LT :
fs/nfsd/nfsproc.c +1 -0
@@ -881,6 +881,7 @@ nfserrno (int errno) { nfserr_serverfault, -ENFILE }, { nfserr_io, -EUCLEAN }, { nfserr_perm, -ENOKEY }, + { nfserr_no_grace, -ENOGRACE}, };int i;
include/linux/errno.h +1 -0
@@ -31,5 +31,6 @@#define EJUKEBOX 528/* Request initiated, but will not complete before timeout */ #define EIOCBQUEUED 529/* iocb queued, will get completion event */ #define ERECALLCONFLICT 530/* conflict with recalled state */ +#define ENOGRACE 531/* NFS file lock reclaim refused */ #endif
include/linux/fs.h +1 -0
@@ -996,6 +996,7 @@ static inline struct file *get_file(struct file *f)#define FL_UNLOCK_PENDING 512/* Lease is being broken */ #define FL_OFDLCK 1024/* lock is "owned" by struct file */ #define FL_LAYOUT 2048/* outstanding pNFS layout */ +#define FL_RECLAIM 4096/* reclaiming from a reboot server */ #define FL_CLOSE_POSIX (FL_POSIX | FL_CLOSE)
Signature · 1 line
2.43.0