Commit b60bc066 authored by Linus Torvalds's avatar Linus Torvalds

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.
parents 87af0c38 af6b61d7
...@@ -329,9 +329,6 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src, ...@@ -329,9 +329,6 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
}; };
ssize_t err, err2; 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)); src_lock = nfs_get_lock_context(nfs_file_open_context(src));
if (IS_ERR(src_lock)) if (IS_ERR(src_lock))
return PTR_ERR(src_lock); return PTR_ERR(src_lock);
......
...@@ -133,8 +133,10 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, ...@@ -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, struct file *file_out, loff_t pos_out,
size_t count, unsigned int flags) 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)) 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); return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
} }
......
...@@ -2589,7 +2589,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr, ...@@ -2589,7 +2589,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
ARRAY_SIZE(nfs4_acl_bitmap), &hdr); ARRAY_SIZE(nfs4_acl_bitmap), &hdr);
rpc_prepare_reply_pages(req, args->acl_pages, 0, rpc_prepare_reply_pages(req, args->acl_pages, 0,
args->acl_len, replen); args->acl_len, replen + 1);
encode_nops(&hdr); encode_nops(&hdr);
} }
...@@ -2811,7 +2811,7 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, ...@@ -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, rpc_prepare_reply_pages(req, (struct page **)&args->page, 0,
PAGE_SIZE, replen); PAGE_SIZE, replen + 1);
encode_nops(&hdr); encode_nops(&hdr);
} }
......
...@@ -2041,7 +2041,8 @@ static int nfs23_validate_mount_data(void *options, ...@@ -2041,7 +2041,8 @@ static int nfs23_validate_mount_data(void *options,
memcpy(sap, &data->addr, sizeof(data->addr)); memcpy(sap, &data->addr, sizeof(data->addr));
args->nfs_server.addrlen = sizeof(data->addr); args->nfs_server.addrlen = sizeof(data->addr);
args->nfs_server.port = ntohs(data->addr.sin_port); 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; goto out_no_address;
if (!(data->flags & NFS_MOUNT_TCP)) if (!(data->flags & NFS_MOUNT_TCP))
......
...@@ -304,12 +304,4 @@ rpc_clnt_swap_deactivate(struct rpc_clnt *clnt) ...@@ -304,12 +304,4 @@ rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
} }
#endif /* CONFIG_SUNRPC_SWAP */ #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_ */ #endif /* _LINUX_SUNRPC_SCHED_H_ */
...@@ -1540,7 +1540,6 @@ call_start(struct rpc_task *task) ...@@ -1540,7 +1540,6 @@ call_start(struct rpc_task *task)
clnt->cl_stats->rpccnt++; clnt->cl_stats->rpccnt++;
task->tk_action = call_reserve; task->tk_action = call_reserve;
rpc_task_set_transport(task, clnt); rpc_task_set_transport(task, clnt);
call_reserve(task);
} }
/* /*
...@@ -1554,9 +1553,6 @@ call_reserve(struct rpc_task *task) ...@@ -1554,9 +1553,6 @@ call_reserve(struct rpc_task *task)
task->tk_status = 0; task->tk_status = 0;
task->tk_action = call_reserveresult; task->tk_action = call_reserveresult;
xprt_reserve(task); xprt_reserve(task);
if (rpc_task_need_resched(task))
return;
call_reserveresult(task);
} }
static void call_retry_reserve(struct rpc_task *task); static void call_retry_reserve(struct rpc_task *task);
...@@ -1579,7 +1575,6 @@ call_reserveresult(struct rpc_task *task) ...@@ -1579,7 +1575,6 @@ call_reserveresult(struct rpc_task *task)
if (status >= 0) { if (status >= 0) {
if (task->tk_rqstp) { if (task->tk_rqstp) {
task->tk_action = call_refresh; task->tk_action = call_refresh;
call_refresh(task);
return; return;
} }
...@@ -1605,7 +1600,6 @@ call_reserveresult(struct rpc_task *task) ...@@ -1605,7 +1600,6 @@ call_reserveresult(struct rpc_task *task)
/* fall through */ /* fall through */
case -EAGAIN: /* woken up; retry */ case -EAGAIN: /* woken up; retry */
task->tk_action = call_retry_reserve; task->tk_action = call_retry_reserve;
call_retry_reserve(task);
return; return;
case -EIO: /* probably a shutdown */ case -EIO: /* probably a shutdown */
break; break;
...@@ -1628,9 +1622,6 @@ call_retry_reserve(struct rpc_task *task) ...@@ -1628,9 +1622,6 @@ call_retry_reserve(struct rpc_task *task)
task->tk_status = 0; task->tk_status = 0;
task->tk_action = call_reserveresult; task->tk_action = call_reserveresult;
xprt_retry_reserve(task); xprt_retry_reserve(task);
if (rpc_task_need_resched(task))
return;
call_reserveresult(task);
} }
/* /*
...@@ -1645,9 +1636,6 @@ call_refresh(struct rpc_task *task) ...@@ -1645,9 +1636,6 @@ call_refresh(struct rpc_task *task)
task->tk_status = 0; task->tk_status = 0;
task->tk_client->cl_stats->rpcauthrefresh++; task->tk_client->cl_stats->rpcauthrefresh++;
rpcauth_refreshcred(task); rpcauth_refreshcred(task);
if (rpc_task_need_resched(task))
return;
call_refreshresult(task);
} }
/* /*
...@@ -1666,7 +1654,6 @@ call_refreshresult(struct rpc_task *task) ...@@ -1666,7 +1654,6 @@ call_refreshresult(struct rpc_task *task)
case 0: case 0:
if (rpcauth_uptodatecred(task)) { if (rpcauth_uptodatecred(task)) {
task->tk_action = call_allocate; task->tk_action = call_allocate;
call_allocate(task);
return; return;
} }
/* Use rate-limiting and a max number of retries if refresh /* Use rate-limiting and a max number of retries if refresh
...@@ -1685,7 +1672,6 @@ call_refreshresult(struct rpc_task *task) ...@@ -1685,7 +1672,6 @@ call_refreshresult(struct rpc_task *task)
task->tk_cred_retry--; task->tk_cred_retry--;
dprintk("RPC: %5u %s: retry refresh creds\n", dprintk("RPC: %5u %s: retry refresh creds\n",
task->tk_pid, __func__); task->tk_pid, __func__);
call_refresh(task);
return; return;
} }
dprintk("RPC: %5u %s: refresh creds failed with error %d\n", dprintk("RPC: %5u %s: refresh creds failed with error %d\n",
...@@ -1711,10 +1697,8 @@ call_allocate(struct rpc_task *task) ...@@ -1711,10 +1697,8 @@ call_allocate(struct rpc_task *task)
task->tk_status = 0; task->tk_status = 0;
task->tk_action = call_encode; task->tk_action = call_encode;
if (req->rq_buffer) { if (req->rq_buffer)
call_encode(task);
return; return;
}
if (proc->p_proc != 0) { if (proc->p_proc != 0) {
BUG_ON(proc->p_arglen == 0); BUG_ON(proc->p_arglen == 0);
...@@ -1740,12 +1724,8 @@ call_allocate(struct rpc_task *task) ...@@ -1740,12 +1724,8 @@ call_allocate(struct rpc_task *task)
status = xprt->ops->buf_alloc(task); status = xprt->ops->buf_alloc(task);
xprt_inject_disconnect(xprt); xprt_inject_disconnect(xprt);
if (status == 0) { if (status == 0)
if (rpc_task_need_resched(task))
return;
call_encode(task);
return; return;
}
if (status != -ENOMEM) { if (status != -ENOMEM) {
rpc_exit(task, status); rpc_exit(task, status);
return; return;
...@@ -1828,8 +1808,12 @@ call_encode(struct rpc_task *task) ...@@ -1828,8 +1808,12 @@ call_encode(struct rpc_task *task)
xprt_request_enqueue_receive(task); xprt_request_enqueue_receive(task);
xprt_request_enqueue_transmit(task); xprt_request_enqueue_transmit(task);
out: out:
task->tk_action = call_bind; task->tk_action = call_transmit;
call_bind(task); /* 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) ...@@ -1847,7 +1831,6 @@ rpc_task_handle_transmitted(struct rpc_task *task)
{ {
xprt_end_transmit(task); xprt_end_transmit(task);
task->tk_action = call_transmit_status; task->tk_action = call_transmit_status;
call_transmit_status(task);
} }
/* /*
...@@ -1865,7 +1848,6 @@ call_bind(struct rpc_task *task) ...@@ -1865,7 +1848,6 @@ call_bind(struct rpc_task *task)
if (xprt_bound(xprt)) { if (xprt_bound(xprt)) {
task->tk_action = call_connect; task->tk_action = call_connect;
call_connect(task);
return; return;
} }
...@@ -1896,7 +1878,6 @@ call_bind_status(struct rpc_task *task) ...@@ -1896,7 +1878,6 @@ call_bind_status(struct rpc_task *task)
dprint_status(task); dprint_status(task);
task->tk_status = 0; task->tk_status = 0;
task->tk_action = call_connect; task->tk_action = call_connect;
call_connect(task);
return; return;
} }
...@@ -1981,7 +1962,6 @@ call_connect(struct rpc_task *task) ...@@ -1981,7 +1962,6 @@ call_connect(struct rpc_task *task)
if (xprt_connected(xprt)) { if (xprt_connected(xprt)) {
task->tk_action = call_transmit; task->tk_action = call_transmit;
call_transmit(task);
return; return;
} }
...@@ -2051,7 +2031,6 @@ call_connect_status(struct rpc_task *task) ...@@ -2051,7 +2031,6 @@ call_connect_status(struct rpc_task *task)
case 0: case 0:
clnt->cl_stats->netreconn++; clnt->cl_stats->netreconn++;
task->tk_action = call_transmit; task->tk_action = call_transmit;
call_transmit(task);
return; return;
} }
rpc_exit(task, status); rpc_exit(task, status);
...@@ -2087,9 +2066,6 @@ call_transmit(struct rpc_task *task) ...@@ -2087,9 +2066,6 @@ call_transmit(struct rpc_task *task)
xprt_transmit(task); xprt_transmit(task);
} }
xprt_end_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) ...@@ -2107,9 +2083,6 @@ call_transmit_status(struct rpc_task *task)
if (rpc_task_transmitted(task)) { if (rpc_task_transmitted(task)) {
if (task->tk_status == 0) if (task->tk_status == 0)
xprt_request_wait_receive(task); xprt_request_wait_receive(task);
if (rpc_task_need_resched(task))
return;
call_status(task);
return; return;
} }
...@@ -2170,7 +2143,6 @@ call_bc_encode(struct rpc_task *task) ...@@ -2170,7 +2143,6 @@ call_bc_encode(struct rpc_task *task)
{ {
xprt_request_enqueue_transmit(task); xprt_request_enqueue_transmit(task);
task->tk_action = call_bc_transmit; task->tk_action = call_bc_transmit;
call_bc_transmit(task);
} }
/* /*
...@@ -2261,7 +2233,6 @@ call_status(struct rpc_task *task) ...@@ -2261,7 +2233,6 @@ call_status(struct rpc_task *task)
status = task->tk_status; status = task->tk_status;
if (status >= 0) { if (status >= 0) {
task->tk_action = call_decode; task->tk_action = call_decode;
call_decode(task);
return; return;
} }
......
...@@ -90,7 +90,7 @@ static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt) ...@@ -90,7 +90,7 @@ static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt)
/* Flush Receives, then wait for deferred Reply work /* Flush Receives, then wait for deferred Reply work
* to complete. * to complete.
*/ */
ib_drain_qp(ia->ri_id->qp); ib_drain_rq(ia->ri_id->qp);
drain_workqueue(buf->rb_completion_wq); drain_workqueue(buf->rb_completion_wq);
/* Deferred Reply processing might have scheduled /* Deferred Reply processing might have scheduled
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment