Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfs-for-4.15-3' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client fixes from Anna Schumaker:
"This has two stable bugfixes, one to fix a BUG_ON() when
nfs_commit_inode() is called with no outstanding commit requests and
another to fix a race in the SUNRPC receive codepath.

Additionally, there are also fixes for an NFS client deadlock and an
xprtrdma performance regression.

Summary:

Stable bugfixes:
- NFS: Avoid a BUG_ON() in nfs_commit_inode() by not waiting for a
commit in the case that there were no commit requests.
- SUNRPC: Fix a race in the receive code path

Other fixes:
- NFS: Fix a deadlock in nfs client initialization
- xprtrdma: Fix a performance regression for small IOs"

* tag 'nfs-for-4.15-3' of git://git.linux-nfs.org/projects/anna/linux-nfs:
SUNRPC: Fix a race in the receive code path
nfs: don't wait on commit in nfs_commit_inode() if there were no commit requests
xprtrdma: Spread reply processing over more CPUs
nfs: fix a deadlock in nfs client initialization

+54 -23
+11
fs/nfs/client.c
··· 291 291 const struct sockaddr *sap = data->addr; 292 292 struct nfs_net *nn = net_generic(data->net, nfs_net_id); 293 293 294 + again: 294 295 list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { 295 296 const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; 296 297 /* Don't match clients that failed to initialise properly */ 297 298 if (clp->cl_cons_state < 0) 298 299 continue; 300 + 301 + /* If a client is still initializing then we need to wait */ 302 + if (clp->cl_cons_state > NFS_CS_READY) { 303 + refcount_inc(&clp->cl_count); 304 + spin_unlock(&nn->nfs_client_lock); 305 + nfs_wait_client_init_complete(clp); 306 + nfs_put_client(clp); 307 + spin_lock(&nn->nfs_client_lock); 308 + goto again; 309 + } 299 310 300 311 /* Different NFS versions cannot share the same nfs_client */ 301 312 if (clp->rpc_ops != data->nfs_mod->rpc_ops)
+13 -4
fs/nfs/nfs4client.c
··· 404 404 if (error < 0) 405 405 goto error; 406 406 407 - if (!nfs4_has_session(clp)) 408 - nfs_mark_client_ready(clp, NFS_CS_READY); 409 - 410 407 error = nfs4_discover_server_trunking(clp, &old); 411 408 if (error < 0) 412 409 goto error; 413 410 414 - if (clp != old) 411 + if (clp != old) { 415 412 clp->cl_preserve_clid = true; 413 + /* 414 + * Mark the client as having failed initialization so other 415 + * processes walking the nfs_client_list in nfs_match_client() 416 + * won't try to use it. 417 + */ 418 + nfs_mark_client_ready(clp, -EPERM); 419 + } 416 420 nfs_put_client(clp); 417 421 clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags); 418 422 return old; ··· 543 539 spin_lock(&nn->nfs_client_lock); 544 540 list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { 545 541 542 + if (pos == new) 543 + goto found; 544 + 546 545 status = nfs4_match_client(pos, new, &prev, nn); 547 546 if (status < 0) 548 547 goto out_unlock; ··· 566 559 * way that a SETCLIENTID_CONFIRM to pos can succeed is 567 560 * if new and pos point to the same server: 568 561 */ 562 + found: 569 563 refcount_inc(&pos->cl_count); 570 564 spin_unlock(&nn->nfs_client_lock); 571 565 ··· 580 572 case 0: 581 573 nfs4_swap_callback_idents(pos, new); 582 574 pos->cl_confirm = new->cl_confirm; 575 + nfs_mark_client_ready(pos, NFS_CS_READY); 583 576 584 577 prev = NULL; 585 578 *result = pos;
+2
fs/nfs/write.c
··· 1890 1890 if (res) 1891 1891 error = nfs_generic_commit_list(inode, &head, how, &cinfo); 1892 1892 nfs_commit_end(cinfo.mds); 1893 + if (res == 0) 1894 + return res; 1893 1895 if (error < 0) 1894 1896 goto out_error; 1895 1897 if (!may_wait)
+23 -13
net/sunrpc/xprt.c
··· 1001 1001 { 1002 1002 struct rpc_rqst *req = task->tk_rqstp; 1003 1003 struct rpc_xprt *xprt = req->rq_xprt; 1004 + unsigned int connect_cookie; 1004 1005 int status, numreqs; 1005 1006 1006 1007 dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); ··· 1025 1024 } else if (!req->rq_bytes_sent) 1026 1025 return; 1027 1026 1027 + connect_cookie = xprt->connect_cookie; 1028 1028 req->rq_xtime = ktime_get(); 1029 1029 status = xprt->ops->send_request(task); 1030 1030 trace_xprt_transmit(xprt, req->rq_xid, status); ··· 1049 1047 xprt->stat.bklog_u += xprt->backlog.qlen; 1050 1048 xprt->stat.sending_u += xprt->sending.qlen; 1051 1049 xprt->stat.pending_u += xprt->pending.qlen; 1052 - 1053 - /* Don't race with disconnect */ 1054 - if (!xprt_connected(xprt)) 1055 - task->tk_status = -ENOTCONN; 1056 - else { 1057 - /* 1058 - * Sleep on the pending queue since 1059 - * we're expecting a reply. 1060 - */ 1061 - if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) 1062 - rpc_sleep_on(&xprt->pending, task, xprt_timer); 1063 - req->rq_connect_cookie = xprt->connect_cookie; 1064 - } 1065 1050 spin_unlock_bh(&xprt->transport_lock); 1051 + 1052 + req->rq_connect_cookie = connect_cookie; 1053 + if (rpc_reply_expected(task) && !READ_ONCE(req->rq_reply_bytes_recvd)) { 1054 + /* 1055 + * Sleep on the pending queue if we're expecting a reply. 1056 + * The spinlock ensures atomicity between the test of 1057 + * req->rq_reply_bytes_recvd, and the call to rpc_sleep_on(). 1058 + */ 1059 + spin_lock(&xprt->recv_lock); 1060 + if (!req->rq_reply_bytes_recvd) { 1061 + rpc_sleep_on(&xprt->pending, task, xprt_timer); 1062 + /* 1063 + * Send an extra queue wakeup call if the 1064 + * connection was dropped in case the call to 1065 + * rpc_sleep_on() raced. 1066 + */ 1067 + if (!xprt_connected(xprt)) 1068 + xprt_wake_pending_tasks(xprt, -ENOTCONN); 1069 + } 1070 + spin_unlock(&xprt->recv_lock); 1071 + } 1066 1072 } 1067 1073 1068 1074 static void xprt_add_backlog(struct rpc_xprt *xprt, struct rpc_task *task)
+1 -5
net/sunrpc/xprtrdma/rpc_rdma.c
··· 1408 1408 dprintk("RPC: %s: reply %p completes request %p (xid 0x%08x)\n", 1409 1409 __func__, rep, req, be32_to_cpu(rep->rr_xid)); 1410 1410 1411 - if (list_empty(&req->rl_registered) && 1412 - !test_bit(RPCRDMA_REQ_F_TX_RESOURCES, &req->rl_flags)) 1413 - rpcrdma_complete_rqst(rep); 1414 - else 1415 - queue_work(rpcrdma_receive_wq, &rep->rr_work); 1411 + queue_work_on(req->rl_cpu, rpcrdma_receive_wq, &rep->rr_work); 1416 1412 return; 1417 1413 1418 1414 out_badstatus:
+2
net/sunrpc/xprtrdma/transport.c
··· 52 52 #include <linux/slab.h> 53 53 #include <linux/seq_file.h> 54 54 #include <linux/sunrpc/addr.h> 55 + #include <linux/smp.h> 55 56 56 57 #include "xprt_rdma.h" 57 58 ··· 657 656 task->tk_pid, __func__, rqst->rq_callsize, 658 657 rqst->rq_rcvsize, req); 659 658 659 + req->rl_cpu = smp_processor_id(); 660 660 req->rl_connect_cookie = 0; /* our reserved value */ 661 661 rpcrdma_set_xprtdata(rqst, req); 662 662 rqst->rq_buffer = req->rl_sendbuf->rg_base;
+1 -1
net/sunrpc/xprtrdma/verbs.c
··· 83 83 struct workqueue_struct *recv_wq; 84 84 85 85 recv_wq = alloc_workqueue("xprtrdma_receive", 86 - WQ_MEM_RECLAIM | WQ_UNBOUND | WQ_HIGHPRI, 86 + WQ_MEM_RECLAIM | WQ_HIGHPRI, 87 87 0); 88 88 if (!recv_wq) 89 89 return -ENOMEM;
+1
net/sunrpc/xprtrdma/xprt_rdma.h
··· 342 342 struct rpcrdma_buffer; 343 343 struct rpcrdma_req { 344 344 struct list_head rl_list; 345 + int rl_cpu; 345 346 unsigned int rl_connect_cookie; 346 347 struct rpcrdma_buffer *rl_buffer; 347 348 struct rpcrdma_rep *rl_reply;