[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20071204212543.GA6907@solidsnake>
Date: Tue, 4 Dec 2007 16:25:43 -0500
From: Liam Howlett <howlett@...il.com>
To: linux-kernel@...r.kernel.org
Cc: neilb@...e.de, trond.myklebust@....uio.no, bfields@...ldses.org,
Matthew Wilcox <matthew@....cx>
Subject: NFS Killable tasks request comments on patch
Signed-off-by: Liam R. Howlett <howlett@...il.com>
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 majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists