summaryrefslogtreecommitdiffstats
path: root/include/linux/sunrpc/sched.h
blob: 279636434e74a61f647f61517395f3355507583f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
 * linux/include/linux/sunrpc/sched.h
 *
 * Scheduling primitives for kernel Sun RPC.
 *
 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
 */

#ifndef _LINUX_SUNRPC_SCHED_H_
#define _LINUX_SUNRPC_SCHED_H_

#include <linux/timer.h>
#include <linux/tqueue.h>
#include <linux/sunrpc/types.h>
#include <linux/wait.h>

/*
 * Define this if you want to test the fast scheduler for async calls.
 * This is still experimental and may not work.
 */
#undef  CONFIG_RPC_FASTSCHED

/*
 * This is the actual RPC procedure call info.
 */
struct rpc_message {
	__u32			rpc_proc;	/* Procedure number */
	void *			rpc_argp;	/* Arguments */
	void *			rpc_resp;	/* Result */
	struct rpc_cred *	rpc_cred;	/* Credentials */
};

/*
 * This is the RPC task struct
 */
struct rpc_task {
	struct rpc_task *	tk_prev;	/* wait queue links */
	struct rpc_task *	tk_next;
#ifdef RPC_DEBUG
	unsigned long		tk_magic;	/* 0xf00baa */
#endif
	struct rpc_task *	tk_next_task;	/* global list of tasks */
	struct rpc_task *	tk_prev_task;	/* global list of tasks */
	struct rpc_clnt *	tk_client;	/* RPC client */
	struct rpc_rqst *	tk_rqstp;	/* RPC request */
	int			tk_status;	/* result of last operation */
	struct rpc_wait_queue *	tk_rpcwait;	/* RPC wait queue we're on */

	/*
	 * RPC call state
	 */
	struct rpc_message	tk_msg;		/* RPC call info */
	__u32 *			tk_buffer;	/* XDR buffer */
	__u8			tk_garb_retry,
				tk_cred_retry,
				tk_suid_retry;

	/*
	 * callback	to be executed after waking up
	 * action	next procedure for async tasks
	 * exit		exit async task and report to caller
	 */
	void			(*tk_callback)(struct rpc_task *);
	void			(*tk_action)(struct rpc_task *);
	void			(*tk_exit)(struct rpc_task *);
	void *			tk_calldata;

	/*
	 * tk_timer is used for async processing by the RPC scheduling
	 * primitives. You should not access this directly unless
	 * you have a pathological interest in kernel oopses.
	 */
	struct timer_list	tk_timer;	/* kernel timer */
	wait_queue_head_t	tk_wait;	/* sync: sleep on this q */
	unsigned long		tk_timeout;	/* timeout for rpc_sleep() */
	unsigned short		tk_flags;	/* misc flags */
	unsigned short		tk_lock;	/* Task lock counter */
	unsigned int		tk_wakeup   : 1,/* Task waiting to wake up */
				tk_sleeping : 1,/* Task is truly asleep */
				tk_active   : 1;/* Task has been activated */
#ifdef RPC_DEBUG
	unsigned short		tk_pid;		/* debugging aid */
#endif
};
#define tk_auth			tk_client->cl_auth
#define tk_xprt			tk_client->cl_xprt

typedef void			(*rpc_action)(struct rpc_task *);

/*
 * RPC task flags
 */
#define RPC_TASK_RUNNING	0x0001		/* is running */
#define RPC_TASK_ASYNC		0x0002		/* is an async task */
#define RPC_TASK_CALLBACK	0x0004		/* invoke callback */
#define RPC_TASK_SWAPPER	0x0008		/* is swapping in/out */
#define RPC_TASK_SETUID		0x0010		/* is setuid process */
#define RPC_TASK_CHILD		0x0020		/* is child of other task */
#define RPC_CALL_REALUID	0x0040		/* try using real uid */
#define RPC_CALL_MAJORSEEN	0x0080		/* major timeout seen */
#define RPC_TASK_ROOTCREDS	0x0100		/* force root creds */
#define RPC_TASK_DYNAMIC	0x0200		/* task was kmalloc'ed */
#define RPC_TASK_KILLED		0x0400		/* task was killed */
#define RPC_TASK_NFSWRITE	0x1000		/* an NFS writeback */

#define RPC_IS_RUNNING(t)	((t)->tk_flags & RPC_TASK_RUNNING)
#define RPC_IS_ASYNC(t)		((t)->tk_flags & RPC_TASK_ASYNC)
#define RPC_IS_SETUID(t)	((t)->tk_flags & RPC_TASK_SETUID)
#define RPC_IS_CHILD(t)		((t)->tk_flags & RPC_TASK_CHILD)
#define RPC_IS_SWAPPER(t)	((t)->tk_flags & RPC_TASK_SWAPPER)
#define RPC_DO_CALLBACK(t)	((t)->tk_flags & RPC_TASK_CALLBACK)
#define RPC_DO_ROOTOVERRIDE(t)	((t)->tk_flags & RPC_TASK_ROOTCREDS)
#define RPC_ASSASSINATED(t)	((t)->tk_flags & RPC_TASK_KILLED)
#define RPC_IS_SLEEPING(t)	((t)->tk_sleeping)
#define RPC_IS_ACTIVATED(t)	((t)->tk_active)

/*
 * RPC synchronization objects
 */
struct rpc_wait_queue {
	struct rpc_task *	task;
#ifdef RPC_DEBUG
	char *			name;
#endif
};

#ifndef RPC_DEBUG
# define RPC_INIT_WAITQ(name)	((struct rpc_wait_queue) { NULL })
#else
# define RPC_INIT_WAITQ(name)	((struct rpc_wait_queue) { NULL, name })
#endif

/*
 * Function prototypes
 */
struct rpc_task *rpc_new_task(struct rpc_clnt *, rpc_action, int flags);
struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent);
void		rpc_init_task(struct rpc_task *, struct rpc_clnt *,
					rpc_action exitfunc, int flags);
void		rpc_release_task(struct rpc_task *);
void		rpc_killall_tasks(struct rpc_clnt *);
int		rpc_execute(struct rpc_task *);
void		rpc_run_child(struct rpc_task *parent, struct rpc_task *child,
					rpc_action action);
int		rpc_add_wait_queue(struct rpc_wait_queue *, struct rpc_task *);
void		rpc_remove_wait_queue(struct rpc_task *);
void		rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *,
					rpc_action action, rpc_action timer);
void		rpc_sleep_locked(struct rpc_wait_queue *, struct rpc_task *,
				 rpc_action action, rpc_action timer);
void		rpc_add_timer(struct rpc_task *, rpc_action);
void		rpc_wake_up_task(struct rpc_task *);
void		rpc_wake_up(struct rpc_wait_queue *);
struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
void		rpc_wake_up_status(struct rpc_wait_queue *, int);
int		rpc_lock_task(struct rpc_task *);
void		rpc_unlock_task(struct rpc_task *);
void		rpc_delay(struct rpc_task *, unsigned long);
void *		rpc_allocate(unsigned int flags, unsigned int);
void		rpc_free(void *);
int		rpciod_up(void);
void		rpciod_down(void);
void		rpciod_wake_up(void);
#ifdef RPC_DEBUG
void		rpc_show_tasks(void);
#endif

extern __inline__ void *
rpc_malloc(struct rpc_task *task, unsigned int size)
{
	return rpc_allocate(task->tk_flags, size);
}

extern __inline__ void
rpc_exit(struct rpc_task *task, int status)
{
	task->tk_status = status;
	task->tk_action = NULL;
}

#ifdef RPC_DEBUG
extern __inline__ char *
rpc_qname(struct rpc_wait_queue *q)
{
	return q->name? q->name : "unknown";
}
#endif

#endif /* _LINUX_SUNRPC_SCHED_H_ */