dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page);
 
-       /* Only do I/O if gfp is a superset of GFP_KERNEL */
-       if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) {
+       /* Only do I/O if gfp is a superset of GFP_KERNEL, and we're not
+        * doing this memory reclaim for a fs-related allocation.
+        */
+       if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL &&
+           !(current->flags & PF_FSTRANS)) {
                int how = FLUSH_SYNC;
 
                /* Don't let kswapd deadlock waiting for OOM RPC calls */
 
        int rc = 0;
 
        if (!xprt->shutdown) {
+               current->flags |= PF_FSTRANS;
                xprt_clear_connected(xprt);
 
                dprintk("RPC:       %s: %sconnect\n", __func__,
 
 out:
        xprt_wake_pending_tasks(xprt, rc);
-
 out_clear:
        dprintk("RPC:       %s: exit\n", __func__);
        xprt_clear_connecting(xprt);
+       current->flags &= ~PF_FSTRANS;
 }
 
 /*
 
        if (xprt->shutdown)
                goto out;
 
+       current->flags |= PF_FSTRANS;
+
        clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
        status = __sock_create(xprt->xprt_net, AF_LOCAL,
                                        SOCK_STREAM, 0, &sock, 1);
 out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
+       current->flags &= ~PF_FSTRANS;
 }
 
 static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
        if (xprt->shutdown)
                goto out;
 
+       current->flags |= PF_FSTRANS;
+
        /* Start by resetting any existing state */
        xs_reset_transport(transport);
        sock = xs_create_sock(xprt, transport,
 out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
+       current->flags &= ~PF_FSTRANS;
 }
 
 /*
        if (xprt->shutdown)
                goto out;
 
+       current->flags |= PF_FSTRANS;
+
        if (!sock) {
                clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
                sock = xs_create_sock(xprt, transport,
        case -EINPROGRESS:
        case -EALREADY:
                xprt_clear_connecting(xprt);
+               current->flags &= ~PF_FSTRANS;
                return;
        case -EINVAL:
                /* Happens, for instance, if the user specified a link
 out:
        xprt_clear_connecting(xprt);
        xprt_wake_pending_tasks(xprt, status);
+       current->flags &= ~PF_FSTRANS;
 }
 
 /**