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
|
/*
* linux/include/linux/sunrpc/svc.h
*
* RPC server declarations.
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
#ifndef SUNRPC_SVC_H
#define SUNRPC_SVC_H
#include <linux/sunrpc/types.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svcauth.h>
/*
* RPC service.
*
* An RPC service is a ``daemon,'' possibly multithreaded, which
* receives and processes incoming RPC messages.
* It has one or more transport sockets associated with it, and maintains
* a list of idle threads waiting for input.
*
* We currently do not support more than one RPC program per daemon.
*/
struct svc_serv {
struct svc_rqst * sv_threads; /* idle server threads */
struct svc_sock * sv_sockets; /* pending sockets */
struct svc_program * sv_program; /* RPC program */
struct svc_stat * sv_stats; /* RPC statistics */
unsigned int sv_nrthreads; /* # of server threads */
unsigned int sv_bufsz; /* datagram buffer size */
unsigned int sv_xdrsize; /* XDR buffer size */
struct svc_sock * sv_allsocks; /* all sockets */
char * sv_name; /* service name */
};
/*
* Maximum payload size supported by a kernel RPC server.
* This is use to determine the max number of pages nfsd is
* willing to return in a single READ operation.
*/
#define RPCSVC_MAXPAYLOAD 16384u
/*
* Buffer to store RPC requests or replies in.
* Each server thread has one of these beasts.
*
* Area points to the allocated memory chunk currently owned by the
* buffer. Base points to the buffer containing the request, which is
* different from area when directly reading from an sk_buff. buf is
* the current read/write position while processing an RPC request.
*
* The array of iovecs can hold additional data that the server process
* may not want to copy into the RPC reply buffer, but pass to the
* network sendmsg routines directly. The prime candidate for this
* will of course be NFS READ operations, but one might also want to
* do something about READLINK and READDIR. It might be worthwhile
* to implement some generic readdir cache in the VFS layer...
*
* On the receiving end of the RPC server, the iovec may be used to hold
* the list of IP fragments once we get to process fragmented UDP
* datagrams directly.
*/
#define RPCSVC_MAXIOV ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE + 1)
struct svc_buf {
u32 * area; /* allocated memory */
u32 * base; /* base of RPC datagram */
int buflen; /* total length of buffer */
u32 * buf; /* read/write pointer */
int len; /* current end of buffer */
/* iovec for zero-copy NFS READs */
struct iovec iov[RPCSVC_MAXIOV];
int nriov;
};
#define svc_getlong(argp, val) { (val) = *(argp)->buf++; (argp)->len--; }
#define svc_putlong(resp, val) { *(resp)->buf++ = (val); (resp)->len++; }
/*
* The context of a single thread, including the request currently being
* processed.
* NOTE: First two items must be prev/next.
*/
struct svc_rqst {
struct svc_rqst * rq_prev; /* idle list */
struct svc_rqst * rq_next;
struct svc_sock * rq_sock; /* socket */
struct sockaddr_in rq_addr; /* peer address */
int rq_addrlen;
struct svc_serv * rq_server; /* RPC service definition */
struct svc_procedure * rq_procinfo; /* procedure info */
struct svc_cred rq_cred; /* auth info */
struct sk_buff * rq_skbuff; /* fast recv inet buffer */
struct svc_buf rq_defbuf; /* default buffer */
struct svc_buf rq_argbuf; /* argument buffer */
struct svc_buf rq_resbuf; /* result buffer */
u32 rq_xid; /* transmission id */
u32 rq_prog; /* program number */
u32 rq_vers; /* program version */
u32 rq_proc; /* procedure number */
u32 rq_prot; /* IP protocol */
unsigned short rq_verfed : 1, /* reply has verifier */
rq_userset : 1, /* auth->setuser OK */
rq_secure : 1, /* secure port */
rq_auth : 1; /* check client */
void * rq_argp; /* decoded arguments */
void * rq_resp; /* xdr'd results */
/* Catering to nfsd */
struct svc_client * rq_client; /* RPC peer info */
struct svc_cacherep * rq_cacherep; /* cache info */
struct wait_queue * rq_wait; /* synchronozation */
};
/*
* RPC program
*/
struct svc_program {
u32 pg_prog; /* program number */
unsigned int pg_lovers; /* lowest version */
unsigned int pg_hivers; /* lowest version */
unsigned int pg_nvers; /* number of versions */
struct svc_version ** pg_vers; /* version array */
char * pg_name; /* service name */
struct svc_stat * pg_stats; /* rpc statistics */
};
/*
* RPC program version
*/
struct svc_version {
u32 vs_vers; /* version number */
u32 vs_nproc; /* number of procedures */
struct svc_procedure * vs_proc; /* per-procedure info */
/* Override dispatch function (e.g. when caching replies).
* A return value of 0 means drop the request.
* vs_dispatch == NULL means use default dispatcher.
*/
int (*vs_dispatch)(struct svc_rqst *, u32 *);
};
/*
* RPC procedure info
*/
typedef int (*svc_procfunc)(struct svc_rqst *, void *argp, void *resp);
struct svc_procedure {
svc_procfunc pc_func; /* process the request */
kxdrproc_t pc_decode; /* XDR decode args */
kxdrproc_t pc_encode; /* XDR encode result */
kxdrproc_t pc_release; /* XDR free result */
unsigned int pc_argsize; /* argument struct size */
unsigned int pc_ressize; /* result struct size */
unsigned int pc_count; /* call count */
unsigned int pc_cachetype; /* cache info (NFS) */
};
/*
* This is the RPC server thread function prototype
*/
typedef void (*svc_thread_fn)(struct svc_rqst *);
/*
* Function prototypes.
*/
struct svc_serv * svc_create(struct svc_program *, unsigned int, unsigned int);
int svc_create_thread(svc_thread_fn, struct svc_serv *);
void svc_exit_thread(struct svc_rqst *);
void svc_destroy(struct svc_serv *);
int svc_process(struct svc_serv *, struct svc_rqst *);
int svc_register(struct svc_serv *, int, unsigned short);
void svc_wake_up(struct svc_serv *);
#endif /* SUNRPC_SVC_H */
|