Signed-off-by: Liam R. Howlett <[EMAIL PROTECTED]>

This patch builds on willy's TASK_INTERRUPTABLE and my own
TASK_KILLABLE patches that are currently in the mm branch.
( see http://lkml.org/lkml/2007/10/18/423 and
http://lkml.org/lkml/2007/11/28/127 )

This patch removes the rpc sigmask code and changes the
out_of_line_wait_on_bit and wait_on_bit calls in the sched.c file to
use TASK_KILLABLE.  The result of this patch is the ability to kill
commands issued to a dead NFS mount by the normal ctrl+c method.  I am
looking for help getting this to work with commands that use the stat
(and friends) system calls.  These system calls seem to use spinlocks
and are not killable-friendly due to the atomic operations involved.
Does anyone have any thoughts on the patch so far or the remaining
issues I am facing?

Please CC me on any responses.

Thanks,
Liam R. Howlett

---
 fs/nfs/direct.c          |    8 --------
 fs/nfs/inode.c           |    4 ----
 fs/nfs/nfs3proc.c        |    3 ---
 fs/nfs/nfs4proc.c        |    9 ---------
 fs/nfs/pagelist.c        |    4 ----
 fs/nfs/read.c            |    5 -----
 fs/nfs/write.c           |    5 -----
 include/linux/nfs_fs.h   |    2 --
 net/sunrpc/clnt.c        |   41 -----------------------------------------
 net/sunrpc/sched.c       |    4 ++--
 net/sunrpc/sunrpc_syms.c |    2 --
 11 files changed, 2 insertions(+), 85 deletions(-)

diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index afcab00..30eefa1 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -358,9 +358,7 @@ static ssize_t nfs_direct_read_schedule(struct 
nfs_direct_req *dreq, unsigned lo
 static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, 
size_t count, loff_t pos)
 {
        ssize_t result = 0;
-       sigset_t oldset;
        struct inode *inode = iocb->ki_filp->f_mapping->host;
-       struct rpc_clnt *clnt = NFS_CLIENT(inode);
        struct nfs_direct_req *dreq;
 
        dreq = nfs_direct_req_alloc();
@@ -373,11 +371,9 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, 
unsigned long user_addr, size
                dreq->iocb = iocb;
 
        nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count);
-       rpc_clnt_sigmask(clnt, &oldset);
        result = nfs_direct_read_schedule(dreq, user_addr, count, pos);
        if (!result)
                result = nfs_direct_wait(dreq);
-       rpc_clnt_sigunmask(clnt, &oldset);
        nfs_direct_req_release(dreq);
 
        return result;
@@ -700,9 +696,7 @@ static ssize_t nfs_direct_write_schedule(struct 
nfs_direct_req *dreq, unsigned l
 static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, 
size_t count, loff_t pos)
 {
        ssize_t result = 0;
-       sigset_t oldset;
        struct inode *inode = iocb->ki_filp->f_mapping->host;
-       struct rpc_clnt *clnt = NFS_CLIENT(inode);
        struct nfs_direct_req *dreq;
        size_t wsize = NFS_SERVER(inode)->wsize;
        int sync = 0;
@@ -722,11 +716,9 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, 
unsigned long user_addr, siz
 
        nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count);
 
-       rpc_clnt_sigmask(clnt, &oldset);
        result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync);
        if (!result)
                result = nfs_direct_wait(dreq);
-       rpc_clnt_sigunmask(clnt, &oldset);
        nfs_direct_req_release(dreq);
 
        return result;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index db5d96d..7fbf610 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -433,15 +433,11 @@ static int nfs_wait_schedule(void *word)
  */
 static int nfs_wait_on_inode(struct inode *inode)
 {
-       struct rpc_clnt *clnt = NFS_CLIENT(inode);
        struct nfs_inode *nfsi = NFS_I(inode);
-       sigset_t oldmask;
        int error;
 
-       rpc_clnt_sigmask(clnt, &oldmask);
        error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING,
                                        nfs_wait_schedule, TASK_INTERRUPTIBLE);
-       rpc_clnt_sigunmask(clnt, &oldmask);
 
        return error;
 }
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 4cdc236..cf98de9 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -27,9 +27,7 @@
 static int
 nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 {
-       sigset_t oldset;
        int res;
-       rpc_clnt_sigmask(clnt, &oldset);
        do {
                res = rpc_call_sync(clnt, msg, flags);
                if (res != -EJUKEBOX)
@@ -37,7 +35,6 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message 
*msg, int flags)
                schedule_timeout_interruptible(NFS_JUKEBOX_RETRY_TIME);
                res = -ERESTARTSYS;
        } while (!signalled());
-       rpc_clnt_sigunmask(clnt, &oldset);
        return res;
 }
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f03d9d5..c7d3955 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -316,12 +316,9 @@ static void nfs4_opendata_put(struct nfs4_opendata *p)
 
 static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
 {
-       sigset_t oldset;
        int ret;
 
-       rpc_clnt_sigmask(task->tk_client, &oldset);
        ret = rpc_wait_for_completion_task(task);
-       rpc_clnt_sigunmask(task->tk_client, &oldset);
        return ret;
 }
 
@@ -2816,18 +2813,15 @@ static int nfs4_wait_bit_interruptible(void *word)
 
 static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client 
*clp)
 {
-       sigset_t oldset;
        int res;
 
        might_sleep();
 
        rwsem_acquire(&clp->cl_sem.dep_map, 0, 0, _RET_IP_);
 
-       rpc_clnt_sigmask(clnt, &oldset);
        res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER,
                        nfs4_wait_bit_interruptible,
                        TASK_INTERRUPTIBLE);
-       rpc_clnt_sigunmask(clnt, &oldset);
 
        rwsem_release(&clp->cl_sem.dep_map, 1, _RET_IP_);
        return res;
@@ -2835,7 +2829,6 @@ static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, 
struct nfs_client *clp)
 
 static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
 {
-       sigset_t oldset;
        int res = 0;
 
        might_sleep();
@@ -2844,14 +2837,12 @@ static int nfs4_delay(struct rpc_clnt *clnt, long 
*timeout)
                *timeout = NFS4_POLL_RETRY_MIN;
        if (*timeout > NFS4_POLL_RETRY_MAX)
                *timeout = NFS4_POLL_RETRY_MAX;
-       rpc_clnt_sigmask(clnt, &oldset);
        if (clnt->cl_intr) {
                schedule_timeout_interruptible(*timeout);
                if (signalled())
                        res = -ERESTARTSYS;
        } else
                schedule_timeout_uninterruptible(*timeout);
-       rpc_clnt_sigunmask(clnt, &oldset);
        *timeout <<= 1;
        return res;
 }
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 345bb9b..e72c007 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -196,8 +196,6 @@ static int nfs_wait_bit_interruptible(void *word)
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-       struct rpc_clnt *clnt = 
NFS_CLIENT(req->wb_context->path.dentry->d_inode);
-       sigset_t oldmask;
        int ret = 0;
 
        if (!test_bit(PG_BUSY, &req->wb_flags))
@@ -206,10 +204,8 @@ nfs_wait_on_request(struct nfs_page *req)
         * Note: the call to rpc_clnt_sigmask() suffices to ensure that we
         *       are not interrupted if intr flag is not set
         */
-       rpc_clnt_sigmask(clnt, &oldmask);
        ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY,
                        nfs_wait_bit_interruptible, TASK_INTERRUPTIBLE);
-       rpc_clnt_sigunmask(clnt, &oldmask);
 out:
        return ret;
 }
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 4587a86..3dcaa6a 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -212,12 +212,7 @@ nfs_async_read_error(struct list_head *head)
  */
 static void nfs_execute_read(struct nfs_read_data *data)
 {
-       struct rpc_clnt *clnt = NFS_CLIENT(data->inode);
-       sigset_t oldset;
-
-       rpc_clnt_sigmask(clnt, &oldset);
        rpc_execute(&data->task);
-       rpc_clnt_sigunmask(clnt, &oldset);
 }
 
 /*
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 89527a4..8dca8c5 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -816,12 +816,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
 
 static void nfs_execute_write(struct nfs_write_data *data)
 {
-       struct rpc_clnt *clnt = NFS_CLIENT(data->inode);
-       sigset_t oldset;
-
-       rpc_clnt_sigmask(clnt, &oldset);
        rpc_execute(&data->task);
-       rpc_clnt_sigunmask(clnt, &oldset);
 }
 
 /*
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index e82a6eb..b87f428 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -520,9 +520,7 @@ extern void * nfs_root_data(void);
        int __retval = 0;                                               \
        if (clnt->cl_intr) {                                            \
                sigset_t oldmask;                                       \
-               rpc_clnt_sigmask(clnt, &oldmask);                       \
                __retval = wait_event_interruptible(wq, condition);     \
-               rpc_clnt_sigunmask(clnt, &oldmask);                     \
        } else                                                          \
                wait_event(wq, condition);                              \
        __retval;                                                       \
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 76be83e..b7aca2e 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -480,44 +480,6 @@ static const struct rpc_call_ops rpc_default_ops = {
        .rpc_call_done = rpc_default_callback,
 };
 
-/*
- *     Export the signal mask handling for synchronous code that
- *     sleeps on RPC calls
- */
-#define RPC_INTR_SIGNALS (sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT) 
| sigmask(SIGTERM))
-
-static void rpc_save_sigmask(sigset_t *oldset, int intr)
-{
-       unsigned long   sigallow = sigmask(SIGKILL);
-       sigset_t sigmask;
-
-       /* Block all signals except those listed in sigallow */
-       if (intr)
-               sigallow |= RPC_INTR_SIGNALS;
-       siginitsetinv(&sigmask, sigallow);
-       sigprocmask(SIG_BLOCK, &sigmask, oldset);
-}
-
-static inline void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset)
-{
-       rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task));
-}
-
-static inline void rpc_restore_sigmask(sigset_t *oldset)
-{
-       sigprocmask(SIG_SETMASK, oldset, NULL);
-}
-
-void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset)
-{
-       rpc_save_sigmask(oldset, clnt->cl_intr);
-}
-
-void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
-{
-       rpc_restore_sigmask(oldset);
-}
-
 static
 struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
                struct rpc_message *msg,
@@ -526,7 +488,6 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
                void *data)
 {
        struct rpc_task *task, *ret;
-       sigset_t oldset;
 
        task = rpc_new_task(clnt, flags, ops, data);
        if (task == NULL) {
@@ -535,7 +496,6 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
        }
 
        /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
-       rpc_task_sigmask(task, &oldset);
        if (msg != NULL) {
                rpc_call_setup(task, msg, 0);
                if (task->tk_status != 0) {
@@ -548,7 +508,6 @@ struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
        rpc_execute(task);
        ret = task;
 out:
-       rpc_restore_sigmask(&oldset);
        return ret;
 }
 
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index c98873f..f67dba7 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -301,7 +301,7 @@ int __rpc_wait_for_completion_task(struct rpc_task *task, 
int (*action)(void *))
        if (action == NULL)
                action = rpc_wait_bit_interruptible;
        return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE,
-                       action, TASK_INTERRUPTIBLE);
+                       action, TASK_KILLABLE);
 }
 EXPORT_SYMBOL(__rpc_wait_for_completion_task);
 
@@ -693,7 +693,7 @@ static void __rpc_execute(struct rpc_task *task)
                /* Note: Caller should be using rpc_clnt_sigmask() */
                status = out_of_line_wait_on_bit(&task->tk_runstate,
                                RPC_TASK_QUEUED, rpc_wait_bit_interruptible,
-                               TASK_INTERRUPTIBLE);
+                               TASK_KILLABLE);
                if (status == -ERESTARTSYS) {
                        /*
                         * When a sync task receives a signal, it exits with
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 33d89e8..1fd3aa8 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -38,8 +38,6 @@ EXPORT_SYMBOL(rpc_killall_tasks);
 EXPORT_SYMBOL(rpc_call_sync);
 EXPORT_SYMBOL(rpc_call_async);
 EXPORT_SYMBOL(rpc_call_setup);
-EXPORT_SYMBOL(rpc_clnt_sigmask);
-EXPORT_SYMBOL(rpc_clnt_sigunmask);
 EXPORT_SYMBOL(rpc_delay);
 EXPORT_SYMBOL(rpc_restart_call);
 EXPORT_SYMBOL(rpc_setbufsize);
-- 
1.5.2.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to