From 64c59a3726f2dfa71680f9f3c34359e10e3ed7ab Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 29 Apr 2016 11:35:45 -0400 Subject: Remove unnecessary allocation Reported-by: Benjamin Coddington Signed-off-by: J. Bruce Fields --- net/sunrpc/auth_gss/svcauth_gss.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 1095be9c80ab..22886097d8ee 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -569,10 +569,9 @@ gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) struct rsc *found; memset(&rsci, 0, sizeof(rsci)); - if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) - return NULL; + rsci.handle.data = handle->data; + rsci.handle.len = handle->len; found = rsc_lookup(cd, &rsci); - rsc_free(&rsci); if (!found) return NULL; if (cache_check(cd, &found->h, NULL)) -- cgit v1.2.3 From 696190eaf168e83fcbf0c9cf087995cdd15807e5 Mon Sep 17 00:00:00 2001 From: Shirley Ma Date: Wed, 4 May 2016 10:52:47 -0400 Subject: svcrdma: Support IPv6 with NFS/RDMA Allow both IPv4 and IPv6 to bind same port at the same time, restricts use of the IPv6 socket to IPv6 communication. Changes from v1: - Check rdma_set_afonly return value (suggested by Leon Romanovsky) Changes from v2: - Acked-by: Leon Romanovsky Signed-off-by: Shirley Ma Acked-by: Leon Romanovsky Reviewed-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_transport.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 90668969d559..d2680b87d162 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -789,7 +789,7 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, int ret; dprintk("svcrdma: Creating RDMA socket\n"); - if (sa->sa_family != AF_INET) { + if ((sa->sa_family != AF_INET) && (sa->sa_family != AF_INET6)) { dprintk("svcrdma: Address family %d is not supported.\n", sa->sa_family); return ERR_PTR(-EAFNOSUPPORT); } @@ -805,6 +805,16 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, goto err0; } + /* Allow both IPv4 and IPv6 sockets to bind a single port + * at the same time. + */ +#if IS_ENABLED(CONFIG_IPV6) + ret = rdma_set_afonly(listen_id, 1); + if (ret) { + dprintk("svcrdma: rdma_set_afonly failed = %d\n", ret); + goto err1; + } +#endif ret = rdma_bind_addr(listen_id, sa); if (ret) { dprintk("svcrdma: rdma_bind_addr failed = %d\n", ret); -- cgit v1.2.3 From 6625d0913771df5f12b9531c8cb8414e55f1c21d Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 4 May 2016 10:52:55 -0400 Subject: svcrdma: Do not add XDR padding to xdr_buf page vector An xdr_buf has a head, a vector of pages, and a tail. Each RPC request is presented to the NFS server contained in an xdr_buf. The RDMA transport would like to supply the NFS server with only the NFS WRITE payload bytes in the page vector. In some common cases, that would allow the NFS server to swap those pages right into the target file's page cache. Have the transport's RDMA Read logic put XDR pad bytes in the tail iovec, and not in the pages that hold the data payload. The NFSv3 WRITE XDR decoder is finicky about the lengths involved, so make sure it is looking in the correct places when computing the total length of the incoming NFS WRITE request. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 3b24a646eb46..234be9de6210 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -488,7 +488,7 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt, if (page_offset & 3) { u32 pad = 4 - (page_offset & 3); - head->arg.page_len += pad; + head->arg.tail[0].iov_len += pad; head->arg.len += pad; head->arg.buflen += pad; page_offset += pad; -- cgit v1.2.3 From 9ec64052060f972101b49f47631f5072f075426c Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 4 May 2016 10:53:05 -0400 Subject: svcrdma: svc_rdma_put_context() is invoked twice in Send error path Get a fresh op_ctxt in send_reply() instead of in svc_rdma_sendto(). This ensures that svc_rdma_put_context() is invoked only once if send_reply() fails. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 4f1b1c4f45f9..54d533300620 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -463,25 +463,21 @@ static int send_reply(struct svcxprt_rdma *rdma, struct svc_rqst *rqstp, struct page *page, struct rpcrdma_msg *rdma_resp, - struct svc_rdma_op_ctxt *ctxt, struct svc_rdma_req_map *vec, int byte_count) { + struct svc_rdma_op_ctxt *ctxt; struct ib_send_wr send_wr; u32 xdr_off; int sge_no; int sge_bytes; int page_no; int pages; - int ret; - - ret = svc_rdma_repost_recv(rdma, GFP_KERNEL); - if (ret) { - svc_rdma_put_context(ctxt, 0); - return -ENOTCONN; - } + int ret = -EIO; /* Prepare the context */ + ctxt = svc_rdma_get_context(rdma); + ctxt->direction = DMA_TO_DEVICE; ctxt->pages[0] = page; ctxt->count = 1; @@ -565,8 +561,7 @@ static int send_reply(struct svcxprt_rdma *rdma, err: svc_rdma_unmap_dma(ctxt); svc_rdma_put_context(ctxt, 1); - pr_err("svcrdma: failed to send reply, rc=%d\n", ret); - return -EIO; + return ret; } void svc_rdma_prep_reply_hdr(struct svc_rqst *rqstp) @@ -585,7 +580,6 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) int ret; int inline_bytes; struct page *res_page; - struct svc_rdma_op_ctxt *ctxt; struct svc_rdma_req_map *vec; dprintk("svcrdma: sending response for rqstp=%p\n", rqstp); @@ -598,8 +592,6 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) rp_ary = svc_rdma_get_reply_array(rdma_argp, wr_ary); /* Build an req vec for the XDR */ - ctxt = svc_rdma_get_context(rdma); - ctxt->direction = DMA_TO_DEVICE; vec = svc_rdma_get_req_map(rdma); ret = svc_rdma_map_xdr(rdma, &rqstp->rq_res, vec, wr_ary != NULL); if (ret) @@ -635,7 +627,12 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) inline_bytes -= ret; } - ret = send_reply(rdma, rqstp, res_page, rdma_resp, ctxt, vec, + /* Post a fresh Receive buffer _before_ sending the reply */ + ret = svc_rdma_post_recv(rdma, GFP_KERNEL); + if (ret) + goto err1; + + ret = send_reply(rdma, rqstp, res_page, rdma_resp, vec, inline_bytes); if (ret < 0) goto err1; @@ -648,7 +645,8 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) put_page(res_page); err0: svc_rdma_put_req_map(rdma, vec); - svc_rdma_put_context(ctxt, 0); + pr_err("svcrdma: Could not send reply, err=%d. Closing transport.\n", + ret); set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags); return -ENOTCONN; } -- cgit v1.2.3 From cac7f15036dc69c8708fa73369a9fae193e82bfb Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 4 May 2016 10:53:14 -0400 Subject: svcrdma: Remove superfluous line from rdma_read_chunks() Clean up: svc_rdma_get_read_chunk() already returns a pointer to the Read list. No need to set "ch" again to the value it already contains. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 234be9de6210..12e78997bf19 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -447,10 +447,8 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt, head->arg.len = rqstp->rq_arg.len; head->arg.buflen = rqstp->rq_arg.buflen; - ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; - position = be32_to_cpu(ch->rc_position); - /* RDMA_NOMSG: RDMA READ data should land just after RDMA RECV data */ + position = be32_to_cpu(ch->rc_position); if (position == 0) { head->arg.pages = &head->pages[0]; page_offset = head->byte_len; -- cgit v1.2.3 From 0319aafc95eaae10fdb867c35ce9bacfca27eaa3 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 4 May 2016 10:53:22 -0400 Subject: svcrdma: Post Receives only for forward channel requests Since backward direction support was added, the rq_depth was increased to accommodate both forward and backward Receives. But only forward Receives need to be posted after a connection has been accepted. Receives for backward replies are posted as needed by svc_rdma_bc_sendto(). This doesn't break anything, but it means some resources are wasted. Fixes: 03fe9931536f ('svcrdma: Define maximum number of ...') Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index d2680b87d162..02a112c7cb6a 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -1083,7 +1083,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_READ_W_INV; /* Post receive buffers */ - for (i = 0; i < newxprt->sc_rq_depth; i++) { + for (i = 0; i < newxprt->sc_max_requests; i++) { ret = svc_rdma_post_recv(newxprt, GFP_KERNEL); if (ret) { dprintk("svcrdma: failure posting receive buffers\n"); -- cgit v1.2.3 From 76ee8fd64ac9af36b03b68912c18b3d3cd5c99de Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 4 May 2016 10:53:30 -0400 Subject: svcrdma: Drain QP before freeing svcrdma_xprt If the server has forced a disconnect, the associated QP has not been moved to the Error state, and thus Receives are still posted. Ensure Receives (and any other outstanding WRs) are drained to release resources that can be freed during teardown of the svcrdma_xprt. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_transport.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 02a112c7cb6a..dd9440137834 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -1180,6 +1180,9 @@ static void __svc_rdma_free(struct work_struct *work) dprintk("svcrdma: %s(%p)\n", __func__, rdma); + if (rdma->sc_qp && !IS_ERR(rdma->sc_qp)) + ib_drain_qp(rdma->sc_qp); + /* We should only be called from kref_put */ if (atomic_read(&xprt->xpt_ref.refcount) != 0) pr_err("svcrdma: sc_xprt still in use? (%d)\n", -- cgit v1.2.3 From 84f225c23d8906c9371d0749e062975c018ef6c4 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 4 May 2016 10:53:39 -0400 Subject: svcrdma: Eliminate code duplication in svc_rdma_recvfrom() Clean up. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 12e78997bf19..1b72f351fbd3 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -508,11 +508,10 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt, return ret; } -static int rdma_read_complete(struct svc_rqst *rqstp, - struct svc_rdma_op_ctxt *head) +static void rdma_read_complete(struct svc_rqst *rqstp, + struct svc_rdma_op_ctxt *head) { int page_no; - int ret; /* Copy RPC pages */ for (page_no = 0; page_no < head->count; page_no++) { @@ -548,23 +547,6 @@ static int rdma_read_complete(struct svc_rqst *rqstp, rqstp->rq_arg.tail[0] = head->arg.tail[0]; rqstp->rq_arg.len = head->arg.len; rqstp->rq_arg.buflen = head->arg.buflen; - - /* Free the context */ - svc_rdma_put_context(head, 0); - - /* XXX: What should this be? */ - rqstp->rq_prot = IPPROTO_MAX; - svc_xprt_copy_addrs(rqstp, rqstp->rq_xprt); - - ret = rqstp->rq_arg.head[0].iov_len - + rqstp->rq_arg.page_len - + rqstp->rq_arg.tail[0].iov_len; - dprintk("svcrdma: deferred read ret=%d, rq_arg.len=%u, " - "rq_arg.head[0].iov_base=%p, rq_arg.head[0].iov_len=%zu\n", - ret, rqstp->rq_arg.len, rqstp->rq_arg.head[0].iov_base, - rqstp->rq_arg.head[0].iov_len); - - return ret; } /* By convention, backchannel calls arrive via rdma_msg type @@ -622,7 +604,8 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) dto_q); list_del_init(&ctxt->dto_q); spin_unlock_bh(&rdma_xprt->sc_rq_dto_lock); - return rdma_read_complete(rqstp, ctxt); + rdma_read_complete(rqstp, ctxt); + goto complete; } else if (!list_empty(&rdma_xprt->sc_rq_dto_q)) { ctxt = list_entry(rdma_xprt->sc_rq_dto_q.next, struct svc_rdma_op_ctxt, @@ -680,6 +663,7 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) return 0; } +complete: ret = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len + rqstp->rq_arg.tail[0].iov_len; -- cgit v1.2.3 From d9e4084f6c9746e51a78a4d7ebf4983023289b32 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 4 May 2016 10:53:47 -0400 Subject: svcrdma: Generalize svc_rdma_xdr_decode_req() Clean up: Pass in just the piece of the svc_rqst that is needed here. While we're in the area, add an informative documenting comment. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_marshal.c | 32 ++++++++++++++++++++++---------- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 2 +- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c index 765bca47c74d..0ba9887f3e22 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c +++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c @@ -145,19 +145,32 @@ static __be32 *decode_reply_array(__be32 *va, __be32 *vaend) return (__be32 *)&ary->wc_array[nchunks]; } -int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp) +/** + * svc_rdma_xdr_decode_req - Parse incoming RPC-over-RDMA header + * @rq_arg: Receive buffer + * + * On entry, xdr->head[0].iov_base points to first byte in the + * RPC-over-RDMA header. + * + * On successful exit, head[0] points to first byte past the + * RPC-over-RDMA header. For RDMA_MSG, this is the RPC message. + * The length of the RPC-over-RDMA header is returned. + */ +int svc_rdma_xdr_decode_req(struct xdr_buf *rq_arg) { + struct rpcrdma_msg *rmsgp; __be32 *va, *vaend; unsigned int len; u32 hdr_len; /* Verify that there's enough bytes for header + something */ - if (rqstp->rq_arg.len <= RPCRDMA_HDRLEN_ERR) { + if (rq_arg->len <= RPCRDMA_HDRLEN_ERR) { dprintk("svcrdma: header too short = %d\n", - rqstp->rq_arg.len); + rq_arg->len); return -EINVAL; } + rmsgp = (struct rpcrdma_msg *)rq_arg->head[0].iov_base; if (rmsgp->rm_vers != rpcrdma_version) { dprintk("%s: bad version %u\n", __func__, be32_to_cpu(rmsgp->rm_vers)); @@ -189,10 +202,10 @@ int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp) be32_to_cpu(rmsgp->rm_body.rm_padded.rm_thresh); va = &rmsgp->rm_body.rm_padded.rm_pempty[4]; - rqstp->rq_arg.head[0].iov_base = va; + rq_arg->head[0].iov_base = va; len = (u32)((unsigned long)va - (unsigned long)rmsgp); - rqstp->rq_arg.head[0].iov_len -= len; - if (len > rqstp->rq_arg.len) + rq_arg->head[0].iov_len -= len; + if (len > rq_arg->len) return -EINVAL; return len; default: @@ -205,7 +218,7 @@ int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp) * chunk list and a reply chunk list. */ va = &rmsgp->rm_body.rm_chunks[0]; - vaend = (__be32 *)((unsigned long)rmsgp + rqstp->rq_arg.len); + vaend = (__be32 *)((unsigned long)rmsgp + rq_arg->len); va = decode_read_list(va, vaend); if (!va) { dprintk("svcrdma: failed to decode read list\n"); @@ -222,10 +235,9 @@ int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp) return -EINVAL; } - rqstp->rq_arg.head[0].iov_base = va; + rq_arg->head[0].iov_base = va; hdr_len = (unsigned long)va - (unsigned long)rmsgp; - rqstp->rq_arg.head[0].iov_len -= hdr_len; - + rq_arg->head[0].iov_len -= hdr_len; return hdr_len; } diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 1b72f351fbd3..c984b0aaecb1 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -636,7 +636,7 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) /* Decode the RDMA header. */ rmsgp = (struct rpcrdma_msg *)rqstp->rq_arg.head[0].iov_base; - ret = svc_rdma_xdr_decode_req(rmsgp, rqstp); + ret = svc_rdma_xdr_decode_req(&rqstp->rq_arg); if (ret < 0) goto out_err; if (ret == 0) -- cgit v1.2.3 From d96b9c9398fcddca7f2386cff44a6788edfe7db1 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 18 May 2016 14:50:14 -0400 Subject: svcrpc: autoload rdma module This should fix failures like: # rpc.nfsd --rdma rpc.nfsd: Unable to request RDMA services: Protocol not supported Reported-by: Steve Dickson Reviewed-by: Chuck Lever Signed-off-by: J. Bruce Fields --- net/sunrpc/svc_xprt.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 7422f28818b2..f5572e31d518 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -244,13 +244,12 @@ void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new) svc_xprt_received(new); } -int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, +int _svc_create_xprt(struct svc_serv *serv, const char *xprt_name, struct net *net, const int family, const unsigned short port, int flags) { struct svc_xprt_class *xcl; - dprintk("svc: creating transport %s[%d]\n", xprt_name, port); spin_lock(&svc_xprt_class_lock); list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) { struct svc_xprt *newxprt; @@ -274,12 +273,28 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, } err: spin_unlock(&svc_xprt_class_lock); - dprintk("svc: transport %s not found\n", xprt_name); - /* This errno is exposed to user space. Provide a reasonable * perror msg for a bad transport. */ return -EPROTONOSUPPORT; } + +int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, + struct net *net, const int family, + const unsigned short port, int flags) +{ + int err; + + dprintk("svc: creating transport %s[%d]\n", xprt_name, port); + err = _svc_create_xprt(serv, xprt_name, net, family, port, flags); + if (err == -EPROTONOSUPPORT) { + request_module("svc%s", xprt_name); + err = _svc_create_xprt(serv, xprt_name, net, family, port, flags); + } + if (err) + dprintk("svc: transport %s not found, err %d\n", + xprt_name, err); + return err; +} EXPORT_SYMBOL_GPL(svc_create_xprt); /* -- cgit v1.2.3 From c0cb8bf3a8e4bd82e640862cdd8891400405cb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Trnka?= Date: Fri, 20 May 2016 16:41:10 +0200 Subject: sunrpc: fix stripping of padded MIC tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The length of the GSS MIC token need not be a multiple of four bytes. It is then padded by XDR to a multiple of 4 B, but unwrap_integ_data() would previously only trim mic.len + 4 B. The remaining up to three bytes would then trigger a check in nfs4svc_decode_compoundargs(), leading to a "garbage args" error and mount failure: nfs4svc_decode_compoundargs: compound not properly padded! nfsd: failed to decode arguments! This would prevent older clients using the pre-RFC 4121 MIC format (37-byte MIC including a 9-byte OID) from mounting exports from v3.9+ servers using krb5i. The trimming was introduced by commit 4c190e2f913f ("sunrpc: trim off trailing checksum before returning decrypted or integrity authenticated buffer"). Fixes: 4c190e2f913f "unrpc: trim off trailing checksum..." Signed-off-by: Tomáš Trnka Cc: stable@vger.kernel.org Acked-by: Jeff Layton Signed-off-by: J. Bruce Fields --- net/sunrpc/auth_gss/svcauth_gss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/sunrpc') diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 22886097d8ee..e085f5ae1548 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -856,8 +856,8 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g goto out; if (svc_getnl(&buf->head[0]) != seq) goto out; - /* trim off the mic at the end before returning */ - xdr_buf_trim(buf, mic.len + 4); + /* trim off the mic and padding at the end before returning */ + xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4); stat = 0; out: kfree(mic.data); -- cgit v1.2.3