diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-01-03 03:55:06 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-01-06 14:58:40 -0500 |
commit | 44c288732fdbd7e38460d156a40d29590bf93bce (patch) | |
tree | d4239fe37529b4799e85443f803db754ef66f874 /include | |
parent | 4ce70ada1ff1d0b80916ec9ec5764ce44a50a54f (diff) |
NFSv4: stateful NFSv4 RPC call interface
The NFSv4 model requires us to complete all RPC calls that might
establish state on the server whether or not the user wants to
interrupt it. We may also need to schedule new work (including
new RPC calls) in order to cancel the new state.
The asynchronous RPC model will allow us to ensure that RPC calls
always complete, but in order to allow for "synchronous" RPC, we
want to add the ability to wait for completion.
The waits are, of course, interruptible.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/sunrpc/sched.h | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index ac1326fc3e1a..94b0afa4ab05 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -42,6 +42,7 @@ struct rpc_task { | |||
42 | #ifdef RPC_DEBUG | 42 | #ifdef RPC_DEBUG |
43 | unsigned long tk_magic; /* 0xf00baa */ | 43 | unsigned long tk_magic; /* 0xf00baa */ |
44 | #endif | 44 | #endif |
45 | atomic_t tk_count; /* Reference count */ | ||
45 | struct list_head tk_task; /* global list of tasks */ | 46 | struct list_head tk_task; /* global list of tasks */ |
46 | struct rpc_clnt * tk_client; /* RPC client */ | 47 | struct rpc_clnt * tk_client; /* RPC client */ |
47 | struct rpc_rqst * tk_rqstp; /* RPC request */ | 48 | struct rpc_rqst * tk_rqstp; /* RPC request */ |
@@ -78,7 +79,6 @@ struct rpc_task { | |||
78 | struct timer_list tk_timer; /* kernel timer */ | 79 | struct timer_list tk_timer; /* kernel timer */ |
79 | unsigned long tk_timeout; /* timeout for rpc_sleep() */ | 80 | unsigned long tk_timeout; /* timeout for rpc_sleep() */ |
80 | unsigned short tk_flags; /* misc flags */ | 81 | unsigned short tk_flags; /* misc flags */ |
81 | unsigned char tk_active : 1;/* Task has been activated */ | ||
82 | unsigned char tk_priority : 2;/* Task priority */ | 82 | unsigned char tk_priority : 2;/* Task priority */ |
83 | unsigned long tk_runstate; /* Task run status */ | 83 | unsigned long tk_runstate; /* Task run status */ |
84 | struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could | 84 | struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could |
@@ -136,7 +136,6 @@ struct rpc_call_ops { | |||
136 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) | 136 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) |
137 | #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) | 137 | #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) |
138 | #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) | 138 | #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) |
139 | #define RPC_IS_ACTIVATED(t) ((t)->tk_active) | ||
140 | #define RPC_DO_CALLBACK(t) ((t)->tk_callback != NULL) | 139 | #define RPC_DO_CALLBACK(t) ((t)->tk_callback != NULL) |
141 | #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) | 140 | #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) |
142 | #define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR) | 141 | #define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR) |
@@ -145,6 +144,7 @@ struct rpc_call_ops { | |||
145 | #define RPC_TASK_QUEUED 1 | 144 | #define RPC_TASK_QUEUED 1 |
146 | #define RPC_TASK_WAKEUP 2 | 145 | #define RPC_TASK_WAKEUP 2 |
147 | #define RPC_TASK_HAS_TIMER 3 | 146 | #define RPC_TASK_HAS_TIMER 3 |
147 | #define RPC_TASK_ACTIVE 4 | ||
148 | 148 | ||
149 | #define RPC_IS_RUNNING(t) (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) | 149 | #define RPC_IS_RUNNING(t) (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) |
150 | #define rpc_set_running(t) (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) | 150 | #define rpc_set_running(t) (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) |
@@ -175,6 +175,15 @@ struct rpc_call_ops { | |||
175 | smp_mb__after_clear_bit(); \ | 175 | smp_mb__after_clear_bit(); \ |
176 | } while (0) | 176 | } while (0) |
177 | 177 | ||
178 | #define RPC_IS_ACTIVATED(t) (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)) | ||
179 | #define rpc_set_active(t) (set_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)) | ||
180 | #define rpc_clear_active(t) \ | ||
181 | do { \ | ||
182 | smp_mb__before_clear_bit(); \ | ||
183 | clear_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate); \ | ||
184 | smp_mb__after_clear_bit(); \ | ||
185 | } while(0) | ||
186 | |||
178 | /* | 187 | /* |
179 | * Task priorities. | 188 | * Task priorities. |
180 | * Note: if you change these, you must also change | 189 | * Note: if you change these, you must also change |
@@ -237,6 +246,8 @@ struct rpc_wait_queue { | |||
237 | */ | 246 | */ |
238 | struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, | 247 | struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, |
239 | const struct rpc_call_ops *ops, void *data); | 248 | const struct rpc_call_ops *ops, void *data); |
249 | struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, | ||
250 | const struct rpc_call_ops *ops, void *data); | ||
240 | struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); | 251 | struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); |
241 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, | 252 | void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, |
242 | int flags, const struct rpc_call_ops *ops, | 253 | int flags, const struct rpc_call_ops *ops, |
@@ -260,6 +271,7 @@ void * rpc_malloc(struct rpc_task *, size_t); | |||
260 | int rpciod_up(void); | 271 | int rpciod_up(void); |
261 | void rpciod_down(void); | 272 | void rpciod_down(void); |
262 | void rpciod_wake_up(void); | 273 | void rpciod_wake_up(void); |
274 | int __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *)); | ||
263 | #ifdef RPC_DEBUG | 275 | #ifdef RPC_DEBUG |
264 | void rpc_show_tasks(void); | 276 | void rpc_show_tasks(void); |
265 | #endif | 277 | #endif |
@@ -272,6 +284,11 @@ static inline void rpc_exit(struct rpc_task *task, int status) | |||
272 | task->tk_action = rpc_exit_task; | 284 | task->tk_action = rpc_exit_task; |
273 | } | 285 | } |
274 | 286 | ||
287 | static inline int rpc_wait_for_completion_task(struct rpc_task *task) | ||
288 | { | ||
289 | return __rpc_wait_for_completion_task(task, NULL); | ||
290 | } | ||
291 | |||
275 | #ifdef RPC_DEBUG | 292 | #ifdef RPC_DEBUG |
276 | static inline const char * rpc_qname(struct rpc_wait_queue *q) | 293 | static inline const char * rpc_qname(struct rpc_wait_queue *q) |
277 | { | 294 | { |