Commit 09662d58d5a2d75c8c29558dda4fc5134ef14b25

Authored by Jeff Layton
Committed by J. Bruce Fields
1 parent 6dc8889589

nfsd: get rid of RC_INTR

The reply cache code never returns this status.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

Showing 2 changed files with 1 additions and 3 deletions Inline Diff

1 /* 1 /*
2 * Request reply cache. This was heavily inspired by the 2 * Request reply cache. This was heavily inspired by the
3 * implementation in 4.3BSD/4.4BSD. 3 * implementation in 4.3BSD/4.4BSD.
4 * 4 *
5 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 5 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
6 */ 6 */
7 7
8 #ifndef NFSCACHE_H 8 #ifndef NFSCACHE_H
9 #define NFSCACHE_H 9 #define NFSCACHE_H
10 10
11 #include <linux/sunrpc/svc.h> 11 #include <linux/sunrpc/svc.h>
12 12
13 /* 13 /*
14 * Representation of a reply cache entry. 14 * Representation of a reply cache entry.
15 * 15 *
16 * Note that we use a sockaddr_in6 to hold the address instead of the more 16 * Note that we use a sockaddr_in6 to hold the address instead of the more
17 * typical sockaddr_storage. This is for space reasons, since sockaddr_storage 17 * typical sockaddr_storage. This is for space reasons, since sockaddr_storage
18 * is much larger than a sockaddr_in6. 18 * is much larger than a sockaddr_in6.
19 */ 19 */
20 struct svc_cacherep { 20 struct svc_cacherep {
21 struct hlist_node c_hash; 21 struct hlist_node c_hash;
22 struct list_head c_lru; 22 struct list_head c_lru;
23 23
24 unsigned char c_state, /* unused, inprog, done */ 24 unsigned char c_state, /* unused, inprog, done */
25 c_type, /* status, buffer */ 25 c_type, /* status, buffer */
26 c_secure : 1; /* req came from port < 1024 */ 26 c_secure : 1; /* req came from port < 1024 */
27 struct sockaddr_in6 c_addr; 27 struct sockaddr_in6 c_addr;
28 __be32 c_xid; 28 __be32 c_xid;
29 u32 c_prot; 29 u32 c_prot;
30 u32 c_proc; 30 u32 c_proc;
31 u32 c_vers; 31 u32 c_vers;
32 unsigned long c_timestamp; 32 unsigned long c_timestamp;
33 union { 33 union {
34 struct kvec u_vec; 34 struct kvec u_vec;
35 __be32 u_status; 35 __be32 u_status;
36 } c_u; 36 } c_u;
37 }; 37 };
38 38
39 #define c_replvec c_u.u_vec 39 #define c_replvec c_u.u_vec
40 #define c_replstat c_u.u_status 40 #define c_replstat c_u.u_status
41 41
42 /* cache entry states */ 42 /* cache entry states */
43 enum { 43 enum {
44 RC_UNUSED, 44 RC_UNUSED,
45 RC_INPROG, 45 RC_INPROG,
46 RC_DONE 46 RC_DONE
47 }; 47 };
48 48
49 /* return values */ 49 /* return values */
50 enum { 50 enum {
51 RC_DROPIT, 51 RC_DROPIT,
52 RC_REPLY, 52 RC_REPLY,
53 RC_DOIT, 53 RC_DOIT
54 RC_INTR
55 }; 54 };
56 55
57 /* 56 /*
58 * Cache types. 57 * Cache types.
59 * We may want to add more types one day, e.g. for diropres and 58 * We may want to add more types one day, e.g. for diropres and
60 * attrstat replies. Using cache entries with fixed length instead 59 * attrstat replies. Using cache entries with fixed length instead
61 * of buffer pointers may be more efficient. 60 * of buffer pointers may be more efficient.
62 */ 61 */
63 enum { 62 enum {
64 RC_NOCACHE, 63 RC_NOCACHE,
65 RC_REPLSTAT, 64 RC_REPLSTAT,
66 RC_REPLBUFF, 65 RC_REPLBUFF,
67 }; 66 };
68 67
69 /* 68 /*
70 * If requests are retransmitted within this interval, they're dropped. 69 * If requests are retransmitted within this interval, they're dropped.
71 */ 70 */
72 #define RC_DELAY (HZ/5) 71 #define RC_DELAY (HZ/5)
73 72
74 int nfsd_reply_cache_init(void); 73 int nfsd_reply_cache_init(void);
75 void nfsd_reply_cache_shutdown(void); 74 void nfsd_reply_cache_shutdown(void);
76 int nfsd_cache_lookup(struct svc_rqst *); 75 int nfsd_cache_lookup(struct svc_rqst *);
77 void nfsd_cache_update(struct svc_rqst *, int, __be32 *); 76 void nfsd_cache_update(struct svc_rqst *, int, __be32 *);
78 77
79 #ifdef CONFIG_NFSD_V4 78 #ifdef CONFIG_NFSD_V4
80 void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp); 79 void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp);
81 #else /* CONFIG_NFSD_V4 */ 80 #else /* CONFIG_NFSD_V4 */
82 static inline void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp) 81 static inline void nfsd4_set_statp(struct svc_rqst *rqstp, __be32 *statp)
83 { 82 {
84 } 83 }
85 #endif /* CONFIG_NFSD_V4 */ 84 #endif /* CONFIG_NFSD_V4 */
86 85
87 #endif /* NFSCACHE_H */ 86 #endif /* NFSCACHE_H */
88 87
1 /* 1 /*
2 * Central processing for nfsd. 2 * Central processing for nfsd.
3 * 3 *
4 * Authors: Olaf Kirch (okir@monad.swb.de) 4 * Authors: Olaf Kirch (okir@monad.swb.de)
5 * 5 *
6 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8 8
9 #include <linux/sched.h> 9 #include <linux/sched.h>
10 #include <linux/freezer.h> 10 #include <linux/freezer.h>
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/fs_struct.h> 12 #include <linux/fs_struct.h>
13 #include <linux/swap.h> 13 #include <linux/swap.h>
14 14
15 #include <linux/sunrpc/stats.h> 15 #include <linux/sunrpc/stats.h>
16 #include <linux/sunrpc/svcsock.h> 16 #include <linux/sunrpc/svcsock.h>
17 #include <linux/lockd/bind.h> 17 #include <linux/lockd/bind.h>
18 #include <linux/nfsacl.h> 18 #include <linux/nfsacl.h>
19 #include <linux/seq_file.h> 19 #include <linux/seq_file.h>
20 #include <net/net_namespace.h> 20 #include <net/net_namespace.h>
21 #include "nfsd.h" 21 #include "nfsd.h"
22 #include "cache.h" 22 #include "cache.h"
23 #include "vfs.h" 23 #include "vfs.h"
24 #include "netns.h" 24 #include "netns.h"
25 25
26 #define NFSDDBG_FACILITY NFSDDBG_SVC 26 #define NFSDDBG_FACILITY NFSDDBG_SVC
27 27
28 extern struct svc_program nfsd_program; 28 extern struct svc_program nfsd_program;
29 static int nfsd(void *vrqstp); 29 static int nfsd(void *vrqstp);
30 30
31 /* 31 /*
32 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members 32 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
33 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some 33 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
34 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt 34 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
35 * 35 *
36 * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a 36 * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a
37 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number 37 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
38 * of nfsd threads must exist and each must listed in ->sp_all_threads in each 38 * of nfsd threads must exist and each must listed in ->sp_all_threads in each
39 * entry of ->sv_pools[]. 39 * entry of ->sv_pools[].
40 * 40 *
41 * Transitions of the thread count between zero and non-zero are of particular 41 * Transitions of the thread count between zero and non-zero are of particular
42 * interest since the svc_serv needs to be created and initialized at that 42 * interest since the svc_serv needs to be created and initialized at that
43 * point, or freed. 43 * point, or freed.
44 * 44 *
45 * Finally, the nfsd_mutex also protects some of the global variables that are 45 * Finally, the nfsd_mutex also protects some of the global variables that are
46 * accessed when nfsd starts and that are settable via the write_* routines in 46 * accessed when nfsd starts and that are settable via the write_* routines in
47 * nfsctl.c. In particular: 47 * nfsctl.c. In particular:
48 * 48 *
49 * user_recovery_dirname 49 * user_recovery_dirname
50 * user_lease_time 50 * user_lease_time
51 * nfsd_versions 51 * nfsd_versions
52 */ 52 */
53 DEFINE_MUTEX(nfsd_mutex); 53 DEFINE_MUTEX(nfsd_mutex);
54 54
55 /* 55 /*
56 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used. 56 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
57 * nfsd_drc_max_pages limits the total amount of memory available for 57 * nfsd_drc_max_pages limits the total amount of memory available for
58 * version 4.1 DRC caches. 58 * version 4.1 DRC caches.
59 * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage. 59 * nfsd_drc_pages_used tracks the current version 4.1 DRC memory usage.
60 */ 60 */
61 spinlock_t nfsd_drc_lock; 61 spinlock_t nfsd_drc_lock;
62 unsigned int nfsd_drc_max_mem; 62 unsigned int nfsd_drc_max_mem;
63 unsigned int nfsd_drc_mem_used; 63 unsigned int nfsd_drc_mem_used;
64 64
65 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 65 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
66 static struct svc_stat nfsd_acl_svcstats; 66 static struct svc_stat nfsd_acl_svcstats;
67 static struct svc_version * nfsd_acl_version[] = { 67 static struct svc_version * nfsd_acl_version[] = {
68 [2] = &nfsd_acl_version2, 68 [2] = &nfsd_acl_version2,
69 [3] = &nfsd_acl_version3, 69 [3] = &nfsd_acl_version3,
70 }; 70 };
71 71
72 #define NFSD_ACL_MINVERS 2 72 #define NFSD_ACL_MINVERS 2
73 #define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version) 73 #define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version)
74 static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS]; 74 static struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS];
75 75
76 static struct svc_program nfsd_acl_program = { 76 static struct svc_program nfsd_acl_program = {
77 .pg_prog = NFS_ACL_PROGRAM, 77 .pg_prog = NFS_ACL_PROGRAM,
78 .pg_nvers = NFSD_ACL_NRVERS, 78 .pg_nvers = NFSD_ACL_NRVERS,
79 .pg_vers = nfsd_acl_versions, 79 .pg_vers = nfsd_acl_versions,
80 .pg_name = "nfsacl", 80 .pg_name = "nfsacl",
81 .pg_class = "nfsd", 81 .pg_class = "nfsd",
82 .pg_stats = &nfsd_acl_svcstats, 82 .pg_stats = &nfsd_acl_svcstats,
83 .pg_authenticate = &svc_set_client, 83 .pg_authenticate = &svc_set_client,
84 }; 84 };
85 85
86 static struct svc_stat nfsd_acl_svcstats = { 86 static struct svc_stat nfsd_acl_svcstats = {
87 .program = &nfsd_acl_program, 87 .program = &nfsd_acl_program,
88 }; 88 };
89 #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ 89 #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
90 90
91 static struct svc_version * nfsd_version[] = { 91 static struct svc_version * nfsd_version[] = {
92 [2] = &nfsd_version2, 92 [2] = &nfsd_version2,
93 #if defined(CONFIG_NFSD_V3) 93 #if defined(CONFIG_NFSD_V3)
94 [3] = &nfsd_version3, 94 [3] = &nfsd_version3,
95 #endif 95 #endif
96 #if defined(CONFIG_NFSD_V4) 96 #if defined(CONFIG_NFSD_V4)
97 [4] = &nfsd_version4, 97 [4] = &nfsd_version4,
98 #endif 98 #endif
99 }; 99 };
100 100
101 #define NFSD_MINVERS 2 101 #define NFSD_MINVERS 2
102 #define NFSD_NRVERS ARRAY_SIZE(nfsd_version) 102 #define NFSD_NRVERS ARRAY_SIZE(nfsd_version)
103 static struct svc_version *nfsd_versions[NFSD_NRVERS]; 103 static struct svc_version *nfsd_versions[NFSD_NRVERS];
104 104
105 struct svc_program nfsd_program = { 105 struct svc_program nfsd_program = {
106 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 106 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
107 .pg_next = &nfsd_acl_program, 107 .pg_next = &nfsd_acl_program,
108 #endif 108 #endif
109 .pg_prog = NFS_PROGRAM, /* program number */ 109 .pg_prog = NFS_PROGRAM, /* program number */
110 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ 110 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
111 .pg_vers = nfsd_versions, /* version table */ 111 .pg_vers = nfsd_versions, /* version table */
112 .pg_name = "nfsd", /* program name */ 112 .pg_name = "nfsd", /* program name */
113 .pg_class = "nfsd", /* authentication class */ 113 .pg_class = "nfsd", /* authentication class */
114 .pg_stats = &nfsd_svcstats, /* version table */ 114 .pg_stats = &nfsd_svcstats, /* version table */
115 .pg_authenticate = &svc_set_client, /* export authentication */ 115 .pg_authenticate = &svc_set_client, /* export authentication */
116 116
117 }; 117 };
118 118
119 u32 nfsd_supported_minorversion; 119 u32 nfsd_supported_minorversion;
120 120
121 int nfsd_vers(int vers, enum vers_op change) 121 int nfsd_vers(int vers, enum vers_op change)
122 { 122 {
123 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS) 123 if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
124 return 0; 124 return 0;
125 switch(change) { 125 switch(change) {
126 case NFSD_SET: 126 case NFSD_SET:
127 nfsd_versions[vers] = nfsd_version[vers]; 127 nfsd_versions[vers] = nfsd_version[vers];
128 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 128 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
129 if (vers < NFSD_ACL_NRVERS) 129 if (vers < NFSD_ACL_NRVERS)
130 nfsd_acl_versions[vers] = nfsd_acl_version[vers]; 130 nfsd_acl_versions[vers] = nfsd_acl_version[vers];
131 #endif 131 #endif
132 break; 132 break;
133 case NFSD_CLEAR: 133 case NFSD_CLEAR:
134 nfsd_versions[vers] = NULL; 134 nfsd_versions[vers] = NULL;
135 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 135 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
136 if (vers < NFSD_ACL_NRVERS) 136 if (vers < NFSD_ACL_NRVERS)
137 nfsd_acl_versions[vers] = NULL; 137 nfsd_acl_versions[vers] = NULL;
138 #endif 138 #endif
139 break; 139 break;
140 case NFSD_TEST: 140 case NFSD_TEST:
141 return nfsd_versions[vers] != NULL; 141 return nfsd_versions[vers] != NULL;
142 case NFSD_AVAIL: 142 case NFSD_AVAIL:
143 return nfsd_version[vers] != NULL; 143 return nfsd_version[vers] != NULL;
144 } 144 }
145 return 0; 145 return 0;
146 } 146 }
147 147
148 int nfsd_minorversion(u32 minorversion, enum vers_op change) 148 int nfsd_minorversion(u32 minorversion, enum vers_op change)
149 { 149 {
150 if (minorversion > NFSD_SUPPORTED_MINOR_VERSION) 150 if (minorversion > NFSD_SUPPORTED_MINOR_VERSION)
151 return -1; 151 return -1;
152 switch(change) { 152 switch(change) {
153 case NFSD_SET: 153 case NFSD_SET:
154 nfsd_supported_minorversion = minorversion; 154 nfsd_supported_minorversion = minorversion;
155 break; 155 break;
156 case NFSD_CLEAR: 156 case NFSD_CLEAR:
157 if (minorversion == 0) 157 if (minorversion == 0)
158 return -1; 158 return -1;
159 nfsd_supported_minorversion = minorversion - 1; 159 nfsd_supported_minorversion = minorversion - 1;
160 break; 160 break;
161 case NFSD_TEST: 161 case NFSD_TEST:
162 return minorversion <= nfsd_supported_minorversion; 162 return minorversion <= nfsd_supported_minorversion;
163 case NFSD_AVAIL: 163 case NFSD_AVAIL:
164 return minorversion <= NFSD_SUPPORTED_MINOR_VERSION; 164 return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
165 } 165 }
166 return 0; 166 return 0;
167 } 167 }
168 168
169 /* 169 /*
170 * Maximum number of nfsd processes 170 * Maximum number of nfsd processes
171 */ 171 */
172 #define NFSD_MAXSERVS 8192 172 #define NFSD_MAXSERVS 8192
173 173
174 int nfsd_nrthreads(struct net *net) 174 int nfsd_nrthreads(struct net *net)
175 { 175 {
176 int rv = 0; 176 int rv = 0;
177 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 177 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
178 178
179 mutex_lock(&nfsd_mutex); 179 mutex_lock(&nfsd_mutex);
180 if (nn->nfsd_serv) 180 if (nn->nfsd_serv)
181 rv = nn->nfsd_serv->sv_nrthreads; 181 rv = nn->nfsd_serv->sv_nrthreads;
182 mutex_unlock(&nfsd_mutex); 182 mutex_unlock(&nfsd_mutex);
183 return rv; 183 return rv;
184 } 184 }
185 185
186 static int nfsd_init_socks(struct net *net) 186 static int nfsd_init_socks(struct net *net)
187 { 187 {
188 int error; 188 int error;
189 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 189 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
190 190
191 if (!list_empty(&nn->nfsd_serv->sv_permsocks)) 191 if (!list_empty(&nn->nfsd_serv->sv_permsocks))
192 return 0; 192 return 0;
193 193
194 error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT, 194 error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT,
195 SVC_SOCK_DEFAULTS); 195 SVC_SOCK_DEFAULTS);
196 if (error < 0) 196 if (error < 0)
197 return error; 197 return error;
198 198
199 error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT, 199 error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT,
200 SVC_SOCK_DEFAULTS); 200 SVC_SOCK_DEFAULTS);
201 if (error < 0) 201 if (error < 0)
202 return error; 202 return error;
203 203
204 return 0; 204 return 0;
205 } 205 }
206 206
207 static int nfsd_users = 0; 207 static int nfsd_users = 0;
208 208
209 static int nfsd_startup_generic(int nrservs) 209 static int nfsd_startup_generic(int nrservs)
210 { 210 {
211 int ret; 211 int ret;
212 212
213 if (nfsd_users++) 213 if (nfsd_users++)
214 return 0; 214 return 0;
215 215
216 /* 216 /*
217 * Readahead param cache - will no-op if it already exists. 217 * Readahead param cache - will no-op if it already exists.
218 * (Note therefore results will be suboptimal if number of 218 * (Note therefore results will be suboptimal if number of
219 * threads is modified after nfsd start.) 219 * threads is modified after nfsd start.)
220 */ 220 */
221 ret = nfsd_racache_init(2*nrservs); 221 ret = nfsd_racache_init(2*nrservs);
222 if (ret) 222 if (ret)
223 return ret; 223 return ret;
224 ret = nfs4_state_start(); 224 ret = nfs4_state_start();
225 if (ret) 225 if (ret)
226 goto out_racache; 226 goto out_racache;
227 return 0; 227 return 0;
228 228
229 out_racache: 229 out_racache:
230 nfsd_racache_shutdown(); 230 nfsd_racache_shutdown();
231 return ret; 231 return ret;
232 } 232 }
233 233
234 static void nfsd_shutdown_generic(void) 234 static void nfsd_shutdown_generic(void)
235 { 235 {
236 if (--nfsd_users) 236 if (--nfsd_users)
237 return; 237 return;
238 238
239 nfs4_state_shutdown(); 239 nfs4_state_shutdown();
240 nfsd_racache_shutdown(); 240 nfsd_racache_shutdown();
241 } 241 }
242 242
243 static int nfsd_startup_net(int nrservs, struct net *net) 243 static int nfsd_startup_net(int nrservs, struct net *net)
244 { 244 {
245 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 245 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
246 int ret; 246 int ret;
247 247
248 if (nn->nfsd_net_up) 248 if (nn->nfsd_net_up)
249 return 0; 249 return 0;
250 250
251 ret = nfsd_startup_generic(nrservs); 251 ret = nfsd_startup_generic(nrservs);
252 if (ret) 252 if (ret)
253 return ret; 253 return ret;
254 ret = nfsd_init_socks(net); 254 ret = nfsd_init_socks(net);
255 if (ret) 255 if (ret)
256 goto out_socks; 256 goto out_socks;
257 ret = lockd_up(net); 257 ret = lockd_up(net);
258 if (ret) 258 if (ret)
259 goto out_socks; 259 goto out_socks;
260 ret = nfs4_state_start_net(net); 260 ret = nfs4_state_start_net(net);
261 if (ret) 261 if (ret)
262 goto out_lockd; 262 goto out_lockd;
263 263
264 nn->nfsd_net_up = true; 264 nn->nfsd_net_up = true;
265 return 0; 265 return 0;
266 266
267 out_lockd: 267 out_lockd:
268 lockd_down(net); 268 lockd_down(net);
269 out_socks: 269 out_socks:
270 nfsd_shutdown_generic(); 270 nfsd_shutdown_generic();
271 return ret; 271 return ret;
272 } 272 }
273 273
274 static void nfsd_shutdown_net(struct net *net) 274 static void nfsd_shutdown_net(struct net *net)
275 { 275 {
276 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 276 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
277 277
278 nfs4_state_shutdown_net(net); 278 nfs4_state_shutdown_net(net);
279 lockd_down(net); 279 lockd_down(net);
280 nn->nfsd_net_up = false; 280 nn->nfsd_net_up = false;
281 nfsd_shutdown_generic(); 281 nfsd_shutdown_generic();
282 } 282 }
283 283
284 static void nfsd_last_thread(struct svc_serv *serv, struct net *net) 284 static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
285 { 285 {
286 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 286 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
287 287
288 /* 288 /*
289 * write_ports can create the server without actually starting 289 * write_ports can create the server without actually starting
290 * any threads--if we get shut down before any threads are 290 * any threads--if we get shut down before any threads are
291 * started, then nfsd_last_thread will be run before any of this 291 * started, then nfsd_last_thread will be run before any of this
292 * other initialization has been done. 292 * other initialization has been done.
293 */ 293 */
294 if (!nn->nfsd_net_up) 294 if (!nn->nfsd_net_up)
295 return; 295 return;
296 nfsd_shutdown_net(net); 296 nfsd_shutdown_net(net);
297 297
298 svc_rpcb_cleanup(serv, net); 298 svc_rpcb_cleanup(serv, net);
299 299
300 printk(KERN_WARNING "nfsd: last server has exited, flushing export " 300 printk(KERN_WARNING "nfsd: last server has exited, flushing export "
301 "cache\n"); 301 "cache\n");
302 nfsd_export_flush(net); 302 nfsd_export_flush(net);
303 } 303 }
304 304
305 void nfsd_reset_versions(void) 305 void nfsd_reset_versions(void)
306 { 306 {
307 int found_one = 0; 307 int found_one = 0;
308 int i; 308 int i;
309 309
310 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { 310 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
311 if (nfsd_program.pg_vers[i]) 311 if (nfsd_program.pg_vers[i])
312 found_one = 1; 312 found_one = 1;
313 } 313 }
314 314
315 if (!found_one) { 315 if (!found_one) {
316 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) 316 for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
317 nfsd_program.pg_vers[i] = nfsd_version[i]; 317 nfsd_program.pg_vers[i] = nfsd_version[i];
318 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) 318 #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
319 for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) 319 for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++)
320 nfsd_acl_program.pg_vers[i] = 320 nfsd_acl_program.pg_vers[i] =
321 nfsd_acl_version[i]; 321 nfsd_acl_version[i];
322 #endif 322 #endif
323 } 323 }
324 } 324 }
325 325
326 /* 326 /*
327 * Each session guarantees a negotiated per slot memory cache for replies 327 * Each session guarantees a negotiated per slot memory cache for replies
328 * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated 328 * which in turn consumes memory beyond the v2/v3/v4.0 server. A dedicated
329 * NFSv4.1 server might want to use more memory for a DRC than a machine 329 * NFSv4.1 server might want to use more memory for a DRC than a machine
330 * with mutiple services. 330 * with mutiple services.
331 * 331 *
332 * Impose a hard limit on the number of pages for the DRC which varies 332 * Impose a hard limit on the number of pages for the DRC which varies
333 * according to the machines free pages. This is of course only a default. 333 * according to the machines free pages. This is of course only a default.
334 * 334 *
335 * For now this is a #defined shift which could be under admin control 335 * For now this is a #defined shift which could be under admin control
336 * in the future. 336 * in the future.
337 */ 337 */
338 static void set_max_drc(void) 338 static void set_max_drc(void)
339 { 339 {
340 #define NFSD_DRC_SIZE_SHIFT 10 340 #define NFSD_DRC_SIZE_SHIFT 10
341 nfsd_drc_max_mem = (nr_free_buffer_pages() 341 nfsd_drc_max_mem = (nr_free_buffer_pages()
342 >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE; 342 >> NFSD_DRC_SIZE_SHIFT) * PAGE_SIZE;
343 nfsd_drc_mem_used = 0; 343 nfsd_drc_mem_used = 0;
344 spin_lock_init(&nfsd_drc_lock); 344 spin_lock_init(&nfsd_drc_lock);
345 dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem); 345 dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem);
346 } 346 }
347 347
348 static int nfsd_get_default_max_blksize(void) 348 static int nfsd_get_default_max_blksize(void)
349 { 349 {
350 struct sysinfo i; 350 struct sysinfo i;
351 unsigned long long target; 351 unsigned long long target;
352 unsigned long ret; 352 unsigned long ret;
353 353
354 si_meminfo(&i); 354 si_meminfo(&i);
355 target = (i.totalram - i.totalhigh) << PAGE_SHIFT; 355 target = (i.totalram - i.totalhigh) << PAGE_SHIFT;
356 /* 356 /*
357 * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig 357 * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig
358 * machines, but only uses 32K on 128M machines. Bottom out at 358 * machines, but only uses 32K on 128M machines. Bottom out at
359 * 8K on 32M and smaller. Of course, this is only a default. 359 * 8K on 32M and smaller. Of course, this is only a default.
360 */ 360 */
361 target >>= 12; 361 target >>= 12;
362 362
363 ret = NFSSVC_MAXBLKSIZE; 363 ret = NFSSVC_MAXBLKSIZE;
364 while (ret > target && ret >= 8*1024*2) 364 while (ret > target && ret >= 8*1024*2)
365 ret /= 2; 365 ret /= 2;
366 return ret; 366 return ret;
367 } 367 }
368 368
369 int nfsd_create_serv(struct net *net) 369 int nfsd_create_serv(struct net *net)
370 { 370 {
371 int error; 371 int error;
372 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 372 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
373 373
374 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 374 WARN_ON(!mutex_is_locked(&nfsd_mutex));
375 if (nn->nfsd_serv) { 375 if (nn->nfsd_serv) {
376 svc_get(nn->nfsd_serv); 376 svc_get(nn->nfsd_serv);
377 return 0; 377 return 0;
378 } 378 }
379 if (nfsd_max_blksize == 0) 379 if (nfsd_max_blksize == 0)
380 nfsd_max_blksize = nfsd_get_default_max_blksize(); 380 nfsd_max_blksize = nfsd_get_default_max_blksize();
381 nfsd_reset_versions(); 381 nfsd_reset_versions();
382 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 382 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
383 nfsd_last_thread, nfsd, THIS_MODULE); 383 nfsd_last_thread, nfsd, THIS_MODULE);
384 if (nn->nfsd_serv == NULL) 384 if (nn->nfsd_serv == NULL)
385 return -ENOMEM; 385 return -ENOMEM;
386 386
387 error = svc_bind(nn->nfsd_serv, net); 387 error = svc_bind(nn->nfsd_serv, net);
388 if (error < 0) { 388 if (error < 0) {
389 svc_destroy(nn->nfsd_serv); 389 svc_destroy(nn->nfsd_serv);
390 return error; 390 return error;
391 } 391 }
392 392
393 set_max_drc(); 393 set_max_drc();
394 do_gettimeofday(&nn->nfssvc_boot); /* record boot time */ 394 do_gettimeofday(&nn->nfssvc_boot); /* record boot time */
395 return 0; 395 return 0;
396 } 396 }
397 397
398 int nfsd_nrpools(struct net *net) 398 int nfsd_nrpools(struct net *net)
399 { 399 {
400 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 400 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
401 401
402 if (nn->nfsd_serv == NULL) 402 if (nn->nfsd_serv == NULL)
403 return 0; 403 return 0;
404 else 404 else
405 return nn->nfsd_serv->sv_nrpools; 405 return nn->nfsd_serv->sv_nrpools;
406 } 406 }
407 407
408 int nfsd_get_nrthreads(int n, int *nthreads, struct net *net) 408 int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
409 { 409 {
410 int i = 0; 410 int i = 0;
411 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 411 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
412 412
413 if (nn->nfsd_serv != NULL) { 413 if (nn->nfsd_serv != NULL) {
414 for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++) 414 for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++)
415 nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads; 415 nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads;
416 } 416 }
417 417
418 return 0; 418 return 0;
419 } 419 }
420 420
421 void nfsd_destroy(struct net *net) 421 void nfsd_destroy(struct net *net)
422 { 422 {
423 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 423 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
424 int destroy = (nn->nfsd_serv->sv_nrthreads == 1); 424 int destroy = (nn->nfsd_serv->sv_nrthreads == 1);
425 425
426 if (destroy) 426 if (destroy)
427 svc_shutdown_net(nn->nfsd_serv, net); 427 svc_shutdown_net(nn->nfsd_serv, net);
428 svc_destroy(nn->nfsd_serv); 428 svc_destroy(nn->nfsd_serv);
429 if (destroy) 429 if (destroy)
430 nn->nfsd_serv = NULL; 430 nn->nfsd_serv = NULL;
431 } 431 }
432 432
433 int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) 433 int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
434 { 434 {
435 int i = 0; 435 int i = 0;
436 int tot = 0; 436 int tot = 0;
437 int err = 0; 437 int err = 0;
438 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 438 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
439 439
440 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 440 WARN_ON(!mutex_is_locked(&nfsd_mutex));
441 441
442 if (nn->nfsd_serv == NULL || n <= 0) 442 if (nn->nfsd_serv == NULL || n <= 0)
443 return 0; 443 return 0;
444 444
445 if (n > nn->nfsd_serv->sv_nrpools) 445 if (n > nn->nfsd_serv->sv_nrpools)
446 n = nn->nfsd_serv->sv_nrpools; 446 n = nn->nfsd_serv->sv_nrpools;
447 447
448 /* enforce a global maximum number of threads */ 448 /* enforce a global maximum number of threads */
449 tot = 0; 449 tot = 0;
450 for (i = 0; i < n; i++) { 450 for (i = 0; i < n; i++) {
451 if (nthreads[i] > NFSD_MAXSERVS) 451 if (nthreads[i] > NFSD_MAXSERVS)
452 nthreads[i] = NFSD_MAXSERVS; 452 nthreads[i] = NFSD_MAXSERVS;
453 tot += nthreads[i]; 453 tot += nthreads[i];
454 } 454 }
455 if (tot > NFSD_MAXSERVS) { 455 if (tot > NFSD_MAXSERVS) {
456 /* total too large: scale down requested numbers */ 456 /* total too large: scale down requested numbers */
457 for (i = 0; i < n && tot > 0; i++) { 457 for (i = 0; i < n && tot > 0; i++) {
458 int new = nthreads[i] * NFSD_MAXSERVS / tot; 458 int new = nthreads[i] * NFSD_MAXSERVS / tot;
459 tot -= (nthreads[i] - new); 459 tot -= (nthreads[i] - new);
460 nthreads[i] = new; 460 nthreads[i] = new;
461 } 461 }
462 for (i = 0; i < n && tot > 0; i++) { 462 for (i = 0; i < n && tot > 0; i++) {
463 nthreads[i]--; 463 nthreads[i]--;
464 tot--; 464 tot--;
465 } 465 }
466 } 466 }
467 467
468 /* 468 /*
469 * There must always be a thread in pool 0; the admin 469 * There must always be a thread in pool 0; the admin
470 * can't shut down NFS completely using pool_threads. 470 * can't shut down NFS completely using pool_threads.
471 */ 471 */
472 if (nthreads[0] == 0) 472 if (nthreads[0] == 0)
473 nthreads[0] = 1; 473 nthreads[0] = 1;
474 474
475 /* apply the new numbers */ 475 /* apply the new numbers */
476 svc_get(nn->nfsd_serv); 476 svc_get(nn->nfsd_serv);
477 for (i = 0; i < n; i++) { 477 for (i = 0; i < n; i++) {
478 err = svc_set_num_threads(nn->nfsd_serv, &nn->nfsd_serv->sv_pools[i], 478 err = svc_set_num_threads(nn->nfsd_serv, &nn->nfsd_serv->sv_pools[i],
479 nthreads[i]); 479 nthreads[i]);
480 if (err) 480 if (err)
481 break; 481 break;
482 } 482 }
483 nfsd_destroy(net); 483 nfsd_destroy(net);
484 return err; 484 return err;
485 } 485 }
486 486
487 /* 487 /*
488 * Adjust the number of threads and return the new number of threads. 488 * Adjust the number of threads and return the new number of threads.
489 * This is also the function that starts the server if necessary, if 489 * This is also the function that starts the server if necessary, if
490 * this is the first time nrservs is nonzero. 490 * this is the first time nrservs is nonzero.
491 */ 491 */
492 int 492 int
493 nfsd_svc(int nrservs, struct net *net) 493 nfsd_svc(int nrservs, struct net *net)
494 { 494 {
495 int error; 495 int error;
496 bool nfsd_up_before; 496 bool nfsd_up_before;
497 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 497 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
498 498
499 mutex_lock(&nfsd_mutex); 499 mutex_lock(&nfsd_mutex);
500 dprintk("nfsd: creating service\n"); 500 dprintk("nfsd: creating service\n");
501 if (nrservs <= 0) 501 if (nrservs <= 0)
502 nrservs = 0; 502 nrservs = 0;
503 if (nrservs > NFSD_MAXSERVS) 503 if (nrservs > NFSD_MAXSERVS)
504 nrservs = NFSD_MAXSERVS; 504 nrservs = NFSD_MAXSERVS;
505 error = 0; 505 error = 0;
506 if (nrservs == 0 && nn->nfsd_serv == NULL) 506 if (nrservs == 0 && nn->nfsd_serv == NULL)
507 goto out; 507 goto out;
508 508
509 error = nfsd_create_serv(net); 509 error = nfsd_create_serv(net);
510 if (error) 510 if (error)
511 goto out; 511 goto out;
512 512
513 nfsd_up_before = nn->nfsd_net_up; 513 nfsd_up_before = nn->nfsd_net_up;
514 514
515 error = nfsd_startup_net(nrservs, net); 515 error = nfsd_startup_net(nrservs, net);
516 if (error) 516 if (error)
517 goto out_destroy; 517 goto out_destroy;
518 error = svc_set_num_threads(nn->nfsd_serv, NULL, nrservs); 518 error = svc_set_num_threads(nn->nfsd_serv, NULL, nrservs);
519 if (error) 519 if (error)
520 goto out_shutdown; 520 goto out_shutdown;
521 /* We are holding a reference to nn->nfsd_serv which 521 /* We are holding a reference to nn->nfsd_serv which
522 * we don't want to count in the return value, 522 * we don't want to count in the return value,
523 * so subtract 1 523 * so subtract 1
524 */ 524 */
525 error = nn->nfsd_serv->sv_nrthreads - 1; 525 error = nn->nfsd_serv->sv_nrthreads - 1;
526 out_shutdown: 526 out_shutdown:
527 if (error < 0 && !nfsd_up_before) 527 if (error < 0 && !nfsd_up_before)
528 nfsd_shutdown_net(net); 528 nfsd_shutdown_net(net);
529 out_destroy: 529 out_destroy:
530 nfsd_destroy(net); /* Release server */ 530 nfsd_destroy(net); /* Release server */
531 out: 531 out:
532 mutex_unlock(&nfsd_mutex); 532 mutex_unlock(&nfsd_mutex);
533 return error; 533 return error;
534 } 534 }
535 535
536 536
537 /* 537 /*
538 * This is the NFS server kernel thread 538 * This is the NFS server kernel thread
539 */ 539 */
540 static int 540 static int
541 nfsd(void *vrqstp) 541 nfsd(void *vrqstp)
542 { 542 {
543 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 543 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
544 struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list); 544 struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list);
545 struct net *net = perm_sock->xpt_net; 545 struct net *net = perm_sock->xpt_net;
546 int err; 546 int err;
547 547
548 /* Lock module and set up kernel thread */ 548 /* Lock module and set up kernel thread */
549 mutex_lock(&nfsd_mutex); 549 mutex_lock(&nfsd_mutex);
550 550
551 /* At this point, the thread shares current->fs 551 /* At this point, the thread shares current->fs
552 * with the init process. We need to create files with a 552 * with the init process. We need to create files with a
553 * umask of 0 instead of init's umask. */ 553 * umask of 0 instead of init's umask. */
554 if (unshare_fs_struct() < 0) { 554 if (unshare_fs_struct() < 0) {
555 printk("Unable to start nfsd thread: out of memory\n"); 555 printk("Unable to start nfsd thread: out of memory\n");
556 goto out; 556 goto out;
557 } 557 }
558 558
559 current->fs->umask = 0; 559 current->fs->umask = 0;
560 560
561 /* 561 /*
562 * thread is spawned with all signals set to SIG_IGN, re-enable 562 * thread is spawned with all signals set to SIG_IGN, re-enable
563 * the ones that will bring down the thread 563 * the ones that will bring down the thread
564 */ 564 */
565 allow_signal(SIGKILL); 565 allow_signal(SIGKILL);
566 allow_signal(SIGHUP); 566 allow_signal(SIGHUP);
567 allow_signal(SIGINT); 567 allow_signal(SIGINT);
568 allow_signal(SIGQUIT); 568 allow_signal(SIGQUIT);
569 569
570 nfsdstats.th_cnt++; 570 nfsdstats.th_cnt++;
571 mutex_unlock(&nfsd_mutex); 571 mutex_unlock(&nfsd_mutex);
572 572
573 /* 573 /*
574 * We want less throttling in balance_dirty_pages() so that nfs to 574 * We want less throttling in balance_dirty_pages() so that nfs to
575 * localhost doesn't cause nfsd to lock up due to all the client's 575 * localhost doesn't cause nfsd to lock up due to all the client's
576 * dirty pages. 576 * dirty pages.
577 */ 577 */
578 current->flags |= PF_LESS_THROTTLE; 578 current->flags |= PF_LESS_THROTTLE;
579 set_freezable(); 579 set_freezable();
580 580
581 /* 581 /*
582 * The main request loop 582 * The main request loop
583 */ 583 */
584 for (;;) { 584 for (;;) {
585 /* 585 /*
586 * Find a socket with data available and call its 586 * Find a socket with data available and call its
587 * recvfrom routine. 587 * recvfrom routine.
588 */ 588 */
589 while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN) 589 while ((err = svc_recv(rqstp, 60*60*HZ)) == -EAGAIN)
590 ; 590 ;
591 if (err == -EINTR) 591 if (err == -EINTR)
592 break; 592 break;
593 validate_process_creds(); 593 validate_process_creds();
594 svc_process(rqstp); 594 svc_process(rqstp);
595 validate_process_creds(); 595 validate_process_creds();
596 } 596 }
597 597
598 /* Clear signals before calling svc_exit_thread() */ 598 /* Clear signals before calling svc_exit_thread() */
599 flush_signals(current); 599 flush_signals(current);
600 600
601 mutex_lock(&nfsd_mutex); 601 mutex_lock(&nfsd_mutex);
602 nfsdstats.th_cnt --; 602 nfsdstats.th_cnt --;
603 603
604 out: 604 out:
605 rqstp->rq_server = NULL; 605 rqstp->rq_server = NULL;
606 606
607 /* Release the thread */ 607 /* Release the thread */
608 svc_exit_thread(rqstp); 608 svc_exit_thread(rqstp);
609 609
610 nfsd_destroy(net); 610 nfsd_destroy(net);
611 611
612 /* Release module */ 612 /* Release module */
613 mutex_unlock(&nfsd_mutex); 613 mutex_unlock(&nfsd_mutex);
614 module_put_and_exit(0); 614 module_put_and_exit(0);
615 return 0; 615 return 0;
616 } 616 }
617 617
618 static __be32 map_new_errors(u32 vers, __be32 nfserr) 618 static __be32 map_new_errors(u32 vers, __be32 nfserr)
619 { 619 {
620 if (nfserr == nfserr_jukebox && vers == 2) 620 if (nfserr == nfserr_jukebox && vers == 2)
621 return nfserr_dropit; 621 return nfserr_dropit;
622 if (nfserr == nfserr_wrongsec && vers < 4) 622 if (nfserr == nfserr_wrongsec && vers < 4)
623 return nfserr_acces; 623 return nfserr_acces;
624 return nfserr; 624 return nfserr;
625 } 625 }
626 626
627 int 627 int
628 nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) 628 nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
629 { 629 {
630 struct svc_procedure *proc; 630 struct svc_procedure *proc;
631 kxdrproc_t xdr; 631 kxdrproc_t xdr;
632 __be32 nfserr; 632 __be32 nfserr;
633 __be32 *nfserrp; 633 __be32 *nfserrp;
634 634
635 dprintk("nfsd_dispatch: vers %d proc %d\n", 635 dprintk("nfsd_dispatch: vers %d proc %d\n",
636 rqstp->rq_vers, rqstp->rq_proc); 636 rqstp->rq_vers, rqstp->rq_proc);
637 proc = rqstp->rq_procinfo; 637 proc = rqstp->rq_procinfo;
638 638
639 /* 639 /*
640 * Give the xdr decoder a chance to change this if it wants 640 * Give the xdr decoder a chance to change this if it wants
641 * (necessary in the NFSv4.0 compound case) 641 * (necessary in the NFSv4.0 compound case)
642 */ 642 */
643 rqstp->rq_cachetype = proc->pc_cachetype; 643 rqstp->rq_cachetype = proc->pc_cachetype;
644 /* Decode arguments */ 644 /* Decode arguments */
645 xdr = proc->pc_decode; 645 xdr = proc->pc_decode;
646 if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base, 646 if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
647 rqstp->rq_argp)) { 647 rqstp->rq_argp)) {
648 dprintk("nfsd: failed to decode arguments!\n"); 648 dprintk("nfsd: failed to decode arguments!\n");
649 *statp = rpc_garbage_args; 649 *statp = rpc_garbage_args;
650 return 1; 650 return 1;
651 } 651 }
652 652
653 /* Check whether we have this call in the cache. */ 653 /* Check whether we have this call in the cache. */
654 switch (nfsd_cache_lookup(rqstp)) { 654 switch (nfsd_cache_lookup(rqstp)) {
655 case RC_INTR:
656 case RC_DROPIT: 655 case RC_DROPIT:
657 return 0; 656 return 0;
658 case RC_REPLY: 657 case RC_REPLY:
659 return 1; 658 return 1;
660 case RC_DOIT:; 659 case RC_DOIT:;
661 /* do it */ 660 /* do it */
662 } 661 }
663 662
664 /* need to grab the location to store the status, as 663 /* need to grab the location to store the status, as
665 * nfsv4 does some encoding while processing 664 * nfsv4 does some encoding while processing
666 */ 665 */
667 nfserrp = rqstp->rq_res.head[0].iov_base 666 nfserrp = rqstp->rq_res.head[0].iov_base
668 + rqstp->rq_res.head[0].iov_len; 667 + rqstp->rq_res.head[0].iov_len;
669 rqstp->rq_res.head[0].iov_len += sizeof(__be32); 668 rqstp->rq_res.head[0].iov_len += sizeof(__be32);
670 669
671 /* Now call the procedure handler, and encode NFS status. */ 670 /* Now call the procedure handler, and encode NFS status. */
672 nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); 671 nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
673 nfserr = map_new_errors(rqstp->rq_vers, nfserr); 672 nfserr = map_new_errors(rqstp->rq_vers, nfserr);
674 if (nfserr == nfserr_dropit || rqstp->rq_dropme) { 673 if (nfserr == nfserr_dropit || rqstp->rq_dropme) {
675 dprintk("nfsd: Dropping request; may be revisited later\n"); 674 dprintk("nfsd: Dropping request; may be revisited later\n");
676 nfsd_cache_update(rqstp, RC_NOCACHE, NULL); 675 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
677 return 0; 676 return 0;
678 } 677 }
679 678
680 if (rqstp->rq_proc != 0) 679 if (rqstp->rq_proc != 0)
681 *nfserrp++ = nfserr; 680 *nfserrp++ = nfserr;
682 681
683 /* Encode result. 682 /* Encode result.
684 * For NFSv2, additional info is never returned in case of an error. 683 * For NFSv2, additional info is never returned in case of an error.
685 */ 684 */
686 if (!(nfserr && rqstp->rq_vers == 2)) { 685 if (!(nfserr && rqstp->rq_vers == 2)) {
687 xdr = proc->pc_encode; 686 xdr = proc->pc_encode;
688 if (xdr && !xdr(rqstp, nfserrp, 687 if (xdr && !xdr(rqstp, nfserrp,
689 rqstp->rq_resp)) { 688 rqstp->rq_resp)) {
690 /* Failed to encode result. Release cache entry */ 689 /* Failed to encode result. Release cache entry */
691 dprintk("nfsd: failed to encode result!\n"); 690 dprintk("nfsd: failed to encode result!\n");
692 nfsd_cache_update(rqstp, RC_NOCACHE, NULL); 691 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
693 *statp = rpc_system_err; 692 *statp = rpc_system_err;
694 return 1; 693 return 1;
695 } 694 }
696 } 695 }
697 696
698 /* Store reply in cache. */ 697 /* Store reply in cache. */
699 nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1); 698 nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1);
700 return 1; 699 return 1;
701 } 700 }
702 701
703 int nfsd_pool_stats_open(struct inode *inode, struct file *file) 702 int nfsd_pool_stats_open(struct inode *inode, struct file *file)
704 { 703 {
705 int ret; 704 int ret;
706 struct net *net = &init_net; 705 struct net *net = &init_net;
707 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 706 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
708 707
709 mutex_lock(&nfsd_mutex); 708 mutex_lock(&nfsd_mutex);
710 if (nn->nfsd_serv == NULL) { 709 if (nn->nfsd_serv == NULL) {
711 mutex_unlock(&nfsd_mutex); 710 mutex_unlock(&nfsd_mutex);
712 return -ENODEV; 711 return -ENODEV;
713 } 712 }
714 /* bump up the psudo refcount while traversing */ 713 /* bump up the psudo refcount while traversing */
715 svc_get(nn->nfsd_serv); 714 svc_get(nn->nfsd_serv);
716 ret = svc_pool_stats_open(nn->nfsd_serv, file); 715 ret = svc_pool_stats_open(nn->nfsd_serv, file);
717 mutex_unlock(&nfsd_mutex); 716 mutex_unlock(&nfsd_mutex);
718 return ret; 717 return ret;
719 } 718 }
720 719
721 int nfsd_pool_stats_release(struct inode *inode, struct file *file) 720 int nfsd_pool_stats_release(struct inode *inode, struct file *file)
722 { 721 {
723 int ret = seq_release(inode, file); 722 int ret = seq_release(inode, file);
724 struct net *net = &init_net; 723 struct net *net = &init_net;
725 724
726 mutex_lock(&nfsd_mutex); 725 mutex_lock(&nfsd_mutex);
727 /* this function really, really should have been called svc_put() */ 726 /* this function really, really should have been called svc_put() */
728 nfsd_destroy(net); 727 nfsd_destroy(net);
729 mutex_unlock(&nfsd_mutex); 728 mutex_unlock(&nfsd_mutex);
730 return ret; 729 return ret;
731 } 730 }
732 731