NFS client bugfixes for Linux 5.1

Highlights include:
 
 Stable fixes:
 - Fix a deadlock in close() due to incorrect draining of RDMA queues
 
 Bugfixes:
 - Revert "SUNRPC: Micro-optimise when the task is known not to be sleeping"
   as it is causing stack overflows
 - Fix a regression where NFSv4 getacl and fs_locations stopped working
 - Forbid setting AF_INET6 to "struct sockaddr_in"->sin_family.
 - Fix xfstests failures due to incorrect copy_file_range() return values
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJcsfeVAAoJEA4mA3inWBJcPjAQAIPERRVWjg7xRz6CJzt2yoM1
 ApPj965DCnC9bGcGAH2U+TbCWJOi3lJwaZOPTL0ut/Tcv9PpKETRqk+rrjUcFRy1
 1b1HH16GivprOmHgCRyqo5Qj2ZiaGNpY3tJfxl/6eIiSpHKPZLa4zY+q2KfK/YNI
 SOVyNU0Gq08p4AiKr3CG5VVZGdNgRMrnzBYJqeTh1zZ7erWE2nJoE+pmvcLhZR0w
 uxshbTWbJT21KLEI+PXTyGtFkz5jNaKy4Ts07MRBJdQjDv73MUW8CcqFZicSjtqx
 zdKYa1VH9pEOjFOs57xGELSnYRdB00Vgd9/b6MqKyWH8iJzXFbgjEusMWiU45aeF
 NLg9ySSU8LeY93SxV66CHG57NIgHqwZu6P+lO3efRzuHgEGceDsz0WwDF2KNIZlm
 /vOmbk0I+woneFUeNDWAXD9/ETUJ8RCNk1/b1UlbkUL7aD5WSLDp1bKPifk/WA6E
 Mtgwmqz1Vso3cIPglWcAgsfEAYJZSJVDMfRIhm2dy7vVU0nfW12I00G8BShgr8f7
 mxAxd/V+1/Q9ftPENgC9z5LWKYQjfjksnYRHXW1m5c92Yoe9TF0yiNyDmT5hBR6w
 MvUN2j3yeQBqk6JHZxtH/mmdSRD0o5kxvFrEqMj1PpP8X8DpWupQA8SZKnHq0wlj
 8Q7LRum+wmhbiKCmZ+1F
 =vRPB
 -----END PGP SIGNATURE-----

Merge tag 'nfs-for-5.1-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:
 "Highlights include:

  Stable fix:

   - Fix a deadlock in close() due to incorrect draining of RDMA queues

  Bugfixes:

   - Revert "SUNRPC: Micro-optimise when the task is known not to be
     sleeping" as it is causing stack overflows

   - Fix a regression where NFSv4 getacl and fs_locations stopped
     working

   - Forbid setting AF_INET6 to "struct sockaddr_in"->sin_family.

   - Fix xfstests failures due to incorrect copy_file_range() return
     values"

* tag 'nfs-for-5.1-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  Revert "SUNRPC: Micro-optimise when the task is known not to be sleeping"
  NFSv4.1 fix incorrect return value in copy_file_range
  xprtrdma: Fix helper that drains the transport
  NFS: Fix handling of reply page vector
  NFS: Forbid setting AF_INET6 to "struct sockaddr_in"->sin_family.
This commit is contained in:
Linus Torvalds 2019-04-13 14:47:06 -07:00
commit b60bc0665e
7 changed files with 16 additions and 53 deletions

View File

@ -329,9 +329,6 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
};
ssize_t err, err2;
if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY))
return -EOPNOTSUPP;
src_lock = nfs_get_lock_context(nfs_file_open_context(src));
if (IS_ERR(src_lock))
return PTR_ERR(src_lock);

View File

@ -133,8 +133,10 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t count, unsigned int flags)
{
if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY))
return -EOPNOTSUPP;
if (file_inode(file_in) == file_inode(file_out))
return -EINVAL;
return -EOPNOTSUPP;
return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
}

View File

@ -2589,7 +2589,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
ARRAY_SIZE(nfs4_acl_bitmap), &hdr);
rpc_prepare_reply_pages(req, args->acl_pages, 0,
args->acl_len, replen);
args->acl_len, replen + 1);
encode_nops(&hdr);
}
@ -2811,7 +2811,7 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req,
}
rpc_prepare_reply_pages(req, (struct page **)&args->page, 0,
PAGE_SIZE, replen);
PAGE_SIZE, replen + 1);
encode_nops(&hdr);
}

View File

@ -2041,7 +2041,8 @@ static int nfs23_validate_mount_data(void *options,
memcpy(sap, &data->addr, sizeof(data->addr));
args->nfs_server.addrlen = sizeof(data->addr);
args->nfs_server.port = ntohs(data->addr.sin_port);
if (!nfs_verify_server_address(sap))
if (sap->sa_family != AF_INET ||
!nfs_verify_server_address(sap))
goto out_no_address;
if (!(data->flags & NFS_MOUNT_TCP))

View File

@ -304,12 +304,4 @@ rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
}
#endif /* CONFIG_SUNRPC_SWAP */
static inline bool
rpc_task_need_resched(const struct rpc_task *task)
{
if (RPC_IS_QUEUED(task) || task->tk_callback)
return true;
return false;
}
#endif /* _LINUX_SUNRPC_SCHED_H_ */

View File

@ -1540,7 +1540,6 @@ call_start(struct rpc_task *task)
clnt->cl_stats->rpccnt++;
task->tk_action = call_reserve;
rpc_task_set_transport(task, clnt);
call_reserve(task);
}
/*
@ -1554,9 +1553,6 @@ call_reserve(struct rpc_task *task)
task->tk_status = 0;
task->tk_action = call_reserveresult;
xprt_reserve(task);
if (rpc_task_need_resched(task))
return;
call_reserveresult(task);
}
static void call_retry_reserve(struct rpc_task *task);
@ -1579,7 +1575,6 @@ call_reserveresult(struct rpc_task *task)
if (status >= 0) {
if (task->tk_rqstp) {
task->tk_action = call_refresh;
call_refresh(task);
return;
}
@ -1605,7 +1600,6 @@ call_reserveresult(struct rpc_task *task)
/* fall through */
case -EAGAIN: /* woken up; retry */
task->tk_action = call_retry_reserve;
call_retry_reserve(task);
return;
case -EIO: /* probably a shutdown */
break;
@ -1628,9 +1622,6 @@ call_retry_reserve(struct rpc_task *task)
task->tk_status = 0;
task->tk_action = call_reserveresult;
xprt_retry_reserve(task);
if (rpc_task_need_resched(task))
return;
call_reserveresult(task);
}
/*
@ -1645,9 +1636,6 @@ call_refresh(struct rpc_task *task)
task->tk_status = 0;
task->tk_client->cl_stats->rpcauthrefresh++;
rpcauth_refreshcred(task);
if (rpc_task_need_resched(task))
return;
call_refreshresult(task);
}
/*
@ -1666,7 +1654,6 @@ call_refreshresult(struct rpc_task *task)
case 0:
if (rpcauth_uptodatecred(task)) {
task->tk_action = call_allocate;
call_allocate(task);
return;
}
/* Use rate-limiting and a max number of retries if refresh
@ -1685,7 +1672,6 @@ call_refreshresult(struct rpc_task *task)
task->tk_cred_retry--;
dprintk("RPC: %5u %s: retry refresh creds\n",
task->tk_pid, __func__);
call_refresh(task);
return;
}
dprintk("RPC: %5u %s: refresh creds failed with error %d\n",
@ -1711,10 +1697,8 @@ call_allocate(struct rpc_task *task)
task->tk_status = 0;
task->tk_action = call_encode;
if (req->rq_buffer) {
call_encode(task);
if (req->rq_buffer)
return;
}
if (proc->p_proc != 0) {
BUG_ON(proc->p_arglen == 0);
@ -1740,12 +1724,8 @@ call_allocate(struct rpc_task *task)
status = xprt->ops->buf_alloc(task);
xprt_inject_disconnect(xprt);
if (status == 0) {
if (rpc_task_need_resched(task))
return;
call_encode(task);
if (status == 0)
return;
}
if (status != -ENOMEM) {
rpc_exit(task, status);
return;
@ -1828,8 +1808,12 @@ call_encode(struct rpc_task *task)
xprt_request_enqueue_receive(task);
xprt_request_enqueue_transmit(task);
out:
task->tk_action = call_bind;
call_bind(task);
task->tk_action = call_transmit;
/* Check that the connection is OK */
if (!xprt_bound(task->tk_xprt))
task->tk_action = call_bind;
else if (!xprt_connected(task->tk_xprt))
task->tk_action = call_connect;
}
/*
@ -1847,7 +1831,6 @@ rpc_task_handle_transmitted(struct rpc_task *task)
{
xprt_end_transmit(task);
task->tk_action = call_transmit_status;
call_transmit_status(task);
}
/*
@ -1865,7 +1848,6 @@ call_bind(struct rpc_task *task)
if (xprt_bound(xprt)) {
task->tk_action = call_connect;
call_connect(task);
return;
}
@ -1896,7 +1878,6 @@ call_bind_status(struct rpc_task *task)
dprint_status(task);
task->tk_status = 0;
task->tk_action = call_connect;
call_connect(task);
return;
}
@ -1981,7 +1962,6 @@ call_connect(struct rpc_task *task)
if (xprt_connected(xprt)) {
task->tk_action = call_transmit;
call_transmit(task);
return;
}
@ -2051,7 +2031,6 @@ call_connect_status(struct rpc_task *task)
case 0:
clnt->cl_stats->netreconn++;
task->tk_action = call_transmit;
call_transmit(task);
return;
}
rpc_exit(task, status);
@ -2087,9 +2066,6 @@ call_transmit(struct rpc_task *task)
xprt_transmit(task);
}
xprt_end_transmit(task);
if (rpc_task_need_resched(task))
return;
call_transmit_status(task);
}
/*
@ -2107,9 +2083,6 @@ call_transmit_status(struct rpc_task *task)
if (rpc_task_transmitted(task)) {
if (task->tk_status == 0)
xprt_request_wait_receive(task);
if (rpc_task_need_resched(task))
return;
call_status(task);
return;
}
@ -2170,7 +2143,6 @@ call_bc_encode(struct rpc_task *task)
{
xprt_request_enqueue_transmit(task);
task->tk_action = call_bc_transmit;
call_bc_transmit(task);
}
/*
@ -2261,7 +2233,6 @@ call_status(struct rpc_task *task)
status = task->tk_status;
if (status >= 0) {
task->tk_action = call_decode;
call_decode(task);
return;
}

View File

@ -90,7 +90,7 @@ static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt)
/* Flush Receives, then wait for deferred Reply work
* to complete.
*/
ib_drain_qp(ia->ri_id->qp);
ib_drain_rq(ia->ri_id->qp);
drain_workqueue(buf->rb_completion_wq);
/* Deferred Reply processing might have scheduled