diff options
| author | Joel Becker <jlbec@evilplan.org> | 2011-03-28 12:44:26 -0400 |
|---|---|---|
| committer | Joel Becker <jlbec@evilplan.org> | 2011-03-28 12:44:26 -0400 |
| commit | 99bdc3880c611c7f2061fbd5372ef81b40217e26 (patch) | |
| tree | ef68a53e28e9ee53ce9db3642bab5fa5b3d44866 /net/sunrpc | |
| parent | ed59992e8d91b70053c53d846a76f7e1ac000454 (diff) | |
| parent | b4e1b7e88b2c87c358c2a88bec0c76d25accc604 (diff) | |
Merge branch 'mlog_replace_for_39' of git://repo.or.cz/taoma-kernel into ocfs2-merge-window-fix
Diffstat (limited to 'net/sunrpc')
| -rw-r--r-- | net/sunrpc/sched.c | 75 | ||||
| -rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 1 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 3 |
3 files changed, 64 insertions, 15 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 243fc09b164e..59e599498e37 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
| @@ -252,23 +252,37 @@ static void rpc_set_active(struct rpc_task *task) | |||
| 252 | 252 | ||
| 253 | /* | 253 | /* |
| 254 | * Mark an RPC call as having completed by clearing the 'active' bit | 254 | * Mark an RPC call as having completed by clearing the 'active' bit |
| 255 | * and then waking up all tasks that were sleeping. | ||
| 255 | */ | 256 | */ |
| 256 | static void rpc_mark_complete_task(struct rpc_task *task) | 257 | static int rpc_complete_task(struct rpc_task *task) |
| 257 | { | 258 | { |
| 258 | smp_mb__before_clear_bit(); | 259 | void *m = &task->tk_runstate; |
| 260 | wait_queue_head_t *wq = bit_waitqueue(m, RPC_TASK_ACTIVE); | ||
| 261 | struct wait_bit_key k = __WAIT_BIT_KEY_INITIALIZER(m, RPC_TASK_ACTIVE); | ||
| 262 | unsigned long flags; | ||
| 263 | int ret; | ||
| 264 | |||
| 265 | spin_lock_irqsave(&wq->lock, flags); | ||
| 259 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 266 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
| 260 | smp_mb__after_clear_bit(); | 267 | ret = atomic_dec_and_test(&task->tk_count); |
| 261 | wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); | 268 | if (waitqueue_active(wq)) |
| 269 | __wake_up_locked_key(wq, TASK_NORMAL, &k); | ||
| 270 | spin_unlock_irqrestore(&wq->lock, flags); | ||
| 271 | return ret; | ||
| 262 | } | 272 | } |
| 263 | 273 | ||
| 264 | /* | 274 | /* |
| 265 | * Allow callers to wait for completion of an RPC call | 275 | * Allow callers to wait for completion of an RPC call |
| 276 | * | ||
| 277 | * Note the use of out_of_line_wait_on_bit() rather than wait_on_bit() | ||
| 278 | * to enforce taking of the wq->lock and hence avoid races with | ||
| 279 | * rpc_complete_task(). | ||
| 266 | */ | 280 | */ |
| 267 | int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) | 281 | int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) |
| 268 | { | 282 | { |
| 269 | if (action == NULL) | 283 | if (action == NULL) |
| 270 | action = rpc_wait_bit_killable; | 284 | action = rpc_wait_bit_killable; |
| 271 | return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, | 285 | return out_of_line_wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, |
| 272 | action, TASK_KILLABLE); | 286 | action, TASK_KILLABLE); |
| 273 | } | 287 | } |
| 274 | EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); | 288 | EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); |
| @@ -857,34 +871,67 @@ static void rpc_async_release(struct work_struct *work) | |||
| 857 | rpc_free_task(container_of(work, struct rpc_task, u.tk_work)); | 871 | rpc_free_task(container_of(work, struct rpc_task, u.tk_work)); |
| 858 | } | 872 | } |
| 859 | 873 | ||
| 860 | void rpc_put_task(struct rpc_task *task) | 874 | static void rpc_release_resources_task(struct rpc_task *task) |
| 861 | { | 875 | { |
| 862 | if (!atomic_dec_and_test(&task->tk_count)) | ||
| 863 | return; | ||
| 864 | /* Release resources */ | ||
| 865 | if (task->tk_rqstp) | 876 | if (task->tk_rqstp) |
| 866 | xprt_release(task); | 877 | xprt_release(task); |
| 867 | if (task->tk_msg.rpc_cred) | 878 | if (task->tk_msg.rpc_cred) |
| 868 | put_rpccred(task->tk_msg.rpc_cred); | 879 | put_rpccred(task->tk_msg.rpc_cred); |
| 869 | rpc_task_release_client(task); | 880 | rpc_task_release_client(task); |
| 870 | if (task->tk_workqueue != NULL) { | 881 | } |
| 882 | |||
| 883 | static void rpc_final_put_task(struct rpc_task *task, | ||
| 884 | struct workqueue_struct *q) | ||
| 885 | { | ||
| 886 | if (q != NULL) { | ||
| 871 | INIT_WORK(&task->u.tk_work, rpc_async_release); | 887 | INIT_WORK(&task->u.tk_work, rpc_async_release); |
| 872 | queue_work(task->tk_workqueue, &task->u.tk_work); | 888 | queue_work(q, &task->u.tk_work); |
| 873 | } else | 889 | } else |
| 874 | rpc_free_task(task); | 890 | rpc_free_task(task); |
| 875 | } | 891 | } |
| 892 | |||
| 893 | static void rpc_do_put_task(struct rpc_task *task, struct workqueue_struct *q) | ||
| 894 | { | ||
| 895 | if (atomic_dec_and_test(&task->tk_count)) { | ||
| 896 | rpc_release_resources_task(task); | ||
| 897 | rpc_final_put_task(task, q); | ||
| 898 | } | ||
| 899 | } | ||
| 900 | |||
| 901 | void rpc_put_task(struct rpc_task *task) | ||
| 902 | { | ||
| 903 | rpc_do_put_task(task, NULL); | ||
| 904 | } | ||
| 876 | EXPORT_SYMBOL_GPL(rpc_put_task); | 905 | EXPORT_SYMBOL_GPL(rpc_put_task); |
| 877 | 906 | ||
| 907 | void rpc_put_task_async(struct rpc_task *task) | ||
| 908 | { | ||
| 909 | rpc_do_put_task(task, task->tk_workqueue); | ||
| 910 | } | ||
| 911 | EXPORT_SYMBOL_GPL(rpc_put_task_async); | ||
| 912 | |||
| 878 | static void rpc_release_task(struct rpc_task *task) | 913 | static void rpc_release_task(struct rpc_task *task) |
| 879 | { | 914 | { |
| 880 | dprintk("RPC: %5u release task\n", task->tk_pid); | 915 | dprintk("RPC: %5u release task\n", task->tk_pid); |
| 881 | 916 | ||
| 882 | BUG_ON (RPC_IS_QUEUED(task)); | 917 | BUG_ON (RPC_IS_QUEUED(task)); |
| 883 | 918 | ||
| 884 | /* Wake up anyone who is waiting for task completion */ | 919 | rpc_release_resources_task(task); |
| 885 | rpc_mark_complete_task(task); | ||
| 886 | 920 | ||
| 887 | rpc_put_task(task); | 921 | /* |
| 922 | * Note: at this point we have been removed from rpc_clnt->cl_tasks, | ||
| 923 | * so it should be safe to use task->tk_count as a test for whether | ||
| 924 | * or not any other processes still hold references to our rpc_task. | ||
| 925 | */ | ||
| 926 | if (atomic_read(&task->tk_count) != 1 + !RPC_IS_ASYNC(task)) { | ||
| 927 | /* Wake up anyone who may be waiting for task completion */ | ||
| 928 | if (!rpc_complete_task(task)) | ||
| 929 | return; | ||
| 930 | } else { | ||
| 931 | if (!atomic_dec_and_test(&task->tk_count)) | ||
| 932 | return; | ||
| 933 | } | ||
| 934 | rpc_final_put_task(task, task->tk_workqueue); | ||
| 888 | } | 935 | } |
| 889 | 936 | ||
| 890 | int rpciod_up(void) | 937 | int rpciod_up(void) |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 9df1eadc912a..1a10dcd999ea 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
| @@ -1335,6 +1335,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp, | |||
| 1335 | p, 0, length, DMA_FROM_DEVICE); | 1335 | p, 0, length, DMA_FROM_DEVICE); |
| 1336 | if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { | 1336 | if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { |
| 1337 | put_page(p); | 1337 | put_page(p); |
| 1338 | svc_rdma_put_context(ctxt, 1); | ||
| 1338 | return; | 1339 | return; |
| 1339 | } | 1340 | } |
| 1340 | atomic_inc(&xprt->sc_dma_used); | 1341 | atomic_inc(&xprt->sc_dma_used); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c431f5a57960..be96d429b475 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -1631,7 +1631,8 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt, | |||
| 1631 | } | 1631 | } |
| 1632 | xs_reclassify_socket(family, sock); | 1632 | xs_reclassify_socket(family, sock); |
| 1633 | 1633 | ||
| 1634 | if (xs_bind(transport, sock)) { | 1634 | err = xs_bind(transport, sock); |
| 1635 | if (err) { | ||
| 1635 | sock_release(sock); | 1636 | sock_release(sock); |
| 1636 | goto out; | 1637 | goto out; |
| 1637 | } | 1638 | } |
