5.10.220-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 353/770 SUNRPC: Add svc_rqst::rq_auth_stat
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 438623a06bacd69c40c4af633bb09a3bbb9dfc78 ]
I'd like to take commit 4532608d71c8 ("SUNRPC: Clean up generic dispatcher code") even further by using only private local SVC dispatchers for all kernel RPC services. This change would enable the removal of the logic that switches between svc_generic_dispatch() and a service's private dispatcher, and simplify the invocation of the service's pc_release method so that humans can visually verify that it is always invoked properly.
All that will come later.
First, let's provide a better way to return authentication errors from SVC dispatcher functions. Instead of overloading the dispatch method's *statp argument, add a field to struct svc_rqst that can hold an error value.
--- include/linux/sunrpc/svc.h | 1 + include/linux/sunrpc/svcauth.h | 4 +-- include/trace/events/sunrpc.h | 6 ++--- net/sunrpc/auth_gss/svcauth_gss.c | 43 +++++++++++++++---------------- net/sunrpc/svc.c | 17 ++++++------ net/sunrpc/svcauth.c | 8 +++--- net/sunrpc/svcauth_unix.c | 12 ++++----- 7 files changed, 46 insertions(+), 45 deletions(-)
include/linux/sunrpc/svc.h +1 -0
@@ -284,6 +284,7 @@ struct svc_rqst {void * rq_argp;/* decoded arguments */ void * rq_resp;/* xdr'd results */ void * rq_auth_data;/* flavor-specific data */ +__be32 rq_auth_stat;/* authentication status */ int rq_auth_slack;/* extra space xdr code * should leave in head * for krb5i, krb5p.
include/linux/sunrpc/svcauth.h +2 -2
@@ -127,7 +127,7 @@ struct auth_ops {char * name;struct module *owner;int flavour; -int (*accept)(struct svc_rqst *rq,__be32 *authp); +int (*accept)(struct svc_rqst *rq);int (*release)(struct svc_rqst *rq);void (*domain_release)(struct auth_domain *);int (*set_client)(struct svc_rqst *rq);
@@ -149,7 +149,7 @@ struct auth_ops {struct svc_xprt ; -extern int svc_authenticate (struct svc_rqst *rqstp,__be32 *authp); +extern int svc_authenticate (struct svc_rqst *rqstp);extern int svc_authorise (struct svc_rqst *rqstp);extern int svc_set_client (struct svc_rqst *rqstp);extern int svc_auth_register (rpc_authflavor_t flavor,struct auth_ops *aops);
include/trace/events/sunrpc.h +3 -3
@@ -1547,9 +1547,9 @@ TRACE_DEFINE_ENUM(SVC_COMPLETE); { SVC_COMPLETE, "SVC_COMPLETE" }) TRACE_EVENT(svc_authenticate, - TP_PROTO(const struct svc_rqst *rqst, int auth_res, __be32 auth_stat), + TP_PROTO(const struct svc_rqst *rqst, int auth_res), - TP_ARGS(rqst, auth_res, auth_stat), + TP_ARGS(rqst, auth_res), TP_STRUCT__entry( __field(u32, xid)
@@ -1560,7 +1560,7 @@ TRACE_EVENT(svc_authenticate,TP_fast_assign ( __entry->xid = be32_to_cpu(rqst->rq_xid); __entry->svc_status = auth_res; - __entry->auth_stat =be32_to_cpu (auth_stat); + __entry->auth_stat =be32_to_cpu (rqst->rq_auth_stat); ), TP_printk("xid=0x%08x auth_res=%s auth_stat=%s",
net/sunrpc/auth_gss/svcauth_gss.c +21 -22
151 lines not on this page · raw message
net/sunrpc/svc.c +9 -8
@@ -1305,7 +1305,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)struct svc_process_info process;__be32 *statp;u32 prog, vers; -__be32 auth_stat, rpc_stat; +__be32 rpc_stat;int auth_res;__be32 *reply_statp;
@@ -1348,14 +1348,14 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)* We do this before anything else in order to get a decent * auth verifier. */ - auth_res =svc_authenticate (rqstp, &auth_stat); + auth_res =svc_authenticate (rqstp);/* Also give the program a chance to reject this call: */ if (auth_res ==SVC_OK && progp) { - auth_stat = rpc_autherr_badcred; + rqstp->rq_auth_stat = rpc_autherr_badcred; auth_res = progp->pg_authenticate (rqstp); }if (auth_res !=SVC_OK ) -trace_svc_authenticate (rqstp, auth_res, auth_stat); +trace_svc_authenticate (rqstp, auth_res);switch (auth_res) {case SVC_OK :break ;
@@ -1414,8 +1414,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) goto release_dropit;if (*statp == rpc_garbage_args) goto err_garbage; - auth_stat =svc_get_autherr (rqstp, statp); -if (auth_stat != rpc_auth_ok) + rqstp->rq_auth_stat =svc_get_autherr (rqstp, statp); +if (rqstp->rq_auth_stat != rpc_auth_ok) goto err_release_bad_auth; }else {dprintk ("svc: calling dispatcher\n" );
@@ -1472,13 +1472,14 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)if (procp->pc_release) procp->pc_release (rqstp); err_bad_auth: -dprintk ("svc: authentication failed (%d)\n" ,ntohl (auth_stat)); +dprintk ("svc: authentication failed (%d)\n" , +be32_to_cpu (rqstp->rq_auth_stat)); serv->sv_stats->rpcbadauth++;/* Restore write pointer to location of accept status: */ xdr_ressize_check (rqstp, reply_statp);svc_putnl (resv,1 );/* REJECT */ svc_putnl (resv,1 );/* AUTH_ERROR */ -svc_putnl (resv,ntohl (auth_stat));/* status */ +svc_putu32 (resv, rqstp->rq_auth_stat);/* status */ goto sendit; err_bad_prog:
net/sunrpc/svcauth.c +4 -4
@@ -59,12 +59,12 @@ svc_put_auth_ops(struct auth_ops *aops) }int -svc_authenticate (struct svc_rqst *rqstp,__be32 *authp) +svc_authenticate (struct svc_rqst *rqstp) {rpc_authflavor_t flavor;struct auth_ops *aops; - *authp = rpc_auth_ok; + rqstp->rq_auth_stat = rpc_auth_ok; flavor =svc_getnl (&rqstp->rq_arg.head[0 ]);
@@ -72,7 +72,7 @@ svc_authenticate(struct svc_rqst *rqstp, __be32 *authp) aops =svc_get_auth_ops (flavor);if (aops ==NULL ) { - *authp = rpc_autherr_badcred; + rqstp->rq_auth_stat = rpc_autherr_badcred;return SVC_DENIED ; }
@@ -80,7 +80,7 @@ svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)init_svc_cred (&rqstp->rq_cred); rqstp->rq_authop = aops; -return aops->accept (rqstp, authp); +return aops->accept (rqstp); }EXPORT_SYMBOL_GPL (svc_authenticate);
net/sunrpc/svcauth_unix.c +6 -6
@@ -743,7 +743,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)EXPORT_SYMBOL_GPL (svcauth_unix_set_client);static int -svcauth_null_accept (struct svc_rqst *rqstp,__be32 *authp) +svcauth_null_accept (struct svc_rqst *rqstp) {struct kvec *argv = &rqstp->rq_arg.head[0 ];struct kvec *resv = &rqstp->rq_res.head[0 ];
@@ -754,12 +754,12 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)if (svc_getu32 (argv) !=0 ) {dprintk ("svc: bad null cred\n" ); - *authp = rpc_autherr_badcred; + rqstp->rq_auth_stat = rpc_autherr_badcred;return SVC_DENIED ; }if (svc_getu32 (argv) !=htonl (RPC_AUTH_NULL ) ||svc_getu32 (argv) !=0 ) {dprintk ("svc: bad null verf\n" ); - *authp = rpc_autherr_badverf; + rqstp->rq_auth_stat = rpc_autherr_badverf;return SVC_DENIED ; }
@@ -803,7 +803,7 @@ struct auth_ops svcauth_null = {static int -svcauth_unix_accept (struct svc_rqst *rqstp,__be32 *authp) +svcauth_unix_accept (struct svc_rqst *rqstp) {struct kvec *argv = &rqstp->rq_arg.head[0 ];struct kvec *resv = &rqstp->rq_res.head[0 ];
@@ -845,7 +845,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) }groups_sort (cred->cr_group_info);if (svc_getu32 (argv) !=htonl (RPC_AUTH_NULL ) ||svc_getu32 (argv) !=0 ) { - *authp = rpc_autherr_badverf; + rqstp->rq_auth_stat = rpc_autherr_badverf;return SVC_DENIED ; }
@@ -857,7 +857,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)return SVC_OK ; badcred: - *authp = rpc_autherr_badcred; + rqstp->rq_auth_stat = rpc_autherr_badcred;return SVC_DENIED ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 354/770 SUNRPC: Set rq_auth_stat in the pg_authenticate() callout
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 5c2465dfd457f3015eebcc3ace50570e1d896aeb ]
In a few moments, rq_auth_stat will need to be explicitly set to rpc_auth_ok before execution gets to the dispatcher.
svc_authenticate() already sets it, but it often gets reset to rpc_autherr_badcred right after that call, even when authentication is successful. Let's ensure that the pg_authenticate callout and svc_set_client() set it properly in every case.
--- fs/lockd/svc.c | 2 ++ fs/nfs/callback.c | 4 ++++ net/sunrpc/auth_gss/svcauth_gss.c | 4 ++++ net/sunrpc/svc.c | 4 +--- net/sunrpc/svcauth_unix.c | 6 +++++- 5 files changed, 16 insertions(+), 4 deletions(-)
fs/lockd/svc.c +2 -0
@@ -649,6 +649,7 @@ static int lockd_authenticate(struct svc_rqst *rqstp)switch (rqstp->rq_authop->flavour) {case RPC_AUTH_NULL :case RPC_AUTH_UNIX : + rqstp->rq_auth_stat = rpc_auth_ok;if (rqstp->rq_proc ==0 )return SVC_OK ;if (is_callback (rqstp->rq_proc)) {
@@ -659,6 +660,7 @@ static int lockd_authenticate(struct svc_rqst *rqstp) }return svc_set_client (rqstp); } + rqstp->rq_auth_stat = rpc_autherr_badcred;return SVC_DENIED ; }
fs/nfs/callback.c +4 -0
@@ -429,6 +429,8 @@ check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)*/ static int nfs_callback_authenticate (struct svc_rqst *rqstp) { + rqstp->rq_auth_stat = rpc_autherr_badcred; +switch (rqstp->rq_authop->flavour) {case RPC_AUTH_NULL :if (rqstp->rq_proc !=CB_NULL )
@@ -439,6 +441,8 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)if (svc_is_backchannel (rqstp))return SVC_DENIED ; } + + rqstp->rq_auth_stat = rpc_auth_ok;return SVC_OK ; }
net/sunrpc/auth_gss/svcauth_gss.c +4 -0
@@ -1038,6 +1038,8 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)struct rpc_gss_wire_cred *gc = &svcdata->clcred;int stat; + rqstp->rq_auth_stat = rpc_autherr_badcred; +/* * A gss export can be specified either by: * export *(sec=krb5,rw)
@@ -1053,6 +1055,8 @@ svcauth_gss_set_client(struct svc_rqst *rqstp) stat =svcauth_unix_set_client (rqstp);if (stat ==SVC_DROP || stat ==SVC_CLOSE )return stat; + + rqstp->rq_auth_stat = rpc_auth_ok;return SVC_OK ; }
net/sunrpc/svc.c +1 -3
@@ -1350,10 +1350,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)*/ auth_res =svc_authenticate (rqstp);/* Also give the program a chance to reject this call: */ -if (auth_res ==SVC_OK && progp) { - rqstp->rq_auth_stat = rpc_autherr_badcred; +if (auth_res ==SVC_OK && progp) auth_res = progp->pg_authenticate (rqstp); - }if (auth_res !=SVC_OK )trace_svc_authenticate (rqstp, auth_res);switch (auth_res) {
net/sunrpc/svcauth_unix.c +5 -1
@@ -699,8 +699,9 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) rqstp->rq_client =NULL ;if (rqstp->rq_proc ==0 ) -return SVC_OK ; + goto out; + rqstp->rq_auth_stat = rpc_autherr_badcred; ipm =ip_map_cached_get (xprt);if (ipm ==NULL ) ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
@@ -737,6 +738,9 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)put_group_info (cred->cr_group_info); cred->cr_group_info = gi; } + +out: + rqstp->rq_auth_stat = rpc_auth_ok;return SVC_OK ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 355/770 SUNRPC: Eliminate the RQ_AUTHERR flag
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 9082e1d914f8b27114352b1940bbcc7522f682e7 ]
Now that there is an alternate method for returning an auth_stat value, replace the RQ_AUTHERR flag with use of that new method.
--- fs/nfs/callback_xdr.c | 3 ++- include/linux/sunrpc/svc.h | 2 -- include/trace/events/sunrpc.h | 3 +-- net/sunrpc/svc.c | 24 ++++-------------------- 4 files changed, 7 insertions(+), 25 deletions(-)
fs/nfs/callback_xdr.c +2 -1
@@ -984,7 +984,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp) out_invalidcred:pr_warn_ratelimited ("NFS: NFSv4 callback contains invalid cred\n" ); -return svc_return_autherr (rqstp, rpc_autherr_badcred); + rqstp->rq_auth_stat = rpc_autherr_badcred; +return rpc_success; }/*
include/linux/sunrpc/svc.h +0 -2
@@ -277,7 +277,6 @@ struct svc_rqst {#define RQ_VICTIM (5)/* about to be shut down */ #define RQ_BUSY (6)/* request is busy */ #define RQ_DATA (7)/* request has data */ -#define RQ_AUTHERR (8)/* Request status is auth error */ unsigned long rq_flags;/* flags field */ ktime_t rq_qtime;/* enqueue time */
@@ -537,7 +536,6 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp,char *svc_fill_symlink_pathname (struct svc_rqst *rqstp,struct kvec *first,void *p,size_t total); -__be32 svc_return_autherr (struct svc_rqst *rqstp,__be32 auth_err);__be32 svc_generic_init_request (struct svc_rqst *rqstp,const struct svc_program *progp,struct svc_process_info *procinfo);
include/trace/events/sunrpc.h +1 -2
@@ -1480,8 +1480,7 @@ DEFINE_SVCXDRBUF_EVENT(sendto); svc_rqst_flag(SPLICE_OK) \ svc_rqst_flag(VICTIM) \ svc_rqst_flag(BUSY) \ - svc_rqst_flag(DATA) \ - svc_rqst_flag_end(AUTHERR) + svc_rqst_flag_end(DATA)#undef svc_rqst_flag#undef svc_rqst_flag_end
net/sunrpc/svc.c +4 -20
@@ -1187,22 +1187,6 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}#endif -__be32 -svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err) -{ - set_bit(RQ_AUTHERR, &rqstp->rq_flags); - return auth_err; -} -EXPORT_SYMBOL_GPL(svc_return_autherr); - -static __be32 -svc_get_autherr(struct svc_rqst *rqstp, __be32 *statp) -{ - if (test_and_clear_bit(RQ_AUTHERR, &rqstp->rq_flags)) - return *statp; -return rpc_auth_ok; -} -static int svc_generic_dispatch (struct svc_rqst *rqstp,__be32 *statp) {
@@ -1226,7 +1210,7 @@ svc_generic_dispatch(struct svc_rqst *rqstp, __be32 *statp) test_bit(RQ_DROPME, &rqstp->rq_flags))return 0 ; -if (test_bit (RQ_AUTHERR , &rqstp->rq_flags)) +if (rqstp->rq_auth_stat != rpc_auth_ok)return 1 ;if (*statp != rpc_success)
@@ -1412,15 +1396,15 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) goto release_dropit;if (*statp == rpc_garbage_args) goto err_garbage; - rqstp->rq_auth_stat =svc_get_autherr (rqstp, statp); -if (rqstp->rq_auth_stat != rpc_auth_ok) - goto err_release_bad_auth; }else {dprintk ("svc: calling dispatcher\n" );if (!process.dispatch (rqstp, statp)) goto release_dropit;/* Release reply info */ } +if (rqstp->rq_auth_stat != rpc_auth_ok) + goto err_release_bad_auth; +/* Check RPC status result */ if (*statp != rpc_success) resv->iov_len = ((void *)statp) - resv->iov_base +4 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 356/770 NFS: Add a private local dispatcher for NFSv4 callback operations
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 7d34c96217cf3c2d37ca0a56ca0bc3c3bef1e189 ]
The client's NFSv4 callback service is the only remaining user of svc_generic_dispatch().
Note that the NFSv4 callback service doesn't use the .pc_encode and .pc_decode callouts in any substantial way, so they are removed.
--- fs/nfs/callback_xdr.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
fs/nfs/callback_xdr.c +11 -2
@@ -988,6 +988,15 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)return rpc_success; } +static int +nfs_callback_dispatch (struct svc_rqst *rqstp,__be32 *statp) +{ +const struct svc_procedure *procp = rqstp->rq_procinfo; + + *statp = procp->pc_func (rqstp); +return 1 ; +} +/* * Define NFS4 callback COMPOUND ops. */
@@ -1076,7 +1085,7 @@ const struct svc_version nfs4_callback_version1 = { .vs_proc = nfs4_callback_procedures1, .vs_count = nfs4_callback_count1, .vs_xdrsize = NFS4_CALLBACK_XDRSIZE, - .vs_dispatch = NULL, + .vs_dispatch = nfs_callback_dispatch, .vs_hidden = true, .vs_need_cong_ctrl = true, };
@@ -1088,7 +1097,7 @@ const struct svc_version nfs4_callback_version4 = { .vs_proc = nfs4_callback_procedures1, .vs_count = nfs4_callback_count4, .vs_xdrsize = NFS4_CALLBACK_XDRSIZE, - .vs_dispatch = NULL, + .vs_dispatch = nfs_callback_dispatch, .vs_hidden = true, .vs_need_cong_ctrl = true, };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 357/770 NFS: Remove unused callback void decoder
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 c35a810ce59524971c4a3b45faed4d0121e5a305 ]
Clean up: The callback RPC dispatcher no longer invokes these call outs, although svc_process_common() relies on seeing a .pc_encode function.
--- fs/nfs/callback_xdr.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
fs/nfs/callback_xdr.c +4 -6
@@ -63,11 +63,10 @@ static __be32 nfs4_callback_null(struct svc_rqst *rqstp)return htonl (NFS4_OK ); } -static int nfs4_decode_void (struct svc_rqst *rqstp,__be32 *p) -{ -return xdr_argsize_check (rqstp, p); -} - +/* +* svc_process_common() looks for an XDR encoder to know when +* not to drop a Reply. +*/ static int nfs4_encode_void (struct svc_rqst *rqstp,__be32 *p) {return xdr_ressize_check (rqstp, p);
@@ -1063,7 +1062,6 @@ static struct callback_op callback_ops[] = {static const struct svc_procedure nfs4_callback_procedures1[] = { [CB_NULL ] = { .pc_func = nfs4_callback_null, - .pc_decode = nfs4_decode_void, .pc_encode = nfs4_encode_void, .pc_xdrressize =1 , .pc_name ="NULL" ,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 358/770 fsnotify: fix sb_connectors leak
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 4396a73115fc8739083536162e2228c0c0c3ed1a ]
Fix a leak in s_fsnotify_connectors counter in case of a race between concurrent add of new fsnotify mark to an object.
The task that lost the race fails to drop the counter before freeing the unused connector.
Following umount() hangs in fsnotify_sb_delete()/wait_var_event(), because s_fsnotify_connectors never drops to zero.
--- fs/notify/mark.c | 1 + 1 file changed, 1 insertion(+)
fs/notify/mark.c +1 -0
@@ -531,6 +531,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,/* Someone else created list structure for us */ if (inode)fsnotify_put_inode_ref (inode); +fsnotify_put_sb_connectors (conn);kmem_cache_free (fsnotify_mark_connector_cachep, conn); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 359/770 NLM: Fix svcxdr_encode_owner()
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 89c485c7a3ecbc2ebd568f9c9c2edf3a8cf7485b ]
Dai Ngo reports that, since the XDR overhaul, the NLM server crashes when the TEST procedure wants to return NLM_DENIED. There is a bug in svcxdr_encode_owner() that none of our standard test cases found.
Replace the open-coded function with a call to an appropriate pre-fabricated XDR helper.
--- fs/lockd/svcxdr.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-)
fs/lockd/svcxdr.h +2 -11
@@ -134,18 +134,9 @@ svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj)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) +if (obj->len >XDR_MAX_NETOBJ )return false; - p[quadlen -1 ] =0 ;/* XDR pad */ -memcpy (p, obj->data, obj->len); - -return true; +return xdr_stream_encode_opaque (xdr, obj->data, obj->len) >0 ; }#endif /* _LOCKD_SVCXDR_H_ */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 360/770 nfsd: Fix a warning for nfsd_file_close_inode
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 19598141f40dff728dd50799e510805261f48850 ]
--- fs/nfsd/filecache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/filecache.c +1 -1
@@ -541,7 +541,7 @@ nfsd_file_close_inode_sync(struct inode *inode) }/** -* nfsd_file_close_inode_sync - attempt to forcibly close a nfsd_file +* nfsd_file_close_inode - attempt a delayed close of a nfsd_file * @inode: inode of the file to attempt to remove * * Walk the whole hash bucket, looking for any files that correspond to "inode".
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 361/770 fsnotify: pass data_type to fsnotify_name()
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 9baf93d68bcc3d0a6042283b82603c076e25e4f5 ]
Align the arguments of fsnotify_name() to those of fsnotify().
--- include/linux/fsnotify.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
include/linux/fsnotify.h +15 -10
@@ -26,20 +26,21 @@* FS_EVENT_ON_CHILD mask on the parent inode and will not be reported if only * the child is interested and not the parent. */ -static inline void fsnotify_name (struct inode *dir,__u32 mask, -struct inode *child, -const struct qstr *name,u32 cookie) +static inline int fsnotify_name (__u32 mask,const void *data,int data_type, +struct inode *dir,const struct qstr *name, +u32 cookie) {if (atomic_long_read (&dir->i_sb->s_fsnotify_connectors) ==0 ) -return ; +return 0 ; -fsnotify (mask, child,FSNOTIFY_EVENT_INODE , dir, name,NULL , cookie); +return fsnotify (mask, data, data_type, dir, name,NULL , cookie); }static inline void fsnotify_dirent (struct inode *dir,struct dentry *dentry,__u32 mask) { -fsnotify_name (dir, mask,d_inode (dentry), &dentry->d_name,0 ); +fsnotify_name (mask,d_inode (dentry),FSNOTIFY_EVENT_INODE , + dir, &dentry->d_name,0 ); }static inline void fsnotify_inode (struct inode *inode,__u32 mask)
@@ -154,8 +155,10 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, new_dir_mask |=FS_ISDIR ; } -fsnotify_name (old_dir, old_dir_mask, source, old_name, fs_cookie); -fsnotify_name (new_dir, new_dir_mask, source, new_name, fs_cookie); +fsnotify_name (old_dir_mask, source,FSNOTIFY_EVENT_INODE , + old_dir, old_name, fs_cookie); +fsnotify_name (new_dir_mask, source,FSNOTIFY_EVENT_INODE , + new_dir, new_name, fs_cookie);if (target)fsnotify_link_count (target);
@@ -209,7 +212,8 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode,fsnotify_link_count (inode);audit_inode_child (dir, new_dentry,AUDIT_TYPE_CHILD_CREATE ); -fsnotify_name (dir,FS_CREATE , inode, &new_dentry->d_name,0 ); +fsnotify_name (FS_CREATE , inode,FSNOTIFY_EVENT_INODE , + dir, &new_dentry->d_name,0 ); }/*
@@ -228,7 +232,8 @@ static inline void fsnotify_delete(struct inode *dir, struct inode *inode,if (S_ISDIR (inode->i_mode)) mask |=FS_ISDIR ; -fsnotify_name (dir, mask, inode, &dentry->d_name,0 ); +fsnotify_name (mask, inode,FSNOTIFY_EVENT_INODE , dir, &dentry->d_name, +0 ); }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 362/770 fsnotify: pass dentry instead of inode data
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 fd5a3ff49a19aa69e2bc1e26e98037c2d778e61a ]
Define a new data type to pass for event - FSNOTIFY_EVENT_DENTRY. Use it to pass the dentry instead of it's ->d_inode where available.
This is needed in preparation to the refactor to retrieve the super block from the data field. In some cases (i.e. mkdir in kernfs), the data inode comes from a negative dentry, such that no super block information would be available. By receiving the dentry itself, instead of the inode, fsnotify can derive the super block even on these cases.
--- include/linux/fsnotify.h | 5 ++--- include/linux/fsnotify_backend.h | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-)
include/linux/fsnotify.h +2 -3
@@ -39,8 +39,7 @@ static inline int fsnotify_name(__u32 mask, const void *data, int data_type,static inline void fsnotify_dirent (struct inode *dir,struct dentry *dentry,__u32 mask) { -fsnotify_name (mask,d_inode (dentry),FSNOTIFY_EVENT_INODE , - dir, &dentry->d_name,0 ); +fsnotify_name (mask, dentry,FSNOTIFY_EVENT_DENTRY , dir, &dentry->d_name,0 ); }static inline void fsnotify_inode (struct inode *inode,__u32 mask)
@@ -87,7 +86,7 @@ static inline int fsnotify_parent(struct dentry *dentry, __u32 mask,*/ static inline void fsnotify_dentry (struct dentry *dentry,__u32 mask) { -fsnotify_parent (dentry, mask,d_inode (dentry),FSNOTIFY_EVENT_INODE ); +fsnotify_parent (dentry, mask, dentry,FSNOTIFY_EVENT_DENTRY ); }static inline int fsnotify_file (struct file *file,__u32 mask)
include/linux/fsnotify_backend.h +16 -0
@@ -248,6 +248,7 @@ enum fsnotify_data_type {FSNOTIFY_EVENT_NONE ,FSNOTIFY_EVENT_PATH ,FSNOTIFY_EVENT_INODE , + FSNOTIFY_EVENT_DENTRY, };static inline struct inode *fsnotify_data_inode (const void *data,int data_type)
@@ -255,6 +256,8 @@ static inline struct inode *fsnotify_data_inode(const void *data, int data_type)switch (data_type) {case FSNOTIFY_EVENT_INODE :return (struct inode *)data; +case FSNOTIFY_EVENT_DENTRY : +return d_inode (data);case FSNOTIFY_EVENT_PATH :return d_inode (((const struct path *)data)->dentry);default :
@@ -262,6 +265,19 @@ static inline struct inode *fsnotify_data_inode(const void *data, int data_type) } } +static inline struct dentry *fsnotify_data_dentry (const void *data,int data_type) +{ +switch (data_type) { +case FSNOTIFY_EVENT_DENTRY : +/* Non const is needed for dget() */ +return (struct dentry *)data; +case FSNOTIFY_EVENT_PATH : +return ((const struct path *)data)->dentry; +default : +return NULL ; + } +} +static inline const struct path *fsnotify_data_path (const void *data,int data_type) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 363/770 fsnotify: clarify contract for create event hooks
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 dabe729dddca550446e9cc118c96d1f91703345b ]
Clarify argument names and contract for fsnotify_create() and fsnotify_mkdir() to reflect the anomaly of kernfs, which leaves dentries negavite after mkdir/create.
Remove the WARN_ON(!inode) in audit code that were added by the Fixes commit under the wrong assumption that dentries cannot be negative after mkdir/create.
--- include/linux/fsnotify.h | 22 ++++++++++++++++------ kernel/audit_fsnotify.c | 3 +-- kernel/audit_watch.c | 3 +-- 3 files changed, 18 insertions(+), 10 deletions(-)
include/linux/fsnotify.h +16 -6
@@ -192,16 +192,22 @@ static inline void fsnotify_inoderemove(struct inode *inode)/* * fsnotify_create - 'name' was linked in +* +* Caller must make sure that dentry->d_name is stable. +* Note: some filesystems (e.g. kernfs) leave @dentry negative and instantiate +* ->d_inode later */ -static inline void fsnotify_create (struct inode *inode,struct dentry *dentry) +static inline void fsnotify_create (struct inode *dir,struct dentry *dentry) { -audit_inode_child (inode, dentry,AUDIT_TYPE_CHILD_CREATE ); +audit_inode_child (dir, dentry,AUDIT_TYPE_CHILD_CREATE ); -fsnotify_dirent (inode, dentry,FS_CREATE ); +fsnotify_dirent (dir, dentry,FS_CREATE ); }/* * fsnotify_link - new hardlink in 'inode' directory +* +* Caller must make sure that new_dentry->d_name is stable. * Note: We have to pass also the linked inode ptr as some filesystems leave * new_dentry->d_inode NULL and instantiate inode pointer later */
@@ -267,12 +273,16 @@ static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)/* * fsnotify_mkdir - directory 'name' was created +* +* Caller must make sure that dentry->d_name is stable. +* Note: some filesystems (e.g. kernfs) leave @dentry negative and instantiate +* ->d_inode later */ -static inline void fsnotify_mkdir (struct inode *inode,struct dentry *dentry) +static inline void fsnotify_mkdir (struct inode *dir,struct dentry *dentry) { -audit_inode_child (inode, dentry,AUDIT_TYPE_CHILD_CREATE ); +audit_inode_child (dir, dentry,AUDIT_TYPE_CHILD_CREATE ); -fsnotify_dirent (inode, dentry,FS_CREATE |FS_ISDIR ); +fsnotify_dirent (dir, dentry,FS_CREATE |FS_ISDIR ); }/*
kernel/audit_fsnotify.c +1 -2
@@ -161,8 +161,7 @@ static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask, audit_mark = container_of(inode_mark, struct audit_fsnotify_mark, mark); -if (WARN_ON_ONCE (inode_mark->group != audit_fsnotify_group) || -WARN_ON_ONCE (!inode)) +if (WARN_ON_ONCE (inode_mark->group != audit_fsnotify_group))return 0 ;if (mask & (FS_CREATE |FS_MOVED_TO |FS_DELETE |FS_MOVED_FROM )) {
kernel/audit_watch.c +1 -2
@@ -472,8 +472,7 @@ static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask, parent = container_of(inode_mark, struct audit_parent, mark); -if (WARN_ON_ONCE (inode_mark->group != audit_watch_group) || -WARN_ON_ONCE (!inode)) +if (WARN_ON_ONCE (inode_mark->group != audit_watch_group))return 0 ;if (mask & (FS_CREATE |FS_MOVED_TO ) && inode)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 364/770 fsnotify: Dont insert unmergeable events in hashtable
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit cc53b55f697fe5aa98bdbfdfe67c6401da242155 ]
Some events, like the overflow event, are not mergeable, so they are not hashed. But, when failing inside fsnotify_add_event for lack of space, fsnotify_add_event() still calls the insert hook, which adds the overflow event to the merge list. Add a check to prevent any kind of unmergeable event to be inserted in the hashtable.
--- fs/notify/fanotify/fanotify.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/notify/fanotify/fanotify.c +4 -2
@@ -702,6 +702,9 @@ static void fanotify_insert_event(struct fsnotify_group *group,assert_spin_locked (&group->notification_lock); +if (!fanotify_is_hashed_event (event->mask)) +return ; +pr_debug ("%s: group=%p event=%p bucket=%u\n" , __func__, group, event, bucket);
@@ -779,8 +782,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, fsn_event = &event->fse; ret =fsnotify_add_event (group, fsn_event, fanotify_merge, -fanotify_is_hashed_event (mask) ? - fanotify_insert_event :NULL ); + fanotify_insert_event);if (ret) {/* Permission events shouldn't be merged */ BUG_ON (ret ==1 && mask &FANOTIFY_PERM_EVENTS );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 365/770 fanotify: Fold event size calculation to its own function
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit b9928e80dda84b349ba8de01780b9bef2fc36ffa ]
Every time this function is invoked, it is immediately added to FAN_EVENT_METADATA_LEN, since there is no need to just calculate the length of info records. This minor clean up folds the rest of the calculation into the function, which now operates in terms of events, returning the size of the entire event, including metadata.
--- fs/notify/fanotify/fanotify_user.c | 35 +++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-)
fs/notify/fanotify/fanotify_user.c +20 -15
@@ -121,17 +121,24 @@ static int fanotify_fid_info_len(int fh_len, int name_len) FANOTIFY_EVENT_ALIGN); } -static int fanotify_event_info_len (unsigned int info_mode, -struct fanotify_event *event) +static size_t fanotify_event_len (unsigned int info_mode, +struct fanotify_event *event) { -struct fanotify_info *info =fanotify_event_info (event); -int dir_fh_len =fanotify_event_dir_fh_len (event); -int fh_len =fanotify_event_object_fh_len (event); -int info_len =0 ; +size_t event_len =FAN_EVENT_METADATA_LEN ; +struct fanotify_info *info; +int dir_fh_len; +int fh_len;int dot_len =0 ; +if (!info_mode) +return event_len; + + info =fanotify_event_info (event); + dir_fh_len =fanotify_event_dir_fh_len (event); + fh_len =fanotify_event_object_fh_len (event); +if (dir_fh_len) { - info_len +=fanotify_fid_info_len (dir_fh_len, info->name_len); + event_len +=fanotify_fid_info_len (dir_fh_len, info->name_len); }else if ((info_mode &FAN_REPORT_NAME ) && (event->mask &FAN_ONDIR )) {/*
@@ -142,12 +149,12 @@ static int fanotify_event_info_len(unsigned int info_mode, }if (info_mode &FAN_REPORT_PIDFD ) - info_len +=FANOTIFY_PIDFD_INFO_HDR_LEN ; + event_len +=FANOTIFY_PIDFD_INFO_HDR_LEN ;if (fh_len) - info_len +=fanotify_fid_info_len (fh_len, dot_len); + event_len +=fanotify_fid_info_len (fh_len, dot_len); -return info_len; +return event_len; }/*
@@ -176,7 +183,7 @@ static void fanotify_unhash_event(struct fsnotify_group *group,static struct fanotify_event *get_one_event (struct fsnotify_group *group,size_t count) { -size_t event_size =FAN_EVENT_METADATA_LEN ; +size_t event_size;struct fanotify_event *event =NULL ;struct fsnotify_event *fsn_event;unsigned int info_mode =FAN_GROUP_FLAG (group,FANOTIFY_INFO_MODES );
@@ -189,8 +196,7 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group, goto out; event =FANOTIFY_E (fsn_event); -if (info_mode) - event_size +=fanotify_event_info_len (info_mode, event); + event_size =fanotify_event_len (info_mode, event);if (event_size > count) { event =ERR_PTR (-EINVAL );
@@ -532,8 +538,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,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.event_len =fanotify_event_len (info_mode, event); metadata.metadata_len =FAN_EVENT_METADATA_LEN ; metadata.vers =FANOTIFY_METADATA_VERSION ; metadata.reserved =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 366/770 fanotify: Split fsid check from other fid mode checks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 8299212cbdb01a5867e230e961f82e5c02a6de34 ]
FAN_FS_ERROR will require fsid, but not necessarily require the filesystem to expose a file handle. Split those checks into different functions, so they can be used separately when setting up an event.
While there, update a comment about tmpfs having 0 fsid, which is no longer true.
--- fs/notify/fanotify/fanotify_user.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-)
fs/notify/fanotify/fanotify_user.c +18 -9
@@ -1295,16 +1295,15 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)return fd; } -/* Check if filesystem can encode a unique fid */ -static int fanotify_test_fid (struct path *path,__kernel_fsid_t *fsid) +static int fanotify_test_fsid (struct dentry *dentry,__kernel_fsid_t *fsid) {__kernel_fsid_t root_fsid;int err;/* -* Make sure path is not in filesystem with zero fsid (e.g. tmpfs). +* Make sure dentry is not of a filesystem with zero fsid (e.g. fuse). */ - err =vfs_get_fsid (path->dentry, fsid); + err =vfs_get_fsid (dentry, fsid);if (err)return err;
@@ -1312,10 +1311,10 @@ static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)return -ENODEV ;/* -* Make sure path is not inside a filesystem subvolume (e.g. btrfs) +* Make sure dentry is not of a filesystem subvolume (e.g. btrfs) * which uses a different fsid than sb root. */ - err =vfs_get_fsid (path->dentry->d_sb->s_root, &root_fsid); + err =vfs_get_fsid (dentry->d_sb->s_root, &root_fsid);if (err)return err;
@@ -1323,6 +1322,12 @@ static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid) root_fsid.val[1] != fsid->val[1])return -EXDEV ; +return 0 ; +} + +/* Check if filesystem can encode a unique fid */ +static int fanotify_test_fid (struct dentry *dentry) +{/* * We need to make sure that the file system supports at least * encoding a file handle so user can use name_to_handle_at() to
@@ -1330,8 +1335,8 @@ static int fanotify_test_fid(struct path *path, __kernel_fsid_t *fsid)* objects. However, name_to_handle_at() requires that the * filesystem also supports decoding file handles. */ -if (!path->dentry->d_sb->s_export_op || - !path->dentry->d_sb->s_export_op->fh_to_dentry) +if (!dentry->d_sb->s_export_op || + !dentry->d_sb->s_export_op->fh_to_dentry)return -EOPNOTSUPP ;return 0 ;
@@ -1500,7 +1505,11 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, }if (fid_mode) { - ret =fanotify_test_fid (&path, &__fsid); + ret =fanotify_test_fsid (path.dentry, &__fsid); +if (ret) + goto path_put_and_out; + + ret =fanotify_test_fid (path.dentry);if (ret) goto path_put_and_out;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 367/770 inotify: Dont force FS_IN_IGNORED
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit e0462f91d24756916fded4313d508e0fc52f39c9 ]
According to Amir:
"FS_IN_IGNORED is completely internal to inotify and there is no need to set it in i_fsnotify_mask at all, so if we remove the bit from the output of inotify_arg_to_mask() no functionality will change and we will be able to overload the event bit for FS_ERROR."
This is done in preparation to overload FS_ERROR with the notification mechanism in fanotify.
--- fs/notify/inotify/inotify_user.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/notify/inotify/inotify_user.c +3 -3
@@ -89,10 +89,10 @@ static inline __u32 inotify_arg_to_mask(struct inode *inode, u32 arg)__u32 mask;/* -* Everything should accept their own ignored and should receive events -* when the inode is unmounted. All directories care about children. +* Everything should receive events when the inode is unmounted. +* All directories care about children. */ - mask = (FS_IN_IGNORED |FS_UNMOUNT ); + mask = (FS_UNMOUNT );if (S_ISDIR (inode->i_mode)) mask |=FS_EVENT_ON_CHILD ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 368/770 fsnotify: Add helper to detect overflow_event
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 808967a0a4d2f4ce6a2005c5692fffbecaf018c1 ]
Similarly to fanotify_is_perm_event and friends, provide a helper predicate to say whether a mask is of an overflow event.
--- fs/notify/fanotify/fanotify.h | 3 ++- include/linux/fsnotify_backend.h | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-)
fs/notify/fanotify/fanotify.h +2 -1
@@ -315,7 +315,8 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event)*/ static inline bool fanotify_is_hashed_event (u32 mask) { -return !fanotify_is_perm_event (mask) && !(mask &FS_Q_OVERFLOW ); +return !(fanotify_is_perm_event (mask) || +fsnotify_is_overflow_event (mask)); } static inline unsigned int fanotify_event_hash_bucket(
include/linux/fsnotify_backend.h +5 -0
@@ -510,6 +510,11 @@ static inline void fsnotify_queue_overflow(struct fsnotify_group *group)fsnotify_add_event (group, group->overflow_event,NULL ,NULL ); } +static inline bool fsnotify_is_overflow_event (u32 mask) +{ +return mask &FS_Q_OVERFLOW ; +} +static inline bool fsnotify_notify_queue_is_empty (struct fsnotify_group *group) {assert_spin_locked (&group->notification_lock);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 369/770 fsnotify: Add wrapper around fsnotify_add_event
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 1ad03c3a326a86e259389592117252c851873395 ]
fsnotify_add_event is growing in number of parameters, which in most case are just passed a NULL pointer. So, split out a new fsnotify_insert_event function to clean things up for users who don't need an insert hook.
--- fs/notify/fanotify/fanotify.c | 4 ++-- fs/notify/inotify/inotify_fsnotify.c | 2 +- fs/notify/notification.c | 12 ++++++------ include/linux/fsnotify_backend.h | 23 ++++++++++++++++------- 4 files changed, 25 insertions(+), 16 deletions(-)
fs/notify/fanotify/fanotify.c +2 -2
@@ -781,8 +781,8 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, } fsn_event = &event->fse; - ret =fsnotify_add_event (group, fsn_event, fanotify_merge, - fanotify_insert_event); + ret =fsnotify_insert_event (group, fsn_event, fanotify_merge, + fanotify_insert_event);if (ret) {/* Permission events shouldn't be merged */ BUG_ON (ret ==1 && mask &FANOTIFY_PERM_EVENTS );
fs/notify/inotify/inotify_fsnotify.c +1 -1
@@ -123,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,NULL ); + ret =fsnotify_add_event (group, fsn_event, inotify_merge);if (ret) {/* Our event wasn't used in the end. Free it. */ fsnotify_destroy_event (group, fsn_event);
fs/notify/notification.c +6 -6
@@ -78,12 +78,12 @@ void fsnotify_destroy_event(struct fsnotify_group *group,* 2 if the event was not queued - either the queue of events has overflown * or the group is shutting down. */ -int fsnotify_add_event (struct fsnotify_group *group, -struct fsnotify_event *event, -int (*merge)(struct fsnotify_group *, -struct fsnotify_event *), -void (*insert)(struct fsnotify_group *, -struct fsnotify_event *)) +int fsnotify_insert_event (struct fsnotify_group *group, +struct fsnotify_event *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;
include/linux/fsnotify_backend.h +16 -7
@@ -498,16 +498,25 @@ extern int fsnotify_fasync(int fd, struct file *file, int on);extern void fsnotify_destroy_event (struct fsnotify_group *group,struct fsnotify_event *event);/* attach the event to the group notification queue */ -extern int fsnotify_add_event (struct fsnotify_group *group, -struct fsnotify_event *event, -int (*merge)(struct fsnotify_group *, -struct fsnotify_event *), -void (*insert)(struct fsnotify_group *, -struct fsnotify_event *)); +extern int fsnotify_insert_event (struct fsnotify_group *group, +struct fsnotify_event *event, +int (*merge)(struct fsnotify_group *, +struct fsnotify_event *), +void (*insert)(struct fsnotify_group *, +struct fsnotify_event *)); + +static inline int fsnotify_add_event (struct fsnotify_group *group, +struct fsnotify_event *event, +int (*merge)(struct fsnotify_group *, +struct fsnotify_event *)) +{ +return fsnotify_insert_event (group, event, merge,NULL ); +} +/* 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 ,NULL ); +fsnotify_add_event (group, group->overflow_event,NULL ); }static inline bool fsnotify_is_overflow_event (u32 mask)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 370/770 fsnotify: Retrieve super block from the data field
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 29335033c574a15334015d8c4e36862cff3d3384 ]
Some file system events (i.e. FS_ERROR) might not be associated with an inode or directory. For these, we can retrieve the super block from the data field. But, since the super_block is available in the data field on every event type, simplify the code to always retrieve it from there, through a new helper.
--- fs/notify/fsnotify.c | 7 +++---- include/linux/fsnotify_backend.h | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-)
fs/notify/fsnotify.c +3 -4
@@ -455,16 +455,16 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)* @file_name is relative to * @file_name: optional file name associated with event * @inode: optional inode associated with event - -* either @dir or @inode must be non-NULL. -* if both are non-NULL event may be reported to both. +* If @dir and @inode are both non-NULL, event may be +* reported to both. * @cookie: inotify rename cookie */ int fsnotify (__u32 mask,const void *data,int data_type,struct inode *dir,const struct qstr *file_name,struct inode *inode,u32 cookie) {const struct path *path =fsnotify_data_path (data, data_type); +struct super_block *sb =fsnotify_data_sb (data, data_type);struct fsnotify_iter_info iter_info = {}; -struct super_block *sb;struct mount *mnt =NULL ;struct inode *parent =NULL ;int ret =0 ;
@@ -483,7 +483,6 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,*/ parent = dir; } - sb = inode->i_sb;/* * Optimization: srcu_read_lock() has a memory barrier which can
include/linux/fsnotify_backend.h +15 -0
@@ -289,6 +289,21 @@ static inline const struct path *fsnotify_data_path(const void *data, } } +static inline struct super_block *fsnotify_data_sb (const void *data, +int data_type) +{ +switch (data_type) { +case FSNOTIFY_EVENT_INODE : +return ((struct inode *)data)->i_sb; +case FSNOTIFY_EVENT_DENTRY : +return ((struct dentry *)data)->d_sb; +case FSNOTIFY_EVENT_PATH : +return ((const struct path *)data)->dentry->d_sb; +default : +return NULL ; + } +} +enum fsnotify_obj_type {FSNOTIFY_OBJ_TYPE_INODE ,FSNOTIFY_OBJ_TYPE_PARENT ,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 371/770 fsnotify: Protect fsnotify_handle_inode_event from no-inode events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 24dca90590509a7a6cbe0650100c90c5b8a3468a ]
FAN_FS_ERROR allows events without inodes - i.e. for file system-wide errors. Even though fsnotify_handle_inode_event is not currently used by fanotify, this patch protects other backends from cases where neither inode or dir are provided. Also document the constraints of the interface (inode and dir cannot be both NULL).
--- fs/nfsd/filecache.c | 3 +++ fs/notify/fsnotify.c | 3 +++ include/linux/fsnotify_backend.h | 1 + 3 files changed, 7 insertions(+)
fs/nfsd/filecache.c +3 -0
@@ -601,6 +601,9 @@ nfsd_file_fsnotify_handle_event(struct fsnotify_mark *mark, u32 mask, struct inode *inode, struct inode *dir, const struct qstr *name, u32 cookie) { + if (WARN_ON_ONCE(!inode)) + return 0; + trace_nfsd_file_fsnotify_handle_event(inode, mask);/* Should be no marks on non-regular files */
fs/notify/fsnotify.c +3 -0
@@ -252,6 +252,9 @@ static int fsnotify_handle_inode_event(struct fsnotify_group *group,if (WARN_ON_ONCE (!ops->handle_inode_event))return 0 ; +if (WARN_ON_ONCE (!inode && !dir)) +return 0 ; +if ((inode_mark->mask &FS_EXCL_UNLINK ) && path &&d_unlinked (path->dentry))return 0 ;
include/linux/fsnotify_backend.h +1 -0
@@ -136,6 +136,7 @@ struct mem_cgroup;* @dir: optional directory associated with event - * if @file_name is not NULL, this is the directory that * @file_name is relative to. +* Either @inode or @dir must be non-NULL. * @file_name: optional file name associated with event * @cookie: inotify rename cookie *
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 372/770 fsnotify: Pass group argument to free_event
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 330ae77d2a5b0af32c0f29e139bf28ec8591de59 ]
For group-wide mempool backed events, like FS_ERROR, the free_event callback will need to reference the group's mempool to free the memory. Wire that argument into the current callers.
--- fs/notify/fanotify/fanotify.c | 3 ++- fs/notify/group.c | 2 +- fs/notify/inotify/inotify_fsnotify.c | 3 ++- fs/notify/notification.c | 2 +- include/linux/fsnotify_backend.h | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-)
fs/notify/fanotify/fanotify.c +2 -1
@@ -835,7 +835,8 @@ static void fanotify_free_name_event(struct fanotify_event *event)kfree (FANOTIFY_NE (event)); } -static void fanotify_free_event (struct fsnotify_event *fsn_event) +static void fanotify_free_event (struct fsnotify_group *group, +struct fsnotify_event *fsn_event) {struct fanotify_event *event;
fs/notify/group.c +1 -1
@@ -88,7 +88,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)* that deliberately ignores overflow events. */ if (group->overflow_event) - group->ops->free_event (group->overflow_event); + group->ops->free_event (group, group->overflow_event);fsnotify_put_group (group); }
fs/notify/inotify/inotify_fsnotify.c +2 -1
@@ -184,7 +184,8 @@ static void inotify_free_group_priv(struct fsnotify_group *group)dec_inotify_instances (group->inotify_data.ucounts); } -static void inotify_free_event (struct fsnotify_event *fsn_event) +static void inotify_free_event (struct fsnotify_group *group, +struct fsnotify_event *fsn_event) {kfree (INOTIFY_E (fsn_event)); }
fs/notify/notification.c +1 -1
@@ -64,7 +64,7 @@ void fsnotify_destroy_event(struct fsnotify_group *group,WARN_ON (!list_empty (&event->list));spin_unlock (&group->notification_lock); } - group->ops->free_event (event); + group->ops->free_event (group, event); }/*
include/linux/fsnotify_backend.h +1 -1
@@ -156,7 +156,7 @@ struct fsnotify_ops { const struct qstr *file_name, u32 cookie);void (*free_group_priv)(struct fsnotify_group *group);void (*freeing_mark)(struct fsnotify_mark *mark,struct fsnotify_group *group); -void (*free_event)(struct fsnotify_event *event); +void (*free_event)(struct fsnotify_group *group,struct fsnotify_event *event);/* called on final put+free to free memory */ void (*free_mark)(struct fsnotify_mark *mark); };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 373/770 fanotify: Support null inode event in fanotify_dfid_inode
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 12f47bf0f0990933d95d021d13d31bda010648fd ]
FAN_FS_ERROR doesn't support DFID, but this function is still called for every event. The problem is that it is not capable of handling null inodes, which now can happen in case of superblock error events. For this case, just returning dir will be enough.
--- fs/notify/fanotify/fanotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/notify/fanotify/fanotify.c +1 -1
@@ -452,7 +452,7 @@ static struct inode *fanotify_dfid_inode(u32 event_mask, const void *data,if (event_mask &ALL_FSNOTIFY_DIRENT_EVENTS )return dir; -if (S_ISDIR (inode->i_mode)) +if (inode &&S_ISDIR (inode->i_mode))return inode;return dir;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 374/770 fanotify: Allow file handle encoding for unhashed events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 74fe4734897a2da2ae2a665a5e622cd490d36eaf ]
Allow passing a NULL hash to fanotify_encode_fh and avoid calculating the hash if not needed.
--- fs/notify/fanotify/fanotify.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
fs/notify/fanotify/fanotify.c +6 -2
@@ -403,8 +403,12 @@ 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); +/* +* Mix fh into event merge key. Hash might be NULL in case of +* unhashed FID events (i.e. FAN_FS_ERROR). +*/ +if (hash) + *hash ^=fanotify_hash_fh (fh);return FANOTIFY_FH_HDR_LEN + fh_len;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 375/770 fanotify: Encode empty file handle when no inode is provided
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 272531ac619b374ab474e989eb387162fded553f ]
Instead of failing, encode an invalid file handle in fanotify_encode_fh if no inode is provided. This bogus file handle will be reported by FAN_FS_ERROR for non-inode errors.
--- fs/notify/fanotify/fanotify.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
fs/notify/fanotify/fanotify.c +8 -1
@@ -370,8 +370,14 @@ static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, fh->type =FILEID_ROOT ; fh->len =0 ; fh->flags =0 ; + +/* +* Invalid FHs are used by FAN_FS_ERROR for errors not +* linked to any inode. The f_handle won't be reported +* back to userspace. +*/ if (!inode) -return 0 ; + goto out;/* * !gpf means preallocated variable size fh, but fh_len could
@@ -403,6 +409,7 @@ static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, fh->type = type; fh->len = fh_len; +out:/* * Mix fh into event merge key. Hash might be NULL in case of * unhashed FID events (i.e. FAN_FS_ERROR).
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 376/770 fanotify: Require fid_mode for any non-fd event
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 4fe595cf1c80e7a5af4d00c4da29def64aff57a2 ]
Like inode events, FAN_FS_ERROR will require fid mode. Therefore, convert the verification during fanotify_mark(2) to require fid for any non-fd event. This means fid_mode will not only be required for inode events, but for any event that doesn't provide a descriptor.
--- fs/notify/fanotify/fanotify_user.c | 12 ++++++------ include/linux/fanotify.h | 3 +++ 2 files changed, 9 insertions(+), 6 deletions(-)
fs/notify/fanotify/fanotify_user.c +6 -6
@@ -1471,14 +1471,14 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, goto fput_and_out;/* -* Events with data type inode do not carry enough information to report -* event->fd, so we do not allow setting a mask for inode events unless -* group supports reporting fid. -* inode events are not supported on a mount mark, because they do not -* carry enough information (i.e. path) to be filtered by mount point. +* Events that do not carry enough information to report +* event->fd require a group that supports reporting fid. Those +* events are not supported on a mount mark, because they do not +* carry enough information (i.e. path) to be filtered by mount +* point. */ fid_mode =FAN_GROUP_FLAG (group,FANOTIFY_FID_BITS ); -if (mask &FANOTIFY_INODE_EVENTS && +if (mask & ~(FANOTIFY_FD_EVENTS |FANOTIFY_EVENT_FLAGS ) && (!fid_mode || mark_type ==FAN_MARK_MOUNT )) goto fput_and_out;
include/linux/fanotify.h +3 -0
@@ -84,6 +84,9 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */*/ #define FANOTIFY_DIRENT_EVENTS (FAN_MOVE | FAN_CREATE | FAN_DELETE) +/* Events that can be reported with event->fd */ +#define FANOTIFY_FD_EVENTS (FANOTIFY_PATH_EVENTS | FANOTIFY_PERM_EVENTS) +/* Events that can only be reported with data type FSNOTIFY_EVENT_INODE */ #define FANOTIFY_INODE_EVENTS (FANOTIFY_DIRENT_EVENTS | \ FAN_ATTRIB | FAN_MOVE_SELF | FAN_DELETE_SELF)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 377/770 fsnotify: Support FS_ERROR event type
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 9daa811073fa19c08e8aad3b90f9235fed161acf ]
Expose a new type of fsnotify event for filesystems to report errors for userspace monitoring tools. fanotify will send this type of notification for FAN_FS_ERROR events. This also introduce a helper for generating the new event.
--- include/linux/fsnotify.h | 13 +++++++++++++ include/linux/fsnotify_backend.h | 32 +++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-)
include/linux/fsnotify.h +13 -0
@@ -376,4 +376,17 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) fsnotify_dentry(dentry, mask); } +static inline int fsnotify_sb_error (struct super_block *sb,struct inode *inode, +int error) +{ +struct fs_error_report report = { + .error = error, + .inode = inode, + .sb = sb, + }; + +return fsnotify (FS_ERROR , &report,FSNOTIFY_EVENT_ERROR , +NULL ,NULL ,NULL ,0 ); +} +#endif /* _LINUX_FS_NOTIFY_H */
include/linux/fsnotify_backend.h +31 -1
@@ -42,6 +42,12 @@#define FS_UNMOUNT 0x00002000/* inode on umount fs */ #define FS_Q_OVERFLOW 0x00004000/* Event queued overflowed */ +#define FS_ERROR 0x00008000/* Filesystem Error (fanotify) */ + +/* +* FS_IN_IGNORED overloads FS_ERROR. It is only used internally by inotify +* which does not support FS_ERROR. +*/ #define FS_IN_IGNORED 0x00008000/* last inotify event here */ #define FS_OPEN_PERM 0x00010000/* open event in an permission hook */
@@ -95,7 +101,8 @@#define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \ FS_EVENTS_POSS_ON_CHILD | \ FS_DELETE_SELF | FS_MOVE_SELF | FS_DN_RENAME | \ - FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED) + FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ + FS_ERROR)/* Extra flags that may be reported with event or control handling of events */ #define ALL_FSNOTIFY_FLAGS (FS_EXCL_UNLINK | FS_ISDIR | FS_IN_ONESHOT | \
@@ -250,6 +257,13 @@ enum fsnotify_data_type {FSNOTIFY_EVENT_PATH ,FSNOTIFY_EVENT_INODE ,FSNOTIFY_EVENT_DENTRY , + FSNOTIFY_EVENT_ERROR, +}; + +struct fs_error_report { +int error; +struct inode *inode; +struct super_block *sb; };static inline struct inode *fsnotify_data_inode (const void *data,int data_type)
@@ -261,6 +275,8 @@ static inline struct inode *fsnotify_data_inode(const void *data, int data_type)return d_inode (data);case FSNOTIFY_EVENT_PATH :return d_inode (((const struct path *)data)->dentry); +case FSNOTIFY_EVENT_ERROR : +return ((struct fs_error_report *)data)->inode;default :return NULL ; }
@@ -300,6 +316,20 @@ static inline struct super_block *fsnotify_data_sb(const void *data,return ((struct dentry *)data)->d_sb;case FSNOTIFY_EVENT_PATH :return ((const struct path *)data)->dentry->d_sb; +case FSNOTIFY_EVENT_ERROR : +return ((struct fs_error_report *) data)->sb; +default : +return NULL ; + } +} + +static inline struct fs_error_report *fsnotify_data_error_report ( +const void *data, +int data_type) +{ +switch (data_type) { +case FSNOTIFY_EVENT_ERROR : +return (struct fs_error_report *) data;default :return NULL ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 378/770 fanotify: Reserve UAPI bits for FAN_FS_ERROR
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 8d11a4f43ef4679be0908026907a7613b33d7127 ]
FAN_FS_ERROR allows reporting of event type FS_ERROR to userspace, which is a mechanism to report file system wide problems via fanotify. This commit preallocate userspace visible bits to match the FS_ERROR event.
--- fs/notify/fanotify/fanotify.c | 1 + include/uapi/linux/fanotify.h | 1 + 2 files changed, 2 insertions(+)
fs/notify/fanotify/fanotify.c +1 -0
@@ -752,6 +752,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,BUILD_BUG_ON (FAN_ONDIR !=FS_ISDIR );BUILD_BUG_ON (FAN_OPEN_EXEC !=FS_OPEN_EXEC );BUILD_BUG_ON (FAN_OPEN_EXEC_PERM !=FS_OPEN_EXEC_PERM ); +BUILD_BUG_ON (FAN_FS_ERROR !=FS_ERROR );BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) !=19 );
include/uapi/linux/fanotify.h +1 -0
@@ -20,6 +20,7 @@#define FAN_OPEN_EXEC 0x00001000/* File was opened for exec */ #define FAN_Q_OVERFLOW 0x00004000/* Event queued overflowed */ +#define FAN_FS_ERROR 0x00008000/* Filesystem error */ #define FAN_OPEN_PERM 0x00010000/* File open in perm check */ #define FAN_ACCESS_PERM 0x00020000/* File accessed in perm check */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 379/770 fanotify: Pre-allocate pool of error events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 734a1a5eccc5f7473002b0669f788e135f1f64aa ]
Pre-allocate slots for file system errors to have greater chances of succeeding, since error events can happen in GFP_NOFS context. This patch introduces a group-wide mempool of error events, shared by all FAN_FS_ERROR marks in this group.
--- fs/notify/fanotify/fanotify.c | 3 +++ fs/notify/fanotify/fanotify.h | 11 +++++++++++ fs/notify/fanotify/fanotify_user.c | 26 +++++++++++++++++++++++++- include/linux/fsnotify_backend.h | 2 ++ 4 files changed, 41 insertions(+), 1 deletion(-)
fs/notify/fanotify/fanotify.c +3 -0
@@ -819,6 +819,9 @@ static void fanotify_free_group_priv(struct fsnotify_group *group)if (group->fanotify_data.ucounts)dec_ucount (group->fanotify_data.ucounts,UCOUNT_FANOTIFY_GROUPS ); + +if (mempool_initialized (&group->fanotify_data.error_events_pool)) +mempool_exit (&group->fanotify_data.error_events_pool); }static void fanotify_free_path_event (struct fanotify_event *event)
fs/notify/fanotify/fanotify.h +11 -0
@@ -141,6 +141,7 @@ enum fanotify_event_type {FANOTIFY_EVENT_TYPE_PATH ,FANOTIFY_EVENT_TYPE_PATH_PERM ,FANOTIFY_EVENT_TYPE_OVERFLOW ,/* struct fanotify_event */ +FANOTIFY_EVENT_TYPE_FS_ERROR ,/* struct fanotify_error_event */ __FANOTIFY_EVENT_TYPE_NUM };
@@ -196,6 +197,16 @@ FANOTIFY_NE(struct fanotify_event *event) return container_of(event, struct fanotify_name_event, fae); } +struct fanotify_error_event { +struct fanotify_event fae; +}; + +static inline struct fanotify_error_event * +FANOTIFY_EE (struct fanotify_event *event) +{ + return container_of(event, struct fanotify_error_event, fae); +} +static inline __kernel_fsid_t *fanotify_event_fsid (struct fanotify_event *event) {if (event->type ==FANOTIFY_EVENT_TYPE_FID )
fs/notify/fanotify/fanotify_user.c +25 -1
@@ -30,6 +30,7 @@#define FANOTIFY_DEFAULT_MAX_EVENTS 16384#define FANOTIFY_OLD_DEFAULT_MAX_MARKS 8192#define FANOTIFY_DEFAULT_MAX_GROUPS 128 +#define FANOTIFY_DEFAULT_FEE_POOL_SIZE 32/* * Legacy fanotify marks limits (8192) is per group and we introduced a tunable
@@ -1049,6 +1050,15 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,return ERR_PTR (ret); } +static int fanotify_group_init_error_pool (struct fsnotify_group *group) +{ +if (mempool_initialized (&group->fanotify_data.error_events_pool)) +return 0 ; + +return mempool_init_kmalloc_pool (&group->fanotify_data.error_events_pool, +FANOTIFY_DEFAULT_FEE_POOL_SIZE , +sizeof (struct fanotify_error_event )); +} static int fanotify_add_mark(struct fsnotify_group *group, fsnotify_connp_t *connp, unsigned int type,
@@ -1057,6 +1067,7 @@ static int fanotify_add_mark(struct fsnotify_group *group, {struct fsnotify_mark *fsn_mark;__u32 added; +int ret =0 ;mutex_lock (&group->mark_mutex); fsn_mark =fsnotify_find_mark (connp, group);
@@ -1067,13 +1078,26 @@ static int fanotify_add_mark(struct fsnotify_group *group,return PTR_ERR (fsn_mark); } } + +/* +* Error events are pre-allocated per group, only if strictly +* needed (i.e. FAN_FS_ERROR was requested). +*/ +if (!(flags &FAN_MARK_IGNORED_MASK ) && (mask &FAN_FS_ERROR )) { + ret =fanotify_group_init_error_pool (group); +if (ret) + goto out; + } + added =fanotify_mark_add_to_mask (fsn_mark, mask, flags);if (added & ~fsnotify_conn_mask (fsn_mark->connector))fsnotify_recalc_mask (fsn_mark->connector); + +out:mutex_unlock (&group->mark_mutex);fsnotify_put_mark (fsn_mark); -return 0 ; +return ret; } static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
include/linux/fsnotify_backend.h +2 -0
@@ -19,6 +19,7 @@#include <linux/atomic.h> #include <linux/user_namespace.h> #include <linux/refcount.h> +#include <linux/mempool.h> /* * IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
@@ -246,6 +247,7 @@ struct fsnotify_group {int flags;/* flags from fanotify_init() */ int f_flags;/* event_f_flags from fanotify_init() */ struct ucounts *ucounts; + mempool_t error_events_pool; } fanotify_data;#endif /* CONFIG_FANOTIFY */ };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 380/770 fanotify: Support enqueueing of error events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 83e9acbe13dc1b767f91b5c1350f7a65689b26f6 ]
Once an error event is triggered, enqueue it in the notification group, similarly to what is done for other events. FAN_FS_ERROR is not handled specially, since the memory is now handled by a preallocated mempool.
For now, make the event unhashed. A future patch implements merging of this kind of event.
--- fs/notify/fanotify/fanotify.c | 35 +++++++++++++++++++++++++++++++++++ fs/notify/fanotify/fanotify.h | 6 ++++++ 2 files changed, 41 insertions(+)
fs/notify/fanotify/fanotify.c +35 -0
@@ -574,6 +574,27 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,return &fne->fae; } +static struct fanotify_event *fanotify_alloc_error_event ( +struct fsnotify_group *group, +__kernel_fsid_t *fsid, +const void *data,int data_type) +{ +struct fs_error_report *report = +fsnotify_data_error_report (data, data_type); +struct fanotify_error_event *fee; + +if (WARN_ON_ONCE (!report)) +return NULL ; + + fee =mempool_alloc (&group->fanotify_data.error_events_pool,GFP_NOFS ); +if (!fee) +return NULL ; + + fee->fae.type =FANOTIFY_EVENT_TYPE_FS_ERROR ; + +return &fee->fae; +} + static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, u32 mask, const void *data, int data_type, struct inode *dir,
@@ -641,6 +662,9 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,if (fanotify_is_perm_event (mask)) { event =fanotify_alloc_perm_event (path, gfp); + }else if (fanotify_is_error_event (mask)) { + event =fanotify_alloc_error_event (group, fsid, data, + data_type); }else if (name_event && (file_name || child)) { event =fanotify_alloc_name_event (id, fsid, file_name, child, &hash, gfp);
@@ -850,6 +874,14 @@ static void fanotify_free_name_event(struct fanotify_event *event)kfree (FANOTIFY_NE (event)); } +static void fanotify_free_error_event (struct fsnotify_group *group, +struct fanotify_event *event) +{ +struct fanotify_error_event *fee =FANOTIFY_EE (event); + +mempool_free (fee, &group->fanotify_data.error_events_pool); +} +static void fanotify_free_event (struct fsnotify_group *group,struct fsnotify_event *fsn_event) {
@@ -873,6 +905,9 @@ static void fanotify_free_event(struct fsnotify_group *group,case FANOTIFY_EVENT_TYPE_OVERFLOW :kfree (event);break ; +case FANOTIFY_EVENT_TYPE_FS_ERROR : +fanotify_free_error_event (group, event); +break ;default :WARN_ON_ONCE (1 ); }
fs/notify/fanotify/fanotify.h +6 -0
@@ -298,6 +298,11 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse) return container_of(fse, struct fanotify_event, fse); } +static inline bool fanotify_is_error_event (u32 mask) +{ +return mask &FAN_FS_ERROR ; +} +static inline bool fanotify_event_has_path (struct fanotify_event *event) { return event->type == FANOTIFY_EVENT_TYPE_PATH ||
@@ -327,6 +332,7 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event)static inline bool fanotify_is_hashed_event (u32 mask) {return !(fanotify_is_perm_event (mask) || +fanotify_is_error_event (mask) ||fsnotify_is_overflow_event (mask)); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 381/770 fanotify: Support merging of error events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 8a6ae64132fd27a944faed7bc38484827609eb76 ]
Error events (FAN_FS_ERROR) against the same file system can be merged by simply iterating the error count. The hash is taken from the fsid, without considering the FH. This means that only the first error object is reported.
--- fs/notify/fanotify/fanotify.c | 26 ++++++++++++++++++++++++-- fs/notify/fanotify/fanotify.h | 4 +++- 2 files changed, 27 insertions(+), 3 deletions(-)
fs/notify/fanotify/fanotify.c +24 -2
@@ -111,6 +111,16 @@ static bool fanotify_name_event_equal(struct fanotify_name_event *fne1,return fanotify_info_equal (info1, info2); } +static bool fanotify_error_event_equal (struct fanotify_error_event *fee1, +struct fanotify_error_event *fee2) +{ +/* Error events against the same file system are always merged. */ +if (!fanotify_fsid_equal (&fee1->fsid, &fee2->fsid)) +return false; + +return true; +} +static bool fanotify_should_merge (struct fanotify_event *old,struct fanotify_event *new) {
@@ -141,6 +151,9 @@ static bool fanotify_should_merge(struct fanotify_event *old,case FANOTIFY_EVENT_TYPE_FID_NAME :return fanotify_name_event_equal (FANOTIFY_NE (old),FANOTIFY_NE (new)); +case FANOTIFY_EVENT_TYPE_FS_ERROR : +return fanotify_error_event_equal (FANOTIFY_EE (old), +FANOTIFY_EE (new));default :WARN_ON_ONCE (1 ); }
@@ -176,6 +189,10 @@ static int fanotify_merge(struct fsnotify_group *group,break ;if (fanotify_should_merge (old, new)) { old->mask |= new->mask; + +if (fanotify_is_error_event (old->mask)) +FANOTIFY_EE (old)->err_count++; +return 1 ; } }
@@ -577,7 +594,8 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,static struct fanotify_event *fanotify_alloc_error_event (struct fsnotify_group *group,__kernel_fsid_t *fsid, -const void *data,int data_type) +const void *data,int data_type, +unsigned int *hash) {struct fs_error_report *report =fsnotify_data_error_report (data, data_type);
@@ -591,6 +609,10 @@ static struct fanotify_event *fanotify_alloc_error_event(return NULL ; fee->fae.type =FANOTIFY_EVENT_TYPE_FS_ERROR ; + fee->err_count =1 ; + fee->fsid = *fsid; + + *hash ^=fanotify_hash_fsid (fsid);return &fee->fae; }
@@ -664,7 +686,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, event =fanotify_alloc_perm_event (path, gfp); }else if (fanotify_is_error_event (mask)) { event =fanotify_alloc_error_event (group, fsid, data, - data_type); + data_type, &hash); }else if (name_event && (file_name || child)) { event =fanotify_alloc_name_event (id, fsid, file_name, child, &hash, gfp);
fs/notify/fanotify/fanotify.h +3 -1
@@ -199,6 +199,9 @@ FANOTIFY_NE(struct fanotify_event *event)struct fanotify_error_event {struct fanotify_event fae; +u32 err_count;/* Suppressed errors count */ + +__kernel_fsid_t fsid;/* FSID this error refers to. */ }; static inline struct fanotify_error_event *
@@ -332,7 +335,6 @@ static inline struct path *fanotify_event_path(struct fanotify_event *event)static inline bool fanotify_is_hashed_event (u32 mask) {return !(fanotify_is_perm_event (mask) || -fanotify_is_error_event (mask) ||fsnotify_is_overflow_event (mask)); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 382/770 fanotify: Wrap object_fh inline space in a creator macro
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 2c5069433a3adc01ff9c5673567961bb7f138074 ]
fanotify_error_event would duplicate this sequence of declarations that already exist elsewhere with a slight different size. Create a helper macro to avoid code duplication.
--- fs/notify/fanotify/fanotify.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
fs/notify/fanotify/fanotify.h +9 -3
@@ -171,12 +171,18 @@ static inline void fanotify_init_event(struct fanotify_event *event, event->pid =NULL ; } +#define FANOTIFY_INLINE_FH (name, size) \ +struct { \ + struct fanotify_fh (name); \ +/* Space for object_fh.buf[] - access with fanotify_fh_buf() */ \ +unsigned char _inline_fh_buf[(size)]; \ +} +struct fanotify_fid_event {struct fanotify_event fae;__kernel_fsid_t fsid; -struct fanotify_fh object_fh; -/* Reserve space in object_fh.buf[] - access with fanotify_fh_buf() */ -unsigned char _inline_fh_buf[FANOTIFY_INLINE_FH_LEN ]; + + FANOTIFY_INLINE_FH(object_fh, FANOTIFY_INLINE_FH_LEN); }; static inline struct fanotify_fid_event *
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 383/770 fanotify: Add helpers to decide whether to report FID/DFID
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 4bd5a5c8e6e5cd964e9738e6ef87f6c2cb453edf ]
Now that there is an event that reports FID records even for a zeroed file handle, wrap the logic that deides whether to issue the records into helper functions. This shouldn't have any impact on the code, but simplifies further patches.
--- fs/notify/fanotify/fanotify.h | 10 ++++++++++ fs/notify/fanotify/fanotify_user.c | 13 +++++++------ 2 files changed, 17 insertions(+), 6 deletions(-)
fs/notify/fanotify/fanotify.h +10 -0
@@ -264,6 +264,16 @@ static inline int fanotify_event_dir_fh_len(struct fanotify_event *event)return info ?fanotify_info_dir_fh_len (info) :0 ; } +static inline bool fanotify_event_has_object_fh (struct fanotify_event *event) +{ +return fanotify_event_object_fh_len (event) >0 ; +} + +static inline bool fanotify_event_has_dir_fh (struct fanotify_event *event) +{ +return fanotify_event_dir_fh_len (event) >0 ; +} +struct fanotify_path_event {struct fanotify_event fae;struct path path;
fs/notify/fanotify/fanotify_user.c +7 -6
@@ -135,10 +135,9 @@ static size_t fanotify_event_len(unsigned int info_mode,return event_len; info =fanotify_event_info (event); - dir_fh_len =fanotify_event_dir_fh_len (event); - fh_len =fanotify_event_object_fh_len (event); -if (dir_fh_len) { +if (fanotify_event_has_dir_fh (event)) { + dir_fh_len =fanotify_event_dir_fh_len (event); event_len +=fanotify_fid_info_len (dir_fh_len, info->name_len); }else if ((info_mode &FAN_REPORT_NAME ) && (event->mask &FAN_ONDIR )) {
@@ -152,8 +151,10 @@ static size_t fanotify_event_len(unsigned int info_mode,if (info_mode &FAN_REPORT_PIDFD ) event_len +=FANOTIFY_PIDFD_INFO_HDR_LEN ; -if (fh_len) +if (fanotify_event_has_object_fh (event)) { + fh_len =fanotify_event_object_fh_len (event); event_len +=fanotify_fid_info_len (fh_len, dot_len); + }return event_len; }
@@ -446,7 +447,7 @@ static int copy_info_records_to_user(struct fanotify_event *event,/* * Event info records order is as follows: dir fid + name, child fid. */ -if (fanotify_event_dir_fh_len (event)) { +if (fanotify_event_has_dir_fh (event)) { info_type = info->name_len ?FAN_EVENT_INFO_TYPE_DFID_NAME :FAN_EVENT_INFO_TYPE_DFID ; ret = copy_fid_info_to_user(fanotify_event_fsid(event),
@@ -462,7 +463,7 @@ static int copy_info_records_to_user(struct fanotify_event *event, total_bytes += ret; } -if (fanotify_event_object_fh_len (event)) { +if (fanotify_event_has_object_fh (event)) {const char *dot =NULL ;int dot_len =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 384/770 fanotify: WARN_ON against too large file handles
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 572c28f27a269f88e2d8d7b6b1507f114d637337 ]
struct fanotify_error_event, at least, is preallocated and isn't able to to handle arbitrarily large file handles. Future-proof the code by complaining loudly if a handle larger than MAX_HANDLE_SZ is ever found.
--- fs/notify/fanotify/fanotify.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
fs/notify/fanotify/fanotify.c +11 -1
@@ -360,13 +360,23 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,static int fanotify_encode_fh_len (struct inode *inode) {int dwords =0 ; +int fh_len;if (!inode)return 0 ;exportfs_encode_inode_fh (inode,NULL , &dwords,NULL ); + fh_len = dwords <<2 ; -return dwords <<2 ; +/* +* struct fanotify_error_event might be preallocated and is +* limited to MAX_HANDLE_SZ. This should never happen, but +* safeguard by forcing an invalid file handle. +*/ +if (WARN_ON_ONCE (fh_len >MAX_HANDLE_SZ )) +return 0 ; + +return fh_len; }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 385/770 fanotify: Report fid info for file related file system errors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 936d6a38be39177495af38497bf8da1c6128fa1b ]
Plumb the pieces to add a FID report to error records. Since all error event memory must be pre-allocated, we pre-allocate the maximum file handle size possible, such that it should always fit.
For errors that don't expose a file handle, report it with an invalid FID. Internally we use zero-length FILEID_ROOT file handle for passing the information (which we report as zero-length FILEID_INVALID file handle to userspace) so we update the handle reporting code to deal with this case correctly.
--- fs/notify/fanotify/fanotify.c | 11 +++++++++++ fs/notify/fanotify/fanotify.h | 9 +++++++++ fs/notify/fanotify/fanotify_user.c | 8 +++++--- 3 files changed, 25 insertions(+), 3 deletions(-)
fs/notify/fanotify/fanotify.c +11 -0
@@ -609,7 +609,9 @@ static struct fanotify_event *fanotify_alloc_error_event( {struct fs_error_report *report =fsnotify_data_error_report (data, data_type); +struct inode *inode;struct fanotify_error_event *fee; +int fh_len;if (WARN_ON_ONCE (!report))return NULL ;
@@ -622,6 +624,15 @@ static struct fanotify_event *fanotify_alloc_error_event( fee->err_count =1 ; fee->fsid = *fsid; + inode = report->inode; + fh_len =fanotify_encode_fh_len (inode); + +/* Bad fh_len. Fallback to using an invalid fh. Should never happen. */ +if (!fh_len && inode) + inode =NULL ; + +fanotify_encode_fh (&fee->object_fh, inode, fh_len,NULL ,0 ); + *hash ^=fanotify_hash_fsid (fsid);return &fee->fae;
fs/notify/fanotify/fanotify.h +9 -0
@@ -208,6 +208,8 @@ struct fanotify_error_event {u32 err_count;/* Suppressed errors count */ __kernel_fsid_t fsid;/* FSID this error refers to. */ + +FANOTIFY_INLINE_FH (object_fh,MAX_HANDLE_SZ ); }; static inline struct fanotify_error_event *
@@ -222,6 +224,8 @@ static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event)return &FANOTIFY_FE (event)->fsid; else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) return &FANOTIFY_NE(event)->fsid; + else if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) + return &FANOTIFY_EE(event)->fsid; else return NULL; }
@@ -233,6 +237,8 @@ static inline struct fanotify_fh *fanotify_event_object_fh(return &FANOTIFY_FE (event)->object_fh; else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME) return fanotify_info_file_fh(&FANOTIFY_NE(event)->info); + else if (event->type == FANOTIFY_EVENT_TYPE_FS_ERROR) + return &FANOTIFY_EE(event)->object_fh; else return NULL; }
@@ -266,6 +272,9 @@ static inline int fanotify_event_dir_fh_len(struct fanotify_event *event)static inline bool fanotify_event_has_object_fh (struct fanotify_event *event) { +/* For error events, even zeroed fh are reported. */ +if (event->type ==FANOTIFY_EVENT_TYPE_FS_ERROR ) +return true;return fanotify_event_object_fh_len (event) >0 ; }
fs/notify/fanotify/fanotify_user.c +5 -3
@@ -334,9 +334,6 @@ static int copy_fid_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh,pr_debug ("%s: fh_len=%zu name_len=%zu, info_len=%zu, count=%zu\n" , __func__, fh_len, name_len, info_len, count); -if (!fh_len) -return 0 ; -if (WARN_ON_ONCE (len <sizeof (info) || len > count))return -EFAULT ;
@@ -371,6 +368,11 @@ static int copy_fid_info_to_user(__kernel_fsid_t *fsid, struct fanotify_fh *fh, handle.handle_type = fh->type; handle.handle_bytes = fh_len; + +/* Mangle handle_type for bad file_handle */ +if (!fh_len) + handle.handle_type =FILEID_INVALID ; +if (copy_to_user (buf, &handle,sizeof (handle)))return -EFAULT ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 386/770 fanotify: Emit generic error info for error event
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 130a3c742107acff985541c28360c8b40203559c ]
The error info is a record sent to users on FAN_FS_ERROR events documenting the type of error. It also carries an error count, documenting how many errors were observed since the last reporting.
--- fs/notify/fanotify/fanotify.c | 1 + fs/notify/fanotify/fanotify.h | 1 + fs/notify/fanotify/fanotify_user.c | 36 ++++++++++++++++++++++++++++++ include/uapi/linux/fanotify.h | 7 ++++++ 4 files changed, 45 insertions(+)
fs/notify/fanotify/fanotify.c +1 -0
@@ -621,6 +621,7 @@ static struct fanotify_event *fanotify_alloc_error_event(return NULL ; fee->fae.type =FANOTIFY_EVENT_TYPE_FS_ERROR ; + fee->error = report->error; fee->err_count =1 ; fee->fsid = *fsid;
fs/notify/fanotify/fanotify.h +1 -0
@@ -205,6 +205,7 @@ FANOTIFY_NE(struct fanotify_event *event)struct fanotify_error_event {struct fanotify_event fae; +s32 error;/* Error reported by the Filesystem. */ u32 err_count;/* Suppressed errors count */ __kernel_fsid_t fsid;/* FSID this error refers to. */
fs/notify/fanotify/fanotify_user.c +36 -0
@@ -110,6 +110,8 @@ struct kmem_cache *fanotify_perm_event_cachep __read_mostly; (sizeof(struct fanotify_event_info_fid) + sizeof(struct file_handle))#define FANOTIFY_PIDFD_INFO_HDR_LEN \ sizeof(struct fanotify_event_info_pidfd) +#define FANOTIFY_ERROR_INFO_LEN \ + (sizeof(struct fanotify_event_info_error))static int fanotify_fid_info_len (int fh_len,int name_len) {
@@ -134,6 +136,9 @@ static size_t fanotify_event_len(unsigned int info_mode,if (!info_mode)return event_len; +if (fanotify_is_error_event (event->mask)) + event_len +=FANOTIFY_ERROR_INFO_LEN ; + info =fanotify_event_info (event);if (fanotify_event_has_dir_fh (event)) {
@@ -319,6 +324,28 @@ static int process_access_response(struct fsnotify_group *group,return -ENOENT ; } +static size_t copy_error_info_to_user (struct fanotify_event *event, +char __user *buf,int count) +{ +struct fanotify_event_info_error info; +struct fanotify_error_event *fee =FANOTIFY_EE (event); + + info.hdr.info_type =FAN_EVENT_INFO_TYPE_ERROR ; + info.hdr.pad =0 ; + info.hdr.len =FANOTIFY_ERROR_INFO_LEN ; + +if (WARN_ON (count < info.hdr.len)) +return -EFAULT ; + + info.error = fee->error; + info.error_count = fee->err_count; + +if (copy_to_user (buf, &info,sizeof (info))) +return -EFAULT ; + +return info.hdr.len; +} + 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,
@@ -525,6 +552,15 @@ static int copy_info_records_to_user(struct fanotify_event *event, total_bytes += ret; } +if (fanotify_is_error_event (event->mask)) { + ret =copy_error_info_to_user (event, buf, count); +if (ret <0 ) +return ret; + buf += ret; + count -= ret; + total_bytes += ret; + } +return total_bytes; }
include/uapi/linux/fanotify.h +7 -0
@@ -126,6 +126,7 @@ struct fanotify_event_metadata {#define FAN_EVENT_INFO_TYPE_DFID_NAME 2#define FAN_EVENT_INFO_TYPE_DFID 3#define FAN_EVENT_INFO_TYPE_PIDFD 4 +#define FAN_EVENT_INFO_TYPE_ERROR 5/* Variable length info record following event metadata */ struct fanotify_event_info_header {
@@ -160,6 +161,12 @@ struct fanotify_event_info_pidfd {__s32 pidfd; }; +struct fanotify_event_info_error { +struct fanotify_event_info_header hdr; +__s32 error; +__u32 error_count; +}; +struct fanotify_response {__s32 fd;__u32 response;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 387/770 fanotify: Allow users to request FAN_FS_ERROR events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriel Krisman Bertazi <[email protected]>
[ Upstream commit 9709bd548f11a092d124698118013f66e1740f9b ]
Wire up the FAN_FS_ERROR event in the fanotify_mark syscall, allowing user space to request the monitoring of FAN_FS_ERROR events.
These events are limited to filesystem marks, so check it is the case in the syscall handler.
--- fs/notify/fanotify/fanotify.c | 2 +- fs/notify/fanotify/fanotify_user.c | 4 ++++ include/linux/fanotify.h | 6 +++++- 3 files changed, 10 insertions(+), 2 deletions(-)
fs/notify/fanotify/fanotify.c +1 -1
@@ -822,7 +822,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,BUILD_BUG_ON (FAN_OPEN_EXEC_PERM !=FS_OPEN_EXEC_PERM );BUILD_BUG_ON (FAN_FS_ERROR !=FS_ERROR ); -BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) !=19 ); +BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) !=20 ); mask =fanotify_group_event_mask (group, iter_info, mask, data, data_type, dir);
fs/notify/fanotify/fanotify_user.c +4 -0
@@ -1533,6 +1533,10 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, group->priority == FS_PRIO_0) goto fput_and_out; +if (mask &FAN_FS_ERROR && + mark_type !=FAN_MARK_FILESYSTEM ) + goto fput_and_out; +/* * Events that do not carry enough information to report * event->fd require a group that supports reporting fid. Those
include/linux/fanotify.h +5 -1
@@ -91,9 +91,13 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_INODE_EVENTS (FANOTIFY_DIRENT_EVENTS | \ FAN_ATTRIB | FAN_MOVE_SELF | FAN_DELETE_SELF) +/* Events that can only be reported with data type FSNOTIFY_EVENT_ERROR */ +#define FANOTIFY_ERROR_EVENTS (FAN_FS_ERROR) +/* Events that user can request to be notified on */ #define FANOTIFY_EVENTS (FANOTIFY_PATH_EVENTS | \ - FANOTIFY_INODE_EVENTS) + FANOTIFY_INODE_EVENTS | \ + FANOTIFY_ERROR_EVENTS)/* Events that require a permission response from user */ #define FANOTIFY_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM | \
Signature · 1 line
2.43.0
PATCH 387/770 fanotify: Allow users to request FAN_FS_ERROR events
Quoted 7 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without 9709bd548f11 in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF: FAN_FS_ERROR not supported in kernel
With 9709bd548f11 in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch
-Ajay
Amir Goldstein
reviewerRe: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
Quoted 22 lines · Ajay Kaher
Quoted 8 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305
Quoted 5 lines
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch-Ajay
I agree that this is the best approach, because the test has no other way to test
if ext4 specifically supports FAN_FS_ERROR.
Chuck,
I wonder how those patches end up in 5.15.y but not in 5.10.y?
Also, since you backported *most* of this series:
https://lore.kernel.org/all/[email protected]/
I think it would be wise to also backport the sample code and documentation patches to 5.15.y and 5.10.y.
9abeae5d4458 docs: Fix formatting of literal sections in fanotify docs 8fc70b3a142f samples: Make fs-monitor depend on libc and headers c0baf9ac0b05 docs: Document the FAN_FS_ERROR event 5451093081db samples: Add fs error monitoring example.
Gabriel, if 9abeae5d4458 has a Fixes: tag it may have been auto seleced for 5.15.y after c0baf9ac0b05 was picked up...
Thanks,
Amir.
Re: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
Quoted 33 lines · Amir Goldstein
Quoted 22 lines · Ajay Kaher
Quoted 8 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305Quoted 5 lines
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch-Ajay
Quoted 7 lines
I agree that this is the best approach, because the test has no other way to test
if ext4 specifically supportsFAN_FS_ERROR.Chuck,
I wonder how those patches end up in 5.15.y but not in 5.10.y?
The process was by hand. I tried to copy the same commit ID set from 5.15 to 5.10, but some patches did not apply to 5.10, or may have been omitted unintentionally.
Quoted 6 lines
Also, since you backported *most* of this series:
https://lore.kernel.org/all/[email protected]/I think it would be wise to also backport the sample code and documentation patches to 5.15.y and 5.10.y.
Quoted 7 lines
9abeae5d4458docs: Fix formatting of literal sections in fanotify docs8fc70b3a142fsamples: Make fs-monitor depend on libc and headersc0baf9ac0b05docs: Document theFAN_FS_ERRORevent5451093081dbsamples: Add fs error monitoring example.Gabriel, if
9abeae5d4458has a Fixes: tag it may have been auto seleced for 5.15.y afterc0baf9ac0b05was picked up...
Or this... I might not have backported those at all to 5.15, and they got pulled in by another process.
In any event, do you want me to backport these to 5.10, or would you like to do it yourself?
--
Chuck Lever
Amir Goldstein
reviewerRe: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
Quoted 59 lines · Chuck Lever III
Quoted 34 lines · Amir Goldstein
Quoted 22 lines · Ajay Kaher
Quoted 8 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305Quoted 5 lines
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch-Ajay
Quoted 7 lines
I agree that this is the best approach, because the test has no other way to test
if ext4 specifically supportsFAN_FS_ERROR.Chuck,
I wonder how those patches end up in 5.15.y but not in 5.10.y?
The process was by hand. I tried to copy the same commit ID set from 5.15 to 5.10, but some patches did not apply to 5.10, or may have been omitted unintentionally.
Quoted 11 lines
Also, since you backported *most* of this series:
https://lore.kernel.org/all/[email protected]/I think it would be wise to also backport the sample code and documentation patches to 5.15.y and 5.10.y.
9abeae5d4458docs: Fix formatting of literal sections in fanotify docs8fc70b3a142fsamples: Make fs-monitor depend on libc and headersc0baf9ac0b05docs: Document theFAN_FS_ERRORevent5451093081dbsamples: Add fs error monitoring example.
Quoted 9 lines
Quoted 2 lines
Gabriel, if
9abeae5d4458has a Fixes: tag it may have been auto seleced for 5.15.y afterc0baf9ac0b05was picked up...Or this... I might not have backported those at all to 5.15, and they got pulled in by another process.
In any event, do you want me to backport these to 5.10, or would you like to do it yourself?
Please backport the docs and sample patches above to 5.15 and 5.10 for completion of the backport.
I do not expect you should have any major conflicts with these standalone document and sample code.
Thanks,
Amir.
Re: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
In reply to Amir GoldsteinQuoted 18 lines · Amir Goldstein
Quoted 11 lines · Ajay Kaher
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305Quoted 5 lines
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch-Ajay
Quoted 7 lines
I agree that this is the best approach, because the test has no other way to test
if ext4 specifically supportsFAN_FS_ERROR.Chuck,
I wonder how those patches end up in 5.15.y but not in 5.10.y?
I wonder why this was backported to stable in the first place. I get there is a lot of refactoring in this series, which might be useful when backporting further fixes. but 9709bd548f11 just enabled a new feature - which seems against stable rules. Considering that "anything is a CVE", we really need to be cautious about this kind of stuff in stable kernels.
Is it possible to drop 9709bd548f11 from stable instead?
Quoted 2 lines
Gabriel, if
9abeae5d4458has a Fixes: tag it may have been auto seleced for 5.15.y afterc0baf9ac0b05was picked up...
right. It would be really cool if we had a way to append this information after the fact. How would people feel about using git-notes in the kernel tree to support that?
Signature · 1 line
Gabriel Krisman Bertazi
Re: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
Quoted 28 lines · Gabriel Krisman Bertazi
Quoted 22 lines · Amir Goldstein
Quoted 11 lines · Ajay Kaher
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305Quoted 5 lines
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch-Ajay
I agree that this is the best approach, because the test has no other way to test
if ext4 specifically supportsFAN_FS_ERROR.
Quoted 5 lines
Quoted 3 lines
Chuck,
I wonder how those patches end up in 5.15.y but not in 5.10.y?
I wonder why this was backported to stable in the first place.
I wanted to fix the myriad problems with the NFSD file cache in v5.10.y and v5.15.y. These problems were addressed by a long list of changes from v5.19 to v6.3. I was told that it was preferred that I do a full backport of all NFSD commits from v6.3 to the older kernels.
The fanotify patches were dependencies.
Quoted 6 lines
I get
there is a lot of refactoring in this series, which might be useful when backporting further fixes. but9709bd548f11just enabled a new feature - which seems against stable rules. Considering that "anything is a CVE", we really need to be cautious about this kind of stuff in stable kernels.
These patches were posted for review before they were included. Amir noted there were some changes to fanotify that would require man page updates and some modifications to ltp, but there were no other comments.
Quoted 1 line
Is it possible to drop
9709bd548f11from stable instead?
I've attempted a revert. It's not clean, but seems to be fixable by hand.
I can run some tests to see if that breaks NFSD.
Quoted 9 lines
Quoted 2 lines
Gabriel, if
9abeae5d4458has a Fixes: tag it may have been auto seleced for 5.15.y afterc0baf9ac0b05was picked up...right. It would be really cool if we had a way to append this information after the fact. How would people feel about using git-notes in the kernel tree to support that?
Signature · 1 line
Gabriel Krisman Bertazi
--
Chuck Lever
[email protected]
maintainerPATCH 1/1 Revert "fanotify: Allow users to request FAN_FS_ERROR events"
In reply to Gabriel Krisman BertaziFrom: Chuck Lever <[email protected]>
Gabriel says:
Quoted 6 lines
9709bd548f11just enabled a new feature -
which seems against stable rules. Considering that "anything is a CVE", we really need to be cautious about this kind of stuff in stable kernels.Is it possible to drop
9709bd548f11from stable instead?
The revert wasn't clean, but adjusting it to fit was straightforward. This passes NFSD CI, and adds no new failures to the fanotify ltp tests.
--- fs/notify/fanotify/fanotify_user.c | 4 ---- include/linux/fanotify.h | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-)
Gabriel, is this what you were thinking?
fs/notify/fanotify/fanotify_user.c +0 -4
@@ -1701,10 +1701,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, group->priority == FS_PRIO_0) goto fput_and_out; -if (mask &FAN_FS_ERROR && - mark_type !=FAN_MARK_FILESYSTEM ) - goto fput_and_out; -/* * Evictable is only relevant for inode marks, because only inode object * can be evicted on memory pressure.
include/linux/fanotify.h +1 -5
@@ -97,13 +97,9 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_INODE_EVENTS (FANOTIFY_DIRENT_EVENTS | \ FAN_ATTRIB | FAN_MOVE_SELF | FAN_DELETE_SELF) -/* Events that can only be reported with data type FSNOTIFY_EVENT_ERROR */ -#define FANOTIFY_ERROR_EVENTS (FAN_FS_ERROR) -/* Events that user can request to be notified on */ #define FANOTIFY_EVENTS (FANOTIFY_PATH_EVENTS | \ - FANOTIFY_INODE_EVENTS | \ - FANOTIFY_ERROR_EVENTS) + FANOTIFY_INODE_EVENTS)/* Events that require a permission response from user */ #define FANOTIFY_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM | \
Signature · 1 line
2.45.2
Re: [PATCH v5.15.y] Revert "fanotify: Allow users to request FAN_FS_ERROR events"
Quoted 14 lines · [email protected] writes:
From: Chuck Lever <[email protected]>
Gabriel says:
Quoted 6 lines
9709bd548f11just enabled a new feature -
which seems against stable rules. Considering that "anything is a CVE", we really need to be cautious about this kind of stuff in stable kernels.Is it possible to drop
9709bd548f11from stable instead?The revert wasn't clean, but adjusting it to fit was straightforward. This passes NFSD CI, and adds no new failures to the fanotify ltp tests.
Quoted 8 lines
Reported-by Gabriel Krisman Bertazi <[email protected]>Signed-off-by Chuck Lever <[email protected]>--- fs/notify/fanotify/fanotify_user.c | 4 ---- include/linux/fanotify.h | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-)Gabriel, is this what you were thinking?
Thanks Chuck.
This looks good to me as a way to disable it in stable and prevent userspace from trying to use it. Up to fanotify maintainers to decide whether to brign the rest of the series or merge this, but either way:
Quoted 35 lines
fs/notify/fanotify/fanotify_user.c +0
-4@@ -1701,10 +1701,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, group->priority == FS_PRIO_0) goto fput_and_out; -if (mask &FAN_FS_ERROR && - mark_type !=FAN_MARK_FILESYSTEM ) - goto fput_and_out; -/* * Evictable is only relevant for inode marks, because only inode object * can be evicted on memory pressure. include/linux/fanotify.h +1
-5@@ -97,13 +97,9 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_INODE_EVENTS (FANOTIFY_DIRENT_EVENTS | \ FAN_ATTRIB | FAN_MOVE_SELF | FAN_DELETE_SELF) -/* Events that can only be reported with data type FSNOTIFY_EVENT_ERROR */ -#define FANOTIFY_ERROR_EVENTS (FAN_FS_ERROR) -/* Events that user can request to be notified on */ #define FANOTIFY_EVENTS (FANOTIFY_PATH_EVENTS | \ - FANOTIFY_INODE_EVENTS | \ - FANOTIFY_ERROR_EVENTS) + FANOTIFY_INODE_EVENTS)/* Events that require a permission response from user */ #define FANOTIFY_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM | \
Signature · 1 line
Gabriel Krisman Bertazi
Amir Goldstein
reviewerRe: [PATCH v5.15.y] Revert "fanotify: Allow users to request FAN_FS_ERROR events"
Quoted 24 lines · Gabriel Krisman Bertazi
Quoted 21 lines · [email protected] writes:
From: Chuck Lever <[email protected]>
Gabriel says:
Quoted 6 lines
9709bd548f11just enabled a new feature -
which seems against stable rules. Considering that "anything is a CVE", we really need to be cautious about this kind of stuff in stable kernels.Is it possible to drop
9709bd548f11from stable instead?The revert wasn't clean, but adjusting it to fit was straightforward. This passes NFSD CI, and adds no new failures to the fanotify ltp tests.
Reported-by Gabriel Krisman Bertazi <[email protected]>Signed-off-by Chuck Lever <[email protected]>--- fs/notify/fanotify/fanotify_user.c | 4 ---- include/linux/fanotify.h | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-)
Quoted 7 lines
Quoted 1 line
Gabriel, is this what you were thinking?
Thanks Chuck.
This looks good to me as a way to disable it in stable and prevent userspace from trying to use it. Up to fanotify maintainers to decide whether to bring the rest of the series or merge this,
First of all, the "rest of the series" is already queued for 5.10.y.
I too was a bit surprised from willingness of stable tree maintainers to allow backports of entire features along with Chuck's nfsd backports. I understand the logic, I was just not aware when this shift in stable ideology had happened.
But having backported the entire fanotify 6.1 code as is to 5.15 and 5.10 I see no reason to make an exception for FAN_FS_ERROR.
Certainly not because two patches were left out of 5.10.y (and are now queued).
I think that the benefits of fanotify code parity across 6.1 5.15 5.10 outweigh the risk of regressions introduced by this specific feature.
So please do not revert.
Thanks,
Amir.
Jan Kara
maintainerRe: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
In reply to Ajay KaherQuoted 17 lines · Ajay Kaher
Quoted 7 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
Quoted 7 lines
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch
I know Chuck has been backporting the huge pile of fsnotify changes for stable and he was running LTP so I'm a bit curious if he saw the fanotify22 failure as well. The reason for the test failure seems to be that the combination of features now present in stable has never been upstream which confuses the test. As such I'm not sure if backporting more features to stable is warranted just to fix a broken LTP test... But given the huge pile Chuck has backported already I'm not strongly opposed to backporting a few more, there's just a question where does this stop :)
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Amir Goldstein
reviewerRe: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
Quoted 27 lines · Jan Kara
Quoted 17 lines · Ajay Kaher
Quoted 7 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:Quoted 7 lines
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patch
Quoted 8 lines
I know Chuck has been backporting the huge pile of fsnotify changes for stable and he was running LTP so I'm a bit curious if he saw the fanotify22 failure as well. The reason for the test failure seems to be that the combination of features now present in stable has never been upstream which confuses the test. As such I'm not sure if backporting more features to stable is warranted just to fix a broken LTP test... But given the huge pile Chuck has backported already I'm not strongly opposed to backporting a few more, there's just a question where does this stop :)
I'm not sure is it exactly "more features".
The fanotify patches and ext4 patches that use them where merges as a feature together.
IOW, FAN_FS_ERROR was merged with support for a single fs (ext4)
it would be weird to backport the feature with support for zero fs. Also, 5.15.y already has the ext4 patches - not sure why 5.10.y didn't get them.
Thanks,
Amir.
Jan Kara
maintainerRe: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
Quoted 37 lines · Amir Goldstein
Quoted 27 lines · Jan Kara
Quoted 17 lines · Ajay Kaher
Quoted 7 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:Quoted 7 lines
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patchQuoted 8 lines
I know Chuck has been backporting the huge pile of fsnotify changes for stable and he was running LTP so I'm a bit curious if he saw the fanotify22 failure as well. The reason for the test failure seems to be that the combination of features now present in stable has never been upstream which confuses the test. As such I'm not sure if backporting more features to stable is warranted just to fix a broken LTP test... But given the huge pile Chuck has backported already I'm not strongly opposed to backporting a few more, there's just a question where does this stop :)
Quoted 6 lines
I'm not sure is it exactly "more features". The fanotify patches and ext4 patches that use them where merges as a feature together.
IOW,
FAN_FS_ERRORwas merged with support for a single fs (ext4)
it would be weird to backport the feature with support for zero fs. Also, 5.15.y already has the ext4 patches - not sure why 5.10.y didn't get them.
I forgot 5.15.y got all the patches. Ok, then pushing them to 5.10.y makes sense as well.
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Re: [PATCH 5.10 387/770] fanotify: Allow users to request FAN_FS_ERROR events
In reply to Jan KaraQuoted 26 lines · Jan Kara
Quoted 21 lines · Ajay Kaher
Quoted 7 lines
[ Upstream commit
9709bd548f11a092d124698118013f66e1740f9b]Wire up the
FAN_FS_ERRORevent in thefanotify_marksyscall, allowing user space to request the monitoring ofFAN_FS_ERRORevents.These events are limited to filesystem marks, so check it is the case in the syscall handler.
Greg,
Without
9709bd548f11in v5.10.y skips LTP fanotify22 test case, as:
fanotify22.c:312: TCONF:FAN_FS_ERRORnot supported in kernelWith
9709bd548f11in v5.10.220, LTP fanotify22 is failing because of timeout as no notification. To fix need to merge following two upstream commit to v5.10:
124e7c61deb27d758df5ec0521c36cf08d417f7a:
0001-ext4_fix_error_code_saved_on_super_block_during_file_system.patch
https://lore.kernel.org/stable/[email protected]/T/#mf76930487697d8c1383ed5d21678fe504e8e2305
Quoted 7 lines
Quoted 3 lines
9a089b21f79b47eed240d4da7ea0d049de7c9b4d:
0001-ext4_Send_notifications_on_error.patchI know Chuck has been backporting the huge pile of fsnotify changes for stable and he was running LTP so I'm a bit curious if he saw the fanotify22 failure as well.
Fwiw, I didn't see any new failures for either 5.10.y or 5.15.y.
Quoted 7 lines
The reason for the test failure seems to be that the combination of features now present in stable has never been upstream which confuses the test. As such I'm not sure if backporting more features to stable is warranted just to fix a broken LTP test... But given the huge pile Chuck has backported already I'm not strongly opposed to backporting a few more, there's just a question where does this stop :)
Quoted 5 lines
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
--
Chuck Lever
Greg Kroah-Hartman
maintainerPATCH 388/770 SUNRPC: Trace calls to .rpc_call_done
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 b40887e10dcacc5e8ae3c1a99dcba20877c4831b ]
Introduce a single tracepoint that can replace simple dprintk call sites in upper layer "rpc_call_done" callbacks. Example:
kworker/u24:2-1254 [001] 771.026677: rpc_stats_latency: task:00000001@00000002 xid=0x16a6f3c0 rpcbindv2 GETPORT backlog=446 rtt=101 execute=555 kworker/u24:2-1254 [001] 771.026677: rpc_task_call_done: task:00000001@00000002 flags=ASYNC|DYNAMIC|SOFT|SOFTCONN|SENT runstate=RUNNING|ACTIVE status=0 action=rpcb_getport_done kworker/u24:2-1254 [001] 771.026678: rpcb_setport: task:00000001@00000002 status=0 port=20048
--- fs/lockd/clntproc.c | 3 --- fs/lockd/svc4proc.c | 2 -- fs/lockd/svcproc.c | 2 -- fs/nfs/filelayout/filelayout.c | 2 -- fs/nfs/flexfilelayout/flexfilelayout.c | 2 -- fs/nfs/pagelist.c | 3 --- fs/nfs/write.c | 3 --- include/trace/events/sunrpc.h | 1 + net/sunrpc/sched.c | 1 + 9 files changed, 2 insertions(+), 17 deletions(-)
fs/lockd/clntproc.c +0 -3
@@ -794,9 +794,6 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) goto retry_cancel; } -dprintk ("lockd: cancel status %u (task %u)\n" , - status, task->tk_pid); -switch (status) {case NLM_LCK_GRANTED :case NLM_LCK_DENIED_GRACE_PERIOD :
fs/lockd/svc4proc.c +0 -2
@@ -269,8 +269,6 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp)*/ static void nlm4svc_callback_exit (struct rpc_task *task,void *data) { -dprintk ("lockd: %5u callback returned %d\n" , task->tk_pid, - -task->tk_status); }static void nlm4svc_callback_release (void *data)
fs/lockd/svcproc.c +0 -2
@@ -301,8 +301,6 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp)*/ static void nlmsvc_callback_exit (struct rpc_task *task,void *data) { -dprintk ("lockd: %5u callback returned %d\n" , task->tk_pid, - -task->tk_status); }void nlmsvc_release_call (struct nlm_rqst *call)
fs/nfs/filelayout/filelayout.c +0 -2
@@ -293,8 +293,6 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data) {struct nfs_pgio_header *hdr = data; -dprintk ("--> %s task->tk_status %d\n" , __func__, task->tk_status); -if (test_bit (NFS_IOHDR_REDO , &hdr->flags) && task->tk_status ==0 ) {nfs41_sequence_done (task, &hdr->res.seq_res);
fs/nfs/flexfilelayout/flexfilelayout.c +0 -2
@@ -1419,8 +1419,6 @@ static void ff_layout_read_call_done(struct rpc_task *task, void *data) {struct nfs_pgio_header *hdr = data; -dprintk ("--> %s task->tk_status %d\n" , __func__, task->tk_status); -if (test_bit (NFS_IOHDR_REDO , &hdr->flags) && task->tk_status ==0 ) {nfs4_sequence_done (task, &hdr->res.seq_res);
fs/nfs/pagelist.c +0 -3
@@ -870,9 +870,6 @@ static void nfs_pgio_result(struct rpc_task *task, void *calldata)struct nfs_pgio_header *hdr = calldata;struct inode *inode = hdr->inode; -dprintk ("NFS: %s: %5u, (status %d)\n" , __func__, - task->tk_pid, task->tk_status); -if (hdr->rw_ops->rw_done (task, hdr, inode) !=0 )return ;if (task->tk_status <0 )
fs/nfs/write.c +0 -3
@@ -1809,9 +1809,6 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) {struct nfs_commit_data *data = calldata; -dprintk ("NFS: %5u nfs_commit_done (status %d)\n" , - task->tk_pid, task->tk_status); -/* Call the NFS version-specific code */ NFS_PROTO (data->inode)->commit_done (task, data);trace_nfs_commit_done (task, data);
include/trace/events/sunrpc.h +1 -0
@@ -394,6 +394,7 @@ DEFINE_RPC_RUNNING_EVENT(complete);DEFINE_RPC_RUNNING_EVENT (timeout);DEFINE_RPC_RUNNING_EVENT (signalled);DEFINE_RPC_RUNNING_EVENT (end); +DEFINE_RPC_RUNNING_EVENT (call_done); DECLARE_EVENT_CLASS(rpc_task_queued,
net/sunrpc/sched.c +1 -0
@@ -821,6 +821,7 @@ void rpc_exit_task(struct rpc_task *task)else if (task->tk_client)rpc_count_iostats (task, task->tk_client->cl_metrics);if (task->tk_ops->rpc_call_done !=NULL ) { +trace_rpc_task_call_done (task, task->tk_ops->rpc_call_done); task->tk_ops->rpc_call_done (task, task->tk_calldata);if (task->tk_action !=NULL ) {/* Always release the RPC slot and buffer memory */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 389/770 NFSD: Optimize DRC bucket pruning
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 8847ecc9274a14114385d1cb4030326baa0766eb ]
DRC bucket pruning is done by nfsd_cache_lookup(), which is part of every NFSv2 and NFSv3 dispatch (ie, it's done while the client is waiting).
I added a trace_printk() in prune_bucket() to see just how long it takes to prune. Here are two ends of the spectrum:
prune_bucket: Scanned 1 and freed 0 in 90 ns, 62 entries remaining
prune_bucket: Scanned 2 and freed 1 in 716 ns, 63 entries remaining
...
prune_bucket: Scanned 75 and freed 74 in 34149 ns, 1 entries remaining
Pruning latency is noticeable on fast transports with fast storage. By noticeable, I mean that the latency measured here in the worst case is the same order of magnitude as the round trip time for cached server operations.
We could do something like moving expired entries to an expired list and then free them later instead of freeing them right in prune_bucket(). But simply limiting the number of entries that can be pruned by a lookup is simple and retains more entries in the cache, making the DRC somewhat more effective.
Comparison with a 70/30 fio 8KB 12 thread direct I/O test:
Before:
write: IOPS=61.6k, BW=481MiB/s (505MB/s)(14.1GiB/30001msec); 0 zone resets
WRITE:
1848726 ops (30%) avg bytes sent per op: 8340 avg bytes received per op: 136 backlog wait: 0.635158 RTT: 0.128525 total execute time: 0.827242 (milliseconds)
After:
write: IOPS=63.0k, BW=492MiB/s (516MB/s)(14.4GiB/30001msec); 0 zone resets
WRITE:
1891144 ops (30%) avg bytes sent per op: 8340 avg bytes received per op: 136 backlog wait: 0.616114 RTT: 0.126842 total execute time: 0.805348 (milliseconds)
--- fs/nfsd/nfscache.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
fs/nfsd/nfscache.c +11 -6
@@ -241,8 +241,8 @@ lru_put_end(struct nfsd_drc_bucket *b, struct svc_cacherep *rp)list_move_tail (&rp->c_lru, &b->lru_head); } -static long -prune_bucket (struct nfsd_drc_bucket *b,struct nfsd_net *nn) +static long prune_bucket (struct nfsd_drc_bucket *b,struct nfsd_net *nn, +unsigned int max) {struct svc_cacherep *rp, *tmp;long freed =0 ;
@@ -258,11 +258,17 @@ prune_bucket(struct nfsd_drc_bucket *b, struct nfsd_net *nn) time_before(jiffies, rp->c_timestamp + RC_EXPIRE)) break;nfsd_reply_cache_free_locked (b, rp, nn); - freed++; +if (max && freed++ > max) +break ; }return freed; } +static long nfsd_prune_bucket (struct nfsd_drc_bucket *b,struct nfsd_net *nn) +{ +return prune_bucket (b, nn,3 ); +} +/* * Walk the LRU list and prune off entries that are older than RC_EXPIRE. * Also prune the oldest ones when the total exceeds the max number of entries.
@@ -279,7 +285,7 @@ prune_cache_entries(struct nfsd_net *nn)if (list_empty (&b->lru_head))continue ;spin_lock (&b->cache_lock); - freed +=prune_bucket (b, nn); + freed +=prune_bucket (b, nn,0 );spin_unlock (&b->cache_lock); }return freed;
@@ -453,8 +459,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp)atomic_inc (&nn->num_drc_entries);nfsd_stats_drc_mem_usage_add (nn,sizeof (*rp)); -/* go ahead and prune the cache */ -prune_bucket (b, nn); +nfsd_prune_bucket (b, nn); out_unlock:spin_unlock (&b->cache_lock);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 390/770 NFSD: move filehandle format declarations out of "uapi".
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 ef5825e3cf0d0af657f5fb4dd86d750ed42fee0a ]
A small part of the declaration concerning filehandle format are currently in the "uapi" include directory:
include/uapi/linux/nfsd/nfsfh.h
There is a lot more to the filehandle format, including "enum fid_type" and "enum nfsd_fsid" which are not exported via "uapi".
This small part of the filehandle definition is of minimal use outside of the kernel, and I can find no evidence that an other code is using it. Certainly nfs-utils and wireshark (The most likely candidates) do not use these declarations.
So move it out of "uapi" by copying the content from
include/uapi/linux/nfsd/nfsfh.h
into
fs/nfsd/nfsfh.h
A few unnecessary "#include" directives are not copied, and neither is the #define of fh_auth, which is annotated as being for userspace only.
The copyright claims in the uapi file are identical to those in the nfsd file, so there is no need to copy those.
The "__u32" style integer types are only needed in "uapi". In kernel-only code we can use the more familiar "u32" style.
--- fs/nfsd/nfsfh.h | 97 ++++++++++++++++++++++++++- fs/nfsd/vfs.c | 1 + include/uapi/linux/nfsd/nfsfh.h | 115 -------------------------------- 3 files changed, 97 insertions(+), 116 deletions(-) delete mode 100644 include/uapi/linux/nfsd/nfsfh.h
fs/nfsd/nfsfh.h +96 -1
@@ -10,9 +10,104 @@#include <linux/crc32.h> #include <linux/sunrpc/svc.h> -#include <uapi/linux/nfsd/nfsfh.h> #include <linux/iversion.h> #include <linux/exportfs.h> +#include <linux/nfs4.h> + + +/* +* This is the old "dentry style" Linux NFSv2 file handle. +* +* The xino and xdev fields are currently used to transport the +* ino/dev of the exported inode. +*/ +struct nfs_fhbase_old { +u32 fb_dcookie;/* dentry cookie - always 0xfeebbaca */ +u32 fb_ino;/* our inode number */ +u32 fb_dirino;/* dir inode number, 0 for directories */ +u32 fb_dev;/* our device */ +u32 fb_xdev; +u32 fb_xino; +u32 fb_generation; +}; + +/* +* This is the new flexible, extensible style NFSv2/v3/v4 file handle. +* +* The file handle starts with a sequence of four-byte words. +* The first word contains a version number (1) and three descriptor bytes +* that tell how the remaining 3 variable length fields should be handled. +* These three bytes are auth_type, fsid_type and fileid_type. +* +* All four-byte values are in host-byte-order. +* +* The auth_type field is deprecated and must be set to 0. +* +* The fsid_type identifies how the filesystem (or export point) is +* encoded. +* Current values: +* 0 - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number +* NOTE: we cannot use the kdev_t device id value, because kdev_t.h +* says we mustn't. We must break it up and reassemble. +* 1 - 4 byte user specified identifier +* 2 - 4 byte major, 4 byte minor, 4 byte inode number - DEPRECATED +* 3 - 4 byte device id, encoded for user-space, 4 byte inode number +* 4 - 4 byte inode number and 4 byte uuid +* 5 - 8 byte uuid +* 6 - 16 byte uuid +* 7 - 8 byte inode number and 16 byte uuid +* +* The fileid_type identified how the file within the filesystem is encoded. +* The values for this field are filesystem specific, exccept that +* filesystems must not use the values '0' or '0xff'. 'See enum fid_type' +* in include/linux/exportfs.h for currently registered values. +*/ +struct nfs_fhbase_new { +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 { +unsigned int fh_size;/* significant for NFSv3. +* Points to the current size while building +* a new file handle +*/ +union { +struct nfs_fhbase_old fh_old; +u32 fh_pad[NFS4_FHSIZE /4 ]; +struct nfs_fhbase_new fh_new; + } fh_base; +}; + +#define ofh_dcookie fh_base.fh_old.fb_dcookie +#define ofh_ino fh_base.fh_old.fb_ino +#define ofh_dirino fh_base.fh_old.fb_dirino +#define ofh_dev fh_base.fh_old.fb_dev +#define ofh_xdev fh_base.fh_old.fb_xdev +#define ofh_xino fh_base.fh_old.fb_xino +#define ofh_generation fh_base.fh_old.fb_generation + +#define fh_version fh_base.fh_new.fb_version +#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_flexstatic inline __u32 ino_t_to_u32 (ino_t ino) {
fs/nfsd/vfs.c +1 -0
@@ -244,6 +244,7 @@ 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 deleted +0 -115
115 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 391/770 NFSD: drop support for ancient filehandles
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 c645a883df34ee10b884ec921e850def54b7f461 ]
Filehandles not in the "new" or "version 1" format have not been handed out for new mounts since Linux 2.4 which was released 20 years ago. I think it is safe to say that no such file handles are still in use, and that we can drop support for them.
--- fs/nfsd/nfsfh.c | 160 +++++++++++++++--------------------------------- fs/nfsd/nfsfh.h | 34 +--------- 2 files changed, 54 insertions(+), 140 deletions(-)
fs/nfsd/nfsfh.c +51 -109
@@ -153,11 +153,12 @@ static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,static __be32 nfsd_set_fh_dentry (struct svc_rqst *rqstp,struct svc_fh *fhp) {struct knfsd_fh *fh = &fhp->fh_handle; -struct fid *fid =NULL , sfid; +struct fid *fid =NULL ;struct svc_export *exp;struct dentry *dentry;int fileid_type;int data_left = fh->fh_size/4 ; +int len;__be32 error; error = nfserr_stale;
@@ -166,48 +167,35 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)if (rqstp->rq_vers ==4 && fh->fh_size ==0 )return nfserr_nofilehandle; -if (fh->fh_version ==1 ) { -int len; - -if (--data_left <0 ) -return error; -if (fh->fh_auth_type !=0 ) -return error; - len =key_len (fh->fh_fsid_type) /4 ; -if (len ==0 ) -return error; -if (fh->fh_fsid_type ==FSID_MAJOR_MINOR ) { -/* deprecated, convert to type 3 */ - len =key_len (FSID_ENCODE_DEV )/4 ; - fh->fh_fsid_type =FSID_ENCODE_DEV ; -/* -* struct knfsd_fh uses host-endian fields, which are -* sometimes used to hold net-endian values. This -* confuses sparse, so we must use __force here to -* keep it from complaining. -*/ - fh->fh_fsid[0 ] =new_encode_dev (MKDEV (ntohl ((__force __be32 )fh->fh_fsid[0 ]), -ntohl ((__force __be32 )fh->fh_fsid[1 ]))); - fh->fh_fsid[1 ] = fh->fh_fsid[2 ]; - } - data_left -= len; -if (data_left <0 ) -return error; - exp =rqst_exp_find (rqstp, fh->fh_fsid_type, fh->fh_fsid); - fid = (struct fid *)(fh->fh_fsid + len); - }else { -__u32 tfh[2 ]; -dev_t xdev; -ino_t xino; - -if (fh->fh_size !=NFS_FHSIZE ) -return error; -/* assume old filehandle format */ - xdev =old_decode_dev (fh->ofh_xdev); - xino =u32_to_ino_t (fh->ofh_xino); -mk_fsid (FSID_DEV , tfh, xdev, xino,0 ,NULL ); - exp =rqst_exp_find (rqstp,FSID_DEV , tfh); +if (fh->fh_version !=1 ) +return error; + +if (--data_left <0 ) +return error; +if (fh->fh_auth_type !=0 ) +return error; + len =key_len (fh->fh_fsid_type) /4 ; +if (len ==0 ) +return error; +if (fh->fh_fsid_type ==FSID_MAJOR_MINOR ) { +/* deprecated, convert to type 3 */ + len =key_len (FSID_ENCODE_DEV )/4 ; + fh->fh_fsid_type =FSID_ENCODE_DEV ; +/* +* struct knfsd_fh uses host-endian fields, which are +* sometimes used to hold net-endian values. This +* confuses sparse, so we must use __force here to +* keep it from complaining. +*/ + fh->fh_fsid[0 ] =new_encode_dev (MKDEV (ntohl ((__force __be32 )fh->fh_fsid[0 ]), +ntohl ((__force __be32 )fh->fh_fsid[1 ]))); + fh->fh_fsid[1 ] = fh->fh_fsid[2 ]; } + data_left -= len; +if (data_left <0 ) +return error; + exp =rqst_exp_find (rqstp, fh->fh_fsid_type, fh->fh_fsid); + fid = (struct fid *)(fh->fh_fsid + len); error = nfserr_stale;if (IS_ERR (exp)) {
@@ -252,18 +240,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)if (rqstp->rq_vers >2 ) error = nfserr_badhandle; -if (fh->fh_version !=1 ) { - sfid.i32.ino = fh->ofh_ino; - sfid.i32.gen = fh->ofh_generation; - sfid.i32.parent_ino = fh->ofh_dirino; - fid = &sfid; - data_left =3 ; -if (fh->ofh_dirino ==0 ) - fileid_type =FILEID_INO32_GEN ; -else - fileid_type =FILEID_INO32_GEN_PARENT ; - }else - fileid_type = fh->fh_fileid_type; + fileid_type = fh->fh_fileid_type;if (fileid_type ==FILEID_ROOT ) dentry =dget (exp->ex_path.dentry);
@@ -451,20 +428,6 @@ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, } } -/* -* for composing old style file handles -*/ -static inline void _fh_update_old (struct dentry *dentry, -struct svc_export *exp, -struct knfsd_fh *fh) -{ - fh->ofh_ino =ino_t_to_u32 (d_inode (dentry)->i_ino); - fh->ofh_generation =d_inode (dentry)->i_generation; -if (d_is_dir (dentry) || - (exp->ex_flags &NFSEXP_NOSUBTREECHECK )) - fh->ofh_dirino =0 ; -} -static bool is_root_export (struct svc_export *exp) {return exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root;
@@ -561,9 +524,6 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,/* ref_fh is a reference file handle. * if it is non-null and for the same filesystem, then we should compose * a filehandle which is of the same version, where possible. -* Currently, that means that if ref_fh->fh_handle.fh_version == 0xca -* Then create a 32byte filehandle using nfs_fhbase_old -* */ struct inode * inode =d_inode (dentry);
@@ -599,35 +559,21 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, fhp->fh_dentry =dget (dentry);/* our internal copy */ fhp->fh_export =exp_get (exp); -if (fhp->fh_handle.fh_version ==0xca ) { -/* old style filehandle please */ -memset (&fhp->fh_handle.fh_base,0 ,NFS_FHSIZE ); - fhp->fh_handle.fh_size =NFS_FHSIZE ; - fhp->fh_handle.ofh_dcookie =0xfeebbaca ; - fhp->fh_handle.ofh_dev =old_encode_dev (ex_dev); - fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; - fhp->fh_handle.ofh_xino = -ino_t_to_u32 (d_inode (exp->ex_path.dentry)->i_ino); - fhp->fh_handle.ofh_dirino =ino_t_to_u32 (parent_ino (dentry)); -if (inode) -_fh_update_old (dentry, exp, &fhp->fh_handle); - }else { - fhp->fh_handle.fh_size = -key_len (fhp->fh_handle.fh_fsid_type) +4 ; - fhp->fh_handle.fh_auth_type =0 ; - -mk_fsid (fhp->fh_handle.fh_fsid_type, - fhp->fh_handle.fh_fsid, - ex_dev, -d_inode (exp->ex_path.dentry)->i_ino, - exp->ex_fsid, exp->ex_uuid); - -if (inode) -_fh_update (fhp, exp, dentry); -if (fhp->fh_handle.fh_fileid_type ==FILEID_INVALID ) { -fh_put (fhp); -return nfserr_opnotsupp; - } + fhp->fh_handle.fh_size = +key_len (fhp->fh_handle.fh_fsid_type) +4 ; + fhp->fh_handle.fh_auth_type =0 ; + +mk_fsid (fhp->fh_handle.fh_fsid_type, + fhp->fh_handle.fh_fsid, + ex_dev, +d_inode (exp->ex_path.dentry)->i_ino, + exp->ex_fsid, exp->ex_uuid); + +if (inode) +_fh_update (fhp, exp, dentry); +if (fhp->fh_handle.fh_fileid_type ==FILEID_INVALID ) { +fh_put (fhp); +return nfserr_opnotsupp; }return 0 ;
@@ -648,16 +594,12 @@ fh_update(struct svc_fh *fhp) dentry = fhp->fh_dentry;if (d_really_is_negative (dentry)) goto out_negative; -if (fhp->fh_handle.fh_version !=1 ) { -_fh_update_old (dentry, fhp->fh_export, &fhp->fh_handle); - }else { -if (fhp->fh_handle.fh_fileid_type !=FILEID_ROOT ) -return 0 ; +if (fhp->fh_handle.fh_fileid_type !=FILEID_ROOT ) +return 0 ; -_fh_update (fhp, fhp->fh_export, dentry); -if (fhp->fh_handle.fh_fileid_type ==FILEID_INVALID ) -return nfserr_opnotsupp; - } +_fh_update (fhp, fhp->fh_export, dentry); +if (fhp->fh_handle.fh_fileid_type ==FILEID_INVALID ) +return nfserr_opnotsupp;return 0 ; out_bad:printk (KERN_ERR "fh_update: fh not verified!\n" );
fs/nfsd/nfsfh.h +3 -31
@@ -14,26 +14,7 @@#include <linux/exportfs.h> #include <linux/nfs4.h> - -/* -* This is the old "dentry style" Linux NFSv2 file handle. -* -* The xino and xdev fields are currently used to transport the -* ino/dev of the exported inode. -*/ -struct nfs_fhbase_old { -u32 fb_dcookie;/* dentry cookie - always 0xfeebbaca */ -u32 fb_ino;/* our inode number */ -u32 fb_dirino;/* dir inode number, 0 for directories */ -u32 fb_dev;/* our device */ -u32 fb_xdev; -u32 fb_xino; -u32 fb_generation; -}; -/* -* This is the new flexible, extensible style NFSv2/v3/v4 file handle. -* * The file handle starts with a sequence of four-byte words. * The first word contains a version number (1) and three descriptor bytes * that tell how the remaining 3 variable length fields should be handled.
@@ -57,7 +38,7 @@ struct nfs_fhbase_old {* 6 - 16 byte uuid * 7 - 8 byte inode number and 16 byte uuid * -* The fileid_type identified how the file within the filesystem is encoded. +* The fileid_type identifies how the file within the filesystem is encoded. * The values for this field are filesystem specific, exccept that * filesystems must not use the values '0' or '0xff'. 'See enum fid_type' * in include/linux/exportfs.h for currently registered values.
@@ -65,7 +46,7 @@ struct nfs_fhbase_old { struct nfs_fhbase_new { union { struct { - u8 fb_version_aux; /* == 1, even => nfs_fhbase_old */ + u8 fb_version_aux; /* == 1 */ u8 fb_auth_type_aux; u8 fb_fsid_type_aux; u8 fb_fileid_type_aux;
@@ -74,7 +55,7 @@ struct nfs_fhbase_new {/* u32 fb_fileid[0]; floating */ };struct { -u8 fb_version;/* == 1, even => nfs_fhbase_old */ +u8 fb_version;/* == 1 */ u8 fb_auth_type;u8 fb_fsid_type;u8 fb_fileid_type;
@@ -89,20 +70,11 @@ struct knfsd_fh {* a new file handle */ union { -struct nfs_fhbase_old fh_old;u32 fh_pad[NFS4_FHSIZE /4 ];struct nfs_fhbase_new fh_new; } fh_base; }; -#define ofh_dcookie fh_base.fh_old.fb_dcookie -#define ofh_ino fh_base.fh_old.fb_ino -#define ofh_dirino fh_base.fh_old.fb_dirino -#define ofh_dev fh_base.fh_old.fb_dev -#define ofh_xdev fh_base.fh_old.fb_xdev -#define ofh_xino fh_base.fh_old.fb_xino -#define ofh_generation fh_base.fh_old.fb_generation -#define fh_version fh_base.fh_new.fb_version#define fh_fsid_type fh_base.fh_new.fb_fsid_type#define fh_auth_type fh_base.fh_new.fb_auth_type
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 392/770 NFSD: simplify struct nfsfh
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 d8b26071e65e80a348602b939e333242f989221b ]
Most of the fields in 'struct knfsd_fh' are 2 levels deep (a union and a struct) and are accessed using macros like:
#define fh_FOO fh_base.fh_new.fb_FOO
This patch makes the union and struct anonymous, so that "fh_FOO" can be a name directly within 'struct knfsd_fh' and the #defines aren't needed.
The file handle as a whole is sometimes accessed as "fh_base" or "fh_base.fh_pad", neither of which are particularly helpful names. As the struct holding the filehandle is now anonymous, we cannot use the name of that, so we union it with 'fh_raw' and use that where the raw filehandle is needed. fh_raw also ensure the structure is large enough for the largest possible filehandle.
fh_raw is a 'char' array, removing any need to cast it for memcpy etc.
SVCFH_fmt() is simplified using the "%ph" printk format. This changes the appearance of filehandles in dprintk() debugging, making them a little more precise.
--- fs/nfsd/flexfilelayout.c | 2 +- fs/nfsd/lockd.c | 2 +- fs/nfsd/nfs3xdr.c | 4 ++-- fs/nfsd/nfs4callback.c | 2 +- fs/nfsd/nfs4proc.c | 4 ++-- fs/nfsd/nfs4state.c | 4 ++-- fs/nfsd/nfs4xdr.c | 4 ++-- fs/nfsd/nfsctl.c | 6 ++--- fs/nfsd/nfsfh.c | 13 ++++------- fs/nfsd/nfsfh.h | 50 ++++++++++++---------------------------- fs/nfsd/nfsxdr.c | 4 ++-- 11 files changed, 35 insertions(+), 60 deletions(-)
fs/nfsd/flexfilelayout.c +1 -1
@@ -61,7 +61,7 @@ nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, goto out_error; fl->fh.size = fhp->fh_handle.fh_size; -memcpy (fl->fh.data, &fhp->fh_handle.fh_base, fl->fh.size); +memcpy (fl->fh.data, &fhp->fh_handle.fh_raw, fl->fh.size);/* Give whole file layout segments */ seg->offset =0 ;
fs/nfsd/lockd.c +1 -1
@@ -35,7 +35,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,/* must initialize before using! but maxsize doesn't matter */ fh_init (&fh,0 ); fh.fh_handle.fh_size = f->size; -memcpy ((char *)&fh.fh_handle.fh_base, f->data, f->size); +memcpy (&fh.fh_handle.fh_raw, f->data, f->size); fh.fh_export =NULL ; access = (mode ==O_WRONLY ) ?NFSD_MAY_WRITE :NFSD_MAY_READ ;
fs/nfsd/nfs3xdr.c +2 -2
@@ -92,7 +92,7 @@ svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)return false;fh_init (fhp,NFS3_FHSIZE ); fhp->fh_handle.fh_size = size; -memcpy (&fhp->fh_handle.fh_base, p, size); +memcpy (&fhp->fh_handle.fh_raw, p, size);return true; }
@@ -131,7 +131,7 @@ svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp) *p++ =cpu_to_be32 (size);if (size) p[XDR_QUADLEN (size) -1 ] =0 ; -memcpy (p, &fhp->fh_handle.fh_base, size); +memcpy (p, &fhp->fh_handle.fh_raw, size);return true; }
fs/nfsd/nfs4callback.c +1 -1
@@ -121,7 +121,7 @@ static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh)BUG_ON (length >NFS4_FHSIZE ); p =xdr_reserve_space (xdr,4 + length); -xdr_encode_opaque (p, &fh->fh_base, length); +xdr_encode_opaque (p, &fh->fh_raw, length); }/*
fs/nfsd/nfs4proc.c +2 -2
@@ -519,7 +519,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,fh_put (&cstate->current_fh); cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; -memcpy (&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, +memcpy (&cstate->current_fh.fh_handle.fh_raw, putfh->pf_fhval, putfh->pf_fhlen); ret =fh_verify (rqstp, &cstate->current_fh,0 ,NFSD_MAY_BYPASS_GSS );#ifdef CONFIG_NFSD_V4_2_INTER_SSC
@@ -1379,7 +1379,7 @@ nfsd4_setup_inter_ssc(struct svc_rqst *rqstp, s_fh = &cstate->save_fh; copy->c_fh.size = s_fh->fh_handle.fh_size; -memcpy (copy->c_fh.data, &s_fh->fh_handle.fh_base, copy->c_fh.size); +memcpy (copy->c_fh.data, &s_fh->fh_handle.fh_raw, copy->c_fh.size); copy->stateid.seqid =cpu_to_be32 (s_stid->si_generation);memcpy (copy->stateid.other, (void *)&s_stid->si_opaque,sizeof (stateid_opaque_t));
fs/nfsd/nfs4state.c +2 -2
@@ -1022,7 +1022,7 @@ static int delegation_blocked(struct knfsd_fh *fh) }spin_unlock (&blocked_delegations_lock); } - hash =jhash (&fh->fh_base, fh->fh_size,0 ); + hash =jhash (&fh->fh_raw, fh->fh_size,0 );if (test_bit (hash&255 , bd->set[0 ]) &&test_bit ((hash>>8 )&255 , bd->set[0 ]) &&test_bit ((hash>>16 )&255 , bd->set[0 ]))
@@ -1041,7 +1041,7 @@ static void block_delegations(struct knfsd_fh *fh)u32 hash;struct bloom_pair *bd = &blocked_delegations; - hash =jhash (&fh->fh_base, fh->fh_size,0 ); + hash =jhash (&fh->fh_raw, fh->fh_size,0 );spin_lock (&blocked_delegations_lock);__set_bit (hash&255 , bd->set[bd->new]);
fs/nfsd/nfs4xdr.c +2 -2
@@ -3110,7 +3110,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, p =xdr_reserve_space (xdr, fhp->fh_handle.fh_size +4 );if (!p) goto out_resource; - p =xdr_encode_opaque (p, &fhp->fh_handle.fh_base, + p =xdr_encode_opaque (p, &fhp->fh_handle.fh_raw, fhp->fh_handle.fh_size); }if (bmval0 &FATTR4_WORD0_FILEID ) {
@@ -3681,7 +3681,7 @@ nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh p =xdr_reserve_space (xdr, len +4 );if (!p)return nfserr_resource; - p =xdr_encode_opaque (p, &fhp->fh_handle.fh_base, len); + p =xdr_encode_opaque (p, &fhp->fh_handle.fh_raw, len);return 0 ; }
fs/nfsd/nfsctl.c +3 -3
@@ -395,12 +395,12 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)auth_domain_put (dom);if (len)return len; - + mesg = buf; len =SIMPLE_TRANSACTION_LIMIT ; -qword_addhex (&mesg, &len, (char *)&fh.fh_base, fh.fh_size); +qword_addhex (&mesg, &len, fh.fh_raw, fh.fh_size); mesg[-1 ] ='\n' ; -return mesg - buf; +return mesg - buf; }/*
fs/nfsd/nfsfh.c +4 -9
@@ -639,16 +639,11 @@ fh_put(struct svc_fh *fhp)char *SVCFH_fmt (struct svc_fh *fhp) {struct knfsd_fh *fh = &fhp->fh_handle; +static char buf[2 +1 +1 +64 *3 +1 ]; -static char buf[80 ]; -sprintf (buf,"%d: %08x %08x %08x %08x %08x %08x" , - fh->fh_size, - fh->fh_base.fh_pad[0 ], - fh->fh_base.fh_pad[1 ], - fh->fh_base.fh_pad[2 ], - fh->fh_base.fh_pad[3 ], - fh->fh_base.fh_pad[4 ], - fh->fh_base.fh_pad[5 ]); +if (fh->fh_size <0 || fh->fh_size>64 ) +return "bad-fh" ; +sprintf (buf,"%d: %*ph" , fh->fh_size, fh->fh_size, fh->fh_raw);return buf; }
fs/nfsd/nfsfh.h +15 -35
80 lines not on this page · raw message
fs/nfsd/nfsxdr.c +2 -2
@@ -64,7 +64,7 @@ svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp)if (!p)return false;fh_init (fhp,NFS_FHSIZE ); -memcpy (&fhp->fh_handle.fh_base, p,NFS_FHSIZE ); +memcpy (&fhp->fh_handle.fh_raw, p,NFS_FHSIZE ); fhp->fh_handle.fh_size =NFS_FHSIZE ;return true;
@@ -78,7 +78,7 @@ svcxdr_encode_fhandle(struct xdr_stream *xdr, const struct svc_fh *fhp) p =xdr_reserve_space (xdr,NFS_FHSIZE );if (!p)return false; -memcpy (p, &fhp->fh_handle.fh_base,NFS_FHSIZE ); +memcpy (p, &fhp->fh_handle.fh_raw,NFS_FHSIZE );return true; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 393/770 NFSD: Initialize pointer ni with NULL and not plain integer 0
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 8e70bf27fd20cc17e87150327a640e546bfbee64 ]
Pointer ni is being initialized with plain integer zero. Fix this by initializing with NULL.
--- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4state.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -1181,7 +1181,7 @@ extern void nfs_sb_deactive(struct super_block *sb);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 ; +struct nfsd4_ssc_umount_item *ni =NULL ;struct nfsd4_ssc_umount_item *work =NULL ;struct nfsd4_ssc_umount_item *tmp;DEFINE_WAIT (wait);
fs/nfsd/nfs4state.c +1 -1
@@ -5573,7 +5573,7 @@ static void nfsd4_ssc_shutdown_umount(struct nfsd_net *nn)static void nfsd4_ssc_expire_umount (struct nfsd_net *nn) {bool do_wakeup = false; -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 394/770 NFSD: Have legacy NFSD WRITE decoders use xdr_stream_subsegment()
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 dae9a6cab8009e526570e7477ce858dcdfeb256e ]
Refactor.
Now that the NFSv2 and NFSv3 XDR decoders have been converted to use xdr_streams, the WRITE decoder functions can use xdr_stream_subsegment() to extract the WRITE payload into its own xdr_buf, just as the NFSv4 WRITE XDR decoder currently does.
That makes it possible to pass the first kvec, pages array + length, page_base, and total payload length via a single function parameter.
The payload's page_base is not yet assigned or used, but will be in subsequent patches.
--- fs/nfsd/nfs3proc.c | 3 +-- fs/nfsd/nfs3xdr.c | 12 ++---------- fs/nfsd/nfs4proc.c | 3 +-- fs/nfsd/nfsproc.c | 3 +-- fs/nfsd/nfsxdr.c | 9 +-------- fs/nfsd/xdr.h | 2 +- fs/nfsd/xdr3.h | 2 +- include/linux/sunrpc/svc.h | 3 +-- net/sunrpc/svc.c | 11 ++++++----- 9 files changed, 15 insertions(+), 33 deletions(-)
fs/nfsd/nfs3proc.c +1 -2
@@ -206,8 +206,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp)fh_copy (&resp->fh, &argp->fh); resp->committed = argp->stable; - nvecs =svc_fill_write_vector (rqstp, rqstp->rq_arg.pages, - &argp->first, cnt); + nvecs =svc_fill_write_vector (rqstp, &argp->payload);if (!nvecs) { resp->status = nfserr_io; goto out;
fs/nfsd/nfs3xdr.c +2 -10
@@ -621,9 +621,6 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd3_writeargs *args = rqstp->rq_argp;u32 max_blocksize =svc_max_payload (rqstp); -struct kvec *head = rqstp->rq_arg.head; -struct kvec *tail = rqstp->rq_arg.tail; -size_t remaining;if (!svcxdr_decode_nfs_fh3 (xdr, &args->fh))return 0 ;
@@ -641,17 +638,12 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)/* request sanity */ if (args->count != args->len)return 0 ; - remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; - remaining -=xdr_stream_pos (xdr); -if (remaining <xdr_align_size (args->len)) -return 0 ;if (args->count > max_blocksize) { args->count = max_blocksize; args->len = max_blocksize; } - - args->first.iov_base = xdr->p; - args->first.iov_len = head->iov_len -xdr_stream_pos (xdr); +if (!xdr_stream_subsegment (xdr, &args->payload, args->count)) +return 0 ;return 1 ; }
fs/nfsd/nfs4proc.c +1 -2
@@ -1034,8 +1034,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, write->wr_how_written = write->wr_stable_how; - nvecs =svc_fill_write_vector (rqstp, write->wr_payload.pages, - write->wr_payload.head, write->wr_buflen); + nvecs =svc_fill_write_vector (rqstp, &write->wr_payload);WARN_ON_ONCE (nvecs >ARRAY_SIZE (rqstp->rq_vec)); status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
fs/nfsd/nfsproc.c +1 -2
@@ -234,8 +234,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)SVCFH_fmt (&argp->fh), argp->len, argp->offset); - nvecs =svc_fill_write_vector (rqstp, rqstp->rq_arg.pages, - &argp->first, cnt); + nvecs =svc_fill_write_vector (rqstp, &argp->payload);if (!nvecs) { resp->status = nfserr_io; goto out;
fs/nfsd/nfsxdr.c +1 -8
@@ -325,10 +325,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p) {struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_writeargs *args = rqstp->rq_argp; -struct kvec *head = rqstp->rq_arg.head; -struct kvec *tail = rqstp->rq_arg.tail;u32 beginoffset, totalcount; -size_t remaining;if (!svcxdr_decode_fhandle (xdr, &args->fh))return 0 ;
@@ -346,12 +343,8 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)return 0 ;if (args->len >NFSSVC_MAXBLKSIZE_V2 )return 0 ; - remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; - remaining -=xdr_stream_pos (xdr); -if (remaining <xdr_align_size (args->len)) +if (!xdr_stream_subsegment (xdr, &args->payload, args->len))return 0 ; - args->first.iov_base = xdr->p; - args->first.iov_len = head->iov_len -xdr_stream_pos (xdr);return 1 ; }
fs/nfsd/xdr.h +1 -1
@@ -33,7 +33,7 @@ struct nfsd_writeargs {svc_fh fh;__u32 offset;__u32 len; -struct kvec first; +struct xdr_buf payload; };struct nfsd_createargs {
fs/nfsd/xdr3.h +1 -1
@@ -40,7 +40,7 @@ struct nfsd3_writeargs {__u32 count;int stable;__u32 len; -struct kvec first; +struct xdr_buf payload; };struct nfsd3_createargs {
include/linux/sunrpc/svc.h +1 -2
@@ -531,8 +531,7 @@ int svc_encode_result_payload(struct svc_rqst *rqstp,unsigned int offset, unsigned int length);unsigned int svc_fill_write_vector (struct svc_rqst *rqstp, -struct page **pages, -struct kvec *first,size_t total); +struct xdr_buf *payload);char *svc_fill_symlink_pathname (struct svc_rqst *rqstp,struct kvec *first,void *p,size_t total);
net/sunrpc/svc.c +6 -5
@@ -1654,16 +1654,17 @@ EXPORT_SYMBOL_GPL(svc_encode_result_payload);/** * svc_fill_write_vector - Construct data argument for VFS write call * @rqstp: svc_rqst to operate on -* @pages: list of pages containing data payload -* @first: buffer containing first section of write payload -* @total: total number of bytes of write payload +* @payload: xdr_buf containing only the write data payload * * Fills in rqstp::rq_vec, and returns the number of elements. */ -unsigned int svc_fill_write_vector (struct svc_rqst *rqstp,struct page **pages, -struct kvec *first,size_t total) +unsigned int svc_fill_write_vector (struct svc_rqst *rqstp, +struct xdr_buf *payload) { +struct page **pages = payload->pages; +struct kvec *first = payload->head;struct kvec *vec = rqstp->rq_vec; +size_t total = payload->len;unsigned int i;/* Some types of transport can present the write payload
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 395/770 SUNRPC: Replace the "__be32 *p" parameter to .pc_decode
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 16c663642c7ec03cd4cee5fec520bb69e97babe4 ]
The passed-in value of the "__be32 *p" parameter is now unused in every server-side XDR decoder, and can be removed.
Note also that there is a line in each decoder that sets up a local pointer to a struct xdr_stream. Passing that pointer from the dispatcher instead saves one line per decoder function.
--- fs/lockd/svc.c | 3 +-- fs/lockd/xdr.c | 27 +++++++++-------------- fs/lockd/xdr4.c | 27 +++++++++-------------- fs/nfsd/nfs2acl.c | 12 +++++----- fs/nfsd/nfs3acl.c | 8 +++---- fs/nfsd/nfs3xdr.c | 45 +++++++++++++------------------------- fs/nfsd/nfs4xdr.c | 4 ++-- fs/nfsd/nfsd.h | 3 ++- fs/nfsd/nfssvc.c | 7 +++--- fs/nfsd/nfsxdr.c | 30 +++++++++---------------- fs/nfsd/xdr.h | 21 +++++++++--------- fs/nfsd/xdr3.h | 31 +++++++++++++------------- fs/nfsd/xdr4.h | 2 +- include/linux/lockd/xdr.h | 19 ++++++++-------- include/linux/lockd/xdr4.h | 19 ++++++++-------- include/linux/sunrpc/svc.h | 3 ++- 16 files changed, 112 insertions(+), 149 deletions(-)
fs/lockd/svc.c +1 -2
@@ -780,11 +780,10 @@ module_exit(exit_nlm);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)) +if (!procp->pc_decode (rqstp, &rqstp->rq_arg_stream)) goto out_decode_err; *statp = procp->pc_func (rqstp);
fs/lockd/xdr.c +10 -17
@@ -146,15 +146,14 @@ svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)*/ int -nlmsvc_decode_void (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) {return 1 ; }int -nlmsvc_decode_testargs (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;
@@ -171,9 +170,8 @@ nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_decode_lockargs (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;
@@ -197,9 +195,8 @@ nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_decode_cancargs (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;
@@ -218,9 +215,8 @@ nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;if (!svcxdr_decode_cookie (xdr, &argp->cookie))
@@ -233,9 +229,8 @@ nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_decode_res (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_res *resp = rqstp->rq_argp;if (!svcxdr_decode_cookie (xdr, &resp->cookie))
@@ -247,10 +242,10 @@ nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_decode_reboot (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_reboot *argp = rqstp->rq_argp; +__be32 *p;u32 len;if (xdr_stream_decode_u32 (xdr, &len) <0 )
@@ -273,9 +268,8 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_decode_shareargs (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;struct nlm_lock *lock = &argp->lock;
@@ -301,9 +295,8 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_decode_notify (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;struct nlm_lock *lock = &argp->lock;
fs/lockd/xdr4.c +10 -17
@@ -145,15 +145,14 @@ svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)*/ int -nlm4svc_decode_void (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) {return 1 ; }int -nlm4svc_decode_testargs (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;
@@ -170,9 +169,8 @@ nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_decode_lockargs (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;
@@ -196,9 +194,8 @@ nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_decode_cancargs (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;
@@ -216,9 +213,8 @@ nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_decode_unlockargs (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;if (!svcxdr_decode_cookie (xdr, &argp->cookie))
@@ -231,9 +227,8 @@ nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_decode_res (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_res *resp = rqstp->rq_argp;if (!svcxdr_decode_cookie (xdr, &resp->cookie))
@@ -245,10 +240,10 @@ nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_decode_reboot (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_reboot *argp = rqstp->rq_argp; +__be32 *p;u32 len;if (xdr_stream_decode_u32 (xdr, &len) <0 )
@@ -271,9 +266,8 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_decode_shareargs (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;struct nlm_lock *lock = &argp->lock;
@@ -299,9 +293,8 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_decode_notify (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nlm_args *argp = rqstp->rq_argp;struct nlm_lock *lock = &argp->lock;
fs/nfsd/nfs2acl.c +6 -6
@@ -186,9 +186,9 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)* XDR decode functions */ -static int nfsaclsvc_decode_getaclargs (struct svc_rqst *rqstp,__be32 *p) +static int +nfsaclsvc_decode_getaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd3_getaclargs *argp = rqstp->rq_argp;if (!svcxdr_decode_fhandle (xdr, &argp->fh))
@@ -199,9 +199,9 @@ static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -static int nfsaclsvc_decode_setaclargs (struct svc_rqst *rqstp,__be32 *p) +static int +nfsaclsvc_decode_setaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd3_setaclargs *argp = rqstp->rq_argp;if (!svcxdr_decode_fhandle (xdr, &argp->fh))
@@ -220,9 +220,9 @@ static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -static int nfsaclsvc_decode_accessargs (struct svc_rqst *rqstp,__be32 *p) +static int +nfsaclsvc_decode_accessargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd3_accessargs *args = rqstp->rq_argp;if (!svcxdr_decode_fhandle (xdr, &args->fh))
fs/nfsd/nfs3acl.c +4 -4
@@ -125,9 +125,9 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)* XDR decode functions */ -static int nfs3svc_decode_getaclargs (struct svc_rqst *rqstp,__be32 *p) +static int +nfs3svc_decode_getaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd3_getaclargs *args = rqstp->rq_argp;if (!svcxdr_decode_nfs_fh3 (xdr, &args->fh))
@@ -138,9 +138,9 @@ static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p)return 1 ; } -static int nfs3svc_decode_setaclargs (struct svc_rqst *rqstp,__be32 *p) +static int +nfs3svc_decode_setaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd3_setaclargs *argp = rqstp->rq_argp;if (!svcxdr_decode_nfs_fh3 (xdr, &argp->fh))
fs/nfsd/nfs3xdr.c +15 -30
150 lines not on this page · raw message
fs/nfsd/nfs4xdr.c +2 -2
@@ -5423,14 +5423,14 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp) }int -nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,__be32 *p) +nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd4_compoundargs *args = rqstp->rq_argp;/* svcxdr_tmp_alloc */ args->to_free =NULL ; - args->xdr = &rqstp->rq_arg_stream; + args->xdr = xdr; args->ops = args->iops; args->rqstp = rqstp;
fs/nfsd/nfsd.h +2 -1
@@ -78,7 +78,8 @@ extern const struct seq_operations nfs_exports_op;*/ struct nfsd_voidargs { };struct nfsd_voidres { }; -int nfssvc_decode_voidarg (struct svc_rqst *rqstp,__be32 *p); +int nfssvc_decode_voidarg (struct svc_rqst *rqstp, +struct xdr_stream *xdr);int nfssvc_encode_voidres (struct svc_rqst *rqstp,__be32 *p);/*
fs/nfsd/nfssvc.c +3 -4
@@ -1004,7 +1004,6 @@ nfsd(void *vrqstp)int nfsd_dispatch (struct svc_rqst *rqstp,__be32 *statp) {const struct svc_procedure *proc = rqstp->rq_procinfo; -struct kvec *argv = &rqstp->rq_arg.head[0 ];struct kvec *resv = &rqstp->rq_res.head[0 ];__be32 *p;
@@ -1015,7 +1014,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) rqstp->rq_cachetype = proc->pc_cachetype;svcxdr_init_decode (rqstp); -if (!proc->pc_decode (rqstp, argv->iov_base)) +if (!proc->pc_decode (rqstp, &rqstp->rq_arg_stream)) goto out_decode_err;switch (nfsd_cache_lookup (rqstp)) {
@@ -1065,13 +1064,13 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)/** * nfssvc_decode_voidarg - Decode void arguments * @rqstp: Server RPC transaction context -* @p: buffer containing arguments to decode +* @xdr: XDR stream positioned at arguments to decode * * Return values: * %0: Arguments were not valid * %1: Decoding was successful */ -int nfssvc_decode_voidarg (struct svc_rqst *rqstp,__be32 *p) +int nfssvc_decode_voidarg (struct svc_rqst *rqstp,struct xdr_stream *xdr) {return 1 ; }
fs/nfsd/nfsxdr.c +10 -20
@@ -273,18 +273,16 @@ svcxdr_encode_fattr(struct svc_rqst *rqstp, struct xdr_stream *xdr,*/ int -nfssvc_decode_fhandleargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_fhandleargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_fhandle *args = rqstp->rq_argp;return svcxdr_decode_fhandle (xdr, &args->fh); }int -nfssvc_decode_sattrargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_sattrargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_sattrargs *args = rqstp->rq_argp; return svcxdr_decode_fhandle(xdr, &args->fh) &&
@@ -292,18 +290,16 @@ nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_decode_diropargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_diropargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_diropargs *args = rqstp->rq_argp;return svcxdr_decode_diropargs (xdr, &args->fh, &args->name, &args->len); }int -nfssvc_decode_readargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_readargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_readargs *args = rqstp->rq_argp;u32 totalcount;
@@ -321,9 +317,8 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_decode_writeargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_writeargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_writeargs *args = rqstp->rq_argp;u32 beginoffset, totalcount;
@@ -350,9 +345,8 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_decode_createargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_createargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_createargs *args = rqstp->rq_argp; return svcxdr_decode_diropargs(xdr, &args->fh,
@@ -361,9 +355,8 @@ nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_decode_renameargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_renameargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_renameargs *args = rqstp->rq_argp; return svcxdr_decode_diropargs(xdr, &args->ffh,
@@ -373,9 +366,8 @@ nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_decode_linkargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_linkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_linkargs *args = rqstp->rq_argp; return svcxdr_decode_fhandle(xdr, &args->ffh) &&
@@ -384,9 +376,8 @@ nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_decode_symlinkargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_symlinkargs *args = rqstp->rq_argp;struct kvec *head = rqstp->rq_arg.head;
@@ -405,9 +396,8 @@ nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_decode_readdirargs (struct svc_rqst *rqstp,__be32 *p) +nfssvc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_arg_stream;struct nfsd_readdirargs *args = rqstp->rq_argp;if (!svcxdr_decode_fhandle (xdr, &args->fh))
fs/nfsd/xdr.h +11 -10
@@ -141,16 +141,17 @@ union nfsd_xdrstore {#define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore) -int nfssvc_decode_fhandleargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_sattrargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_diropargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_readargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_writeargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_createargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_renameargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_linkargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_symlinkargs (struct svc_rqst *,__be32 *); -int nfssvc_decode_readdirargs (struct svc_rqst *,__be32 *); +int nfssvc_decode_fhandleargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_sattrargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_diropargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_readargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_writeargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_createargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_renameargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_linkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_encode_statres (struct svc_rqst *,__be32 *);int nfssvc_encode_attrstatres (struct svc_rqst *,__be32 *);int nfssvc_encode_diropres (struct svc_rqst *,__be32 *);
fs/nfsd/xdr3.h +16 -15
@@ -265,21 +265,22 @@ union nfsd3_xdrstore {#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) -int nfs3svc_decode_fhandleargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_sattrargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_diropargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_accessargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_readargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_writeargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_createargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_mkdirargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_mknodargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_renameargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_linkargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_symlinkargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_readdirargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_readdirplusargs (struct svc_rqst *,__be32 *); -int nfs3svc_decode_commitargs (struct svc_rqst *,__be32 *); +int nfs3svc_decode_fhandleargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_sattrargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_diropargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_accessargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_readargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_writeargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_createargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_mkdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_mknodargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_renameargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_linkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_readdirplusargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_decode_commitargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_getattrres (struct svc_rqst *,__be32 *);int nfs3svc_encode_wccstat (struct svc_rqst *,__be32 *);int nfs3svc_encode_lookupres (struct svc_rqst *,__be32 *);
fs/nfsd/xdr4.h +1 -1
@@ -756,7 +756,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)bool nfsd4_mach_creds_match (struct nfs4_client *cl,struct svc_rqst *rqstp); -int nfs4svc_decode_compoundargs (struct svc_rqst *,__be32 *); +int nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);int nfs4svc_encode_compoundres (struct svc_rqst *,__be32 *);__be32 nfsd4_check_resp_size (struct nfsd4_compoundres *,u32 );void nfsd4_encode_operation (struct nfsd4_compoundres *,struct nfsd4_op *);
include/linux/lockd/xdr.h +10 -9
@@ -96,18 +96,19 @@ struct nlm_reboot {*/ #define NLMSVC_XDRSIZE sizeof(struct nlm_args) -int nlmsvc_decode_testargs (struct svc_rqst *,__be32 *); +int nlmsvc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_encode_testres (struct svc_rqst *,__be32 *); -int nlmsvc_decode_lockargs (struct svc_rqst *,__be32 *); -int nlmsvc_decode_cancargs (struct svc_rqst *,__be32 *); -int nlmsvc_decode_unlockargs (struct svc_rqst *,__be32 *);int nlmsvc_encode_res (struct svc_rqst *,__be32 *); -int nlmsvc_decode_res (struct svc_rqst *,__be32 *);int nlmsvc_encode_void (struct svc_rqst *,__be32 *); -int nlmsvc_decode_void (struct svc_rqst *,__be32 *); -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 *);#endif /* LOCKD_XDR_H */
include/linux/lockd/xdr4.h +9 -10
@@ -22,21 +22,20 @@#define nlm4_fbig cpu_to_be32(NLM_FBIG)#define nlm4_failed cpu_to_be32(NLM_FAILED) +int nlm4svc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); - -int nlm4svc_decode_testargs (struct svc_rqst *,__be32 *);int nlm4svc_encode_testres (struct svc_rqst *,__be32 *); -int nlm4svc_decode_lockargs (struct svc_rqst *,__be32 *); -int nlm4svc_decode_cancargs (struct svc_rqst *,__be32 *); -int nlm4svc_decode_unlockargs (struct svc_rqst *,__be32 *);int nlm4svc_encode_res (struct svc_rqst *,__be32 *); -int nlm4svc_decode_res (struct svc_rqst *,__be32 *);int nlm4svc_encode_void (struct svc_rqst *,__be32 *); -int nlm4svc_decode_void (struct svc_rqst *,__be32 *); -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 *);extern const struct rpc_version nlm_version4;
include/linux/sunrpc/svc.h +2 -1
@@ -457,7 +457,8 @@ struct svc_procedure {/* process the request: */ __be32 (*pc_func)(struct svc_rqst *);/* XDR decode args: */ -int (*pc_decode)(struct svc_rqst *,__be32 *data); +int (*pc_decode)(struct svc_rqst *rqstp, +struct xdr_stream *xdr);/* XDR encode result: */ int (*pc_encode)(struct svc_rqst *,__be32 *data);/* XDR free result: */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 396/770 SUNRPC: Change return value type of .pc_decode
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 c44b31c263798ec34614dd394c31ef1a2e7e716e ]
Returning an undecorated integer is an age-old trope, but it's not clear (even to previous experts in this code) that the only valid return values are 1 and 0. These functions do not return a negative errno, rpc_stat value, or a positive length.
Document there are only two valid return values by having .pc_decode return only true or false.
--- fs/lockd/xdr.c | 96 +++++++++++++++--------------- fs/lockd/xdr4.c | 97 +++++++++++++++--------------- fs/nfsd/nfs2acl.c | 30 +++++----- fs/nfsd/nfs3acl.c | 22 +++---- fs/nfsd/nfs3xdr.c | 118 ++++++++++++++++++------------------- fs/nfsd/nfs4xdr.c | 24 ++++---- fs/nfsd/nfsd.h | 2 +- fs/nfsd/nfssvc.c | 6 +- fs/nfsd/nfsxdr.c | 62 +++++++++---------- fs/nfsd/xdr.h | 20 +++---- fs/nfsd/xdr3.h | 30 +++++----- fs/nfsd/xdr4.h | 2 +- include/linux/lockd/xdr.h | 18 +++--- include/linux/lockd/xdr4.h | 18 +++--- include/linux/sunrpc/svc.h | 2 +- 15 files changed, 274 insertions(+), 273 deletions(-)
fs/lockd/xdr.c +48 -48
@@ -145,103 +145,103 @@ svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)* Decode Call arguments */ -int +bool nlmsvc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -return 1 ; +return true; } -int +bool nlmsvc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;if (!svcxdr_decode_cookie (xdr, &argp->cookie)) -return 0 ; +return false;if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) -return 0 ; +return false;if (!svcxdr_decode_lock (xdr, &argp->lock)) -return 0 ; +return false;if (exclusive) argp->lock.fl.fl_type =F_WRLCK ; -return 1 ; +return true; } -int +bool nlmsvc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;if (!svcxdr_decode_cookie (xdr, &argp->cookie)) -return 0 ; +return false;if (xdr_stream_decode_bool (xdr, &argp->block) <0 ) -return 0 ; +return false;if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) -return 0 ; +return false;if (!svcxdr_decode_lock (xdr, &argp->lock)) -return 0 ; +return false;if (exclusive) argp->lock.fl.fl_type =F_WRLCK ;if (xdr_stream_decode_bool (xdr, &argp->reclaim) <0 ) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) -return 0 ; +return false; argp->monitor =1 ;/* monitor client by default */ -return 1 ; +return true; } -int +bool nlmsvc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_args *argp = rqstp->rq_argp;u32 exclusive;if (!svcxdr_decode_cookie (xdr, &argp->cookie)) -return 0 ; +return false;if (xdr_stream_decode_bool (xdr, &argp->block) <0 ) -return 0 ; +return false;if (xdr_stream_decode_bool (xdr, &exclusive) <0 ) -return 0 ; +return false;if (!svcxdr_decode_lock (xdr, &argp->lock)) -return 0 ; +return false;if (exclusive) argp->lock.fl.fl_type =F_WRLCK ; -return 1 ; +return true; } -int +bool nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_args *argp = rqstp->rq_argp;if (!svcxdr_decode_cookie (xdr, &argp->cookie)) -return 0 ; +return false;if (!svcxdr_decode_lock (xdr, &argp->lock)) -return 0 ; +return false; argp->lock.fl.fl_type =F_UNLCK ; -return 1 ; +return true; } -int +bool nlmsvc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_res *resp = rqstp->rq_argp;if (!svcxdr_decode_cookie (xdr, &resp->cookie)) -return 0 ; +return false;if (!svcxdr_decode_stats (xdr, &resp->status)) -return 0 ; +return false; -return 1 ; +return true; } -int +bool nlmsvc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_reboot *argp = rqstp->rq_argp;
@@ -249,25 +249,25 @@ nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)u32 len;if (xdr_stream_decode_u32 (xdr, &len) <0 ) -return 0 ; +return false;if (len >SM_MAXSTRLEN ) -return 0 ; +return false; p =xdr_inline_decode (xdr, len);if (!p) -return 0 ; +return false; argp->len = len; argp->mon = (char *)p;if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) -return 0 ; +return false; p =xdr_inline_decode (xdr,SM_PRIV_SIZE );if (!p) -return 0 ; +return false;memcpy (&argp->priv.data, p,sizeof (argp->priv.data)); -return 1 ; +return true; } -int +bool nlmsvc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_args *argp = rqstp->rq_argp;
@@ -278,34 +278,34 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) lock->svid = ~(u32 )0 ;if (!svcxdr_decode_cookie (xdr, &argp->cookie)) -return 0 ; +return false;if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) -return 0 ; +return false;if (!svcxdr_decode_fhandle (xdr, &lock->fh)) -return 0 ; +return false;if (!svcxdr_decode_owner (xdr, &lock->oh)) -return 0 ; +return false;/* XXX: Range checks are missing in the original code */ if (xdr_stream_decode_u32 (xdr, &argp->fsm_mode) <0 ) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &argp->fsm_access) <0 ) -return 0 ; +return false; -return 1 ; +return true; } -int +bool nlmsvc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_args *argp = rqstp->rq_argp;struct nlm_lock *lock = &argp->lock;if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len)) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &argp->state) <0 ) -return 0 ; +return false; -return 1 ; +return true; }
fs/lockd/xdr4.c +49 -48
210 lines not on this page · raw message
fs/nfsd/nfs2acl.c +15 -15
@@ -186,51 +186,51 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp)* XDR decode functions */ -static int +static bool nfsaclsvc_decode_getaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_getaclargs *argp = rqstp->rq_argp;if (!svcxdr_decode_fhandle (xdr, &argp->fh)) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &argp->mask) <0 ) -return 0 ; +return false; -return 1 ; +return true; } -static int +static bool nfsaclsvc_decode_setaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_setaclargs *argp = rqstp->rq_argp;if (!svcxdr_decode_fhandle (xdr, &argp->fh)) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &argp->mask) <0 ) -return 0 ; +return false;if (argp->mask & ~NFS_ACL_MASK ) -return 0 ; +return false;if (!nfs_stream_decode_acl (xdr,NULL , (argp->mask &NFS_ACL ) ? &argp->acl_access :NULL )) -return 0 ; +return false;if (!nfs_stream_decode_acl (xdr,NULL , (argp->mask &NFS_DFACL ) ? &argp->acl_default :NULL )) -return 0 ; +return false; -return 1 ; +return true; } -static int +static bool nfsaclsvc_decode_accessargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_accessargs *args = rqstp->rq_argp;if (!svcxdr_decode_fhandle (xdr, &args->fh)) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &args->access) <0 ) -return 0 ; +return false; -return 1 ; +return true; }/*
fs/nfsd/nfs3acl.c +11 -11
@@ -125,38 +125,38 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)* XDR decode functions */ -static int +static bool nfs3svc_decode_getaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_getaclargs *args = rqstp->rq_argp;if (!svcxdr_decode_nfs_fh3 (xdr, &args->fh)) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &args->mask) <0 ) -return 0 ; +return false; -return 1 ; +return true; } -static int +static bool nfs3svc_decode_setaclargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_setaclargs *argp = rqstp->rq_argp;if (!svcxdr_decode_nfs_fh3 (xdr, &argp->fh)) -return 0 ; +return false;if (xdr_stream_decode_u32 (xdr, &argp->mask) <0 ) -return 0 ; +return false;if (argp->mask & ~NFS_ACL_MASK ) -return 0 ; +return false;if (!nfs_stream_decode_acl (xdr,NULL , (argp->mask &NFS_ACL ) ? &argp->acl_access :NULL )) -return 0 ; +return false;if (!nfs_stream_decode_acl (xdr,NULL , (argp->mask &NFS_DFACL ) ? &argp->acl_default :NULL )) -return 0 ; +return false; -return 1 ; +return true; }/*
fs/nfsd/nfs3xdr.c +59 -59
289 lines not on this page · raw message
fs/nfsd/nfs4xdr.c +12 -12
@@ -2322,7 +2322,7 @@ nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)return true; } -static int +static bool nfsd4_decode_compound (struct nfsd4_compoundargs *argp) {struct nfsd4_op *op;
@@ -2335,25 +2335,25 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)int i;if (xdr_stream_decode_u32 (argp->xdr, &argp->taglen) <0 ) -return 0 ; +return false; max_reply +=XDR_UNIT ; argp->tag =NULL ;if (unlikely (argp->taglen)) {if (argp->taglen >NFSD4_MAX_TAGLEN ) -return 0 ; +return false; p =xdr_inline_decode (argp->xdr, argp->taglen);if (!p) -return 0 ; +return false; argp->tag =svcxdr_savemem (argp, p, argp->taglen);if (!argp->tag) -return 0 ; +return false; max_reply +=xdr_align_size (argp->taglen); }if (xdr_stream_decode_u32 (argp->xdr, &argp->minorversion) <0 ) -return 0 ; +return false;if (xdr_stream_decode_u32 (argp->xdr, &argp->opcnt) <0 ) -return 0 ; +return false;/* * NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
@@ -2361,14 +2361,14 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)* nfsd4_proc can handle this is an NFS-level error. */ if (argp->opcnt >NFSD_MAX_OPS_PER_COMPOUND ) -return 1 ; +return true;if (argp->opcnt >ARRAY_SIZE (argp->iops)) { argp->ops =kzalloc (argp->opcnt *sizeof (*argp->ops),GFP_KERNEL );if (!argp->ops) { argp->ops = argp->iops;dprintk ("nfsd: couldn't allocate room for COMPOUND\n" ); -return 0 ; +return false; } }
@@ -2380,7 +2380,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) op->replay =NULL ;if (xdr_stream_decode_u32 (argp->xdr, &op->opnum) <0 ) -return 0 ; +return false;if (nfsd4_opnum_in_range (argp, op)) { op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);if (op->status != nfs_ok)
@@ -2427,7 +2427,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)if (readcount >1 || max_reply >PAGE_SIZE - auth_slack)clear_bit (RQ_SPLICE_OK , &argp->rqstp->rq_flags); -return 1 ; +return true; } static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
@@ -5422,7 +5422,7 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp) } } -int +bool nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd4_compoundargs *args = rqstp->rq_argp;
fs/nfsd/nfsd.h +1 -1
@@ -78,7 +78,7 @@ extern const struct seq_operations nfs_exports_op;*/ struct nfsd_voidargs { };struct nfsd_voidres { }; -int nfssvc_decode_voidarg (struct svc_rqst *rqstp, +bool nfssvc_decode_voidarg (struct svc_rqst *rqstp,struct xdr_stream *xdr);int nfssvc_encode_voidres (struct svc_rqst *rqstp,__be32 *p);
fs/nfsd/nfssvc.c +3 -3
@@ -1067,10 +1067,10 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)* @xdr: XDR stream positioned at arguments to decode * * Return values: -* %0: Arguments were not valid -* %1: Decoding was successful +* %false: Arguments were not valid +* %true: Decoding was successful */ -int nfssvc_decode_voidarg (struct svc_rqst *rqstp,struct xdr_stream *xdr) +bool nfssvc_decode_voidarg (struct svc_rqst *rqstp,struct xdr_stream *xdr) {return 1 ; }
fs/nfsd/nfsxdr.c +31 -31
159 lines not on this page · raw message
fs/nfsd/xdr.h +10 -10
@@ -141,16 +141,16 @@ union nfsd_xdrstore {#define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore) -int nfssvc_decode_fhandleargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_sattrargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_diropargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_readargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_writeargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_createargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_renameargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_linkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_fhandleargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_sattrargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_diropargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_readargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_writeargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_createargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_renameargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_linkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);int nfssvc_encode_statres (struct svc_rqst *,__be32 *);int nfssvc_encode_attrstatres (struct svc_rqst *,__be32 *);
fs/nfsd/xdr3.h +15 -15
@@ -265,21 +265,21 @@ union nfsd3_xdrstore {#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) -int nfs3svc_decode_fhandleargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_sattrargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_diropargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_accessargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_readargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_writeargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_createargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_mkdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_mknodargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_renameargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_linkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_readdirplusargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_decode_commitargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_fhandleargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_sattrargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_diropargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_accessargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_readargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_writeargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_createargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_mkdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_mknodargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_renameargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_linkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_readdirplusargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_decode_commitargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);int nfs3svc_encode_getattrres (struct svc_rqst *,__be32 *);int nfs3svc_encode_wccstat (struct svc_rqst *,__be32 *);
fs/nfsd/xdr4.h +1 -1
@@ -756,7 +756,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)bool nfsd4_mach_creds_match (struct nfs4_client *cl,struct svc_rqst *rqstp); -int nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);int nfs4svc_encode_compoundres (struct svc_rqst *,__be32 *);__be32 nfsd4_check_resp_size (struct nfsd4_compoundres *,u32 );void nfsd4_encode_operation (struct nfsd4_compoundres *,struct nfsd4_op *);
include/linux/lockd/xdr.h +9 -9
@@ -96,15 +96,15 @@ struct nlm_reboot {*/ #define NLMSVC_XDRSIZE sizeof(struct nlm_args) -int nlmsvc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr);int nlmsvc_encode_testres (struct svc_rqst *,__be32 *);int nlmsvc_encode_res (struct svc_rqst *,__be32 *);
include/linux/lockd/xdr4.h +9 -9
@@ -22,15 +22,15 @@#define nlm4_fbig cpu_to_be32(NLM_FBIG)#define nlm4_failed cpu_to_be32(NLM_FAILED) -int nlm4svc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_testargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_lockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_cancargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_unlockargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_reboot (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr);int nlm4svc_encode_testres (struct svc_rqst *,__be32 *);int nlm4svc_encode_res (struct svc_rqst *,__be32 *);
include/linux/sunrpc/svc.h +1 -1
@@ -457,7 +457,7 @@ struct svc_procedure {/* process the request: */ __be32 (*pc_func)(struct svc_rqst *);/* XDR decode args: */ -int (*pc_decode)(struct svc_rqst *rqstp, +bool (*pc_decode)(struct svc_rqst *rqstp,struct xdr_stream *xdr);/* XDR encode result: */ int (*pc_encode)(struct svc_rqst *,__be32 *data);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 397/770 NFSD: Save location of NFSv4 COMPOUND status
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 3b0ebb255fdc49a3d340846deebf045ef58ec744 ]
Refactor: Currently nfs4svc_encode_compoundres() relies on the NFS dispatcher to pass in the buffer location of the COMPOUND status. Instead, save that buffer location in struct nfsd4_compoundres.
The compound tag follows immediately after.
--- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4xdr.c | 9 +++++++-- fs/nfsd/xdr4.h | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -2456,11 +2456,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)__be32 status; resp->xdr = &rqstp->rq_res_stream; + resp->statusp = resp->xdr->p;/* reserve space for: NFS status code */ xdr_reserve_space (resp->xdr,XDR_UNIT ); - resp->tagp = resp->xdr->p;/* reserve space for: taglen, tag, and opcnt */ xdr_reserve_space (resp->xdr,XDR_UNIT *2 + args->taglen); resp->taglen = args->taglen;
fs/nfsd/nfs4xdr.c +7 -2
@@ -5446,11 +5446,16 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p)WARN_ON_ONCE (buf->len != buf->head[0 ].iov_len + buf->page_len + buf->tail[0 ].iov_len); - *p = resp->cstate.status; +/* +* Send buffer space for the following items is reserved +* at the top of nfsd4_proc_compound(). +*/ + p = resp->statusp; + + *p++ = resp->cstate.status; rqstp->rq_next_page = resp->xdr->page_ptr +1 ; - p = resp->tagp; *p++ =htonl (resp->taglen);memcpy (p, resp->tag, resp->taglen); p +=XDR_QUADLEN (resp->taglen);
fs/nfsd/xdr4.h +2 -1
@@ -702,10 +702,11 @@ struct nfsd4_compoundres {struct xdr_stream *xdr;struct svc_rqst * rqstp; +__be32 *statusp;u32 taglen;char * tag;u32 opcnt; -__be32 * tagp;/* tag, opcount encode location */ +struct nfsd4_compound_state cstate; };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 398/770 SUNRPC: Replace the "__be32 *p" parameter to .pc_encode
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 fda494411485aff91768842c532f90fb8eb54943 ]
The passed-in value of the "__be32 *p" parameter is now unused in every server-side XDR encoder, and can be removed.
Note also that there is a line in each encoder that sets up a local pointer to a struct xdr_stream. Passing that pointer from the dispatcher instead saves one line per encoder function.
--- fs/lockd/svc.c | 3 +-- fs/lockd/xdr.c | 11 ++++----- fs/lockd/xdr4.c | 11 ++++----- fs/nfs/callback_xdr.c | 4 ++-- fs/nfsd/nfs2acl.c | 8 +++---- fs/nfsd/nfs3acl.c | 8 +++---- fs/nfsd/nfs3xdr.c | 46 +++++++++++++------------------------- fs/nfsd/nfs4xdr.c | 7 +++--- fs/nfsd/nfsd.h | 3 ++- fs/nfsd/nfssvc.c | 9 +++----- fs/nfsd/nfsxdr.c | 22 +++++++----------- fs/nfsd/xdr.h | 14 ++++++------ fs/nfsd/xdr3.h | 30 ++++++++++++------------- fs/nfsd/xdr4.h | 2 +- include/linux/lockd/xdr.h | 8 +++---- include/linux/lockd/xdr4.h | 8 +++---- include/linux/sunrpc/svc.h | 3 ++- 17 files changed, 85 insertions(+), 112 deletions(-)
fs/lockd/svc.c +1 -2
@@ -780,7 +780,6 @@ module_exit(exit_nlm);static int nlmsvc_dispatch (struct svc_rqst *rqstp,__be32 *statp) {const struct svc_procedure *procp = rqstp->rq_procinfo; -struct kvec *resv = rqstp->rq_res.head;svcxdr_init_decode (rqstp);if (!procp->pc_decode (rqstp, &rqstp->rq_arg_stream))
@@ -793,7 +792,7 @@ static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp)return 1 ;svcxdr_init_encode (rqstp); -if (!procp->pc_encode (rqstp, resv->iov_base + resv->iov_len)) +if (!procp->pc_encode (rqstp, &rqstp->rq_res_stream)) goto out_encode_err;return 1 ;
fs/lockd/xdr.c +4 -7
@@ -314,15 +314,14 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)*/ int -nlmsvc_encode_void (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) {return 1 ; }int -nlmsvc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; return svcxdr_encode_cookie(xdr, &resp->cookie) &&
@@ -330,9 +329,8 @@ nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_encode_res (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; return svcxdr_encode_cookie(xdr, &resp->cookie) &&
@@ -340,9 +338,8 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p) }int -nlmsvc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) +nlmsvc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp;if (!svcxdr_encode_cookie (xdr, &resp->cookie))
fs/lockd/xdr4.c +4 -7
@@ -313,15 +313,14 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)*/ int -nlm4svc_encode_void (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) {return 1 ; }int -nlm4svc_encode_testres (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; return svcxdr_encode_cookie(xdr, &resp->cookie) &&
@@ -329,9 +328,8 @@ nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_encode_res (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp; return svcxdr_encode_cookie(xdr, &resp->cookie) &&
@@ -339,9 +337,8 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p) }int -nlm4svc_encode_shareres (struct svc_rqst *rqstp,__be32 *p) +nlm4svc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nlm_res *resp = rqstp->rq_resp;if (!svcxdr_encode_cookie (xdr, &resp->cookie))
fs/nfs/callback_xdr.c +2 -2
@@ -67,9 +67,9 @@ static __be32 nfs4_callback_null(struct svc_rqst *rqstp)* svc_process_common() looks for an XDR encoder to know when * not to drop a Reply. */ -static int nfs4_encode_void (struct svc_rqst *rqstp,__be32 *p) +static int nfs4_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -return xdr_ressize_check (rqstp, p); +return 1 ; } static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len,
fs/nfsd/nfs2acl.c +4 -4
@@ -238,9 +238,9 @@ nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)*/ /* GETACL */ -static int nfsaclsvc_encode_getaclres (struct svc_rqst *rqstp,__be32 *p) +static int +nfsaclsvc_encode_getaclres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd3_getaclres *resp = rqstp->rq_resp;struct dentry *dentry = resp->fh.fh_dentry;struct inode *inode;
@@ -278,9 +278,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) }/* ACCESS */ -static int nfsaclsvc_encode_accessres (struct svc_rqst *rqstp,__be32 *p) +static int +nfsaclsvc_encode_accessres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd3_accessres *resp = rqstp->rq_resp;if (!svcxdr_encode_stat (xdr, resp->status))
fs/nfsd/nfs3acl.c +4 -4
@@ -164,9 +164,9 @@ nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)*/ /* GETACL */ -static int nfs3svc_encode_getaclres (struct svc_rqst *rqstp,__be32 *p) +static int +nfs3svc_encode_getaclres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -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;
@@ -216,9 +216,9 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) }/* SETACL */ -static int nfs3svc_encode_setaclres (struct svc_rqst *rqstp,__be32 *p) +static int +nfs3svc_encode_setaclres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd3_attrstat *resp = rqstp->rq_resp; return svcxdr_encode_nfsstat3(xdr, resp->status) &&
fs/nfsd/nfs3xdr.c +16 -30
151 lines not on this page · raw message
fs/nfsd/nfs4xdr.c +4 -3
@@ -5438,10 +5438,11 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) }int -nfs4svc_encode_compoundres (struct svc_rqst *rqstp,__be32 *p) +nfs4svc_encode_compoundres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd4_compoundres *resp = rqstp->rq_resp; -struct xdr_buf *buf = resp->xdr->buf; +struct xdr_buf *buf = xdr->buf; +__be32 *p;WARN_ON_ONCE (buf->len != buf->head[0 ].iov_len + buf->page_len + buf->tail[0 ].iov_len);
@@ -5454,7 +5455,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p) *p++ = resp->cstate.status; - rqstp->rq_next_page = resp->xdr->page_ptr +1 ; + rqstp->rq_next_page = xdr->page_ptr +1 ; *p++ =htonl (resp->taglen);memcpy (p, resp->tag, resp->taglen);
fs/nfsd/nfsd.h +2 -1
@@ -80,7 +80,8 @@ struct nfsd_voidargs { };struct nfsd_voidres { };bool nfssvc_decode_voidarg (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_voidres (struct svc_rqst *rqstp,__be32 *p); +int nfssvc_encode_voidres (struct svc_rqst *rqstp, +struct xdr_stream *xdr);/* * Function prototypes.
fs/nfsd/nfssvc.c +3 -6
@@ -1004,8 +1004,6 @@ nfsd(void *vrqstp)int nfsd_dispatch (struct svc_rqst *rqstp,__be32 *statp) {const struct svc_procedure *proc = rqstp->rq_procinfo; -struct kvec *resv = &rqstp->rq_res.head[0 ]; -__be32 *p;/* * Give the xdr decoder a chance to change this if it wants
@@ -1030,14 +1028,13 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)* Need to grab the location to store the status, as * NFSv4 does some encoding while processing */ - p = resv->iov_base + resv->iov_len;svcxdr_init_encode (rqstp); *statp = proc->pc_func (rqstp);if (*statp == rpc_drop_reply ||test_bit (RQ_DROPME , &rqstp->rq_flags)) goto out_update_drop; -if (!proc->pc_encode (rqstp, p)) +if (!proc->pc_encode (rqstp, &rqstp->rq_res_stream)) goto out_encode_err;nfsd_cache_update (rqstp, rqstp->rq_cachetype, statp +1 );
@@ -1078,13 +1075,13 @@ bool nfssvc_decode_voidarg(struct svc_rqst *rqstp, struct xdr_stream *xdr)/** * nfssvc_encode_voidres - Encode void results * @rqstp: Server RPC transaction context -* @p: buffer in which to encode results +* @xdr: XDR stream into which to encode results * * Return values: * %0: Local error while encoding * %1: Encoding was successful */ -int nfssvc_encode_voidres (struct svc_rqst *rqstp,__be32 *p) +int nfssvc_encode_voidres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {return 1 ; }
fs/nfsd/nfsxdr.c +8 -14
@@ -415,18 +415,16 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)*/ int -nfssvc_encode_statres (struct svc_rqst *rqstp,__be32 *p) +nfssvc_encode_statres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd_stat *resp = rqstp->rq_resp;return svcxdr_encode_stat (xdr, resp->status); }int -nfssvc_encode_attrstatres (struct svc_rqst *rqstp,__be32 *p) +nfssvc_encode_attrstatres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd_attrstat *resp = rqstp->rq_resp;if (!svcxdr_encode_stat (xdr, resp->status))
@@ -442,9 +440,8 @@ nfssvc_encode_attrstatres(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_encode_diropres (struct svc_rqst *rqstp,__be32 *p) +nfssvc_encode_diropres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd_diropres *resp = rqstp->rq_resp;if (!svcxdr_encode_stat (xdr, resp->status))
@@ -462,9 +459,8 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_encode_readlinkres (struct svc_rqst *rqstp,__be32 *p) +nfssvc_encode_readlinkres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd_readlinkres *resp = rqstp->rq_resp;struct kvec *head = rqstp->rq_res.head;
@@ -484,9 +480,8 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_encode_readres (struct svc_rqst *rqstp,__be32 *p) +nfssvc_encode_readres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd_readres *resp = rqstp->rq_resp;struct kvec *head = rqstp->rq_res.head;
@@ -509,9 +504,8 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_encode_readdirres (struct svc_rqst *rqstp,__be32 *p) +nfssvc_encode_readdirres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd_readdirres *resp = rqstp->rq_resp;struct xdr_buf *dirlist = &resp->dirlist;
@@ -532,11 +526,11 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p) }int -nfssvc_encode_statfsres (struct svc_rqst *rqstp,__be32 *p) +nfssvc_encode_statfsres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -struct xdr_stream *xdr = &rqstp->rq_res_stream;struct nfsd_statfsres *resp = rqstp->rq_resp;struct kstatfs *stat = &resp->stats; +__be32 *p;if (!svcxdr_encode_stat (xdr, resp->status))return 0 ;
fs/nfsd/xdr.h +7 -7
@@ -152,13 +152,13 @@ bool nfssvc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nfssvc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nfssvc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_statres (struct svc_rqst *,__be32 *); -int nfssvc_encode_attrstatres (struct svc_rqst *,__be32 *); -int nfssvc_encode_diropres (struct svc_rqst *,__be32 *); -int nfssvc_encode_readlinkres (struct svc_rqst *,__be32 *); -int nfssvc_encode_readres (struct svc_rqst *,__be32 *); -int nfssvc_encode_statfsres (struct svc_rqst *,__be32 *); -int nfssvc_encode_readdirres (struct svc_rqst *,__be32 *); +int nfssvc_encode_statres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_encode_attrstatres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_encode_diropres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_encode_readlinkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_encode_readres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_encode_statfsres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfssvc_encode_readdirres (struct svc_rqst *rqstp,struct xdr_stream *xdr);void nfssvc_encode_nfscookie (struct nfsd_readdirres *resp,u32 offset); int nfssvc_encode_entry(void *data, const char *name, int namlen,
fs/nfsd/xdr3.h +15 -15
@@ -281,21 +281,21 @@ bool nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nfs3svc_decode_readdirplusargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nfs3svc_decode_commitargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_getattrres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_wccstat (struct svc_rqst *,__be32 *); -int nfs3svc_encode_lookupres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_accessres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_readlinkres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_readres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_writeres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_createres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_renameres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_linkres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_readdirres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_fsstatres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_fsinfores (struct svc_rqst *,__be32 *); -int nfs3svc_encode_pathconfres (struct svc_rqst *,__be32 *); -int nfs3svc_encode_commitres (struct svc_rqst *,__be32 *); +int nfs3svc_encode_getattrres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_wccstat (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_lookupres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_accessres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_readlinkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_readres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_writeres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_createres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_renameres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_linkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_readdirres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_fsstatres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_fsinfores (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_pathconfres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nfs3svc_encode_commitres (struct svc_rqst *rqstp,struct xdr_stream *xdr);void nfs3svc_release_fhandle (struct svc_rqst *);void nfs3svc_release_fhandle2 (struct svc_rqst *);
fs/nfsd/xdr4.h +1 -1
@@ -758,7 +758,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)bool nfsd4_mach_creds_match (struct nfs4_client *cl,struct svc_rqst *rqstp);bool nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs4svc_encode_compoundres (struct svc_rqst *,__be32 *); +int nfs4svc_encode_compoundres (struct svc_rqst *rqstp,struct xdr_stream *xdr);__be32 nfsd4_check_resp_size (struct nfsd4_compoundres *,u32 );void nfsd4_encode_operation (struct nfsd4_compoundres *,struct nfsd4_op *);void nfsd4_encode_replay (struct xdr_stream *xdr,struct nfsd4_op *op);
include/linux/lockd/xdr.h +4 -4
@@ -106,9 +106,9 @@ bool nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nlmsvc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nlmsvc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_encode_testres (struct svc_rqst *,__be32 *); -int nlmsvc_encode_res (struct svc_rqst *,__be32 *); -int nlmsvc_encode_void (struct svc_rqst *,__be32 *); -int nlmsvc_encode_shareres (struct svc_rqst *,__be32 *); +int nlmsvc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlmsvc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr);#endif /* LOCKD_XDR_H */
include/linux/lockd/xdr4.h +4 -4
@@ -32,10 +32,10 @@ bool nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nlm4svc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nlm4svc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_encode_testres (struct svc_rqst *,__be32 *); -int nlm4svc_encode_res (struct svc_rqst *,__be32 *); -int nlm4svc_encode_void (struct svc_rqst *,__be32 *); -int nlm4svc_encode_shareres (struct svc_rqst *,__be32 *); +int nlm4svc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +int nlm4svc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr);extern const struct rpc_version nlm_version4;
include/linux/sunrpc/svc.h +2 -1
@@ -460,7 +460,8 @@ struct svc_procedure {bool (*pc_decode)(struct svc_rqst *rqstp,struct xdr_stream *xdr);/* XDR encode result: */ -int (*pc_encode)(struct svc_rqst *,__be32 *data); +int (*pc_encode)(struct svc_rqst *rqstp, +struct xdr_stream *xdr);/* XDR free result: */ void (*pc_release)(struct svc_rqst *);unsigned int pc_argsize;/* argument struct size */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 399/770 SUNRPC: Change return value type of .pc_encode
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 130e2054d4a652a2bd79fb1557ddcd19c053cb37 ]
Returning an undecorated integer is an age-old trope, but it's not clear (even to previous experts in this code) that the only valid return values are 1 and 0. These functions do not return a negative errno, rpc_stat value, or a positive length.
Document there are only two valid return values by having .pc_encode return only true or false.
--- fs/lockd/xdr.c | 18 ++-- fs/lockd/xdr4.c | 18 ++-- fs/nfs/callback_xdr.c | 4 +- fs/nfsd/nfs2acl.c | 4 +- fs/nfsd/nfs3acl.c | 18 ++-- fs/nfsd/nfs3xdr.c | 166 ++++++++++++++++++------------------- fs/nfsd/nfs4xdr.c | 4 +- fs/nfsd/nfsd.h | 2 +- fs/nfsd/nfssvc.c | 8 +- fs/nfsd/nfsxdr.c | 60 +++++++------- fs/nfsd/xdr.h | 14 ++-- fs/nfsd/xdr3.h | 30 +++---- fs/nfsd/xdr4.h | 2 +- include/linux/lockd/xdr.h | 8 +- include/linux/lockd/xdr4.h | 8 +- include/linux/sunrpc/svc.h | 2 +- 16 files changed, 183 insertions(+), 183 deletions(-)
fs/lockd/xdr.c +9 -9
@@ -313,13 +313,13 @@ nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)* Encode Reply results */ -int +bool nlmsvc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -return 1 ; +return true; } -int +bool nlmsvc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_res *resp = rqstp->rq_resp;
@@ -328,7 +328,7 @@ nlmsvc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)svcxdr_encode_testrply (xdr, resp); } -int +bool nlmsvc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_res *resp = rqstp->rq_resp;
@@ -337,18 +337,18 @@ nlmsvc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)svcxdr_encode_stats (xdr, resp->status); } -int +bool nlmsvc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_res *resp = rqstp->rq_resp;if (!svcxdr_encode_cookie (xdr, &resp->cookie)) -return 0 ; +return false;if (!svcxdr_encode_stats (xdr, resp->status)) -return 0 ; +return false;/* sequence */ if (xdr_stream_encode_u32 (xdr,0 ) <0 ) -return 0 ; +return false; -return 1 ; +return true; }
fs/lockd/xdr4.c +9 -9
@@ -312,13 +312,13 @@ nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)* Encode Reply results */ -int +bool nlm4svc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -return 1 ; +return true; } -int +bool nlm4svc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_res *resp = rqstp->rq_resp;
@@ -327,7 +327,7 @@ nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)svcxdr_encode_testrply (xdr, resp); } -int +bool nlm4svc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_res *resp = rqstp->rq_resp;
@@ -336,18 +336,18 @@ nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)svcxdr_encode_stats (xdr, resp->status); } -int +bool nlm4svc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nlm_res *resp = rqstp->rq_resp;if (!svcxdr_encode_cookie (xdr, &resp->cookie)) -return 0 ; +return false;if (!svcxdr_encode_stats (xdr, resp->status)) -return 0 ; +return false;/* sequence */ if (xdr_stream_encode_u32 (xdr,0 ) <0 ) -return 0 ; +return false; -return 1 ; +return true; }
fs/nfs/callback_xdr.c +2 -2
@@ -67,9 +67,9 @@ static __be32 nfs4_callback_null(struct svc_rqst *rqstp)* svc_process_common() looks for an XDR encoder to know when * not to drop a Reply. */ -static int nfs4_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) +static bool nfs4_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -return 1 ; +return true; } static __be32 decode_string(struct xdr_stream *xdr, unsigned int *len,
fs/nfsd/nfs2acl.c +2 -2
@@ -238,7 +238,7 @@ nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)*/ /* GETACL */ -static int +static bool nfsaclsvc_encode_getaclres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_getaclres *resp = rqstp->rq_resp;
@@ -278,7 +278,7 @@ nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr) }/* ACCESS */ -static int +static bool nfsaclsvc_encode_accessres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_accessres *resp = rqstp->rq_resp;
fs/nfsd/nfs3acl.c +9 -9
@@ -164,7 +164,7 @@ nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)*/ /* GETACL */ -static int +static bool nfs3svc_encode_getaclres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_getaclres *resp = rqstp->rq_resp;
@@ -176,14 +176,14 @@ nfs3svc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr)int w;if (!svcxdr_encode_nfsstat3 (xdr, resp->status)) -return 0 ; +return false;switch (resp->status) {case nfs_ok: inode =d_inode (dentry);if (!svcxdr_encode_post_op_attr (rqstp, xdr, &resp->fh)) -return 0 ; +return false;if (xdr_stream_encode_u32 (xdr, resp->mask) <0 ) -return 0 ; +return false; base = (char *)xdr->p - (char *)head->iov_base;
@@ -192,7 +192,7 @@ nfs3svc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr) (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);while (w >0 ) {if (!*(rqstp->rq_next_page++)) -return 0 ; +return false; w -=PAGE_SIZE ; }
@@ -205,18 +205,18 @@ nfs3svc_encode_getaclres(struct svc_rqst *rqstp, struct xdr_stream *xdr) resp->mask &NFS_DFACL , NFS_ACL_DEFAULT);if (n <=0 ) -return 0 ; +return false;break ;default :if (!svcxdr_encode_post_op_attr (rqstp, xdr, &resp->fh)) -return 0 ; +return false; } -return 1 ; +return true; }/* SETACL */ -static int +static bool nfs3svc_encode_setaclres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd3_attrstat *resp = rqstp->rq_resp;
fs/nfsd/nfs3xdr.c +83 -83
416 lines not on this page · raw message
fs/nfsd/nfs4xdr.c +2 -2
@@ -5437,7 +5437,7 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)return nfsd4_decode_compound (args); } -int +bool nfs4svc_encode_compoundres (struct svc_rqst *rqstp,struct xdr_stream *xdr) {struct nfsd4_compoundres *resp = rqstp->rq_resp;
@@ -5463,7 +5463,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, struct xdr_stream *xdr) *p++ =htonl (resp->opcnt);nfsd4_sequence_done (resp); -return 1 ; +return true; }/*
fs/nfsd/nfsd.h +1 -1
@@ -80,7 +80,7 @@ struct nfsd_voidargs { };struct nfsd_voidres { };bool nfssvc_decode_voidarg (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_voidres (struct svc_rqst *rqstp, +bool nfssvc_encode_voidres (struct svc_rqst *rqstp,struct xdr_stream *xdr);/*
fs/nfsd/nfssvc.c +4 -4
@@ -1078,12 +1078,12 @@ bool nfssvc_decode_voidarg(struct svc_rqst *rqstp, struct xdr_stream *xdr)* @xdr: XDR stream into which to encode results * * Return values: -* %0: Local error while encoding -* %1: Encoding was successful +* %false: Local error while encoding +* %true: Encoding was successful */ -int nfssvc_encode_voidres (struct svc_rqst *rqstp,struct xdr_stream *xdr) +bool nfssvc_encode_voidres (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -return 1 ; +return true; }int nfsd_pool_stats_open (struct inode *inode,struct file *file)
fs/nfsd/nfsxdr.c +30 -30
166 lines not on this page · raw message
fs/nfsd/xdr.h +7 -7
@@ -152,13 +152,13 @@ bool nfssvc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nfssvc_decode_symlinkargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nfssvc_decode_readdirargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_statres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_attrstatres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_diropres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_readlinkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_readres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_statfsres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfssvc_encode_readdirres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_encode_statres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_encode_attrstatres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_encode_diropres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_encode_readlinkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_encode_readres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_encode_statfsres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfssvc_encode_readdirres (struct svc_rqst *rqstp,struct xdr_stream *xdr);void nfssvc_encode_nfscookie (struct nfsd_readdirres *resp,u32 offset); int nfssvc_encode_entry(void *data, const char *name, int namlen,
fs/nfsd/xdr3.h +15 -15
@@ -281,21 +281,21 @@ bool nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nfs3svc_decode_readdirplusargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nfs3svc_decode_commitargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_getattrres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_wccstat (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_lookupres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_accessres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_readlinkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_readres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_writeres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_createres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_renameres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_linkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_readdirres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_fsstatres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_fsinfores (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_pathconfres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs3svc_encode_commitres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_getattrres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_wccstat (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_lookupres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_accessres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_readlinkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_readres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_writeres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_createres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_renameres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_linkres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_readdirres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_fsstatres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_fsinfores (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_pathconfres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs3svc_encode_commitres (struct svc_rqst *rqstp,struct xdr_stream *xdr);void nfs3svc_release_fhandle (struct svc_rqst *);void nfs3svc_release_fhandle2 (struct svc_rqst *);
fs/nfsd/xdr4.h +1 -1
@@ -758,7 +758,7 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)bool nfsd4_mach_creds_match (struct nfs4_client *cl,struct svc_rqst *rqstp);bool nfs4svc_decode_compoundargs (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nfs4svc_encode_compoundres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nfs4svc_encode_compoundres (struct svc_rqst *rqstp,struct xdr_stream *xdr);__be32 nfsd4_check_resp_size (struct nfsd4_compoundres *,u32 );void nfsd4_encode_operation (struct nfsd4_compoundres *,struct nfsd4_op *);void nfsd4_encode_replay (struct xdr_stream *xdr,struct nfsd4_op *op);
include/linux/lockd/xdr.h +4 -4
@@ -106,9 +106,9 @@ bool nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nlmsvc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nlmsvc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlmsvc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlmsvc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr);#endif /* LOCKD_XDR_H */
include/linux/lockd/xdr4.h +4 -4
@@ -32,10 +32,10 @@ bool nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr);bool nlm4svc_decode_shareargs (struct svc_rqst *rqstp,struct xdr_stream *xdr);bool nlm4svc_decode_notify (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); -int nlm4svc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_encode_testres (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_encode_res (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_encode_void (struct svc_rqst *rqstp,struct xdr_stream *xdr); +bool nlm4svc_encode_shareres (struct svc_rqst *rqstp,struct xdr_stream *xdr);extern const struct rpc_version nlm_version4;
include/linux/sunrpc/svc.h +1 -1
@@ -460,7 +460,7 @@ struct svc_procedure {bool (*pc_decode)(struct svc_rqst *rqstp,struct xdr_stream *xdr);/* XDR encode result: */ -int (*pc_encode)(struct svc_rqst *rqstp, +bool (*pc_encode)(struct svc_rqst *rqstp,struct xdr_stream *xdr);/* XDR free result: */ void (*pc_release)(struct svc_rqst *);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 400/770 nfsd: update create verifier 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 2336d696862186fd4a6ddd1ea0cb243b3e32847c ]
I don't know if that Solaris behavior matters any more or if it's still possible to look up that bug ID any more. The XFS behavior's definitely still relevant, though; any but the most recent XFS filesystems will lose the top bits.
--- fs/nfsd/vfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nfsd/vfs.c +2 -1
@@ -1431,7 +1431,8 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,if (nfsd_create_is_exclusive (createmode)) {/* solaris7 gets confused (bugid 4218508) if these have -* the high bit set, so just clear the high bits. If this is +* the high bit set, as do xfs filesystems without the +* "bigtime" feature. So just clear the high bits. If this is * ever changed to use different attrs for storing the * verifier, then do_open_lookup() will also need to be fixed * accordingly.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 401/770 NFSD:fix boolreturn.cocci warning
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Changcheng Deng <[email protected]>
[ Upstream commit 291cd656da04163f4bba67953c1f2f823e0d1231 ]
./fs/nfsd/nfssvc.c: 1072: 8-9: :WARNING return of 0/1 in function 'nfssvc_decode_voidarg' with return type bool
Return statements in functions returning bool should use true/false instead of 1/0.
--- fs/nfsd/nfssvc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfssvc.c +1 -1
@@ -1069,7 +1069,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)*/ bool nfssvc_decode_voidarg (struct svc_rqst *rqstp,struct xdr_stream *xdr) { -return 1 ; +return true; }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 402/770 nfsd4: remove obselete 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 80479eb862102f9513e93fcf726c78cc0be2e3b2 ]
Mandatory locking has been removed. And the rest of this comment is redundant with the code.
--- fs/nfsd/vfs.c | 3 --- 1 file changed, 3 deletions(-)
fs/nfsd/vfs.c +0 -3
@@ -751,9 +751,6 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, path.dentry = fhp->fh_dentry; inode =d_inode (path.dentry); -/* Disallow write access to files with the append-only bit set -* or any access when mandatory locking enabled -*/ err = nfserr_perm;if (IS_APPEND (inode) && (may_flags &NFSD_MAY_WRITE )) goto out;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 403/770 NFSD: Fix exposure in nfsd4_decode_bitmap()
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 c0019b7db1d7ac62c711cda6b357a659d46428fe ]
[email protected] reports:
Quoted 5 lines
nfsd4_decode_bitmap4()will write beyond bmval[bmlen-1] if the RPC directs it to do so. This can causenfsd4_decode_state_protect4_a()to write client-supplied data beyond the end of nfsd4_exchange_id.spo_must_allow[] when called bynfsd4_decode_exchange_id().
Rewrite the loops so nfsd4_decode_bitmap() cannot iterate beyond @bmlen.
Reported by: [email protected]
--- fs/nfsd/nfs4xdr.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
fs/nfsd/nfs4xdr.c +2 -5
@@ -288,11 +288,8 @@ nfsd4_decode_bitmap4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen) p =xdr_inline_decode (argp->xdr, count <<2 );if (!p)return nfserr_bad_xdr; - i =0 ; -while (i < count) - bmval[i++] =be32_to_cpup (p++); -while (i < bmlen) - bmval[i++] =0 ; +for (i =0 ; i < bmlen; i++) + bmval[i] = (i < count) ?be32_to_cpup (p++) :0 ;return nfs_ok; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 404/770 NFSD: Fix READDIR buffer overflow
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 53b1119a6e5028b125f431a0116ba73510d82a72 ]
If a client sends a READDIR count argument that is too small (say, zero), then the buffer size calculation in the new init_dirlist helper functions results in an underflow, allowing the XDR stream functions to write beyond the actual buffer.
This calculation has always been suspect. NFSD has never sanity- checked the READDIR count argument, but the old entry encoders managed the problem correctly.
With the commits below, entry encoding changed, exposing the underflow to the pointer arithmetic in xdr_reserve_space().
Modern NFS clients attempt to retrieve as much data as possible for each READDIR request. Also, we have no unit tests that exercise the behavior of READDIR at the lower bound of @count values. Thus this case was missed during testing.
--- fs/nfsd/nfs3proc.c | 11 ++++------- fs/nfsd/nfsproc.c | 8 ++++---- 2 files changed, 8 insertions(+), 11 deletions(-)
fs/nfsd/nfs3proc.c +4 -7
@@ -443,22 +443,19 @@ nfsd3_proc_link(struct svc_rqst *rqstp)static void nfsd3_init_dirlist_pages (struct svc_rqst *rqstp,struct nfsd3_readdirres *resp, -int count) +u32 count) {struct xdr_buf *buf = &resp->dirlist;struct xdr_stream *xdr = &resp->xdr; - count =min_t (u32, count,svc_max_payload (rqstp)); + count =clamp (count, (u32)(XDR_UNIT *2 ),svc_max_payload (rqstp));memset (buf,0 ,sizeof (*buf));/* Reserve room for the NULL ptr & eof flag (-2 words) */ buf->buflen = count -XDR_UNIT *2 ; buf->pages = rqstp->rq_next_page; -while (count >0 ) { - rqstp->rq_next_page++; - count -=PAGE_SIZE ; - } + rqstp->rq_next_page += (buf->buflen +PAGE_SIZE -1 ) >>PAGE_SHIFT ;/* This is xdr_init_encode(), but it assumes that * the head kvec has already been consumed. */
@@ -467,7 +464,7 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp, xdr->page_ptr = buf->pages; xdr->iov =NULL ; xdr->p =page_address (*buf->pages); - xdr->end = xdr->p + (PAGE_SIZE >>2 ); + xdr->end = (void *)xdr->p +min_t (u32, buf->buflen,PAGE_SIZE ); xdr->rqst =NULL ; }
fs/nfsd/nfsproc.c +4 -4
@@ -556,17 +556,17 @@ nfsd_proc_rmdir(struct svc_rqst *rqstp)static void nfsd_init_dirlist_pages (struct svc_rqst *rqstp,struct nfsd_readdirres *resp, -int count) +u32 count) {struct xdr_buf *buf = &resp->dirlist;struct xdr_stream *xdr = &resp->xdr; - count =min_t (u32, count,PAGE_SIZE ); + count =clamp (count, (u32)(XDR_UNIT *2 ),svc_max_payload (rqstp));memset (buf,0 ,sizeof (*buf));/* Reserve room for the NULL ptr & eof flag (-2 words) */ - buf->buflen = count -sizeof (__be32) *2 ; + buf->buflen = count -XDR_UNIT *2 ; buf->pages = rqstp->rq_next_page; rqstp->rq_next_page++;
@@ -577,7 +577,7 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp, xdr->page_ptr = buf->pages; xdr->iov =NULL ; xdr->p =page_address (*buf->pages); - xdr->end = xdr->p + (PAGE_SIZE >>2 ); + xdr->end = (void *)xdr->p +min_t (u32, buf->buflen,PAGE_SIZE ); xdr->rqst =NULL ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 405/770 fsnotify: clarify object type argument
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 ad69cd9972e79aba103ba5365de0acd35770c265 ]
In preparation for separating object type from iterator type, rename some 'type' arguments in functions to 'obj_type' and remove the unused interface to clear marks by object type mask.
--- fs/notify/fanotify/fanotify_user.c | 8 ++++---- fs/notify/group.c | 2 +- fs/notify/mark.c | 27 +++++++++++++++------------ include/linux/fsnotify_backend.h | 28 ++++++++++++---------------- 4 files changed, 32 insertions(+), 33 deletions(-)
fs/notify/fanotify/fanotify_user.c +4 -4
@@ -1052,7 +1052,7 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,static struct fsnotify_mark *fanotify_add_new_mark (struct fsnotify_group *group,fsnotify_connp_t *connp, -unsigned int type, +unsigned int obj_type,__kernel_fsid_t *fsid) {struct ucounts *ucounts = group->fanotify_data.ucounts;
@@ -1075,7 +1075,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group, }fsnotify_init_mark (mark, group); - ret =fsnotify_add_mark_locked (mark, connp, type,0 , fsid); + ret =fsnotify_add_mark_locked (mark, connp, obj_type,0 , fsid);if (ret) {fsnotify_put_mark (mark); goto out_dec_ucounts;
@@ -1100,7 +1100,7 @@ static int fanotify_group_init_error_pool(struct fsnotify_group *group) }static int fanotify_add_mark (struct fsnotify_group *group, -fsnotify_connp_t *connp,unsigned int type, +fsnotify_connp_t *connp,unsigned int obj_type,__u32 mask,unsigned int flags,__kernel_fsid_t *fsid) {
@@ -1111,7 +1111,7 @@ static int fanotify_add_mark(struct fsnotify_group *group,mutex_lock (&group->mark_mutex); fsn_mark =fsnotify_find_mark (connp, group);if (!fsn_mark) { - fsn_mark =fanotify_add_new_mark (group, connp, type, fsid); + fsn_mark =fanotify_add_new_mark (group, connp, obj_type, fsid);if (IS_ERR (fsn_mark)) {mutex_unlock (&group->mark_mutex);return PTR_ERR (fsn_mark);
fs/notify/group.c +1 -1
@@ -58,7 +58,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)fsnotify_group_stop_queueing (group);/* Clear all marks for this group and queue them for destruction */ -fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_ALL_TYPES_MASK ); +fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_TYPE_ANY );/* * Some marks can still be pinned when waiting for response from
fs/notify/mark.c +15 -12
@@ -496,7 +496,7 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b) }static int fsnotify_attach_connector_to_object (fsnotify_connp_t *connp, -unsigned int type, +unsigned int obj_type,__kernel_fsid_t *fsid) {struct inode *inode =NULL ;
@@ -507,7 +507,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,return -ENOMEM ;spin_lock_init (&conn->lock);INIT_HLIST_HEAD (&conn->list); - conn->type = type; + conn->type = obj_type; conn->obj = connp;/* Cache fsid of filesystem containing the object */ if (fsid) {
@@ -572,7 +572,8 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(* priority, highest number first, and then by the group's location in memory. */ static int fsnotify_add_mark_list (struct fsnotify_mark *mark, -fsnotify_connp_t *connp,unsigned int type, +fsnotify_connp_t *connp, +unsigned int obj_type,int allow_dups,__kernel_fsid_t *fsid) {struct fsnotify_mark *lmark, *last =NULL ;
@@ -580,7 +581,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,int cmp;int err =0 ; -if (WARN_ON (!fsnotify_valid_obj_type (type))) +if (WARN_ON (!fsnotify_valid_obj_type (obj_type)))return -EINVAL ;/* Backend is expected to check for zero fsid (e.g. tmpfs) */
@@ -592,7 +593,8 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, conn =fsnotify_grab_connector (connp);if (!conn) {spin_unlock (&mark->lock); - err =fsnotify_attach_connector_to_object (connp, type, fsid); + err =fsnotify_attach_connector_to_object (connp, obj_type, + fsid);if (err)return err; goto restart;
@@ -665,7 +667,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,* event types should be delivered to which group. */ int fsnotify_add_mark_locked (struct fsnotify_mark *mark, -fsnotify_connp_t *connp,unsigned int type, +fsnotify_connp_t *connp,unsigned int obj_type,int allow_dups,__kernel_fsid_t *fsid) {struct fsnotify_group *group = mark->group;
@@ -686,7 +688,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,fsnotify_get_mark (mark);/* for g_list */ spin_unlock (&mark->lock); - ret =fsnotify_add_mark_list (mark, connp, type, allow_dups, fsid); + ret =fsnotify_add_mark_list (mark, connp, obj_type, allow_dups, fsid);if (ret) goto err;
@@ -706,13 +708,14 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, }int fsnotify_add_mark (struct fsnotify_mark *mark,fsnotify_connp_t *connp, -unsigned int type,int allow_dups,__kernel_fsid_t *fsid) +unsigned int obj_type,int allow_dups, +__kernel_fsid_t *fsid) {int ret;struct fsnotify_group *group = mark->group;mutex_lock (&group->mark_mutex); - ret =fsnotify_add_mark_locked (mark, connp, type, allow_dups, fsid); + ret =fsnotify_add_mark_locked (mark, connp, obj_type, allow_dups, fsid);mutex_unlock (&group->mark_mutex);return ret; }
@@ -747,14 +750,14 @@ EXPORT_SYMBOL_GPL(fsnotify_find_mark);/* Clear any marks in a group with given type mask */ void fsnotify_clear_marks_by_group (struct fsnotify_group *group, -unsigned int type_mask) +unsigned int obj_type) {struct fsnotify_mark *lmark, *mark;LIST_HEAD (to_free);struct list_head *head = &to_free;/* Skip selection step if we want to clear all marks. */ -if (type_mask ==FSNOTIFY_OBJ_ALL_TYPES_MASK ) { +if (obj_type ==FSNOTIFY_OBJ_TYPE_ANY ) { head = &group->marks_list; goto clear; }
@@ -769,7 +772,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group,*/ mutex_lock (&group->mark_mutex);list_for_each_entry_safe (mark, lmark, &group->marks_list, g_list) { -if ((1U << mark->connector->type) & type_mask) +if (mark->connector->type == obj_type)list_move (&mark->g_list, &to_free); }mutex_unlock (&group->mark_mutex);
include/linux/fsnotify_backend.h +12 -16
@@ -338,6 +338,7 @@ static inline struct fs_error_report *fsnotify_data_error_report( }enum fsnotify_obj_type { +FSNOTIFY_OBJ_TYPE_ANY =-1 ,FSNOTIFY_OBJ_TYPE_INODE ,FSNOTIFY_OBJ_TYPE_PARENT ,FSNOTIFY_OBJ_TYPE_VFSMOUNT ,
@@ -346,15 +347,9 @@ enum fsnotify_obj_type {FSNOTIFY_OBJ_TYPE_DETACHED =FSNOTIFY_OBJ_TYPE_COUNT }; -#define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) -#define FSNOTIFY_OBJ_TYPE_PARENT_FL (1U << FSNOTIFY_OBJ_TYPE_PARENT) -#define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) -#define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) -#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) - -static inline bool fsnotify_valid_obj_type (unsigned int type) +static inline bool fsnotify_valid_obj_type (unsigned int obj_type) { -return (type <FSNOTIFY_OBJ_TYPE_COUNT ); +return (obj_type <FSNOTIFY_OBJ_TYPE_COUNT ); }struct fsnotify_iter_info {
@@ -387,7 +382,7 @@ static inline void fsnotify_iter_set_report_type_mark( static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ struct fsnotify_iter_info *iter_info) \ { \ - return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \ + return (iter_info->report_mask & (1U << FSNOTIFY_OBJ_TYPE_##NAME)) ? \ iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \ }
@@ -604,11 +599,11 @@ extern int fsnotify_get_conn_fsid(const struct fsnotify_mark_connector *conn, __kernel_fsid_t *fsid);/* attach the mark to the object */ extern int fsnotify_add_mark (struct fsnotify_mark *mark, -fsnotify_connp_t *connp,unsigned int type, +fsnotify_connp_t *connp,unsigned int obj_type,int allow_dups,__kernel_fsid_t *fsid);extern int fsnotify_add_mark_locked (struct fsnotify_mark *mark,fsnotify_connp_t *connp, -unsigned int type,int allow_dups, +unsigned int obj_type,int allow_dups,__kernel_fsid_t *fsid);/* attach the mark to the inode */
@@ -637,22 +632,23 @@ extern void fsnotify_detach_mark(struct fsnotify_mark *mark);extern void fsnotify_free_mark (struct fsnotify_mark *mark);/* Wait until all marks queued for destruction are destroyed */ extern void fsnotify_wait_marks_destroyed (void ); -/* run all the marks in a group, and clear all of the marks attached to given object type */ -extern void fsnotify_clear_marks_by_group (struct fsnotify_group *group,unsigned int type); +/* Clear all of the marks of a group attached to a given object type */ +extern void fsnotify_clear_marks_by_group (struct fsnotify_group *group, +unsigned int obj_type);/* run all the marks in a group, and clear all of the vfsmount marks */ static inline void fsnotify_clear_vfsmount_marks_by_group (struct fsnotify_group *group) { -fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL ); +fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_TYPE_VFSMOUNT ); }/* run all the marks in a group, and clear all of the inode marks */ static inline void fsnotify_clear_inode_marks_by_group (struct fsnotify_group *group) { -fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_TYPE_INODE_FL ); +fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_TYPE_INODE ); }/* run all the marks in a group, and clear all of the sn marks */ static inline void fsnotify_clear_sb_marks_by_group (struct fsnotify_group *group) { -fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_TYPE_SB_FL ); +fsnotify_clear_marks_by_group (group,FSNOTIFY_OBJ_TYPE_SB ); }extern void fsnotify_get_mark (struct fsnotify_mark *mark);extern void fsnotify_put_mark (struct fsnotify_mark *mark);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 406/770 fsnotify: separate mark iterator type from object type enum
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 1c9007d62bea6fd164285314f7553f73e5308863 ]
They are two different types that use the same enum, so this confusing.
Use the object type to indicate the type of object mark is attached to and the iter type to indicate the type of watch.
A group can have two different watches of the same object type (parent and child watches) that match the same event.
--- fs/notify/fanotify/fanotify.c | 6 ++--- fs/notify/fsnotify.c | 18 +++++++------- fs/notify/mark.c | 4 ++-- include/linux/fsnotify_backend.h | 41 ++++++++++++++++++++++---------- 4 files changed, 42 insertions(+), 27 deletions(-)
fs/notify/fanotify/fanotify.c +3 -3
@@ -299,7 +299,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,return 0 ; } -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) {if (!fsnotify_iter_should_report_type (iter_info, type))continue ; mark = iter_info->marks[type];
@@ -318,7 +318,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,* If the event is on a child and this mark is on a parent not * watching children, don't send it! */ -if (type ==FSNOTIFY_OBJ_TYPE_PARENT && +if (type ==FSNOTIFY_ITER_TYPE_PARENT && !(mark->mask &FS_EVENT_ON_CHILD ))continue ;
@@ -746,7 +746,7 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)int type;__kernel_fsid_t fsid = {}; -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) {struct fsnotify_mark_connector *conn;if (!fsnotify_iter_should_report_type (iter_info, type))
fs/notify/fsnotify.c +9 -9
@@ -330,7 +330,7 @@ static int send_to_group(__u32 mask, const void *data, int data_type,/* clear ignored on inode modification */ if (mask &FS_MODIFY ) { -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) {if (!fsnotify_iter_should_report_type (iter_info, type))continue ; mark = iter_info->marks[type];
@@ -340,7 +340,7 @@ static int send_to_group(__u32 mask, const void *data, int data_type, } } -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) {if (!fsnotify_iter_should_report_type (iter_info, type))continue ; mark = iter_info->marks[type];
@@ -405,7 +405,7 @@ static unsigned int fsnotify_iter_select_report_types(int type;/* Choose max prio group among groups of all queue heads */ -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) { mark = iter_info->marks[type];if (mark &&fsnotify_compare_groups (max_prio_group, mark->group) >0 )
@@ -417,7 +417,7 @@ static unsigned int fsnotify_iter_select_report_types(/* Set the report mask for marks from same group as max prio group */ iter_info->report_mask =0 ; -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) { mark = iter_info->marks[type];if (mark &&fsnotify_compare_groups (max_prio_group, mark->group) ==0 )
@@ -435,7 +435,7 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) {int type; -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) {if (fsnotify_iter_should_report_type (iter_info, type)) iter_info->marks[type] =fsnotify_next_mark (iter_info->marks[type]);
@@ -519,18 +519,18 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, iter_info.srcu_idx =srcu_read_lock (&fsnotify_mark_srcu); - iter_info.marks[FSNOTIFY_OBJ_TYPE_SB ] = + iter_info.marks[FSNOTIFY_ITER_TYPE_SB ] =fsnotify_first_mark (&sb->s_fsnotify_marks);if (mnt) { - iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT ] = + iter_info.marks[FSNOTIFY_ITER_TYPE_VFSMOUNT ] =fsnotify_first_mark (&mnt->mnt_fsnotify_marks); }if (inode) { - iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE ] = + iter_info.marks[FSNOTIFY_ITER_TYPE_INODE ] =fsnotify_first_mark (&inode->i_fsnotify_marks); }if (parent) { - iter_info.marks[FSNOTIFY_OBJ_TYPE_PARENT ] = + iter_info.marks[FSNOTIFY_ITER_TYPE_PARENT ] =fsnotify_first_mark (&parent->i_fsnotify_marks); }
fs/notify/mark.c +2 -2
@@ -353,7 +353,7 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) {int type; -fsnotify_foreach_obj_type (type) { +fsnotify_foreach_iter_type (type) {/* This can fail if mark is being removed */ if (!fsnotify_get_mark_safe (iter_info->marks[type])) {__release (&fsnotify_mark_srcu);
@@ -382,7 +382,7 @@ void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info)int type; iter_info->srcu_idx =srcu_read_lock (&fsnotify_mark_srcu); -fsnotify_foreach_obj_type (type) +fsnotify_foreach_iter_type (type) fsnotify_put_mark_wake(iter_info->marks[type]); }
include/linux/fsnotify_backend.h +28 -13
83 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 407/770 fanotify: introduce group flag FAN_REPORT_TARGET_FID
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 d61fd650e9d206a71fda789f02a1ced4b19944c4 ]
FAN_REPORT_FID is ambiguous in that it reports the fid of the child for some events and the fid of the parent for create/delete/move events.
The new FAN_REPORT_TARGET_FID flag is an implicit request to report the fid of the target object of the operation (a.k.a the child inode) also in create/delete/move events in addition to the fid of the parent and the name of the child.
To reduce the test matrix for uninteresting use cases, the new FAN_REPORT_TARGET_FID flag requires both FAN_REPORT_NAME and FAN_REPORT_FID. The convenience macro FAN_REPORT_DFID_NAME_TARGET combines FAN_REPORT_TARGET_FID with all the required flags.
--- fs/notify/fanotify/fanotify.c | 48 ++++++++++++++++++++++-------- fs/notify/fanotify/fanotify_user.c | 11 ++++++- include/linux/fanotify.h | 2 +- include/uapi/linux/fanotify.h | 4 +++ 4 files changed, 51 insertions(+), 14 deletions(-)
fs/notify/fanotify/fanotify.c +36 -12
@@ -458,17 +458,41 @@ static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode, }/* -* The inode to use as identifier when reporting fid depends on the event. -* Report the modified directory inode on dirent modification events. -* Report the "victim" inode otherwise. +* FAN_REPORT_FID is ambiguous in that it reports the fid of the child for +* some events and the fid of the parent for create/delete/move events. +* +* With the FAN_REPORT_TARGET_FID flag, the fid of the child is reported +* also in create/delete/move events in addition to the fid of the parent +* and the name of the child. +*/ +static inline bool fanotify_report_child_fid (unsigned int fid_mode,u32 mask) +{ +if (mask &ALL_FSNOTIFY_DIRENT_EVENTS ) +return (fid_mode &FAN_REPORT_TARGET_FID ); + +return (fid_mode &FAN_REPORT_FID ) && !(mask &FAN_ONDIR ); +} + +/* +* The inode to use as identifier when reporting fid depends on the event +* and the group flags. +* +* With the group flag FAN_REPORT_TARGET_FID, always report the child fid. +* +* Without the group flag FAN_REPORT_TARGET_FID, report the modified directory +* fid on dirent events and the child fid otherwise. +* * For example: -* FS_ATTRIB reports the child inode even if reported on a watched parent. -* FS_CREATE reports the modified dir inode and not the created inode. +* FS_ATTRIB reports the child fid even if reported on a watched parent. +* FS_CREATE reports the modified dir fid without FAN_REPORT_TARGET_FID. +* and reports the created child fid with FAN_REPORT_TARGET_FID. */ static struct inode *fanotify_fid_inode (u32 event_mask,const void *data, -int data_type,struct inode *dir) +int data_type,struct inode *dir, +unsigned int fid_mode) { -if (event_mask &ALL_FSNOTIFY_DIRENT_EVENTS ) +if ((event_mask &ALL_FSNOTIFY_DIRENT_EVENTS ) && + !(fid_mode &FAN_REPORT_TARGET_FID ))return dir;return fsnotify_data_inode (data, data_type);
@@ -647,10 +671,11 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, {struct fanotify_event *event =NULL ;gfp_t gfp =GFP_KERNEL_ACCOUNT ; -struct inode *id =fanotify_fid_inode (mask, data, data_type, dir); +unsigned int fid_mode =FAN_GROUP_FLAG (group,FANOTIFY_FID_BITS ); +struct inode *id =fanotify_fid_inode (mask, data, data_type, dir, + fid_mode);struct inode *dirid =fanotify_dfid_inode (mask, data, data_type, dir);const struct path *path =fsnotify_data_path (data, data_type); -unsigned int fid_mode =FAN_GROUP_FLAG (group,FANOTIFY_FID_BITS );struct mem_cgroup *old_memcg;struct inode *child =NULL ;bool name_event = false;
@@ -660,11 +685,10 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,if ((fid_mode &FAN_REPORT_DIR_FID ) && dirid) {/* -* With both flags FAN_REPORT_DIR_FID and FAN_REPORT_FID, we -* report the child fid for events reported on a non-dir child +* For certain events and group flags, report the child fid * in addition to reporting the parent fid and maybe child name. */ -if ((fid_mode &FAN_REPORT_FID ) && id != dirid && !ondir) +if (fanotify_report_child_fid (fid_mode, mask) && id != dirid) child = id; id = dirid;
fs/notify/fanotify/fanotify_user.c +10 -1
@@ -1270,6 +1270,15 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)if ((fid_mode &FAN_REPORT_NAME ) && !(fid_mode &FAN_REPORT_DIR_FID ))return -EINVAL ; +/* +* FAN_REPORT_TARGET_FID requires FAN_REPORT_NAME and FAN_REPORT_FID +* and is used as an indication to report both dir and child fid on all +* dirent events. +*/ +if ((fid_mode &FAN_REPORT_TARGET_FID ) && + (!(fid_mode &FAN_REPORT_NAME ) || !(fid_mode &FAN_REPORT_FID ))) +return -EINVAL ; + f_flags =O_RDWR |FMODE_NONOTIFY ;if (flags &FAN_CLOEXEC ) f_flags |=O_CLOEXEC ;
@@ -1680,7 +1689,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 ) !=11 ); +BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) !=12 );BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_MARK_FLAGS ) !=9 ); fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
include/linux/fanotify.h +1 -1
@@ -25,7 +25,7 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_CLASS_BITS (FAN_CLASS_NOTIF | FANOTIFY_PERM_CLASSES) -#define FANOTIFY_FID_BITS (FAN_REPORT_FID | FAN_REPORT_DFID_NAME) +#define FANOTIFY_FID_BITS (FAN_REPORT_DFID_NAME_TARGET)#define FANOTIFY_INFO_MODES (FANOTIFY_FID_BITS | FAN_REPORT_PIDFD)
include/uapi/linux/fanotify.h +4 -0
@@ -57,9 +57,13 @@#define FAN_REPORT_FID 0x00000200/* Report unique file id */ #define FAN_REPORT_DIR_FID 0x00000400/* Report unique directory id */ #define FAN_REPORT_NAME 0x00000800/* Report events with name */ +#define FAN_REPORT_TARGET_FID 0x00001000/* Report dirent target id */ /* Convenience macro - FAN_REPORT_NAME requires FAN_REPORT_DIR_FID */ #define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME) +/* Convenience macro - FAN_REPORT_TARGET_FID requires all other FID flags */ +#define FAN_REPORT_DFID_NAME_TARGET (FAN_REPORT_DFID_NAME | \ + FAN_REPORT_FID | FAN_REPORT_TARGET_FID)/* Deprecated - do not use this in programs and do not add new flags here! */ #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 408/770 fsnotify: generate FS_RENAME event with rich information
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 e54183fa7047c15819bc155f4c58501d9a9a3489 ]
The dnotify FS_DN_RENAME event is used to request notification about a move within the same parent directory and was always coupled with the FS_MOVED_FROM event.
Rename the FS_DN_RENAME event flag to FS_RENAME, decouple it from FS_MOVED_FROM and report it with the moved dentry instead of the moved inode, so it has the information about both old and new parent and name.
Generate the FS_RENAME event regardless of same parent dir and apply the "same parent" rule in the generic fsnotify_handle_event() helper that is used to call backends with ->handle_inode_event() method (i.e. dnotify). The ->handle_inode_event() method is not rich enough to report both old and new parent and name anyway.
The enriched event is reported to fanotify over the ->handle_event() method with the old and new dir inode marks in marks array slots for ITER_TYPE_INODE and a new iter type slot ITER_TYPE_INODE2.
The enriched event will be used for reporting old and new parent+name to fanotify groups with FAN_RENAME events.
--- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/fsnotify.c | 37 +++++++++++++++++++++++++------- include/linux/dnotify.h | 2 +- include/linux/fsnotify.h | 9 +++++--- include/linux/fsnotify_backend.h | 7 +++--- 5 files changed, 41 insertions(+), 16 deletions(-)
fs/notify/dnotify/dnotify.c +1 -1
@@ -196,7 +196,7 @@ static __u32 convert_arg(unsigned long arg)if (arg &DN_ATTRIB ) new_mask |=FS_ATTRIB ;if (arg &DN_RENAME ) - new_mask |=FS_DN_RENAME ; + new_mask |=FS_RENAME ;if (arg &DN_CREATE ) new_mask |= (FS_CREATE |FS_MOVED_TO );
fs/notify/fsnotify.c +29 -8
@@ -279,6 +279,18 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info)))return 0 ; +/* +* For FS_RENAME, 'dir' is old dir and 'data' is new dentry. +* The only ->handle_inode_event() backend that supports FS_RENAME is +* dnotify, where it means file was renamed within same parent. +*/ +if (mask &FS_RENAME ) { +struct dentry *moved =fsnotify_data_dentry (data, data_type); + +if (dir != moved->d_parent->d_inode) +return 0 ; + } +if (parent_mark) {/* * parent_mark indicates that the parent inode is watching
@@ -469,7 +481,9 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,struct super_block *sb =fsnotify_data_sb (data, data_type);struct fsnotify_iter_info iter_info = {};struct mount *mnt =NULL ; -struct inode *parent =NULL ; +struct inode *inode2 =NULL ; +struct dentry *moved; +int inode2_type;int ret =0 ;__u32 test_mask, marks_mask;
@@ -479,12 +493,19 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,if (!inode) {/* Dirent event - report on TYPE_INODE to dir */ inode = dir; +/* For FS_RENAME, inode is old_dir and inode2 is new_dir */ +if (mask &FS_RENAME ) { + moved =fsnotify_data_dentry (data, data_type); + inode2 = moved->d_parent->d_inode; + inode2_type =FSNOTIFY_ITER_TYPE_INODE2 ; + } }else if (mask &FS_EVENT_ON_CHILD ) {/* * Event on child - report on TYPE_PARENT to dir if it is * watching children and on TYPE_INODE to child. */ - parent = dir; + inode2 = dir; + inode2_type =FSNOTIFY_ITER_TYPE_PARENT ; }/*
@@ -497,7 +518,7 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,if (!sb->s_fsnotify_marks && (!mnt || !mnt->mnt_fsnotify_marks) && (!inode || !inode->i_fsnotify_marks) && - (!parent || !parent->i_fsnotify_marks)) + (!inode2 || !inode2->i_fsnotify_marks))return 0 ; marks_mask = sb->s_fsnotify_mask;
@@ -505,8 +526,8 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, marks_mask |= mnt->mnt_fsnotify_mask;if (inode) marks_mask |= inode->i_fsnotify_mask; -if (parent) - marks_mask |= parent->i_fsnotify_mask; +if (inode2) + marks_mask |= inode2->i_fsnotify_mask;/*
@@ -529,9 +550,9 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, iter_info.marks[FSNOTIFY_ITER_TYPE_INODE ] =fsnotify_first_mark (&inode->i_fsnotify_marks); } -if (parent) { - iter_info.marks[FSNOTIFY_ITER_TYPE_PARENT ] = -fsnotify_first_mark (&parent->i_fsnotify_marks); +if (inode2) { + iter_info.marks[inode2_type] = +fsnotify_first_mark (&inode2->i_fsnotify_marks); }/*
include/linux/dnotify.h +1 -1
@@ -26,7 +26,7 @@ struct dnotify_struct {FS_MODIFY |FS_MODIFY_CHILD |\FS_ACCESS |FS_ACCESS_CHILD |\FS_ATTRIB |FS_ATTRIB_CHILD |\ -FS_CREATE |FS_DN_RENAME |\ +FS_CREATE |FS_RENAME |\ FS_MOVED_FROM | FS_MOVED_TO) extern int dir_notify_enable;
include/linux/fsnotify.h +6 -3
@@ -144,16 +144,19 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,u32 fs_cookie =fsnotify_get_cookie ();__u32 old_dir_mask =FS_MOVED_FROM ;__u32 new_dir_mask =FS_MOVED_TO ; +__u32 rename_mask =FS_RENAME ;const struct qstr *new_name = &moved->d_name; -if (old_dir == new_dir) - old_dir_mask |=FS_DN_RENAME ; -if (isdir) { old_dir_mask |=FS_ISDIR ; new_dir_mask |=FS_ISDIR ; + rename_mask |=FS_ISDIR ; } +/* Event with information about both old and new parent+name */ +fsnotify_name (rename_mask, moved,FSNOTIFY_EVENT_DENTRY , + old_dir, old_name,0 ); +fsnotify_name (old_dir_mask, source,FSNOTIFY_EVENT_INODE , old_dir, old_name, fs_cookie); fsnotify_name(new_dir_mask, source, FSNOTIFY_EVENT_INODE,
include/linux/fsnotify_backend.h +4 -3
@@ -63,7 +63,7 @@*/ #define FS_EVENT_ON_CHILD 0x08000000 -#define FS_DN_RENAME 0x10000000/* file renamed */ +#define FS_RENAME 0x10000000/* File was renamed */ #define FS_DN_MULTISHOT 0x20000000/* dnotify multishot */ #define FS_ISDIR 0x40000000/* event occurred against dir */ #define FS_IN_ONESHOT 0x80000000/* only send event once */
@@ -76,7 +76,7 @@* The watching parent may get an FS_ATTRIB|FS_EVENT_ON_CHILD event * when a directory entry inside a child subdir changes. */ -#define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE) +#define ALL_FSNOTIFY_DIRENT_EVENTS (FS_CREATE | FS_DELETE | FS_MOVE | FS_RENAME)#define ALL_FSNOTIFY_PERM_EVENTS (FS_OPEN_PERM | FS_ACCESS_PERM | \ FS_OPEN_EXEC_PERM)
@@ -101,7 +101,7 @@/* Events that can be reported to backends */ #define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \ FS_EVENTS_POSS_ON_CHILD | \ - FS_DELETE_SELF | FS_MOVE_SELF | FS_DN_RENAME | \ + FS_DELETE_SELF | FS_MOVE_SELF | \ FS_UNMOUNT | FS_Q_OVERFLOW | FS_IN_IGNORED | \ FS_ERROR)
@@ -349,6 +349,7 @@ enum fsnotify_iter_type {FSNOTIFY_ITER_TYPE_VFSMOUNT ,FSNOTIFY_ITER_TYPE_SB ,FSNOTIFY_ITER_TYPE_PARENT , +FSNOTIFY_ITER_TYPE_INODE2 , FSNOTIFY_ITER_TYPE_COUNT };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 409/770 fanotify: use macros to get the offset to fanotify_info buffer
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 2d9374f095136206a02eb0b6cd9ef94632c1e9f7 ]
The fanotify_info buffer contains up to two file handles and a name. Use macros to simplify the code that access the different items within the buffer.
Add assertions to verify that stored fh len and name len do not overflow the u8 stored value in fanotify_info header.
Remove the unused fanotify_info_len() helper.
--- fs/notify/fanotify/fanotify.c | 2 +- fs/notify/fanotify/fanotify.h | 41 +++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 12 deletions(-)
fs/notify/fanotify/fanotify.c +1 -1
@@ -411,7 +411,7 @@ static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode,* be zero in that case if encoding fh len failed. */ err = -ENOENT ; -if (fh_len <4 ||WARN_ON_ONCE (fh_len %4 )) +if (fh_len <4 ||WARN_ON_ONCE (fh_len %4 ) || fh_len >MAX_HANDLE_SZ ) goto out_err;/* No external buffer in a variable size allocated fh */
fs/notify/fanotify/fanotify.h +30 -11
75 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 410/770 fanotify: use helpers to parcel fanotify_info buffer
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 1a9515ac9e55e68d733bab81bd408463ab1e25b1 ]
fanotify_info buffer is parceled into variable sized records, so the records must be written in order: dir_fh, file_fh, name.
Use helpers to assert that order and make fanotify_alloc_name_event() a bit more generic to allow empty dir_fh record and to allow expanding to more records (i.e. name2) soon.
--- fs/notify/fanotify/fanotify.c | 35 +++++++++++++++++++---------------- fs/notify/fanotify/fanotify.h | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 16 deletions(-)
fs/notify/fanotify/fanotify.c +19 -16
@@ -576,7 +576,7 @@ static struct fanotify_event *fanotify_alloc_fid_event(struct inode *id,return &ffe->fae; } -static struct fanotify_event *fanotify_alloc_name_event(struct inode *id, +static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir, __kernel_fsid_t *fsid, const struct qstr *name, struct inode *child,
@@ -586,15 +586,17 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id,struct fanotify_name_event *fne;struct fanotify_info *info;struct fanotify_fh *dfh, *ffh; -unsigned int dir_fh_len =fanotify_encode_fh_len (id); +unsigned int dir_fh_len =fanotify_encode_fh_len (dir);unsigned int child_fh_len =fanotify_encode_fh_len (child); -unsigned int size; +unsigned long name_len = name ? name->len :0 ; +unsigned int len, size; - size =sizeof (*fne) +FANOTIFY_FH_HDR_LEN + dir_fh_len; +/* Reserve terminating null byte even for empty name */ + size =sizeof (*fne) + name_len +1 ; +if (dir_fh_len) + size +=FANOTIFY_FH_HDR_LEN + dir_fh_len;if (child_fh_len) size +=FANOTIFY_FH_HDR_LEN + child_fh_len; -if (name) - size += name->len +1 ; fne =kmalloc (size, gfp);if (!fne)return NULL ;
@@ -604,22 +606,23 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *id, *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, hash,0 ); +if (dir_fh_len) { + dfh =fanotify_info_dir_fh (info); + len =fanotify_encode_fh (dfh, dir, dir_fh_len, hash,0 ); +fanotify_info_set_dir_fh (info, len); + }if (child_fh_len) { ffh =fanotify_info_file_fh (info); - info->file_fh_totlen =fanotify_encode_fh (ffh, child, - child_fh_len, hash,0 ); + len =fanotify_encode_fh (ffh, child, child_fh_len, hash,0 ); +fanotify_info_set_file_fh (info, len); } -if (name) { -long salt = name->len; - +if (name_len) {fanotify_info_copy_name (info, name); - *hash ^=full_name_hash ((void *)salt, name->name, name->len); + *hash ^=full_name_hash ((void *)name_len, name->name, name_len); } -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, +pr_debug ("%s: size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n" , + __func__, size, dir_fh_len, child_fh_len, info->name_len, info->name_len,fanotify_info_name (info));return &fne->fae;
fs/notify/fanotify/fanotify.h +20 -0
@@ -138,6 +138,26 @@ static inline void fanotify_info_init(struct fanotify_info *info) info->name_len =0 ; } +/* These set/copy helpers MUST be called by order */ +static inline void fanotify_info_set_dir_fh (struct fanotify_info *info, +unsigned int totlen) +{ +if (WARN_ON_ONCE (info->file_fh_totlen >0 ) || +WARN_ON_ONCE (info->name_len >0 )) +return ; + + info->dir_fh_totlen = totlen; +} + +static inline void fanotify_info_set_file_fh (struct fanotify_info *info, +unsigned int totlen) +{ +if (WARN_ON_ONCE (info->name_len >0 )) +return ; + + info->file_fh_totlen = totlen; +} +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 411/770 fanotify: support secondary dir fh and name in fanotify_info
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 3cf984e950c1c3f41d407ed31db33beb996be132 ]
Allow storing a secondary dir fh and name tupple in fanotify_info. This will be used to store the new parent and name information in FAN_RENAME event.
--- fs/notify/fanotify/fanotify.c | 20 ++++++-- fs/notify/fanotify/fanotify.h | 79 +++++++++++++++++++++++++++--- fs/notify/fanotify/fanotify_user.c | 3 +- 3 files changed, 88 insertions(+), 14 deletions(-)
fs/notify/fanotify/fanotify.c +16 -4
@@ -76,8 +76,10 @@ static bool fanotify_info_equal(struct fanotify_info *info1, struct fanotify_info *info2) {if (info1->dir_fh_totlen != info2->dir_fh_totlen || + info1->dir2_fh_totlen != info2->dir2_fh_totlen || info1->file_fh_totlen != info2->file_fh_totlen || - info1->name_len != info2->name_len) + info1->name_len != info2->name_len || + info1->name2_len != info2->name2_len)return false; if (info1->dir_fh_totlen &&
@@ -85,14 +87,24 @@ static bool fanotify_info_equal(struct fanotify_info *info1, fanotify_info_dir_fh(info2)))return false; +if (info1->dir2_fh_totlen && + !fanotify_fh_equal (fanotify_info_dir2_fh (info1), +fanotify_info_dir2_fh (info2))) +return false; +if (info1->file_fh_totlen && !fanotify_fh_equal (fanotify_info_file_fh (info1),fanotify_info_file_fh (info2)))return false; -return !info1->name_len || - !memcmp (fanotify_info_name (info1),fanotify_info_name (info2), - info1->name_len); +if (info1->name_len && +memcmp (fanotify_info_name (info1),fanotify_info_name (info2), + info1->name_len)) +return false; + +return !info1->name2_len || + !memcmp (fanotify_info_name2 (info1),fanotify_info_name2 (info2), + info1->name2_len); } static bool fanotify_name_event_equal(struct fanotify_name_event *fne1,
fs/notify/fanotify/fanotify.h +71 -8
152 lines not on this page · raw message
fs/notify/fanotify/fanotify_user.c +1 -2
@@ -327,11 +327,10 @@ static int process_access_response(struct fsnotify_group *group,static size_t copy_error_info_to_user (struct fanotify_event *event,char __user *buf,int count) { -struct fanotify_event_info_error info; +struct fanotify_event_info_error info = { };struct fanotify_error_event *fee =FANOTIFY_EE (event); info.hdr.info_type =FAN_EVENT_INFO_TYPE_ERROR ; - info.hdr.pad =0 ; info.hdr.len =FANOTIFY_ERROR_INFO_LEN ;if (WARN_ON (count < info.hdr.len))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 412/770 fanotify: record old and new parent and name in FAN_RENAME event
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 3982534ba5ce45e890b2f5ef5e7372c1accd14c7 ]
In the special case of FAN_RENAME event, we record both the old and new parent and name.
--- fs/notify/fanotify/fanotify.c | 42 +++++++++++++++++++++++++++++++---- include/uapi/linux/fanotify.h | 2 ++ 2 files changed, 40 insertions(+), 4 deletions(-)
fs/notify/fanotify/fanotify.c +38 -4
@@ -592,21 +592,28 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,__kernel_fsid_t *fsid, const struct qstr *name, struct inode *child, + struct dentry *moved, unsigned int *hash, gfp_t gfp) { struct fanotify_name_event *fne;struct fanotify_info *info;struct fanotify_fh *dfh, *ffh; +struct inode *dir2 = moved ?d_inode (moved->d_parent) :NULL ; +const struct qstr *name2 = moved ? &moved->d_name :NULL ;unsigned int dir_fh_len =fanotify_encode_fh_len (dir); +unsigned int dir2_fh_len =fanotify_encode_fh_len (dir2);unsigned int child_fh_len =fanotify_encode_fh_len (child);unsigned long name_len = name ? name->len :0 ; +unsigned long name2_len = name2 ? name2->len :0 ;unsigned int len, size;/* Reserve terminating null byte even for empty name */ - size =sizeof (*fne) + name_len +1 ; + size =sizeof (*fne) + name_len + name2_len +2 ;if (dir_fh_len) size +=FANOTIFY_FH_HDR_LEN + dir_fh_len; +if (dir2_fh_len) + size +=FANOTIFY_FH_HDR_LEN + dir2_fh_len;if (child_fh_len) size +=FANOTIFY_FH_HDR_LEN + child_fh_len; fne =kmalloc (size, gfp);
@@ -623,6 +630,11 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir, len =fanotify_encode_fh (dfh, dir, dir_fh_len, hash,0 );fanotify_info_set_dir_fh (info, len); } +if (dir2_fh_len) { + dfh =fanotify_info_dir2_fh (info); + len =fanotify_encode_fh (dfh, dir2, dir2_fh_len, hash,0 ); +fanotify_info_set_dir2_fh (info, len); + }if (child_fh_len) { ffh =fanotify_info_file_fh (info); len =fanotify_encode_fh (ffh, child, child_fh_len, hash,0 );
@@ -632,11 +644,22 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,fanotify_info_copy_name (info, name); *hash ^=full_name_hash ((void *)name_len, name->name, name_len); } +if (name2_len) { +fanotify_info_copy_name2 (info, name2); + *hash ^=full_name_hash ((void *)name2_len, name2->name, + name2_len); + }pr_debug ("%s: size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n" , __func__, size, dir_fh_len, child_fh_len, info->name_len, info->name_len,fanotify_info_name (info)); +if (dir2_fh_len) { +pr_debug ("%s: dir2_fh_len=%u name2_len=%u name2='%.*s'\n" , + __func__, dir2_fh_len, info->name2_len, + info->name2_len,fanotify_info_name2 (info)); + } +return &fne->fae; }
@@ -692,6 +715,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,struct inode *dirid =fanotify_dfid_inode (mask, data, data_type, dir);const struct path *path =fsnotify_data_path (data, data_type);struct mem_cgroup *old_memcg; +struct dentry *moved =NULL ;struct inode *child =NULL ;bool name_event = false;unsigned int hash =0 ;
@@ -727,6 +751,15 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, }else if ((mask &ALL_FSNOTIFY_DIRENT_EVENTS ) || !ondir) { name_event = true; } + +/* +* In the special case of FAN_RENAME event, we record both +* old and new parent+name. +* 'dirid' and 'file_name' are the old parent+name and +* 'moved' has the new parent+name. +*/ +if (mask &FAN_RENAME ) + moved =fsnotify_data_dentry (data, data_type); }/*
@@ -748,9 +781,9 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, }else if (fanotify_is_error_event (mask)) { event =fanotify_alloc_error_event (group, fsid, data, data_type, &hash); - }else if (name_event && (file_name || child)) { - event =fanotify_alloc_name_event (id, fsid, file_name, child, - &hash, gfp); + }else if (name_event && (file_name || moved || child)) { + event =fanotify_alloc_name_event (dirid, fsid, file_name, child, + moved, &hash, gfp); }else if (fid_mode) { event =fanotify_alloc_fid_event (id, fsid, &hash, gfp); }else {
@@ -860,6 +893,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,BUILD_BUG_ON (FAN_OPEN_EXEC !=FS_OPEN_EXEC );BUILD_BUG_ON (FAN_OPEN_EXEC_PERM !=FS_OPEN_EXEC_PERM );BUILD_BUG_ON (FAN_FS_ERROR !=FS_ERROR ); +BUILD_BUG_ON (FAN_RENAME !=FS_RENAME );BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) !=20 );
include/uapi/linux/fanotify.h +2 -0
@@ -28,6 +28,8 @@#define FAN_EVENT_ON_CHILD 0x08000000/* Interested in child events */ +#define FAN_RENAME 0x10000000/* File was renamed */ +#define FAN_ONDIR 0x40000000/* Event occurred against dir */ /* helper events */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 413/770 fanotify: record either old name new name or both for FAN_RENAME
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 2bfbcccde6e7a787feabad4645f628f963fe0663 ]
We do not want to report the dirfid+name of a directory whose inode/sb are not watched, because watcher may not have permissions to see the directory content.
Use an internal iter_info to indicate to fanotify_alloc_event() which marks of this group are watching FAN_RENAME, so it can decide if we need to record only the old parent+name, new parent+name or both.
[JK: Modified code to pass around only mask of mark types matching generated event]
--- fs/notify/fanotify/fanotify.c | 59 ++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 15 deletions(-)
fs/notify/fanotify/fanotify.c +44 -15
@@ -284,8 +284,9 @@ static int fanotify_get_response(struct fsnotify_group *group,*/ static u32 fanotify_group_event_mask (struct fsnotify_group *group,struct fsnotify_iter_info *iter_info, -u32 event_mask,const void *data, -int data_type,struct inode *dir) +u32 *match_mask,u32 event_mask, +const void *data,int data_type, +struct inode *dir) {__u32 marks_mask =0 , marks_ignored_mask =0 ; __u32 test_mask, user_mask = FANOTIFY_OUTGOING_EVENTS |
@@ -335,6 +336,9 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,continue ; marks_mask |= mark->mask; + +/* Record the mark types of this group that matched the event */ + *match_mask |=1U << type; } test_mask = event_mask & marks_mask & ~marks_ignored_mask;
@@ -701,11 +705,11 @@ static struct fanotify_event *fanotify_alloc_error_event(return &fee->fae; } -static struct fanotify_event *fanotify_alloc_event (struct fsnotify_group *group, -u32 mask,const void *data, -int data_type,struct inode *dir, -const struct qstr *file_name, -__kernel_fsid_t *fsid) +static struct fanotify_event *fanotify_alloc_event ( +struct fsnotify_group *group, +u32 mask,const void *data,int data_type, +struct inode *dir,const struct qstr *file_name, +__kernel_fsid_t *fsid,u32 match_mask) {struct fanotify_event *event =NULL ;gfp_t gfp =GFP_KERNEL_ACCOUNT ;
@@ -753,13 +757,36 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group, }/* -* In the special case of FAN_RENAME event, we record both -* old and new parent+name. +* In the special case of FAN_RENAME event, use the match_mask +* to determine if we need to report only the old parent+name, +* only the new parent+name or both. * 'dirid' and 'file_name' are the old parent+name and * 'moved' has the new parent+name. */ -if (mask &FAN_RENAME ) - moved =fsnotify_data_dentry (data, data_type); +if (mask &FAN_RENAME ) { +bool report_old, report_new; + +if (WARN_ON_ONCE (!match_mask)) +return NULL ; + +/* Report both old and new parent+name if sb watching */ + report_old = report_new = + match_mask & (1U <<FSNOTIFY_ITER_TYPE_SB ); + report_old |= + match_mask & (1U <<FSNOTIFY_ITER_TYPE_INODE ); + report_new |= + match_mask & (1U <<FSNOTIFY_ITER_TYPE_INODE2 ); + +if (!report_old) { +/* Do not report old parent+name */ + dirid =NULL ; + file_name =NULL ; + } +if (report_new) { +/* Report new parent+name */ + moved =fsnotify_data_dentry (data, data_type); + } + } }/*
@@ -872,6 +899,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,struct fanotify_event *event;struct fsnotify_event *fsn_event;__kernel_fsid_t fsid = {}; +u32 match_mask =0 ;BUILD_BUG_ON (FAN_ACCESS !=FS_ACCESS );BUILD_BUG_ON (FAN_MODIFY !=FS_MODIFY );
@@ -897,12 +925,13 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) !=20 ); - mask =fanotify_group_event_mask (group, iter_info, mask, data, - data_type, dir); + mask =fanotify_group_event_mask (group, iter_info, &match_mask, + mask, data, data_type, dir);if (!mask)return 0 ; -pr_debug ("%s: group=%p mask=%x\n" , __func__, group, mask); +pr_debug ("%s: group=%p mask=%x report_mask=%x\n" , __func__, + group, mask, match_mask);if (fanotify_is_perm_event (mask)) {/*
@@ -921,7 +950,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, } event =fanotify_alloc_event (group, mask, data, data_type, dir, - file_name, &fsid); + file_name, &fsid, match_mask); ret = -ENOMEM ;if (unlikely (!event)) {/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 414/770 fanotify: report old and/or new parent+name in FAN_RENAME event
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 7326e382c21e9c23c89c88369afdc90b82a14da8 ]
In the special case of FAN_RENAME event, we report old or new or both old and new parent+name.
A single info record will be reported if either the old or new dir is watched and two records will be reported if both old and new dir (or their filesystem) are watched.
The old and new parent+name are reported using new info record types FAN_EVENT_INFO_TYPE_{OLD,NEW}_DFID_NAME, so if a single info record is reported, it is clear to the application, to which dir entry the fid+name info is referring to.
--- fs/notify/fanotify/fanotify.c | 7 ++++ fs/notify/fanotify/fanotify.h | 18 +++++++++++ fs/notify/fanotify/fanotify_user.c | 52 +++++++++++++++++++++++++++--- include/uapi/linux/fanotify.h | 6 ++++ 4 files changed, 78 insertions(+), 5 deletions(-)
fs/notify/fanotify/fanotify.c +7 -0
@@ -153,6 +153,13 @@ static bool fanotify_should_merge(struct fanotify_event *old,if ((old->mask &FS_ISDIR ) != (new->mask &FS_ISDIR ))return false; +/* +* FAN_RENAME event is reported with special info record types, +* so we cannot merge it with other events. +*/ +if ((old->mask &FAN_RENAME ) != (new->mask &FAN_RENAME )) +return false; +switch (old->type) {case FANOTIFY_EVENT_TYPE_PATH : return fanotify_path_equal(fanotify_event_path(old),
fs/notify/fanotify/fanotify.h +18 -0
@@ -373,6 +373,13 @@ static inline int fanotify_event_dir_fh_len(struct fanotify_event *event)return info ?fanotify_info_dir_fh_len (info) :0 ; } +static inline int fanotify_event_dir2_fh_len (struct fanotify_event *event) +{ +struct fanotify_info *info =fanotify_event_info (event); + +return info ?fanotify_info_dir2_fh_len (info) :0 ; +} +static inline bool fanotify_event_has_object_fh (struct fanotify_event *event) {/* For error events, even zeroed fh are reported. */
@@ -386,6 +393,17 @@ static inline bool fanotify_event_has_dir_fh(struct fanotify_event *event)return fanotify_event_dir_fh_len (event) >0 ; } +static inline bool fanotify_event_has_dir2_fh (struct fanotify_event *event) +{ +return fanotify_event_dir2_fh_len (event) >0 ; +} + +static inline bool fanotify_event_has_any_dir_fh (struct fanotify_event *event) +{ +return fanotify_event_has_dir_fh (event) || +fanotify_event_has_dir2_fh (event); +} +struct fanotify_path_event {struct fanotify_event fae;struct path path;
fs/notify/fanotify/fanotify_user.c +47 -5
91 lines not on this page · raw message
include/uapi/linux/fanotify.h +6 -0
@@ -134,6 +134,12 @@ struct fanotify_event_metadata {#define FAN_EVENT_INFO_TYPE_PIDFD 4#define FAN_EVENT_INFO_TYPE_ERROR 5 +/* Special info types for FAN_RENAME */ +#define FAN_EVENT_INFO_TYPE_OLD_DFID_NAME 10 +/* Reserved for FAN_EVENT_INFO_TYPE_OLD_DFID 11 */ +#define FAN_EVENT_INFO_TYPE_NEW_DFID_NAME 12 +/* Reserved for FAN_EVENT_INFO_TYPE_NEW_DFID 13 */ +/* Variable length info record following event metadata */ struct fanotify_event_info_header {__u8 info_type;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 415/770 fanotify: wire up FAN_RENAME event
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 8cc3b1ccd930fe6971e1527f0c4f1bdc8cb56026 ]
FAN_RENAME is the successor of FAN_MOVED_FROM and FAN_MOVED_TO and can be used to get the old and new parent+name information in a single event.
FAN_MOVED_FROM and FAN_MOVED_TO are still supported for backward compatibility, but it makes little sense to use them together with FAN_RENAME in the same group.
FAN_RENAME uses special info type records to report the old and new parent+name, so reporting only old and new parent id is less useful and was not implemented.
Therefore, FAN_REANAME requires a group with flag FAN_REPORT_NAME.
--- fs/notify/fanotify/fanotify.c | 2 +- fs/notify/fanotify/fanotify_user.c | 8 ++++++++ include/linux/fanotify.h | 3 ++- 3 files changed, 11 insertions(+), 2 deletions(-)
fs/notify/fanotify/fanotify.c +1 -1
@@ -930,7 +930,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,BUILD_BUG_ON (FAN_FS_ERROR !=FS_ERROR );BUILD_BUG_ON (FAN_RENAME !=FS_RENAME ); -BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) !=20 ); +BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) !=21 ); mask =fanotify_group_event_mask (group, iter_info, &match_mask, mask, data, data_type, dir);
fs/notify/fanotify/fanotify_user.c +8 -0
@@ -1599,6 +1599,14 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, (!fid_mode || mark_type == FAN_MARK_MOUNT)) goto fput_and_out; +/* +* FAN_RENAME uses special info type records to report the old and +* new parent+name. Reporting only old and new parent id is less +* useful and was not implemented. +*/ +if (mask &FAN_RENAME && !(fid_mode &FAN_REPORT_NAME )) + goto fput_and_out; +if (flags &FAN_MARK_FLUSH ) { ret =0 ;if (mark_type ==FAN_MARK_MOUNT )
include/linux/fanotify.h +2 -1
@@ -82,7 +82,8 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */* Directory entry modification events - reported only to directory * where entry is modified and not to a watching parent. */ -#define FANOTIFY_DIRENT_EVENTS (FAN_MOVE | FAN_CREATE | FAN_DELETE) +#define FANOTIFY_DIRENT_EVENTS (FAN_MOVE | FAN_CREATE | FAN_DELETE | \ + FAN_RENAME)/* Events that can be reported with event->fd */ #define FANOTIFY_FD_EVENTS (FANOTIFY_PATH_EVENTS | FANOTIFY_PERM_EVENTS)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 416/770 exit: Implement kthread_exit
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric W. Biederman <[email protected]>
[ Upstream commit bbda86e988d4c124e4cfa816291cbd583ae8bfb1 ]
The way the per task_struct exit_code is used by kernel threads is not quite compatible how it is used by userspace applications. The low byte of the userspace exit_code value encodes the exit signal. While kthreads just use the value as an int holding ordinary kernel function exit status like -EPERM.
Add kthread_exit to clearly separate the two kinds of uses.
Stable-dep-of: ca3574bd653a ("exit: Rename module_put_and_exit to module_put_and_kthread_exit")
--- include/linux/kthread.h | 1 + kernel/kthread.c | 23 +++++++++++++++++++---- tools/objtool/check.c | 1 + 3 files changed, 21 insertions(+), 4 deletions(-)
include/linux/kthread.h +1 -0
@@ -68,6 +68,7 @@ void *kthread_probe_data(struct task_struct *k);int kthread_park (struct task_struct *k);void kthread_unpark (struct task_struct *k);void kthread_parkme (void ); +void kthread_exit (long result)__noreturn ;int kthreadd (void *unused);extern struct task_struct *kthreadd_task;
kernel/kthread.c +19 -4
@@ -262,6 +262,21 @@ void kthread_parkme(void) }EXPORT_SYMBOL_GPL (kthread_parkme); +/** +* kthread_exit - Cause the current kthread return @result to kthread_stop(). +* @result: The integer value to return to kthread_stop(). +* +* While kthread_exit can be called directly, it exists so that +* functions which do some additional work in non-modular code such as +* module_put_and_kthread_exit can be implemented. +* +* Does not return. +*/ +void __noreturn kthread_exit (long result) +{ +do_exit (result); +} +static int kthread (void *_create) {/* Copy data: it's on kthread's stack */
@@ -279,13 +294,13 @@ static int kthread(void *_create) done =xchg (&create->done,NULL );if (!done) {kfree (create); -do_exit (-EINTR ); +kthread_exit (-EINTR ); }if (!self) { create->result =ERR_PTR (-ENOMEM );complete (done); -do_exit (-ENOMEM ); +kthread_exit (-ENOMEM ); } self->threadfn = threadfn;
@@ -312,7 +327,7 @@ static int kthread(void *_create)__kthread_parkme (self); ret =threadfn (data); } -do_exit (ret); +kthread_exit (ret); }/* called from do_fork() to get node information for about to be created task */
@@ -621,7 +636,7 @@ EXPORT_SYMBOL_GPL(kthread_park);* instead of calling wake_up_process(): the thread will exit without * calling threadfn(). * -* If threadfn() may call do_exit() itself, the caller must ensure +* If threadfn() may call kthread_exit() itself, the caller must ensure * task_struct can't go away. * * Returns the result of threadfn(), or %-EINTR if wake_up_process()
tools/objtool/check.c +1 -0
@@ -168,6 +168,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,"panic" ,"do_exit" ,"do_task_dead" , +"kthread_exit" ,"make_task_dead" ,"__module_put_and_exit" , "complete_and_exit",
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 417/770 exit: Rename module_put_and_exit to module_put_and_kthread_exit
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric W. Biederman <[email protected]>
[ Upstream commit ca3574bd653aba234a4b31955f2778947403be16 ]
Update module_put_and_exit to call kthread_exit instead of do_exit.
Change the name to reflect this change in functionality. All of the users of module_put_and_exit are causing the current kthread to exit so this change makes it clear what is happening. There is no functional change.
--- crypto/algboss.c | 4 ++-- fs/cifs/connect.c | 2 +- fs/nfs/callback.c | 4 ++-- fs/nfs/nfs4state.c | 2 +- fs/nfsd/nfssvc.c | 2 +- include/linux/module.h | 6 +++--- kernel/module.c | 6 +++--- net/bluetooth/bnep/core.c | 2 +- net/bluetooth/cmtp/core.c | 2 +- net/bluetooth/hidp/core.c | 2 +- tools/objtool/check.c | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-)
crypto/algboss.c +2 -2
@@ -74,7 +74,7 @@ static int cryptomgr_probe(void *data)complete_all (¶m->larval->completion);crypto_alg_put (¶m->larval->alg);kfree (param); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 ); }static int cryptomgr_schedule_probe (struct crypto_larval *larval)
@@ -209,7 +209,7 @@ static int cryptomgr_test(void *data)crypto_alg_tested (param->driver, err);kfree (param); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 ); }static int cryptomgr_schedule_test (struct crypto_alg *alg)
fs/cifs/connect.c +1 -1
@@ -1242,7 +1242,7 @@ cifs_demultiplex_thread(void *p) }memalloc_noreclaim_restore (noreclaim_flag); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 ); }/* extract the host portion of the UNC string */
fs/nfs/callback.c +2 -2
@@ -93,7 +93,7 @@ nfs4_callback_svc(void *vrqstp)svc_process (rqstp); }svc_exit_thread (rqstp); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 );return 0 ; }
@@ -137,7 +137,7 @@ nfs41_callback_svc(void *vrqstp) } }svc_exit_thread (rqstp); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 );return 0 ; }
fs/nfs/nfs4state.c +1 -1
@@ -2757,7 +2757,7 @@ static int nfs4_run_state_manager(void *ptr) goto again;nfs_put_client (clp); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 );return 0 ; }
fs/nfsd/nfssvc.c +1 -1
@@ -986,7 +986,7 @@ nfsd(void *vrqstp)/* Release module */ mutex_unlock (&nfsd_mutex); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 );return 0 ; }
include/linux/module.h +3 -3
@@ -604,9 +604,9 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,/* Look for this name: can be of form module:name. */ unsigned long module_kallsyms_lookup_name (const char *name); -extern void __noreturn __module_put_and_exit (struct module *mod, +extern void __noreturn __module_put_and_kthread_exit (struct module *mod,long code); -#define module_put_and_exit (code) __module_put_and_exit(THIS_MODULE, code) +#define module_put_and_kthread_exit (code) __module_put_and_kthread_exit(THIS_MODULE, code)#ifdef CONFIG_MODULE_UNLOAD int module_refcount (struct module *mod);
@@ -798,7 +798,7 @@ static inline int unregister_module_notifier(struct notifier_block *nb)return 0 ; } -#define module_put_and_exit (code) do_exit(code) +#define module_put_and_kthread_exit (code) kthread_exit(code)static inline void print_modules (void ) {
kernel/module.c +3 -3
@@ -336,12 +336,12 @@ static inline void add_taint_module(struct module *mod, unsigned flag,* A thread that wants to hold a reference to a module only while it * is running can call this to safely exit. nfsd and lockd use this. */ -void __noreturn __module_put_and_exit (struct module *mod,long code) +void __noreturn __module_put_and_kthread_exit (struct module *mod,long code) {module_put (mod); -do_exit (code); +kthread_exit (code); } -EXPORT_SYMBOL (__module_put_and_exit); +EXPORT_SYMBOL (__module_put_and_kthread_exit);/* Find a module section: 0 means not found. */ static unsigned int find_sec (const struct load_info *info,const char *name)
net/bluetooth/bnep/core.c +1 -1
@@ -535,7 +535,7 @@ static int bnep_session(void *arg)up_write (&bnep_session_sem);free_netdev (dev); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 );return 0 ; }
net/bluetooth/cmtp/core.c +1 -1
@@ -323,7 +323,7 @@ static int cmtp_session(void *arg)up_write (&cmtp_session_sem);kfree (session); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 );return 0 ; }
net/bluetooth/hidp/core.c +1 -1
@@ -1305,7 +1305,7 @@ static int hidp_session_thread(void *arg)l2cap_unregister_user (session->conn, &session->user);hidp_session_put (session); -module_put_and_exit (0 ); +module_put_and_kthread_exit (0 );return 0 ; }
tools/objtool/check.c +1 -1
@@ -170,7 +170,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,"do_task_dead" ,"kthread_exit" ,"make_task_dead" , -"__module_put_and_exit" , +"__module_put_and_kthread_exit" ,"complete_and_exit" ,"__reiserfs_panic" , "lbug_with_loc",
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 418/770 NFSD: Fix sparse warning
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 c2f1c4bd20621175c581f298b4943df0cffbd841 ]
/home/cel/src/linux/linux/fs/nfsd/nfs4proc.c:1539:24: warning: incorrect type in assignment (different base types)/home/cel/src/linux/linux/fs/nfsd/nfs4proc.c:1539:24: expected restricted __be32 [usertype] status/home/cel/src/linux/linux/fs/nfsd/nfs4proc.c:1539:24: got int
--- fs/nfsd/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -1508,7 +1508,7 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)u64 bytes_total = copy->cp_count;u64 src_pos = copy->cp_src_pos;u64 dst_pos = copy->cp_dst_pos; -__be32 status; +int status;/* See RFC 7862 p.67: */ if (bytes_total ==0 )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 419/770 NFSD: handle errors better in write_ports_addfd()
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 89b24336f03a8ba560e96b0c47a8434a7fa48e3c ]
If write_ports_add() fails, we shouldn't destroy the serv, unless we had only just created it. So if there are any permanent sockets already attached, leave the serv in place.
--- fs/nfsd/nfsctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfsctl.c +1 -1
@@ -742,7 +742,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct credreturn err; err =svc_addsock (nn->nfsd_serv, fd, buf,SIMPLE_TRANSACTION_LIMIT , cred); -if (err <0 ) { +if (err <0 &&list_empty (&nn->nfsd_serv->sv_permsocks)) {nfsd_destroy (net);return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 420/770 SUNRPC: change svc_get() to return the svc.
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 df5e49c880ea0776806b8a9f8ab95e035272cf6f ]
It is common for 'get' functions to return the object that was 'got', and there are a couple of places where users of svc_get() would be a little simpler if svc_get() did that.
Make it so.
--- fs/lockd/svc.c | 6 ++---- fs/nfs/callback.c | 6 ++---- include/linux/sunrpc/svc.h | 3 ++- 3 files changed, 6 insertions(+), 9 deletions(-)
fs/lockd/svc.c +2 -4
@@ -430,14 +430,12 @@ static struct svc_serv *lockd_create_svc(void)/* * Check whether we're already up and running. */ -if (nlmsvc_rqst) { +if (nlmsvc_rqst)/* * Note: increase service usage, because later in case of error * svc_destroy() will be called. */ -svc_get (nlmsvc_rqst->rq_server); -return nlmsvc_rqst->rq_server; - } +return svc_get (nlmsvc_rqst->rq_server);/* * Sanity check: if there's no pid,
fs/nfs/callback.c +2 -4
@@ -266,14 +266,12 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion)/* * Check whether we're already up and running. */ -if (cb_info->serv) { +if (cb_info->serv)/* * Note: increase service usage, because later in case of error * svc_destroy() will be called. */ -svc_get (cb_info->serv); -return cb_info->serv; - } +return svc_get (cb_info->serv);switch (minorversion) {case 0 :
include/linux/sunrpc/svc.h +2 -1
@@ -120,9 +120,10 @@ struct svc_serv {* change the number of threads. Horrible, but there it is. * Should be called with the "service mutex" held. */ -static inline void svc_get (struct svc_serv *serv) +static inline struct svc_serv *svc_get (struct svc_serv *serv) { serv->sv_nrthreads++; +return serv; }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 421/770 SUNRPC/NFSD: clean up get/put functions.
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 8c62d12740a1450d2e8456d5747f440e10db281a ]
svc_destroy() is poorly named - it doesn't necessarily destroy the svc, it might just reduce the ref count.nfsd_destroy() is poorly named for the same reason.
This patch:
- removes the refcount functionality from svc_destroy(), moving it to a new svc_put(). Almost all previous callers of svc_destroy() now call svc_put().
- renames nfsd_destroy() to nfsd_put() and improves the code, using the new svc_destroy() rather than svc_put()
- removes a few comments that explain the important for balanced get/put calls. This should be obvious.
The only non-trivial part of this is that svc_destroy() would call svc_sock_update() on a non-final decrement. It can no longer do that, and svc_put() isn't really a good place of it. This call is now made from svc_exit_thread() which seems like a good place. This makes the call *before* sv_nrthreads is decremented rather than after. This is not particularly important as the call just sets a flag which causes sv_nrthreads set be checked later. A subsequent patch will improve the ordering.
--- fs/lockd/svc.c | 6 +----- fs/nfs/callback.c | 14 ++------------ fs/nfsd/nfsctl.c | 4 ++-- fs/nfsd/nfsd.h | 2 +- fs/nfsd/nfssvc.c | 30 ++++++++++++++++-------------- include/linux/sunrpc/svc.h | 26 +++++++++++++++++++++++--- net/sunrpc/svc.c | 19 +++++-------------- 7 files changed, 50 insertions(+), 51 deletions(-)
fs/lockd/svc.c +1 -5
@@ -431,10 +431,6 @@ static struct svc_serv *lockd_create_svc(void)* Check whether we're already up and running. */ if (nlmsvc_rqst) -/* -* Note: increase service usage, because later in case of error -* svc_destroy() will be called. -*/ return svc_get (nlmsvc_rqst->rq_server);/*
@@ -495,7 +491,7 @@ int lockd_up(struct net *net, const struct cred *cred)* so we exit through here on both success and failure. */ err_put: -svc_destroy (serv); +svc_put (serv); err_create:mutex_unlock (&nlmsvc_mutex);return error;
fs/nfs/callback.c +2 -12
@@ -267,10 +267,6 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion)* Check whether we're already up and running. */ if (cb_info->serv) -/* -* Note: increase service usage, because later in case of error -* svc_destroy() will be called. -*/ return svc_get (cb_info->serv);switch (minorversion) {
@@ -333,16 +329,10 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) goto err_start; cb_info->users++; -/* -* svc_create creates the svc_serv with sv_nrthreads == 1, and then -* svc_prepare_thread increments that. So we need to call svc_destroy -* on both success and failure so that the refcount is 1 when the -* thread exits. -*/ err_net:if (!cb_info->users) cb_info->serv =NULL ; -svc_destroy (serv); +svc_put (serv); err_create:mutex_unlock (&nfs_callback_mutex);return ret;
@@ -368,7 +358,7 @@ void nfs_callback_down(int minorversion, struct net *net)if (cb_info->users ==0 ) {svc_get (serv); serv->sv_ops->svo_setup (serv,NULL ,0 ); -svc_destroy (serv); +svc_put (serv);dprintk ("nfs_callback_down: service destroyed\n" ); cb_info->serv =NULL ; }
fs/nfsd/nfsctl.c +2 -2
@@ -743,7 +743,7 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred err =svc_addsock (nn->nfsd_serv, fd, buf,SIMPLE_TRANSACTION_LIMIT , cred);if (err <0 &&list_empty (&nn->nfsd_serv->sv_permsocks)) { -nfsd_destroy (net); +nfsd_put (net);return err; }
@@ -796,7 +796,7 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct crif (!list_empty (&nn->nfsd_serv->sv_permsocks)) nn->nfsd_serv->sv_nrthreads--;else -nfsd_destroy (net); +nfsd_put (net);return err; }
fs/nfsd/nfsd.h +1 -1
@@ -97,7 +97,7 @@ int nfsd_pool_stats_open(struct inode *, struct file *);int nfsd_pool_stats_release (struct inode *,struct file *);void nfsd_shutdown_threads (struct net *net); -void nfsd_destroy (struct net *net); +void nfsd_put (struct net *net);bool i_am_nfsd (void );
fs/nfsd/nfssvc.c +16 -14
@@ -623,7 +623,7 @@ void nfsd_shutdown_threads(struct net *net)svc_get (serv);/* Kill outstanding nfsd threads */ serv->sv_ops->svo_setup (serv,NULL ,0 ); -nfsd_destroy (net); +nfsd_put (net);mutex_unlock (&nfsd_mutex);/* Wait for shutdown of nfsd_serv to complete */ wait_for_completion (&nn->nfsd_shutdown_complete);
@@ -656,7 +656,10 @@ int nfsd_create_serv(struct net *net) nn->nfsd_serv->sv_maxconn = nn->max_connections; error =svc_bind (nn->nfsd_serv, net);if (error <0 ) { -svc_destroy (nn->nfsd_serv); +/* NOT nfsd_put() as notifiers (see below) haven't +* been set up yet. +*/ +svc_put (nn->nfsd_serv);nfsd_complete_shutdown (net);return error; }
@@ -697,16 +700,16 @@ int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)return 0 ; } -void nfsd_destroy (struct net *net) +void nfsd_put (struct net *net) {struct nfsd_net *nn =net_generic (net, nfsd_net_id); -int destroy = (nn->nfsd_serv->sv_nrthreads ==1 ); -if (destroy) + nn->nfsd_serv->sv_nrthreads -=1 ; +if (nn->nfsd_serv->sv_nrthreads ==0 ) {svc_shutdown_net (nn->nfsd_serv, net); -svc_destroy (nn->nfsd_serv); -if (destroy) +svc_destroy (nn->nfsd_serv);nfsd_complete_shutdown (net); + } }int nfsd_set_nrthreads (int n,int *nthreads,struct net *net)
@@ -758,7 +761,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)if (err)break ; } -nfsd_destroy (net); +nfsd_put (net);return err; }
@@ -795,7 +798,7 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred) error =nfsd_startup_net (net, cred);if (error) - goto out_destroy; + goto out_put; error = nn->nfsd_serv->sv_ops->svo_setup (nn->nfsd_serv,NULL , nrservs);if (error)
@@ -808,8 +811,8 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred) out_shutdown:if (error <0 && !nfsd_up_before)nfsd_shutdown_net (net); -out_destroy: -nfsd_destroy (net);/* Release server */ +out_put: +nfsd_put (net); out:mutex_unlock (&nfsd_mutex);return error;
@@ -982,7 +985,7 @@ nfsd(void *vrqstp)/* Release the thread */ svc_exit_thread (rqstp); -nfsd_destroy (net); +nfsd_put (net);/* Release module */ mutex_unlock (&nfsd_mutex);
@@ -1109,8 +1112,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file)struct net *net = inode->i_sb->s_fs_info;mutex_lock (&nfsd_mutex); -/* this function really, really should have been called svc_put() */ -nfsd_destroy (net); +nfsd_put (net);mutex_unlock (&nfsd_mutex);return ret; }
include/linux/sunrpc/svc.h +23 -3
@@ -114,8 +114,13 @@ struct svc_serv {#endif /* CONFIG_SUNRPC_BACKCHANNEL */ }; -/* -* We use sv_nrthreads as a reference count. svc_destroy() drops +/** +* svc_get() - increment reference count on a SUNRPC serv +* @serv: the svc_serv to have count incremented +* +* Returns: the svc_serv that was passed in. +* +* We use sv_nrthreads as a reference count. svc_put() drops * this refcount, so we need to bump it up around operations that * change the number of threads. Horrible, but there it is. * Should be called with the "service mutex" held.
@@ -126,6 +131,22 @@ static inline struct svc_serv *svc_get(struct svc_serv *serv)return serv; } +void svc_destroy (struct svc_serv *serv); + +/** +* svc_put - decrement reference count on a SUNRPC serv +* @serv: the svc_serv to have count decremented +* +* When the reference count reaches zero, svc_destroy() +* is called to clean up and free the serv. +*/ +static inline void svc_put (struct svc_serv *serv) +{ + serv->sv_nrthreads -=1 ; +if (serv->sv_nrthreads ==0 ) +svc_destroy (serv); +} +/* * Maximum payload size supported by a kernel RPC server. * This is use to determine the max number of pages nfsd is
@@ -518,7 +539,6 @@ struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,int svc_set_num_threads (struct svc_serv *,struct svc_pool *,int );int svc_set_num_threads_sync (struct svc_serv *,struct svc_pool *,int );int svc_pool_stats_open (struct svc_serv *serv,struct file *file); -void svc_destroy (struct svc_serv *);void svc_shutdown_net (struct svc_serv *,struct net *);int svc_process (struct svc_rqst *); int bc_svc_process(struct svc_serv *, struct rpc_rqst *,
net/sunrpc/svc.c +5 -14
@@ -526,17 +526,7 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net);void svc_destroy (struct svc_serv *serv) { -dprintk ("svc: svc_destroy(%s, %d)\n" , - serv->sv_program->pg_name, - serv->sv_nrthreads); - -if (serv->sv_nrthreads) { -if (--(serv->sv_nrthreads) !=0 ) { -svc_sock_update_bufs (serv); -return ; - } - }else -printk ("svc_destroy: no threads for serv=%p!\n" , serv); +dprintk ("svc: svc_destroy(%s)\n" , serv->sv_program->pg_name);del_timer_sync (&serv->sv_temptimer);
@@ -893,9 +883,10 @@ svc_exit_thread(struct svc_rqst *rqstp)svc_rqst_free (rqstp); -/* Release the server */ -if (serv) -svc_destroy (serv); +if (!serv) +return ; +svc_sock_update_bufs (serv); +svc_destroy (serv); }EXPORT_SYMBOL_GPL (svc_exit_thread);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 422/770 SUNRPC: stop using ->sv_nrthreads as a refcount
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 ec52361df99b490f6af412b046df9799b92c1050 ]
The use of sv_nrthreads as a general refcount results in clumsy code, as is seen by various comments needed to explain the situation.
This patch introduces a 'struct kref' and uses that for reference counting, leaving sv_nrthreads to be a pure count of threads. The kref is managed particularly in svc_get() and svc_put(), and also nfsd_put();
svc_destroy() now takes a pointer to the embedded kref, rather than to the serv.
nfsd allows the svc_serv to exist with ->sv_nrhtreads being zero. This happens when a transport is created before the first thread is started. To support this, a 'keep_active' flag is introduced which holds a ref on the svc_serv. This is set when any listening socket is successfully added (unless there are running threads), and cleared when the number of threads is set. So when the last thread exits, the nfs_serv will be destroyed.
The use of 'keep_active' replaces previous code which checked if there were any permanent sockets.
We no longer clear ->rq_server when nfsd() exits. This was done to prevent svc_exit_thread() from calling svc_destroy(). Instead we take an extra reference to the svc_serv to prevent svc_destroy() from being called.
--- fs/lockd/svc.c | 4 ---- fs/nfs/callback.c | 2 +- fs/nfsd/netns.h | 7 +++++++ fs/nfsd/nfsctl.c | 22 +++++++++----------- fs/nfsd/nfssvc.c | 42 +++++++++++++++++++++++--------------- include/linux/sunrpc/svc.h | 14 ++++--------- net/sunrpc/svc.c | 22 ++++++++++---------- 7 files changed, 59 insertions(+), 54 deletions(-)
fs/lockd/svc.c +0 -4
@@ -486,10 +486,6 @@ int lockd_up(struct net *net, const struct cred *cred) goto err_put; } nlmsvc_users++; -/* -* Note: svc_serv structures have an initial use count of 1, -* so we exit through here on both success and failure. -*/ err_put:svc_put (serv); err_create:
fs/nfs/callback.c +1 -1
@@ -169,7 +169,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,if (nrservs <NFS4_MIN_NR_CALLBACK_THREADS ) nrservs =NFS4_MIN_NR_CALLBACK_THREADS ; -if (serv->sv_nrthreads-1 == nrservs) +if (serv->sv_nrthreads == nrservs)return 0 ; ret = serv->sv_ops->svo_setup (serv,NULL , nrservs);
fs/nfsd/netns.h +7 -0
@@ -123,6 +123,13 @@ struct nfsd_net {u32 clverifier_counter;struct svc_serv *nfsd_serv; +/* When a listening socket is added to nfsd, keep_active is set +* and this justifies a reference on nfsd_serv. This stops +* nfsd_serv from being freed. When the number of threads is +* set, keep_active is cleared and the reference is dropped. So +* when the last thread exits, the service will be destroyed. +*/ +int keep_active;wait_queue_head_t ntf_wq;atomic_t ntf_refcnt;
fs/nfsd/nfsctl.c +10 -12
@@ -742,13 +742,12 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct credreturn err; err =svc_addsock (nn->nfsd_serv, fd, buf,SIMPLE_TRANSACTION_LIMIT , cred); -if (err <0 &&list_empty (&nn->nfsd_serv->sv_permsocks)) { -nfsd_put (net); -return err; - } -/* Decrease the count, but don't shut down the service */ - nn->nfsd_serv->sv_nrthreads--; +if (err >=0 && + !nn->nfsd_serv->sv_nrthreads && !xchg (&nn->keep_active,1 )) +svc_get (nn->nfsd_serv); + +nfsd_put (net);return err; }
@@ -783,8 +782,10 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct crif (err <0 && err != -EAFNOSUPPORT ) goto out_close; -/* Decrease the count, but don't shut down the service */ - nn->nfsd_serv->sv_nrthreads--; +if (!nn->nfsd_serv->sv_nrthreads && !xchg (&nn->keep_active,1 )) +svc_get (nn->nfsd_serv); + +nfsd_put (net);return 0 ; out_close: xprt =svc_find_xprt (nn->nfsd_serv, transport, net,PF_INET , port);
@@ -793,10 +794,7 @@ static ssize_t __write_ports_addxprt(char *buf, struct net *net, const struct crsvc_xprt_put (xprt); } out_err: -if (!list_empty (&nn->nfsd_serv->sv_permsocks)) - nn->nfsd_serv->sv_nrthreads--; -else -nfsd_put (net); +nfsd_put (net);return err; }
fs/nfsd/nfssvc.c +26 -16
86 lines not on this page · raw message
include/linux/sunrpc/svc.h +4 -10
@@ -85,6 +85,7 @@ struct svc_serv {struct svc_program * sv_program;/* RPC program */ struct svc_stat * sv_stats;/* RPC statistics */ spinlock_t sv_lock; +struct kref sv_refcnt;unsigned int sv_nrthreads;/* # of server threads */ unsigned int sv_maxconn;/* max connections allowed or * '0' causing max to be based
@@ -119,19 +120,14 @@ struct svc_serv {* @serv: the svc_serv to have count incremented * * Returns: the svc_serv that was passed in. -* -* We use sv_nrthreads as a reference count. svc_put() drops -* this refcount, so we need to bump it up around operations that -* change the number of threads. Horrible, but there it is. -* Should be called with the "service mutex" held. */ static inline struct svc_serv *svc_get (struct svc_serv *serv) { - serv->sv_nrthreads++; +kref_get (&serv->sv_refcnt);return serv; } -void svc_destroy (struct svc_serv *serv); +void svc_destroy (struct kref *);/** * svc_put - decrement reference count on a SUNRPC serv
@@ -142,9 +138,7 @@ void svc_destroy(struct svc_serv *serv);*/ static inline void svc_put (struct svc_serv *serv) { - serv->sv_nrthreads -=1 ; -if (serv->sv_nrthreads ==0 ) -svc_destroy (serv); +kref_put (&serv->sv_refcnt, svc_destroy); }/*
net/sunrpc/svc.c +11 -11
@@ -433,7 +433,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools,return NULL ; serv->sv_name = prog->pg_name; serv->sv_program = prog; - serv->sv_nrthreads =1 ; +kref_init (&serv->sv_refcnt); serv->sv_stats = prog->pg_stats;if (bufsize >RPCSVC_MAXPAYLOAD ) bufsize =RPCSVC_MAXPAYLOAD ;
@@ -524,10 +524,11 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net);* protect the sv_nrthreads, sv_permsocks and sv_tempsocks. */ void -svc_destroy (struct svc_serv *serv) +svc_destroy (struct kref *ref) { -dprintk ("svc: svc_destroy(%s)\n" , serv->sv_program->pg_name); + struct svc_serv *serv = container_of(ref, struct svc_serv, sv_refcnt); +dprintk ("svc: svc_destroy(%s)\n" , serv->sv_program->pg_name);del_timer_sync (&serv->sv_temptimer);/*
@@ -635,6 +636,7 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)if (!rqstp)return ERR_PTR (-ENOMEM ); +svc_get (serv); serv->sv_nrthreads++;spin_lock_bh (&pool->sp_lock); pool->sp_nrthreads++;
@@ -774,8 +776,7 @@ int svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) { if (pool == NULL) { -/* The -1 assumes caller has done a svc_get() */ - nrservs -= (serv->sv_nrthreads-1); + nrservs -= serv->sv_nrthreads; } else {spin_lock_bh (&pool->sp_lock); nrservs -= pool->sp_nrthreads;
@@ -816,8 +817,7 @@ int svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrservs) { if (pool == NULL) { -/* The -1 assumes caller has done a svc_get() */ - nrservs -= (serv->sv_nrthreads-1); + nrservs -= serv->sv_nrthreads; } else {spin_lock_bh (&pool->sp_lock); nrservs -= pool->sp_nrthreads;
@@ -881,12 +881,12 @@ svc_exit_thread(struct svc_rqst *rqstp)list_del_rcu (&rqstp->rq_all);spin_unlock_bh (&pool->sp_lock); + serv->sv_nrthreads -=1 ; +svc_sock_update_bufs (serv); +svc_rqst_free (rqstp); -if (!serv) -return ; -svc_sock_update_bufs (serv); -svc_destroy (serv); +svc_put (serv); }EXPORT_SYMBOL_GPL (svc_exit_thread);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 423/770 nfsd: make nfsd_stats.th_cnt atomic_t
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 9b6c8c9bebccd5fb785c306b948c08874a88874d ]
This allows us to move the updates for th_cnt out of the mutex. This is a step towards reducing mutex coverage in nfsd().
--- fs/nfsd/nfssvc.c | 6 +++--- fs/nfsd/stats.c | 2 +- fs/nfsd/stats.h | 4 +--- 3 files changed, 5 insertions(+), 7 deletions(-)
fs/nfsd/nfssvc.c +3 -3
@@ -57,7 +57,7 @@ static __be32 nfsd_init_request(struct svc_rqst *,/* * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members * of the svc_serv struct. In particular, ->sv_nrthreads but also to some -* extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt +* extent ->sv_temp_socks and ->sv_permsocks. * * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0 (unless
@@ -955,8 +955,8 @@ nfsd(void *vrqstp)allow_signal (SIGINT );allow_signal (SIGQUIT ); - nfsdstats.th_cnt++;mutex_unlock (&nfsd_mutex); +atomic_inc (&nfsdstats.th_cnt);set_freezable ();
@@ -983,8 +983,8 @@ nfsd(void *vrqstp)/* Clear signals before calling svc_exit_thread() */ flush_signals (current); +atomic_dec (&nfsdstats.th_cnt);mutex_lock (&nfsd_mutex); - nfsdstats.th_cnt --; out:/* Take an extra ref so that the svc_put in svc_exit_thread()
fs/nfsd/stats.c +1 -1
@@ -45,7 +45,7 @@ static int nfsd_proc_show(struct seq_file *seq, void *v) percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_WRITE]));/* thread usage: */ -seq_printf (seq,"th %u 0" , nfsdstats.th_cnt); +seq_printf (seq,"th %u 0" ,atomic_read (&nfsdstats.th_cnt));/* deprecated thread usage histogram stats */ for (i =0 ; i <10 ; i++)
fs/nfsd/stats.h +1 -3
@@ -29,11 +29,9 @@ enum {struct nfsd_stats {struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM ]; -/* Protected by nfsd_mutex */ -unsigned int th_cnt;/* number of available threads */ +atomic_t th_cnt;/* number of available threads */ }; -extern struct nfsd_stats nfsdstats;extern struct svc_stat nfsd_svcstats;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 424/770 SUNRPC: use sv_lock to protect updates to sv_nrthreads.
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 2a36395fac3b72771f87c3ee4387e3a96d85a7cc ]
Using sv_lock means we don't need to hold the service mutex over these updates.
In particular, svc_exit_thread() no longer requires synchronisation, so threads can exit asynchronously.
Note that we could use an atomic_t, but as there are many more read sites than writes, that would add unnecessary noise to the code. Some reads are already racy, and there is no need for them to not be.
--- fs/nfsd/nfssvc.c | 5 ++--- net/sunrpc/svc.c | 9 +++++++-- 2 files changed, 9 insertions(+), 5 deletions(-)
fs/nfsd/nfssvc.c +2 -3
@@ -55,9 +55,8 @@ static __be32 nfsd_init_request(struct svc_rqst *, struct svc_process_info *);/* -* nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members -* of the svc_serv struct. In particular, ->sv_nrthreads but also to some -* extent ->sv_temp_socks and ->sv_permsocks. +* nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and some members +* of the svc_serv struct such as ->sv_temp_socks and ->sv_permsocks. * * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0 (unless
net/sunrpc/svc.c +7 -2
@@ -521,7 +521,7 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net);/* * Destroy an RPC service. Should be called with appropriate locking to -* protect the sv_nrthreads, sv_permsocks and sv_tempsocks. +* protect sv_permsocks and sv_tempsocks. */ void svc_destroy (struct kref *ref)
@@ -637,7 +637,10 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)return ERR_PTR (-ENOMEM );svc_get (serv); - serv->sv_nrthreads++; +spin_lock_bh (&serv->sv_lock); + serv->sv_nrthreads +=1 ; +spin_unlock_bh (&serv->sv_lock); +spin_lock_bh (&pool->sp_lock); pool->sp_nrthreads++;list_add_rcu (&rqstp->rq_all, &pool->sp_all_threads);
@@ -881,7 +884,9 @@ svc_exit_thread(struct svc_rqst *rqstp)list_del_rcu (&rqstp->rq_all);spin_unlock_bh (&pool->sp_lock); +spin_lock_bh (&serv->sv_lock); serv->sv_nrthreads -=1 ; +spin_unlock_bh (&serv->sv_lock);svc_sock_update_bufs (serv);svc_rqst_free (rqstp);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 425/770 NFSD: narrow nfsd_mutex protection in nfsd thread
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 9d3792aefdcda71d20c2b1ecc589c17ae71eb523 ]
There is nothing happening in the start of nfsd() that requires protection by the mutex, so don't take it until shutting down the thread
- which does still require protection - but only for nfsd_put().
--- fs/nfsd/nfssvc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
fs/nfsd/nfssvc.c +2 -6
@@ -932,9 +932,6 @@ nfsd(void *vrqstp)struct nfsd_net *nn =net_generic (net, nfsd_net_id);int err; -/* Lock module and set up kernel thread */ -mutex_lock (&nfsd_mutex); -/* At this point, the thread shares current->fs * with the init process. We need to create files with the * umask as defined by the client instead of init's umask. */
@@ -954,7 +951,6 @@ nfsd(void *vrqstp)allow_signal (SIGINT );allow_signal (SIGQUIT ); -mutex_unlock (&nfsd_mutex);atomic_inc (&nfsdstats.th_cnt);set_freezable ();
@@ -983,7 +979,6 @@ nfsd(void *vrqstp)flush_signals (current);atomic_dec (&nfsdstats.th_cnt); -mutex_lock (&nfsd_mutex); out:/* Take an extra ref so that the svc_put in svc_exit_thread()
@@ -995,10 +990,11 @@ nfsd(void *vrqstp)svc_exit_thread (rqstp);/* Now if needed we call svc_destroy in appropriate context */ +mutex_lock (&nfsd_mutex);nfsd_put (net); +mutex_unlock (&nfsd_mutex);/* Release module */ -mutex_unlock (&nfsd_mutex);module_put_and_kthread_exit (0 );return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 426/770 NFSD: Make it possible to use svc_set_num_threads_sync
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 3409e4f1e8f239f0ed81be0b068ecf4e73e2e826 ]
nfsd cannot currently use svc_set_num_threads_sync. It instead uses svc_set_num_threads which does *not* wait for threads to all exit, and has a separate mechanism (nfsd_shutdown_complete) to wait for completion.
The reason that nfsd is unlike other services is that nfsd threads can exit separately from svc_set_num_threads being called - they die on receipt of SIGKILL. Also, when the last thread exits, the service must be shut down (sockets closed).
For this, the nfsd_mutex needs to be taken, and as that mutex needs to be held while svc_set_num_threads is called, the one cannot wait for the other.
This patch changes the nfsd thread so that it can drop the ref on the service without blocking on nfsd_mutex, so that svc_set_num_threads_sync can be used:
- if it can drop a non-last reference, it does that. This does not trigger shutdown and does not require a mutex. This will likely happen for all but the last thread signalled, and for all threads being shut down by nfsd_shutdown_threads()
- if it can get the mutex without blocking (trylock), it does that and then drops the reference. This will likely happen for the last thread killed by SIGKILL
- Otherwise there might be an unrelated task holding the mutex, possibly in another network namespace, or nfsd_shutdown_threads() might be just about to get a reference on the service, after which we can drop ours safely.
We cannot conveniently get wakeup notifications on these events, and we are unlikely to need to, so we sleep briefly and check again.
With this we can discard nfsd_shutdown_complete and nfsd_complete_shutdown(), and switch to svc_set_num_threads_sync.
--- fs/nfsd/netns.h | 3 --- fs/nfsd/nfssvc.c | 41 +++++++++++++++++++------------------- include/linux/sunrpc/svc.h | 13 ++++++++++++ 3 files changed, 33 insertions(+), 24 deletions(-)
fs/nfsd/netns.h +0 -3
@@ -134,9 +134,6 @@ struct nfsd_net {wait_queue_head_t ntf_wq;atomic_t ntf_refcnt; -/* Allow umount to wait for nfsd state cleanup */ -struct completion nfsd_shutdown_complete; -/* * clientid and stateid data for construction of net unique COPY * stateids.
fs/nfsd/nfssvc.c +20 -21
86 lines not on this page · raw message
include/linux/sunrpc/svc.h +13 -0
@@ -141,6 +141,19 @@ static inline void svc_put(struct svc_serv *serv)kref_put (&serv->sv_refcnt, svc_destroy); } +/** +* svc_put_not_last - decrement non-final reference count on SUNRPC serv +* @serv: the svc_serv to have count decremented +* +* Returns: %true is refcount was decremented. +* +* If the refcount is 1, it is not decremented and instead failure is reported. +*/ +static inline bool svc_put_not_last (struct svc_serv *serv) +{ +return refcount_dec_not_one (&serv->sv_refcnt.refcount); +} +/* * Maximum payload size supported by a kernel RPC server. * This is use to determine the max number of pages nfsd is
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 427/770 SUNRPC: discard svo_setup and rename svc_set_num_threads_sync()
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 3ebdbe5203a874614819700d3f470724cb803709 ]
The ->svo_setup callback serves no purpose. It is always called from within the same module that chooses which callback is needed. So discard it and call the relevant function directly.
Now that svc_set_num_threads() is no longer used remove it and rename svc_set_num_threads_sync() to remove the "_sync" suffix.
--- fs/nfs/callback.c | 8 +++---- fs/nfsd/nfssvc.c | 11 ++++----- include/linux/sunrpc/svc.h | 4 ---- net/sunrpc/svc.c | 49 ++------------------------------------ 4 files changed, 10 insertions(+), 62 deletions(-)
fs/nfs/callback.c +3 -5
@@ -172,9 +172,9 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,if (serv->sv_nrthreads == nrservs)return 0 ; - ret = serv->sv_ops->svo_setup (serv,NULL , nrservs); + ret =svc_set_num_threads (serv,NULL , nrservs);if (ret) { - serv->sv_ops->svo_setup (serv,NULL ,0 ); +svc_set_num_threads (serv,NULL ,0 );return ret; }dprintk ("nfs_callback_up: service started\n" );
@@ -235,14 +235,12 @@ static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,static const struct svc_serv_ops nfs40_cb_sv_ops = { .svo_function = nfs4_callback_svc, .svo_enqueue_xprt = svc_xprt_do_enqueue, - .svo_setup = svc_set_num_threads_sync, .svo_module =THIS_MODULE , };#if defined(CONFIG_NFS_V4_1 )static const struct svc_serv_ops nfs41_cb_sv_ops = { .svo_function = nfs41_callback_svc, .svo_enqueue_xprt = svc_xprt_do_enqueue, - .svo_setup = svc_set_num_threads_sync, .svo_module =THIS_MODULE , };
@@ -357,7 +355,7 @@ void nfs_callback_down(int minorversion, struct net *net) cb_info->users--;if (cb_info->users ==0 ) {svc_get (serv); - serv->sv_ops->svo_setup (serv,NULL ,0 ); +svc_set_num_threads (serv,NULL ,0 );svc_put (serv);dprintk ("nfs_callback_down: service destroyed\n" ); cb_info->serv =NULL ;
fs/nfsd/nfssvc.c +5 -6
@@ -593,7 +593,6 @@ static const struct svc_serv_ops nfsd_thread_sv_ops = { .svo_shutdown = nfsd_last_thread, .svo_function = nfsd, .svo_enqueue_xprt = svc_xprt_do_enqueue, - .svo_setup = svc_set_num_threads_sync, .svo_module = THIS_MODULE, };
@@ -611,7 +610,7 @@ void nfsd_shutdown_threads(struct net *net)svc_get (serv);/* Kill outstanding nfsd threads */ - serv->sv_ops->svo_setup (serv,NULL ,0 ); +svc_set_num_threads (serv,NULL ,0 );nfsd_put (net);mutex_unlock (&nfsd_mutex); }
@@ -750,8 +749,9 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)/* apply the new numbers */ svc_get (nn->nfsd_serv);for (i =0 ; i < n; i++) { - err = nn->nfsd_serv->sv_ops->svo_setup (nn->nfsd_serv, - &nn->nfsd_serv->sv_pools[i], nthreads[i]); + err =svc_set_num_threads (nn->nfsd_serv, + &nn->nfsd_serv->sv_pools[i], + nthreads[i]);if (err)break ; }
@@ -793,8 +793,7 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred) error =nfsd_startup_net (net, cred);if (error) goto out_put; - error = nn->nfsd_serv->sv_ops->svo_setup (nn->nfsd_serv, -NULL , nrservs); + error =svc_set_num_threads (nn->nfsd_serv,NULL , nrservs);if (error) goto out_shutdown; error = nn->nfsd_serv->sv_nrthreads;
include/linux/sunrpc/svc.h +0 -4
@@ -64,9 +64,6 @@ struct svc_serv_ops {/* queue up a transport for servicing */ void (*svo_enqueue_xprt)(struct svc_xprt *); -/* set up thread (or whatever) execution context */ -int (*svo_setup)(struct svc_serv *,struct svc_pool *,int ); -/* optional module to count when adding threads (pooled svcs only) */ struct module *svo_module; };
@@ -544,7 +541,6 @@ void svc_pool_map_put(void);struct svc_serv *svc_create_pooled (struct svc_program *,unsigned int ,const struct svc_serv_ops *);int svc_set_num_threads (struct svc_serv *,struct svc_pool *,int ); -int svc_set_num_threads_sync (struct svc_serv *,struct svc_pool *,int );int svc_pool_stats_open (struct svc_serv *serv,struct file *file);void svc_shutdown_net (struct svc_serv *,struct net *);int svc_process (struct svc_rqst *);
net/sunrpc/svc.c +2 -47
74 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 428/770 NFSD: simplify locking for network notifier.
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 d057cfec4940ce6eeffa22b4a71dec203b06cd55 ]
nfsd currently maintains an open-coded read/write semaphore (refcount and wait queue) for each network namespace to ensure the nfs service isn't shut down while the notifier is running.
This is excessive. As there is unlikely to be contention between notifiers and they run without sleeping, a single spinlock is sufficient to avoid problems.
--- fs/nfsd/netns.h | 3 --- fs/nfsd/nfsctl.c | 2 -- fs/nfsd/nfssvc.c | 38 ++++++++++++++++++++------------------ 3 files changed, 20 insertions(+), 23 deletions(-)
fs/nfsd/netns.h +0 -3
@@ -131,9 +131,6 @@ struct nfsd_net {*/ int keep_active; -wait_queue_head_t ntf_wq; -atomic_t ntf_refcnt; -/* * clientid and stateid data for construction of net unique COPY * stateids.
fs/nfsd/nfsctl.c +0 -2
@@ -1484,8 +1484,6 @@ static __net_init int nfsd_init_net(struct net *net) nn->clientid_counter = nn->clientid_base +1 ; nn->s2s_cp_cl_id = nn->clientid_counter++; -atomic_set (&nn->ntf_refcnt,0 ); -init_waitqueue_head (&nn->ntf_wq);seqlock_init (&nn->boot_lock);return 0 ;
fs/nfsd/nfssvc.c +20 -18
@@ -434,6 +434,7 @@ static void nfsd_shutdown_net(struct net *net)nfsd_shutdown_generic (); } +static DEFINE_SPINLOCK (nfsd_notifier_lock);static int nfsd_inetaddr_event (struct notifier_block *this,unsigned long event,void *ptr) {
@@ -443,18 +444,17 @@ static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,struct nfsd_net *nn =net_generic (net, nfsd_net_id);struct sockaddr_in sin; -if ((event !=NETDEV_DOWN ) || - !atomic_inc_not_zero (&nn->ntf_refcnt)) +if (event !=NETDEV_DOWN || !nn->nfsd_serv) goto out; +spin_lock (&nfsd_notifier_lock);if (nn->nfsd_serv) {dprintk ("nfsd_inetaddr_event: removed %pI4\n" , &ifa->ifa_local); sin.sin_family =AF_INET ; sin.sin_addr.s_addr = ifa->ifa_local;svc_age_temp_xprts_now (nn->nfsd_serv, (struct sockaddr *)&sin); } -atomic_dec (&nn->ntf_refcnt); -wake_up (&nn->ntf_wq); +spin_unlock (&nfsd_notifier_lock); out:return NOTIFY_DONE ;
@@ -474,10 +474,10 @@ static int nfsd_inet6addr_event(struct notifier_block *this,struct nfsd_net *nn =net_generic (net, nfsd_net_id);struct sockaddr_in6 sin6; -if ((event !=NETDEV_DOWN ) || - !atomic_inc_not_zero (&nn->ntf_refcnt)) +if (event !=NETDEV_DOWN || !nn->nfsd_serv) goto out; +spin_lock (&nfsd_notifier_lock);if (nn->nfsd_serv) {dprintk ("nfsd_inet6addr_event: removed %pI6\n" , &ifa->addr); sin6.sin6_family =AF_INET6 ;
@@ -486,8 +486,8 @@ static int nfsd_inet6addr_event(struct notifier_block *this, sin6.sin6_scope_id = ifa->idev->dev->ifindex;svc_age_temp_xprts_now (nn->nfsd_serv, (struct sockaddr *)&sin6); } -atomic_dec (&nn->ntf_refcnt); -wake_up (&nn->ntf_wq); +spin_unlock (&nfsd_notifier_lock); + out:return NOTIFY_DONE ; }
@@ -504,7 +504,6 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) {struct nfsd_net *nn =net_generic (net, nfsd_net_id); -atomic_dec (&nn->ntf_refcnt);/* check if the notifier still has clients */ if (atomic_dec_return (&nfsd_notifier_refcount) ==0 ) {unregister_inetaddr_notifier (&nfsd_inetaddr_notifier);
@@ -512,7 +511,6 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)unregister_inet6addr_notifier (&nfsd_inet6addr_notifier);#endif } -wait_event (nn->ntf_wq,atomic_read (&nn->ntf_refcnt) ==0 );/* * write_ports can create the server without actually starting
@@ -624,6 +622,7 @@ int nfsd_create_serv(struct net *net) {int error;struct nfsd_net *nn =net_generic (net, nfsd_net_id); +struct svc_serv *serv;WARN_ON (!mutex_is_locked (&nfsd_mutex));if (nn->nfsd_serv) {
@@ -633,21 +632,23 @@ int nfsd_create_serv(struct net *net)if (nfsd_max_blksize ==0 ) nfsd_max_blksize =nfsd_get_default_max_blksize ();nfsd_reset_versions (nn); - nn->nfsd_serv =svc_create_pooled (&nfsd_program, nfsd_max_blksize, - &nfsd_thread_sv_ops); -if (nn->nfsd_serv ==NULL ) + serv =svc_create_pooled (&nfsd_program, nfsd_max_blksize, + &nfsd_thread_sv_ops); +if (serv ==NULL )return -ENOMEM ; - nn->nfsd_serv->sv_maxconn = nn->max_connections; - error =svc_bind (nn->nfsd_serv, net); + serv->sv_maxconn = nn->max_connections; + error =svc_bind (serv, net);if (error <0 ) {/* NOT nfsd_put() as notifiers (see below) haven't * been set up yet. */ -svc_put (nn->nfsd_serv); - nn->nfsd_serv =NULL ; +svc_put (serv);return error; } +spin_lock (&nfsd_notifier_lock); + nn->nfsd_serv = serv; +spin_unlock (&nfsd_notifier_lock);set_max_drc ();/* check if the notifier is already set */
@@ -657,7 +658,6 @@ int nfsd_create_serv(struct net *net)register_inet6addr_notifier (&nfsd_inet6addr_notifier);#endif } -atomic_inc (&nn->ntf_refcnt);nfsd_reset_boot_verifier (nn);return 0 ; }
@@ -701,7 +701,9 @@ void nfsd_put(struct net *net)if (kref_put (&nn->nfsd_serv->sv_refcnt, nfsd_noop)) {svc_shutdown_net (nn->nfsd_serv, net);svc_destroy (&nn->nfsd_serv->sv_refcnt); +spin_lock (&nfsd_notifier_lock); nn->nfsd_serv =NULL ; +spin_unlock (&nfsd_notifier_lock); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 429/770 lockd: introduce nlmsvc_serv
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 2840fe864c91a0fe822169b1fbfddbcac9aeac43 ]
lockd has two globals - nlmsvc_task and nlmsvc_rqst - but mostly it wants the 'struct svc_serv', and when it doesn't want it exactly it can get to what it wants from the serv.
This patch is a first step to removing nlmsvc_task and nlmsvc_rqst. It introduces nlmsvc_serv to store the 'struct svc_serv*'. This is set as soon as the serv is created, and cleared only when it is destroyed.
--- fs/lockd/svc.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-)
fs/lockd/svc.c +20 -16
@@ -54,6 +54,7 @@ EXPORT_SYMBOL_GPL(nlmsvc_ops);static DEFINE_MUTEX (nlmsvc_mutex);static unsigned int nlmsvc_users; +static struct svc_serv *nlmsvc_serv;static struct task_struct *nlmsvc_task;static struct svc_rqst *nlmsvc_rqst;unsigned long nlmsvc_timeout;
@@ -306,13 +307,12 @@ static int lockd_inetaddr_event(struct notifier_block *this, !atomic_inc_not_zero(&nlm_ntf_refcnt)) goto out; -if (nlmsvc_rqst) { +if (nlmsvc_serv) {dprintk ("lockd_inetaddr_event: removed %pI4\n" , &ifa->ifa_local); sin.sin_family =AF_INET ; sin.sin_addr.s_addr = ifa->ifa_local; -svc_age_temp_xprts_now (nlmsvc_rqst->rq_server, - (struct sockaddr *)&sin); +svc_age_temp_xprts_now (nlmsvc_serv, (struct sockaddr *)&sin); }atomic_dec (&nlm_ntf_refcnt);wake_up (&nlm_ntf_wq);
@@ -336,14 +336,13 @@ static int lockd_inet6addr_event(struct notifier_block *this, !atomic_inc_not_zero(&nlm_ntf_refcnt)) goto out; -if (nlmsvc_rqst) { +if (nlmsvc_serv) {dprintk ("lockd_inet6addr_event: removed %pI6\n" , &ifa->addr); sin6.sin6_family =AF_INET6 ; sin6.sin6_addr = ifa->addr;if (ipv6_addr_type (&sin6.sin6_addr) &IPV6_ADDR_LINKLOCAL ) sin6.sin6_scope_id = ifa->idev->dev->ifindex; -svc_age_temp_xprts_now (nlmsvc_rqst->rq_server, - (struct sockaddr *)&sin6); +svc_age_temp_xprts_now (nlmsvc_serv, (struct sockaddr *)&sin6); }atomic_dec (&nlm_ntf_refcnt);wake_up (&nlm_ntf_wq);
@@ -423,15 +422,17 @@ static const struct svc_serv_ops lockd_sv_ops = { .svo_enqueue_xprt = svc_xprt_do_enqueue, }; -static struct svc_serv *lockd_create_svc (void ) +static int lockd_create_svc (void ) {struct svc_serv *serv;/* * Check whether we're already up and running. */ -if (nlmsvc_rqst) -return svc_get (nlmsvc_rqst->rq_server); +if (nlmsvc_serv) { +svc_get (nlmsvc_serv); +return 0 ; + }/* * Sanity check: if there's no pid,
@@ -448,14 +449,15 @@ static struct svc_serv *lockd_create_svc(void) serv =svc_create (&nlmsvc_program,LOCKD_BUFSIZE , &lockd_sv_ops);if (!serv) {printk (KERN_WARNING "lockd_up: create service failed\n" ); -return ERR_PTR (-ENOMEM ); +return -ENOMEM ; } + nlmsvc_serv = serv;register_inetaddr_notifier (&lockd_inetaddr_notifier);#if IS_ENABLED (CONFIG_IPV6 )register_inet6addr_notifier (&lockd_inet6addr_notifier);#endif dprintk ("lockd_up: service created\n" ); -return serv; +return 0 ; }/*
@@ -468,11 +470,10 @@ int lockd_up(struct net *net, const struct cred *cred)mutex_lock (&nlmsvc_mutex); - serv =lockd_create_svc (); -if (IS_ERR (serv)) { - error =PTR_ERR (serv); + error =lockd_create_svc (); +if (error) goto err_create; - } + serv = nlmsvc_serv; error =lockd_up_net (serv, net, cred);if (error <0 ) {
@@ -487,6 +488,8 @@ int lockd_up(struct net *net, const struct cred *cred) } nlmsvc_users++; err_put: +if (nlmsvc_users ==0 ) + nlmsvc_serv =NULL ;svc_put (serv); err_create:mutex_unlock (&nlmsvc_mutex);
@@ -501,7 +504,7 @@ void lockd_down(struct net *net) {mutex_lock (&nlmsvc_mutex); -lockd_down_net (nlmsvc_rqst->rq_server, net); +lockd_down_net (nlmsvc_serv, net);if (nlmsvc_users) {if (--nlmsvc_users) goto out;
@@ -519,6 +522,7 @@ lockd_down(struct net *net)dprintk ("lockd_down: service stopped\n" );lockd_svc_exit_thread ();dprintk ("lockd_down: service destroyed\n" ); + nlmsvc_serv =NULL ; nlmsvc_task =NULL ; nlmsvc_rqst =NULL ; out:
Signature · 1 line
2.43.0