From d75e490f35601aae12c7284d3c22684c65fb8354 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sat, 29 Jul 2023 14:36:10 -0400 Subject: SUNRPC: change svc_xprt::xpt_flags bits to enum When a sequence of numbers are needed for internal-use only, an enum is typically best. The sequence will inevitably need to be changed one day, and having an enum means the developer doesn't need to think about renumbering after insertion or deletion. Such patches will be easier to review. Suggested-by: NeilBrown Signed-off-by: Chuck Lever --- include/trace/events/sunrpc.h | 53 ++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 18 deletions(-) (limited to 'include/trace') diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 43711753616a..00db9e1fb711 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h @@ -1918,25 +1918,42 @@ TRACE_EVENT(svc_stats_latency, __get_str(procedure), __entry->execute) ); +/* + * from include/linux/sunrpc/svc_xprt.h + */ +#define SVC_XPRT_FLAG_LIST \ + svc_xprt_flag(BUSY) \ + svc_xprt_flag(CONN) \ + svc_xprt_flag(CLOSE) \ + svc_xprt_flag(DATA) \ + svc_xprt_flag(TEMP) \ + svc_xprt_flag(DEAD) \ + svc_xprt_flag(CHNGBUF) \ + svc_xprt_flag(DEFERRED) \ + svc_xprt_flag(OLD) \ + svc_xprt_flag(LISTENER) \ + svc_xprt_flag(CACHE_AUTH) \ + svc_xprt_flag(LOCAL) \ + svc_xprt_flag(KILL_TEMP) \ + svc_xprt_flag(CONG_CTRL) \ + svc_xprt_flag(HANDSHAKE) \ + svc_xprt_flag(TLS_SESSION) \ + svc_xprt_flag_end(PEER_AUTH) + +#undef svc_xprt_flag +#undef svc_xprt_flag_end +#define svc_xprt_flag(x) TRACE_DEFINE_ENUM(XPT_##x); +#define svc_xprt_flag_end(x) TRACE_DEFINE_ENUM(XPT_##x); + +SVC_XPRT_FLAG_LIST + +#undef svc_xprt_flag +#undef svc_xprt_flag_end +#define svc_xprt_flag(x) { BIT(XPT_##x), #x }, +#define svc_xprt_flag_end(x) { BIT(XPT_##x), #x } + #define show_svc_xprt_flags(flags) \ - __print_flags(flags, "|", \ - { BIT(XPT_BUSY), "BUSY" }, \ - { BIT(XPT_CONN), "CONN" }, \ - { BIT(XPT_CLOSE), "CLOSE" }, \ - { BIT(XPT_DATA), "DATA" }, \ - { BIT(XPT_TEMP), "TEMP" }, \ - { BIT(XPT_DEAD), "DEAD" }, \ - { BIT(XPT_CHNGBUF), "CHNGBUF" }, \ - { BIT(XPT_DEFERRED), "DEFERRED" }, \ - { BIT(XPT_OLD), "OLD" }, \ - { BIT(XPT_LISTENER), "LISTENER" }, \ - { BIT(XPT_CACHE_AUTH), "CACHE_AUTH" }, \ - { BIT(XPT_LOCAL), "LOCAL" }, \ - { BIT(XPT_KILL_TEMP), "KILL_TEMP" }, \ - { BIT(XPT_CONG_CTRL), "CONG_CTRL" }, \ - { BIT(XPT_HANDSHAKE), "HANDSHAKE" }, \ - { BIT(XPT_TLS_SESSION), "TLS_SESSION" }, \ - { BIT(XPT_PEER_AUTH), "PEER_AUTH" }) + __print_flags(flags, "|", SVC_XPRT_FLAG_LIST) TRACE_EVENT(svc_xprt_create_err, TP_PROTO( -- cgit v1.2.3 From 78c542f916bccafffef4f3bec9bc60d7cda548f5 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sat, 29 Jul 2023 20:58:54 -0400 Subject: SUNRPC: Add enum svc_auth_status In addition to the benefits of using an enum rather than a set of macros, we now have a named type that can improve static type checking of function return values. As part of this change, I removed a stale comment from svcauth.h; the return values from current implementations of the auth_ops::release method are all zero/negative errno, not the SVC_OK enum values as the old comment suggested. Suggested-by: NeilBrown Signed-off-by: Chuck Lever --- fs/lockd/svc.c | 2 +- fs/nfs/callback.c | 2 +- include/linux/sunrpc/svc.h | 2 +- include/linux/sunrpc/svcauth.h | 50 +++++++++++++++++++-------------------- include/trace/events/sunrpc.h | 9 ++++--- net/sunrpc/auth_gss/svcauth_gss.c | 7 ++---- net/sunrpc/svc.c | 6 ++++- net/sunrpc/svcauth.c | 35 ++++++++++++++++++++++----- net/sunrpc/svcauth_unix.c | 9 ++++--- 9 files changed, 73 insertions(+), 49 deletions(-) (limited to 'include/trace') diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index ef3f77a59556..6579948070a4 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -506,7 +506,7 @@ static inline int is_callback(u32 proc) } -static int lockd_authenticate(struct svc_rqst *rqstp) +static enum svc_auth_status lockd_authenticate(struct svc_rqst *rqstp) { rqstp->rq_client = NULL; switch (rqstp->rq_authop->flavour) { diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 39a0ba746267..466ebf1d41b2 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -372,7 +372,7 @@ check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp) * All other checking done after NFS decoding where the nfs_client can be * found in nfs4_callback_compound */ -static int nfs_callback_authenticate(struct svc_rqst *rqstp) +static enum svc_auth_status nfs_callback_authenticate(struct svc_rqst *rqstp) { rqstp->rq_auth_stat = rpc_autherr_badcred; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 9b429253dbd9..1c491f02efc8 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -336,7 +336,7 @@ struct svc_program { char * pg_name; /* service name */ char * pg_class; /* class name: services sharing authentication */ struct svc_stat * pg_stats; /* rpc statistics */ - int (*pg_authenticate)(struct svc_rqst *); + enum svc_auth_status (*pg_authenticate)(struct svc_rqst *rqstp); __be32 (*pg_init_request)(struct svc_rqst *, const struct svc_program *, struct svc_process_info *); diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index 27582d3b538f..6f90203edbf8 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -83,6 +83,19 @@ struct auth_domain { struct rcu_head rcu_head; }; +enum svc_auth_status { + SVC_GARBAGE = 1, + SVC_SYSERR, + SVC_VALID, + SVC_NEGATIVE, + SVC_OK, + SVC_DROP, + SVC_CLOSE, + SVC_DENIED, + SVC_PENDING, + SVC_COMPLETE, +}; + /* * Each authentication flavour registers an auth_ops * structure. @@ -98,6 +111,8 @@ struct auth_domain { * is (probably) already in place. Certainly space is * reserved for it. * DROP - simply drop the request. It may have been deferred + * CLOSE - like SVC_DROP, but request is definitely lost. + * If there is a tcp connection, it should be closed. * GARBAGE - rpc garbage_args error * SYSERR - rpc system_err error * DENIED - authp holds reason for denial. @@ -111,14 +126,10 @@ struct auth_domain { * * release() is given a request after the procedure has been run. * It should sign/encrypt the results if needed - * It should return: - * OK - the resbuf is ready to be sent - * DROP - the reply should be quitely dropped - * DENIED - authp holds a reason for MSG_DENIED - * SYSERR - rpc system_err * * domain_release() * This call releases a domain. + * * set_client() * Givens a pending request (struct svc_rqst), finds and assigns * an appropriate 'auth_domain' as the client. @@ -127,31 +138,18 @@ struct auth_ops { char * name; struct module *owner; int flavour; - 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); -}; -#define SVC_GARBAGE 1 -#define SVC_SYSERR 2 -#define SVC_VALID 3 -#define SVC_NEGATIVE 4 -#define SVC_OK 5 -#define SVC_DROP 6 -#define SVC_CLOSE 7 /* Like SVC_DROP, but request is definitely - * lost so if there is a tcp connection, it - * should be closed - */ -#define SVC_DENIED 8 -#define SVC_PENDING 9 -#define SVC_COMPLETE 10 + enum svc_auth_status (*accept)(struct svc_rqst *rqstp); + int (*release)(struct svc_rqst *rqstp); + void (*domain_release)(struct auth_domain *dom); + enum svc_auth_status (*set_client)(struct svc_rqst *rqstp); +}; struct svc_xprt; -extern int svc_authenticate(struct svc_rqst *rqstp); +extern enum svc_auth_status svc_authenticate(struct svc_rqst *rqstp); extern int svc_authorise(struct svc_rqst *rqstp); -extern int svc_set_client(struct svc_rqst *rqstp); +extern enum svc_auth_status svc_set_client(struct svc_rqst *rqstp); extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops); extern void svc_auth_unregister(rpc_authflavor_t flavor); @@ -161,7 +159,7 @@ extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *ne extern struct auth_domain *auth_domain_find(char *name); extern void svcauth_unix_purge(struct net *net); extern void svcauth_unix_info_release(struct svc_xprt *xpt); -extern int svcauth_unix_set_client(struct svc_rqst *rqstp); +extern enum svc_auth_status svcauth_unix_set_client(struct svc_rqst *rqstp); extern int unix_gid_cache_create(struct net *net); extern void unix_gid_cache_destroy(struct net *net); diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 00db9e1fb711..55716b62ce91 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h @@ -1706,7 +1706,7 @@ TRACE_DEFINE_ENUM(SVC_DENIED); TRACE_DEFINE_ENUM(SVC_PENDING); TRACE_DEFINE_ENUM(SVC_COMPLETE); -#define svc_show_status(status) \ +#define show_svc_auth_status(status) \ __print_symbolic(status, \ { SVC_GARBAGE, "SVC_GARBAGE" }, \ { SVC_SYSERR, "SVC_SYSERR" }, \ @@ -1743,7 +1743,10 @@ TRACE_DEFINE_ENUM(SVC_COMPLETE); __entry->xid, __get_sockaddr(server), __get_sockaddr(client) TRACE_EVENT_CONDITION(svc_authenticate, - TP_PROTO(const struct svc_rqst *rqst, int auth_res), + TP_PROTO( + const struct svc_rqst *rqst, + enum svc_auth_status auth_res + ), TP_ARGS(rqst, auth_res), @@ -1766,7 +1769,7 @@ TRACE_EVENT_CONDITION(svc_authenticate, TP_printk(SVC_RQST_ENDPOINT_FORMAT " auth_res=%s auth_stat=%s", SVC_RQST_ENDPOINT_VARARGS, - svc_show_status(__entry->svc_status), + show_svc_auth_status(__entry->svc_status), rpc_show_auth_stat(__entry->auth_stat)) ); diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index c4a566737085..18734e70c5dd 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -986,7 +986,7 @@ bad_unwrap: return -EINVAL; } -static int +static enum svc_auth_status svcauth_gss_set_client(struct svc_rqst *rqstp) { struct gss_svc_data *svcdata = rqstp->rq_auth_data; @@ -1634,7 +1634,7 @@ svcauth_gss_decode_credbody(struct xdr_stream *xdr, * * The rqstp->rq_auth_stat field is also set (see RFCs 2203 and 5531). */ -static int +static enum svc_auth_status svcauth_gss_accept(struct svc_rqst *rqstp) { struct gss_svc_data *svcdata = rqstp->rq_auth_data; @@ -1945,9 +1945,6 @@ bad_wrap: * %0: the Reply is ready to be sent * %-ENOMEM: failed to allocate memory * %-EINVAL: encoding error - * - * XXX: These return values do not match the return values documented - * for the auth_ops ->release method in linux/sunrpc/svcauth.h. */ static int svcauth_gss_release(struct svc_rqst *rqstp) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 030f8c759ee6..7873a3ff24a8 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1275,8 +1275,9 @@ svc_process_common(struct svc_rqst *rqstp) const struct svc_procedure *procp = NULL; struct svc_serv *serv = rqstp->rq_server; struct svc_process_info process; - int auth_res, rc; + enum svc_auth_status auth_res; unsigned int aoffset; + int rc; __be32 *p; /* Will be turned off by GSS integrity and privacy services */ @@ -1331,6 +1332,9 @@ svc_process_common(struct svc_rqst *rqstp) goto dropit; case SVC_COMPLETE: goto sendit; + default: + pr_warn_once("Unexpected svc_auth_status (%d)\n", auth_res); + goto err_system_err; } if (progp == NULL) diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c index 67d8245a08af..aa4429d0b810 100644 --- a/net/sunrpc/svcauth.c +++ b/net/sunrpc/svcauth.c @@ -60,8 +60,19 @@ svc_put_auth_ops(struct auth_ops *aops) module_put(aops->owner); } -int -svc_authenticate(struct svc_rqst *rqstp) +/** + * svc_authenticate - Initialize an outgoing credential + * @rqstp: RPC execution context + * + * Return values: + * %SVC_OK: XDR encoding of the result can begin + * %SVC_DENIED: Credential or verifier is not valid + * %SVC_GARBAGE: Failed to decode credential or verifier + * %SVC_COMPLETE: GSS context lifetime event; no further action + * %SVC_DROP: Drop this request; no further action + * %SVC_CLOSE: Like drop, but also close transport connection + */ +enum svc_auth_status svc_authenticate(struct svc_rqst *rqstp) { struct auth_ops *aops; u32 flavor; @@ -89,16 +100,28 @@ svc_authenticate(struct svc_rqst *rqstp) } EXPORT_SYMBOL_GPL(svc_authenticate); -int svc_set_client(struct svc_rqst *rqstp) +/** + * svc_set_client - Assign an appropriate 'auth_domain' as the client + * @rqstp: RPC execution context + * + * Return values: + * %SVC_OK: Client was found and assigned + * %SVC_DENY: Client was explicitly denied + * %SVC_DROP: Ignore this request + * %SVC_CLOSE: Ignore this request and close the connection + */ +enum svc_auth_status svc_set_client(struct svc_rqst *rqstp) { rqstp->rq_client = NULL; return rqstp->rq_authop->set_client(rqstp); } EXPORT_SYMBOL_GPL(svc_set_client); -/* A request, which was authenticated, has now executed. - * Time to finalise the credentials and verifier - * and release and resources +/** + * svc_authorise - Finalize credentials/verifier and release resources + * @rqstp: RPC execution context + * + * Returns zero on success, or a negative errno. */ int svc_authorise(struct svc_rqst *rqstp) { diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 174783f804fa..04b45588ae6f 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -665,7 +665,7 @@ static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp) } } -int +enum svc_auth_status svcauth_unix_set_client(struct svc_rqst *rqstp) { struct sockaddr_in *sin; @@ -736,7 +736,6 @@ out: rqstp->rq_auth_stat = rpc_auth_ok; return SVC_OK; } - EXPORT_SYMBOL_GPL(svcauth_unix_set_client); /** @@ -751,7 +750,7 @@ EXPORT_SYMBOL_GPL(svcauth_unix_set_client); * * rqstp->rq_auth_stat is set as mandated by RFC 5531. */ -static int +static enum svc_auth_status svcauth_null_accept(struct svc_rqst *rqstp) { struct xdr_stream *xdr = &rqstp->rq_arg_stream; @@ -828,7 +827,7 @@ struct auth_ops svcauth_null = { * * rqstp->rq_auth_stat is set as mandated by RFC 5531. */ -static int +static enum svc_auth_status svcauth_tls_accept(struct svc_rqst *rqstp) { struct xdr_stream *xdr = &rqstp->rq_arg_stream; @@ -913,7 +912,7 @@ struct auth_ops svcauth_tls = { * * rqstp->rq_auth_stat is set as mandated by RFC 5531. */ -static int +static enum svc_auth_status svcauth_unix_accept(struct svc_rqst *rqstp) { struct xdr_stream *xdr = &rqstp->rq_arg_stream; -- cgit v1.2.3 From 82e5d82a45741839bd9dcb6636cfcf67747a5af5 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 19 Jul 2023 15:24:42 -0400 Subject: SUNRPC: Move trace_svc_xprt_enqueue The xpt_flags field frequently changes between the time that svc_xprt_ready() grabs a copy and execution flow arrives at the tracepoint at the tail of svc_xprt_enqueue(). In fact, there's usually a sleep/wake-up in there, so those flags are almost guaranteed to be different. It would be more useful to record the exact flags that were used to decide whether the transport is ready, so move the tracepoint. Moving it means the tracepoint can't pick up the waker's pid. That can be added to struct svc_rqst if it turns out that is important. Signed-off-by: Chuck Lever --- include/trace/events/sunrpc.h | 18 +++++++++--------- net/sunrpc/svc_xprt.c | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'include/trace') diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 55716b62ce91..6beb38c1dcb5 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h @@ -2014,25 +2014,25 @@ TRACE_EVENT(svc_xprt_create_err, TRACE_EVENT(svc_xprt_enqueue, TP_PROTO( const struct svc_xprt *xprt, - const struct svc_rqst *rqst + unsigned long flags ), - TP_ARGS(xprt, rqst), + TP_ARGS(xprt, flags), TP_STRUCT__entry( SVC_XPRT_ENDPOINT_FIELDS(xprt) - - __field(int, pid) ), TP_fast_assign( - SVC_XPRT_ENDPOINT_ASSIGNMENTS(xprt); - - __entry->pid = rqst? rqst->rq_task->pid : 0; + __assign_sockaddr(server, &xprt->xpt_local, + xprt->xpt_locallen); + __assign_sockaddr(client, &xprt->xpt_remote, + xprt->xpt_remotelen); + __entry->flags = flags; + __entry->netns_ino = xprt->xpt_net->ns.inum; ), - TP_printk(SVC_XPRT_ENDPOINT_FORMAT " pid=%d", - SVC_XPRT_ENDPOINT_VARARGS, __entry->pid) + TP_printk(SVC_XPRT_ENDPOINT_FORMAT, SVC_XPRT_ENDPOINT_VARARGS) ); TRACE_EVENT(svc_xprt_dequeue, diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 9bdcdd8401b8..cdea4b49cbc5 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -434,6 +434,7 @@ static bool svc_xprt_ready(struct svc_xprt *xprt) smp_rmb(); xpt_flags = READ_ONCE(xprt->xpt_flags); + trace_svc_xprt_enqueue(xprt, xpt_flags); if (xpt_flags & BIT(XPT_BUSY)) return false; if (xpt_flags & (BIT(XPT_CONN) | BIT(XPT_CLOSE) | BIT(XPT_HANDSHAKE))) @@ -490,7 +491,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) rqstp = NULL; out_unlock: rcu_read_unlock(); - trace_svc_xprt_enqueue(xprt, rqstp); } EXPORT_SYMBOL_GPL(svc_xprt_enqueue); -- cgit v1.2.3