Commit 1aff5256 authored by NeilBrown's avatar NeilBrown Committed by Trond Myklebust

NFS/SUNRPC: Remove other deadlock-avoidance mechanisms in nfs_release_page()

Now that nfs_release_page() doesn't block indefinitely, other deadlock
avoidance mechanisms aren't needed.
 - it doesn't hurt for kswapd to block occasionally.  If it doesn't
   want to block it would clear __GFP_WAIT.  The current_is_kswapd()
   was only added to avoid deadlocks and we have a new approach for
   that.
 - memory allocation in the SUNRPC layer can very rarely try to
   ->releasepage() a page it is trying to handle.  The deadlock
   is removed as nfs_release_page() doesn't block indefinitely.

So we don't need to set PF_FSTRANS for sunrpc network operations any
more.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Acked-by: default avatarJeff Layton <jlayton@primarydata.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent 353db796
...@@ -476,20 +476,18 @@ static int nfs_release_page(struct page *page, gfp_t gfp) ...@@ -476,20 +476,18 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
/* Always try to initiate a 'commit' if relevant, but only /* Always try to initiate a 'commit' if relevant, but only
* wait for it if __GFP_WAIT is set and the calling process is * wait for it if __GFP_WAIT is set. Even then, only wait 1
* allowed to block. Even then, only wait 1 second and only * second and only if the 'bdi' is not congested.
* if the 'bdi' is not congested.
* Waiting indefinitely can cause deadlocks when the NFS * Waiting indefinitely can cause deadlocks when the NFS
* server is on this machine, and there is no particular need * server is on this machine, when a new TCP connection is
* to wait extensively here. A short wait has the benefit * needed and in other rare cases. There is no particular
* that someone else can worry about the freezer. * need to wait extensively here. A short wait has the
* benefit that someone else can worry about the freezer.
*/ */
if (mapping) { if (mapping) {
struct nfs_server *nfss = NFS_SERVER(mapping->host); struct nfs_server *nfss = NFS_SERVER(mapping->host);
nfs_commit_inode(mapping->host, 0); nfs_commit_inode(mapping->host, 0);
if ((gfp & __GFP_WAIT) && if ((gfp & __GFP_WAIT) &&
!current_is_kswapd() &&
!(current->flags & PF_FSTRANS) &&
!bdi_write_congested(&nfss->backing_dev_info)) { !bdi_write_congested(&nfss->backing_dev_info)) {
wait_on_page_bit_killable_timeout(page, PG_private, wait_on_page_bit_killable_timeout(page, PG_private,
HZ); HZ);
......
...@@ -821,9 +821,7 @@ void rpc_execute(struct rpc_task *task) ...@@ -821,9 +821,7 @@ void rpc_execute(struct rpc_task *task)
static void rpc_async_schedule(struct work_struct *work) static void rpc_async_schedule(struct work_struct *work)
{ {
current->flags |= PF_FSTRANS;
__rpc_execute(container_of(work, struct rpc_task, u.tk_work)); __rpc_execute(container_of(work, struct rpc_task, u.tk_work));
current->flags &= ~PF_FSTRANS;
} }
/** /**
......
...@@ -205,7 +205,6 @@ xprt_rdma_connect_worker(struct work_struct *work) ...@@ -205,7 +205,6 @@ xprt_rdma_connect_worker(struct work_struct *work)
struct rpc_xprt *xprt = &r_xprt->xprt; struct rpc_xprt *xprt = &r_xprt->xprt;
int rc = 0; int rc = 0;
current->flags |= PF_FSTRANS;
xprt_clear_connected(xprt); xprt_clear_connected(xprt);
dprintk("RPC: %s: %sconnect\n", __func__, dprintk("RPC: %s: %sconnect\n", __func__,
...@@ -216,7 +215,6 @@ xprt_rdma_connect_worker(struct work_struct *work) ...@@ -216,7 +215,6 @@ xprt_rdma_connect_worker(struct work_struct *work)
dprintk("RPC: %s: exit\n", __func__); dprintk("RPC: %s: exit\n", __func__);
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
current->flags &= ~PF_FSTRANS;
} }
/* /*
......
...@@ -1954,8 +1954,6 @@ static int xs_local_setup_socket(struct sock_xprt *transport) ...@@ -1954,8 +1954,6 @@ static int xs_local_setup_socket(struct sock_xprt *transport)
struct socket *sock; struct socket *sock;
int status = -EIO; int status = -EIO;
current->flags |= PF_FSTRANS;
clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
status = __sock_create(xprt->xprt_net, AF_LOCAL, status = __sock_create(xprt->xprt_net, AF_LOCAL,
SOCK_STREAM, 0, &sock, 1); SOCK_STREAM, 0, &sock, 1);
...@@ -1995,7 +1993,6 @@ static int xs_local_setup_socket(struct sock_xprt *transport) ...@@ -1995,7 +1993,6 @@ static int xs_local_setup_socket(struct sock_xprt *transport)
out: out:
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
xprt_wake_pending_tasks(xprt, status); xprt_wake_pending_tasks(xprt, status);
current->flags &= ~PF_FSTRANS;
return status; return status;
} }
...@@ -2098,8 +2095,6 @@ static void xs_udp_setup_socket(struct work_struct *work) ...@@ -2098,8 +2095,6 @@ static void xs_udp_setup_socket(struct work_struct *work)
struct socket *sock = transport->sock; struct socket *sock = transport->sock;
int status = -EIO; int status = -EIO;
current->flags |= PF_FSTRANS;
/* Start by resetting any existing state */ /* Start by resetting any existing state */
xs_reset_transport(transport); xs_reset_transport(transport);
sock = xs_create_sock(xprt, transport, sock = xs_create_sock(xprt, transport,
...@@ -2119,7 +2114,6 @@ static void xs_udp_setup_socket(struct work_struct *work) ...@@ -2119,7 +2114,6 @@ static void xs_udp_setup_socket(struct work_struct *work)
out: out:
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
xprt_wake_pending_tasks(xprt, status); xprt_wake_pending_tasks(xprt, status);
current->flags &= ~PF_FSTRANS;
} }
/* /*
...@@ -2256,8 +2250,6 @@ static void xs_tcp_setup_socket(struct work_struct *work) ...@@ -2256,8 +2250,6 @@ static void xs_tcp_setup_socket(struct work_struct *work)
struct rpc_xprt *xprt = &transport->xprt; struct rpc_xprt *xprt = &transport->xprt;
int status = -EIO; int status = -EIO;
current->flags |= PF_FSTRANS;
if (!sock) { if (!sock) {
clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
sock = xs_create_sock(xprt, transport, sock = xs_create_sock(xprt, transport,
...@@ -2305,7 +2297,6 @@ static void xs_tcp_setup_socket(struct work_struct *work) ...@@ -2305,7 +2297,6 @@ static void xs_tcp_setup_socket(struct work_struct *work)
case -EINPROGRESS: case -EINPROGRESS:
case -EALREADY: case -EALREADY:
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
current->flags &= ~PF_FSTRANS;
return; return;
case -EINVAL: case -EINVAL:
/* Happens, for instance, if the user specified a link /* Happens, for instance, if the user specified a link
...@@ -2323,7 +2314,6 @@ static void xs_tcp_setup_socket(struct work_struct *work) ...@@ -2323,7 +2314,6 @@ static void xs_tcp_setup_socket(struct work_struct *work)
out: out:
xprt_clear_connecting(xprt); xprt_clear_connecting(xprt);
xprt_wake_pending_tasks(xprt, status); xprt_wake_pending_tasks(xprt, status);
current->flags &= ~PF_FSTRANS;
} }
/** /**
......
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