Rev 423 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
423 | giacomo | 1 | /* |
2 | * linux/include/linux/sunrpc/svc.h |
||
3 | * |
||
4 | * RPC server declarations. |
||
5 | * |
||
6 | * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> |
||
7 | */ |
||
8 | |||
9 | |||
10 | #ifndef SUNRPC_SVC_H |
||
11 | #define SUNRPC_SVC_H |
||
12 | |||
13 | #include <linux/in.h> |
||
14 | #include <linux/sunrpc/types.h> |
||
15 | #include <linux/sunrpc/xdr.h> |
||
16 | #include <linux/sunrpc/svcauth.h> |
||
17 | #include <linux/wait.h> |
||
18 | #include <linux/mm.h> |
||
19 | |||
20 | /* |
||
21 | * RPC service. |
||
22 | * |
||
23 | * An RPC service is a ``daemon,'' possibly multithreaded, which |
||
24 | * receives and processes incoming RPC messages. |
||
25 | * It has one or more transport sockets associated with it, and maintains |
||
26 | * a list of idle threads waiting for input. |
||
27 | * |
||
28 | * We currently do not support more than one RPC program per daemon. |
||
29 | */ |
||
30 | struct svc_serv { |
||
31 | struct list_head sv_threads; /* idle server threads */ |
||
32 | struct list_head sv_sockets; /* pending sockets */ |
||
33 | struct svc_program * sv_program; /* RPC program */ |
||
34 | struct svc_stat * sv_stats; /* RPC statistics */ |
||
35 | spinlock_t sv_lock; |
||
36 | unsigned int sv_nrthreads; /* # of server threads */ |
||
37 | unsigned int sv_bufsz; /* datagram buffer size */ |
||
38 | unsigned int sv_xdrsize; /* XDR buffer size */ |
||
39 | |||
40 | struct list_head sv_permsocks; /* all permanent sockets */ |
||
41 | struct list_head sv_tempsocks; /* all temporary sockets */ |
||
42 | int sv_tmpcnt; /* count of temporary sockets */ |
||
43 | |||
44 | char * sv_name; /* service name */ |
||
45 | }; |
||
46 | |||
47 | /* |
||
48 | * Maximum payload size supported by a kernel RPC server. |
||
49 | * This is use to determine the max number of pages nfsd is |
||
50 | * willing to return in a single READ operation. |
||
51 | */ |
||
52 | #define RPCSVC_MAXPAYLOAD (64*1024u) |
||
53 | |||
54 | /* |
||
55 | * RPC Requsts and replies are stored in one or more pages. |
||
56 | * We maintain an array of pages for each server thread. |
||
57 | * Requests are copied into these pages as they arrive. Remaining |
||
58 | * pages are available to write the reply into. |
||
59 | * |
||
60 | * Pages are sent using ->sendpage so each server thread needs to |
||
61 | * allocate more to replace those used in sending. To help keep track |
||
62 | * of these pages we have a receive list where all pages initialy live, |
||
63 | * and a send list where pages are moved to when there are to be part |
||
64 | * of a reply. |
||
65 | * |
||
66 | * We use xdr_buf for holding responses as it fits well with NFS |
||
67 | * read responses (that have a header, and some data pages, and possibly |
||
68 | * a tail) and means we can share some client side routines. |
||
69 | * |
||
70 | * The xdr_buf.head iovec always points to the first page in the rq_*pages |
||
71 | * list. The xdr_buf.pages pointer points to the second page on that |
||
72 | * list. xdr_buf.tail points to the end of the first page. |
||
73 | * This assumes that the non-page part of an rpc reply will fit |
||
74 | * in a page - NFSd ensures this. lockd also has no trouble. |
||
75 | * |
||
76 | * Each request/reply pair can have at most one "payload", plus two pages, |
||
77 | * one for the request, and one for the reply. |
||
78 | */ |
||
79 | #define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 2) |
||
80 | |||
81 | static inline u32 svc_getu32(struct iovec *iov) |
||
82 | { |
||
83 | u32 val, *vp; |
||
84 | vp = iov->iov_base; |
||
85 | val = *vp++; |
||
86 | iov->iov_base = (void*)vp; |
||
87 | iov->iov_len -= sizeof(u32); |
||
88 | return val; |
||
89 | } |
||
90 | static inline void svc_putu32(struct iovec *iov, u32 val) |
||
91 | { |
||
92 | u32 *vp = iov->iov_base + iov->iov_len; |
||
93 | *vp = val; |
||
94 | iov->iov_len += sizeof(u32); |
||
95 | } |
||
96 | |||
97 | |||
98 | /* |
||
99 | * The context of a single thread, including the request currently being |
||
100 | * processed. |
||
101 | * NOTE: First two items must be prev/next. |
||
102 | */ |
||
103 | struct svc_rqst { |
||
104 | struct list_head rq_list; /* idle list */ |
||
105 | struct svc_sock * rq_sock; /* socket */ |
||
106 | struct sockaddr_in rq_addr; /* peer address */ |
||
107 | int rq_addrlen; |
||
108 | |||
109 | struct svc_serv * rq_server; /* RPC service definition */ |
||
110 | struct svc_procedure * rq_procinfo; /* procedure info */ |
||
111 | struct auth_ops * rq_authop; /* authentication flavour */ |
||
112 | struct svc_cred rq_cred; /* auth info */ |
||
113 | struct sk_buff * rq_skbuff; /* fast recv inet buffer */ |
||
114 | struct svc_deferred_req*rq_deferred; /* deferred request we are replaying */ |
||
115 | |||
116 | struct xdr_buf rq_arg; |
||
117 | struct xdr_buf rq_res; |
||
118 | struct page * rq_argpages[RPCSVC_MAXPAGES]; |
||
119 | struct page * rq_respages[RPCSVC_MAXPAGES]; |
||
120 | int rq_restailpage; |
||
121 | short rq_argused; /* pages used for argument */ |
||
122 | short rq_arghi; /* pages available in argument page list */ |
||
123 | short rq_resused; /* pages used for result */ |
||
124 | |||
125 | u32 rq_xid; /* transmission id */ |
||
126 | u32 rq_prog; /* program number */ |
||
127 | u32 rq_vers; /* program version */ |
||
128 | u32 rq_proc; /* procedure number */ |
||
129 | u32 rq_prot; /* IP protocol */ |
||
130 | unsigned short |
||
131 | rq_secure : 1; /* secure port */ |
||
132 | |||
133 | |||
134 | __u32 rq_daddr; /* dest addr of request - reply from here */ |
||
135 | |||
136 | void * rq_argp; /* decoded arguments */ |
||
137 | void * rq_resp; /* xdr'd results */ |
||
138 | |||
139 | int rq_reserved; /* space on socket outq |
||
140 | * reserved for this request |
||
141 | */ |
||
142 | |||
143 | struct cache_req rq_chandle; /* handle passed to caches for |
||
144 | * request delaying |
||
145 | */ |
||
146 | /* Catering to nfsd */ |
||
147 | struct auth_domain * rq_client; /* RPC peer info */ |
||
148 | struct svc_cacherep * rq_cacherep; /* cache info */ |
||
149 | struct knfsd_fh * rq_reffh; /* Referrence filehandle, used to |
||
150 | * determine what device number |
||
151 | * to report (real or virtual) |
||
152 | */ |
||
153 | |||
154 | wait_queue_head_t rq_wait; /* synchronization */ |
||
155 | }; |
||
156 | |||
157 | /* |
||
158 | * Check buffer bounds after decoding arguments |
||
159 | */ |
||
160 | static inline int |
||
161 | xdr_argsize_check(struct svc_rqst *rqstp, u32 *p) |
||
162 | { |
||
163 | char *cp = (char *)p; |
||
164 | struct iovec *vec = &rqstp->rq_arg.head[0]; |
||
165 | return cp - (char*)vec->iov_base <= vec->iov_len; |
||
166 | } |
||
167 | |||
168 | static inline int |
||
169 | xdr_ressize_check(struct svc_rqst *rqstp, u32 *p) |
||
170 | { |
||
171 | struct iovec *vec = &rqstp->rq_res.head[0]; |
||
172 | char *cp = (char*)p; |
||
173 | |||
174 | vec->iov_len = cp - (char*)vec->iov_base; |
||
175 | |||
176 | return vec->iov_len <= PAGE_SIZE; |
||
177 | } |
||
178 | |||
179 | static inline int svc_take_page(struct svc_rqst *rqstp) |
||
180 | { |
||
181 | if (rqstp->rq_arghi <= rqstp->rq_argused) |
||
182 | return -ENOMEM; |
||
183 | rqstp->rq_arghi--; |
||
184 | rqstp->rq_respages[rqstp->rq_resused] = |
||
185 | rqstp->rq_argpages[rqstp->rq_arghi]; |
||
186 | rqstp->rq_resused++; |
||
187 | return 0; |
||
188 | } |
||
189 | |||
190 | static inline void svc_pushback_allpages(struct svc_rqst *rqstp) |
||
191 | { |
||
192 | while (rqstp->rq_resused) { |
||
193 | if (rqstp->rq_respages[--rqstp->rq_resused] == NULL) |
||
194 | continue; |
||
195 | rqstp->rq_argpages[rqstp->rq_arghi++] = |
||
196 | rqstp->rq_respages[rqstp->rq_resused]; |
||
197 | rqstp->rq_respages[rqstp->rq_resused] = NULL; |
||
198 | } |
||
199 | } |
||
200 | |||
201 | static inline void svc_pushback_unused_pages(struct svc_rqst *rqstp) |
||
202 | { |
||
203 | while (rqstp->rq_resused && |
||
204 | rqstp->rq_res.pages != &rqstp->rq_respages[rqstp->rq_resused]) { |
||
205 | |||
206 | if (rqstp->rq_respages[--rqstp->rq_resused] != NULL) { |
||
207 | rqstp->rq_argpages[rqstp->rq_arghi++] = |
||
208 | rqstp->rq_respages[rqstp->rq_resused]; |
||
209 | rqstp->rq_respages[rqstp->rq_resused] = NULL; |
||
210 | } |
||
211 | } |
||
212 | } |
||
213 | |||
214 | static inline void svc_free_allpages(struct svc_rqst *rqstp) |
||
215 | { |
||
216 | while (rqstp->rq_resused) { |
||
217 | if (rqstp->rq_respages[--rqstp->rq_resused] == NULL) |
||
218 | continue; |
||
219 | put_page(rqstp->rq_respages[rqstp->rq_resused]); |
||
220 | rqstp->rq_respages[rqstp->rq_resused] = NULL; |
||
221 | } |
||
222 | } |
||
223 | |||
224 | struct svc_deferred_req { |
||
225 | u32 prot; /* protocol (UDP or TCP) */ |
||
226 | struct sockaddr_in addr; |
||
227 | struct svc_sock *svsk; /* where reply must go */ |
||
228 | struct cache_deferred_req handle; |
||
229 | int argslen; |
||
230 | u32 args[0]; |
||
231 | }; |
||
232 | |||
233 | /* |
||
234 | * RPC program |
||
235 | */ |
||
236 | struct svc_program { |
||
237 | u32 pg_prog; /* program number */ |
||
238 | unsigned int pg_lovers; /* lowest version */ |
||
239 | unsigned int pg_hivers; /* lowest version */ |
||
240 | unsigned int pg_nvers; /* number of versions */ |
||
241 | struct svc_version ** pg_vers; /* version array */ |
||
242 | char * pg_name; /* service name */ |
||
243 | char * pg_class; /* class name: services sharing authentication */ |
||
244 | struct svc_stat * pg_stats; /* rpc statistics */ |
||
245 | }; |
||
246 | |||
247 | /* |
||
248 | * RPC program version |
||
249 | */ |
||
250 | struct svc_version { |
||
251 | u32 vs_vers; /* version number */ |
||
252 | u32 vs_nproc; /* number of procedures */ |
||
253 | struct svc_procedure * vs_proc; /* per-procedure info */ |
||
254 | u32 vs_xdrsize; /* xdrsize needed for this version */ |
||
255 | |||
256 | /* Override dispatch function (e.g. when caching replies). |
||
257 | * A return value of 0 means drop the request. |
||
258 | * vs_dispatch == NULL means use default dispatcher. |
||
259 | */ |
||
260 | int (*vs_dispatch)(struct svc_rqst *, u32 *); |
||
261 | }; |
||
262 | |||
263 | /* |
||
264 | * RPC procedure info |
||
265 | */ |
||
266 | typedef int (*svc_procfunc)(struct svc_rqst *, void *argp, void *resp); |
||
267 | struct svc_procedure { |
||
268 | svc_procfunc pc_func; /* process the request */ |
||
269 | kxdrproc_t pc_decode; /* XDR decode args */ |
||
270 | kxdrproc_t pc_encode; /* XDR encode result */ |
||
271 | kxdrproc_t pc_release; /* XDR free result */ |
||
272 | unsigned int pc_argsize; /* argument struct size */ |
||
273 | unsigned int pc_ressize; /* result struct size */ |
||
274 | unsigned int pc_count; /* call count */ |
||
275 | unsigned int pc_cachetype; /* cache info (NFS) */ |
||
276 | unsigned int pc_xdrressize; /* maximum size of XDR reply */ |
||
277 | }; |
||
278 | |||
279 | /* |
||
280 | * This is the RPC server thread function prototype |
||
281 | */ |
||
282 | typedef void (*svc_thread_fn)(struct svc_rqst *); |
||
283 | |||
284 | /* |
||
285 | * Function prototypes. |
||
286 | */ |
||
287 | struct svc_serv * svc_create(struct svc_program *, unsigned int); |
||
288 | int svc_create_thread(svc_thread_fn, struct svc_serv *); |
||
289 | void svc_exit_thread(struct svc_rqst *); |
||
290 | void svc_destroy(struct svc_serv *); |
||
291 | int svc_process(struct svc_serv *, struct svc_rqst *); |
||
292 | int svc_register(struct svc_serv *, int, unsigned short); |
||
293 | void svc_wake_up(struct svc_serv *); |
||
294 | void svc_reserve(struct svc_rqst *rqstp, int space); |
||
295 | |||
296 | #endif /* SUNRPC_SVC_H */ |