diff options
author | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2014-04-07 23:49:35 (GMT) |
commit | 62b8c978ee6b8d135d9e7953221de58000dba986 (patch) | |
tree | 683b04b2e627f6710c22c151b23c8cc9a165315e /net/sunrpc | |
parent | 78fd82238d0e5716578c326404184a27ba67fd6e (diff) | |
download | linux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz |
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 59 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_unseal.c | 8 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 10 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_upcall.c | 3 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_rpc_xdr.c | 29 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 4 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 177 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 23 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 2 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 4 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 63 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 75 |
12 files changed, 146 insertions, 311 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 42fdfc6..0846566 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -420,53 +420,41 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) memcpy(gss_msg->databuf, &uid, sizeof(uid)); gss_msg->msg.data = gss_msg->databuf; gss_msg->msg.len = sizeof(uid); - - BUILD_BUG_ON(sizeof(uid) > sizeof(gss_msg->databuf)); + BUG_ON(sizeof(uid) > UPCALL_BUF_LEN); } -static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, +static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, const char *service_name, const char *target_name) { struct gss_api_mech *mech = gss_msg->auth->mech; char *p = gss_msg->databuf; - size_t buflen = sizeof(gss_msg->databuf); - int len; - - len = scnprintf(p, buflen, "mech=%s uid=%d ", mech->gm_name, - from_kuid(&init_user_ns, gss_msg->uid)); - buflen -= len; - p += len; - gss_msg->msg.len = len; + int len = 0; + + gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ", + mech->gm_name, + from_kuid(&init_user_ns, gss_msg->uid)); + p += gss_msg->msg.len; if (target_name) { - len = scnprintf(p, buflen, "target=%s ", target_name); - buflen -= len; + len = sprintf(p, "target=%s ", target_name); p += len; gss_msg->msg.len += len; } if (service_name != NULL) { - len = scnprintf(p, buflen, "service=%s ", service_name); - buflen -= len; + len = sprintf(p, "service=%s ", service_name); p += len; gss_msg->msg.len += len; } if (mech->gm_upcall_enctypes) { - len = scnprintf(p, buflen, "enctypes=%s ", - mech->gm_upcall_enctypes); - buflen -= len; + len = sprintf(p, "enctypes=%s ", mech->gm_upcall_enctypes); p += len; gss_msg->msg.len += len; } - len = scnprintf(p, buflen, "\n"); - if (len == 0) - goto out_overflow; + len = sprintf(p, "\n"); gss_msg->msg.len += len; gss_msg->msg.data = gss_msg->databuf; - return 0; -out_overflow: - WARN_ON_ONCE(1); - return -ENOMEM; + BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN); } static struct gss_upcall_msg * @@ -475,15 +463,15 @@ gss_alloc_msg(struct gss_auth *gss_auth, { struct gss_upcall_msg *gss_msg; int vers; - int err = -ENOMEM; gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); if (gss_msg == NULL) - goto err; + return ERR_PTR(-ENOMEM); vers = get_pipe_version(gss_auth->net); - err = vers; - if (err < 0) - goto err_free_msg; + if (vers < 0) { + kfree(gss_msg); + return ERR_PTR(vers); + } gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe; INIT_LIST_HEAD(&gss_msg->list); rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); @@ -494,17 +482,10 @@ gss_alloc_msg(struct gss_auth *gss_auth, switch (vers) { case 0: gss_encode_v0_msg(gss_msg); - break; default: - err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); - if (err) - goto err_free_msg; + gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); }; return gss_msg; -err_free_msg: - kfree(gss_msg); -err: - return ERR_PTR(err); } static struct gss_upcall_msg * @@ -1517,7 +1498,7 @@ out: static int gss_refresh_null(struct rpc_task *task) { - return 0; + return -EACCES; } static __be32 * diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index 6c981dd..6cd930f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -150,6 +150,7 @@ gss_verify_mic_v2(struct krb5_ctx *ctx, struct xdr_netobj cksumobj = {.len = sizeof(cksumdata), .data = cksumdata}; s32 now; + u64 seqnum; u8 *ptr = read_token->data; u8 *cksumkey; u8 flags; @@ -196,10 +197,9 @@ gss_verify_mic_v2(struct krb5_ctx *ctx, if (now > ctx->endtime) return GSS_S_CONTEXT_EXPIRED; - /* - * NOTE: the sequence number at ptr + 8 is skipped, rpcsec_gss - * doesn't want it checked; see page 6 of rfc 2203. - */ + /* do sequencing checks */ + + seqnum = be64_to_cpup((__be64 *)ptr + 8); return GSS_S_COMPLETE; } diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 42560e5..1da52d1 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -489,6 +489,7 @@ static u32 gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) { s32 now; + u64 seqnum; u8 *ptr; u8 flags = 0x00; u16 ec, rrc; @@ -524,10 +525,7 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) ec = be16_to_cpup((__be16 *)(ptr + 4)); rrc = be16_to_cpup((__be16 *)(ptr + 6)); - /* - * NOTE: the sequence number at ptr + 8 is skipped, rpcsec_gss - * doesn't want it checked; see page 6 of rfc 2203. - */ + seqnum = be64_to_cpup((__be64 *)(ptr + 8)); if (rrc != 0) rotate_left(offset + 16, buf, rrc); @@ -576,8 +574,8 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip; buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip; - /* Trim off the trailing "extra count" and checksum blob */ - xdr_buf_trim(buf, ec + GSS_KRB5_TOK_HDR_LEN + tailskip); + /* Trim off the checksum blob */ + xdr_buf_trim(buf, GSS_KRB5_TOK_HDR_LEN + tailskip); return GSS_S_COMPLETE; } diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c index 458f85e..f1eb0d1 100644 --- a/net/sunrpc/auth_gss/gss_rpc_upcall.c +++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c @@ -298,8 +298,7 @@ int gssp_accept_sec_context_upcall(struct net *net, if (res.context_handle) { data->out_handle = rctxh.exported_context_token; data->mech_oid.len = rctxh.mech.len; - if (rctxh.mech.data) - memcpy(data->mech_oid.data, rctxh.mech.data, + memcpy(data->mech_oid.data, rctxh.mech.data, data->mech_oid.len); client_name = rctxh.src_name.display_name; } diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 1ec19f6..f0f78c5 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c @@ -559,8 +559,6 @@ static int gssx_enc_cred(struct xdr_stream *xdr, /* cred->elements */ err = dummy_enc_credel_array(xdr, &cred->elements); - if (err) - return err; /* cred->cred_handle_reference */ err = gssx_enc_buffer(xdr, &cred->cred_handle_reference); @@ -742,20 +740,22 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req, goto done; /* arg->context_handle */ - if (arg->context_handle) + if (arg->context_handle) { err = gssx_enc_ctx(xdr, arg->context_handle); - else + if (err) + goto done; + } else { err = gssx_enc_bool(xdr, 0); - if (err) - goto done; + } /* arg->cred_handle */ - if (arg->cred_handle) + if (arg->cred_handle) { err = gssx_enc_cred(xdr, arg->cred_handle); - else + if (err) + goto done; + } else { err = gssx_enc_bool(xdr, 0); - if (err) - goto done; + } /* arg->input_token */ err = gssx_enc_in_token(xdr, &arg->input_token); @@ -763,12 +763,13 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req, goto done; /* arg->input_cb */ - if (arg->input_cb) + if (arg->input_cb) { err = gssx_enc_cb(xdr, arg->input_cb); - else + if (err) + goto done; + } else { err = gssx_enc_bool(xdr, 0); - if (err) - goto done; + } err = gssx_enc_bool(xdr, arg->ret_deleg_cred); if (err) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 008cdad..09fb638 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1167,8 +1167,8 @@ static int gss_proxy_save_rsc(struct cache_detail *cd, if (!ud->found_creds) { /* userspace seem buggy, we should always get at least a * mapping to nobody */ - dprintk("RPC: No creds found!\n"); - goto out; + dprintk("RPC: No creds found, marking Negative!\n"); + set_bit(CACHE_NEGATIVE, &rsci.h.flags); } else { /* steal creds */ diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f09b7db..7747960 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -25,12 +25,12 @@ #include <linux/namei.h> #include <linux/mount.h> #include <linux/slab.h> -#include <linux/rcupdate.h> #include <linux/utsname.h> #include <linux/workqueue.h> #include <linux/in.h> #include <linux/in6.h> #include <linux/un.h> +#include <linux/rcupdate.h> #include <linux/sunrpc/clnt.h> #include <linux/sunrpc/addr.h> @@ -264,26 +264,6 @@ void rpc_clients_notifier_unregister(void) return rpc_pipefs_notifier_unregister(&rpc_clients_block); } -static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt, - struct rpc_xprt *xprt, - const struct rpc_timeout *timeout) -{ - struct rpc_xprt *old; - - spin_lock(&clnt->cl_lock); - old = rcu_dereference_protected(clnt->cl_xprt, - lockdep_is_held(&clnt->cl_lock)); - - if (!xprt_bound(xprt)) - clnt->cl_autobind = 1; - - clnt->cl_timeout = timeout; - rcu_assign_pointer(clnt->cl_xprt, xprt); - spin_unlock(&clnt->cl_lock); - - return old; -} - static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) { clnt->cl_nodelen = strlen(nodename); @@ -292,13 +272,12 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); } -static int rpc_client_register(struct rpc_clnt *clnt, - rpc_authflavor_t pseudoflavor, - const char *client_name) +static int rpc_client_register(const struct rpc_create_args *args, + struct rpc_clnt *clnt) { struct rpc_auth_create_args auth_args = { - .pseudoflavor = pseudoflavor, - .target_name = client_name, + .pseudoflavor = args->authflavor, + .target_name = args->client_name, }; struct rpc_auth *auth; struct net *net = rpc_net_ns(clnt); @@ -319,7 +298,7 @@ static int rpc_client_register(struct rpc_clnt *clnt, auth = rpcauth_create(&auth_args, clnt); if (IS_ERR(auth)) { dprintk("RPC: Couldn't create auth handle (flavor %u)\n", - pseudoflavor); + args->authflavor); err = PTR_ERR(auth); goto err_auth; } @@ -358,8 +337,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, { const struct rpc_program *program = args->program; const struct rpc_version *version; - struct rpc_clnt *clnt = NULL; - const struct rpc_timeout *timeout; + struct rpc_clnt *clnt = NULL; int err; /* sanity check the name before trying to print it */ @@ -387,6 +365,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, if (err) goto out_no_clid; + rcu_assign_pointer(clnt->cl_xprt, xprt); clnt->cl_procinfo = version->procs; clnt->cl_maxproc = version->nrprocs; clnt->cl_prog = args->prognumber ? : program->number; @@ -401,15 +380,16 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, INIT_LIST_HEAD(&clnt->cl_tasks); spin_lock_init(&clnt->cl_lock); - timeout = xprt->timeout; + if (!xprt_bound(xprt)) + clnt->cl_autobind = 1; + + clnt->cl_timeout = xprt->timeout; if (args->timeout != NULL) { memcpy(&clnt->cl_timeout_default, args->timeout, sizeof(clnt->cl_timeout_default)); - timeout = &clnt->cl_timeout_default; + clnt->cl_timeout = &clnt->cl_timeout_default; } - rpc_clnt_set_transport(clnt, xprt, timeout); - clnt->cl_rtt = &clnt->cl_rtt_default; rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); @@ -418,7 +398,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, /* save the nodename */ rpc_clnt_set_nodename(clnt, utsname()->nodename); - err = rpc_client_register(clnt, args->authflavor, args->client_name); + err = rpc_client_register(args, clnt); if (err) goto out_no_path; if (parent) @@ -620,80 +600,6 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) } EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth); -/** - * rpc_switch_client_transport: switch the RPC transport on the fly - * @clnt: pointer to a struct rpc_clnt - * @args: pointer to the new transport arguments - * @timeout: pointer to the new timeout parameters - * - * This function allows the caller to switch the RPC transport for the - * rpc_clnt structure 'clnt' to allow it to connect to a mirrored NFS - * server, for instance. It assumes that the caller has ensured that - * there are no active RPC tasks by using some form of locking. - * - * Returns zero if "clnt" is now using the new xprt. Otherwise a - * negative errno is returned, and "clnt" continues to use the old - * xprt. - */ -int rpc_switch_client_transport(struct rpc_clnt *clnt, - struct xprt_create *args, - const struct rpc_timeout *timeout) -{ - const struct rpc_timeout *old_timeo; - rpc_authflavor_t pseudoflavor; - struct rpc_xprt *xprt, *old; - struct rpc_clnt *parent; - int err; - - xprt = xprt_create_transport(args); - if (IS_ERR(xprt)) { - dprintk("RPC: failed to create new xprt for clnt %p\n", - clnt); - return PTR_ERR(xprt); - } - - pseudoflavor = clnt->cl_auth->au_flavor; - - old_timeo = clnt->cl_timeout; - old = rpc_clnt_set_transport(clnt, xprt, timeout); - - rpc_unregister_client(clnt); - __rpc_clnt_remove_pipedir(clnt); - - /* - * A new transport was created. "clnt" therefore - * becomes the root of a new cl_parent tree. clnt's - * children, if it has any, still point to the old xprt. - */ - parent = clnt->cl_parent; - clnt->cl_parent = clnt; - - /* - * The old rpc_auth cache cannot be re-used. GSS - * contexts in particular are between a single - * client and server. - */ - err = rpc_client_register(clnt, pseudoflavor, NULL); - if (err) - goto out_revert; - - synchronize_rcu(); - if (parent != clnt) - rpc_release_client(parent); - xprt_put(old); - dprintk("RPC: replaced xprt for clnt %p\n", clnt); - return 0; - -out_revert: - rpc_clnt_set_transport(clnt, old, old_timeo); - clnt->cl_parent = parent; - rpc_client_register(clnt, pseudoflavor, NULL); - xprt_put(xprt); - dprintk("RPC: failed to switch xprt for clnt %p\n", clnt); - return err; -} -EXPORT_SYMBOL_GPL(rpc_switch_client_transport); - /* * Kill all tasks for the given client. * XXX: kill their descendants as well? @@ -750,16 +656,14 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); /* * Free an RPC client */ -static struct rpc_clnt * +static void rpc_free_client(struct rpc_clnt *clnt) { - struct rpc_clnt *parent = NULL; - dprintk_rcu("RPC: destroying %s client for %s\n", clnt->cl_program->name, rcu_dereference(clnt->cl_xprt)->servername); if (clnt->cl_parent != clnt) - parent = clnt->cl_parent; + rpc_release_client(clnt->cl_parent); rpc_clnt_remove_pipedir(clnt); rpc_unregister_client(clnt); rpc_free_iostats(clnt->cl_metrics); @@ -768,17 +672,18 @@ rpc_free_client(struct rpc_clnt *clnt) rpciod_down(); rpc_free_clid(clnt); kfree(clnt); - return parent; } /* * Free an RPC client */ -static struct rpc_clnt * +static void rpc_free_auth(struct rpc_clnt *clnt) { - if (clnt->cl_auth == NULL) - return rpc_free_client(clnt); + if (clnt->cl_auth == NULL) { + rpc_free_client(clnt); + return; + } /* * Note: RPCSEC_GSS may need to send NULL RPC calls in order to @@ -789,8 +694,7 @@ rpc_free_auth(struct rpc_clnt *clnt) rpcauth_release(clnt->cl_auth); clnt->cl_auth = NULL; if (atomic_dec_and_test(&clnt->cl_count)) - return rpc_free_client(clnt); - return NULL; + rpc_free_client(clnt); } /* @@ -801,13 +705,10 @@ rpc_release_client(struct rpc_clnt *clnt) { dprintk("RPC: rpc_release_client(%p)\n", clnt); - do { - if (list_empty(&clnt->cl_tasks)) - wake_up(&destroy_wait); - if (!atomic_dec_and_test(&clnt->cl_count)) - break; - clnt = rpc_free_auth(clnt); - } while (clnt != NULL); + if (list_empty(&clnt->cl_tasks)) + wake_up(&destroy_wait); + if (atomic_dec_and_test(&clnt->cl_count)) + rpc_free_auth(clnt); } EXPORT_SYMBOL_GPL(rpc_release_client); @@ -871,8 +772,6 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) atomic_inc(&clnt->cl_count); if (clnt->cl_softrtry) task->tk_flags |= RPC_TASK_SOFT; - if (clnt->cl_noretranstimeo) - task->tk_flags |= RPC_TASK_NO_RETRANS_TIMEOUT; if (sk_memalloc_socks()) { struct rpc_xprt *xprt; @@ -1791,7 +1690,6 @@ call_connect_status(struct rpc_task *task) dprint_status(task); trace_rpc_connect_status(task, status); - task->tk_status = 0; switch (status) { /* if soft mounted, test if we've timed out */ case -ETIMEDOUT: @@ -1800,14 +1698,12 @@ call_connect_status(struct rpc_task *task) case -ECONNREFUSED: case -ECONNRESET: case -ENETUNREACH: - /* retry with existing socket, after a delay */ - rpc_delay(task, 3*HZ); if (RPC_IS_SOFTCONN(task)) break; - case -EAGAIN: - task->tk_action = call_bind; - return; + /* retry with existing socket, after a delay */ case 0: + case -EAGAIN: + task->tk_status = 0; clnt->cl_stats->netreconn++; task->tk_action = call_transmit; return; @@ -1821,14 +1717,13 @@ call_connect_status(struct rpc_task *task) static void call_transmit(struct rpc_task *task) { - int is_retrans = RPC_WAS_SENT(task); - dprint_status(task); task->tk_action = call_status; if (task->tk_status < 0) return; - if (!xprt_prepare_transmit(task)) + task->tk_status = xprt_prepare_transmit(task); + if (task->tk_status != 0) return; task->tk_action = call_transmit_status; /* Encode here so that rpcsec_gss can use correct sequence number. */ @@ -1847,8 +1742,6 @@ call_transmit(struct rpc_task *task) xprt_transmit(task); if (task->tk_status < 0) return; - if (is_retrans) - task->tk_client->cl_stats->rpcretrans++; /* * On success, ensure that we call xprt_end_transmit() before sleeping * in order to allow access to the socket to other RPC requests. @@ -1918,7 +1811,8 @@ call_bc_transmit(struct rpc_task *task) { struct rpc_rqst *req = task->tk_rqstp; - if (!xprt_prepare_transmit(task)) { + task->tk_status = xprt_prepare_transmit(task); + if (task->tk_status == -EAGAIN) { /* * Could not reserve the transport. Try again after the * transport is released. @@ -2006,8 +1900,7 @@ call_status(struct rpc_task *task) rpc_delay(task, 3*HZ); case -ETIMEDOUT: task->tk_action = call_timeout; - if (!(task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT) - && task->tk_client->cl_discrtry) + if (task->tk_client->cl_discrtry) xprt_conditional_disconnect(req->rq_xprt, req->rq_connect_cookie); break; @@ -2089,6 +1982,7 @@ call_timeout(struct rpc_task *task) rpcauth_invalcred(task); retry: + clnt->cl_stats->rpcretrans++; task->tk_action = call_bind; task->tk_status = 0; } @@ -2131,6 +2025,7 @@ call_decode(struct rpc_task *task) if (req->rq_rcv_buf.len < 12) { if (!RPC_IS_SOFT(task)) { task->tk_action = call_bind; + clnt->cl_stats->rpcretrans++; goto out_retry; } dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index bf04b30..f94567b 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -471,6 +471,15 @@ struct rpc_filelist { umode_t mode; }; +static int rpc_delete_dentry(const struct dentry *dentry) +{ + return 1; +} + +static const struct dentry_operations rpc_dentry_operations = { + .d_delete = rpc_delete_dentry, +}; + static struct inode * rpc_get_inode(struct super_block *sb, umode_t mode) { @@ -510,8 +519,8 @@ static int __rpc_create_common(struct inode *dir, struct dentry *dentry, d_add(dentry, inode); return 0; out_err: - printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %pd\n", - __FILE__, __func__, dentry); + printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", + __FILE__, __func__, dentry->d_name.name); dput(dentry); return -ENOMEM; } @@ -746,8 +755,8 @@ static int rpc_populate(struct dentry *parent, out_bad: __rpc_depopulate(parent, files, start, eof); mutex_unlock(&dir->i_mutex); - printk(KERN_WARNING "%s: %s failed to populate directory %pd\n", - __FILE__, __func__, parent); + printk(KERN_WARNING "%s: %s failed to populate directory %s\n", + __FILE__, __func__, parent->d_name.name); return err; } @@ -843,8 +852,8 @@ out: return dentry; out_err: dentry = ERR_PTR(err); - printk(KERN_WARNING "%s: %s() failed to create pipe %pd/%s (errno = %d)\n", - __FILE__, __func__, parent, name, + printk(KERN_WARNING "%s: %s() failed to create pipe %s/%s (errno = %d)\n", + __FILE__, __func__, parent->d_name.name, name, err); goto out; } @@ -1257,7 +1266,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = RPCAUTH_GSSMAGIC; sb->s_op = &s_ops; - sb->s_d_op = &simple_dentry_operations; + sb->s_d_op = &rpc_dentry_operations; sb->s_time_gran = 1; inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e7fbe36..b974571 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1104,6 +1104,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) rqstp->rq_vers = vers = svc_getnl(argv); /* version number */ rqstp->rq_proc = proc = svc_getnl(argv); /* procedure number */ + progp = serv->sv_program; + for (progp = serv->sv_program; progp; progp = progp->pg_next) if (prog == progp->pg_prog) break; diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index b6e59f0..9c9caaa 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -291,14 +291,12 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) &inet_sk(sk)->inet_rcv_saddr, inet_sk(sk)->inet_num); break; -#if IS_ENABLED(CONFIG_IPV6) case PF_INET6: len = snprintf(buf, remaining, "ipv6 %s %pI6 %d\n", proto_name, - &sk->sk_v6_rcv_saddr, + &inet6_sk(sk)->rcv_saddr, inet_sk(sk)->inet_num); break; -#endif default: len = snprintf(buf, remaining, "*unknown-%d*\n", sk->sk_family); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 04199bc..095363e 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -205,8 +205,10 @@ int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task) goto out_sleep; } xprt->snd_task = task; - if (req != NULL) + if (req != NULL) { + req->rq_bytes_sent = 0; req->rq_ntrans++; + } return 1; @@ -261,6 +263,7 @@ int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) } if (__xprt_get_cong(xprt, task)) { xprt->snd_task = task; + req->rq_bytes_sent = 0; req->rq_ntrans++; return 1; } @@ -297,8 +300,10 @@ static bool __xprt_lock_write_func(struct rpc_task *task, void *data) req = task->tk_rqstp; xprt->snd_task = task; - if (req) + if (req) { + req->rq_bytes_sent = 0; req->rq_ntrans++; + } return true; } @@ -324,6 +329,7 @@ static bool __xprt_lock_write_cong_func(struct rpc_task *task, void *data) } if (__xprt_get_cong(xprt, task)) { xprt->snd_task = task; + req->rq_bytes_sent = 0; req->rq_ntrans++; return true; } @@ -352,11 +358,6 @@ out_unlock: void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) { if (xprt->snd_task == task) { - if (task != NULL) { - struct rpc_rqst *req = task->tk_rqstp; - if (req != NULL) - req->rq_bytes_sent = 0; - } xprt_clear_locked(xprt); __xprt_lock_write_next(xprt); } @@ -374,11 +375,6 @@ EXPORT_SYMBOL_GPL(xprt_release_xprt); void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) { if (xprt->snd_task == task) { - if (task != NULL) { - struct rpc_rqst *req = task->tk_rqstp; - if (req != NULL) - req->rq_bytes_sent = 0; - } xprt_clear_locked(xprt); __xprt_lock_write_next_cong(xprt); } @@ -858,36 +854,24 @@ static inline int xprt_has_timer(struct rpc_xprt *xprt) * @task: RPC task about to send a request * */ -bool xprt_prepare_transmit(struct rpc_task *task) +int xprt_prepare_transmit(struct rpc_task *task) { struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; - bool ret = false; + int err = 0; dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid); spin_lock_bh(&xprt->transport_lock); - if (!req->rq_bytes_sent) { - if (req->rq_reply_bytes_recvd) { - task->tk_status = req->rq_reply_bytes_recvd; - goto out_unlock; - } - if ((task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT) - && xprt_connected(xprt) - && req->rq_connect_cookie == xprt->connect_cookie) { - xprt->ops->set_retrans_timeout(task); - rpc_sleep_on(&xprt->pending, task, xprt_timer); - goto out_unlock; - } - } - if (!xprt->ops->reserve_xprt(xprt, task)) { - task->tk_status = -EAGAIN; + if (req->rq_reply_bytes_recvd && !req->rq_bytes_sent) { + err = req->rq_reply_bytes_recvd; goto out_unlock; } - ret = true; + if (!xprt->ops->reserve_xprt(xprt, task)) + err = -EAGAIN; out_unlock: spin_unlock_bh(&xprt->transport_lock); - return ret; + return err; } void xprt_end_transmit(struct rpc_task *task) @@ -928,6 +912,7 @@ void xprt_transmit(struct rpc_task *task) } else if (!req->rq_bytes_sent) return; + req->rq_connect_cookie = xprt->connect_cookie; req->rq_xtime = ktime_get(); status = xprt->ops->send_request(task); if (status != 0) { @@ -953,14 +938,12 @@ void xprt_transmit(struct rpc_task *task) /* Don't race with disconnect */ if (!xprt_connected(xprt)) task->tk_status = -ENOTCONN; - else { + else if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) { /* * Sleep on the pending queue since * we're expecting a reply. */ - if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) - rpc_sleep_on(&xprt->pending, task, xprt_timer); - req->rq_connect_cookie = xprt->connect_cookie; + rpc_sleep_on(&xprt->pending, task, xprt_timer); } spin_unlock_bh(&xprt->transport_lock); } @@ -1104,9 +1087,11 @@ struct rpc_xprt *xprt_alloc(struct net *net, size_t size, for (i = 0; i < num_prealloc; i++) { req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL); if (!req) - goto out_free; + break; list_add(&req->rq_list, &xprt->free); } + if (i < num_prealloc) + goto out_free; if (max_alloc > num_prealloc) xprt->max_reqs = max_alloc; else @@ -1201,12 +1186,6 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) req->rq_xprt = xprt; req->rq_buffer = NULL; req->rq_xid = xprt_alloc_xid(xprt); - req->rq_connect_cookie = xprt->connect_cookie - 1; - req->rq_bytes_sent = 0; - req->rq_snd_buf.len = 0; - req->rq_snd_buf.buflen = 0; - req->rq_rcv_buf.len = 0; - req->rq_rcv_buf.buflen = 0; req->rq_release_snd_buf = NULL; xprt_reset_majortimeo(req); dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid, diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index dd9d295..ee03d35 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -393,10 +393,8 @@ static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen, return kernel_sendmsg(sock, &msg, NULL, 0, 0); } -static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy) +static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more) { - ssize_t (*do_sendpage)(struct socket *sock, struct page *page, - int offset, size_t size, int flags); struct page **ppage; unsigned int remainder; int err, sent = 0; @@ -405,9 +403,6 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i base += xdr->page_base; ppage = xdr->pages + (base >> PAGE_SHIFT); base &= ~PAGE_MASK; - do_sendpage = sock->ops->sendpage; - if (!zerocopy) - do_sendpage = sock_no_sendpage; for(;;) { unsigned int len = min_t(unsigned int, PAGE_SIZE - base, remainder); int flags = XS_SENDMSG_FLAGS; @@ -415,7 +410,7 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i remainder -= len; if (remainder != 0 || more) flags |= MSG_MORE; - err = do_sendpage(sock, *ppage, base, len, flags); + err = sock->ops->sendpage(sock, *ppage, base, len, flags); if (remainder == 0 || err != len) break; sent += err; @@ -436,10 +431,9 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i * @addrlen: UDP only -- length of destination address * @xdr: buffer containing this request * @base: starting position in the buffer - * @zerocopy: true if it is safe to use sendpage() * */ -static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy) +static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base) { unsigned int remainder = xdr->len - base; int err, sent = 0; @@ -467,7 +461,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, if (base < xdr->page_len) { unsigned int len = xdr->page_len - base; remainder -= len; - err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy); + err = xs_send_pagedata(sock, xdr, base, remainder != 0); if (remainder == 0 || err != len) goto out; sent += err; @@ -570,7 +564,7 @@ static int xs_local_send_request(struct rpc_task *task) req->rq_svec->iov_base, req->rq_svec->iov_len); status = xs_sendpages(transport->sock, NULL, 0, - xdr, req->rq_bytes_sent, true); + xdr, req->rq_bytes_sent); dprintk("RPC: %s(%u) = %d\n", __func__, xdr->len - req->rq_bytes_sent, status); if (likely(status >= 0)) { @@ -626,7 +620,7 @@ static int xs_udp_send_request(struct rpc_task *task) status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, xdr, - req->rq_bytes_sent, true); + req->rq_bytes_sent); dprintk("RPC: xs_udp_send_request(%u) = %d\n", xdr->len - req->rq_bytes_sent, status); @@ -699,7 +693,6 @@ static int xs_tcp_send_request(struct rpc_task *task) struct rpc_xprt *xprt = req->rq_xprt; struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); struct xdr_buf *xdr = &req->rq_snd_buf; - bool zerocopy = true; int status; xs_encode_stream_record_marker(&req->rq_snd_buf); @@ -707,20 +700,13 @@ static int xs_tcp_send_request(struct rpc_task *task) xs_pktdump("packet data:", req->rq_svec->iov_base, req->rq_svec->iov_len); - /* Don't use zero copy if this is a resend. If the RPC call - * completes while the socket holds a reference to the pages, - * then we may end up resending corrupted data. - */ - if (task->tk_flags & RPC_TASK_SENT) - zerocopy = false; /* Continue transmitting the packet/record. We must be careful * to cope with writespace callbacks arriving _after_ we have * called sendmsg(). */ while (1) { status = xs_sendpages(transport->sock, - NULL, 0, xdr, req->rq_bytes_sent, - zerocopy); + NULL, 0, xdr, req->rq_bytes_sent); dprintk("RPC: xs_tcp_send_request(%u) = %d\n", xdr->len - req->rq_bytes_sent, status); @@ -849,8 +835,6 @@ static void xs_close(struct rpc_xprt *xprt) dprintk("RPC: xs_close xprt %p\n", xprt); - cancel_delayed_work_sync(&transport->connect_worker); - xs_reset_transport(transport); xprt->reestablish_timeout = 0; @@ -870,6 +854,14 @@ static void xs_tcp_close(struct rpc_xprt *xprt) xs_tcp_shutdown(xprt); } +static void xs_local_destroy(struct rpc_xprt *xprt) +{ + xs_close(xprt); + xs_free_peer_addresses(xprt); + xprt_free(xprt); + module_put(THIS_MODULE); +} + /** * xs_destroy - prepare to shutdown a transport * @xprt: doomed transport @@ -877,12 +869,13 @@ static void xs_tcp_close(struct rpc_xprt *xprt) */ static void xs_destroy(struct rpc_xprt *xprt) { + struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); + dprintk("RPC: xs_destroy xprt %p\n", xprt); - xs_close(xprt); - xs_free_peer_addresses(xprt); - xprt_free(xprt); - module_put(THIS_MODULE); + cancel_delayed_work_sync(&transport->connect_worker); + + xs_local_destroy(xprt); } static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) @@ -1518,7 +1511,6 @@ static void xs_tcp_state_change(struct sock *sk) transport->tcp_copied = 0; transport->tcp_flags = TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; - xprt->connect_cookie++; xprt_wake_pending_tasks(xprt, -EAGAIN); } @@ -1824,10 +1816,6 @@ static inline void xs_reclassify_socket(int family, struct socket *sock) } #endif -static void xs_dummy_setup_socket(struct work_struct *work) -{ -} - static struct socket *xs_create_sock(struct rpc_xprt *xprt, struct sock_xprt *transport, int family, int type, int protocol) { @@ -2124,19 +2112,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) if (!transport->inet) { struct sock *sk = sock->sk; - unsigned int keepidle = xprt->timeout->to_initval / HZ; - unsigned int keepcnt = xprt->timeout->to_retries + 1; - unsigned int opt_on = 1; - - /* TCP Keepalive options */ - kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, - (char *)&opt_on, sizeof(opt_on)); - kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, - (char *)&keepidle, sizeof(keepidle)); - kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, - (char *)&keepidle, sizeof(keepidle)); - kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT, - (char *)&keepcnt, sizeof(keepcnt)); write_lock_bh(&sk->sk_callback_lock); @@ -2176,6 +2151,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) case 0: case -EINPROGRESS: /* SYN_SENT! */ + xprt->connect_cookie++; if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO; } @@ -2522,7 +2498,7 @@ static struct rpc_xprt_ops xs_local_ops = { .send_request = xs_local_send_request, .set_retrans_timeout = xprt_set_retrans_timeout_def, .close = xs_close, - .destroy = xs_destroy, + .destroy = xs_local_destroy, .print_stats = xs_local_print_stats, }; @@ -2679,9 +2655,6 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args) xprt->ops = &xs_local_ops; xprt->timeout = &xs_local_default_timeout; - INIT_DELAYED_WORK(&transport->connect_worker, - xs_dummy_setup_socket); - switch (sun->sun_family) { case AF_LOCAL: if (sun->sun_path[0] != '/') { @@ -2886,8 +2859,8 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) if (args->bc_xprt->xpt_bc_xprt) { /* * This server connection already has a backchannel - * transport; we can't create a new one, as we wouldn't - * be able to match replies based on xid any more. So, + * export; we can't create a new one, as we wouldn't be + * able to match replies based on xid any more. So, * reuse the already-existing one: */ return args->bc_xprt->xpt_bc_xprt; |