ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / include / linux / sunrpc / sched.h
1 /*
2  * linux/include/linux/sunrpc/sched.h
3  *
4  * Scheduling primitives for kernel Sun RPC.
5  *
6  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #ifndef _LINUX_SUNRPC_SCHED_H_
10 #define _LINUX_SUNRPC_SCHED_H_
11
12 #include <linux/timer.h>
13 #include <linux/sunrpc/types.h>
14 #include <linux/wait.h>
15 #include <linux/sunrpc/xdr.h>
16
17 /*
18  * This is the actual RPC procedure call info.
19  */
20 struct rpc_procinfo;
21 struct rpc_message {
22         struct rpc_procinfo *   rpc_proc;       /* Procedure information */
23         void *                  rpc_argp;       /* Arguments */
24         void *                  rpc_resp;       /* Result */
25         struct rpc_cred *       rpc_cred;       /* Credentials */
26 };
27
28 /*
29  * This is the RPC task struct
30  */
31 struct rpc_task {
32         struct list_head        tk_list;        /* wait queue links */
33 #ifdef RPC_DEBUG
34         unsigned long           tk_magic;       /* 0xf00baa */
35 #endif
36         struct list_head        tk_task;        /* global list of tasks */
37         struct rpc_clnt *       tk_client;      /* RPC client */
38         struct rpc_rqst *       tk_rqstp;       /* RPC request */
39         int                     tk_status;      /* result of last operation */
40         struct rpc_wait_queue * tk_rpcwait;     /* RPC wait queue we're on */
41
42         /*
43          * RPC call state
44          */
45         struct rpc_message      tk_msg;         /* RPC call info */
46         __u32 *                 tk_buffer;      /* XDR buffer */
47         size_t                  tk_bufsize;
48         __u8                    tk_garb_retry,
49                                 tk_cred_retry,
50                                 tk_suid_retry;
51
52         unsigned long           tk_cookie;      /* Cookie for batching tasks */
53
54         /*
55          * timeout_fn   to be executed by timer bottom half
56          * callback     to be executed after waking up
57          * action       next procedure for async tasks
58          * exit         exit async task and report to caller
59          */
60         void                    (*tk_timeout_fn)(struct rpc_task *);
61         void                    (*tk_callback)(struct rpc_task *);
62         void                    (*tk_action)(struct rpc_task *);
63         void                    (*tk_exit)(struct rpc_task *);
64         void                    (*tk_release)(struct rpc_task *);
65         void *                  tk_calldata;
66
67         /*
68          * tk_timer is used for async processing by the RPC scheduling
69          * primitives. You should not access this directly unless
70          * you have a pathological interest in kernel oopses.
71          */
72         struct timer_list       tk_timer;       /* kernel timer */
73         wait_queue_head_t       tk_wait;        /* sync: sleep on this q */
74         unsigned long           tk_timeout;     /* timeout for rpc_sleep() */
75         unsigned short          tk_flags;       /* misc flags */
76         unsigned char           tk_active   : 1;/* Task has been activated */
77         unsigned char           tk_priority : 2;/* Task priority */
78         unsigned long           tk_runstate;    /* Task run status */
79         struct list_head        tk_links;       /* links to related tasks */
80 #ifdef RPC_DEBUG
81         unsigned short          tk_pid;         /* debugging aid */
82 #endif
83 };
84 #define tk_auth                 tk_client->cl_auth
85 #define tk_xprt                 tk_client->cl_xprt
86
87 /* support walking a list of tasks on a wait queue */
88 #define task_for_each(task, pos, head) \
89         list_for_each(pos, head) \
90                 if ((task=list_entry(pos, struct rpc_task, tk_list)),1)
91
92 #define task_for_first(task, head) \
93         if (!list_empty(head) &&  \
94             ((task=list_entry((head)->next, struct rpc_task, tk_list)),1))
95
96 /* .. and walking list of all tasks */
97 #define alltask_for_each(task, pos, head) \
98         list_for_each(pos, head) \
99                 if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
100
101 typedef void                    (*rpc_action)(struct rpc_task *);
102
103 /*
104  * RPC task flags
105  */
106 #define RPC_TASK_ASYNC          0x0001          /* is an async task */
107 #define RPC_TASK_SWAPPER        0x0002          /* is swapping in/out */
108 #define RPC_TASK_SETUID         0x0004          /* is setuid process */
109 #define RPC_TASK_CHILD          0x0008          /* is child of other task */
110 #define RPC_CALL_REALUID        0x0010          /* try using real uid */
111 #define RPC_CALL_MAJORSEEN      0x0020          /* major timeout seen */
112 #define RPC_TASK_ROOTCREDS      0x0040          /* force root creds */
113 #define RPC_TASK_DYNAMIC        0x0080          /* task was kmalloc'ed */
114 #define RPC_TASK_KILLED         0x0100          /* task was killed */
115 #define RPC_TASK_SOFT           0x0200          /* Use soft timeouts */
116
117 #define RPC_IS_ASYNC(t)         ((t)->tk_flags & RPC_TASK_ASYNC)
118 #define RPC_IS_SETUID(t)        ((t)->tk_flags & RPC_TASK_SETUID)
119 #define RPC_IS_CHILD(t)         ((t)->tk_flags & RPC_TASK_CHILD)
120 #define RPC_IS_SWAPPER(t)       ((t)->tk_flags & RPC_TASK_SWAPPER)
121 #define RPC_DO_ROOTOVERRIDE(t)  ((t)->tk_flags & RPC_TASK_ROOTCREDS)
122 #define RPC_ASSASSINATED(t)     ((t)->tk_flags & RPC_TASK_KILLED)
123 #define RPC_IS_ACTIVATED(t)     ((t)->tk_active)
124 #define RPC_DO_CALLBACK(t)      ((t)->tk_callback != NULL)
125 #define RPC_IS_SOFT(t)          ((t)->tk_flags & RPC_TASK_SOFT)
126
127 #define RPC_TASK_SLEEPING       0
128 #define RPC_TASK_RUNNING        1
129 #define RPC_IS_SLEEPING(t)      (test_bit(RPC_TASK_SLEEPING, &(t)->tk_runstate))
130 #define RPC_IS_RUNNING(t)       (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
131
132 #define rpc_set_running(t)      (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
133 #define rpc_clear_running(t)    (clear_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
134
135 #define rpc_set_sleeping(t)     (set_bit(RPC_TASK_SLEEPING, &(t)->tk_runstate))
136
137 #define rpc_clear_sleeping(t) \
138         do { \
139                 smp_mb__before_clear_bit(); \
140                 clear_bit(RPC_TASK_SLEEPING, &(t)->tk_runstate); \
141                 smp_mb__after_clear_bit(); \
142         } while(0)
143
144 /*
145  * Task priorities.
146  * Note: if you change these, you must also change
147  * the task initialization definitions below.
148  */
149 #define RPC_PRIORITY_LOW        0
150 #define RPC_PRIORITY_NORMAL     1
151 #define RPC_PRIORITY_HIGH       2
152 #define RPC_NR_PRIORITY         (RPC_PRIORITY_HIGH+1)
153
154 /*
155  * RPC synchronization objects
156  */
157 struct rpc_wait_queue {
158         struct list_head        tasks[RPC_NR_PRIORITY]; /* task queue for each priority level */
159         unsigned long           cookie;                 /* cookie of last task serviced */
160         unsigned char           maxpriority;            /* maximum priority (0 if queue is not a priority queue) */
161         unsigned char           priority;               /* current priority */
162         unsigned char           count;                  /* # task groups remaining serviced so far */
163         unsigned char           nr;                     /* # tasks remaining for cookie */
164 #ifdef RPC_DEBUG
165         const char *            name;
166 #endif
167 };
168
169 /*
170  * This is the # requests to send consecutively
171  * from a single cookie.  The aim is to improve
172  * performance of NFS operations such as read/write.
173  */
174 #define RPC_BATCH_COUNT                 16
175
176 #ifndef RPC_DEBUG
177 # define RPC_WAITQ_INIT(var,qname) { \
178                 .tasks = { \
179                         [0] = LIST_HEAD_INIT(var.tasks[0]), \
180                         [1] = LIST_HEAD_INIT(var.tasks[1]), \
181                         [2] = LIST_HEAD_INIT(var.tasks[2]), \
182                 }, \
183         }
184 #else
185 # define RPC_WAITQ_INIT(var,qname) { \
186                 .tasks = { \
187                         [0] = LIST_HEAD_INIT(var.tasks[0]), \
188                         [1] = LIST_HEAD_INIT(var.tasks[1]), \
189                         [2] = LIST_HEAD_INIT(var.tasks[2]), \
190                 }, \
191                 .name = qname, \
192         }
193 #endif
194 # define RPC_WAITQ(var,qname)      struct rpc_wait_queue var = RPC_WAITQ_INIT(var,qname)
195
196 #define RPC_IS_PRIORITY(q)              ((q)->maxpriority > 0)
197
198 /*
199  * Function prototypes
200  */
201 struct rpc_task *rpc_new_task(struct rpc_clnt *, rpc_action, int flags);
202 struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent);
203 void            rpc_init_task(struct rpc_task *, struct rpc_clnt *,
204                                         rpc_action exitfunc, int flags);
205 void            rpc_release_task(struct rpc_task *);
206 void            rpc_killall_tasks(struct rpc_clnt *);
207 int             rpc_execute(struct rpc_task *);
208 void            rpc_run_child(struct rpc_task *parent, struct rpc_task *child,
209                                         rpc_action action);
210 int             rpc_add_wait_queue(struct rpc_wait_queue *, struct rpc_task *);
211 void            rpc_remove_wait_queue(struct rpc_task *);
212 void            rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
213 void            rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
214 void            rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
215                                         rpc_action action, rpc_action timer);
216 void            rpc_add_timer(struct rpc_task *, rpc_action);
217 void            rpc_wake_up_task(struct rpc_task *);
218 void            rpc_wake_up(struct rpc_wait_queue *);
219 struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
220 void            rpc_wake_up_status(struct rpc_wait_queue *, int);
221 void            rpc_delay(struct rpc_task *, unsigned long);
222 void *          rpc_malloc(struct rpc_task *, size_t);
223 void            rpc_free(struct rpc_task *);
224 int             rpciod_up(void);
225 void            rpciod_down(void);
226 void            rpciod_wake_up(void);
227 #ifdef RPC_DEBUG
228 void            rpc_show_tasks(void);
229 #endif
230 int             rpc_init_mempool(void);
231 void            rpc_destroy_mempool(void);
232
233 static inline void rpc_exit(struct rpc_task *task, int status)
234 {
235         task->tk_status = status;
236         task->tk_action = NULL;
237 }
238
239 #ifdef RPC_DEBUG
240 static inline const char * rpc_qname(struct rpc_wait_queue *q)
241 {
242         return ((q && q->name) ? q->name : "unknown");
243 }
244 #endif
245
246 #endif /* _LINUX_SUNRPC_SCHED_H_ */