* [PATCH 07/10] SUNRPC: Switch tasks to using the rpc_waitqueue's timer function
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
2008-02-26 17:23 ` [PATCH 05/10] SUNRPC: Add a (empty for the moment) destructor for rpc_wait_queues Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 01/10] SUNRPC: Clean up rpc_run_timer() Trond Myklebust
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
include/linux/sunrpc/sched.h | 9 +-----
net/sunrpc/sched.c | 59 +++++++-----------------------------------
2 files changed, 11 insertions(+), 57 deletions(-)
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 7751d3a..0d7be16 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -67,12 +67,6 @@ struct rpc_task {
const struct rpc_call_ops *tk_ops;
void * tk_calldata;
- /*
- * tk_timer is used for async processing by the RPC scheduling
- * primitives. You should not access this directly unless
- * you have a pathological interest in kernel oopses.
- */
- struct timer_list tk_timer; /* kernel timer */
unsigned long tk_timeout; /* timeout for rpc_sleep() */
unsigned short tk_flags; /* misc flags */
unsigned long tk_runstate; /* Task run status */
@@ -149,8 +143,7 @@ struct rpc_task_setup {
#define RPC_TASK_RUNNING 0
#define RPC_TASK_QUEUED 1
#define RPC_TASK_WAKEUP 2
-#define RPC_TASK_HAS_TIMER 3
-#define RPC_TASK_ACTIVE 4
+#define RPC_TASK_ACTIVE 3
#define RPC_IS_RUNNING(t) test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
#define rpc_set_running(t) set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index cdff04d..bb58eb4 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -58,18 +58,20 @@ struct workqueue_struct *rpciod_workqueue;
* rpc_run_timer().
*/
static void
-__rpc_disable_timer(struct rpc_task *task)
+__rpc_disable_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
{
dprintk("RPC: %5u disabling timer\n", task->tk_pid);
task->tk_timeout = 0;
list_del(&task->u.tk_wait.timer_list);
+ if (list_empty(&queue->timer_list.list))
+ del_timer(&queue->timer_list.timer);
}
/*
* Set up a timer for the current task.
*/
static void
-__rpc_add_timer(struct rpc_task *task)
+__rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task)
{
if (!task->tk_timeout)
return;
@@ -77,23 +79,10 @@ __rpc_add_timer(struct rpc_task *task)
dprintk("RPC: %5u setting alarm for %lu ms\n",
task->tk_pid, task->tk_timeout * 1000 / HZ);
- set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
- mod_timer(&task->tk_timer, jiffies + task->tk_timeout);
-}
-
-/*
- * Delete any timer for the current task. Because we use del_timer_sync(),
- * this function should never be called while holding queue->lock.
- */
-static void
-rpc_delete_timer(struct rpc_task *task)
-{
- if (RPC_IS_QUEUED(task))
- return;
- if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
- del_singleshot_timer_sync(&task->tk_timer);
- dprintk("RPC: %5u deleting timer\n", task->tk_pid);
- }
+ task->u.tk_wait.expires = jiffies + task->tk_timeout;
+ if (list_empty(&queue->timer_list.list) || time_before(task->u.tk_wait.expires, queue->timer_list.expires))
+ mod_timer(&queue->timer_list.timer, task->u.tk_wait.expires);
+ list_add(&queue->timer_list.list, &task->u.tk_wait.timer_list);
}
/*
@@ -164,7 +153,7 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
*/
static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
{
- __rpc_disable_timer(task);
+ __rpc_disable_timer(queue, task);
if (RPC_IS_PRIORITY(queue))
__rpc_remove_wait_queue_priority(task);
list_del(&task->u.tk_wait.list);
@@ -336,7 +325,7 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
BUG_ON(task->tk_callback != NULL);
task->tk_callback = action;
- __rpc_add_timer(task);
+ __rpc_add_timer(q, task);
}
void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
@@ -547,26 +536,6 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
}
EXPORT_SYMBOL_GPL(rpc_wake_up_status);
-/*
- * Run a timeout function.
- */
-static void rpc_run_timer(unsigned long ptr)
-{
- struct rpc_task *task = (struct rpc_task *)ptr;
- struct rpc_wait_queue *queue = task->tk_waitqueue;
-
- spin_lock(&queue->lock);
- if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue) {
- dprintk("RPC: %5u timeout\n", task->tk_pid);
- task->tk_status = -ETIMEDOUT;
- rpc_wake_up_task_queue_locked(queue, task);
- }
- spin_unlock(&queue->lock);
- smp_mb__before_clear_bit();
- clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
- smp_mb__after_clear_bit();
-}
-
static void __rpc_queue_timer_fn(unsigned long ptr)
{
struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr;
@@ -660,10 +629,6 @@ static void __rpc_execute(struct rpc_task *task)
BUG_ON(RPC_IS_QUEUED(task));
for (;;) {
- /*
- * Garbage collection of pending timers...
- */
- rpc_delete_timer(task);
/*
* Execute any pending callback.
@@ -832,7 +797,6 @@ EXPORT_SYMBOL_GPL(rpc_free);
static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data)
{
memset(task, 0, sizeof(*task));
- setup_timer(&task->tk_timer, rpc_run_timer, (unsigned long)task);
atomic_set(&task->tk_count, 1);
task->tk_flags = task_setup_data->flags;
task->tk_ops = task_setup_data->callback_ops;
@@ -965,9 +929,6 @@ static void rpc_release_task(struct rpc_task *task)
}
BUG_ON (RPC_IS_QUEUED(task));
- /* Synchronously delete any running timer */
- rpc_delete_timer(task);
-
#ifdef RPC_DEBUG
task->tk_magic = 0;
#endif
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 08/10] SUNRPC: Eliminate the now-redundant rpc_start_wakeup()
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
` (4 preceding siblings ...)
2008-02-26 17:23 ` [PATCH 03/10] SUNRPC: Convert users of rpc_wake_up_task to use rpc_wake_up_queued_task Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 02/10] SUNRPC: Add a new helper rpc_wake_up_queued_task() Trond Myklebust
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
include/linux/sunrpc/sched.h | 12 +-----------
net/sunrpc/sched.c | 8 ++------
2 files changed, 3 insertions(+), 17 deletions(-)
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 0d7be16..bf69fce 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -142,8 +142,7 @@ struct rpc_task_setup {
#define RPC_TASK_RUNNING 0
#define RPC_TASK_QUEUED 1
-#define RPC_TASK_WAKEUP 2
-#define RPC_TASK_ACTIVE 3
+#define RPC_TASK_ACTIVE 2
#define RPC_IS_RUNNING(t) test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
#define rpc_set_running(t) set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
@@ -165,15 +164,6 @@ struct rpc_task_setup {
smp_mb__after_clear_bit(); \
} while (0)
-#define rpc_start_wakeup(t) \
- (test_and_set_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate) == 0)
-#define rpc_finish_wakeup(t) \
- do { \
- smp_mb__before_clear_bit(); \
- clear_bit(RPC_TASK_WAKEUP, &(t)->tk_runstate); \
- smp_mb__after_clear_bit(); \
- } while (0)
-
#define RPC_IS_ACTIVATED(t) test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
/*
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index bb58eb4..0c6fb50 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -376,12 +376,8 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task
*/
static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
{
- if (!RPC_IS_QUEUED(task) || task->tk_waitqueue != queue)
- return;
- if (rpc_start_wakeup(task)) {
- __rpc_do_wake_up_task(queue, task);
- rpc_finish_wakeup(task);
- }
+ if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue)
+ __rpc_do_wake_up_task(queue, task);
}
/*
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 05/10] SUNRPC: Add a (empty for the moment) destructor for rpc_wait_queues
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 07/10] SUNRPC: Switch tasks to using the rpc_waitqueue's timer function Trond Myklebust
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/client.c | 1 +
fs/nfs/nfs4state.c | 6 +++++-
include/linux/sunrpc/sched.h | 1 +
net/sunrpc/auth_gss/auth_gss.c | 1 +
net/sunrpc/sched.c | 21 ++++++++++++++-------
net/sunrpc/xprt.c | 5 +++++
6 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index c5c0175..2b20650 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -189,6 +189,7 @@ static void nfs_free_client(struct nfs_client *clp)
if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
nfs_callback_down();
+ rpc_destroy_wait_queue(&clp->cl_rpcwaitq);
kfree(clp->cl_hostname);
kfree(clp);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index a2ef028..7775435 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -292,8 +292,10 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
spin_unlock(&clp->cl_lock);
if (sp == new)
get_rpccred(cred);
- else
+ else {
+ rpc_destroy_wait_queue(&new->so_sequence.wait);
kfree(new);
+ }
return sp;
}
@@ -310,6 +312,7 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
return;
nfs4_remove_state_owner(clp, sp);
spin_unlock(&clp->cl_lock);
+ rpc_destroy_wait_queue(&sp->so_sequence.wait);
put_rpccred(cred);
kfree(sp);
}
@@ -529,6 +532,7 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
spin_lock(&clp->cl_lock);
nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
spin_unlock(&clp->cl_lock);
+ rpc_destroy_wait_queue(&lsp->ls_sequence.wait);
kfree(lsp);
}
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 503a937..d39729e 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -228,6 +228,7 @@ void rpc_killall_tasks(struct rpc_clnt *);
void rpc_execute(struct rpc_task *);
void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
void rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
+void rpc_destroy_wait_queue(struct rpc_wait_queue *);
void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
rpc_action action);
void rpc_wake_up_queued_task(struct rpc_wait_queue *,
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index dc6391b..ef63849 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -266,6 +266,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
BUG_ON(!list_empty(&gss_msg->list));
if (gss_msg->ctx != NULL)
gss_put_ctx(gss_msg->ctx);
+ rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
kfree(gss_msg);
}
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index caf12fd..86aa897 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -214,6 +214,11 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
}
EXPORT_SYMBOL_GPL(rpc_init_wait_queue);
+void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
+{
+}
+EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
+
static int rpc_wait_bit_killable(void *word)
{
if (fatal_signal_pending(current))
@@ -1020,11 +1025,20 @@ rpc_destroy_mempool(void)
kmem_cache_destroy(rpc_task_slabp);
if (rpc_buffer_slabp)
kmem_cache_destroy(rpc_buffer_slabp);
+ rpc_destroy_wait_queue(&delay_queue);
}
int
rpc_init_mempool(void)
{
+ /*
+ * The following is not strictly a mempool initialisation,
+ * but there is no harm in doing it here
+ */
+ rpc_init_wait_queue(&delay_queue, "delayq");
+ if (!rpciod_start())
+ goto err_nomem;
+
rpc_task_slabp = kmem_cache_create("rpc_tasks",
sizeof(struct rpc_task),
0, SLAB_HWCACHE_ALIGN,
@@ -1045,13 +1059,6 @@ rpc_init_mempool(void)
rpc_buffer_slabp);
if (!rpc_buffer_mempool)
goto err_nomem;
- if (!rpciod_start())
- goto err_nomem;
- /*
- * The following is not strictly a mempool initialisation,
- * but there is no harm in doing it here
- */
- rpc_init_wait_queue(&delay_queue, "delayq");
return 0;
err_nomem:
rpc_destroy_mempool();
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 9bf118c..85199c6 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1052,6 +1052,11 @@ static void xprt_destroy(struct kref *kref)
xprt->shutdown = 1;
del_timer_sync(&xprt->timer);
+ rpc_destroy_wait_queue(&xprt->binding);
+ rpc_destroy_wait_queue(&xprt->pending);
+ rpc_destroy_wait_queue(&xprt->sending);
+ rpc_destroy_wait_queue(&xprt->resend);
+ rpc_destroy_wait_queue(&xprt->backlog);
/*
* Tear down transport state and free the rpc_xprt
*/
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 02/10] SUNRPC: Add a new helper rpc_wake_up_queued_task()
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
` (5 preceding siblings ...)
2008-02-26 17:23 ` [PATCH 08/10] SUNRPC: Eliminate the now-redundant rpc_start_wakeup() Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 09/10] SUNRPC: Ensure that we read all available tcp data Trond Myklebust
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
In all cases where we currently use rpc_wake_up_task(), we almost always
know on which waitqueue the rpc_task is actually sleeping. This will allows
us to simplify the queue locking in a future patch.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
include/linux/sunrpc/sched.h | 4 ++-
net/sunrpc/clnt.c | 2 +
net/sunrpc/sched.c | 64 ++++++++++++++++++++----------------------
3 files changed, 34 insertions(+), 36 deletions(-)
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index fefb0ab..83f6777 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -33,7 +33,6 @@ struct rpc_wait_queue;
struct rpc_wait {
struct list_head list; /* wait queue links */
struct list_head links; /* Links to related tasks */
- struct rpc_wait_queue * rpc_waitq; /* RPC wait queue we're on */
};
/*
@@ -80,6 +79,7 @@ struct rpc_task {
struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could
* be any workqueue
*/
+ struct rpc_wait_queue *tk_waitqueue; /* RPC wait queue we're on */
union {
struct work_struct tk_work; /* Async task work queue */
struct rpc_wait tk_wait; /* RPC wait */
@@ -233,6 +233,8 @@ void rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
rpc_action action, rpc_action timer);
void rpc_wake_up_task(struct rpc_task *);
+void rpc_wake_up_queued_task(struct rpc_wait_queue *,
+ struct rpc_task *);
void rpc_wake_up(struct rpc_wait_queue *);
struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
void rpc_wake_up_status(struct rpc_wait_queue *, int);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 8c6a7f1..fe95bd0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1535,7 +1535,7 @@ void rpc_show_tasks(void)
proc = -1;
if (RPC_IS_QUEUED(t))
- rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
+ rpc_waitq = rpc_qname(t->tk_waitqueue);
printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
t->tk_pid, proc,
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 9433a11..9233ace 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -148,7 +148,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *
list_add(&task->u.tk_wait.list, &queue->tasks[0]);
else
list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
- task->u.tk_wait.rpc_waitq = queue;
+ task->tk_waitqueue = queue;
queue->qlen++;
rpc_set_queued(task);
@@ -175,11 +175,8 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
* Remove request from queue.
* Note: must be called with spin lock held.
*/
-static void __rpc_remove_wait_queue(struct rpc_task *task)
+static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
{
- struct rpc_wait_queue *queue;
- queue = task->u.tk_wait.rpc_waitq;
-
if (RPC_IS_PRIORITY(queue))
__rpc_remove_wait_queue_priority(task);
else
@@ -364,11 +361,12 @@ EXPORT_SYMBOL_GPL(rpc_sleep_on);
/**
* __rpc_do_wake_up_task - wake up a single rpc_task
+ * @queue: wait queue
* @task: task to be woken up
*
* Caller must hold queue->lock, and have cleared the task queued flag.
*/
-static void __rpc_do_wake_up_task(struct rpc_task *task)
+static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task *task)
{
dprintk("RPC: %5u __rpc_wake_up_task (now %lu)\n",
task->tk_pid, jiffies);
@@ -383,7 +381,7 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
}
__rpc_disable_timer(task);
- __rpc_remove_wait_queue(task);
+ __rpc_remove_wait_queue(queue, task);
rpc_make_runnable(task);
@@ -391,36 +389,38 @@ static void __rpc_do_wake_up_task(struct rpc_task *task)
}
/*
- * Wake up the specified task
+ * Wake up a queued task while the queue lock is being held
*/
-static void __rpc_wake_up_task(struct rpc_task *task)
+static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
{
+ if (!RPC_IS_QUEUED(task) || task->tk_waitqueue != queue)
+ return;
if (rpc_start_wakeup(task)) {
- if (RPC_IS_QUEUED(task))
- __rpc_do_wake_up_task(task);
+ __rpc_do_wake_up_task(queue, task);
rpc_finish_wakeup(task);
}
}
/*
- * Wake up the specified task
+ * Wake up a task on a specific queue
*/
-void rpc_wake_up_task(struct rpc_task *task)
+void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
{
rcu_read_lock_bh();
- if (rpc_start_wakeup(task)) {
- if (RPC_IS_QUEUED(task)) {
- struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
-
- /* Note: we're already in a bh-safe context */
- spin_lock(&queue->lock);
- __rpc_do_wake_up_task(task);
- spin_unlock(&queue->lock);
- }
- rpc_finish_wakeup(task);
- }
+ spin_lock(&queue->lock);
+ rpc_wake_up_task_queue_locked(queue, task);
+ spin_unlock(&queue->lock);
rcu_read_unlock_bh();
}
+EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
+
+/*
+ * Wake up the specified task
+ */
+void rpc_wake_up_task(struct rpc_task *task)
+{
+ rpc_wake_up_queued_task(task->tk_waitqueue, task);
+}
EXPORT_SYMBOL_GPL(rpc_wake_up_task);
/*
@@ -471,7 +471,7 @@ new_queue:
new_owner:
rpc_set_waitqueue_owner(queue, task->tk_owner);
out:
- __rpc_wake_up_task(task);
+ rpc_wake_up_task_queue_locked(queue, task);
return task;
}
@@ -490,7 +490,7 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
task = __rpc_wake_up_next_priority(queue);
else {
task_for_first(task, &queue->tasks[0])
- __rpc_wake_up_task(task);
+ rpc_wake_up_task_queue_locked(queue, task);
}
spin_unlock(&queue->lock);
rcu_read_unlock_bh();
@@ -515,7 +515,7 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
head = &queue->tasks[queue->maxpriority];
for (;;) {
list_for_each_entry_safe(task, next, head, u.tk_wait.list)
- __rpc_wake_up_task(task);
+ rpc_wake_up_task_queue_locked(queue, task);
if (head == &queue->tasks[0])
break;
head--;
@@ -543,7 +543,7 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
for (;;) {
list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
task->tk_status = status;
- __rpc_wake_up_task(task);
+ rpc_wake_up_task_queue_locked(queue, task);
}
if (head == &queue->tasks[0])
break;
@@ -562,10 +562,8 @@ static void rpc_run_timer(unsigned long ptr)
struct rpc_task *task = (struct rpc_task *)ptr;
void (*callback)(struct rpc_task *);
- if (!rpc_start_wakeup(task))
- goto out;
if (RPC_IS_QUEUED(task)) {
- struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
+ struct rpc_wait_queue *queue = task->tk_waitqueue;
callback = task->tk_timeout_fn;
dprintk("RPC: %5u running timer\n", task->tk_pid);
@@ -573,11 +571,9 @@ static void rpc_run_timer(unsigned long ptr)
callback(task);
/* Note: we're already in a bh-safe context */
spin_lock(&queue->lock);
- __rpc_do_wake_up_task(task);
+ rpc_wake_up_task_queue_locked(queue, task);
spin_unlock(&queue->lock);
}
- rpc_finish_wakeup(task);
-out:
smp_mb__before_clear_bit();
clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
smp_mb__after_clear_bit();
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 03/10] SUNRPC: Convert users of rpc_wake_up_task to use rpc_wake_up_queued_task
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
` (3 preceding siblings ...)
2008-02-26 17:23 ` [PATCH 04/10] SUNRPC: Run rpc timeout functions as callbacks instead of in softirqs Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 08/10] SUNRPC: Eliminate the now-redundant rpc_start_wakeup() Trond Myklebust
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/nfs4proc.c | 2 +-
include/linux/sunrpc/sched.h | 1 -
net/sunrpc/clnt.c | 2 +-
net/sunrpc/sched.c | 3 +--
net/sunrpc/xprt.c | 10 +++++-----
5 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b6db833..5474339 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2768,7 +2768,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
nfs4_schedule_state_recovery(clp);
if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
- rpc_wake_up_task(task);
+ rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
task->tk_status = 0;
return -EAGAIN;
case -NFS4ERR_DELAY:
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 83f6777..7963ef0 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -232,7 +232,6 @@ void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
void rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
rpc_action action, rpc_action timer);
-void rpc_wake_up_task(struct rpc_task *);
void rpc_wake_up_queued_task(struct rpc_wait_queue *,
struct rpc_task *);
void rpc_wake_up(struct rpc_wait_queue *);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index fe95bd0..0e209af 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1066,7 +1066,7 @@ call_transmit(struct rpc_task *task)
if (task->tk_msg.rpc_proc->p_decode != NULL)
return;
task->tk_action = rpc_exit_task;
- rpc_wake_up_task(task);
+ rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
}
/*
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 9233ace..35acdc3 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -417,11 +417,10 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
/*
* Wake up the specified task
*/
-void rpc_wake_up_task(struct rpc_task *task)
+static void rpc_wake_up_task(struct rpc_task *task)
{
rpc_wake_up_queued_task(task->tk_waitqueue, task);
}
-EXPORT_SYMBOL_GPL(rpc_wake_up_task);
/*
* Wake up the next task on a priority queue.
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 96c212d..6e27722 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -472,7 +472,7 @@ void xprt_write_space(struct rpc_xprt *xprt)
if (xprt->snd_task) {
dprintk("RPC: write space: waking waiting task on "
"xprt %p\n", xprt);
- rpc_wake_up_task(xprt->snd_task);
+ rpc_wake_up_queued_task(&xprt->pending, xprt->snd_task);
}
spin_unlock_bh(&xprt->transport_lock);
}
@@ -602,8 +602,7 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
/* Try to schedule an autoclose RPC call */
if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
queue_work(rpciod_workqueue, &xprt->task_cleanup);
- else if (xprt->snd_task != NULL)
- rpc_wake_up_task(xprt->snd_task);
+ xprt_wake_pending_tasks(xprt, -ENOTCONN);
spin_unlock_bh(&xprt->transport_lock);
}
EXPORT_SYMBOL_GPL(xprt_force_disconnect);
@@ -749,18 +748,19 @@ EXPORT_SYMBOL_GPL(xprt_update_rtt);
void xprt_complete_rqst(struct rpc_task *task, int copied)
{
struct rpc_rqst *req = task->tk_rqstp;
+ struct rpc_xprt *xprt = req->rq_xprt;
dprintk("RPC: %5u xid %08x complete (%d bytes received)\n",
task->tk_pid, ntohl(req->rq_xid), copied);
- task->tk_xprt->stat.recvs++;
+ xprt->stat.recvs++;
task->tk_rtt = (long)jiffies - req->rq_xtime;
list_del_init(&req->rq_list);
/* Ensure all writes are done before we update req->rq_received */
smp_wmb();
req->rq_received = req->rq_private_buf.len = copied;
- rpc_wake_up_task(task);
+ rpc_wake_up_queued_task(&xprt->pending, task);
}
EXPORT_SYMBOL_GPL(xprt_complete_rqst);
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 09/10] SUNRPC: Ensure that we read all available tcp data
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
` (6 preceding siblings ...)
2008-02-26 17:23 ` [PATCH 02/10] SUNRPC: Add a new helper rpc_wake_up_queued_task() Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
[not found] ` <20080226172308.10383.82368.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
2008-02-26 17:23 ` [PATCH 06/10] SUNRPC: Add a timer function to wait queues Trond Myklebust
2008-02-26 17:23 ` [PATCH 10/10] SUNRPC: Remove now-redundant RCU-safe rpc_task free path Trond Myklebust
9 siblings, 1 reply; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
Don't stop until we run out of data, or we hit an error.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
net/sunrpc/xprtsock.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 30e7ac2..8bd3b0f 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1073,6 +1073,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
{
struct rpc_xprt *xprt;
read_descriptor_t rd_desc;
+ int read;
dprintk("RPC: xs_tcp_data_ready...\n");
@@ -1084,8 +1085,10 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
/* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
rd_desc.arg.data = xprt;
- rd_desc.count = 65536;
- tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
+ do {
+ rd_desc.count = 65536;
+ read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
+ } while (read > 0);
out:
read_unlock(&sk->sk_callback_lock);
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 01/10] SUNRPC: Clean up rpc_run_timer()
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
2008-02-26 17:23 ` [PATCH 05/10] SUNRPC: Add a (empty for the moment) destructor for rpc_wait_queues Trond Myklebust
2008-02-26 17:23 ` [PATCH 07/10] SUNRPC: Switch tasks to using the rpc_waitqueue's timer function Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 04/10] SUNRPC: Run rpc timeout functions as callbacks instead of in softirqs Trond Myklebust
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
All RPC timeout callback functions are expected to wake the task up. We can
enforce this by moving the wakeup back into rpc_run_timer.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
net/sunrpc/sched.c | 67 +++++++++++++++++++++++++++-------------------------
net/sunrpc/xprt.c | 2 --
2 files changed, 35 insertions(+), 34 deletions(-)
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 3e0b223..9433a11 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -38,7 +38,6 @@ static struct kmem_cache *rpc_buffer_slabp __read_mostly;
static mempool_t *rpc_task_mempool __read_mostly;
static mempool_t *rpc_buffer_mempool __read_mostly;
-static void __rpc_default_timer(struct rpc_task *task);
static void rpc_async_schedule(struct work_struct *);
static void rpc_release_task(struct rpc_task *task);
@@ -66,25 +65,13 @@ __rpc_disable_timer(struct rpc_task *task)
}
/*
- * Run a timeout function.
- * We use the callback in order to allow __rpc_wake_up_task()
- * and friends to disable the timer synchronously on SMP systems
- * without calling del_timer_sync(). The latter could cause a
- * deadlock if called while we're holding spinlocks...
+ * Default timeout handler if none specified by user
*/
-static void rpc_run_timer(struct rpc_task *task)
+static void
+__rpc_default_timer(struct rpc_task *task)
{
- void (*callback)(struct rpc_task *);
-
- callback = task->tk_timeout_fn;
- task->tk_timeout_fn = NULL;
- if (callback && RPC_IS_QUEUED(task)) {
- dprintk("RPC: %5u running timer\n", task->tk_pid);
- callback(task);
- }
- smp_mb__before_clear_bit();
- clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
- smp_mb__after_clear_bit();
+ dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
+ task->tk_status = -ETIMEDOUT;
}
/*
@@ -416,17 +403,6 @@ static void __rpc_wake_up_task(struct rpc_task *task)
}
/*
- * Default timeout handler if none specified by user
- */
-static void
-__rpc_default_timer(struct rpc_task *task)
-{
- dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
- task->tk_status = -ETIMEDOUT;
- rpc_wake_up_task(task);
-}
-
-/*
* Wake up the specified task
*/
void rpc_wake_up_task(struct rpc_task *task)
@@ -578,9 +554,37 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
}
EXPORT_SYMBOL_GPL(rpc_wake_up_status);
+/*
+ * Run a timeout function.
+ */
+static void rpc_run_timer(unsigned long ptr)
+{
+ struct rpc_task *task = (struct rpc_task *)ptr;
+ void (*callback)(struct rpc_task *);
+
+ if (!rpc_start_wakeup(task))
+ goto out;
+ if (RPC_IS_QUEUED(task)) {
+ struct rpc_wait_queue *queue = task->u.tk_wait.rpc_waitq;
+ callback = task->tk_timeout_fn;
+
+ dprintk("RPC: %5u running timer\n", task->tk_pid);
+ if (callback != NULL)
+ callback(task);
+ /* Note: we're already in a bh-safe context */
+ spin_lock(&queue->lock);
+ __rpc_do_wake_up_task(task);
+ spin_unlock(&queue->lock);
+ }
+ rpc_finish_wakeup(task);
+out:
+ smp_mb__before_clear_bit();
+ clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
+ smp_mb__after_clear_bit();
+}
+
static void __rpc_atrun(struct rpc_task *task)
{
- rpc_wake_up_task(task);
}
/*
@@ -816,8 +820,7 @@ EXPORT_SYMBOL_GPL(rpc_free);
static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data)
{
memset(task, 0, sizeof(*task));
- setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer,
- (unsigned long)task);
+ setup_timer(&task->tk_timer, rpc_run_timer, (unsigned long)task);
atomic_set(&task->tk_count, 1);
task->tk_flags = task_setup_data->flags;
task->tk_ops = task_setup_data->callback_ops;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index d5553b8..96c212d 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -777,8 +777,6 @@ static void xprt_timer(struct rpc_task *task)
xprt->ops->timer(task);
task->tk_status = -ETIMEDOUT;
}
- task->tk_timeout = 0;
- rpc_wake_up_task(task);
spin_unlock(&xprt->transport_lock);
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 04/10] SUNRPC: Run rpc timeout functions as callbacks instead of in softirqs
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
` (2 preceding siblings ...)
2008-02-26 17:23 ` [PATCH 01/10] SUNRPC: Clean up rpc_run_timer() Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 03/10] SUNRPC: Convert users of rpc_wake_up_task to use rpc_wake_up_queued_task Trond Myklebust
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
An audit of the current RPC timeout functions shows that they don't really
ever need to run in the softirq context. As long as the softirq is
able to signal that the wakeup is due to a timeout (which it can do by
setting task->tk_status to -ETIMEDOUT) then the callback functions can just
run as standard task->tk_callback functions (in the rpciod/process
context).
The only possible border-line case would be xprt_timer() for the case of
UDP, when the callback is used to reduce the size of the transport
congestion window. In testing, however, the effect of moving that update
to a callback would appear to be minor.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/nfs4proc.c | 2 +-
fs/nfs/nfs4state.c | 2 +-
include/linux/sunrpc/sched.h | 4 +--
net/sunrpc/auth_gss/auth_gss.c | 4 ++-
net/sunrpc/rpcb_clnt.c | 2 +-
net/sunrpc/sched.c | 50 ++++++++++++----------------------------
net/sunrpc/xprt.c | 28 ++++++++++++----------
7 files changed, 36 insertions(+), 56 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5474339..bbb0d58 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2765,7 +2765,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
- rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
+ rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
nfs4_schedule_state_recovery(clp);
if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index b962397..a2ef028 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -731,7 +731,7 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
list_add_tail(&seqid->list, &sequence->list);
if (list_first_entry(&sequence->list, struct nfs_seqid, list) == seqid)
goto unlock;
- rpc_sleep_on(&sequence->wait, task, NULL, NULL);
+ rpc_sleep_on(&sequence->wait, task, NULL);
status = -EAGAIN;
unlock:
spin_unlock(&sequence->lock);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 7963ef0..503a937 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -56,12 +56,10 @@ struct rpc_task {
__u8 tk_cred_retry;
/*
- * timeout_fn to be executed by timer bottom half
* callback to be executed after waking up
* action next procedure for async tasks
* tk_ops caller callbacks
*/
- void (*tk_timeout_fn)(struct rpc_task *);
void (*tk_callback)(struct rpc_task *);
void (*tk_action)(struct rpc_task *);
const struct rpc_call_ops *tk_ops;
@@ -231,7 +229,7 @@ void rpc_execute(struct rpc_task *);
void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
void rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
- rpc_action action, rpc_action timer);
+ rpc_action action);
void rpc_wake_up_queued_task(struct rpc_wait_queue *,
struct rpc_task *);
void rpc_wake_up(struct rpc_wait_queue *);
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 6dac387..dc6391b 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -408,13 +408,13 @@ gss_refresh_upcall(struct rpc_task *task)
}
spin_lock(&inode->i_lock);
if (gss_cred->gc_upcall != NULL)
- rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
+ rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
task->tk_timeout = 0;
gss_cred->gc_upcall = gss_msg;
/* gss_upcall_callback will release the reference to gss_upcall_msg */
atomic_inc(&gss_msg->count);
- rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
+ rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
} else
err = gss_msg->msg.errno;
spin_unlock(&inode->i_lock);
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 3164a08..f480c71 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -298,7 +298,7 @@ void rpcb_getport_async(struct rpc_task *task)
/* Put self on queue before sending rpcbind request, in case
* rpcb_getport_done completes before we return from rpc_run_task */
- rpc_sleep_on(&xprt->binding, task, NULL, NULL);
+ rpc_sleep_on(&xprt->binding, task, NULL);
/* Someone else may have bound if we slept */
if (xprt_bound(xprt)) {
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 35acdc3..caf12fd 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -56,29 +56,18 @@ struct workqueue_struct *rpciod_workqueue;
* queue->lock and bh_disabled in order to avoid races within
* rpc_run_timer().
*/
-static inline void
+static void
__rpc_disable_timer(struct rpc_task *task)
{
dprintk("RPC: %5u disabling timer\n", task->tk_pid);
- task->tk_timeout_fn = NULL;
task->tk_timeout = 0;
}
/*
- * Default timeout handler if none specified by user
- */
-static void
-__rpc_default_timer(struct rpc_task *task)
-{
- dprintk("RPC: %5u timeout (default timer)\n", task->tk_pid);
- task->tk_status = -ETIMEDOUT;
-}
-
-/*
* Set up a timer for the current task.
*/
-static inline void
-__rpc_add_timer(struct rpc_task *task, rpc_action timer)
+static void
+__rpc_add_timer(struct rpc_task *task)
{
if (!task->tk_timeout)
return;
@@ -86,10 +75,6 @@ __rpc_add_timer(struct rpc_task *task, rpc_action timer)
dprintk("RPC: %5u setting alarm for %lu ms\n",
task->tk_pid, task->tk_timeout * 1000 / HZ);
- if (timer)
- task->tk_timeout_fn = timer;
- else
- task->tk_timeout_fn = __rpc_default_timer;
set_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
mod_timer(&task->tk_timer, jiffies + task->tk_timeout);
}
@@ -297,7 +282,6 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task);
*/
static void rpc_make_runnable(struct rpc_task *task)
{
- BUG_ON(task->tk_timeout_fn);
rpc_clear_queued(task);
if (rpc_test_and_set_running(task))
return;
@@ -327,7 +311,7 @@ static void rpc_make_runnable(struct rpc_task *task)
* as it's on a wait queue.
*/
static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
- rpc_action action, rpc_action timer)
+ rpc_action action)
{
dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n",
task->tk_pid, rpc_qname(q), jiffies);
@@ -341,11 +325,11 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
BUG_ON(task->tk_callback != NULL);
task->tk_callback = action;
- __rpc_add_timer(task, timer);
+ __rpc_add_timer(task);
}
void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
- rpc_action action, rpc_action timer)
+ rpc_action action)
{
/* Mark the task as being activated if so needed */
rpc_set_active(task);
@@ -354,7 +338,7 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
* Protect the queue operations.
*/
spin_lock_bh(&q->lock);
- __rpc_sleep_on(q, task, action, timer);
+ __rpc_sleep_on(q, task, action);
spin_unlock_bh(&q->lock);
}
EXPORT_SYMBOL_GPL(rpc_sleep_on);
@@ -559,20 +543,15 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_status);
static void rpc_run_timer(unsigned long ptr)
{
struct rpc_task *task = (struct rpc_task *)ptr;
- void (*callback)(struct rpc_task *);
+ struct rpc_wait_queue *queue = task->tk_waitqueue;
- if (RPC_IS_QUEUED(task)) {
- struct rpc_wait_queue *queue = task->tk_waitqueue;
- callback = task->tk_timeout_fn;
-
- dprintk("RPC: %5u running timer\n", task->tk_pid);
- if (callback != NULL)
- callback(task);
- /* Note: we're already in a bh-safe context */
- spin_lock(&queue->lock);
+ spin_lock(&queue->lock);
+ if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue) {
+ dprintk("RPC: %5u timeout\n", task->tk_pid);
+ task->tk_status = -ETIMEDOUT;
rpc_wake_up_task_queue_locked(queue, task);
- spin_unlock(&queue->lock);
}
+ spin_unlock(&queue->lock);
smp_mb__before_clear_bit();
clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate);
smp_mb__after_clear_bit();
@@ -580,6 +559,7 @@ static void rpc_run_timer(unsigned long ptr)
static void __rpc_atrun(struct rpc_task *task)
{
+ task->tk_status = 0;
}
/*
@@ -588,7 +568,7 @@ static void __rpc_atrun(struct rpc_task *task)
void rpc_delay(struct rpc_task *task, unsigned long delay)
{
task->tk_timeout = delay;
- rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun);
+ rpc_sleep_on(&delay_queue, task, __rpc_atrun);
}
EXPORT_SYMBOL_GPL(rpc_delay);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 6e27722..9bf118c 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -188,9 +188,9 @@ out_sleep:
task->tk_timeout = 0;
task->tk_status = -EAGAIN;
if (req && req->rq_ntrans)
- rpc_sleep_on(&xprt->resend, task, NULL, NULL);
+ rpc_sleep_on(&xprt->resend, task, NULL);
else
- rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+ rpc_sleep_on(&xprt->sending, task, NULL);
return 0;
}
EXPORT_SYMBOL_GPL(xprt_reserve_xprt);
@@ -238,9 +238,9 @@ out_sleep:
task->tk_timeout = 0;
task->tk_status = -EAGAIN;
if (req && req->rq_ntrans)
- rpc_sleep_on(&xprt->resend, task, NULL, NULL);
+ rpc_sleep_on(&xprt->resend, task, NULL);
else
- rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+ rpc_sleep_on(&xprt->sending, task, NULL);
return 0;
}
EXPORT_SYMBOL_GPL(xprt_reserve_xprt_cong);
@@ -453,7 +453,7 @@ void xprt_wait_for_buffer_space(struct rpc_task *task)
struct rpc_xprt *xprt = req->rq_xprt;
task->tk_timeout = req->rq_timeout;
- rpc_sleep_on(&xprt->pending, task, NULL, NULL);
+ rpc_sleep_on(&xprt->pending, task, NULL);
}
EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space);
@@ -652,7 +652,7 @@ void xprt_connect(struct rpc_task *task)
task->tk_rqstp->rq_bytes_sent = 0;
task->tk_timeout = xprt->connect_timeout;
- rpc_sleep_on(&xprt->pending, task, xprt_connect_status, NULL);
+ rpc_sleep_on(&xprt->pending, task, xprt_connect_status);
xprt->stat.connect_start = jiffies;
xprt->ops->connect(task);
}
@@ -769,15 +769,17 @@ static void xprt_timer(struct rpc_task *task)
struct rpc_rqst *req = task->tk_rqstp;
struct rpc_xprt *xprt = req->rq_xprt;
+ if (task->tk_status != -ETIMEDOUT)
+ return;
dprintk("RPC: %5u xprt_timer\n", task->tk_pid);
- spin_lock(&xprt->transport_lock);
+ spin_lock_bh(&xprt->transport_lock);
if (!req->rq_received) {
if (xprt->ops->timer)
xprt->ops->timer(task);
- task->tk_status = -ETIMEDOUT;
- }
- spin_unlock(&xprt->transport_lock);
+ } else
+ task->tk_status = 0;
+ spin_unlock_bh(&xprt->transport_lock);
}
/**
@@ -862,7 +864,7 @@ void xprt_transmit(struct rpc_task *task)
if (!xprt_connected(xprt))
task->tk_status = -ENOTCONN;
else if (!req->rq_received)
- rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
+ rpc_sleep_on(&xprt->pending, task, xprt_timer);
spin_unlock_bh(&xprt->transport_lock);
return;
}
@@ -873,7 +875,7 @@ void xprt_transmit(struct rpc_task *task)
*/
task->tk_status = status;
if (status == -ECONNREFUSED)
- rpc_sleep_on(&xprt->sending, task, NULL, NULL);
+ rpc_sleep_on(&xprt->sending, task, NULL);
}
static inline void do_xprt_reserve(struct rpc_task *task)
@@ -893,7 +895,7 @@ static inline void do_xprt_reserve(struct rpc_task *task)
dprintk("RPC: waiting for request slot\n");
task->tk_status = -EAGAIN;
task->tk_timeout = 0;
- rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
+ rpc_sleep_on(&xprt->backlog, task, NULL);
}
/**
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 06/10] SUNRPC: Add a timer function to wait queues.
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
` (7 preceding siblings ...)
2008-02-26 17:23 ` [PATCH 09/10] SUNRPC: Ensure that we read all available tcp data Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
2008-02-26 17:23 ` [PATCH 10/10] SUNRPC: Remove now-redundant RCU-safe rpc_task free path Trond Myklebust
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
This is designed to replace the timeout timer in the individual rpc_tasks.
By putting the timer function in the wait queue, we will eventually be able
to reduce the total number of timers in use by the RPC subsystem.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
include/linux/sunrpc/sched.h | 9 +++++++++
net/sunrpc/sched.c | 40 ++++++++++++++++++++++++++++++++++++----
2 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index d39729e..7751d3a 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -33,6 +33,8 @@ struct rpc_wait_queue;
struct rpc_wait {
struct list_head list; /* wait queue links */
struct list_head links; /* Links to related tasks */
+ struct list_head timer_list; /* Timer list */
+ unsigned long expires;
};
/*
@@ -191,6 +193,12 @@ struct rpc_task_setup {
#define RPC_PRIORITY_HIGH (1)
#define RPC_NR_PRIORITY (1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW)
+struct rpc_timer {
+ struct timer_list timer;
+ struct list_head list;
+ unsigned long expires;
+};
+
/*
* RPC synchronization objects
*/
@@ -203,6 +211,7 @@ struct rpc_wait_queue {
unsigned char count; /* # task groups remaining serviced so far */
unsigned char nr; /* # tasks remaining for cookie */
unsigned short qlen; /* total # tasks waiting in queue */
+ struct rpc_timer timer_list;
#ifdef RPC_DEBUG
const char * name;
#endif
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 86aa897..cdff04d 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -40,6 +40,7 @@ static mempool_t *rpc_buffer_mempool __read_mostly;
static void rpc_async_schedule(struct work_struct *);
static void rpc_release_task(struct rpc_task *task);
+static void __rpc_queue_timer_fn(unsigned long ptr);
/*
* RPC tasks sit here while waiting for conditions to improve.
@@ -61,6 +62,7 @@ __rpc_disable_timer(struct rpc_task *task)
{
dprintk("RPC: %5u disabling timer\n", task->tk_pid);
task->tk_timeout = 0;
+ list_del(&task->u.tk_wait.timer_list);
}
/*
@@ -127,6 +129,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *
{
BUG_ON (RPC_IS_QUEUED(task));
+ INIT_LIST_HEAD(&task->u.tk_wait.timer_list);
if (RPC_IS_PRIORITY(queue))
__rpc_add_wait_queue_priority(queue, task);
else if (RPC_IS_SWAPPER(task))
@@ -153,7 +156,6 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
list_move(&t->u.tk_wait.list, &task->u.tk_wait.list);
list_splice_init(&task->u.tk_wait.links, &t->u.tk_wait.links);
}
- list_del(&task->u.tk_wait.list);
}
/*
@@ -162,10 +164,10 @@ static void __rpc_remove_wait_queue_priority(struct rpc_task *task)
*/
static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_task *task)
{
+ __rpc_disable_timer(task);
if (RPC_IS_PRIORITY(queue))
__rpc_remove_wait_queue_priority(task);
- else
- list_del(&task->u.tk_wait.list);
+ list_del(&task->u.tk_wait.list);
queue->qlen--;
dprintk("RPC: %5u removed from queue %p \"%s\"\n",
task->tk_pid, queue, rpc_qname(queue));
@@ -198,6 +200,9 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c
INIT_LIST_HEAD(&queue->tasks[i]);
queue->maxpriority = nr_queues - 1;
rpc_reset_waitqueue_priority(queue);
+ queue->qlen = 0;
+ setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue);
+ INIT_LIST_HEAD(&queue->timer_list.list);
#ifdef RPC_DEBUG
queue->name = qname;
#endif
@@ -216,6 +221,7 @@ EXPORT_SYMBOL_GPL(rpc_init_wait_queue);
void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
{
+ del_timer_sync(&queue->timer_list.timer);
}
EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
@@ -369,7 +375,6 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task
return;
}
- __rpc_disable_timer(task);
__rpc_remove_wait_queue(queue, task);
rpc_make_runnable(task);
@@ -562,6 +567,33 @@ static void rpc_run_timer(unsigned long ptr)
smp_mb__after_clear_bit();
}
+static void __rpc_queue_timer_fn(unsigned long ptr)
+{
+ struct rpc_wait_queue *queue = (struct rpc_wait_queue *)ptr;
+ struct rpc_task *task, *n;
+ unsigned long expires, now, timeo;
+
+ spin_lock(&queue->lock);
+ expires = now = jiffies;
+ list_for_each_entry_safe(task, n, &queue->timer_list.list, u.tk_wait.timer_list) {
+ timeo = task->u.tk_wait.expires;
+ if (time_after_eq(now, timeo)) {
+ list_del_init(&task->u.tk_wait.timer_list);
+ dprintk("RPC: %5u timeout\n", task->tk_pid);
+ task->tk_status = -ETIMEDOUT;
+ rpc_wake_up_task_queue_locked(queue, task);
+ continue;
+ }
+ if (expires == now || time_before(expires, timeo))
+ expires = timeo;
+ }
+ if (!list_empty(&queue->timer_list.list)) {
+ mod_timer(&queue->timer_list.timer, expires);
+ queue->timer_list.expires = expires;
+ }
+ spin_unlock(&queue->lock);
+}
+
static void __rpc_atrun(struct rpc_task *task)
{
task->tk_status = 0;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 10/10] SUNRPC: Remove now-redundant RCU-safe rpc_task free path
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
` (8 preceding siblings ...)
2008-02-26 17:23 ` [PATCH 06/10] SUNRPC: Add a timer function to wait queues Trond Myklebust
@ 2008-02-26 17:23 ` Trond Myklebust
9 siblings, 0 replies; 11+ messages in thread
From: Trond Myklebust @ 2008-02-26 17:23 UTC (permalink / raw)
To: linux-nfs
Now that we've tightened up the locking rules for RPC queue wakeups, we can
remove the RCU-safe kfree calls...
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/read.c | 8 +-------
fs/nfs/write.c | 16 ++--------------
include/linux/sunrpc/sched.h | 2 --
net/sunrpc/sched.c | 37 ++++++++++++-------------------------
4 files changed, 15 insertions(+), 48 deletions(-)
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 87546cd..be9e827 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -58,19 +58,13 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
return p;
}
-static void nfs_readdata_rcu_free(struct rcu_head *head)
+static void nfs_readdata_free(struct nfs_read_data *p)
{
- struct nfs_read_data *p = container_of(head, struct nfs_read_data, task.u.tk_rcu);
if (p && (p->pagevec != &p->page_array[0]))
kfree(p->pagevec);
mempool_free(p, nfs_rdata_mempool);
}
-static void nfs_readdata_free(struct nfs_read_data *rdata)
-{
- call_rcu_bh(&rdata->task.u.tk_rcu, nfs_readdata_rcu_free);
-}
-
void nfs_readdata_release(void *data)
{
struct nfs_read_data *rdata = data;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 84495ef..3051302 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -58,19 +58,13 @@ struct nfs_write_data *nfs_commit_alloc(void)
return p;
}
-static void nfs_commit_rcu_free(struct rcu_head *head)
+void nfs_commit_free(struct nfs_write_data *p)
{
- struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
if (p && (p->pagevec != &p->page_array[0]))
kfree(p->pagevec);
mempool_free(p, nfs_commit_mempool);
}
-void nfs_commit_free(struct nfs_write_data *wdata)
-{
- call_rcu_bh(&wdata->task.u.tk_rcu, nfs_commit_rcu_free);
-}
-
struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
{
struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS);
@@ -92,19 +86,13 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
return p;
}
-static void nfs_writedata_rcu_free(struct rcu_head *head)
+static void nfs_writedata_free(struct nfs_write_data *p)
{
- struct nfs_write_data *p = container_of(head, struct nfs_write_data, task.u.tk_rcu);
if (p && (p->pagevec != &p->page_array[0]))
kfree(p->pagevec);
mempool_free(p, nfs_wdata_mempool);
}
-static void nfs_writedata_free(struct nfs_write_data *wdata)
-{
- call_rcu_bh(&wdata->task.u.tk_rcu, nfs_writedata_rcu_free);
-}
-
void nfs_writedata_release(void *data)
{
struct nfs_write_data *wdata = data;
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index bf69fce..d1a5c8c 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -11,7 +11,6 @@
#include <linux/timer.h>
#include <linux/sunrpc/types.h>
-#include <linux/rcupdate.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
@@ -77,7 +76,6 @@ struct rpc_task {
union {
struct work_struct tk_work; /* Async task work queue */
struct rpc_wait tk_wait; /* RPC wait */
- struct rcu_head tk_rcu; /* for task deletion */
} u;
unsigned short tk_timeouts; /* maj timeouts */
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 0c6fb50..872da12 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -385,11 +385,9 @@ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct r
*/
void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
{
- rcu_read_lock_bh();
- spin_lock(&queue->lock);
+ spin_lock_bh(&queue->lock);
rpc_wake_up_task_queue_locked(queue, task);
- spin_unlock(&queue->lock);
- rcu_read_unlock_bh();
+ spin_unlock_bh(&queue->lock);
}
EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
@@ -462,16 +460,14 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue)
dprintk("RPC: wake_up_next(%p \"%s\")\n",
queue, rpc_qname(queue));
- rcu_read_lock_bh();
- spin_lock(&queue->lock);
+ spin_lock_bh(&queue->lock);
if (RPC_IS_PRIORITY(queue))
task = __rpc_wake_up_next_priority(queue);
else {
task_for_first(task, &queue->tasks[0])
rpc_wake_up_task_queue_locked(queue, task);
}
- spin_unlock(&queue->lock);
- rcu_read_unlock_bh();
+ spin_unlock_bh(&queue->lock);
return task;
}
@@ -488,8 +484,7 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
struct rpc_task *task, *next;
struct list_head *head;
- rcu_read_lock_bh();
- spin_lock(&queue->lock);
+ spin_lock_bh(&queue->lock);
head = &queue->tasks[queue->maxpriority];
for (;;) {
list_for_each_entry_safe(task, next, head, u.tk_wait.list)
@@ -498,8 +493,7 @@ void rpc_wake_up(struct rpc_wait_queue *queue)
break;
head--;
}
- spin_unlock(&queue->lock);
- rcu_read_unlock_bh();
+ spin_unlock_bh(&queue->lock);
}
EXPORT_SYMBOL_GPL(rpc_wake_up);
@@ -515,8 +509,7 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
struct rpc_task *task, *next;
struct list_head *head;
- rcu_read_lock_bh();
- spin_lock(&queue->lock);
+ spin_lock_bh(&queue->lock);
head = &queue->tasks[queue->maxpriority];
for (;;) {
list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
@@ -527,8 +520,7 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
break;
head--;
}
- spin_unlock(&queue->lock);
- rcu_read_unlock_bh();
+ spin_unlock_bh(&queue->lock);
}
EXPORT_SYMBOL_GPL(rpc_wake_up_status);
@@ -843,13 +835,6 @@ rpc_alloc_task(void)
return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
}
-static void rpc_free_task_rcu(struct rcu_head *rcu)
-{
- struct rpc_task *task = container_of(rcu, struct rpc_task, u.tk_rcu);
- dprintk("RPC: %5u freeing task\n", task->tk_pid);
- mempool_free(task, rpc_task_mempool);
-}
-
/*
* Create a new task for the specified client.
*/
@@ -878,8 +863,10 @@ static void rpc_free_task(struct rpc_task *task)
const struct rpc_call_ops *tk_ops = task->tk_ops;
void *calldata = task->tk_calldata;
- if (task->tk_flags & RPC_TASK_DYNAMIC)
- call_rcu_bh(&task->u.tk_rcu, rpc_free_task_rcu);
+ if (task->tk_flags & RPC_TASK_DYNAMIC) {
+ dprintk("RPC: %5u freeing task\n", task->tk_pid);
+ mempool_free(task, rpc_task_mempool);
+ }
rpc_release_calldata(tk_ops, calldata);
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 09/10] SUNRPC: Ensure that we read all available tcp data
[not found] ` <20080226172308.10383.82368.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
@ 2008-02-27 18:21 ` Chuck Lever
0 siblings, 0 replies; 11+ messages in thread
From: Chuck Lever @ 2008-02-27 18:21 UTC (permalink / raw)
To: Trond Myklebust; +Cc: linux-nfs
[-- Attachment #1: Type: text/plain, Size: 1341 bytes --]
Trond Myklebust wrote:
> Don't stop until we run out of data, or we hit an error.
I don't understand how this patch is related to the others.
> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
> ---
>
> net/sunrpc/xprtsock.c | 7 +++++--
> 1 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
> index 30e7ac2..8bd3b0f 100644
> --- a/net/sunrpc/xprtsock.c
> +++ b/net/sunrpc/xprtsock.c
> @@ -1073,6 +1073,7 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
> {
> struct rpc_xprt *xprt;
> read_descriptor_t rd_desc;
> + int read;
>
> dprintk("RPC: xs_tcp_data_ready...\n");
>
> @@ -1084,8 +1085,10 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes)
>
> /* We use rd_desc to pass struct xprt to xs_tcp_data_recv */
> rd_desc.arg.data = xprt;
> - rd_desc.count = 65536;
> - tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
> + do {
> + rd_desc.count = 65536;
> + read = tcp_read_sock(sk, &rd_desc, xs_tcp_data_recv);
> + } while (read > 0);
Why are we looping instead of simply setting rd_desc.count to a larger
value (say, a megabyte)?
(If we keep this, it would be nice to replace the "65536" with a macro,
and to add a comment explaining the need for the loop).
> out:
> read_unlock(&sk->sk_callback_lock);
> }
[-- Attachment #2: chuck_lever.vcf --]
[-- Type: text/x-vcard, Size: 270 bytes --]
begin:vcard
fn:Chuck Lever
n:Lever;Chuck
org:Oracle Corporation;Corporate Architecture: Linux Projects Group
adr:;;1015 Granger Avenue;Ann Arbor;MI;48104;USA
title:Principal Member of Staff
tel;work:+1 248 614 5091
x-mozilla-html:FALSE
version:2.1
end:vcard
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-02-27 18:22 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20080226172308.10383.49081.stgit@c-69-242-210-120.hsd1.mi.comcast.net>
[not found] ` <20080226172308.10383.49081.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
2008-02-26 17:23 ` [PATCH 05/10] SUNRPC: Add a (empty for the moment) destructor for rpc_wait_queues Trond Myklebust
2008-02-26 17:23 ` [PATCH 07/10] SUNRPC: Switch tasks to using the rpc_waitqueue's timer function Trond Myklebust
2008-02-26 17:23 ` [PATCH 01/10] SUNRPC: Clean up rpc_run_timer() Trond Myklebust
2008-02-26 17:23 ` [PATCH 04/10] SUNRPC: Run rpc timeout functions as callbacks instead of in softirqs Trond Myklebust
2008-02-26 17:23 ` [PATCH 03/10] SUNRPC: Convert users of rpc_wake_up_task to use rpc_wake_up_queued_task Trond Myklebust
2008-02-26 17:23 ` [PATCH 08/10] SUNRPC: Eliminate the now-redundant rpc_start_wakeup() Trond Myklebust
2008-02-26 17:23 ` [PATCH 02/10] SUNRPC: Add a new helper rpc_wake_up_queued_task() Trond Myklebust
2008-02-26 17:23 ` [PATCH 09/10] SUNRPC: Ensure that we read all available tcp data Trond Myklebust
[not found] ` <20080226172308.10383.82368.stgit-KPEdlmqt5P7XOazzY/2fV4TcuzvYVacciM950cveMlzk1uMJSBkQmQ@public.gmane.org>
2008-02-27 18:21 ` Chuck Lever
2008-02-26 17:23 ` [PATCH 06/10] SUNRPC: Add a timer function to wait queues Trond Myklebust
2008-02-26 17:23 ` [PATCH 10/10] SUNRPC: Remove now-redundant RCU-safe rpc_task free path Trond Myklebust
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox