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/tqueue.h> 14#include <linux/sunrpc/types.h> 15#include <linux/wait.h> 16 17/* 18 * Define this if you want to test the fast scheduler for async calls. 19 * This is still experimental and may not work. 20 */ 21#undef CONFIG_RPC_FASTSCHED 22 23/* 24 * This is the actual RPC procedure call info. 25 */ 26struct rpc_message { 27 __u32 rpc_proc; /* Procedure number */ 28 void * rpc_argp; /* Arguments */ 29 void * rpc_resp; /* Result */ 30 struct rpc_cred * rpc_cred; /* Credentials */ 31}; 32 33/* 34 * This is the RPC task struct 35 */ 36struct rpc_task { 37 struct list_head tk_list; /* wait queue links */ 38#ifdef RPC_DEBUG 39 unsigned long tk_magic; /* 0xf00baa */ 40#endif 41 struct list_head tk_task; /* global list of tasks */ 42 struct rpc_clnt * tk_client; /* RPC client */ 43 struct rpc_rqst * tk_rqstp; /* RPC request */ 44 int tk_status; /* result of last operation */ 45 struct rpc_wait_queue * tk_rpcwait; /* RPC wait queue we're on */ 46 47 /* 48 * RPC call state 49 */ 50 struct rpc_message tk_msg; /* RPC call info */ 51 __u32 * tk_buffer; /* XDR buffer */ 52 __u8 tk_garb_retry, 53 tk_cred_retry, 54 tk_suid_retry; 55 56 /* 57 * timeout_fn to be executed by timer bottom half 58 * callback to be executed after waking up 59 * action next procedure for async tasks 60 * exit exit async task and report to caller 61 */ 62 void (*tk_timeout_fn)(struct rpc_task *); 63 void (*tk_callback)(struct rpc_task *); 64 void (*tk_action)(struct rpc_task *); 65 void (*tk_exit)(struct rpc_task *); 66 void (*tk_release)(struct rpc_task *); 67 void * tk_calldata; 68 69 /* 70 * tk_timer is used for async processing by the RPC scheduling 71 * primitives. You should not access this directly unless 72 * you have a pathological interest in kernel oopses. 73 */ 74 struct timer_list tk_timer; /* kernel timer */ 75 wait_queue_head_t tk_wait; /* sync: sleep on this q */ 76 unsigned long tk_timeout; /* timeout for rpc_sleep() */ 77 unsigned short tk_flags; /* misc flags */ 78 unsigned char tk_active : 1;/* Task has been activated */ 79 unsigned long tk_runstate; /* Task run status */ 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 101typedef 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 116#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) 117#define RPC_IS_SETUID(t) ((t)->tk_flags & RPC_TASK_SETUID) 118#define RPC_IS_CHILD(t) ((t)->tk_flags & RPC_TASK_CHILD) 119#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) 120#define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) 121#define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) 122#define RPC_IS_ACTIVATED(t) ((t)->tk_active) 123#define RPC_DO_CALLBACK(t) ((t)->tk_callback != NULL) 124 125#define RPC_TASK_SLEEPING 0 126#define RPC_TASK_RUNNING 1 127#define RPC_IS_SLEEPING(t) (test_bit(RPC_TASK_SLEEPING, &(t)->tk_runstate)) 128#define RPC_IS_RUNNING(t) (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) 129 130#define rpc_set_running(t) (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) 131#define rpc_clear_running(t) (clear_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) 132 133#define rpc_set_sleeping(t) (set_bit(RPC_TASK_SLEEPING, &(t)->tk_runstate)) 134 135#define rpc_clear_sleeping(t) \ 136 do { \ 137 smp_mb__before_clear_bit(); \ 138 clear_bit(RPC_TASK_SLEEPING, &(t)->tk_runstate); \ 139 smp_mb__after_clear_bit(); \ 140 } while(0) 141 142/* 143 * RPC synchronization objects 144 */ 145struct rpc_wait_queue { 146 struct list_head tasks; 147#ifdef RPC_DEBUG 148 char * name; 149#endif 150}; 151 152#ifndef RPC_DEBUG 153# define RPC_WAITQ_INIT(var,qname) ((struct rpc_wait_queue) {LIST_HEAD_INIT(var)}) 154# define RPC_WAITQ(var,qname) struct rpc_wait_queue var = RPC_WAITQ_INIT(var.tasks,qname) 155# define INIT_RPC_WAITQ(ptr,qname) do { \ 156 INIT_LIST_HEAD(&(ptr)->tasks); \ 157 } while(0) 158#else 159# define RPC_WAITQ_INIT(var,qname) ((struct rpc_wait_queue) {LIST_HEAD_INIT(var.tasks), qname}) 160# define RPC_WAITQ(var,qname) struct rpc_wait_queue var = RPC_WAITQ_INIT(var,qname) 161# define INIT_RPC_WAITQ(ptr,qname) do { \ 162 INIT_LIST_HEAD(&(ptr)->tasks); (ptr)->name = qname; \ 163 } while(0) 164#endif 165 166/* 167 * Function prototypes 168 */ 169struct rpc_task *rpc_new_task(struct rpc_clnt *, rpc_action, int flags); 170struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); 171void rpc_init_task(struct rpc_task *, struct rpc_clnt *, 172 rpc_action exitfunc, int flags); 173void rpc_release_task(struct rpc_task *); 174void rpc_killall_tasks(struct rpc_clnt *); 175int rpc_execute(struct rpc_task *); 176void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, 177 rpc_action action); 178int rpc_add_wait_queue(struct rpc_wait_queue *, struct rpc_task *); 179void rpc_remove_wait_queue(struct rpc_task *); 180void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *, 181 rpc_action action, rpc_action timer); 182void rpc_add_timer(struct rpc_task *, rpc_action); 183void rpc_wake_up_task(struct rpc_task *); 184void rpc_wake_up(struct rpc_wait_queue *); 185struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *); 186void rpc_wake_up_status(struct rpc_wait_queue *, int); 187void rpc_delay(struct rpc_task *, unsigned long); 188void * rpc_allocate(unsigned int flags, unsigned int); 189void rpc_free(void *); 190int rpciod_up(void); 191void rpciod_down(void); 192void rpciod_wake_up(void); 193#ifdef RPC_DEBUG 194void rpc_show_tasks(void); 195#endif 196 197static __inline__ void * 198rpc_malloc(struct rpc_task *task, unsigned int size) 199{ 200 return rpc_allocate(task->tk_flags, size); 201} 202 203static __inline__ void 204rpc_exit(struct rpc_task *task, int status) 205{ 206 task->tk_status = status; 207 task->tk_action = NULL; 208} 209 210#ifdef RPC_DEBUG 211static __inline__ char * 212rpc_qname(struct rpc_wait_queue *q) 213{ 214 return q->name? q->name : "unknown"; 215} 216#endif 217 218#endif /* _LINUX_SUNRPC_SCHED_H_ */ 219