Merge tag 'nfs-for-4.2-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights include: Stable patches: - Fix a situation where the client uses the wrong (zero) stateid. - Fix a memory leak in nfs_do_recoalesce Bugfixes: - Plug a memory leak when ->prepare_layoutcommit fails - Fix an Oops in the NFSv4 open code - Fix a backchannel deadlock - Fix a livelock in sunrpc when sendmsg fails due to low memory availability - Don't revalidate the mapping if both size and change attr are up to date - Ensure we don't miss a file extension when doing pNFS - Several fixes to handle NFSv4.1 sequence operation status bits correctly - Several pNFS layout return bugfixes" * tag 'nfs-for-4.2-2' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (28 commits) nfs: Fix an oops caused by using other thread's stack space in ASYNC mode nfs: plug memory leak when ->prepare_layoutcommit fails SUNRPC: Report TCP errors to the caller sunrpc: translate -EAGAIN to -ENOBUFS when socket is writable. NFSv4.2: handle NFS-specific llseek errors NFS: Don't clear desc->pg_moreio in nfs_do_recoalesce() NFS: Fix a memory leak in nfs_do_recoalesce NFS: nfs_mark_for_revalidate should always set NFS_INO_REVAL_PAGECACHE NFS: Remove the "NFS_CAP_CHANGE_ATTR" capability NFS: Set NFS_INO_REVAL_PAGECACHE if the change attribute is uninitialised NFS: Don't revalidate the mapping if both size and change attr are up to date NFSv4/pnfs: Ensure we don't miss a file extension NFSv4: We must set NFS_OPEN_STATE flag in nfs_resync_open_stateid_locked SUNRPC: xprt_complete_bc_request must also decrement the free slot count SUNRPC: Fix a backchannel deadlock pNFS: Don't throw out valid layout segments pNFS: pnfs_roc_drain() fix a race with open pNFS: Fix races between return-on-close and layoutreturn. pNFS: pnfs_roc_drain should return 'true' when sleeping pNFS: Layoutreturn must invalidate all existing layout segments. ...
This commit is contained in:
@@ -240,8 +240,8 @@ static struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt, __be32 xid)
|
||||
req = xprt_alloc_bc_req(xprt, GFP_ATOMIC);
|
||||
if (!req)
|
||||
goto not_found;
|
||||
/* Note: this 'free' request adds it to xprt->bc_pa_list */
|
||||
xprt_free_bc_request(req);
|
||||
list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list);
|
||||
xprt->bc_alloc_count++;
|
||||
}
|
||||
req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
|
||||
rq_bc_pa_list);
|
||||
@@ -336,7 +336,7 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
|
||||
|
||||
spin_lock(&xprt->bc_pa_lock);
|
||||
list_del(&req->rq_bc_pa_list);
|
||||
xprt->bc_alloc_count--;
|
||||
xprt_dec_alloc_count(xprt, 1);
|
||||
spin_unlock(&xprt->bc_pa_lock);
|
||||
|
||||
req->rq_private_buf.len = copied;
|
||||
|
@@ -1902,6 +1902,7 @@ call_transmit_status(struct rpc_task *task)
|
||||
|
||||
switch (task->tk_status) {
|
||||
case -EAGAIN:
|
||||
case -ENOBUFS:
|
||||
break;
|
||||
default:
|
||||
dprint_status(task);
|
||||
@@ -1928,7 +1929,6 @@ call_transmit_status(struct rpc_task *task)
|
||||
case -ECONNABORTED:
|
||||
case -EADDRINUSE:
|
||||
case -ENOTCONN:
|
||||
case -ENOBUFS:
|
||||
case -EPIPE:
|
||||
rpc_task_force_reencode(task);
|
||||
}
|
||||
@@ -2057,12 +2057,13 @@ call_status(struct rpc_task *task)
|
||||
case -ECONNABORTED:
|
||||
rpc_force_rebind(clnt);
|
||||
case -EADDRINUSE:
|
||||
case -ENOBUFS:
|
||||
rpc_delay(task, 3*HZ);
|
||||
case -EPIPE:
|
||||
case -ENOTCONN:
|
||||
task->tk_action = call_bind;
|
||||
break;
|
||||
case -ENOBUFS:
|
||||
rpc_delay(task, HZ>>2);
|
||||
case -EAGAIN:
|
||||
task->tk_action = call_transmit;
|
||||
break;
|
||||
|
@@ -527,6 +527,10 @@ static int xs_local_send_request(struct rpc_task *task)
|
||||
true, &sent);
|
||||
dprintk("RPC: %s(%u) = %d\n",
|
||||
__func__, xdr->len - req->rq_bytes_sent, status);
|
||||
|
||||
if (status == -EAGAIN && sock_writeable(transport->inet))
|
||||
status = -ENOBUFS;
|
||||
|
||||
if (likely(sent > 0) || status == 0) {
|
||||
req->rq_bytes_sent += sent;
|
||||
req->rq_xmit_bytes_sent += sent;
|
||||
@@ -539,6 +543,7 @@ static int xs_local_send_request(struct rpc_task *task)
|
||||
|
||||
switch (status) {
|
||||
case -ENOBUFS:
|
||||
break;
|
||||
case -EAGAIN:
|
||||
status = xs_nospace(task);
|
||||
break;
|
||||
@@ -589,6 +594,9 @@ static int xs_udp_send_request(struct rpc_task *task)
|
||||
if (status == -EPERM)
|
||||
goto process_status;
|
||||
|
||||
if (status == -EAGAIN && sock_writeable(transport->inet))
|
||||
status = -ENOBUFS;
|
||||
|
||||
if (sent > 0 || status == 0) {
|
||||
req->rq_xmit_bytes_sent += sent;
|
||||
if (sent >= req->rq_slen)
|
||||
@@ -669,9 +677,6 @@ static int xs_tcp_send_request(struct rpc_task *task)
|
||||
dprintk("RPC: xs_tcp_send_request(%u) = %d\n",
|
||||
xdr->len - req->rq_bytes_sent, status);
|
||||
|
||||
if (unlikely(sent == 0 && status < 0))
|
||||
break;
|
||||
|
||||
/* If we've sent the entire packet, immediately
|
||||
* reset the count of bytes sent. */
|
||||
req->rq_bytes_sent += sent;
|
||||
@@ -681,18 +686,21 @@ static int xs_tcp_send_request(struct rpc_task *task)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sent != 0)
|
||||
continue;
|
||||
status = -EAGAIN;
|
||||
break;
|
||||
if (status < 0)
|
||||
break;
|
||||
if (sent == 0) {
|
||||
status = -EAGAIN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status == -EAGAIN && sk_stream_is_writeable(transport->inet))
|
||||
status = -ENOBUFS;
|
||||
|
||||
switch (status) {
|
||||
case -ENOTSOCK:
|
||||
status = -ENOTCONN;
|
||||
/* Should we call xs_close() here? */
|
||||
break;
|
||||
case -ENOBUFS:
|
||||
case -EAGAIN:
|
||||
status = xs_nospace(task);
|
||||
break;
|
||||
@@ -703,6 +711,7 @@ static int xs_tcp_send_request(struct rpc_task *task)
|
||||
case -ECONNREFUSED:
|
||||
case -ENOTCONN:
|
||||
case -EADDRINUSE:
|
||||
case -ENOBUFS:
|
||||
case -EPIPE:
|
||||
clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
|
||||
}
|
||||
|
Reference in New Issue
Block a user