diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-30 03:54:24 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-30 03:54:24 -0500 |
commit | 85004cc367abc000aa36c0d0e270ab609a68b0cb (patch) | |
tree | 5739aae778d67b6d119fe5c668313fc2823e9836 /net/sunrpc/sched.c | |
parent | 149a051f82d2b3860fe32fa182dbc83a66274894 (diff) | |
parent | 3fbd67ad61f6d5a09ea717b56c50bc5c3d8042a8 (diff) |
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: (118 commits)
NFSv4: Iterate through all nfs_clients when the server recalls a delegation
NFSv4: Deal more correctly with duplicate delegations
NFS: Fix a potential race between umount and nfs_access_cache_shrinker()
NFS: Add an asynchronous delegreturn operation for use in nfs_clear_inode
nfs: convert NFS_*(inode) helpers to static inline
nfs: obliterate NFS_FLAGS macro
NFS: Address memory leaks in the NFS client mount option parser
nfs4: allow nfsv4 acls on non-regular-files
NFS: Optimise away the sigmask code in aio/dio reads and writes
SUNRPC: Don't bother changing the sigmask for asynchronous RPC calls
SUNRPC: rpcb_getport_sync() passes incorrect address size to rpc_create()
SUNRPC: Clean up block comment preceding rpcb_getport_sync()
SUNRPC: Use appropriate argument types in rpcb client
SUNRPC: rpcb_getport_sync() should use built-in hostname generator
SUNRPC: Clean up functions that free address_strings array
NFS: NFS version number is unsigned
NLM: Fix a bogus 'return' in nlmclnt_rpc_release
NLM: Introduce an arguments structure for nlmclnt_init()
NLM/NFS: Use cached nlm_host when calling nlmclnt_proc()
NFS: Invoke nlmclnt_init during NFS mount processing
...
Diffstat (limited to 'net/sunrpc/sched.c')
-rw-r--r-- | net/sunrpc/sched.c | 106 |
1 files changed, 66 insertions, 40 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index eed5dd9819cd..40ce6f6672d6 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -45,7 +45,7 @@ static void rpc_release_task(struct rpc_task *task); | |||
45 | /* | 45 | /* |
46 | * RPC tasks sit here while waiting for conditions to improve. | 46 | * RPC tasks sit here while waiting for conditions to improve. |
47 | */ | 47 | */ |
48 | static RPC_WAITQ(delay_queue, "delayq"); | 48 | static struct rpc_wait_queue delay_queue; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * rpciod-related stuff | 51 | * rpciod-related stuff |
@@ -135,7 +135,7 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, struct r | |||
135 | if (unlikely(task->tk_priority > queue->maxpriority)) | 135 | if (unlikely(task->tk_priority > queue->maxpriority)) |
136 | q = &queue->tasks[queue->maxpriority]; | 136 | q = &queue->tasks[queue->maxpriority]; |
137 | list_for_each_entry(t, q, u.tk_wait.list) { | 137 | list_for_each_entry(t, q, u.tk_wait.list) { |
138 | if (t->tk_cookie == task->tk_cookie) { | 138 | if (t->tk_owner == task->tk_owner) { |
139 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); | 139 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); |
140 | return; | 140 | return; |
141 | } | 141 | } |
@@ -208,26 +208,26 @@ static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int | |||
208 | queue->count = 1 << (priority * 2); | 208 | queue->count = 1 << (priority * 2); |
209 | } | 209 | } |
210 | 210 | ||
211 | static inline void rpc_set_waitqueue_cookie(struct rpc_wait_queue *queue, unsigned long cookie) | 211 | static inline void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) |
212 | { | 212 | { |
213 | queue->cookie = cookie; | 213 | queue->owner = pid; |
214 | queue->nr = RPC_BATCH_COUNT; | 214 | queue->nr = RPC_BATCH_COUNT; |
215 | } | 215 | } |
216 | 216 | ||
217 | static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) | 217 | static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) |
218 | { | 218 | { |
219 | rpc_set_waitqueue_priority(queue, queue->maxpriority); | 219 | rpc_set_waitqueue_priority(queue, queue->maxpriority); |
220 | rpc_set_waitqueue_cookie(queue, 0); | 220 | rpc_set_waitqueue_owner(queue, 0); |
221 | } | 221 | } |
222 | 222 | ||
223 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, int maxprio) | 223 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) |
224 | { | 224 | { |
225 | int i; | 225 | int i; |
226 | 226 | ||
227 | spin_lock_init(&queue->lock); | 227 | spin_lock_init(&queue->lock); |
228 | for (i = 0; i < ARRAY_SIZE(queue->tasks); i++) | 228 | for (i = 0; i < ARRAY_SIZE(queue->tasks); i++) |
229 | INIT_LIST_HEAD(&queue->tasks[i]); | 229 | INIT_LIST_HEAD(&queue->tasks[i]); |
230 | queue->maxpriority = maxprio; | 230 | queue->maxpriority = nr_queues - 1; |
231 | rpc_reset_waitqueue_priority(queue); | 231 | rpc_reset_waitqueue_priority(queue); |
232 | #ifdef RPC_DEBUG | 232 | #ifdef RPC_DEBUG |
233 | queue->name = qname; | 233 | queue->name = qname; |
@@ -236,14 +236,14 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c | |||
236 | 236 | ||
237 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 237 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
238 | { | 238 | { |
239 | __rpc_init_priority_wait_queue(queue, qname, RPC_PRIORITY_HIGH); | 239 | __rpc_init_priority_wait_queue(queue, qname, RPC_NR_PRIORITY); |
240 | } | 240 | } |
241 | 241 | ||
242 | void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 242 | void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
243 | { | 243 | { |
244 | __rpc_init_priority_wait_queue(queue, qname, 0); | 244 | __rpc_init_priority_wait_queue(queue, qname, 1); |
245 | } | 245 | } |
246 | EXPORT_SYMBOL(rpc_init_wait_queue); | 246 | EXPORT_SYMBOL_GPL(rpc_init_wait_queue); |
247 | 247 | ||
248 | static int rpc_wait_bit_interruptible(void *word) | 248 | static int rpc_wait_bit_interruptible(void *word) |
249 | { | 249 | { |
@@ -303,7 +303,7 @@ int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) | |||
303 | return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, | 303 | return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, |
304 | action, TASK_INTERRUPTIBLE); | 304 | action, TASK_INTERRUPTIBLE); |
305 | } | 305 | } |
306 | EXPORT_SYMBOL(__rpc_wait_for_completion_task); | 306 | EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); |
307 | 307 | ||
308 | /* | 308 | /* |
309 | * Make an RPC task runnable. | 309 | * Make an RPC task runnable. |
@@ -373,6 +373,7 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
373 | __rpc_sleep_on(q, task, action, timer); | 373 | __rpc_sleep_on(q, task, action, timer); |
374 | spin_unlock_bh(&q->lock); | 374 | spin_unlock_bh(&q->lock); |
375 | } | 375 | } |
376 | EXPORT_SYMBOL_GPL(rpc_sleep_on); | ||
376 | 377 | ||
377 | /** | 378 | /** |
378 | * __rpc_do_wake_up_task - wake up a single rpc_task | 379 | * __rpc_do_wake_up_task - wake up a single rpc_task |
@@ -444,6 +445,7 @@ void rpc_wake_up_task(struct rpc_task *task) | |||
444 | } | 445 | } |
445 | rcu_read_unlock_bh(); | 446 | rcu_read_unlock_bh(); |
446 | } | 447 | } |
448 | EXPORT_SYMBOL_GPL(rpc_wake_up_task); | ||
447 | 449 | ||
448 | /* | 450 | /* |
449 | * Wake up the next task on a priority queue. | 451 | * Wake up the next task on a priority queue. |
@@ -454,12 +456,12 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu | |||
454 | struct rpc_task *task; | 456 | struct rpc_task *task; |
455 | 457 | ||
456 | /* | 458 | /* |
457 | * Service a batch of tasks from a single cookie. | 459 | * Service a batch of tasks from a single owner. |
458 | */ | 460 | */ |
459 | q = &queue->tasks[queue->priority]; | 461 | q = &queue->tasks[queue->priority]; |
460 | if (!list_empty(q)) { | 462 | if (!list_empty(q)) { |
461 | task = list_entry(q->next, struct rpc_task, u.tk_wait.list); | 463 | task = list_entry(q->next, struct rpc_task, u.tk_wait.list); |
462 | if (queue->cookie == task->tk_cookie) { | 464 | if (queue->owner == task->tk_owner) { |
463 | if (--queue->nr) | 465 | if (--queue->nr) |
464 | goto out; | 466 | goto out; |
465 | list_move_tail(&task->u.tk_wait.list, q); | 467 | list_move_tail(&task->u.tk_wait.list, q); |
@@ -468,7 +470,7 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu | |||
468 | * Check if we need to switch queues. | 470 | * Check if we need to switch queues. |
469 | */ | 471 | */ |
470 | if (--queue->count) | 472 | if (--queue->count) |
471 | goto new_cookie; | 473 | goto new_owner; |
472 | } | 474 | } |
473 | 475 | ||
474 | /* | 476 | /* |
@@ -490,8 +492,8 @@ static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queu | |||
490 | 492 | ||
491 | new_queue: | 493 | new_queue: |
492 | rpc_set_waitqueue_priority(queue, (unsigned int)(q - &queue->tasks[0])); | 494 | rpc_set_waitqueue_priority(queue, (unsigned int)(q - &queue->tasks[0])); |
493 | new_cookie: | 495 | new_owner: |
494 | rpc_set_waitqueue_cookie(queue, task->tk_cookie); | 496 | rpc_set_waitqueue_owner(queue, task->tk_owner); |
495 | out: | 497 | out: |
496 | __rpc_wake_up_task(task); | 498 | __rpc_wake_up_task(task); |
497 | return task; | 499 | return task; |
@@ -519,6 +521,7 @@ struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue) | |||
519 | 521 | ||
520 | return task; | 522 | return task; |
521 | } | 523 | } |
524 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); | ||
522 | 525 | ||
523 | /** | 526 | /** |
524 | * rpc_wake_up - wake up all rpc_tasks | 527 | * rpc_wake_up - wake up all rpc_tasks |
@@ -544,6 +547,7 @@ void rpc_wake_up(struct rpc_wait_queue *queue) | |||
544 | spin_unlock(&queue->lock); | 547 | spin_unlock(&queue->lock); |
545 | rcu_read_unlock_bh(); | 548 | rcu_read_unlock_bh(); |
546 | } | 549 | } |
550 | EXPORT_SYMBOL_GPL(rpc_wake_up); | ||
547 | 551 | ||
548 | /** | 552 | /** |
549 | * rpc_wake_up_status - wake up all rpc_tasks and set their status value. | 553 | * rpc_wake_up_status - wake up all rpc_tasks and set their status value. |
@@ -572,6 +576,7 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) | |||
572 | spin_unlock(&queue->lock); | 576 | spin_unlock(&queue->lock); |
573 | rcu_read_unlock_bh(); | 577 | rcu_read_unlock_bh(); |
574 | } | 578 | } |
579 | EXPORT_SYMBOL_GPL(rpc_wake_up_status); | ||
575 | 580 | ||
576 | static void __rpc_atrun(struct rpc_task *task) | 581 | static void __rpc_atrun(struct rpc_task *task) |
577 | { | 582 | { |
@@ -586,6 +591,7 @@ void rpc_delay(struct rpc_task *task, unsigned long delay) | |||
586 | task->tk_timeout = delay; | 591 | task->tk_timeout = delay; |
587 | rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); | 592 | rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); |
588 | } | 593 | } |
594 | EXPORT_SYMBOL_GPL(rpc_delay); | ||
589 | 595 | ||
590 | /* | 596 | /* |
591 | * Helper to call task->tk_ops->rpc_call_prepare | 597 | * Helper to call task->tk_ops->rpc_call_prepare |
@@ -614,7 +620,7 @@ void rpc_exit_task(struct rpc_task *task) | |||
614 | } | 620 | } |
615 | } | 621 | } |
616 | } | 622 | } |
617 | EXPORT_SYMBOL(rpc_exit_task); | 623 | EXPORT_SYMBOL_GPL(rpc_exit_task); |
618 | 624 | ||
619 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) | 625 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) |
620 | { | 626 | { |
@@ -808,39 +814,49 @@ EXPORT_SYMBOL_GPL(rpc_free); | |||
808 | /* | 814 | /* |
809 | * Creation and deletion of RPC task structures | 815 | * Creation and deletion of RPC task structures |
810 | */ | 816 | */ |
811 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) | 817 | static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *task_setup_data) |
812 | { | 818 | { |
813 | memset(task, 0, sizeof(*task)); | 819 | memset(task, 0, sizeof(*task)); |
814 | setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer, | 820 | setup_timer(&task->tk_timer, (void (*)(unsigned long))rpc_run_timer, |
815 | (unsigned long)task); | 821 | (unsigned long)task); |
816 | atomic_set(&task->tk_count, 1); | 822 | atomic_set(&task->tk_count, 1); |
817 | task->tk_client = clnt; | 823 | task->tk_flags = task_setup_data->flags; |
818 | task->tk_flags = flags; | 824 | task->tk_ops = task_setup_data->callback_ops; |
819 | task->tk_ops = tk_ops; | 825 | task->tk_calldata = task_setup_data->callback_data; |
820 | if (tk_ops->rpc_call_prepare != NULL) | ||
821 | task->tk_action = rpc_prepare_task; | ||
822 | task->tk_calldata = calldata; | ||
823 | INIT_LIST_HEAD(&task->tk_task); | 826 | INIT_LIST_HEAD(&task->tk_task); |
824 | 827 | ||
825 | /* Initialize retry counters */ | 828 | /* Initialize retry counters */ |
826 | task->tk_garb_retry = 2; | 829 | task->tk_garb_retry = 2; |
827 | task->tk_cred_retry = 2; | 830 | task->tk_cred_retry = 2; |
828 | 831 | ||
829 | task->tk_priority = RPC_PRIORITY_NORMAL; | 832 | task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; |
830 | task->tk_cookie = (unsigned long)current; | 833 | task->tk_owner = current->tgid; |
831 | 834 | ||
832 | /* Initialize workqueue for async tasks */ | 835 | /* Initialize workqueue for async tasks */ |
833 | task->tk_workqueue = rpciod_workqueue; | 836 | task->tk_workqueue = rpciod_workqueue; |
834 | 837 | ||
835 | if (clnt) { | 838 | task->tk_client = task_setup_data->rpc_client; |
836 | kref_get(&clnt->cl_kref); | 839 | if (task->tk_client != NULL) { |
837 | if (clnt->cl_softrtry) | 840 | kref_get(&task->tk_client->cl_kref); |
841 | if (task->tk_client->cl_softrtry) | ||
838 | task->tk_flags |= RPC_TASK_SOFT; | 842 | task->tk_flags |= RPC_TASK_SOFT; |
839 | if (!clnt->cl_intr) | 843 | if (!task->tk_client->cl_intr) |
840 | task->tk_flags |= RPC_TASK_NOINTR; | 844 | task->tk_flags |= RPC_TASK_NOINTR; |
841 | } | 845 | } |
842 | 846 | ||
843 | BUG_ON(task->tk_ops == NULL); | 847 | if (task->tk_ops->rpc_call_prepare != NULL) |
848 | task->tk_action = rpc_prepare_task; | ||
849 | |||
850 | if (task_setup_data->rpc_message != NULL) { | ||
851 | memcpy(&task->tk_msg, task_setup_data->rpc_message, sizeof(task->tk_msg)); | ||
852 | /* Bind the user cred */ | ||
853 | if (task->tk_msg.rpc_cred != NULL) | ||
854 | rpcauth_holdcred(task); | ||
855 | else | ||
856 | rpcauth_bindcred(task); | ||
857 | if (task->tk_action == NULL) | ||
858 | rpc_call_start(task); | ||
859 | } | ||
844 | 860 | ||
845 | /* starting timestamp */ | 861 | /* starting timestamp */ |
846 | task->tk_start = jiffies; | 862 | task->tk_start = jiffies; |
@@ -865,18 +881,22 @@ static void rpc_free_task(struct rcu_head *rcu) | |||
865 | /* | 881 | /* |
866 | * Create a new task for the specified client. | 882 | * Create a new task for the specified client. |
867 | */ | 883 | */ |
868 | struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) | 884 | struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) |
869 | { | 885 | { |
870 | struct rpc_task *task; | 886 | struct rpc_task *task = setup_data->task; |
871 | 887 | unsigned short flags = 0; | |
872 | task = rpc_alloc_task(); | 888 | |
873 | if (!task) | 889 | if (task == NULL) { |
874 | goto out; | 890 | task = rpc_alloc_task(); |
891 | if (task == NULL) | ||
892 | goto out; | ||
893 | flags = RPC_TASK_DYNAMIC; | ||
894 | } | ||
875 | 895 | ||
876 | rpc_init_task(task, clnt, flags, tk_ops, calldata); | 896 | rpc_init_task(task, setup_data); |
877 | 897 | ||
898 | task->tk_flags |= flags; | ||
878 | dprintk("RPC: allocated task %p\n", task); | 899 | dprintk("RPC: allocated task %p\n", task); |
879 | task->tk_flags |= RPC_TASK_DYNAMIC; | ||
880 | out: | 900 | out: |
881 | return task; | 901 | return task; |
882 | } | 902 | } |
@@ -902,7 +922,7 @@ void rpc_put_task(struct rpc_task *task) | |||
902 | call_rcu_bh(&task->u.tk_rcu, rpc_free_task); | 922 | call_rcu_bh(&task->u.tk_rcu, rpc_free_task); |
903 | rpc_release_calldata(tk_ops, calldata); | 923 | rpc_release_calldata(tk_ops, calldata); |
904 | } | 924 | } |
905 | EXPORT_SYMBOL(rpc_put_task); | 925 | EXPORT_SYMBOL_GPL(rpc_put_task); |
906 | 926 | ||
907 | static void rpc_release_task(struct rpc_task *task) | 927 | static void rpc_release_task(struct rpc_task *task) |
908 | { | 928 | { |
@@ -959,6 +979,7 @@ void rpc_killall_tasks(struct rpc_clnt *clnt) | |||
959 | } | 979 | } |
960 | spin_unlock(&clnt->cl_lock); | 980 | spin_unlock(&clnt->cl_lock); |
961 | } | 981 | } |
982 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | ||
962 | 983 | ||
963 | int rpciod_up(void) | 984 | int rpciod_up(void) |
964 | { | 985 | { |
@@ -1038,6 +1059,11 @@ rpc_init_mempool(void) | |||
1038 | goto err_nomem; | 1059 | goto err_nomem; |
1039 | if (!rpciod_start()) | 1060 | if (!rpciod_start()) |
1040 | goto err_nomem; | 1061 | goto err_nomem; |
1062 | /* | ||
1063 | * The following is not strictly a mempool initialisation, | ||
1064 | * but there is no harm in doing it here | ||
1065 | */ | ||
1066 | rpc_init_wait_queue(&delay_queue, "delayq"); | ||
1041 | return 0; | 1067 | return 0; |
1042 | err_nomem: | 1068 | err_nomem: |
1043 | rpc_destroy_mempool(); | 1069 | rpc_destroy_mempool(); |