aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/nfsd
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/Makefile12
-rw-r--r--fs/nfsd/auth.c63
-rw-r--r--fs/nfsd/export.c1200
-rw-r--r--fs/nfsd/lockd.c79
-rw-r--r--fs/nfsd/nfs3proc.c702
-rw-r--r--fs/nfsd/nfs3xdr.c1092
-rw-r--r--fs/nfsd/nfs4acl.c954
-rw-r--r--fs/nfsd/nfs4callback.c547
-rw-r--r--fs/nfsd/nfs4idmap.c588
-rw-r--r--fs/nfsd/nfs4proc.c984
-rw-r--r--fs/nfsd/nfs4state.c3320
-rw-r--r--fs/nfsd/nfs4xdr.c2536
-rw-r--r--fs/nfsd/nfscache.c328
-rw-r--r--fs/nfsd/nfsctl.c438
-rw-r--r--fs/nfsd/nfsfh.c532
-rw-r--r--fs/nfsd/nfsproc.c605
-rw-r--r--fs/nfsd/nfssvc.c385
-rw-r--r--fs/nfsd/nfsxdr.c511
-rw-r--r--fs/nfsd/stats.c101
-rw-r--r--fs/nfsd/vfs.c1859
20 files changed, 16836 insertions, 0 deletions
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
new file mode 100644
index 000000000000..b8680a247f8b
--- /dev/null
+++ b/fs/nfsd/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for the Linux nfs server
3#
4
5obj-$(CONFIG_NFSD) += nfsd.o
6
7nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
8 export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
9nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
10nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
11 nfs4acl.o nfs4callback.o
12nfsd-objs := $(nfsd-y)
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
new file mode 100644
index 000000000000..cfe9ce881613
--- /dev/null
+++ b/fs/nfsd/auth.c
@@ -0,0 +1,63 @@
1/*
2 * linux/fs/nfsd/auth.c
3 *
4 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
5 */
6
7#include <linux/types.h>
8#include <linux/sched.h>
9#include <linux/sunrpc/svc.h>
10#include <linux/sunrpc/svcauth.h>
11#include <linux/nfsd/nfsd.h>
12
13#define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
14
15int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
16{
17 struct svc_cred *cred = &rqstp->rq_cred;
18 int i;
19 int ret;
20
21 if (exp->ex_flags & NFSEXP_ALLSQUASH) {
22 cred->cr_uid = exp->ex_anon_uid;
23 cred->cr_gid = exp->ex_anon_gid;
24 put_group_info(cred->cr_group_info);
25 cred->cr_group_info = groups_alloc(0);
26 } else if (exp->ex_flags & NFSEXP_ROOTSQUASH) {
27 struct group_info *gi;
28 if (!cred->cr_uid)
29 cred->cr_uid = exp->ex_anon_uid;
30 if (!cred->cr_gid)
31 cred->cr_gid = exp->ex_anon_gid;
32 gi = groups_alloc(cred->cr_group_info->ngroups);
33 if (gi)
34 for (i = 0; i < cred->cr_group_info->ngroups; i++) {
35 if (!GROUP_AT(cred->cr_group_info, i))
36 GROUP_AT(gi, i) = exp->ex_anon_gid;
37 else
38 GROUP_AT(gi, i) = GROUP_AT(cred->cr_group_info, i);
39 }
40 put_group_info(cred->cr_group_info);
41 cred->cr_group_info = gi;
42 }
43
44 if (cred->cr_uid != (uid_t) -1)
45 current->fsuid = cred->cr_uid;
46 else
47 current->fsuid = exp->ex_anon_uid;
48 if (cred->cr_gid != (gid_t) -1)
49 current->fsgid = cred->cr_gid;
50 else
51 current->fsgid = exp->ex_anon_gid;
52
53 if (!cred->cr_group_info)
54 return -ENOMEM;
55 ret = set_current_groups(cred->cr_group_info);
56 if ((cred->cr_uid)) {
57 cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
58 } else {
59 cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
60 current->cap_permitted);
61 }
62 return ret;
63}
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
new file mode 100644
index 000000000000..9a11aa39e2e4
--- /dev/null
+++ b/fs/nfsd/export.c
@@ -0,0 +1,1200 @@
1#define MSNFS /* HACK HACK */
2/*
3 * linux/fs/nfsd/export.c
4 *
5 * NFS exporting and validation.
6 *
7 * We maintain a list of clients, each of which has a list of
8 * exports. To export an fs to a given client, you first have
9 * to create the client entry with NFSCTL_ADDCLIENT, which
10 * creates a client control block and adds it to the hash
11 * table. Then, you call NFSCTL_EXPORT for each fs.
12 *
13 *
14 * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
15 */
16
17#include <linux/unistd.h>
18#include <linux/slab.h>
19#include <linux/sched.h>
20#include <linux/stat.h>
21#include <linux/in.h>
22#include <linux/seq_file.h>
23#include <linux/syscalls.h>
24#include <linux/rwsem.h>
25#include <linux/dcache.h>
26#include <linux/namei.h>
27#include <linux/mount.h>
28#include <linux/hash.h>
29
30#include <linux/sunrpc/svc.h>
31#include <linux/nfsd/nfsd.h>
32#include <linux/nfsd/nfsfh.h>
33#include <linux/nfsd/syscall.h>
34#include <linux/lockd/bind.h>
35
36#define NFSDDBG_FACILITY NFSDDBG_EXPORT
37#define NFSD_PARANOIA 1
38
39typedef struct auth_domain svc_client;
40typedef struct svc_export svc_export;
41
42static void exp_do_unexport(svc_export *unexp);
43static int exp_verify_string(char *cp, int max);
44
45/*
46 * We have two caches.
47 * One maps client+vfsmnt+dentry to export options - the export map
48 * The other maps client+filehandle-fragment to export options. - the expkey map
49 *
50 * The export options are actually stored in the first map, and the
51 * second map contains a reference to the entry in the first map.
52 */
53
54#define EXPKEY_HASHBITS 8
55#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
56#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
57static struct cache_head *expkey_table[EXPKEY_HASHMAX];
58
59static inline int svc_expkey_hash(struct svc_expkey *item)
60{
61 int hash = item->ek_fsidtype;
62 char * cp = (char*)item->ek_fsid;
63 int len = key_len(item->ek_fsidtype);
64
65 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
66 hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
67 return hash & EXPKEY_HASHMASK;
68}
69
70void expkey_put(struct cache_head *item, struct cache_detail *cd)
71{
72 if (cache_put(item, cd)) {
73 struct svc_expkey *key = container_of(item, struct svc_expkey, h);
74 if (test_bit(CACHE_VALID, &item->flags) &&
75 !test_bit(CACHE_NEGATIVE, &item->flags))
76 exp_put(key->ek_export);
77 auth_domain_put(key->ek_client);
78 kfree(key);
79 }
80}
81
82static void expkey_request(struct cache_detail *cd,
83 struct cache_head *h,
84 char **bpp, int *blen)
85{
86 /* client fsidtype \xfsid */
87 struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
88 char type[5];
89
90 qword_add(bpp, blen, ek->ek_client->name);
91 snprintf(type, 5, "%d", ek->ek_fsidtype);
92 qword_add(bpp, blen, type);
93 qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
94 (*bpp)[-1] = '\n';
95}
96
97static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int);
98static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
99{
100 /* client fsidtype fsid [path] */
101 char *buf;
102 int len;
103 struct auth_domain *dom = NULL;
104 int err;
105 int fsidtype;
106 char *ep;
107 struct svc_expkey key;
108
109 if (mesg[mlen-1] != '\n')
110 return -EINVAL;
111 mesg[mlen-1] = 0;
112
113 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
114 err = -ENOMEM;
115 if (!buf) goto out;
116
117 err = -EINVAL;
118 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
119 goto out;
120
121 err = -ENOENT;
122 dom = auth_domain_find(buf);
123 if (!dom)
124 goto out;
125 dprintk("found domain %s\n", buf);
126
127 err = -EINVAL;
128 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
129 goto out;
130 fsidtype = simple_strtoul(buf, &ep, 10);
131 if (*ep)
132 goto out;
133 dprintk("found fsidtype %d\n", fsidtype);
134 if (fsidtype > 2)
135 goto out;
136 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
137 goto out;
138 dprintk("found fsid length %d\n", len);
139 if (len != key_len(fsidtype))
140 goto out;
141
142 /* OK, we seem to have a valid key */
143 key.h.flags = 0;
144 key.h.expiry_time = get_expiry(&mesg);
145 if (key.h.expiry_time == 0)
146 goto out;
147
148 key.ek_client = dom;
149 key.ek_fsidtype = fsidtype;
150 memcpy(key.ek_fsid, buf, len);
151
152 /* now we want a pathname, or empty meaning NEGATIVE */
153 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
154 goto out;
155 dprintk("Path seems to be <%s>\n", buf);
156 err = 0;
157 if (len == 0) {
158 struct svc_expkey *ek;
159 set_bit(CACHE_NEGATIVE, &key.h.flags);
160 ek = svc_expkey_lookup(&key, 1);
161 if (ek)
162 expkey_put(&ek->h, &svc_expkey_cache);
163 } else {
164 struct nameidata nd;
165 struct svc_expkey *ek;
166 struct svc_export *exp;
167 err = path_lookup(buf, 0, &nd);
168 if (err)
169 goto out;
170
171 dprintk("Found the path %s\n", buf);
172 exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
173
174 err = -ENOENT;
175 if (!exp)
176 goto out_nd;
177 key.ek_export = exp;
178 dprintk("And found export\n");
179
180 ek = svc_expkey_lookup(&key, 1);
181 if (ek)
182 expkey_put(&ek->h, &svc_expkey_cache);
183 exp_put(exp);
184 err = 0;
185 out_nd:
186 path_release(&nd);
187 }
188 cache_flush();
189 out:
190 if (dom)
191 auth_domain_put(dom);
192 if (buf)
193 kfree(buf);
194 return err;
195}
196
197static int expkey_show(struct seq_file *m,
198 struct cache_detail *cd,
199 struct cache_head *h)
200{
201 struct svc_expkey *ek ;
202
203 if (h ==NULL) {
204 seq_puts(m, "#domain fsidtype fsid [path]\n");
205 return 0;
206 }
207 ek = container_of(h, struct svc_expkey, h);
208 seq_printf(m, "%s %d 0x%08x", ek->ek_client->name,
209 ek->ek_fsidtype, ek->ek_fsid[0]);
210 if (ek->ek_fsidtype != 1)
211 seq_printf(m, "%08x", ek->ek_fsid[1]);
212 if (ek->ek_fsidtype == 2)
213 seq_printf(m, "%08x", ek->ek_fsid[2]);
214 if (test_bit(CACHE_VALID, &h->flags) &&
215 !test_bit(CACHE_NEGATIVE, &h->flags)) {
216 seq_printf(m, " ");
217 seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n");
218 }
219 seq_printf(m, "\n");
220 return 0;
221}
222
223struct cache_detail svc_expkey_cache = {
224 .hash_size = EXPKEY_HASHMAX,
225 .hash_table = expkey_table,
226 .name = "nfsd.fh",
227 .cache_put = expkey_put,
228 .cache_request = expkey_request,
229 .cache_parse = expkey_parse,
230 .cache_show = expkey_show,
231};
232
233static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b)
234{
235 if (a->ek_fsidtype != b->ek_fsidtype ||
236 a->ek_client != b->ek_client ||
237 memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0)
238 return 0;
239 return 1;
240}
241
242static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item)
243{
244 cache_get(&item->ek_client->h);
245 new->ek_client = item->ek_client;
246 new->ek_fsidtype = item->ek_fsidtype;
247 new->ek_fsid[0] = item->ek_fsid[0];
248 new->ek_fsid[1] = item->ek_fsid[1];
249 new->ek_fsid[2] = item->ek_fsid[2];
250}
251
252static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item)
253{
254 cache_get(&item->ek_export->h);
255 new->ek_export = item->ek_export;
256}
257
258static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */
259
260#define EXPORT_HASHBITS 8
261#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
262#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
263
264static struct cache_head *export_table[EXPORT_HASHMAX];
265
266static inline int svc_export_hash(struct svc_export *item)
267{
268 int rv;
269
270 rv = hash_ptr(item->ex_client, EXPORT_HASHBITS);
271 rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS);
272 rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS);
273 return rv;
274}
275
276void svc_export_put(struct cache_head *item, struct cache_detail *cd)
277{
278 if (cache_put(item, cd)) {
279 struct svc_export *exp = container_of(item, struct svc_export, h);
280 dput(exp->ex_dentry);
281 mntput(exp->ex_mnt);
282 auth_domain_put(exp->ex_client);
283 kfree(exp);
284 }
285}
286
287static void svc_export_request(struct cache_detail *cd,
288 struct cache_head *h,
289 char **bpp, int *blen)
290{
291 /* client path */
292 struct svc_export *exp = container_of(h, struct svc_export, h);
293 char *pth;
294
295 qword_add(bpp, blen, exp->ex_client->name);
296 pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen);
297 if (IS_ERR(pth)) {
298 /* is this correct? */
299 (*bpp)[0] = '\n';
300 return;
301 }
302 qword_add(bpp, blen, pth);
303 (*bpp)[-1] = '\n';
304}
305
306static struct svc_export *svc_export_lookup(struct svc_export *, int);
307
308static int check_export(struct inode *inode, int flags)
309{
310
311 /* We currently export only dirs and regular files.
312 * This is what umountd does.
313 */
314 if (!S_ISDIR(inode->i_mode) &&
315 !S_ISREG(inode->i_mode))
316 return -ENOTDIR;
317
318 /* There are two requirements on a filesystem to be exportable.
319 * 1: We must be able to identify the filesystem from a number.
320 * either a device number (so FS_REQUIRES_DEV needed)
321 * or an FSID number (so NFSEXP_FSID needed).
322 * 2: We must be able to find an inode from a filehandle.
323 * This means that s_export_op must be set.
324 */
325 if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
326 !(flags & NFSEXP_FSID)) {
327 dprintk("exp_export: export of non-dev fs without fsid");
328 return -EINVAL;
329 }
330 if (!inode->i_sb->s_export_op) {
331 dprintk("exp_export: export of invalid fs type.\n");
332 return -EINVAL;
333 }
334
335 /* Ok, we can export it */;
336 if (!inode->i_sb->s_export_op->find_exported_dentry)
337 inode->i_sb->s_export_op->find_exported_dentry =
338 find_exported_dentry;
339 return 0;
340
341}
342
343static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
344{
345 /* client path expiry [flags anonuid anongid fsid] */
346 char *buf;
347 int len;
348 int err;
349 struct auth_domain *dom = NULL;
350 struct nameidata nd;
351 struct svc_export exp, *expp;
352 int an_int;
353
354 nd.dentry = NULL;
355
356 if (mesg[mlen-1] != '\n')
357 return -EINVAL;
358 mesg[mlen-1] = 0;
359
360 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
361 err = -ENOMEM;
362 if (!buf) goto out;
363
364 /* client */
365 len = qword_get(&mesg, buf, PAGE_SIZE);
366 err = -EINVAL;
367 if (len <= 0) goto out;
368
369 err = -ENOENT;
370 dom = auth_domain_find(buf);
371 if (!dom)
372 goto out;
373
374 /* path */
375 err = -EINVAL;
376 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
377 goto out;
378 err = path_lookup(buf, 0, &nd);
379 if (err) goto out;
380
381 exp.h.flags = 0;
382 exp.ex_client = dom;
383 exp.ex_mnt = nd.mnt;
384 exp.ex_dentry = nd.dentry;
385
386 /* expiry */
387 err = -EINVAL;
388 exp.h.expiry_time = get_expiry(&mesg);
389 if (exp.h.expiry_time == 0)
390 goto out;
391
392 /* flags */
393 err = get_int(&mesg, &an_int);
394 if (err == -ENOENT)
395 set_bit(CACHE_NEGATIVE, &exp.h.flags);
396 else {
397 if (err || an_int < 0) goto out;
398 exp.ex_flags= an_int;
399
400 /* anon uid */
401 err = get_int(&mesg, &an_int);
402 if (err) goto out;
403 exp.ex_anon_uid= an_int;
404
405 /* anon gid */
406 err = get_int(&mesg, &an_int);
407 if (err) goto out;
408 exp.ex_anon_gid= an_int;
409
410 /* fsid */
411 err = get_int(&mesg, &an_int);
412 if (err) goto out;
413 exp.ex_fsid = an_int;
414
415 err = check_export(nd.dentry->d_inode, exp.ex_flags);
416 if (err) goto out;
417 }
418
419 expp = svc_export_lookup(&exp, 1);
420 if (expp)
421 exp_put(expp);
422 err = 0;
423 cache_flush();
424 out:
425 if (nd.dentry)
426 path_release(&nd);
427 if (dom)
428 auth_domain_put(dom);
429 if (buf)
430 kfree(buf);
431 return err;
432}
433
434static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong);
435
436static int svc_export_show(struct seq_file *m,
437 struct cache_detail *cd,
438 struct cache_head *h)
439{
440 struct svc_export *exp ;
441
442 if (h ==NULL) {
443 seq_puts(m, "#path domain(flags)\n");
444 return 0;
445 }
446 exp = container_of(h, struct svc_export, h);
447 seq_path(m, exp->ex_mnt, exp->ex_dentry, " \t\n\\");
448 seq_putc(m, '\t');
449 seq_escape(m, exp->ex_client->name, " \t\n\\");
450 seq_putc(m, '(');
451 if (test_bit(CACHE_VALID, &h->flags) &&
452 !test_bit(CACHE_NEGATIVE, &h->flags))
453 exp_flags(m, exp->ex_flags, exp->ex_fsid,
454 exp->ex_anon_uid, exp->ex_anon_gid);
455 seq_puts(m, ")\n");
456 return 0;
457}
458struct cache_detail svc_export_cache = {
459 .hash_size = EXPORT_HASHMAX,
460 .hash_table = export_table,
461 .name = "nfsd.export",
462 .cache_put = svc_export_put,
463 .cache_request = svc_export_request,
464 .cache_parse = svc_export_parse,
465 .cache_show = svc_export_show,
466};
467
468static inline int svc_export_match(struct svc_export *a, struct svc_export *b)
469{
470 return a->ex_client == b->ex_client &&
471 a->ex_dentry == b->ex_dentry &&
472 a->ex_mnt == b->ex_mnt;
473}
474static inline void svc_export_init(struct svc_export *new, struct svc_export *item)
475{
476 cache_get(&item->ex_client->h);
477 new->ex_client = item->ex_client;
478 new->ex_dentry = dget(item->ex_dentry);
479 new->ex_mnt = mntget(item->ex_mnt);
480}
481
482static inline void svc_export_update(struct svc_export *new, struct svc_export *item)
483{
484 new->ex_flags = item->ex_flags;
485 new->ex_anon_uid = item->ex_anon_uid;
486 new->ex_anon_gid = item->ex_anon_gid;
487 new->ex_fsid = item->ex_fsid;
488}
489
490static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */
491
492
493struct svc_expkey *
494exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
495{
496 struct svc_expkey key, *ek;
497 int err;
498
499 if (!clp)
500 return NULL;
501
502 key.ek_client = clp;
503 key.ek_fsidtype = fsid_type;
504 memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
505
506 ek = svc_expkey_lookup(&key, 0);
507 if (ek != NULL)
508 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
509 ek = ERR_PTR(err);
510 return ek;
511}
512
513static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
514 struct svc_export *exp)
515{
516 struct svc_expkey key, *ek;
517
518 key.ek_client = clp;
519 key.ek_fsidtype = fsid_type;
520 memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
521 key.ek_export = exp;
522 key.h.expiry_time = NEVER;
523 key.h.flags = 0;
524
525 ek = svc_expkey_lookup(&key, 1);
526 if (ek) {
527 expkey_put(&ek->h, &svc_expkey_cache);
528 return 0;
529 }
530 return -ENOMEM;
531}
532
533/*
534 * Find the client's export entry matching xdev/xino.
535 */
536static inline struct svc_expkey *
537exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
538{
539 u32 fsidv[3];
540
541 if (old_valid_dev(dev)) {
542 mk_fsid_v0(fsidv, dev, ino);
543 return exp_find_key(clp, 0, fsidv, NULL);
544 }
545 mk_fsid_v3(fsidv, dev, ino);
546 return exp_find_key(clp, 3, fsidv, NULL);
547}
548
549/*
550 * Find the client's export entry matching fsid
551 */
552static inline struct svc_expkey *
553exp_get_fsid_key(svc_client *clp, int fsid)
554{
555 u32 fsidv[2];
556
557 mk_fsid_v1(fsidv, fsid);
558
559 return exp_find_key(clp, 1, fsidv, NULL);
560}
561
562svc_export *
563exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
564 struct cache_req *reqp)
565{
566 struct svc_export *exp, key;
567
568 if (!clp)
569 return NULL;
570
571 key.ex_client = clp;
572 key.ex_mnt = mnt;
573 key.ex_dentry = dentry;
574
575 exp = svc_export_lookup(&key, 0);
576 if (exp != NULL)
577 switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
578 case 0: break;
579 case -EAGAIN:
580 exp = ERR_PTR(-EAGAIN);
581 break;
582 default:
583 exp = NULL;
584 }
585
586 return exp;
587}
588
589/*
590 * Find the export entry for a given dentry.
591 */
592struct svc_export *
593exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
594 struct cache_req *reqp)
595{
596 svc_export *exp;
597
598 dget(dentry);
599 exp = exp_get_by_name(clp, mnt, dentry, reqp);
600
601 while (exp == NULL && !IS_ROOT(dentry)) {
602 struct dentry *parent;
603
604 parent = dget_parent(dentry);
605 dput(dentry);
606 dentry = parent;
607 exp = exp_get_by_name(clp, mnt, dentry, reqp);
608 }
609 dput(dentry);
610 return exp;
611}
612
613/*
614 * Hashtable locking. Write locks are placed only by user processes
615 * wanting to modify export information.
616 * Write locking only done in this file. Read locking
617 * needed externally.
618 */
619
620static DECLARE_RWSEM(hash_sem);
621
622void
623exp_readlock(void)
624{
625 down_read(&hash_sem);
626}
627
628static inline void
629exp_writelock(void)
630{
631 down_write(&hash_sem);
632}
633
634void
635exp_readunlock(void)
636{
637 up_read(&hash_sem);
638}
639
640static inline void
641exp_writeunlock(void)
642{
643 up_write(&hash_sem);
644}
645
646static void exp_fsid_unhash(struct svc_export *exp)
647{
648 struct svc_expkey *ek;
649
650 if ((exp->ex_flags & NFSEXP_FSID) == 0)
651 return;
652
653 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
654 if (ek && !IS_ERR(ek)) {
655 ek->h.expiry_time = get_seconds()-1;
656 expkey_put(&ek->h, &svc_expkey_cache);
657 }
658 svc_expkey_cache.nextcheck = get_seconds();
659}
660
661static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
662{
663 u32 fsid[2];
664
665 if ((exp->ex_flags & NFSEXP_FSID) == 0)
666 return 0;
667
668 mk_fsid_v1(fsid, exp->ex_fsid);
669 return exp_set_key(clp, 1, fsid, exp);
670}
671
672static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
673{
674 u32 fsid[2];
675 struct inode *inode = exp->ex_dentry->d_inode;
676 dev_t dev = inode->i_sb->s_dev;
677
678 if (old_valid_dev(dev)) {
679 mk_fsid_v0(fsid, dev, inode->i_ino);
680 return exp_set_key(clp, 0, fsid, exp);
681 }
682 mk_fsid_v3(fsid, dev, inode->i_ino);
683 return exp_set_key(clp, 3, fsid, exp);
684}
685
686static void exp_unhash(struct svc_export *exp)
687{
688 struct svc_expkey *ek;
689 struct inode *inode = exp->ex_dentry->d_inode;
690
691 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
692 if (ek && !IS_ERR(ek)) {
693 ek->h.expiry_time = get_seconds()-1;
694 expkey_put(&ek->h, &svc_expkey_cache);
695 }
696 svc_expkey_cache.nextcheck = get_seconds();
697}
698
699/*
700 * Export a file system.
701 */
702int
703exp_export(struct nfsctl_export *nxp)
704{
705 svc_client *clp;
706 struct svc_export *exp = NULL;
707 struct svc_export new;
708 struct svc_expkey *fsid_key = NULL;
709 struct nameidata nd;
710 int err;
711
712 /* Consistency check */
713 err = -EINVAL;
714 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
715 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
716 goto out;
717
718 dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
719 nxp->ex_client, nxp->ex_path,
720 (unsigned)nxp->ex_dev, (long)nxp->ex_ino,
721 nxp->ex_flags);
722
723 /* Try to lock the export table for update */
724 exp_writelock();
725
726 /* Look up client info */
727 if (!(clp = auth_domain_find(nxp->ex_client)))
728 goto out_unlock;
729
730
731 /* Look up the dentry */
732 err = path_lookup(nxp->ex_path, 0, &nd);
733 if (err)
734 goto out_unlock;
735 err = -EINVAL;
736
737 exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
738
739 /* must make sure there won't be an ex_fsid clash */
740 if ((nxp->ex_flags & NFSEXP_FSID) &&
741 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
742 !IS_ERR(fsid_key) &&
743 fsid_key->ek_export &&
744 fsid_key->ek_export != exp)
745 goto finish;
746
747 if (exp) {
748 /* just a flags/id/fsid update */
749
750 exp_fsid_unhash(exp);
751 exp->ex_flags = nxp->ex_flags;
752 exp->ex_anon_uid = nxp->ex_anon_uid;
753 exp->ex_anon_gid = nxp->ex_anon_gid;
754 exp->ex_fsid = nxp->ex_dev;
755
756 err = exp_fsid_hash(clp, exp);
757 goto finish;
758 }
759
760 err = check_export(nd.dentry->d_inode, nxp->ex_flags);
761 if (err) goto finish;
762
763 err = -ENOMEM;
764
765 dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
766
767 new.h.expiry_time = NEVER;
768 new.h.flags = 0;
769 new.ex_client = clp;
770 new.ex_mnt = nd.mnt;
771 new.ex_dentry = nd.dentry;
772 new.ex_flags = nxp->ex_flags;
773 new.ex_anon_uid = nxp->ex_anon_uid;
774 new.ex_anon_gid = nxp->ex_anon_gid;
775 new.ex_fsid = nxp->ex_dev;
776
777 exp = svc_export_lookup(&new, 1);
778
779 if (exp == NULL)
780 goto finish;
781
782 err = 0;
783
784 if (exp_hash(clp, exp) ||
785 exp_fsid_hash(clp, exp)) {
786 /* failed to create at least one index */
787 exp_do_unexport(exp);
788 cache_flush();
789 err = -ENOMEM;
790 }
791
792finish:
793 if (exp)
794 exp_put(exp);
795 if (fsid_key && !IS_ERR(fsid_key))
796 expkey_put(&fsid_key->h, &svc_expkey_cache);
797 if (clp)
798 auth_domain_put(clp);
799 path_release(&nd);
800out_unlock:
801 exp_writeunlock();
802out:
803 return err;
804}
805
806/*
807 * Unexport a file system. The export entry has already
808 * been removed from the client's list of exported fs's.
809 */
810static void
811exp_do_unexport(svc_export *unexp)
812{
813 unexp->h.expiry_time = get_seconds()-1;
814 svc_export_cache.nextcheck = get_seconds();
815 exp_unhash(unexp);
816 exp_fsid_unhash(unexp);
817}
818
819
820/*
821 * unexport syscall.
822 */
823int
824exp_unexport(struct nfsctl_export *nxp)
825{
826 struct auth_domain *dom;
827 svc_export *exp;
828 struct nameidata nd;
829 int err;
830
831 /* Consistency check */
832 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
833 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
834 return -EINVAL;
835
836 exp_writelock();
837
838 err = -EINVAL;
839 dom = auth_domain_find(nxp->ex_client);
840 if (!dom) {
841 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
842 goto out_unlock;
843 }
844
845 err = path_lookup(nxp->ex_path, 0, &nd);
846 if (err)
847 goto out_domain;
848
849 err = -EINVAL;
850 exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
851 path_release(&nd);
852 if (!exp)
853 goto out_domain;
854
855 exp_do_unexport(exp);
856 exp_put(exp);
857 err = 0;
858
859out_domain:
860 auth_domain_put(dom);
861 cache_flush();
862out_unlock:
863 exp_writeunlock();
864 return err;
865}
866
867/*
868 * Obtain the root fh on behalf of a client.
869 * This could be done in user space, but I feel that it adds some safety
870 * since its harder to fool a kernel module than a user space program.
871 */
872int
873exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
874{
875 struct svc_export *exp;
876 struct nameidata nd;
877 struct inode *inode;
878 struct svc_fh fh;
879 int err;
880
881 err = -EPERM;
882 /* NB: we probably ought to check that it's NUL-terminated */
883 if (path_lookup(path, 0, &nd)) {
884 printk("nfsd: exp_rootfh path not found %s", path);
885 return err;
886 }
887 inode = nd.dentry->d_inode;
888
889 dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
890 path, nd.dentry, clp->name,
891 inode->i_sb->s_id, inode->i_ino);
892 exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
893 if (!exp) {
894 dprintk("nfsd: exp_rootfh export not found.\n");
895 goto out;
896 }
897
898 /*
899 * fh must be initialized before calling fh_compose
900 */
901 fh_init(&fh, maxsize);
902 if (fh_compose(&fh, exp, nd.dentry, NULL))
903 err = -EINVAL;
904 else
905 err = 0;
906 memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
907 fh_put(&fh);
908 exp_put(exp);
909out:
910 path_release(&nd);
911 return err;
912}
913
914/*
915 * Called when we need the filehandle for the root of the pseudofs,
916 * for a given NFSv4 client. The root is defined to be the
917 * export point with fsid==0
918 */
919int
920exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
921 struct cache_req *creq)
922{
923 struct svc_expkey *fsid_key;
924 int rv;
925 u32 fsidv[2];
926
927 mk_fsid_v1(fsidv, 0);
928
929 fsid_key = exp_find_key(clp, 1, fsidv, creq);
930 if (IS_ERR(fsid_key) && PTR_ERR(fsid_key) == -EAGAIN)
931 return nfserr_dropit;
932 if (!fsid_key || IS_ERR(fsid_key))
933 return nfserr_perm;
934
935 rv = fh_compose(fhp, fsid_key->ek_export,
936 fsid_key->ek_export->ex_dentry, NULL);
937 expkey_put(&fsid_key->h, &svc_expkey_cache);
938 return rv;
939}
940
941/* Iterator */
942
943static void *e_start(struct seq_file *m, loff_t *pos)
944{
945 loff_t n = *pos;
946 unsigned hash, export;
947 struct cache_head *ch;
948
949 exp_readlock();
950 read_lock(&svc_export_cache.hash_lock);
951 if (!n--)
952 return (void *)1;
953 hash = n >> 32;
954 export = n & ((1LL<<32) - 1);
955
956
957 for (ch=export_table[hash]; ch; ch=ch->next)
958 if (!export--)
959 return ch;
960 n &= ~((1LL<<32) - 1);
961 do {
962 hash++;
963 n += 1LL<<32;
964 } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL);
965 if (hash >= EXPORT_HASHMAX)
966 return NULL;
967 *pos = n+1;
968 return export_table[hash];
969}
970
971static void *e_next(struct seq_file *m, void *p, loff_t *pos)
972{
973 struct cache_head *ch = p;
974 int hash = (*pos >> 32);
975
976 if (p == (void *)1)
977 hash = 0;
978 else if (ch->next == NULL) {
979 hash++;
980 *pos += 1LL<<32;
981 } else {
982 ++*pos;
983 return ch->next;
984 }
985 *pos &= ~((1LL<<32) - 1);
986 while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) {
987 hash++;
988 *pos += 1LL<<32;
989 }
990 if (hash >= EXPORT_HASHMAX)
991 return NULL;
992 ++*pos;
993 return export_table[hash];
994}
995
996static void e_stop(struct seq_file *m, void *p)
997{
998 read_unlock(&svc_export_cache.hash_lock);
999 exp_readunlock();
1000}
1001
1002static struct flags {
1003 int flag;
1004 char *name[2];
1005} expflags[] = {
1006 { NFSEXP_READONLY, {"ro", "rw"}},
1007 { NFSEXP_INSECURE_PORT, {"insecure", ""}},
1008 { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
1009 { NFSEXP_ALLSQUASH, {"all_squash", ""}},
1010 { NFSEXP_ASYNC, {"async", "sync"}},
1011 { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
1012 { NFSEXP_NOHIDE, {"nohide", ""}},
1013 { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
1014 { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
1015 { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
1016#ifdef MSNFS
1017 { NFSEXP_MSNFS, {"msnfs", ""}},
1018#endif
1019 { 0, {"", ""}}
1020};
1021
1022static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong)
1023{
1024 int first = 0;
1025 struct flags *flg;
1026
1027 for (flg = expflags; flg->flag; flg++) {
1028 int state = (flg->flag & flag)?0:1;
1029 if (*flg->name[state])
1030 seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
1031 }
1032 if (flag & NFSEXP_FSID)
1033 seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
1034 if (anonu != (uid_t)-2 && anonu != (0x10000-2))
1035 seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
1036 if (anong != (gid_t)-2 && anong != (0x10000-2))
1037 seq_printf(m, "%sanongid=%d", first++?",":"", anong);
1038}
1039
1040static int e_show(struct seq_file *m, void *p)
1041{
1042 struct cache_head *cp = p;
1043 struct svc_export *exp = container_of(cp, struct svc_export, h);
1044 svc_client *clp;
1045
1046 if (p == (void *)1) {
1047 seq_puts(m, "# Version 1.1\n");
1048 seq_puts(m, "# Path Client(Flags) # IPs\n");
1049 return 0;
1050 }
1051
1052 clp = exp->ex_client;
1053 cache_get(&exp->h);
1054 if (cache_check(&svc_export_cache, &exp->h, NULL))
1055 return 0;
1056 if (cache_put(&exp->h, &svc_export_cache)) BUG();
1057 return svc_export_show(m, &svc_export_cache, cp);
1058}
1059
1060struct seq_operations nfs_exports_op = {
1061 .start = e_start,
1062 .next = e_next,
1063 .stop = e_stop,
1064 .show = e_show,
1065};
1066
1067/*
1068 * Add or modify a client.
1069 * Change requests may involve the list of host addresses. The list of
1070 * exports and possibly existing uid maps are left untouched.
1071 */
1072int
1073exp_addclient(struct nfsctl_client *ncp)
1074{
1075 struct auth_domain *dom;
1076 int i, err;
1077
1078 /* First, consistency check. */
1079 err = -EINVAL;
1080 if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1081 goto out;
1082 if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
1083 goto out;
1084
1085 /* Lock the hashtable */
1086 exp_writelock();
1087
1088 dom = unix_domain_find(ncp->cl_ident);
1089
1090 err = -ENOMEM;
1091 if (!dom)
1092 goto out_unlock;
1093
1094 /* Insert client into hashtable. */
1095 for (i = 0; i < ncp->cl_naddr; i++)
1096 auth_unix_add_addr(ncp->cl_addrlist[i], dom);
1097
1098 auth_unix_forget_old(dom);
1099 auth_domain_put(dom);
1100
1101 err = 0;
1102
1103out_unlock:
1104 exp_writeunlock();
1105out:
1106 return err;
1107}
1108
1109/*
1110 * Delete a client given an identifier.
1111 */
1112int
1113exp_delclient(struct nfsctl_client *ncp)
1114{
1115 int err;
1116 struct auth_domain *dom;
1117
1118 err = -EINVAL;
1119 if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1120 goto out;
1121
1122 /* Lock the hashtable */
1123 exp_writelock();
1124
1125 dom = auth_domain_find(ncp->cl_ident);
1126 /* just make sure that no addresses work
1127 * and that it will expire soon
1128 */
1129 if (dom) {
1130 err = auth_unix_forget_old(dom);
1131 dom->h.expiry_time = get_seconds();
1132 auth_domain_put(dom);
1133 }
1134
1135 exp_writeunlock();
1136out:
1137 return err;
1138}
1139
1140/*
1141 * Verify that string is non-empty and does not exceed max length.
1142 */
1143static int
1144exp_verify_string(char *cp, int max)
1145{
1146 int i;
1147
1148 for (i = 0; i < max; i++)
1149 if (!cp[i])
1150 return i;
1151 cp[i] = 0;
1152 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
1153 return 0;
1154}
1155
1156/*
1157 * Initialize the exports module.
1158 */
1159void
1160nfsd_export_init(void)
1161{
1162 dprintk("nfsd: initializing export module.\n");
1163
1164 cache_register(&svc_export_cache);
1165 cache_register(&svc_expkey_cache);
1166
1167}
1168
1169/*
1170 * Flush exports table - called when last nfsd thread is killed
1171 */
1172void
1173nfsd_export_flush(void)
1174{
1175 exp_writelock();
1176 cache_purge(&svc_expkey_cache);
1177 cache_purge(&svc_export_cache);
1178 exp_writeunlock();
1179}
1180
1181/*
1182 * Shutdown the exports module.
1183 */
1184void
1185nfsd_export_shutdown(void)
1186{
1187
1188 dprintk("nfsd: shutting down export module.\n");
1189
1190 exp_writelock();
1191
1192 if (cache_unregister(&svc_expkey_cache))
1193 printk(KERN_ERR "nfsd: failed to unregister expkey cache\n");
1194 if (cache_unregister(&svc_export_cache))
1195 printk(KERN_ERR "nfsd: failed to unregister export cache\n");
1196 svcauth_unix_purge();
1197
1198 exp_writeunlock();
1199 dprintk("nfsd: export shutdown complete.\n");
1200}
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
new file mode 100644
index 000000000000..7b889ff15ae6
--- /dev/null
+++ b/fs/nfsd/lockd.c
@@ -0,0 +1,79 @@
1/*
2 * linux/fs/nfsd/lockd.c
3 *
4 * This file contains all the stubs needed when communicating with lockd.
5 * This level of indirection is necessary so we can run nfsd+lockd without
6 * requiring the nfs client to be compiled in/loaded, and vice versa.
7 *
8 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
9 */
10
11#include <linux/types.h>
12#include <linux/fs.h>
13#include <linux/file.h>
14#include <linux/mount.h>
15#include <linux/sunrpc/clnt.h>
16#include <linux/sunrpc/svc.h>
17#include <linux/nfsd/nfsd.h>
18#include <linux/lockd/bind.h>
19
20#define NFSDDBG_FACILITY NFSDDBG_LOCKD
21
22/*
23 * Note: we hold the dentry use count while the file is open.
24 */
25static u32
26nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
27{
28 u32 nfserr;
29 struct svc_fh fh;
30
31 /* must initialize before using! but maxsize doesn't matter */
32 fh_init(&fh,0);
33 fh.fh_handle.fh_size = f->size;
34 memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
35 fh.fh_export = NULL;
36
37 exp_readlock();
38 nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
39 fh_put(&fh);
40 rqstp->rq_client = NULL;
41 exp_readunlock();
42 /* nlm and nfsd don't share error codes.
43 * we invent: 0 = no error
44 * 1 = stale file handle
45 * 2 = other error
46 */
47 switch (nfserr) {
48 case nfs_ok:
49 return 0;
50 case nfserr_stale:
51 return 1;
52 default:
53 return 2;
54 }
55}
56
57static void
58nlm_fclose(struct file *filp)
59{
60 fput(filp);
61}
62
63static struct nlmsvc_binding nfsd_nlm_ops = {
64 .fopen = nlm_fopen, /* open file for locking */
65 .fclose = nlm_fclose, /* close file */
66};
67
68void
69nfsd_lockd_init(void)
70{
71 dprintk("nfsd: initializing lockd\n");
72 nlmsvc_ops = &nfsd_nlm_ops;
73}
74
75void
76nfsd_lockd_shutdown(void)
77{
78 nlmsvc_ops = NULL;
79}
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
new file mode 100644
index 000000000000..041380fe667b
--- /dev/null
+++ b/fs/nfsd/nfs3proc.c
@@ -0,0 +1,702 @@
1/*
2 * linux/fs/nfsd/nfs3proc.c
3 *
4 * Process version 3 NFS requests.
5 *
6 * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
7 */
8
9#include <linux/linkage.h>
10#include <linux/time.h>
11#include <linux/errno.h>
12#include <linux/fs.h>
13#include <linux/ext2_fs.h>
14#include <linux/stat.h>
15#include <linux/fcntl.h>
16#include <linux/net.h>
17#include <linux/in.h>
18#include <linux/unistd.h>
19#include <linux/slab.h>
20#include <linux/major.h>
21
22#include <linux/sunrpc/svc.h>
23#include <linux/nfsd/nfsd.h>
24#include <linux/nfsd/cache.h>
25#include <linux/nfsd/xdr3.h>
26#include <linux/nfs3.h>
27
28#define NFSDDBG_FACILITY NFSDDBG_PROC
29
30#define RETURN_STATUS(st) { resp->status = (st); return (st); }
31
32static int nfs3_ftypes[] = {
33 0, /* NF3NON */
34 S_IFREG, /* NF3REG */
35 S_IFDIR, /* NF3DIR */
36 S_IFBLK, /* NF3BLK */
37 S_IFCHR, /* NF3CHR */
38 S_IFLNK, /* NF3LNK */
39 S_IFSOCK, /* NF3SOCK */
40 S_IFIFO, /* NF3FIFO */
41};
42
43/*
44 * NULL call.
45 */
46static int
47nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
48{
49 return nfs_ok;
50}
51
52/*
53 * Get a file's attributes
54 */
55static int
56nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
57 struct nfsd3_attrstat *resp)
58{
59 int nfserr;
60
61 dprintk("nfsd: GETATTR(3) %s\n",
62 SVCFH_fmt(&argp->fh));
63
64 fh_copy(&resp->fh, &argp->fh);
65 nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
66 RETURN_STATUS(nfserr);
67}
68
69/*
70 * Set a file's attributes
71 */
72static int
73nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
74 struct nfsd3_attrstat *resp)
75{
76 int nfserr;
77
78 dprintk("nfsd: SETATTR(3) %s\n",
79 SVCFH_fmt(&argp->fh));
80
81 fh_copy(&resp->fh, &argp->fh);
82 nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
83 argp->check_guard, argp->guardtime);
84 RETURN_STATUS(nfserr);
85}
86
87/*
88 * Look up a path name component
89 */
90static int
91nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
92 struct nfsd3_diropres *resp)
93{
94 int nfserr;
95
96 dprintk("nfsd: LOOKUP(3) %s %.*s\n",
97 SVCFH_fmt(&argp->fh),
98 argp->len,
99 argp->name);
100
101 fh_copy(&resp->dirfh, &argp->fh);
102 fh_init(&resp->fh, NFS3_FHSIZE);
103
104 nfserr = nfsd_lookup(rqstp, &resp->dirfh,
105 argp->name,
106 argp->len,
107 &resp->fh);
108 RETURN_STATUS(nfserr);
109}
110
111/*
112 * Check file access
113 */
114static int
115nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
116 struct nfsd3_accessres *resp)
117{
118 int nfserr;
119
120 dprintk("nfsd: ACCESS(3) %s 0x%x\n",
121 SVCFH_fmt(&argp->fh),
122 argp->access);
123
124 fh_copy(&resp->fh, &argp->fh);
125 resp->access = argp->access;
126 nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
127 RETURN_STATUS(nfserr);
128}
129
130/*
131 * Read a symlink.
132 */
133static int
134nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp,
135 struct nfsd3_readlinkres *resp)
136{
137 int nfserr;
138
139 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
140
141 /* Read the symlink. */
142 fh_copy(&resp->fh, &argp->fh);
143 resp->len = NFS3_MAXPATHLEN;
144 nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
145 RETURN_STATUS(nfserr);
146}
147
148/*
149 * Read a portion of a file.
150 */
151static int
152nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
153 struct nfsd3_readres *resp)
154{
155 int nfserr;
156
157 dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
158 SVCFH_fmt(&argp->fh),
159 (unsigned long) argp->count,
160 (unsigned long) argp->offset);
161
162 /* Obtain buffer pointer for payload.
163 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
164 * + 1 (xdr opaque byte count) = 26
165 */
166
167 resp->count = argp->count;
168 if (NFSSVC_MAXBLKSIZE < resp->count)
169 resp->count = NFSSVC_MAXBLKSIZE;
170
171 svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
172
173 fh_copy(&resp->fh, &argp->fh);
174 nfserr = nfsd_read(rqstp, &resp->fh, NULL,
175 argp->offset,
176 argp->vec, argp->vlen,
177 &resp->count);
178 if (nfserr == 0) {
179 struct inode *inode = resp->fh.fh_dentry->d_inode;
180
181 resp->eof = (argp->offset + resp->count) >= inode->i_size;
182 }
183
184 RETURN_STATUS(nfserr);
185}
186
187/*
188 * Write data to a file
189 */
190static int
191nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
192 struct nfsd3_writeres *resp)
193{
194 int nfserr;
195
196 dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n",
197 SVCFH_fmt(&argp->fh),
198 argp->len,
199 (unsigned long) argp->offset,
200 argp->stable? " stable" : "");
201
202 fh_copy(&resp->fh, &argp->fh);
203 resp->committed = argp->stable;
204 nfserr = nfsd_write(rqstp, &resp->fh, NULL,
205 argp->offset,
206 argp->vec, argp->vlen,
207 argp->len,
208 &resp->committed);
209 resp->count = argp->count;
210 RETURN_STATUS(nfserr);
211}
212
213/*
214 * With NFSv3, CREATE processing is a lot easier than with NFSv2.
215 * At least in theory; we'll see how it fares in practice when the
216 * first reports about SunOS compatibility problems start to pour in...
217 */
218static int
219nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
220 struct nfsd3_diropres *resp)
221{
222 svc_fh *dirfhp, *newfhp = NULL;
223 struct iattr *attr;
224 u32 nfserr;
225
226 dprintk("nfsd: CREATE(3) %s %.*s\n",
227 SVCFH_fmt(&argp->fh),
228 argp->len,
229 argp->name);
230
231 dirfhp = fh_copy(&resp->dirfh, &argp->fh);
232 newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
233 attr = &argp->attrs;
234
235 /* Get the directory inode */
236 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE);
237 if (nfserr)
238 RETURN_STATUS(nfserr);
239
240 /* Unfudge the mode bits */
241 attr->ia_mode &= ~S_IFMT;
242 if (!(attr->ia_valid & ATTR_MODE)) {
243 attr->ia_valid |= ATTR_MODE;
244 attr->ia_mode = S_IFREG;
245 } else {
246 attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
247 }
248
249 /* Now create the file and set attributes */
250 nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len,
251 attr, newfhp,
252 argp->createmode, argp->verf, NULL);
253
254 RETURN_STATUS(nfserr);
255}
256
257/*
258 * Make directory. This operation is not idempotent.
259 */
260static int
261nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
262 struct nfsd3_diropres *resp)
263{
264 int nfserr;
265
266 dprintk("nfsd: MKDIR(3) %s %.*s\n",
267 SVCFH_fmt(&argp->fh),
268 argp->len,
269 argp->name);
270
271 argp->attrs.ia_valid &= ~ATTR_SIZE;
272 fh_copy(&resp->dirfh, &argp->fh);
273 fh_init(&resp->fh, NFS3_FHSIZE);
274 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
275 &argp->attrs, S_IFDIR, 0, &resp->fh);
276
277 RETURN_STATUS(nfserr);
278}
279
280static int
281nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
282 struct nfsd3_diropres *resp)
283{
284 int nfserr;
285
286 dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
287 SVCFH_fmt(&argp->ffh),
288 argp->flen, argp->fname,
289 argp->tlen, argp->tname);
290
291 fh_copy(&resp->dirfh, &argp->ffh);
292 fh_init(&resp->fh, NFS3_FHSIZE);
293 nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
294 argp->tname, argp->tlen,
295 &resp->fh, &argp->attrs);
296 RETURN_STATUS(nfserr);
297}
298
299/*
300 * Make socket/fifo/device.
301 */
302static int
303nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
304 struct nfsd3_diropres *resp)
305{
306 int nfserr, type;
307 dev_t rdev = 0;
308
309 dprintk("nfsd: MKNOD(3) %s %.*s\n",
310 SVCFH_fmt(&argp->fh),
311 argp->len,
312 argp->name);
313
314 fh_copy(&resp->dirfh, &argp->fh);
315 fh_init(&resp->fh, NFS3_FHSIZE);
316
317 if (argp->ftype == 0 || argp->ftype >= NF3BAD)
318 RETURN_STATUS(nfserr_inval);
319 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
320 rdev = MKDEV(argp->major, argp->minor);
321 if (MAJOR(rdev) != argp->major ||
322 MINOR(rdev) != argp->minor)
323 RETURN_STATUS(nfserr_inval);
324 } else
325 if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
326 RETURN_STATUS(nfserr_inval);
327
328 type = nfs3_ftypes[argp->ftype];
329 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
330 &argp->attrs, type, rdev, &resp->fh);
331
332 RETURN_STATUS(nfserr);
333}
334
335/*
336 * Remove file/fifo/socket etc.
337 */
338static int
339nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
340 struct nfsd3_attrstat *resp)
341{
342 int nfserr;
343
344 dprintk("nfsd: REMOVE(3) %s %.*s\n",
345 SVCFH_fmt(&argp->fh),
346 argp->len,
347 argp->name);
348
349 /* Unlink. -S_IFDIR means file must not be a directory */
350 fh_copy(&resp->fh, &argp->fh);
351 nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
352 RETURN_STATUS(nfserr);
353}
354
355/*
356 * Remove a directory
357 */
358static int
359nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
360 struct nfsd3_attrstat *resp)
361{
362 int nfserr;
363
364 dprintk("nfsd: RMDIR(3) %s %.*s\n",
365 SVCFH_fmt(&argp->fh),
366 argp->len,
367 argp->name);
368
369 fh_copy(&resp->fh, &argp->fh);
370 nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
371 RETURN_STATUS(nfserr);
372}
373
374static int
375nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp,
376 struct nfsd3_renameres *resp)
377{
378 int nfserr;
379
380 dprintk("nfsd: RENAME(3) %s %.*s ->\n",
381 SVCFH_fmt(&argp->ffh),
382 argp->flen,
383 argp->fname);
384 dprintk("nfsd: -> %s %.*s\n",
385 SVCFH_fmt(&argp->tfh),
386 argp->tlen,
387 argp->tname);
388
389 fh_copy(&resp->ffh, &argp->ffh);
390 fh_copy(&resp->tfh, &argp->tfh);
391 nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
392 &resp->tfh, argp->tname, argp->tlen);
393 RETURN_STATUS(nfserr);
394}
395
396static int
397nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp,
398 struct nfsd3_linkres *resp)
399{
400 int nfserr;
401
402 dprintk("nfsd: LINK(3) %s ->\n",
403 SVCFH_fmt(&argp->ffh));
404 dprintk("nfsd: -> %s %.*s\n",
405 SVCFH_fmt(&argp->tfh),
406 argp->tlen,
407 argp->tname);
408
409 fh_copy(&resp->fh, &argp->ffh);
410 fh_copy(&resp->tfh, &argp->tfh);
411 nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
412 &resp->fh);
413 RETURN_STATUS(nfserr);
414}
415
416/*
417 * Read a portion of a directory.
418 */
419static int
420nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
421 struct nfsd3_readdirres *resp)
422{
423 int nfserr, count;
424
425 dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
426 SVCFH_fmt(&argp->fh),
427 argp->count, (u32) argp->cookie);
428
429 /* Make sure we've room for the NULL ptr & eof flag, and shrink to
430 * client read size */
431 count = (argp->count >> 2) - 2;
432
433 /* Read directory and encode entries on the fly */
434 fh_copy(&resp->fh, &argp->fh);
435
436 resp->buflen = count;
437 resp->common.err = nfs_ok;
438 resp->buffer = argp->buffer;
439 resp->rqstp = rqstp;
440 nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie,
441 &resp->common, nfs3svc_encode_entry);
442 memcpy(resp->verf, argp->verf, 8);
443 resp->count = resp->buffer - argp->buffer;
444 if (resp->offset)
445 xdr_encode_hyper(resp->offset, argp->cookie);
446
447 RETURN_STATUS(nfserr);
448}
449
450/*
451 * Read a portion of a directory, including file handles and attrs.
452 * For now, we choose to ignore the dircount parameter.
453 */
454static int
455nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
456 struct nfsd3_readdirres *resp)
457{
458 int nfserr, count = 0;
459 loff_t offset;
460 int i;
461 caddr_t page_addr = NULL;
462
463 dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
464 SVCFH_fmt(&argp->fh),
465 argp->count, (u32) argp->cookie);
466
467 /* Convert byte count to number of words (i.e. >> 2),
468 * and reserve room for the NULL ptr & eof flag (-2 words) */
469 resp->count = (argp->count >> 2) - 2;
470
471 /* Read directory and encode entries on the fly */
472 fh_copy(&resp->fh, &argp->fh);
473
474 resp->common.err = nfs_ok;
475 resp->buffer = argp->buffer;
476 resp->buflen = resp->count;
477 resp->rqstp = rqstp;
478 offset = argp->cookie;
479 nfserr = nfsd_readdir(rqstp, &resp->fh,
480 &offset,
481 &resp->common,
482 nfs3svc_encode_entry_plus);
483 memcpy(resp->verf, argp->verf, 8);
484 for (i=1; i<rqstp->rq_resused ; i++) {
485 page_addr = page_address(rqstp->rq_respages[i]);
486
487 if (((caddr_t)resp->buffer >= page_addr) &&
488 ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
489 count += (caddr_t)resp->buffer - page_addr;
490 break;
491 }
492 count += PAGE_SIZE;
493 }
494 resp->count = count >> 2;
495 if (resp->offset) {
496 if (unlikely(resp->offset1)) {
497 /* we ended up with offset on a page boundary */
498 *resp->offset = htonl(offset >> 32);
499 *resp->offset1 = htonl(offset & 0xffffffff);
500 resp->offset1 = NULL;
501 } else {
502 xdr_encode_hyper(resp->offset, offset);
503 }
504 }
505
506 RETURN_STATUS(nfserr);
507}
508
509/*
510 * Get file system stats
511 */
512static int
513nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
514 struct nfsd3_fsstatres *resp)
515{
516 int nfserr;
517
518 dprintk("nfsd: FSSTAT(3) %s\n",
519 SVCFH_fmt(&argp->fh));
520
521 nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
522 fh_put(&argp->fh);
523 RETURN_STATUS(nfserr);
524}
525
526/*
527 * Get file system info
528 */
529static int
530nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
531 struct nfsd3_fsinfores *resp)
532{
533 int nfserr;
534
535 dprintk("nfsd: FSINFO(3) %s\n",
536 SVCFH_fmt(&argp->fh));
537
538 resp->f_rtmax = NFSSVC_MAXBLKSIZE;
539 resp->f_rtpref = NFSSVC_MAXBLKSIZE;
540 resp->f_rtmult = PAGE_SIZE;
541 resp->f_wtmax = NFSSVC_MAXBLKSIZE;
542 resp->f_wtpref = NFSSVC_MAXBLKSIZE;
543 resp->f_wtmult = PAGE_SIZE;
544 resp->f_dtpref = PAGE_SIZE;
545 resp->f_maxfilesize = ~(u32) 0;
546 resp->f_properties = NFS3_FSF_DEFAULT;
547
548 nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP);
549
550 /* Check special features of the file system. May request
551 * different read/write sizes for file systems known to have
552 * problems with large blocks */
553 if (nfserr == 0) {
554 struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
555
556 /* Note that we don't care for remote fs's here */
557 if (sb->s_magic == 0x4d44 /* MSDOS_SUPER_MAGIC */) {
558 resp->f_properties = NFS3_FSF_BILLYBOY;
559 }
560 resp->f_maxfilesize = sb->s_maxbytes;
561 }
562
563 fh_put(&argp->fh);
564 RETURN_STATUS(nfserr);
565}
566
567/*
568 * Get pathconf info for the specified file
569 */
570static int
571nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
572 struct nfsd3_pathconfres *resp)
573{
574 int nfserr;
575
576 dprintk("nfsd: PATHCONF(3) %s\n",
577 SVCFH_fmt(&argp->fh));
578
579 /* Set default pathconf */
580 resp->p_link_max = 255; /* at least */
581 resp->p_name_max = 255; /* at least */
582 resp->p_no_trunc = 0;
583 resp->p_chown_restricted = 1;
584 resp->p_case_insensitive = 0;
585 resp->p_case_preserving = 1;
586
587 nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP);
588
589 if (nfserr == 0) {
590 struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
591
592 /* Note that we don't care for remote fs's here */
593 switch (sb->s_magic) {
594 case EXT2_SUPER_MAGIC:
595 resp->p_link_max = EXT2_LINK_MAX;
596 resp->p_name_max = EXT2_NAME_LEN;
597 break;
598 case 0x4d44: /* MSDOS_SUPER_MAGIC */
599 resp->p_case_insensitive = 1;
600 resp->p_case_preserving = 0;
601 break;
602 }
603 }
604
605 fh_put(&argp->fh);
606 RETURN_STATUS(nfserr);
607}
608
609
610/*
611 * Commit a file (range) to stable storage.
612 */
613static int
614nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp,
615 struct nfsd3_commitres *resp)
616{
617 int nfserr;
618
619 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
620 SVCFH_fmt(&argp->fh),
621 argp->count,
622 (unsigned long long) argp->offset);
623
624 if (argp->offset > NFS_OFFSET_MAX)
625 RETURN_STATUS(nfserr_inval);
626
627 fh_copy(&resp->fh, &argp->fh);
628 nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
629
630 RETURN_STATUS(nfserr);
631}
632
633
634/*
635 * NFSv3 Server procedures.
636 * Only the results of non-idempotent operations are cached.
637 */
638#define nfs3svc_decode_voidargs NULL
639#define nfs3svc_release_void NULL
640#define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle
641#define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
642#define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
643#define nfsd3_mkdirargs nfsd3_createargs
644#define nfsd3_readdirplusargs nfsd3_readdirargs
645#define nfsd3_fhandleargs nfsd_fhandle
646#define nfsd3_fhandleres nfsd3_attrstat
647#define nfsd3_attrstatres nfsd3_attrstat
648#define nfsd3_wccstatres nfsd3_attrstat
649#define nfsd3_createres nfsd3_diropres
650#define nfsd3_voidres nfsd3_voidargs
651struct nfsd3_voidargs { int dummy; };
652
653#define PROC(name, argt, rest, relt, cache, respsize) \
654 { (svc_procfunc) nfsd3_proc_##name, \
655 (kxdrproc_t) nfs3svc_decode_##argt##args, \
656 (kxdrproc_t) nfs3svc_encode_##rest##res, \
657 (kxdrproc_t) nfs3svc_release_##relt, \
658 sizeof(struct nfsd3_##argt##args), \
659 sizeof(struct nfsd3_##rest##res), \
660 0, \
661 cache, \
662 respsize, \
663 }
664
665#define ST 1 /* status*/
666#define FH 17 /* filehandle with length */
667#define AT 21 /* attributes */
668#define pAT (1+AT) /* post attributes - conditional */
669#define WC (7+pAT) /* WCC attributes */
670
671static struct svc_procedure nfsd_procedures3[22] = {
672 PROC(null, void, void, void, RC_NOCACHE, ST),
673 PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
674 PROC(setattr, sattr, wccstat, fhandle, RC_REPLBUFF, ST+WC),
675 PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
676 PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1),
677 PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
678 PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE),
679 PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4),
680 PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
681 PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
682 PROC(symlink, symlink, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
683 PROC(mknod, mknod, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
684 PROC(remove, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
685 PROC(rmdir, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
686 PROC(rename, rename, rename, fhandle2, RC_REPLBUFF, ST+WC+WC),
687 PROC(link, link, link, fhandle2, RC_REPLBUFF, ST+pAT+WC),
688 PROC(readdir, readdir, readdir, fhandle, RC_NOCACHE, 0),
689 PROC(readdirplus,readdirplus, readdir, fhandle, RC_NOCACHE, 0),
690 PROC(fsstat, fhandle, fsstat, void, RC_NOCACHE, ST+pAT+2*6+1),
691 PROC(fsinfo, fhandle, fsinfo, void, RC_NOCACHE, ST+pAT+12),
692 PROC(pathconf, fhandle, pathconf, void, RC_NOCACHE, ST+pAT+6),
693 PROC(commit, commit, commit, fhandle, RC_NOCACHE, ST+WC+2),
694};
695
696struct svc_version nfsd_version3 = {
697 .vs_vers = 3,
698 .vs_nproc = 22,
699 .vs_proc = nfsd_procedures3,
700 .vs_dispatch = nfsd_dispatch,
701 .vs_xdrsize = NFS3_SVC_XDRSIZE,
702};
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
new file mode 100644
index 000000000000..11f806835c5a
--- /dev/null
+++ b/fs/nfsd/nfs3xdr.c
@@ -0,0 +1,1092 @@
1/*
2 * linux/fs/nfsd/nfs3xdr.c
3 *
4 * XDR support for nfsd/protocol version 3.
5 *
6 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
7 *
8 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
9 */
10
11#include <linux/types.h>
12#include <linux/time.h>
13#include <linux/nfs3.h>
14#include <linux/list.h>
15#include <linux/spinlock.h>
16#include <linux/dcache.h>
17#include <linux/namei.h>
18#include <linux/mm.h>
19#include <linux/vfs.h>
20#include <linux/sunrpc/xdr.h>
21#include <linux/sunrpc/svc.h>
22#include <linux/nfsd/nfsd.h>
23#include <linux/nfsd/xdr3.h>
24
25#define NFSDDBG_FACILITY NFSDDBG_XDR
26
27#ifdef NFSD_OPTIMIZE_SPACE
28# define inline
29#endif
30
31
32/*
33 * Mapping of S_IF* types to NFS file types
34 */
35static u32 nfs3_ftypes[] = {
36 NF3NON, NF3FIFO, NF3CHR, NF3BAD,
37 NF3DIR, NF3BAD, NF3BLK, NF3BAD,
38 NF3REG, NF3BAD, NF3LNK, NF3BAD,
39 NF3SOCK, NF3BAD, NF3LNK, NF3BAD,
40};
41
42/*
43 * XDR functions for basic NFS types
44 */
45static inline u32 *
46encode_time3(u32 *p, struct timespec *time)
47{
48 *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
49 return p;
50}
51
52static inline u32 *
53decode_time3(u32 *p, struct timespec *time)
54{
55 time->tv_sec = ntohl(*p++);
56 time->tv_nsec = ntohl(*p++);
57 return p;
58}
59
60static inline u32 *
61decode_fh(u32 *p, struct svc_fh *fhp)
62{
63 unsigned int size;
64 fh_init(fhp, NFS3_FHSIZE);
65 size = ntohl(*p++);
66 if (size > NFS3_FHSIZE)
67 return NULL;
68
69 memcpy(&fhp->fh_handle.fh_base, p, size);
70 fhp->fh_handle.fh_size = size;
71 return p + XDR_QUADLEN(size);
72}
73
74static inline u32 *
75encode_fh(u32 *p, struct svc_fh *fhp)
76{
77 unsigned int size = fhp->fh_handle.fh_size;
78 *p++ = htonl(size);
79 if (size) p[XDR_QUADLEN(size)-1]=0;
80 memcpy(p, &fhp->fh_handle.fh_base, size);
81 return p + XDR_QUADLEN(size);
82}
83
84/*
85 * Decode a file name and make sure that the path contains
86 * no slashes or null bytes.
87 */
88static inline u32 *
89decode_filename(u32 *p, char **namp, int *lenp)
90{
91 char *name;
92 int i;
93
94 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
95 for (i = 0, name = *namp; i < *lenp; i++, name++) {
96 if (*name == '\0' || *name == '/')
97 return NULL;
98 }
99 }
100
101 return p;
102}
103
104static inline u32 *
105decode_sattr3(u32 *p, struct iattr *iap)
106{
107 u32 tmp;
108
109 iap->ia_valid = 0;
110
111 if (*p++) {
112 iap->ia_valid |= ATTR_MODE;
113 iap->ia_mode = ntohl(*p++);
114 }
115 if (*p++) {
116 iap->ia_valid |= ATTR_UID;
117 iap->ia_uid = ntohl(*p++);
118 }
119 if (*p++) {
120 iap->ia_valid |= ATTR_GID;
121 iap->ia_gid = ntohl(*p++);
122 }
123 if (*p++) {
124 u64 newsize;
125
126 iap->ia_valid |= ATTR_SIZE;
127 p = xdr_decode_hyper(p, &newsize);
128 if (newsize <= NFS_OFFSET_MAX)
129 iap->ia_size = newsize;
130 else
131 iap->ia_size = NFS_OFFSET_MAX;
132 }
133 if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
134 iap->ia_valid |= ATTR_ATIME;
135 } else if (tmp == 2) { /* set to client time */
136 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
137 iap->ia_atime.tv_sec = ntohl(*p++);
138 iap->ia_atime.tv_nsec = ntohl(*p++);
139 }
140 if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
141 iap->ia_valid |= ATTR_MTIME;
142 } else if (tmp == 2) { /* set to client time */
143 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
144 iap->ia_mtime.tv_sec = ntohl(*p++);
145 iap->ia_mtime.tv_nsec = ntohl(*p++);
146 }
147 return p;
148}
149
150static inline u32 *
151encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
152{
153 struct vfsmount *mnt = fhp->fh_export->ex_mnt;
154 struct dentry *dentry = fhp->fh_dentry;
155 struct kstat stat;
156 struct timespec time;
157
158 vfs_getattr(mnt, dentry, &stat);
159
160 *p++ = htonl(nfs3_ftypes[(stat.mode & S_IFMT) >> 12]);
161 *p++ = htonl((u32) stat.mode);
162 *p++ = htonl((u32) stat.nlink);
163 *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid));
164 *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
165 if (S_ISLNK(stat.mode) && stat.size > NFS3_MAXPATHLEN) {
166 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
167 } else {
168 p = xdr_encode_hyper(p, (u64) stat.size);
169 }
170 p = xdr_encode_hyper(p, ((u64)stat.blocks) << 9);
171 *p++ = htonl((u32) MAJOR(stat.rdev));
172 *p++ = htonl((u32) MINOR(stat.rdev));
173 if (is_fsid(fhp, rqstp->rq_reffh))
174 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
175 else
176 p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat.dev));
177 p = xdr_encode_hyper(p, (u64) stat.ino);
178 p = encode_time3(p, &stat.atime);
179 lease_get_mtime(dentry->d_inode, &time);
180 p = encode_time3(p, &time);
181 p = encode_time3(p, &stat.ctime);
182
183 return p;
184}
185
186static inline u32 *
187encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
188{
189 struct inode *inode = fhp->fh_dentry->d_inode;
190
191 /* Attributes to follow */
192 *p++ = xdr_one;
193
194 *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]);
195 *p++ = htonl((u32) fhp->fh_post_mode);
196 *p++ = htonl((u32) fhp->fh_post_nlink);
197 *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
198 *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
199 if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
200 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
201 } else {
202 p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
203 }
204 p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
205 *p++ = fhp->fh_post_rdev[0];
206 *p++ = fhp->fh_post_rdev[1];
207 if (is_fsid(fhp, rqstp->rq_reffh))
208 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
209 else
210 p = xdr_encode_hyper(p, (u64)huge_encode_dev(inode->i_sb->s_dev));
211 p = xdr_encode_hyper(p, (u64) inode->i_ino);
212 p = encode_time3(p, &fhp->fh_post_atime);
213 p = encode_time3(p, &fhp->fh_post_mtime);
214 p = encode_time3(p, &fhp->fh_post_ctime);
215
216 return p;
217}
218
219/*
220 * Encode post-operation attributes.
221 * The inode may be NULL if the call failed because of a stale file
222 * handle. In this case, no attributes are returned.
223 */
224static u32 *
225encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
226{
227 struct dentry *dentry = fhp->fh_dentry;
228 if (dentry && dentry->d_inode != NULL) {
229 *p++ = xdr_one; /* attributes follow */
230 return encode_fattr3(rqstp, p, fhp);
231 }
232 *p++ = xdr_zero;
233 return p;
234}
235
236/*
237 * Enocde weak cache consistency data
238 */
239static u32 *
240encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
241{
242 struct dentry *dentry = fhp->fh_dentry;
243
244 if (dentry && dentry->d_inode && fhp->fh_post_saved) {
245 if (fhp->fh_pre_saved) {
246 *p++ = xdr_one;
247 p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
248 p = encode_time3(p, &fhp->fh_pre_mtime);
249 p = encode_time3(p, &fhp->fh_pre_ctime);
250 } else {
251 *p++ = xdr_zero;
252 }
253 return encode_saved_post_attr(rqstp, p, fhp);
254 }
255 /* no pre- or post-attrs */
256 *p++ = xdr_zero;
257 return encode_post_op_attr(rqstp, p, fhp);
258}
259
260
261/*
262 * XDR decode functions
263 */
264int
265nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args)
266{
267 if (!(p = decode_fh(p, &args->fh)))
268 return 0;
269 return xdr_argsize_check(rqstp, p);
270}
271
272int
273nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
274 struct nfsd3_sattrargs *args)
275{
276 if (!(p = decode_fh(p, &args->fh))
277 || !(p = decode_sattr3(p, &args->attrs)))
278 return 0;
279
280 if ((args->check_guard = ntohl(*p++)) != 0) {
281 struct timespec time;
282 p = decode_time3(p, &time);
283 args->guardtime = time.tv_sec;
284 }
285
286 return xdr_argsize_check(rqstp, p);
287}
288
289int
290nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
291 struct nfsd3_diropargs *args)
292{
293 if (!(p = decode_fh(p, &args->fh))
294 || !(p = decode_filename(p, &args->name, &args->len)))
295 return 0;
296
297 return xdr_argsize_check(rqstp, p);
298}
299
300int
301nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
302 struct nfsd3_accessargs *args)
303{
304 if (!(p = decode_fh(p, &args->fh)))
305 return 0;
306 args->access = ntohl(*p++);
307
308 return xdr_argsize_check(rqstp, p);
309}
310
311int
312nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
313 struct nfsd3_readargs *args)
314{
315 unsigned int len;
316 int v,pn;
317
318 if (!(p = decode_fh(p, &args->fh))
319 || !(p = xdr_decode_hyper(p, &args->offset)))
320 return 0;
321
322 len = args->count = ntohl(*p++);
323
324 if (len > NFSSVC_MAXBLKSIZE)
325 len = NFSSVC_MAXBLKSIZE;
326
327 /* set up the kvec */
328 v=0;
329 while (len > 0) {
330 pn = rqstp->rq_resused;
331 svc_take_page(rqstp);
332 args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
333 args->vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE;
334 len -= args->vec[v].iov_len;
335 v++;
336 }
337 args->vlen = v;
338 return xdr_argsize_check(rqstp, p);
339}
340
341int
342nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
343 struct nfsd3_writeargs *args)
344{
345 unsigned int len, v, hdr;
346
347 if (!(p = decode_fh(p, &args->fh))
348 || !(p = xdr_decode_hyper(p, &args->offset)))
349 return 0;
350
351 args->count = ntohl(*p++);
352 args->stable = ntohl(*p++);
353 len = args->len = ntohl(*p++);
354
355 hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
356 if (rqstp->rq_arg.len < len + hdr)
357 return 0;
358
359 args->vec[0].iov_base = (void*)p;
360 args->vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
361
362 if (len > NFSSVC_MAXBLKSIZE)
363 len = NFSSVC_MAXBLKSIZE;
364 v= 0;
365 while (len > args->vec[v].iov_len) {
366 len -= args->vec[v].iov_len;
367 v++;
368 args->vec[v].iov_base = page_address(rqstp->rq_argpages[v]);
369 args->vec[v].iov_len = PAGE_SIZE;
370 }
371 args->vec[v].iov_len = len;
372 args->vlen = v+1;
373
374 return args->count == args->len && args->vec[0].iov_len > 0;
375}
376
377int
378nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
379 struct nfsd3_createargs *args)
380{
381 if (!(p = decode_fh(p, &args->fh))
382 || !(p = decode_filename(p, &args->name, &args->len)))
383 return 0;
384
385 switch (args->createmode = ntohl(*p++)) {
386 case NFS3_CREATE_UNCHECKED:
387 case NFS3_CREATE_GUARDED:
388 if (!(p = decode_sattr3(p, &args->attrs)))
389 return 0;
390 break;
391 case NFS3_CREATE_EXCLUSIVE:
392 args->verf = p;
393 p += 2;
394 break;
395 default:
396 return 0;
397 }
398
399 return xdr_argsize_check(rqstp, p);
400}
401int
402nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, u32 *p,
403 struct nfsd3_createargs *args)
404{
405 if (!(p = decode_fh(p, &args->fh))
406 || !(p = decode_filename(p, &args->name, &args->len))
407 || !(p = decode_sattr3(p, &args->attrs)))
408 return 0;
409
410 return xdr_argsize_check(rqstp, p);
411}
412
413int
414nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
415 struct nfsd3_symlinkargs *args)
416{
417 unsigned int len;
418 int avail;
419 char *old, *new;
420 struct kvec *vec;
421
422 if (!(p = decode_fh(p, &args->ffh))
423 || !(p = decode_filename(p, &args->fname, &args->flen))
424 || !(p = decode_sattr3(p, &args->attrs))
425 )
426 return 0;
427 /* now decode the pathname, which might be larger than the first page.
428 * As we have to check for nul's anyway, we copy it into a new page
429 * This page appears in the rq_res.pages list, but as pages_len is always
430 * 0, it won't get in the way
431 */
432 svc_take_page(rqstp);
433 len = ntohl(*p++);
434 if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE)
435 return 0;
436 args->tname = new = page_address(rqstp->rq_respages[rqstp->rq_resused-1]);
437 args->tlen = len;
438 /* first copy and check from the first page */
439 old = (char*)p;
440 vec = &rqstp->rq_arg.head[0];
441 avail = vec->iov_len - (old - (char*)vec->iov_base);
442 while (len && avail && *old) {
443 *new++ = *old++;
444 len--;
445 avail--;
446 }
447 /* now copy next page if there is one */
448 if (len && !avail && rqstp->rq_arg.page_len) {
449 avail = rqstp->rq_arg.page_len;
450 if (avail > PAGE_SIZE) avail = PAGE_SIZE;
451 old = page_address(rqstp->rq_arg.pages[0]);
452 }
453 while (len && avail && *old) {
454 *new++ = *old++;
455 len--;
456 avail--;
457 }
458 *new = '\0';
459 if (len)
460 return 0;
461
462 return 1;
463}
464
465int
466nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, u32 *p,
467 struct nfsd3_mknodargs *args)
468{
469 if (!(p = decode_fh(p, &args->fh))
470 || !(p = decode_filename(p, &args->name, &args->len)))
471 return 0;
472
473 args->ftype = ntohl(*p++);
474
475 if (args->ftype == NF3BLK || args->ftype == NF3CHR
476 || args->ftype == NF3SOCK || args->ftype == NF3FIFO) {
477 if (!(p = decode_sattr3(p, &args->attrs)))
478 return 0;
479 }
480
481 if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
482 args->major = ntohl(*p++);
483 args->minor = ntohl(*p++);
484 }
485
486 return xdr_argsize_check(rqstp, p);
487}
488
489int
490nfs3svc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
491 struct nfsd3_renameargs *args)
492{
493 if (!(p = decode_fh(p, &args->ffh))
494 || !(p = decode_filename(p, &args->fname, &args->flen))
495 || !(p = decode_fh(p, &args->tfh))
496 || !(p = decode_filename(p, &args->tname, &args->tlen)))
497 return 0;
498
499 return xdr_argsize_check(rqstp, p);
500}
501
502int
503nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p,
504 struct nfsd3_readlinkargs *args)
505{
506 if (!(p = decode_fh(p, &args->fh)))
507 return 0;
508 svc_take_page(rqstp);
509 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]);
510
511 return xdr_argsize_check(rqstp, p);
512}
513
514int
515nfs3svc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
516 struct nfsd3_linkargs *args)
517{
518 if (!(p = decode_fh(p, &args->ffh))
519 || !(p = decode_fh(p, &args->tfh))
520 || !(p = decode_filename(p, &args->tname, &args->tlen)))
521 return 0;
522
523 return xdr_argsize_check(rqstp, p);
524}
525
526int
527nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
528 struct nfsd3_readdirargs *args)
529{
530 if (!(p = decode_fh(p, &args->fh)))
531 return 0;
532 p = xdr_decode_hyper(p, &args->cookie);
533 args->verf = p; p += 2;
534 args->dircount = ~0;
535 args->count = ntohl(*p++);
536
537 if (args->count > PAGE_SIZE)
538 args->count = PAGE_SIZE;
539
540 svc_take_page(rqstp);
541 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]);
542
543 return xdr_argsize_check(rqstp, p);
544}
545
546int
547nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
548 struct nfsd3_readdirargs *args)
549{
550 int len, pn;
551
552 if (!(p = decode_fh(p, &args->fh)))
553 return 0;
554 p = xdr_decode_hyper(p, &args->cookie);
555 args->verf = p; p += 2;
556 args->dircount = ntohl(*p++);
557 args->count = ntohl(*p++);
558
559 len = (args->count > NFSSVC_MAXBLKSIZE) ? NFSSVC_MAXBLKSIZE :
560 args->count;
561 args->count = len;
562
563 while (len > 0) {
564 pn = rqstp->rq_resused;
565 svc_take_page(rqstp);
566 if (!args->buffer)
567 args->buffer = page_address(rqstp->rq_respages[pn]);
568 len -= PAGE_SIZE;
569 }
570
571 return xdr_argsize_check(rqstp, p);
572}
573
574int
575nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
576 struct nfsd3_commitargs *args)
577{
578 if (!(p = decode_fh(p, &args->fh)))
579 return 0;
580 p = xdr_decode_hyper(p, &args->offset);
581 args->count = ntohl(*p++);
582
583 return xdr_argsize_check(rqstp, p);
584}
585
586/*
587 * XDR encode functions
588 */
589/*
590 * There must be an encoding function for void results so svc_process
591 * will work properly.
592 */
593int
594nfs3svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
595{
596 return xdr_ressize_check(rqstp, p);
597}
598
599/* GETATTR */
600int
601nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
602 struct nfsd3_attrstat *resp)
603{
604 if (resp->status == 0)
605 p = encode_fattr3(rqstp, p, &resp->fh);
606 return xdr_ressize_check(rqstp, p);
607}
608
609/* SETATTR, REMOVE, RMDIR */
610int
611nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p,
612 struct nfsd3_attrstat *resp)
613{
614 p = encode_wcc_data(rqstp, p, &resp->fh);
615 return xdr_ressize_check(rqstp, p);
616}
617
618/* LOOKUP */
619int
620nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
621 struct nfsd3_diropres *resp)
622{
623 if (resp->status == 0) {
624 p = encode_fh(p, &resp->fh);
625 p = encode_post_op_attr(rqstp, p, &resp->fh);
626 }
627 p = encode_post_op_attr(rqstp, p, &resp->dirfh);
628 return xdr_ressize_check(rqstp, p);
629}
630
631/* ACCESS */
632int
633nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
634 struct nfsd3_accessres *resp)
635{
636 p = encode_post_op_attr(rqstp, p, &resp->fh);
637 if (resp->status == 0)
638 *p++ = htonl(resp->access);
639 return xdr_ressize_check(rqstp, p);
640}
641
642/* READLINK */
643int
644nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
645 struct nfsd3_readlinkres *resp)
646{
647 p = encode_post_op_attr(rqstp, p, &resp->fh);
648 if (resp->status == 0) {
649 *p++ = htonl(resp->len);
650 xdr_ressize_check(rqstp, p);
651 rqstp->rq_res.page_len = resp->len;
652 if (resp->len & 3) {
653 /* need to pad the tail */
654 rqstp->rq_restailpage = 0;
655 rqstp->rq_res.tail[0].iov_base = p;
656 *p = 0;
657 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
658 }
659 return 1;
660 } else
661 return xdr_ressize_check(rqstp, p);
662}
663
664/* READ */
665int
666nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
667 struct nfsd3_readres *resp)
668{
669 p = encode_post_op_attr(rqstp, p, &resp->fh);
670 if (resp->status == 0) {
671 *p++ = htonl(resp->count);
672 *p++ = htonl(resp->eof);
673 *p++ = htonl(resp->count); /* xdr opaque count */
674 xdr_ressize_check(rqstp, p);
675 /* now update rqstp->rq_res to reflect data aswell */
676 rqstp->rq_res.page_len = resp->count;
677 if (resp->count & 3) {
678 /* need to pad the tail */
679 rqstp->rq_restailpage = 0;
680 rqstp->rq_res.tail[0].iov_base = p;
681 *p = 0;
682 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3);
683 }
684 return 1;
685 } else
686 return xdr_ressize_check(rqstp, p);
687}
688
689/* WRITE */
690int
691nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p,
692 struct nfsd3_writeres *resp)
693{
694 p = encode_wcc_data(rqstp, p, &resp->fh);
695 if (resp->status == 0) {
696 *p++ = htonl(resp->count);
697 *p++ = htonl(resp->committed);
698 *p++ = htonl(nfssvc_boot.tv_sec);
699 *p++ = htonl(nfssvc_boot.tv_usec);
700 }
701 return xdr_ressize_check(rqstp, p);
702}
703
704/* CREATE, MKDIR, SYMLINK, MKNOD */
705int
706nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
707 struct nfsd3_diropres *resp)
708{
709 if (resp->status == 0) {
710 *p++ = xdr_one;
711 p = encode_fh(p, &resp->fh);
712 p = encode_post_op_attr(rqstp, p, &resp->fh);
713 }
714 p = encode_wcc_data(rqstp, p, &resp->dirfh);
715 return xdr_ressize_check(rqstp, p);
716}
717
718/* RENAME */
719int
720nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p,
721 struct nfsd3_renameres *resp)
722{
723 p = encode_wcc_data(rqstp, p, &resp->ffh);
724 p = encode_wcc_data(rqstp, p, &resp->tfh);
725 return xdr_ressize_check(rqstp, p);
726}
727
728/* LINK */
729int
730nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
731 struct nfsd3_linkres *resp)
732{
733 p = encode_post_op_attr(rqstp, p, &resp->fh);
734 p = encode_wcc_data(rqstp, p, &resp->tfh);
735 return xdr_ressize_check(rqstp, p);
736}
737
738/* READDIR */
739int
740nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
741 struct nfsd3_readdirres *resp)
742{
743 p = encode_post_op_attr(rqstp, p, &resp->fh);
744
745 if (resp->status == 0) {
746 /* stupid readdir cookie */
747 memcpy(p, resp->verf, 8); p += 2;
748 xdr_ressize_check(rqstp, p);
749 if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE)
750 return 1; /*No room for trailer */
751 rqstp->rq_res.page_len = (resp->count) << 2;
752
753 /* add the 'tail' to the end of the 'head' page - page 0. */
754 rqstp->rq_restailpage = 0;
755 rqstp->rq_res.tail[0].iov_base = p;
756 *p++ = 0; /* no more entries */
757 *p++ = htonl(resp->common.err == nfserr_eof);
758 rqstp->rq_res.tail[0].iov_len = 2<<2;
759 return 1;
760 } else
761 return xdr_ressize_check(rqstp, p);
762}
763
764static inline u32 *
765encode_entry_baggage(struct nfsd3_readdirres *cd, u32 *p, const char *name,
766 int namlen, ino_t ino)
767{
768 *p++ = xdr_one; /* mark entry present */
769 p = xdr_encode_hyper(p, ino); /* file id */
770 p = xdr_encode_array(p, name, namlen);/* name length & name */
771
772 cd->offset = p; /* remember pointer */
773 p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */
774
775 return p;
776}
777
778static inline u32 *
779encode_entryplus_baggage(struct nfsd3_readdirres *cd, u32 *p,
780 struct svc_fh *fhp)
781{
782 p = encode_post_op_attr(cd->rqstp, p, fhp);
783 *p++ = xdr_one; /* yes, a file handle follows */
784 p = encode_fh(p, fhp);
785 fh_put(fhp);
786 return p;
787}
788
789static int
790compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
791 const char *name, int namlen)
792{
793 struct svc_export *exp;
794 struct dentry *dparent, *dchild;
795 int rv = 0;
796
797 dparent = cd->fh.fh_dentry;
798 exp = cd->fh.fh_export;
799
800 fh_init(fhp, NFS3_FHSIZE);
801 if (isdotent(name, namlen)) {
802 if (namlen == 2) {
803 dchild = dget_parent(dparent);
804 if (dchild == dparent) {
805 /* filesystem root - cannot return filehandle for ".." */
806 dput(dchild);
807 return 1;
808 }
809 } else
810 dchild = dget(dparent);
811 } else
812 dchild = lookup_one_len(name, dparent, namlen);
813 if (IS_ERR(dchild))
814 return 1;
815 if (d_mountpoint(dchild) ||
816 fh_compose(fhp, exp, dchild, &cd->fh) != 0 ||
817 !dchild->d_inode)
818 rv = 1;
819 dput(dchild);
820 return rv;
821}
822
823/*
824 * Encode a directory entry. This one works for both normal readdir
825 * and readdirplus.
826 * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
827 * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
828 *
829 * The readdirplus baggage is 1+21 words for post_op_attr, plus the
830 * file handle.
831 */
832
833#define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1)
834#define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
835static int
836encode_entry(struct readdir_cd *ccd, const char *name,
837 int namlen, off_t offset, ino_t ino, unsigned int d_type, int plus)
838{
839 struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
840 common);
841 u32 *p = cd->buffer;
842 caddr_t curr_page_addr = NULL;
843 int pn; /* current page number */
844 int slen; /* string (name) length */
845 int elen; /* estimated entry length in words */
846 int num_entry_words = 0; /* actual number of words */
847
848 if (cd->offset) {
849 u64 offset64 = offset;
850
851 if (unlikely(cd->offset1)) {
852 /* we ended up with offset on a page boundary */
853 *cd->offset = htonl(offset64 >> 32);
854 *cd->offset1 = htonl(offset64 & 0xffffffff);
855 cd->offset1 = NULL;
856 } else {
857 xdr_encode_hyper(cd->offset, (u64) offset);
858 }
859 }
860
861 /*
862 dprintk("encode_entry(%.*s @%ld%s)\n",
863 namlen, name, (long) offset, plus? " plus" : "");
864 */
865
866 /* truncate filename if too long */
867 if (namlen > NFS3_MAXNAMLEN)
868 namlen = NFS3_MAXNAMLEN;
869
870 slen = XDR_QUADLEN(namlen);
871 elen = slen + NFS3_ENTRY_BAGGAGE
872 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
873
874 if (cd->buflen < elen) {
875 cd->common.err = nfserr_toosmall;
876 return -EINVAL;
877 }
878
879 /* determine which page in rq_respages[] we are currently filling */
880 for (pn=1; pn < cd->rqstp->rq_resused; pn++) {
881 curr_page_addr = page_address(cd->rqstp->rq_respages[pn]);
882
883 if (((caddr_t)cd->buffer >= curr_page_addr) &&
884 ((caddr_t)cd->buffer < curr_page_addr + PAGE_SIZE))
885 break;
886 }
887
888 if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) {
889 /* encode entry in current page */
890
891 p = encode_entry_baggage(cd, p, name, namlen, ino);
892
893 /* throw in readdirplus baggage */
894 if (plus) {
895 struct svc_fh fh;
896
897 if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
898 *p++ = 0;
899 *p++ = 0;
900 } else
901 p = encode_entryplus_baggage(cd, p, &fh);
902 }
903 num_entry_words = p - cd->buffer;
904 } else if (cd->rqstp->rq_respages[pn+1] != NULL) {
905 /* temporarily encode entry into next page, then move back to
906 * current and next page in rq_respages[] */
907 u32 *p1, *tmp;
908 int len1, len2;
909
910 /* grab next page for temporary storage of entry */
911 p1 = tmp = page_address(cd->rqstp->rq_respages[pn+1]);
912
913 p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
914
915 /* throw in readdirplus baggage */
916 if (plus) {
917 struct svc_fh fh;
918
919 if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
920 /* zero out the filehandle */
921 *p1++ = 0;
922 *p1++ = 0;
923 } else
924 p1 = encode_entryplus_baggage(cd, p1, &fh);
925 }
926
927 /* determine entry word length and lengths to go in pages */
928 num_entry_words = p1 - tmp;
929 len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer;
930 if ((num_entry_words << 2) < len1) {
931 /* the actual number of words in the entry is less
932 * than elen and can still fit in the current page
933 */
934 memmove(p, tmp, num_entry_words << 2);
935 p += num_entry_words;
936
937 /* update offset */
938 cd->offset = cd->buffer + (cd->offset - tmp);
939 } else {
940 unsigned int offset_r = (cd->offset - tmp) << 2;
941
942 /* update pointer to offset location.
943 * This is a 64bit quantity, so we need to
944 * deal with 3 cases:
945 * - entirely in first page
946 * - entirely in second page
947 * - 4 bytes in each page
948 */
949 if (offset_r + 8 <= len1) {
950 cd->offset = p + (cd->offset - tmp);
951 } else if (offset_r >= len1) {
952 cd->offset -= len1 >> 2;
953 } else {
954 /* sitting on the fence */
955 BUG_ON(offset_r != len1 - 4);
956 cd->offset = p + (cd->offset - tmp);
957 cd->offset1 = tmp;
958 }
959
960 len2 = (num_entry_words << 2) - len1;
961
962 /* move from temp page to current and next pages */
963 memmove(p, tmp, len1);
964 memmove(tmp, (caddr_t)tmp+len1, len2);
965
966 p = tmp + (len2 >> 2);
967 }
968 }
969 else {
970 cd->common.err = nfserr_toosmall;
971 return -EINVAL;
972 }
973
974 cd->buflen -= num_entry_words;
975 cd->buffer = p;
976 cd->common.err = nfs_ok;
977 return 0;
978
979}
980
981int
982nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
983 int namlen, loff_t offset, ino_t ino, unsigned int d_type)
984{
985 return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
986}
987
988int
989nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
990 int namlen, loff_t offset, ino_t ino, unsigned int d_type)
991{
992 return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
993}
994
995/* FSSTAT */
996int
997nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, u32 *p,
998 struct nfsd3_fsstatres *resp)
999{
1000 struct kstatfs *s = &resp->stats;
1001 u64 bs = s->f_bsize;
1002
1003 *p++ = xdr_zero; /* no post_op_attr */
1004
1005 if (resp->status == 0) {
1006 p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */
1007 p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */
1008 p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */
1009 p = xdr_encode_hyper(p, s->f_files); /* total inodes */
1010 p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */
1011 p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */
1012 *p++ = htonl(resp->invarsec); /* mean unchanged time */
1013 }
1014 return xdr_ressize_check(rqstp, p);
1015}
1016
1017/* FSINFO */
1018int
1019nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p,
1020 struct nfsd3_fsinfores *resp)
1021{
1022 *p++ = xdr_zero; /* no post_op_attr */
1023
1024 if (resp->status == 0) {
1025 *p++ = htonl(resp->f_rtmax);
1026 *p++ = htonl(resp->f_rtpref);
1027 *p++ = htonl(resp->f_rtmult);
1028 *p++ = htonl(resp->f_wtmax);
1029 *p++ = htonl(resp->f_wtpref);
1030 *p++ = htonl(resp->f_wtmult);
1031 *p++ = htonl(resp->f_dtpref);
1032 p = xdr_encode_hyper(p, resp->f_maxfilesize);
1033 *p++ = xdr_one;
1034 *p++ = xdr_zero;
1035 *p++ = htonl(resp->f_properties);
1036 }
1037
1038 return xdr_ressize_check(rqstp, p);
1039}
1040
1041/* PATHCONF */
1042int
1043nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p,
1044 struct nfsd3_pathconfres *resp)
1045{
1046 *p++ = xdr_zero; /* no post_op_attr */
1047
1048 if (resp->status == 0) {
1049 *p++ = htonl(resp->p_link_max);
1050 *p++ = htonl(resp->p_name_max);
1051 *p++ = htonl(resp->p_no_trunc);
1052 *p++ = htonl(resp->p_chown_restricted);
1053 *p++ = htonl(resp->p_case_insensitive);
1054 *p++ = htonl(resp->p_case_preserving);
1055 }
1056
1057 return xdr_ressize_check(rqstp, p);
1058}
1059
1060/* COMMIT */
1061int
1062nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p,
1063 struct nfsd3_commitres *resp)
1064{
1065 p = encode_wcc_data(rqstp, p, &resp->fh);
1066 /* Write verifier */
1067 if (resp->status == 0) {
1068 *p++ = htonl(nfssvc_boot.tv_sec);
1069 *p++ = htonl(nfssvc_boot.tv_usec);
1070 }
1071 return xdr_ressize_check(rqstp, p);
1072}
1073
1074/*
1075 * XDR release functions
1076 */
1077int
1078nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
1079 struct nfsd3_attrstat *resp)
1080{
1081 fh_put(&resp->fh);
1082 return 1;
1083}
1084
1085int
1086nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p,
1087 struct nfsd3_fhandle_pair *resp)
1088{
1089 fh_put(&resp->fh1);
1090 fh_put(&resp->fh2);
1091 return 1;
1092}
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
new file mode 100644
index 000000000000..11ebf6c4aa54
--- /dev/null
+++ b/fs/nfsd/nfs4acl.c
@@ -0,0 +1,954 @@
1/*
2 * fs/nfs4acl/acl.c
3 *
4 * Common NFSv4 ACL handling code.
5 *
6 * Copyright (c) 2002, 2003 The Regents of the University of Michigan.
7 * All rights reserved.
8 *
9 * Marius Aamodt Eriksen <marius@umich.edu>
10 * Jeff Sedlak <jsedlak@umich.edu>
11 * J. Bruce Fields <bfields@umich.edu>
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the University nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
33 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include <linux/string.h>
40#include <linux/slab.h>
41#include <linux/list.h>
42#include <linux/types.h>
43#include <linux/fs.h>
44#include <linux/module.h>
45#include <linux/nfs_fs.h>
46#include <linux/posix_acl.h>
47#include <linux/nfs4.h>
48#include <linux/nfs4_acl.h>
49
50
51/* mode bit translations: */
52#define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
53#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
54#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
55#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
56#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
57
58/* We don't support these bits; insist they be neither allowed nor denied */
59#define NFS4_MASK_UNSUPP (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
60 | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
61
62/* flags used to simulate posix default ACLs */
63#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
64 | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
65
66#define MASK_EQUAL(mask1, mask2) \
67 ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) )
68
69static u32
70mask_from_posix(unsigned short perm, unsigned int flags)
71{
72 int mask = NFS4_ANYONE_MODE;
73
74 if (flags & NFS4_ACL_OWNER)
75 mask |= NFS4_OWNER_MODE;
76 if (perm & ACL_READ)
77 mask |= NFS4_READ_MODE;
78 if (perm & ACL_WRITE)
79 mask |= NFS4_WRITE_MODE;
80 if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR))
81 mask |= NFS4_ACE_DELETE_CHILD;
82 if (perm & ACL_EXECUTE)
83 mask |= NFS4_EXECUTE_MODE;
84 return mask;
85}
86
87static u32
88deny_mask(u32 allow_mask, unsigned int flags)
89{
90 u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP;
91 if (!(flags & NFS4_ACL_DIR))
92 ret &= ~NFS4_ACE_DELETE_CHILD;
93 return ret;
94}
95
96/* XXX: modify functions to return NFS errors; they're only ever
97 * used by nfs code, after all.... */
98
99static int
100mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
101{
102 u32 ignore = 0;
103
104 if (!(flags & NFS4_ACL_DIR))
105 ignore |= NFS4_ACE_DELETE_CHILD; /* ignore it */
106 perm |= ignore;
107 *mode = 0;
108 if ((perm & NFS4_READ_MODE) == NFS4_READ_MODE)
109 *mode |= ACL_READ;
110 if ((perm & NFS4_WRITE_MODE) == NFS4_WRITE_MODE)
111 *mode |= ACL_WRITE;
112 if ((perm & NFS4_EXECUTE_MODE) == NFS4_EXECUTE_MODE)
113 *mode |= ACL_EXECUTE;
114 if (!MASK_EQUAL(perm, ignore|mask_from_posix(*mode, flags)))
115 return -EINVAL;
116 return 0;
117}
118
119struct ace_container {
120 struct nfs4_ace *ace;
121 struct list_head ace_l;
122};
123
124static short ace2type(struct nfs4_ace *);
125static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
126static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
127int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
128int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
129
130struct nfs4_acl *
131nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
132 unsigned int flags)
133{
134 struct nfs4_acl *acl;
135 int error = -EINVAL;
136
137 if ((pacl != NULL &&
138 (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
139 (dpacl != NULL &&
140 (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
141 goto out_err;
142
143 acl = nfs4_acl_new();
144 if (acl == NULL) {
145 error = -ENOMEM;
146 goto out_err;
147 }
148
149 if (pacl != NULL) {
150 error = _posix_to_nfsv4_one(pacl, acl,
151 flags & ~NFS4_ACL_TYPE_DEFAULT);
152 if (error < 0)
153 goto out_acl;
154 }
155
156 if (dpacl != NULL) {
157 error = _posix_to_nfsv4_one(dpacl, acl,
158 flags | NFS4_ACL_TYPE_DEFAULT);
159 if (error < 0)
160 goto out_acl;
161 }
162
163 return acl;
164
165out_acl:
166 nfs4_acl_free(acl);
167out_err:
168 acl = ERR_PTR(error);
169
170 return acl;
171}
172
173static int
174nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
175 uid_t owner, unsigned int flags)
176{
177 int error;
178
179 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
180 eflag, mask, whotype, owner);
181 if (error < 0)
182 return error;
183 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
184 eflag, deny_mask(mask, flags), whotype, owner);
185 return error;
186}
187
188/* We assume the acl has been verified with posix_acl_valid. */
189static int
190_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
191 unsigned int flags)
192{
193 struct posix_acl_entry *pa, *pe, *group_owner_entry;
194 int error = -EINVAL;
195 u32 mask, mask_mask;
196 int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
197 NFS4_INHERITANCE_FLAGS : 0);
198
199 BUG_ON(pacl->a_count < 3);
200 pe = pacl->a_entries + pacl->a_count;
201 pa = pe - 2; /* if mask entry exists, it's second from the last. */
202 if (pa->e_tag == ACL_MASK)
203 mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags);
204 else
205 mask_mask = 0;
206
207 pa = pacl->a_entries;
208 BUG_ON(pa->e_tag != ACL_USER_OBJ);
209 mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
210 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
211 if (error < 0)
212 goto out;
213 pa++;
214
215 while (pa->e_tag == ACL_USER) {
216 mask = mask_from_posix(pa->e_perm, flags);
217 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
218 eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
219 if (error < 0)
220 goto out;
221
222
223 error = nfs4_acl_add_pair(acl, eflag, mask,
224 NFS4_ACL_WHO_NAMED, pa->e_id, flags);
225 if (error < 0)
226 goto out;
227 pa++;
228 }
229
230 /* In the case of groups, we apply allow ACEs first, then deny ACEs,
231 * since a user can be in more than one group. */
232
233 /* allow ACEs */
234
235 if (pacl->a_count > 3) {
236 BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
237 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
238 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
239 NFS4_ACL_WHO_GROUP, 0);
240 if (error < 0)
241 goto out;
242 }
243 group_owner_entry = pa;
244 mask = mask_from_posix(pa->e_perm, flags);
245 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
246 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
247 NFS4_ACL_WHO_GROUP, 0);
248 if (error < 0)
249 goto out;
250 pa++;
251
252 while (pa->e_tag == ACL_GROUP) {
253 mask = mask_from_posix(pa->e_perm, flags);
254 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
255 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
256 NFS4_ACL_WHO_NAMED, pa->e_id);
257 if (error < 0)
258 goto out;
259
260 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
261 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
262 NFS4_ACL_WHO_NAMED, pa->e_id);
263 if (error < 0)
264 goto out;
265 pa++;
266 }
267
268 /* deny ACEs */
269
270 pa = group_owner_entry;
271 mask = mask_from_posix(pa->e_perm, flags);
272 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
273 NFS4_ACE_IDENTIFIER_GROUP | eflag,
274 deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
275 if (error < 0)
276 goto out;
277 pa++;
278 while (pa->e_tag == ACL_GROUP) {
279 mask = mask_from_posix(pa->e_perm, flags);
280 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
281 NFS4_ACE_IDENTIFIER_GROUP | eflag,
282 deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
283 if (error < 0)
284 goto out;
285 pa++;
286 }
287
288 if (pa->e_tag == ACL_MASK)
289 pa++;
290 BUG_ON(pa->e_tag != ACL_OTHER);
291 mask = mask_from_posix(pa->e_perm, flags);
292 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
293
294out:
295 return error;
296}
297
298static void
299sort_pacl_range(struct posix_acl *pacl, int start, int end) {
300 int sorted = 0, i;
301 struct posix_acl_entry tmp;
302
303 /* We just do a bubble sort; easy to do in place, and we're not
304 * expecting acl's to be long enough to justify anything more. */
305 while (!sorted) {
306 sorted = 1;
307 for (i = start; i < end; i++) {
308 if (pacl->a_entries[i].e_id
309 > pacl->a_entries[i+1].e_id) {
310 sorted = 0;
311 tmp = pacl->a_entries[i];
312 pacl->a_entries[i] = pacl->a_entries[i+1];
313 pacl->a_entries[i+1] = tmp;
314 }
315 }
316 }
317}
318
319static void
320sort_pacl(struct posix_acl *pacl)
321{
322 /* posix_acl_valid requires that users and groups be in order
323 * by uid/gid. */
324 int i, j;
325
326 if (pacl->a_count <= 4)
327 return; /* no users or groups */
328 i = 1;
329 while (pacl->a_entries[i].e_tag == ACL_USER)
330 i++;
331 sort_pacl_range(pacl, 1, i-1);
332
333 BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
334 j = i++;
335 while (pacl->a_entries[j].e_tag == ACL_GROUP)
336 j++;
337 sort_pacl_range(pacl, i, j-1);
338 return;
339}
340
341static int
342write_pace(struct nfs4_ace *ace, struct posix_acl *pacl,
343 struct posix_acl_entry **pace, short tag, unsigned int flags)
344{
345 struct posix_acl_entry *this = *pace;
346
347 if (*pace == pacl->a_entries + pacl->a_count)
348 return -EINVAL; /* fell off the end */
349 (*pace)++;
350 this->e_tag = tag;
351 if (tag == ACL_USER_OBJ)
352 flags |= NFS4_ACL_OWNER;
353 if (mode_from_nfs4(ace->access_mask, &this->e_perm, flags))
354 return -EINVAL;
355 this->e_id = (tag == ACL_USER || tag == ACL_GROUP ?
356 ace->who : ACL_UNDEFINED_ID);
357 return 0;
358}
359
360static struct nfs4_ace *
361get_next_v4_ace(struct list_head **p, struct list_head *head)
362{
363 struct nfs4_ace *ace;
364
365 *p = (*p)->next;
366 if (*p == head)
367 return NULL;
368 ace = list_entry(*p, struct nfs4_ace, l_ace);
369
370 return ace;
371}
372
373int
374nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
375 struct posix_acl **dpacl, unsigned int flags)
376{
377 struct nfs4_acl *dacl;
378 int error = -ENOMEM;
379
380 *pacl = NULL;
381 *dpacl = NULL;
382
383 dacl = nfs4_acl_new();
384 if (dacl == NULL)
385 goto out;
386
387 error = nfs4_acl_split(acl, dacl);
388 if (error < 0)
389 goto out_acl;
390
391 if (pacl != NULL) {
392 if (acl->naces == 0) {
393 error = -ENODATA;
394 goto try_dpacl;
395 }
396
397 *pacl = _nfsv4_to_posix_one(acl, flags);
398 if (IS_ERR(*pacl)) {
399 error = PTR_ERR(*pacl);
400 *pacl = NULL;
401 goto out_acl;
402 }
403 }
404
405try_dpacl:
406 if (dpacl != NULL) {
407 if (dacl->naces == 0) {
408 if (pacl == NULL || *pacl == NULL)
409 error = -ENODATA;
410 goto out_acl;
411 }
412
413 error = 0;
414 *dpacl = _nfsv4_to_posix_one(dacl, flags);
415 if (IS_ERR(*dpacl)) {
416 error = PTR_ERR(*dpacl);
417 *dpacl = NULL;
418 goto out_acl;
419 }
420 }
421
422out_acl:
423 if (error && pacl) {
424 posix_acl_release(*pacl);
425 *pacl = NULL;
426 }
427 nfs4_acl_free(dacl);
428out:
429 return error;
430}
431
432static int
433same_who(struct nfs4_ace *a, struct nfs4_ace *b)
434{
435 return a->whotype == b->whotype &&
436 (a->whotype != NFS4_ACL_WHO_NAMED || a->who == b->who);
437}
438
439static int
440complementary_ace_pair(struct nfs4_ace *allow, struct nfs4_ace *deny,
441 unsigned int flags)
442{
443 int ignore = 0;
444 if (!(flags & NFS4_ACL_DIR))
445 ignore |= NFS4_ACE_DELETE_CHILD;
446 return MASK_EQUAL(ignore|deny_mask(allow->access_mask, flags),
447 ignore|deny->access_mask) &&
448 allow->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
449 deny->type == NFS4_ACE_ACCESS_DENIED_ACE_TYPE &&
450 allow->flag == deny->flag &&
451 same_who(allow, deny);
452}
453
454static inline int
455user_obj_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
456 struct posix_acl *pacl, struct posix_acl_entry **pace,
457 unsigned int flags)
458{
459 int error = -EINVAL;
460 struct nfs4_ace *ace, *ace2;
461
462 ace = get_next_v4_ace(p, &n4acl->ace_head);
463 if (ace == NULL)
464 goto out;
465 if (ace2type(ace) != ACL_USER_OBJ)
466 goto out;
467 error = write_pace(ace, pacl, pace, ACL_USER_OBJ, flags);
468 if (error < 0)
469 goto out;
470 error = -EINVAL;
471 ace2 = get_next_v4_ace(p, &n4acl->ace_head);
472 if (ace2 == NULL)
473 goto out;
474 if (!complementary_ace_pair(ace, ace2, flags))
475 goto out;
476 error = 0;
477out:
478 return error;
479}
480
481static inline int
482users_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
483 struct nfs4_ace **mask_ace,
484 struct posix_acl *pacl, struct posix_acl_entry **pace,
485 unsigned int flags)
486{
487 int error = -EINVAL;
488 struct nfs4_ace *ace, *ace2;
489
490 ace = get_next_v4_ace(p, &n4acl->ace_head);
491 if (ace == NULL)
492 goto out;
493 while (ace2type(ace) == ACL_USER) {
494 if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
495 goto out;
496 if (*mask_ace &&
497 !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
498 goto out;
499 *mask_ace = ace;
500 ace = get_next_v4_ace(p, &n4acl->ace_head);
501 if (ace == NULL)
502 goto out;
503 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
504 goto out;
505 error = write_pace(ace, pacl, pace, ACL_USER, flags);
506 if (error < 0)
507 goto out;
508 error = -EINVAL;
509 ace2 = get_next_v4_ace(p, &n4acl->ace_head);
510 if (ace2 == NULL)
511 goto out;
512 if (!complementary_ace_pair(ace, ace2, flags))
513 goto out;
514 if ((*mask_ace)->flag != ace2->flag ||
515 !same_who(*mask_ace, ace2))
516 goto out;
517 ace = get_next_v4_ace(p, &n4acl->ace_head);
518 if (ace == NULL)
519 goto out;
520 }
521 error = 0;
522out:
523 return error;
524}
525
526static inline int
527group_obj_and_groups_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
528 struct nfs4_ace **mask_ace,
529 struct posix_acl *pacl, struct posix_acl_entry **pace,
530 unsigned int flags)
531{
532 int error = -EINVAL;
533 struct nfs4_ace *ace, *ace2;
534 struct ace_container *ac;
535 struct list_head group_l;
536
537 INIT_LIST_HEAD(&group_l);
538 ace = list_entry(*p, struct nfs4_ace, l_ace);
539
540 /* group owner (mask and allow aces) */
541
542 if (pacl->a_count != 3) {
543 /* then the group owner should be preceded by mask */
544 if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
545 goto out;
546 if (*mask_ace &&
547 !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
548 goto out;
549 *mask_ace = ace;
550 ace = get_next_v4_ace(p, &n4acl->ace_head);
551 if (ace == NULL)
552 goto out;
553
554 if ((*mask_ace)->flag != ace->flag || !same_who(*mask_ace, ace))
555 goto out;
556 }
557
558 if (ace2type(ace) != ACL_GROUP_OBJ)
559 goto out;
560
561 ac = kmalloc(sizeof(*ac), GFP_KERNEL);
562 error = -ENOMEM;
563 if (ac == NULL)
564 goto out;
565 ac->ace = ace;
566 list_add_tail(&ac->ace_l, &group_l);
567
568 error = -EINVAL;
569 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
570 goto out;
571
572 error = write_pace(ace, pacl, pace, ACL_GROUP_OBJ, flags);
573 if (error < 0)
574 goto out;
575
576 error = -EINVAL;
577 ace = get_next_v4_ace(p, &n4acl->ace_head);
578 if (ace == NULL)
579 goto out;
580
581 /* groups (mask and allow aces) */
582
583 while (ace2type(ace) == ACL_GROUP) {
584 if (*mask_ace == NULL)
585 goto out;
586
587 if (ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE ||
588 !MASK_EQUAL(ace->access_mask, (*mask_ace)->access_mask))
589 goto out;
590 *mask_ace = ace;
591
592 ace = get_next_v4_ace(p, &n4acl->ace_head);
593 if (ace == NULL)
594 goto out;
595 ac = kmalloc(sizeof(*ac), GFP_KERNEL);
596 error = -ENOMEM;
597 if (ac == NULL)
598 goto out;
599 error = -EINVAL;
600 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE ||
601 !same_who(ace, *mask_ace))
602 goto out;
603
604 ac->ace = ace;
605 list_add_tail(&ac->ace_l, &group_l);
606
607 error = write_pace(ace, pacl, pace, ACL_GROUP, flags);
608 if (error < 0)
609 goto out;
610 error = -EINVAL;
611 ace = get_next_v4_ace(p, &n4acl->ace_head);
612 if (ace == NULL)
613 goto out;
614 }
615
616 /* group owner (deny ace) */
617
618 if (ace2type(ace) != ACL_GROUP_OBJ)
619 goto out;
620 ac = list_entry(group_l.next, struct ace_container, ace_l);
621 ace2 = ac->ace;
622 if (!complementary_ace_pair(ace2, ace, flags))
623 goto out;
624 list_del(group_l.next);
625 kfree(ac);
626
627 /* groups (deny aces) */
628
629 while (!list_empty(&group_l)) {
630 ace = get_next_v4_ace(p, &n4acl->ace_head);
631 if (ace == NULL)
632 goto out;
633 if (ace2type(ace) != ACL_GROUP)
634 goto out;
635 ac = list_entry(group_l.next, struct ace_container, ace_l);
636 ace2 = ac->ace;
637 if (!complementary_ace_pair(ace2, ace, flags))
638 goto out;
639 list_del(group_l.next);
640 kfree(ac);
641 }
642
643 ace = get_next_v4_ace(p, &n4acl->ace_head);
644 if (ace == NULL)
645 goto out;
646 if (ace2type(ace) != ACL_OTHER)
647 goto out;
648 error = 0;
649out:
650 while (!list_empty(&group_l)) {
651 ac = list_entry(group_l.next, struct ace_container, ace_l);
652 list_del(group_l.next);
653 kfree(ac);
654 }
655 return error;
656}
657
658static inline int
659mask_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
660 struct nfs4_ace **mask_ace,
661 struct posix_acl *pacl, struct posix_acl_entry **pace,
662 unsigned int flags)
663{
664 int error = -EINVAL;
665 struct nfs4_ace *ace;
666
667 ace = list_entry(*p, struct nfs4_ace, l_ace);
668 if (pacl->a_count != 3) {
669 if (*mask_ace == NULL)
670 goto out;
671 (*mask_ace)->access_mask = deny_mask((*mask_ace)->access_mask, flags);
672 write_pace(*mask_ace, pacl, pace, ACL_MASK, flags);
673 }
674 error = 0;
675out:
676 return error;
677}
678
679static inline int
680other_from_v4(struct nfs4_acl *n4acl, struct list_head **p,
681 struct posix_acl *pacl, struct posix_acl_entry **pace,
682 unsigned int flags)
683{
684 int error = -EINVAL;
685 struct nfs4_ace *ace, *ace2;
686
687 ace = list_entry(*p, struct nfs4_ace, l_ace);
688 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE)
689 goto out;
690 error = write_pace(ace, pacl, pace, ACL_OTHER, flags);
691 if (error < 0)
692 goto out;
693 error = -EINVAL;
694 ace2 = get_next_v4_ace(p, &n4acl->ace_head);
695 if (ace2 == NULL)
696 goto out;
697 if (!complementary_ace_pair(ace, ace2, flags))
698 goto out;
699 error = 0;
700out:
701 return error;
702}
703
704static int
705calculate_posix_ace_count(struct nfs4_acl *n4acl)
706{
707 if (n4acl->naces == 6) /* owner, owner group, and other only */
708 return 3;
709 else { /* Otherwise there must be a mask entry. */
710 /* Also, the remaining entries are for named users and
711 * groups, and come in threes (mask, allow, deny): */
712 if (n4acl->naces < 7)
713 return -1;
714 if ((n4acl->naces - 7) % 3)
715 return -1;
716 return 4 + (n4acl->naces - 7)/3;
717 }
718}
719
720
721static struct posix_acl *
722_nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags)
723{
724 struct posix_acl *pacl;
725 int error = -EINVAL, nace = 0;
726 struct list_head *p;
727 struct nfs4_ace *mask_ace = NULL;
728 struct posix_acl_entry *pace;
729
730 nace = calculate_posix_ace_count(n4acl);
731 if (nace < 0)
732 goto out_err;
733
734 pacl = posix_acl_alloc(nace, GFP_KERNEL);
735 error = -ENOMEM;
736 if (pacl == NULL)
737 goto out_err;
738
739 pace = &pacl->a_entries[0];
740 p = &n4acl->ace_head;
741
742 error = user_obj_from_v4(n4acl, &p, pacl, &pace, flags);
743 if (error)
744 goto out_acl;
745
746 error = users_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
747 if (error)
748 goto out_acl;
749
750 error = group_obj_and_groups_from_v4(n4acl, &p, &mask_ace, pacl, &pace,
751 flags);
752 if (error)
753 goto out_acl;
754
755 error = mask_from_v4(n4acl, &p, &mask_ace, pacl, &pace, flags);
756 if (error)
757 goto out_acl;
758 error = other_from_v4(n4acl, &p, pacl, &pace, flags);
759 if (error)
760 goto out_acl;
761
762 error = -EINVAL;
763 if (p->next != &n4acl->ace_head)
764 goto out_acl;
765 if (pace != pacl->a_entries + pacl->a_count)
766 goto out_acl;
767
768 sort_pacl(pacl);
769
770 return pacl;
771out_acl:
772 posix_acl_release(pacl);
773out_err:
774 pacl = ERR_PTR(error);
775 return pacl;
776}
777
778int
779nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
780{
781 struct list_head *h, *n;
782 struct nfs4_ace *ace;
783 int error = 0;
784
785 list_for_each_safe(h, n, &acl->ace_head) {
786 ace = list_entry(h, struct nfs4_ace, l_ace);
787
788 if ((ace->flag & NFS4_INHERITANCE_FLAGS)
789 != NFS4_INHERITANCE_FLAGS)
790 continue;
791
792 error = nfs4_acl_add_ace(dacl, ace->type, ace->flag,
793 ace->access_mask, ace->whotype, ace->who) == -1;
794 if (error < 0)
795 goto out;
796
797 list_del(h);
798 kfree(ace);
799 acl->naces--;
800 }
801
802out:
803 return error;
804}
805
806static short
807ace2type(struct nfs4_ace *ace)
808{
809 switch (ace->whotype) {
810 case NFS4_ACL_WHO_NAMED:
811 return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
812 ACL_GROUP : ACL_USER);
813 case NFS4_ACL_WHO_OWNER:
814 return ACL_USER_OBJ;
815 case NFS4_ACL_WHO_GROUP:
816 return ACL_GROUP_OBJ;
817 case NFS4_ACL_WHO_EVERYONE:
818 return ACL_OTHER;
819 }
820 BUG();
821 return -1;
822}
823
824EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
825EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
826
827struct nfs4_acl *
828nfs4_acl_new(void)
829{
830 struct nfs4_acl *acl;
831
832 if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
833 return NULL;
834
835 acl->naces = 0;
836 INIT_LIST_HEAD(&acl->ace_head);
837
838 return acl;
839}
840
841void
842nfs4_acl_free(struct nfs4_acl *acl)
843{
844 struct list_head *h;
845 struct nfs4_ace *ace;
846
847 if (!acl)
848 return;
849
850 while (!list_empty(&acl->ace_head)) {
851 h = acl->ace_head.next;
852 list_del(h);
853 ace = list_entry(h, struct nfs4_ace, l_ace);
854 kfree(ace);
855 }
856
857 kfree(acl);
858
859 return;
860}
861
862int
863nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
864 int whotype, uid_t who)
865{
866 struct nfs4_ace *ace;
867
868 if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
869 return -1;
870
871 ace->type = type;
872 ace->flag = flag;
873 ace->access_mask = access_mask;
874 ace->whotype = whotype;
875 ace->who = who;
876
877 list_add_tail(&ace->l_ace, &acl->ace_head);
878 acl->naces++;
879
880 return 0;
881}
882
883static struct {
884 char *string;
885 int stringlen;
886 int type;
887} s2t_map[] = {
888 {
889 .string = "OWNER@",
890 .stringlen = sizeof("OWNER@") - 1,
891 .type = NFS4_ACL_WHO_OWNER,
892 },
893 {
894 .string = "GROUP@",
895 .stringlen = sizeof("GROUP@") - 1,
896 .type = NFS4_ACL_WHO_GROUP,
897 },
898 {
899 .string = "EVERYONE@",
900 .stringlen = sizeof("EVERYONE@") - 1,
901 .type = NFS4_ACL_WHO_EVERYONE,
902 },
903};
904
905int
906nfs4_acl_get_whotype(char *p, u32 len)
907{
908 int i;
909
910 for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
911 if (s2t_map[i].stringlen == len &&
912 0 == memcmp(s2t_map[i].string, p, len))
913 return s2t_map[i].type;
914 }
915 return NFS4_ACL_WHO_NAMED;
916}
917
918int
919nfs4_acl_write_who(int who, char *p)
920{
921 int i;
922
923 for (i=0; i < sizeof(s2t_map) / sizeof(*s2t_map); i++) {
924 if (s2t_map[i].type == who) {
925 memcpy(p, s2t_map[i].string, s2t_map[i].stringlen);
926 return s2t_map[i].stringlen;
927 }
928 }
929 BUG();
930 return -1;
931}
932
933static inline int
934match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who)
935{
936 switch (ace->whotype) {
937 case NFS4_ACL_WHO_NAMED:
938 return who == ace->who;
939 case NFS4_ACL_WHO_OWNER:
940 return who == owner;
941 case NFS4_ACL_WHO_GROUP:
942 return who == group;
943 case NFS4_ACL_WHO_EVERYONE:
944 return 1;
945 default:
946 return 0;
947 }
948}
949
950EXPORT_SYMBOL(nfs4_acl_new);
951EXPORT_SYMBOL(nfs4_acl_free);
952EXPORT_SYMBOL(nfs4_acl_add_ace);
953EXPORT_SYMBOL(nfs4_acl_get_whotype);
954EXPORT_SYMBOL(nfs4_acl_write_who);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
new file mode 100644
index 000000000000..c70de9c2af74
--- /dev/null
+++ b/fs/nfsd/nfs4callback.c
@@ -0,0 +1,547 @@
1/*
2 * linux/fs/nfsd/nfs4callback.c
3 *
4 * Copyright (c) 2001 The Regents of the University of Michigan.
5 * All rights reserved.
6 *
7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <andros@umich.edu>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include <linux/config.h>
37#include <linux/module.h>
38#include <linux/list.h>
39#include <linux/inet.h>
40#include <linux/errno.h>
41#include <linux/delay.h>
42#include <linux/sunrpc/xdr.h>
43#include <linux/sunrpc/svc.h>
44#include <linux/sunrpc/clnt.h>
45#include <linux/nfsd/nfsd.h>
46#include <linux/nfsd/state.h>
47#include <linux/sunrpc/sched.h>
48#include <linux/nfs4.h>
49
50#define NFSDDBG_FACILITY NFSDDBG_PROC
51
52#define NFSPROC4_CB_NULL 0
53#define NFSPROC4_CB_COMPOUND 1
54
55/* declarations */
56static void nfs4_cb_null(struct rpc_task *task);
57extern spinlock_t recall_lock;
58
59/* Index of predefined Linux callback client operations */
60
61enum {
62 NFSPROC4_CLNT_CB_NULL = 0,
63 NFSPROC4_CLNT_CB_RECALL,
64};
65
66enum nfs_cb_opnum4 {
67 OP_CB_RECALL = 4,
68};
69
70#define NFS4_MAXTAGLEN 20
71
72#define NFS4_enc_cb_null_sz 0
73#define NFS4_dec_cb_null_sz 0
74#define cb_compound_enc_hdr_sz 4
75#define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2))
76#define op_enc_sz 1
77#define op_dec_sz 2
78#define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2))
79#define enc_stateid_sz 16
80#define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \
81 1 + enc_stateid_sz + \
82 enc_nfs4_fh_sz)
83
84#define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \
85 op_dec_sz)
86
87/*
88* Generic encode routines from fs/nfs/nfs4xdr.c
89*/
90static inline u32 *
91xdr_writemem(u32 *p, const void *ptr, int nbytes)
92{
93 int tmp = XDR_QUADLEN(nbytes);
94 if (!tmp)
95 return p;
96 p[tmp-1] = 0;
97 memcpy(p, ptr, nbytes);
98 return p + tmp;
99}
100
101#define WRITE32(n) *p++ = htonl(n)
102#define WRITEMEM(ptr,nbytes) do { \
103 p = xdr_writemem(p, ptr, nbytes); \
104} while (0)
105#define RESERVE_SPACE(nbytes) do { \
106 p = xdr_reserve_space(xdr, nbytes); \
107 if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __FUNCTION__); \
108 BUG_ON(!p); \
109} while (0)
110
111/*
112 * Generic decode routines from fs/nfs/nfs4xdr.c
113 */
114#define DECODE_TAIL \
115 status = 0; \
116out: \
117 return status; \
118xdr_error: \
119 dprintk("NFSD: xdr error! (%s:%d)\n", __FILE__, __LINE__); \
120 status = -EIO; \
121 goto out
122
123#define READ32(x) (x) = ntohl(*p++)
124#define READ64(x) do { \
125 (x) = (u64)ntohl(*p++) << 32; \
126 (x) |= ntohl(*p++); \
127} while (0)
128#define READTIME(x) do { \
129 p++; \
130 (x.tv_sec) = ntohl(*p++); \
131 (x.tv_nsec) = ntohl(*p++); \
132} while (0)
133#define READ_BUF(nbytes) do { \
134 p = xdr_inline_decode(xdr, nbytes); \
135 if (!p) { \
136 dprintk("NFSD: %s: reply buffer overflowed in line %d.", \
137 __FUNCTION__, __LINE__); \
138 return -EIO; \
139 } \
140} while (0)
141
142struct nfs4_cb_compound_hdr {
143 int status;
144 u32 ident;
145 u32 nops;
146 u32 taglen;
147 char * tag;
148};
149
150static struct {
151int stat;
152int errno;
153} nfs_cb_errtbl[] = {
154 { NFS4_OK, 0 },
155 { NFS4ERR_PERM, EPERM },
156 { NFS4ERR_NOENT, ENOENT },
157 { NFS4ERR_IO, EIO },
158 { NFS4ERR_NXIO, ENXIO },
159 { NFS4ERR_ACCESS, EACCES },
160 { NFS4ERR_EXIST, EEXIST },
161 { NFS4ERR_XDEV, EXDEV },
162 { NFS4ERR_NOTDIR, ENOTDIR },
163 { NFS4ERR_ISDIR, EISDIR },
164 { NFS4ERR_INVAL, EINVAL },
165 { NFS4ERR_FBIG, EFBIG },
166 { NFS4ERR_NOSPC, ENOSPC },
167 { NFS4ERR_ROFS, EROFS },
168 { NFS4ERR_MLINK, EMLINK },
169 { NFS4ERR_NAMETOOLONG, ENAMETOOLONG },
170 { NFS4ERR_NOTEMPTY, ENOTEMPTY },
171 { NFS4ERR_DQUOT, EDQUOT },
172 { NFS4ERR_STALE, ESTALE },
173 { NFS4ERR_BADHANDLE, EBADHANDLE },
174 { NFS4ERR_BAD_COOKIE, EBADCOOKIE },
175 { NFS4ERR_NOTSUPP, ENOTSUPP },
176 { NFS4ERR_TOOSMALL, ETOOSMALL },
177 { NFS4ERR_SERVERFAULT, ESERVERFAULT },
178 { NFS4ERR_BADTYPE, EBADTYPE },
179 { NFS4ERR_LOCKED, EAGAIN },
180 { NFS4ERR_RESOURCE, EREMOTEIO },
181 { NFS4ERR_SYMLINK, ELOOP },
182 { NFS4ERR_OP_ILLEGAL, EOPNOTSUPP },
183 { NFS4ERR_DEADLOCK, EDEADLK },
184 { -1, EIO }
185};
186
187static int
188nfs_cb_stat_to_errno(int stat)
189{
190 int i;
191 for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) {
192 if (nfs_cb_errtbl[i].stat == stat)
193 return nfs_cb_errtbl[i].errno;
194 }
195 /* If we cannot translate the error, the recovery routines should
196 * handle it.
197 * Note: remaining NFSv4 error codes have values > 10000, so should
198 * not conflict with native Linux error codes.
199 */
200 return stat;
201}
202
203/*
204 * XDR encode
205 */
206
207static int
208encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr)
209{
210 u32 * p;
211
212 RESERVE_SPACE(16);
213 WRITE32(0); /* tag length is always 0 */
214 WRITE32(NFS4_MINOR_VERSION);
215 WRITE32(hdr->ident);
216 WRITE32(hdr->nops);
217 return 0;
218}
219
220static int
221encode_cb_recall(struct xdr_stream *xdr, struct nfs4_cb_recall *cb_rec)
222{
223 u32 *p;
224 int len = cb_rec->cbr_fhlen;
225
226 RESERVE_SPACE(12+sizeof(cb_rec->cbr_stateid) + len);
227 WRITE32(OP_CB_RECALL);
228 WRITEMEM(&cb_rec->cbr_stateid, sizeof(stateid_t));
229 WRITE32(cb_rec->cbr_trunc);
230 WRITE32(len);
231 WRITEMEM(cb_rec->cbr_fhval, len);
232 return 0;
233}
234
235static int
236nfs4_xdr_enc_cb_null(struct rpc_rqst *req, u32 *p)
237{
238 struct xdr_stream xdrs, *xdr = &xdrs;
239
240 xdr_init_encode(&xdrs, &req->rq_snd_buf, p);
241 RESERVE_SPACE(0);
242 return 0;
243}
244
245static int
246nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, u32 *p, struct nfs4_cb_recall *args)
247{
248 struct xdr_stream xdr;
249 struct nfs4_cb_compound_hdr hdr = {
250 .ident = args->cbr_ident,
251 .nops = 1,
252 };
253
254 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
255 encode_cb_compound_hdr(&xdr, &hdr);
256 return (encode_cb_recall(&xdr, args));
257}
258
259
260static int
261decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){
262 u32 *p;
263
264 READ_BUF(8);
265 READ32(hdr->status);
266 READ32(hdr->taglen);
267 READ_BUF(hdr->taglen + 4);
268 hdr->tag = (char *)p;
269 p += XDR_QUADLEN(hdr->taglen);
270 READ32(hdr->nops);
271 return 0;
272}
273
274static int
275decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
276{
277 u32 *p;
278 u32 op;
279 int32_t nfserr;
280
281 READ_BUF(8);
282 READ32(op);
283 if (op != expected) {
284 dprintk("NFSD: decode_cb_op_hdr: Callback server returned "
285 " operation %d but we issued a request for %d\n",
286 op, expected);
287 return -EIO;
288 }
289 READ32(nfserr);
290 if (nfserr != NFS_OK)
291 return -nfs_cb_stat_to_errno(nfserr);
292 return 0;
293}
294
295static int
296nfs4_xdr_dec_cb_null(struct rpc_rqst *req, u32 *p)
297{
298 return 0;
299}
300
301static int
302nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p)
303{
304 struct xdr_stream xdr;
305 struct nfs4_cb_compound_hdr hdr;
306 int status;
307
308 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
309 status = decode_cb_compound_hdr(&xdr, &hdr);
310 if (status)
311 goto out;
312 status = decode_cb_op_hdr(&xdr, OP_CB_RECALL);
313out:
314 return status;
315}
316
317/*
318 * RPC procedure tables
319 */
320#ifndef MAX
321# define MAX(a, b) (((a) > (b))? (a) : (b))
322#endif
323
324#define PROC(proc, call, argtype, restype) \
325[NFSPROC4_CLNT_##proc] = { \
326 .p_proc = NFSPROC4_CB_##call, \
327 .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \
328 .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \
329 .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \
330}
331
332struct rpc_procinfo nfs4_cb_procedures[] = {
333 PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null),
334 PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall),
335};
336
337struct rpc_version nfs_cb_version4 = {
338 .number = 1,
339 .nrprocs = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]),
340 .procs = nfs4_cb_procedures
341};
342
343static struct rpc_version * nfs_cb_version[] = {
344 NULL,
345 &nfs_cb_version4,
346};
347
348/*
349 * Use the SETCLIENTID credential
350 */
351struct rpc_cred *
352nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
353{
354 struct auth_cred acred;
355 struct rpc_clnt *clnt = clp->cl_callback.cb_client;
356 struct rpc_cred *ret;
357
358 get_group_info(clp->cl_cred.cr_group_info);
359 acred.uid = clp->cl_cred.cr_uid;
360 acred.gid = clp->cl_cred.cr_gid;
361 acred.group_info = clp->cl_cred.cr_group_info;
362
363 dprintk("NFSD: looking up %s cred\n",
364 clnt->cl_auth->au_ops->au_name);
365 ret = rpcauth_lookup_credcache(clnt->cl_auth, &acred, taskflags);
366 put_group_info(clp->cl_cred.cr_group_info);
367 return ret;
368}
369
370/*
371 * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
372 */
373void
374nfsd4_probe_callback(struct nfs4_client *clp)
375{
376 struct sockaddr_in addr;
377 struct nfs4_callback *cb = &clp->cl_callback;
378 struct rpc_timeout timeparms;
379 struct rpc_xprt * xprt;
380 struct rpc_program * program = &cb->cb_program;
381 struct rpc_stat * stat = &cb->cb_stat;
382 struct rpc_clnt * clnt;
383 struct rpc_message msg = {
384 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
385 .rpc_argp = clp,
386 };
387 char hostname[32];
388 int status;
389
390 dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n",
391 cb->cb_parsed, atomic_read(&cb->cb_set));
392 if (!cb->cb_parsed || atomic_read(&cb->cb_set))
393 return;
394
395 /* Initialize address */
396 memset(&addr, 0, sizeof(addr));
397 addr.sin_family = AF_INET;
398 addr.sin_port = htons(cb->cb_port);
399 addr.sin_addr.s_addr = htonl(cb->cb_addr);
400
401 /* Initialize timeout */
402 timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ;
403 timeparms.to_retries = 0;
404 timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ;
405 timeparms.to_exponential = 1;
406
407 /* Create RPC transport */
408 if (!(xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms))) {
409 dprintk("NFSD: couldn't create callback transport!\n");
410 goto out_err;
411 }
412
413 /* Initialize rpc_program */
414 program->name = "nfs4_cb";
415 program->number = cb->cb_prog;
416 program->nrvers = sizeof(nfs_cb_version)/sizeof(nfs_cb_version[0]);
417 program->version = nfs_cb_version;
418 program->stats = stat;
419
420 /* Initialize rpc_stat */
421 memset(stat, 0, sizeof(struct rpc_stat));
422 stat->program = program;
423
424 /* Create RPC client
425 *
426 * XXX AUTH_UNIX only - need AUTH_GSS....
427 */
428 sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
429 if (!(clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX))) {
430 dprintk("NFSD: couldn't create callback client\n");
431 goto out_xprt;
432 }
433 clnt->cl_intr = 0;
434 clnt->cl_softrtry = 1;
435 clnt->cl_chatty = 1;
436
437 /* Kick rpciod, put the call on the wire. */
438
439 if (rpciod_up() != 0) {
440 dprintk("nfsd: couldn't start rpciod for callbacks!\n");
441 goto out_clnt;
442 }
443
444 /* the task holds a reference to the nfs4_client struct */
445 cb->cb_client = clnt;
446 atomic_inc(&clp->cl_count);
447
448 msg.rpc_cred = nfsd4_lookupcred(clp,0);
449 if (IS_ERR(msg.rpc_cred))
450 goto out_rpciod;
451 status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL);
452 put_rpccred(msg.rpc_cred);
453
454 if (status != 0) {
455 dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
456 goto out_rpciod;
457 }
458 return;
459
460out_rpciod:
461 atomic_dec(&clp->cl_count);
462 rpciod_down();
463out_clnt:
464 rpc_shutdown_client(clnt);
465 goto out_err;
466out_xprt:
467 xprt_destroy(xprt);
468out_err:
469 dprintk("NFSD: warning: no callback path to client %.*s\n",
470 (int)clp->cl_name.len, clp->cl_name.data);
471 cb->cb_client = NULL;
472}
473
474static void
475nfs4_cb_null(struct rpc_task *task)
476{
477 struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
478 struct nfs4_callback *cb = &clp->cl_callback;
479 u32 addr = htonl(cb->cb_addr);
480
481 dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status);
482
483 if (task->tk_status < 0) {
484 dprintk("NFSD: callback establishment to client %.*s failed\n",
485 (int)clp->cl_name.len, clp->cl_name.data);
486 goto out;
487 }
488 atomic_set(&cb->cb_set, 1);
489 dprintk("NFSD: callback set to client %u.%u.%u.%u\n", NIPQUAD(addr));
490out:
491 put_nfs4_client(clp);
492}
493
494/*
495 * called with dp->dl_count inc'ed.
496 * nfs4_lock_state() may or may not have been called.
497 */
498void
499nfsd4_cb_recall(struct nfs4_delegation *dp)
500{
501 struct nfs4_client *clp = dp->dl_client;
502 struct rpc_clnt *clnt = clp->cl_callback.cb_client;
503 struct nfs4_cb_recall *cbr = &dp->dl_recall;
504 struct rpc_message msg = {
505 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
506 .rpc_argp = cbr,
507 };
508 int retries = 1;
509 int status = 0;
510
511 if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt)
512 return;
513
514 msg.rpc_cred = nfsd4_lookupcred(clp, 0);
515 if (IS_ERR(msg.rpc_cred))
516 goto out;
517
518 cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
519 cbr->cbr_dp = dp;
520
521 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
522 while (retries--) {
523 switch (status) {
524 case -EIO:
525 /* Network partition? */
526 case -EBADHANDLE:
527 case -NFS4ERR_BAD_STATEID:
528 /* Race: client probably got cb_recall
529 * before open reply granting delegation */
530 break;
531 default:
532 goto out_put_cred;
533 }
534 ssleep(2);
535 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
536 }
537out_put_cred:
538 put_rpccred(msg.rpc_cred);
539out:
540 if (status == -EIO)
541 atomic_set(&clp->cl_callback.cb_set, 0);
542 /* Success or failure, now we're either waiting for lease expiration
543 * or deleg_return. */
544 dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
545 nfs4_put_delegation(dp);
546 return;
547}
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
new file mode 100644
index 000000000000..4ba540841cf6
--- /dev/null
+++ b/fs/nfsd/nfs4idmap.c
@@ -0,0 +1,588 @@
1/*
2 * fs/nfsd/nfs4idmap.c
3 *
4 * Mapping of UID/GIDs to name and vice versa.
5 *
6 * Copyright (c) 2002, 2003 The Regents of the University of
7 * Michigan. All rights reserved.
8 *
9 * Marius Aamodt Eriksen <marius@umich.edu>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <linux/config.h>
38#include <linux/module.h>
39#include <linux/init.h>
40
41#include <linux/mm.h>
42#include <linux/utsname.h>
43#include <linux/errno.h>
44#include <linux/string.h>
45#include <linux/sunrpc/clnt.h>
46#include <linux/nfs.h>
47#include <linux/nfs4.h>
48#include <linux/nfs_fs.h>
49#include <linux/nfs_page.h>
50#include <linux/smp_lock.h>
51#include <linux/sunrpc/cache.h>
52#include <linux/nfsd_idmap.h>
53#include <linux/list.h>
54#include <linux/sched.h>
55#include <linux/time.h>
56#include <linux/seq_file.h>
57#include <linux/sunrpc/svcauth.h>
58
59/*
60 * Cache entry
61 */
62
63/*
64 * XXX we know that IDMAP_NAMESZ < PAGE_SIZE, but it's ugly to rely on
65 * that.
66 */
67
68#define IDMAP_TYPE_USER 0
69#define IDMAP_TYPE_GROUP 1
70
71struct ent {
72 struct cache_head h;
73 int type; /* User / Group */
74 uid_t id;
75 char name[IDMAP_NAMESZ];
76 char authname[IDMAP_NAMESZ];
77};
78
79#define DefineSimpleCacheLookupMap(STRUCT, FUNC) \
80 DefineCacheLookup(struct STRUCT, h, FUNC##_lookup, \
81 (struct STRUCT *item, int set), /*no setup */, \
82 & FUNC##_cache, FUNC##_hash(item), FUNC##_match(item, tmp), \
83 STRUCT##_init(new, item), STRUCT##_update(tmp, item), 0)
84
85/* Common entry handling */
86
87#define ENT_HASHBITS 8
88#define ENT_HASHMAX (1 << ENT_HASHBITS)
89#define ENT_HASHMASK (ENT_HASHMAX - 1)
90
91static inline void
92ent_init(struct ent *new, struct ent *itm)
93{
94 new->id = itm->id;
95 new->type = itm->type;
96
97 strlcpy(new->name, itm->name, sizeof(new->name));
98 strlcpy(new->authname, itm->authname, sizeof(new->name));
99}
100
101static inline void
102ent_update(struct ent *new, struct ent *itm)
103{
104 ent_init(new, itm);
105}
106
107void
108ent_put(struct cache_head *ch, struct cache_detail *cd)
109{
110 if (cache_put(ch, cd)) {
111 struct ent *map = container_of(ch, struct ent, h);
112 kfree(map);
113 }
114}
115
116/*
117 * ID -> Name cache
118 */
119
120static struct cache_head *idtoname_table[ENT_HASHMAX];
121
122static uint32_t
123idtoname_hash(struct ent *ent)
124{
125 uint32_t hash;
126
127 hash = hash_str(ent->authname, ENT_HASHBITS);
128 hash = hash_long(hash ^ ent->id, ENT_HASHBITS);
129
130 /* Flip LSB for user/group */
131 if (ent->type == IDMAP_TYPE_GROUP)
132 hash ^= 1;
133
134 return hash;
135}
136
137static void
138idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
139 int *blen)
140{
141 struct ent *ent = container_of(ch, struct ent, h);
142 char idstr[11];
143
144 qword_add(bpp, blen, ent->authname);
145 snprintf(idstr, sizeof(idstr), "%d", ent->id);
146 qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
147 qword_add(bpp, blen, idstr);
148
149 (*bpp)[-1] = '\n';
150}
151
152static inline int
153idtoname_match(struct ent *a, struct ent *b)
154{
155 return (a->id == b->id && a->type == b->type &&
156 strcmp(a->authname, b->authname) == 0);
157}
158
159static int
160idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
161{
162 struct ent *ent;
163
164 if (h == NULL) {
165 seq_puts(m, "#domain type id [name]\n");
166 return 0;
167 }
168 ent = container_of(h, struct ent, h);
169 seq_printf(m, "%s %s %d", ent->authname,
170 ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
171 ent->id);
172 if (test_bit(CACHE_VALID, &h->flags))
173 seq_printf(m, " %s", ent->name);
174 seq_printf(m, "\n");
175 return 0;
176}
177
178static void
179warn_no_idmapd(struct cache_detail *detail)
180{
181 printk("nfsd: nfsv4 idmapping failing: has idmapd %s?\n",
182 detail->last_close? "died" : "not been started");
183}
184
185
186static int idtoname_parse(struct cache_detail *, char *, int);
187static struct ent *idtoname_lookup(struct ent *, int);
188
189struct cache_detail idtoname_cache = {
190 .hash_size = ENT_HASHMAX,
191 .hash_table = idtoname_table,
192 .name = "nfs4.idtoname",
193 .cache_put = ent_put,
194 .cache_request = idtoname_request,
195 .cache_parse = idtoname_parse,
196 .cache_show = idtoname_show,
197 .warn_no_listener = warn_no_idmapd,
198};
199
200int
201idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
202{
203 struct ent ent, *res;
204 char *buf1, *bp;
205 int error = -EINVAL;
206
207 if (buf[buflen - 1] != '\n')
208 return (-EINVAL);
209 buf[buflen - 1]= '\0';
210
211 buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
212 if (buf1 == NULL)
213 return (-ENOMEM);
214
215 memset(&ent, 0, sizeof(ent));
216
217 /* Authentication name */
218 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
219 goto out;
220 memcpy(ent.authname, buf1, sizeof(ent.authname));
221
222 /* Type */
223 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
224 goto out;
225 ent.type = strcmp(buf1, "user") == 0 ?
226 IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
227
228 /* ID */
229 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
230 goto out;
231 ent.id = simple_strtoul(buf1, &bp, 10);
232 if (bp == buf1)
233 goto out;
234
235 /* expiry */
236 ent.h.expiry_time = get_expiry(&buf);
237 if (ent.h.expiry_time == 0)
238 goto out;
239
240 /* Name */
241 error = qword_get(&buf, buf1, PAGE_SIZE);
242 if (error == -EINVAL)
243 goto out;
244 if (error == -ENOENT)
245 set_bit(CACHE_NEGATIVE, &ent.h.flags);
246 else {
247 if (error >= IDMAP_NAMESZ) {
248 error = -EINVAL;
249 goto out;
250 }
251 memcpy(ent.name, buf1, sizeof(ent.name));
252 }
253 error = -ENOMEM;
254 if ((res = idtoname_lookup(&ent, 1)) == NULL)
255 goto out;
256
257 ent_put(&res->h, &idtoname_cache);
258
259 error = 0;
260out:
261 kfree(buf1);
262
263 return error;
264}
265
266static DefineSimpleCacheLookupMap(ent, idtoname);
267
268/*
269 * Name -> ID cache
270 */
271
272static struct cache_head *nametoid_table[ENT_HASHMAX];
273
274static inline int
275nametoid_hash(struct ent *ent)
276{
277 return hash_str(ent->name, ENT_HASHBITS);
278}
279
280void
281nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
282 int *blen)
283{
284 struct ent *ent = container_of(ch, struct ent, h);
285
286 qword_add(bpp, blen, ent->authname);
287 qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
288 qword_add(bpp, blen, ent->name);
289
290 (*bpp)[-1] = '\n';
291}
292
293static inline int
294nametoid_match(struct ent *a, struct ent *b)
295{
296 return (a->type == b->type && strcmp(a->name, b->name) == 0 &&
297 strcmp(a->authname, b->authname) == 0);
298}
299
300static int
301nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
302{
303 struct ent *ent;
304
305 if (h == NULL) {
306 seq_puts(m, "#domain type name [id]\n");
307 return 0;
308 }
309 ent = container_of(h, struct ent, h);
310 seq_printf(m, "%s %s %s", ent->authname,
311 ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
312 ent->name);
313 if (test_bit(CACHE_VALID, &h->flags))
314 seq_printf(m, " %d", ent->id);
315 seq_printf(m, "\n");
316 return 0;
317}
318
319static struct ent *nametoid_lookup(struct ent *, int);
320int nametoid_parse(struct cache_detail *, char *, int);
321
322struct cache_detail nametoid_cache = {
323 .hash_size = ENT_HASHMAX,
324 .hash_table = nametoid_table,
325 .name = "nfs4.nametoid",
326 .cache_put = ent_put,
327 .cache_request = nametoid_request,
328 .cache_parse = nametoid_parse,
329 .cache_show = nametoid_show,
330 .warn_no_listener = warn_no_idmapd,
331};
332
333int
334nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
335{
336 struct ent ent, *res;
337 char *buf1;
338 int error = -EINVAL;
339
340 if (buf[buflen - 1] != '\n')
341 return (-EINVAL);
342 buf[buflen - 1]= '\0';
343
344 buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
345 if (buf1 == NULL)
346 return (-ENOMEM);
347
348 memset(&ent, 0, sizeof(ent));
349
350 /* Authentication name */
351 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
352 goto out;
353 memcpy(ent.authname, buf1, sizeof(ent.authname));
354
355 /* Type */
356 if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
357 goto out;
358 ent.type = strcmp(buf1, "user") == 0 ?
359 IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
360
361 /* Name */
362 error = qword_get(&buf, buf1, PAGE_SIZE);
363 if (error <= 0 || error >= IDMAP_NAMESZ)
364 goto out;
365 memcpy(ent.name, buf1, sizeof(ent.name));
366
367 /* expiry */
368 ent.h.expiry_time = get_expiry(&buf);
369 if (ent.h.expiry_time == 0)
370 goto out;
371
372 /* ID */
373 error = get_int(&buf, &ent.id);
374 if (error == -EINVAL)
375 goto out;
376 if (error == -ENOENT)
377 set_bit(CACHE_NEGATIVE, &ent.h.flags);
378
379 error = -ENOMEM;
380 if ((res = nametoid_lookup(&ent, 1)) == NULL)
381 goto out;
382
383 ent_put(&res->h, &nametoid_cache);
384 error = 0;
385out:
386 kfree(buf1);
387
388 return (error);
389}
390
391static DefineSimpleCacheLookupMap(ent, nametoid);
392
393/*
394 * Exported API
395 */
396
397void
398nfsd_idmap_init(void)
399{
400 cache_register(&idtoname_cache);
401 cache_register(&nametoid_cache);
402}
403
404void
405nfsd_idmap_shutdown(void)
406{
407 cache_unregister(&idtoname_cache);
408 cache_unregister(&nametoid_cache);
409}
410
411/*
412 * Deferred request handling
413 */
414
415struct idmap_defer_req {
416 struct cache_req req;
417 struct cache_deferred_req deferred_req;
418 wait_queue_head_t waitq;
419 atomic_t count;
420};
421
422static inline void
423put_mdr(struct idmap_defer_req *mdr)
424{
425 if (atomic_dec_and_test(&mdr->count))
426 kfree(mdr);
427}
428
429static inline void
430get_mdr(struct idmap_defer_req *mdr)
431{
432 atomic_inc(&mdr->count);
433}
434
435static void
436idmap_revisit(struct cache_deferred_req *dreq, int toomany)
437{
438 struct idmap_defer_req *mdr =
439 container_of(dreq, struct idmap_defer_req, deferred_req);
440
441 wake_up(&mdr->waitq);
442 put_mdr(mdr);
443}
444
445static struct cache_deferred_req *
446idmap_defer(struct cache_req *req)
447{
448 struct idmap_defer_req *mdr =
449 container_of(req, struct idmap_defer_req, req);
450
451 mdr->deferred_req.revisit = idmap_revisit;
452 get_mdr(mdr);
453 return (&mdr->deferred_req);
454}
455
456static inline int
457do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
458 struct cache_detail *detail, struct ent **item,
459 struct idmap_defer_req *mdr)
460{
461 *item = lookup_fn(key, 0);
462 if (!*item)
463 return -ENOMEM;
464 return cache_check(detail, &(*item)->h, &mdr->req);
465}
466
467static inline int
468do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int),
469 struct ent *key, struct cache_detail *detail,
470 struct ent **item)
471{
472 int ret = -ENOMEM;
473
474 *item = lookup_fn(key, 0);
475 if (!*item)
476 goto out_err;
477 ret = -ETIMEDOUT;
478 if (!test_bit(CACHE_VALID, &(*item)->h.flags)
479 || (*item)->h.expiry_time < get_seconds()
480 || detail->flush_time > (*item)->h.last_refresh)
481 goto out_put;
482 ret = -ENOENT;
483 if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
484 goto out_put;
485 return 0;
486out_put:
487 ent_put(&(*item)->h, detail);
488out_err:
489 *item = NULL;
490 return ret;
491}
492
493static int
494idmap_lookup(struct svc_rqst *rqstp,
495 struct ent *(*lookup_fn)(struct ent *, int), struct ent *key,
496 struct cache_detail *detail, struct ent **item)
497{
498 struct idmap_defer_req *mdr;
499 int ret;
500
501 mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
502 if (!mdr)
503 return -ENOMEM;
504 memset(mdr, 0, sizeof(*mdr));
505 atomic_set(&mdr->count, 1);
506 init_waitqueue_head(&mdr->waitq);
507 mdr->req.defer = idmap_defer;
508 ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr);
509 if (ret == -EAGAIN) {
510 wait_event_interruptible_timeout(mdr->waitq,
511 test_bit(CACHE_VALID, &(*item)->h.flags), 1 * HZ);
512 ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item);
513 }
514 put_mdr(mdr);
515 return ret;
516}
517
518static int
519idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
520 uid_t *id)
521{
522 struct ent *item, key = {
523 .type = type,
524 };
525 int ret;
526
527 if (namelen + 1 > sizeof(key.name))
528 return -EINVAL;
529 memcpy(key.name, name, namelen);
530 key.name[namelen] = '\0';
531 strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
532 ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
533 if (ret == -ENOENT)
534 ret = -ESRCH; /* nfserr_badname */
535 if (ret)
536 return ret;
537 *id = item->id;
538 ent_put(&item->h, &nametoid_cache);
539 return 0;
540}
541
542static int
543idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
544{
545 struct ent *item, key = {
546 .id = id,
547 .type = type,
548 };
549 int ret;
550
551 strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
552 ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
553 if (ret == -ENOENT)
554 return sprintf(name, "%u", id);
555 if (ret)
556 return ret;
557 ret = strlen(item->name);
558 BUG_ON(ret > IDMAP_NAMESZ);
559 memcpy(name, item->name, ret);
560 ent_put(&item->h, &idtoname_cache);
561 return ret;
562}
563
564int
565nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
566 __u32 *id)
567{
568 return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
569}
570
571int
572nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
573 __u32 *id)
574{
575 return idmap_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
576}
577
578int
579nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
580{
581 return idmap_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
582}
583
584int
585nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
586{
587 return idmap_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
588}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
new file mode 100644
index 000000000000..e8158741e8b5
--- /dev/null
+++ b/fs/nfsd/nfs4proc.c
@@ -0,0 +1,984 @@
1/*
2 * fs/nfsd/nfs4proc.c
3 *
4 * Server-side procedures for NFSv4.
5 *
6 * Copyright (c) 2002 The Regents of the University of Michigan.
7 * All rights reserved.
8 *
9 * Kendrick Smith <kmsmith@umich.edu>
10 * Andy Adamson <andros@umich.edu>
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Note: some routines in this file are just trivial wrappers
38 * (e.g. nfsd4_lookup()) defined solely for the sake of consistent
39 * naming. Since all such routines have been declared "inline",
40 * there shouldn't be any associated overhead. At some point in
41 * the future, I might inline these "by hand" to clean up a
42 * little.
43 */
44
45#include <linux/param.h>
46#include <linux/major.h>
47#include <linux/slab.h>
48
49#include <linux/sunrpc/svc.h>
50#include <linux/nfsd/nfsd.h>
51#include <linux/nfsd/cache.h>
52#include <linux/nfs4.h>
53#include <linux/nfsd/state.h>
54#include <linux/nfsd/xdr4.h>
55#include <linux/nfs4_acl.h>
56
57#define NFSDDBG_FACILITY NFSDDBG_PROC
58
59static inline void
60fh_dup2(struct svc_fh *dst, struct svc_fh *src)
61{
62 fh_put(dst);
63 dget(src->fh_dentry);
64 if (src->fh_export)
65 cache_get(&src->fh_export->h);
66 *dst = *src;
67}
68
69static int
70do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
71{
72 int accmode, status;
73
74 if (open->op_truncate &&
75 !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
76 return nfserr_inval;
77
78 accmode = MAY_NOP;
79 if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
80 accmode = MAY_READ;
81 if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE)
82 accmode |= (MAY_WRITE | MAY_TRUNC);
83 accmode |= MAY_OWNER_OVERRIDE;
84
85 status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
86
87 return status;
88}
89
90static int
91do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
92{
93 struct svc_fh resfh;
94 int status;
95
96 fh_init(&resfh, NFS4_FHSIZE);
97 open->op_truncate = 0;
98
99 if (open->op_create) {
100 /*
101 * Note: create modes (UNCHECKED,GUARDED...) are the same
102 * in NFSv4 as in v3.
103 */
104 status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
105 open->op_fname.len, &open->op_iattr,
106 &resfh, open->op_createmode,
107 (u32 *)open->op_verf.data, &open->op_truncate);
108 }
109 else {
110 status = nfsd_lookup(rqstp, current_fh,
111 open->op_fname.data, open->op_fname.len, &resfh);
112 fh_unlock(current_fh);
113 }
114
115 if (!status) {
116 set_change_info(&open->op_cinfo, current_fh);
117
118 /* set reply cache */
119 fh_dup2(current_fh, &resfh);
120 open->op_stateowner->so_replay.rp_openfh_len =
121 resfh.fh_handle.fh_size;
122 memcpy(open->op_stateowner->so_replay.rp_openfh,
123 &resfh.fh_handle.fh_base,
124 resfh.fh_handle.fh_size);
125
126 status = do_open_permission(rqstp, current_fh, open);
127 }
128
129 fh_put(&resfh);
130 return status;
131}
132
133static int
134do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
135{
136 int status;
137
138 /* Only reclaims from previously confirmed clients are valid */
139 if ((status = nfs4_check_open_reclaim(&open->op_clientid)))
140 return status;
141
142 /* We don't know the target directory, and therefore can not
143 * set the change info
144 */
145
146 memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
147
148 /* set replay cache */
149 open->op_stateowner->so_replay.rp_openfh_len = current_fh->fh_handle.fh_size;
150 memcpy(open->op_stateowner->so_replay.rp_openfh,
151 &current_fh->fh_handle.fh_base,
152 current_fh->fh_handle.fh_size);
153
154 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
155 (open->op_iattr.ia_size == 0);
156
157 status = do_open_permission(rqstp, current_fh, open);
158
159 return status;
160}
161
162
163static inline int
164nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
165{
166 int status;
167 dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
168 (int)open->op_fname.len, open->op_fname.data,
169 open->op_stateowner);
170
171 if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
172 return nfserr_grace;
173
174 if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
175 return nfserr_no_grace;
176
177 /* This check required by spec. */
178 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
179 return nfserr_inval;
180
181 nfs4_lock_state();
182
183 /* check seqid for replay. set nfs4_owner */
184 status = nfsd4_process_open1(open);
185 if (status == NFSERR_REPLAY_ME) {
186 struct nfs4_replay *rp = &open->op_stateowner->so_replay;
187 fh_put(current_fh);
188 current_fh->fh_handle.fh_size = rp->rp_openfh_len;
189 memcpy(&current_fh->fh_handle.fh_base, rp->rp_openfh,
190 rp->rp_openfh_len);
191 status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
192 if (status)
193 dprintk("nfsd4_open: replay failed"
194 " restoring previous filehandle\n");
195 else
196 status = NFSERR_REPLAY_ME;
197 }
198 if (status)
199 goto out;
200 switch (open->op_claim_type) {
201 case NFS4_OPEN_CLAIM_NULL:
202 /*
203 * (1) set CURRENT_FH to the file being opened,
204 * creating it if necessary, (2) set open->op_cinfo,
205 * (3) set open->op_truncate if the file is to be
206 * truncated after opening, (4) do permission checking.
207 */
208 status = do_open_lookup(rqstp, current_fh, open);
209 if (status)
210 goto out;
211 break;
212 case NFS4_OPEN_CLAIM_PREVIOUS:
213 /*
214 * The CURRENT_FH is already set to the file being
215 * opened. (1) set open->op_cinfo, (2) set
216 * open->op_truncate if the file is to be truncated
217 * after opening, (3) do permission checking.
218 */
219 status = do_open_fhandle(rqstp, current_fh, open);
220 if (status)
221 goto out;
222 break;
223 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
224 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
225 printk("NFSD: unsupported OPEN claim type %d\n",
226 open->op_claim_type);
227 status = nfserr_notsupp;
228 goto out;
229 default:
230 printk("NFSD: Invalid OPEN claim type %d\n",
231 open->op_claim_type);
232 status = nfserr_inval;
233 goto out;
234 }
235 /*
236 * nfsd4_process_open2() does the actual opening of the file. If
237 * successful, it (1) truncates the file if open->op_truncate was
238 * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
239 */
240 status = nfsd4_process_open2(rqstp, current_fh, open);
241out:
242 if (open->op_stateowner)
243 nfs4_get_stateowner(open->op_stateowner);
244 nfs4_unlock_state();
245 return status;
246}
247
248/*
249 * filehandle-manipulating ops.
250 */
251static inline int
252nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh)
253{
254 if (!current_fh->fh_dentry)
255 return nfserr_nofilehandle;
256
257 *getfh = current_fh;
258 return nfs_ok;
259}
260
261static inline int
262nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh)
263{
264 fh_put(current_fh);
265 current_fh->fh_handle.fh_size = putfh->pf_fhlen;
266 memcpy(&current_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen);
267 return fh_verify(rqstp, current_fh, 0, MAY_NOP);
268}
269
270static inline int
271nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
272{
273 int status;
274
275 fh_put(current_fh);
276 status = exp_pseudoroot(rqstp->rq_client, current_fh,
277 &rqstp->rq_chandle);
278 if (!status)
279 status = nfserrno(nfsd_setuser(rqstp, current_fh->fh_export));
280 return status;
281}
282
283static inline int
284nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
285{
286 if (!save_fh->fh_dentry)
287 return nfserr_restorefh;
288
289 fh_dup2(current_fh, save_fh);
290 return nfs_ok;
291}
292
293static inline int
294nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
295{
296 if (!current_fh->fh_dentry)
297 return nfserr_nofilehandle;
298
299 fh_dup2(save_fh, current_fh);
300 return nfs_ok;
301}
302
303/*
304 * misc nfsv4 ops
305 */
306static inline int
307nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access)
308{
309 if (access->ac_req_access & ~NFS3_ACCESS_FULL)
310 return nfserr_inval;
311
312 access->ac_resp_access = access->ac_req_access;
313 return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported);
314}
315
316static inline int
317nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
318{
319 int status;
320
321 u32 *p = (u32 *)commit->co_verf.data;
322 *p++ = nfssvc_boot.tv_sec;
323 *p++ = nfssvc_boot.tv_usec;
324
325 status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
326 if (status == nfserr_symlink)
327 status = nfserr_inval;
328 return status;
329}
330
331static int
332nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
333{
334 struct svc_fh resfh;
335 int status;
336 dev_t rdev;
337
338 fh_init(&resfh, NFS4_FHSIZE);
339
340 status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE);
341 if (status == nfserr_symlink)
342 status = nfserr_notdir;
343 if (status)
344 return status;
345
346 switch (create->cr_type) {
347 case NF4LNK:
348 /* ugh! we have to null-terminate the linktext, or
349 * vfs_symlink() will choke. it is always safe to
350 * null-terminate by brute force, since at worst we
351 * will overwrite the first byte of the create namelen
352 * in the XDR buffer, which has already been extracted
353 * during XDR decode.
354 */
355 create->cr_linkname[create->cr_linklen] = 0;
356
357 status = nfsd_symlink(rqstp, current_fh, create->cr_name,
358 create->cr_namelen, create->cr_linkname,
359 create->cr_linklen, &resfh, &create->cr_iattr);
360 break;
361
362 case NF4BLK:
363 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
364 if (MAJOR(rdev) != create->cr_specdata1 ||
365 MINOR(rdev) != create->cr_specdata2)
366 return nfserr_inval;
367 status = nfsd_create(rqstp, current_fh, create->cr_name,
368 create->cr_namelen, &create->cr_iattr,
369 S_IFBLK, rdev, &resfh);
370 break;
371
372 case NF4CHR:
373 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
374 if (MAJOR(rdev) != create->cr_specdata1 ||
375 MINOR(rdev) != create->cr_specdata2)
376 return nfserr_inval;
377 status = nfsd_create(rqstp, current_fh, create->cr_name,
378 create->cr_namelen, &create->cr_iattr,
379 S_IFCHR, rdev, &resfh);
380 break;
381
382 case NF4SOCK:
383 status = nfsd_create(rqstp, current_fh, create->cr_name,
384 create->cr_namelen, &create->cr_iattr,
385 S_IFSOCK, 0, &resfh);
386 break;
387
388 case NF4FIFO:
389 status = nfsd_create(rqstp, current_fh, create->cr_name,
390 create->cr_namelen, &create->cr_iattr,
391 S_IFIFO, 0, &resfh);
392 break;
393
394 case NF4DIR:
395 create->cr_iattr.ia_valid &= ~ATTR_SIZE;
396 status = nfsd_create(rqstp, current_fh, create->cr_name,
397 create->cr_namelen, &create->cr_iattr,
398 S_IFDIR, 0, &resfh);
399 break;
400
401 default:
402 status = nfserr_badtype;
403 }
404
405 if (!status) {
406 fh_unlock(current_fh);
407 set_change_info(&create->cr_cinfo, current_fh);
408 fh_dup2(current_fh, &resfh);
409 }
410
411 fh_put(&resfh);
412 return status;
413}
414
415static inline int
416nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr)
417{
418 int status;
419
420 status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
421 if (status)
422 return status;
423
424 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
425 return nfserr_inval;
426
427 getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
428 getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
429
430 getattr->ga_fhp = current_fh;
431 return nfs_ok;
432}
433
434static inline int
435nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
436 struct svc_fh *save_fh, struct nfsd4_link *link)
437{
438 int status = nfserr_nofilehandle;
439
440 if (!save_fh->fh_dentry)
441 return status;
442 status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
443 if (!status)
444 set_change_info(&link->li_cinfo, current_fh);
445 return status;
446}
447
448static int
449nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
450{
451 struct svc_fh tmp_fh;
452 int ret;
453
454 fh_init(&tmp_fh, NFS4_FHSIZE);
455 if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
456 &rqstp->rq_chandle)) != 0)
457 return ret;
458 if (tmp_fh.fh_dentry == current_fh->fh_dentry) {
459 fh_put(&tmp_fh);
460 return nfserr_noent;
461 }
462 fh_put(&tmp_fh);
463 return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
464}
465
466static inline int
467nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup)
468{
469 return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
470}
471
472static inline int
473nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
474{
475 int status;
476 struct file *filp = NULL;
477
478 /* no need to check permission - this will be done in nfsd_read() */
479
480 if (read->rd_offset >= OFFSET_MAX)
481 return nfserr_inval;
482
483 nfs4_lock_state();
484 /* check stateid */
485 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
486 CHECK_FH | RD_STATE, &filp))) {
487 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
488 goto out;
489 }
490 status = nfs_ok;
491out:
492 nfs4_unlock_state();
493 read->rd_rqstp = rqstp;
494 read->rd_fhp = current_fh;
495 read->rd_filp = filp;
496 return status;
497}
498
499static inline int
500nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
501{
502 u64 cookie = readdir->rd_cookie;
503 static const nfs4_verifier zeroverf;
504
505 /* no need to check permission - this will be done in nfsd_readdir() */
506
507 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
508 return nfserr_inval;
509
510 readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
511 readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
512
513 if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
514 (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
515 return nfserr_bad_cookie;
516
517 readdir->rd_rqstp = rqstp;
518 readdir->rd_fhp = current_fh;
519 return nfs_ok;
520}
521
522static inline int
523nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink)
524{
525 readlink->rl_rqstp = rqstp;
526 readlink->rl_fhp = current_fh;
527 return nfs_ok;
528}
529
530static inline int
531nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove)
532{
533 int status;
534
535 status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
536 if (status == nfserr_symlink)
537 return nfserr_notdir;
538 if (!status) {
539 fh_unlock(current_fh);
540 set_change_info(&remove->rm_cinfo, current_fh);
541 }
542 return status;
543}
544
545static inline int
546nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
547 struct svc_fh *save_fh, struct nfsd4_rename *rename)
548{
549 int status = nfserr_nofilehandle;
550
551 if (!save_fh->fh_dentry)
552 return status;
553 status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
554 rename->rn_snamelen, current_fh,
555 rename->rn_tname, rename->rn_tnamelen);
556
557 /* the underlying filesystem returns different error's than required
558 * by NFSv4. both save_fh and current_fh have been verified.. */
559 if (status == nfserr_isdir)
560 status = nfserr_exist;
561 else if ((status == nfserr_notdir) &&
562 (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) &&
563 S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
564 status = nfserr_exist;
565 else if (status == nfserr_symlink)
566 status = nfserr_notdir;
567
568 if (!status) {
569 set_change_info(&rename->rn_sinfo, current_fh);
570 set_change_info(&rename->rn_tinfo, save_fh);
571 }
572 return status;
573}
574
575static inline int
576nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
577{
578 int status = nfs_ok;
579
580 if (!current_fh->fh_dentry)
581 return nfserr_nofilehandle;
582
583 status = nfs_ok;
584 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
585 nfs4_lock_state();
586 if ((status = nfs4_preprocess_stateid_op(current_fh,
587 &setattr->sa_stateid,
588 CHECK_FH | WR_STATE, NULL))) {
589 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
590 goto out_unlock;
591 }
592 nfs4_unlock_state();
593 }
594 status = nfs_ok;
595 if (setattr->sa_acl != NULL)
596 status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
597 if (status)
598 goto out;
599 status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
600 0, (time_t)0);
601out:
602 return status;
603out_unlock:
604 nfs4_unlock_state();
605 return status;
606}
607
608static inline int
609nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
610{
611 stateid_t *stateid = &write->wr_stateid;
612 struct file *filp = NULL;
613 u32 *p;
614 int status = nfs_ok;
615
616 /* no need to check permission - this will be done in nfsd_write() */
617
618 if (write->wr_offset >= OFFSET_MAX)
619 return nfserr_inval;
620
621 nfs4_lock_state();
622 if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
623 CHECK_FH | WR_STATE, &filp))) {
624 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
625 goto out;
626 }
627 nfs4_unlock_state();
628
629 write->wr_bytes_written = write->wr_buflen;
630 write->wr_how_written = write->wr_stable_how;
631 p = (u32 *)write->wr_verifier.data;
632 *p++ = nfssvc_boot.tv_sec;
633 *p++ = nfssvc_boot.tv_usec;
634
635 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
636 write->wr_vec, write->wr_vlen, write->wr_buflen,
637 &write->wr_how_written);
638
639 if (status == nfserr_symlink)
640 status = nfserr_inval;
641 return status;
642out:
643 nfs4_unlock_state();
644 return status;
645}
646
647/* This routine never returns NFS_OK! If there are no other errors, it
648 * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the
649 * attributes matched. VERIFY is implemented by mapping NFSERR_SAME
650 * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
651 */
652static int
653nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify)
654{
655 u32 *buf, *p;
656 int count;
657 int status;
658
659 status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
660 if (status)
661 return status;
662
663 if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)
664 || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
665 return nfserr_attrnotsupp;
666 if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
667 || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
668 return nfserr_inval;
669 if (verify->ve_attrlen & 3)
670 return nfserr_inval;
671
672 /* count in words:
673 * bitmap_len(1) + bitmap(2) + attr_len(1) = 4
674 */
675 count = 4 + (verify->ve_attrlen >> 2);
676 buf = kmalloc(count << 2, GFP_KERNEL);
677 if (!buf)
678 return nfserr_resource;
679
680 status = nfsd4_encode_fattr(current_fh, current_fh->fh_export,
681 current_fh->fh_dentry, buf,
682 &count, verify->ve_bmval,
683 rqstp);
684
685 /* this means that nfsd4_encode_fattr() ran out of space */
686 if (status == nfserr_resource && count == 0)
687 status = nfserr_not_same;
688 if (status)
689 goto out_kfree;
690
691 p = buf + 3;
692 status = nfserr_not_same;
693 if (ntohl(*p++) != verify->ve_attrlen)
694 goto out_kfree;
695 if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen))
696 status = nfserr_same;
697
698out_kfree:
699 kfree(buf);
700 return status;
701}
702
703/*
704 * NULL call.
705 */
706static int
707nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
708{
709 return nfs_ok;
710}
711
712
713/*
714 * COMPOUND call.
715 */
716static int
717nfsd4_proc_compound(struct svc_rqst *rqstp,
718 struct nfsd4_compoundargs *args,
719 struct nfsd4_compoundres *resp)
720{
721 struct nfsd4_op *op;
722 struct svc_fh *current_fh = NULL;
723 struct svc_fh *save_fh = NULL;
724 struct nfs4_stateowner *replay_owner = NULL;
725 int slack_space; /* in words, not bytes! */
726 int status;
727
728 status = nfserr_resource;
729 current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL);
730 if (current_fh == NULL)
731 goto out;
732 fh_init(current_fh, NFS4_FHSIZE);
733 save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL);
734 if (save_fh == NULL)
735 goto out;
736 fh_init(save_fh, NFS4_FHSIZE);
737
738 resp->xbuf = &rqstp->rq_res;
739 resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
740 resp->tagp = resp->p;
741 /* reserve space for: taglen, tag, and opcnt */
742 resp->p += 2 + XDR_QUADLEN(args->taglen);
743 resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
744 resp->taglen = args->taglen;
745 resp->tag = args->tag;
746 resp->opcnt = 0;
747 resp->rqstp = rqstp;
748
749 /*
750 * According to RFC3010, this takes precedence over all other errors.
751 */
752 status = nfserr_minor_vers_mismatch;
753 if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
754 goto out;
755
756 status = nfs_ok;
757 while (!status && resp->opcnt < args->opcnt) {
758 op = &args->ops[resp->opcnt++];
759
760 /*
761 * The XDR decode routines may have pre-set op->status;
762 * for example, if there is a miscellaneous XDR error
763 * it will be set to nfserr_bad_xdr.
764 */
765 if (op->status)
766 goto encode_op;
767
768 /* We must be able to encode a successful response to
769 * this operation, with enough room left over to encode a
770 * failed response to the next operation. If we don't
771 * have enough room, fail with ERR_RESOURCE.
772 */
773/* FIXME - is slack_space *really* words, or bytes??? - neilb */
774 slack_space = (char *)resp->end - (char *)resp->p;
775 if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) {
776 BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE);
777 op->status = nfserr_resource;
778 goto encode_op;
779 }
780
781 /* All operations except RENEW, SETCLIENTID, RESTOREFH
782 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
783 * require a valid current filehandle
784 *
785 * SETATTR NOFILEHANDLE error handled in nfsd4_setattr
786 * due to required returned bitmap argument
787 */
788 if ((!current_fh->fh_dentry) &&
789 !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
790 (op->opnum == OP_SETCLIENTID) ||
791 (op->opnum == OP_SETCLIENTID_CONFIRM) ||
792 (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
793 (op->opnum == OP_RELEASE_LOCKOWNER) ||
794 (op->opnum == OP_SETATTR))) {
795 op->status = nfserr_nofilehandle;
796 goto encode_op;
797 }
798 switch (op->opnum) {
799 case OP_ACCESS:
800 op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
801 break;
802 case OP_CLOSE:
803 op->status = nfsd4_close(rqstp, current_fh, &op->u.close);
804 replay_owner = op->u.close.cl_stateowner;
805 break;
806 case OP_COMMIT:
807 op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
808 break;
809 case OP_CREATE:
810 op->status = nfsd4_create(rqstp, current_fh, &op->u.create);
811 break;
812 case OP_DELEGRETURN:
813 op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn);
814 break;
815 case OP_GETATTR:
816 op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr);
817 break;
818 case OP_GETFH:
819 op->status = nfsd4_getfh(current_fh, &op->u.getfh);
820 break;
821 case OP_LINK:
822 op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
823 break;
824 case OP_LOCK:
825 op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock);
826 replay_owner = op->u.lock.lk_stateowner;
827 break;
828 case OP_LOCKT:
829 op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
830 break;
831 case OP_LOCKU:
832 op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku);
833 replay_owner = op->u.locku.lu_stateowner;
834 break;
835 case OP_LOOKUP:
836 op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
837 break;
838 case OP_LOOKUPP:
839 op->status = nfsd4_lookupp(rqstp, current_fh);
840 break;
841 case OP_NVERIFY:
842 op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify);
843 if (op->status == nfserr_not_same)
844 op->status = nfs_ok;
845 break;
846 case OP_OPEN:
847 op->status = nfsd4_open(rqstp, current_fh, &op->u.open);
848 replay_owner = op->u.open.op_stateowner;
849 break;
850 case OP_OPEN_CONFIRM:
851 op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm);
852 replay_owner = op->u.open_confirm.oc_stateowner;
853 break;
854 case OP_OPEN_DOWNGRADE:
855 op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade);
856 replay_owner = op->u.open_downgrade.od_stateowner;
857 break;
858 case OP_PUTFH:
859 op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
860 break;
861 case OP_PUTROOTFH:
862 op->status = nfsd4_putrootfh(rqstp, current_fh);
863 break;
864 case OP_READ:
865 op->status = nfsd4_read(rqstp, current_fh, &op->u.read);
866 break;
867 case OP_READDIR:
868 op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir);
869 break;
870 case OP_READLINK:
871 op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink);
872 break;
873 case OP_REMOVE:
874 op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove);
875 break;
876 case OP_RENAME:
877 op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename);
878 break;
879 case OP_RENEW:
880 op->status = nfsd4_renew(&op->u.renew);
881 break;
882 case OP_RESTOREFH:
883 op->status = nfsd4_restorefh(current_fh, save_fh);
884 break;
885 case OP_SAVEFH:
886 op->status = nfsd4_savefh(current_fh, save_fh);
887 break;
888 case OP_SETATTR:
889 op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr);
890 break;
891 case OP_SETCLIENTID:
892 op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
893 break;
894 case OP_SETCLIENTID_CONFIRM:
895 op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
896 break;
897 case OP_VERIFY:
898 op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify);
899 if (op->status == nfserr_same)
900 op->status = nfs_ok;
901 break;
902 case OP_WRITE:
903 op->status = nfsd4_write(rqstp, current_fh, &op->u.write);
904 break;
905 case OP_RELEASE_LOCKOWNER:
906 op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
907 break;
908 default:
909 BUG_ON(op->status == nfs_ok);
910 break;
911 }
912
913encode_op:
914 if (op->status == NFSERR_REPLAY_ME) {
915 op->replay = &replay_owner->so_replay;
916 nfsd4_encode_replay(resp, op);
917 status = op->status = op->replay->rp_status;
918 } else {
919 nfsd4_encode_operation(resp, op);
920 status = op->status;
921 }
922 if (replay_owner && (replay_owner != (void *)(-1))) {
923 nfs4_put_stateowner(replay_owner);
924 replay_owner = NULL;
925 }
926 }
927
928out:
929 nfsd4_release_compoundargs(args);
930 if (current_fh)
931 fh_put(current_fh);
932 kfree(current_fh);
933 if (save_fh)
934 fh_put(save_fh);
935 kfree(save_fh);
936 return status;
937}
938
939#define nfs4svc_decode_voidargs NULL
940#define nfs4svc_release_void NULL
941#define nfsd4_voidres nfsd4_voidargs
942#define nfs4svc_release_compound NULL
943struct nfsd4_voidargs { int dummy; };
944
945#define PROC(name, argt, rest, relt, cache, respsize) \
946 { (svc_procfunc) nfsd4_proc_##name, \
947 (kxdrproc_t) nfs4svc_decode_##argt##args, \
948 (kxdrproc_t) nfs4svc_encode_##rest##res, \
949 (kxdrproc_t) nfs4svc_release_##relt, \
950 sizeof(struct nfsd4_##argt##args), \
951 sizeof(struct nfsd4_##rest##res), \
952 0, \
953 cache, \
954 respsize, \
955 }
956
957/*
958 * TODO: At the present time, the NFSv4 server does not do XID caching
959 * of requests. Implementing XID caching would not be a serious problem,
960 * although it would require a mild change in interfaces since one
961 * doesn't know whether an NFSv4 request is idempotent until after the
962 * XDR decode. However, XID caching totally confuses pynfs (Peter
963 * Astrand's regression testsuite for NFSv4 servers), which reuses
964 * XID's liberally, so I've left it unimplemented until pynfs generates
965 * better XID's.
966 */
967static struct svc_procedure nfsd_procedures4[2] = {
968 PROC(null, void, void, void, RC_NOCACHE, 1),
969 PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE)
970};
971
972struct svc_version nfsd_version4 = {
973 .vs_vers = 4,
974 .vs_nproc = 2,
975 .vs_proc = nfsd_procedures4,
976 .vs_dispatch = nfsd_dispatch,
977 .vs_xdrsize = NFS4_SVC_XDRSIZE,
978};
979
980/*
981 * Local variables:
982 * c-basic-offset: 8
983 * End:
984 */
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
new file mode 100644
index 000000000000..579f7fea7968
--- /dev/null
+++ b/fs/nfsd/nfs4state.c
@@ -0,0 +1,3320 @@
1/*
2* linux/fs/nfsd/nfs4state.c
3*
4* Copyright (c) 2001 The Regents of the University of Michigan.
5* All rights reserved.
6*
7* Kendrick Smith <kmsmith@umich.edu>
8* Andy Adamson <kandros@umich.edu>
9*
10* Redistribution and use in source and binary forms, with or without
11* modification, are permitted provided that the following conditions
12* are met:
13*
14* 1. Redistributions of source code must retain the above copyright
15* notice, this list of conditions and the following disclaimer.
16* 2. Redistributions in binary form must reproduce the above copyright
17* notice, this list of conditions and the following disclaimer in the
18* documentation and/or other materials provided with the distribution.
19* 3. Neither the name of the University nor the names of its
20* contributors may be used to endorse or promote products derived
21* from this software without specific prior written permission.
22*
23* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*
35*/
36
37#include <linux/param.h>
38#include <linux/major.h>
39#include <linux/slab.h>
40
41#include <linux/sunrpc/svc.h>
42#include <linux/nfsd/nfsd.h>
43#include <linux/nfsd/cache.h>
44#include <linux/mount.h>
45#include <linux/workqueue.h>
46#include <linux/smp_lock.h>
47#include <linux/kthread.h>
48#include <linux/nfs4.h>
49#include <linux/nfsd/state.h>
50#include <linux/nfsd/xdr4.h>
51
52#define NFSDDBG_FACILITY NFSDDBG_PROC
53
54/* Globals */
55static time_t lease_time = 90; /* default lease time */
56static time_t old_lease_time = 90; /* past incarnation lease time */
57static u32 nfs4_reclaim_init = 0;
58time_t boot_time;
59static time_t grace_end = 0;
60static u32 current_clientid = 1;
61static u32 current_ownerid = 1;
62static u32 current_fileid = 1;
63static u32 current_delegid = 1;
64static u32 nfs4_init;
65stateid_t zerostateid; /* bits all 0 */
66stateid_t onestateid; /* bits all 1 */
67
68/* debug counters */
69u32 list_add_perfile = 0;
70u32 list_del_perfile = 0;
71u32 add_perclient = 0;
72u32 del_perclient = 0;
73u32 alloc_file = 0;
74u32 free_file = 0;
75u32 vfsopen = 0;
76u32 vfsclose = 0;
77u32 alloc_delegation= 0;
78u32 free_delegation= 0;
79
80/* forward declarations */
81struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
82static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
83static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
84
85/* Locking:
86 *
87 * client_sema:
88 * protects clientid_hashtbl[], clientstr_hashtbl[],
89 * unconfstr_hashtbl[], uncofid_hashtbl[].
90 */
91static DECLARE_MUTEX(client_sema);
92
93void
94nfs4_lock_state(void)
95{
96 down(&client_sema);
97}
98
99void
100nfs4_unlock_state(void)
101{
102 up(&client_sema);
103}
104
105static inline u32
106opaque_hashval(const void *ptr, int nbytes)
107{
108 unsigned char *cptr = (unsigned char *) ptr;
109
110 u32 x = 0;
111 while (nbytes--) {
112 x *= 37;
113 x += *cptr++;
114 }
115 return x;
116}
117
118/* forward declarations */
119static void release_stateowner(struct nfs4_stateowner *sop);
120static void release_stateid(struct nfs4_stateid *stp, int flags);
121static void release_file(struct nfs4_file *fp);
122
123/*
124 * Delegation state
125 */
126
127/* recall_lock protects the del_recall_lru */
128spinlock_t recall_lock;
129static struct list_head del_recall_lru;
130
131static struct nfs4_delegation *
132alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
133{
134 struct nfs4_delegation *dp;
135 struct nfs4_file *fp = stp->st_file;
136 struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
137
138 dprintk("NFSD alloc_init_deleg\n");
139 if ((dp = kmalloc(sizeof(struct nfs4_delegation),
140 GFP_KERNEL)) == NULL)
141 return dp;
142 INIT_LIST_HEAD(&dp->dl_del_perfile);
143 INIT_LIST_HEAD(&dp->dl_del_perclnt);
144 INIT_LIST_HEAD(&dp->dl_recall_lru);
145 dp->dl_client = clp;
146 dp->dl_file = fp;
147 dp->dl_flock = NULL;
148 get_file(stp->st_vfs_file);
149 dp->dl_vfs_file = stp->st_vfs_file;
150 dp->dl_type = type;
151 dp->dl_recall.cbr_dp = NULL;
152 dp->dl_recall.cbr_ident = cb->cb_ident;
153 dp->dl_recall.cbr_trunc = 0;
154 dp->dl_stateid.si_boot = boot_time;
155 dp->dl_stateid.si_stateownerid = current_delegid++;
156 dp->dl_stateid.si_fileid = 0;
157 dp->dl_stateid.si_generation = 0;
158 dp->dl_fhlen = current_fh->fh_handle.fh_size;
159 memcpy(dp->dl_fhval, &current_fh->fh_handle.fh_base,
160 current_fh->fh_handle.fh_size);
161 dp->dl_time = 0;
162 atomic_set(&dp->dl_count, 1);
163 list_add(&dp->dl_del_perfile, &fp->fi_del_perfile);
164 list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
165 alloc_delegation++;
166 return dp;
167}
168
169void
170nfs4_put_delegation(struct nfs4_delegation *dp)
171{
172 if (atomic_dec_and_test(&dp->dl_count)) {
173 dprintk("NFSD: freeing dp %p\n",dp);
174 kfree(dp);
175 free_delegation++;
176 }
177}
178
179/* Remove the associated file_lock first, then remove the delegation.
180 * lease_modify() is called to remove the FS_LEASE file_lock from
181 * the i_flock list, eventually calling nfsd's lock_manager
182 * fl_release_callback.
183 */
184static void
185nfs4_close_delegation(struct nfs4_delegation *dp)
186{
187 struct file *filp = dp->dl_vfs_file;
188
189 dprintk("NFSD: close_delegation dp %p\n",dp);
190 dp->dl_vfs_file = NULL;
191 /* The following nfsd_close may not actually close the file,
192 * but we want to remove the lease in any case. */
193 setlease(filp, F_UNLCK, &dp->dl_flock);
194 nfsd_close(filp);
195 vfsclose++;
196}
197
198/* Called under the state lock. */
199static void
200unhash_delegation(struct nfs4_delegation *dp)
201{
202 list_del_init(&dp->dl_del_perfile);
203 list_del_init(&dp->dl_del_perclnt);
204 spin_lock(&recall_lock);
205 list_del_init(&dp->dl_recall_lru);
206 spin_unlock(&recall_lock);
207 nfs4_close_delegation(dp);
208 nfs4_put_delegation(dp);
209}
210
211/*
212 * SETCLIENTID state
213 */
214
215/* Hash tables for nfs4_clientid state */
216#define CLIENT_HASH_BITS 4
217#define CLIENT_HASH_SIZE (1 << CLIENT_HASH_BITS)
218#define CLIENT_HASH_MASK (CLIENT_HASH_SIZE - 1)
219
220#define clientid_hashval(id) \
221 ((id) & CLIENT_HASH_MASK)
222#define clientstr_hashval(name, namelen) \
223 (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK)
224/*
225 * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
226 * used in reboot/reset lease grace period processing
227 *
228 * conf_id_hashtbl[], and conf_str_hashtbl[] hold confirmed
229 * setclientid_confirmed info.
230 *
231 * unconf_str_hastbl[] and unconf_id_hashtbl[] hold unconfirmed
232 * setclientid info.
233 *
234 * client_lru holds client queue ordered by nfs4_client.cl_time
235 * for lease renewal.
236 *
237 * close_lru holds (open) stateowner queue ordered by nfs4_stateowner.so_time
238 * for last close replay.
239 */
240static struct list_head reclaim_str_hashtbl[CLIENT_HASH_SIZE];
241static int reclaim_str_hashtbl_size = 0;
242static struct list_head conf_id_hashtbl[CLIENT_HASH_SIZE];
243static struct list_head conf_str_hashtbl[CLIENT_HASH_SIZE];
244static struct list_head unconf_str_hashtbl[CLIENT_HASH_SIZE];
245static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE];
246static struct list_head client_lru;
247static struct list_head close_lru;
248
249static inline void
250renew_client(struct nfs4_client *clp)
251{
252 /*
253 * Move client to the end to the LRU list.
254 */
255 dprintk("renewing client (clientid %08x/%08x)\n",
256 clp->cl_clientid.cl_boot,
257 clp->cl_clientid.cl_id);
258 list_move_tail(&clp->cl_lru, &client_lru);
259 clp->cl_time = get_seconds();
260}
261
262/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
263static int
264STALE_CLIENTID(clientid_t *clid)
265{
266 if (clid->cl_boot == boot_time)
267 return 0;
268 dprintk("NFSD stale clientid (%08x/%08x)\n",
269 clid->cl_boot, clid->cl_id);
270 return 1;
271}
272
273/*
274 * XXX Should we use a slab cache ?
275 * This type of memory management is somewhat inefficient, but we use it
276 * anyway since SETCLIENTID is not a common operation.
277 */
278static inline struct nfs4_client *
279alloc_client(struct xdr_netobj name)
280{
281 struct nfs4_client *clp;
282
283 if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
284 memset(clp, 0, sizeof(*clp));
285 if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
286 memcpy(clp->cl_name.data, name.data, name.len);
287 clp->cl_name.len = name.len;
288 }
289 else {
290 kfree(clp);
291 clp = NULL;
292 }
293 }
294 return clp;
295}
296
297static inline void
298free_client(struct nfs4_client *clp)
299{
300 if (clp->cl_cred.cr_group_info)
301 put_group_info(clp->cl_cred.cr_group_info);
302 kfree(clp->cl_name.data);
303 kfree(clp);
304}
305
306void
307put_nfs4_client(struct nfs4_client *clp)
308{
309 if (atomic_dec_and_test(&clp->cl_count))
310 free_client(clp);
311}
312
313static void
314expire_client(struct nfs4_client *clp)
315{
316 struct nfs4_stateowner *sop;
317 struct nfs4_delegation *dp;
318 struct nfs4_callback *cb = &clp->cl_callback;
319 struct rpc_clnt *clnt = clp->cl_callback.cb_client;
320 struct list_head reaplist;
321
322 dprintk("NFSD: expire_client cl_count %d\n",
323 atomic_read(&clp->cl_count));
324
325 /* shutdown rpc client, ending any outstanding recall rpcs */
326 if (atomic_read(&cb->cb_set) == 1 && clnt) {
327 rpc_shutdown_client(clnt);
328 clnt = clp->cl_callback.cb_client = NULL;
329 }
330
331 INIT_LIST_HEAD(&reaplist);
332 spin_lock(&recall_lock);
333 while (!list_empty(&clp->cl_del_perclnt)) {
334 dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt);
335 dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
336 dp->dl_flock);
337 list_del_init(&dp->dl_del_perclnt);
338 list_move(&dp->dl_recall_lru, &reaplist);
339 }
340 spin_unlock(&recall_lock);
341 while (!list_empty(&reaplist)) {
342 dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
343 list_del_init(&dp->dl_recall_lru);
344 unhash_delegation(dp);
345 }
346 list_del(&clp->cl_idhash);
347 list_del(&clp->cl_strhash);
348 list_del(&clp->cl_lru);
349 while (!list_empty(&clp->cl_perclient)) {
350 sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient);
351 release_stateowner(sop);
352 }
353 put_nfs4_client(clp);
354}
355
356static struct nfs4_client *
357create_client(struct xdr_netobj name) {
358 struct nfs4_client *clp;
359
360 if (!(clp = alloc_client(name)))
361 goto out;
362 atomic_set(&clp->cl_count, 1);
363 atomic_set(&clp->cl_callback.cb_set, 0);
364 clp->cl_callback.cb_parsed = 0;
365 INIT_LIST_HEAD(&clp->cl_idhash);
366 INIT_LIST_HEAD(&clp->cl_strhash);
367 INIT_LIST_HEAD(&clp->cl_perclient);
368 INIT_LIST_HEAD(&clp->cl_del_perclnt);
369 INIT_LIST_HEAD(&clp->cl_lru);
370out:
371 return clp;
372}
373
374static void
375copy_verf(struct nfs4_client *target, nfs4_verifier *source) {
376 memcpy(target->cl_verifier.data, source->data, sizeof(target->cl_verifier.data));
377}
378
379static void
380copy_clid(struct nfs4_client *target, struct nfs4_client *source) {
381 target->cl_clientid.cl_boot = source->cl_clientid.cl_boot;
382 target->cl_clientid.cl_id = source->cl_clientid.cl_id;
383}
384
385static void
386copy_cred(struct svc_cred *target, struct svc_cred *source) {
387
388 target->cr_uid = source->cr_uid;
389 target->cr_gid = source->cr_gid;
390 target->cr_group_info = source->cr_group_info;
391 get_group_info(target->cr_group_info);
392}
393
394static int
395cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
396 if (!n1 || !n2)
397 return 0;
398 return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
399}
400
401static int
402cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) {
403 return(!memcmp(v1->data,v2->data,sizeof(v1->data)));
404}
405
406static int
407cmp_clid(clientid_t * cl1, clientid_t * cl2) {
408 return((cl1->cl_boot == cl2->cl_boot) &&
409 (cl1->cl_id == cl2->cl_id));
410}
411
412/* XXX what about NGROUP */
413static int
414cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){
415 return(cr1->cr_uid == cr2->cr_uid);
416
417}
418
419static void
420gen_clid(struct nfs4_client *clp) {
421 clp->cl_clientid.cl_boot = boot_time;
422 clp->cl_clientid.cl_id = current_clientid++;
423}
424
425static void
426gen_confirm(struct nfs4_client *clp) {
427 struct timespec tv;
428 u32 * p;
429
430 tv = CURRENT_TIME;
431 p = (u32 *)clp->cl_confirm.data;
432 *p++ = tv.tv_sec;
433 *p++ = tv.tv_nsec;
434}
435
436static int
437check_name(struct xdr_netobj name) {
438
439 if (name.len == 0)
440 return 0;
441 if (name.len > NFS4_OPAQUE_LIMIT) {
442 printk("NFSD: check_name: name too long(%d)!\n", name.len);
443 return 0;
444 }
445 return 1;
446}
447
448void
449add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
450{
451 unsigned int idhashval;
452
453 list_add(&clp->cl_strhash, &unconf_str_hashtbl[strhashval]);
454 idhashval = clientid_hashval(clp->cl_clientid.cl_id);
455 list_add(&clp->cl_idhash, &unconf_id_hashtbl[idhashval]);
456 list_add_tail(&clp->cl_lru, &client_lru);
457 clp->cl_time = get_seconds();
458}
459
460void
461move_to_confirmed(struct nfs4_client *clp)
462{
463 unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
464 unsigned int strhashval;
465
466 dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
467 list_del_init(&clp->cl_strhash);
468 list_del_init(&clp->cl_idhash);
469 list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
470 strhashval = clientstr_hashval(clp->cl_name.data,
471 clp->cl_name.len);
472 list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
473 renew_client(clp);
474}
475
476static struct nfs4_client *
477find_confirmed_client(clientid_t *clid)
478{
479 struct nfs4_client *clp;
480 unsigned int idhashval = clientid_hashval(clid->cl_id);
481
482 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
483 if (cmp_clid(&clp->cl_clientid, clid))
484 return clp;
485 }
486 return NULL;
487}
488
489static struct nfs4_client *
490find_unconfirmed_client(clientid_t *clid)
491{
492 struct nfs4_client *clp;
493 unsigned int idhashval = clientid_hashval(clid->cl_id);
494
495 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
496 if (cmp_clid(&clp->cl_clientid, clid))
497 return clp;
498 }
499 return NULL;
500}
501
502/* a helper function for parse_callback */
503static int
504parse_octet(unsigned int *lenp, char **addrp)
505{
506 unsigned int len = *lenp;
507 char *p = *addrp;
508 int n = -1;
509 char c;
510
511 for (;;) {
512 if (!len)
513 break;
514 len--;
515 c = *p++;
516 if (c == '.')
517 break;
518 if ((c < '0') || (c > '9')) {
519 n = -1;
520 break;
521 }
522 if (n < 0)
523 n = 0;
524 n = (n * 10) + (c - '0');
525 if (n > 255) {
526 n = -1;
527 break;
528 }
529 }
530 *lenp = len;
531 *addrp = p;
532 return n;
533}
534
535/* parse and set the setclientid ipv4 callback address */
536int
537parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
538{
539 int temp = 0;
540 u32 cbaddr = 0;
541 u16 cbport = 0;
542 u32 addrlen = addr_len;
543 char *addr = addr_val;
544 int i, shift;
545
546 /* ipaddress */
547 shift = 24;
548 for(i = 4; i > 0 ; i--) {
549 if ((temp = parse_octet(&addrlen, &addr)) < 0) {
550 return 0;
551 }
552 cbaddr |= (temp << shift);
553 if (shift > 0)
554 shift -= 8;
555 }
556 *cbaddrp = cbaddr;
557
558 /* port */
559 shift = 8;
560 for(i = 2; i > 0 ; i--) {
561 if ((temp = parse_octet(&addrlen, &addr)) < 0) {
562 return 0;
563 }
564 cbport |= (temp << shift);
565 if (shift > 0)
566 shift -= 8;
567 }
568 *cbportp = cbport;
569 return 1;
570}
571
572void
573gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
574{
575 struct nfs4_callback *cb = &clp->cl_callback;
576
577 /* Currently, we only support tcp for the callback channel */
578 if ((se->se_callback_netid_len != 3) || memcmp((char *)se->se_callback_netid_val, "tcp", 3))
579 goto out_err;
580
581 if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
582 &cb->cb_addr, &cb->cb_port)))
583 goto out_err;
584 cb->cb_prog = se->se_callback_prog;
585 cb->cb_ident = se->se_callback_ident;
586 cb->cb_parsed = 1;
587 return;
588out_err:
589 printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
590 "will not receive delegations\n",
591 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
592
593 cb->cb_parsed = 0;
594 return;
595}
596
597/*
598 * RFC 3010 has a complex implmentation description of processing a
599 * SETCLIENTID request consisting of 5 bullets, labeled as
600 * CASE0 - CASE4 below.
601 *
602 * NOTES:
603 * callback information will be processed in a future patch
604 *
605 * an unconfirmed record is added when:
606 * NORMAL (part of CASE 4): there is no confirmed nor unconfirmed record.
607 * CASE 1: confirmed record found with matching name, principal,
608 * verifier, and clientid.
609 * CASE 2: confirmed record found with matching name, principal,
610 * and there is no unconfirmed record with matching
611 * name and principal
612 *
613 * an unconfirmed record is replaced when:
614 * CASE 3: confirmed record found with matching name, principal,
615 * and an unconfirmed record is found with matching
616 * name, principal, and with clientid and
617 * confirm that does not match the confirmed record.
618 * CASE 4: there is no confirmed record with matching name and
619 * principal. there is an unconfirmed record with
620 * matching name, principal.
621 *
622 * an unconfirmed record is deleted when:
623 * CASE 1: an unconfirmed record that matches input name, verifier,
624 * and confirmed clientid.
625 * CASE 4: any unconfirmed records with matching name and principal
626 * that exist after an unconfirmed record has been replaced
627 * as described above.
628 *
629 */
630int
631nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
632{
633 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
634 struct xdr_netobj clname = {
635 .len = setclid->se_namelen,
636 .data = setclid->se_name,
637 };
638 nfs4_verifier clverifier = setclid->se_verf;
639 unsigned int strhashval;
640 struct nfs4_client * conf, * unconf, * new, * clp;
641 int status;
642
643 status = nfserr_inval;
644 if (!check_name(clname))
645 goto out;
646
647 /*
648 * XXX The Duplicate Request Cache (DRC) has been checked (??)
649 * We get here on a DRC miss.
650 */
651
652 strhashval = clientstr_hashval(clname.data, clname.len);
653
654 conf = NULL;
655 nfs4_lock_state();
656 list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
657 if (!cmp_name(&clp->cl_name, &clname))
658 continue;
659 /*
660 * CASE 0:
661 * clname match, confirmed, different principal
662 * or different ip_address
663 */
664 status = nfserr_clid_inuse;
665 if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) {
666 printk("NFSD: setclientid: string in use by client"
667 "(clientid %08x/%08x)\n",
668 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
669 goto out;
670 }
671 if (clp->cl_addr != ip_addr) {
672 printk("NFSD: setclientid: string in use by client"
673 "(clientid %08x/%08x)\n",
674 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
675 goto out;
676 }
677
678 /*
679 * cl_name match from a previous SETCLIENTID operation
680 * XXX check for additional matches?
681 */
682 conf = clp;
683 break;
684 }
685 unconf = NULL;
686 list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
687 if (!cmp_name(&clp->cl_name, &clname))
688 continue;
689 /* cl_name match from a previous SETCLIENTID operation */
690 unconf = clp;
691 break;
692 }
693 status = nfserr_resource;
694 if (!conf) {
695 /*
696 * CASE 4:
697 * placed first, because it is the normal case.
698 */
699 if (unconf)
700 expire_client(unconf);
701 if (!(new = create_client(clname)))
702 goto out;
703 copy_verf(new, &clverifier);
704 new->cl_addr = ip_addr;
705 copy_cred(&new->cl_cred,&rqstp->rq_cred);
706 gen_clid(new);
707 gen_confirm(new);
708 gen_callback(new, setclid);
709 add_to_unconfirmed(new, strhashval);
710 } else if (cmp_verf(&conf->cl_verifier, &clverifier)) {
711 /*
712 * CASE 1:
713 * cl_name match, confirmed, principal match
714 * verifier match: probable callback update
715 *
716 * remove any unconfirmed nfs4_client with
717 * matching cl_name, cl_verifier, and cl_clientid
718 *
719 * create and insert an unconfirmed nfs4_client with same
720 * cl_name, cl_verifier, and cl_clientid as existing
721 * nfs4_client, but with the new callback info and a
722 * new cl_confirm
723 */
724 if ((unconf) &&
725 cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) &&
726 cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) {
727 expire_client(unconf);
728 }
729 if (!(new = create_client(clname)))
730 goto out;
731 copy_verf(new,&conf->cl_verifier);
732 new->cl_addr = ip_addr;
733 copy_cred(&new->cl_cred,&rqstp->rq_cred);
734 copy_clid(new, conf);
735 gen_confirm(new);
736 gen_callback(new, setclid);
737 add_to_unconfirmed(new,strhashval);
738 } else if (!unconf) {
739 /*
740 * CASE 2:
741 * clname match, confirmed, principal match
742 * verfier does not match
743 * no unconfirmed. create a new unconfirmed nfs4_client
744 * using input clverifier, clname, and callback info
745 * and generate a new cl_clientid and cl_confirm.
746 */
747 if (!(new = create_client(clname)))
748 goto out;
749 copy_verf(new,&clverifier);
750 new->cl_addr = ip_addr;
751 copy_cred(&new->cl_cred,&rqstp->rq_cred);
752 gen_clid(new);
753 gen_confirm(new);
754 gen_callback(new, setclid);
755 add_to_unconfirmed(new, strhashval);
756 } else if (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm)) {
757 /*
758 * CASE3:
759 * confirmed found (name, principal match)
760 * confirmed verifier does not match input clverifier
761 *
762 * unconfirmed found (name match)
763 * confirmed->cl_confirm != unconfirmed->cl_confirm
764 *
765 * remove unconfirmed.
766 *
767 * create an unconfirmed nfs4_client
768 * with same cl_name as existing confirmed nfs4_client,
769 * but with new callback info, new cl_clientid,
770 * new cl_verifier and a new cl_confirm
771 */
772 expire_client(unconf);
773 if (!(new = create_client(clname)))
774 goto out;
775 copy_verf(new,&clverifier);
776 new->cl_addr = ip_addr;
777 copy_cred(&new->cl_cred,&rqstp->rq_cred);
778 gen_clid(new);
779 gen_confirm(new);
780 gen_callback(new, setclid);
781 add_to_unconfirmed(new, strhashval);
782 } else {
783 /* No cases hit !!! */
784 status = nfserr_inval;
785 goto out;
786
787 }
788 setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
789 setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
790 memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data));
791 status = nfs_ok;
792out:
793 nfs4_unlock_state();
794 return status;
795}
796
797
798/*
799 * RFC 3010 has a complex implmentation description of processing a
800 * SETCLIENTID_CONFIRM request consisting of 4 bullets describing
801 * processing on a DRC miss, labeled as CASE1 - CASE4 below.
802 *
803 * NOTE: callback information will be processed here in a future patch
804 */
805int
806nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
807{
808 u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
809 struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
810 nfs4_verifier confirm = setclientid_confirm->sc_confirm;
811 clientid_t * clid = &setclientid_confirm->sc_clientid;
812 int status;
813
814 if (STALE_CLIENTID(clid))
815 return nfserr_stale_clientid;
816 /*
817 * XXX The Duplicate Request Cache (DRC) has been checked (??)
818 * We get here on a DRC miss.
819 */
820
821 nfs4_lock_state();
822 clp = find_confirmed_client(clid);
823 if (clp) {
824 status = nfserr_inval;
825 /*
826 * Found a record for this clientid. If the IP addresses
827 * don't match, return ERR_INVAL just as if the record had
828 * not been found.
829 */
830 if (clp->cl_addr != ip_addr) {
831 printk("NFSD: setclientid: string in use by client"
832 "(clientid %08x/%08x)\n",
833 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
834 goto out;
835 }
836 conf = clp;
837 }
838 clp = find_unconfirmed_client(clid);
839 if (clp) {
840 status = nfserr_inval;
841 if (clp->cl_addr != ip_addr) {
842 printk("NFSD: setclientid: string in use by client"
843 "(clientid %08x/%08x)\n",
844 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
845 goto out;
846 }
847 unconf = clp;
848 }
849 /* CASE 1:
850 * unconf record that matches input clientid and input confirm.
851 * conf record that matches input clientid.
852 * conf and unconf records match names, verifiers
853 */
854 if ((conf && unconf) &&
855 (cmp_verf(&unconf->cl_confirm, &confirm)) &&
856 (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
857 (cmp_name(&conf->cl_name,&unconf->cl_name)) &&
858 (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
859 if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred))
860 status = nfserr_clid_inuse;
861 else {
862 expire_client(conf);
863 clp = unconf;
864 move_to_confirmed(unconf);
865 status = nfs_ok;
866 }
867 goto out;
868 }
869 /* CASE 2:
870 * conf record that matches input clientid.
871 * if unconf record that matches input clientid, then unconf->cl_name
872 * or unconf->cl_verifier don't match the conf record.
873 */
874 if ((conf && !unconf) ||
875 ((conf && unconf) &&
876 (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
877 !cmp_name(&conf->cl_name, &unconf->cl_name)))) {
878 if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
879 status = nfserr_clid_inuse;
880 } else {
881 clp = conf;
882 status = nfs_ok;
883 }
884 goto out;
885 }
886 /* CASE 3:
887 * conf record not found.
888 * unconf record found.
889 * unconf->cl_confirm matches input confirm
890 */
891 if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
892 if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
893 status = nfserr_clid_inuse;
894 } else {
895 status = nfs_ok;
896 clp = unconf;
897 move_to_confirmed(unconf);
898 }
899 goto out;
900 }
901 /* CASE 4:
902 * conf record not found, or if conf, then conf->cl_confirm does not
903 * match input confirm.
904 * unconf record not found, or if unconf, then unconf->cl_confirm
905 * does not match input confirm.
906 */
907 if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
908 (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
909 status = nfserr_stale_clientid;
910 goto out;
911 }
912 /* check that we have hit one of the cases...*/
913 status = nfserr_inval;
914 goto out;
915out:
916 if (!status)
917 nfsd4_probe_callback(clp);
918 nfs4_unlock_state();
919 return status;
920}
921
922/*
923 * Open owner state (share locks)
924 */
925
926/* hash tables for nfs4_stateowner */
927#define OWNER_HASH_BITS 8
928#define OWNER_HASH_SIZE (1 << OWNER_HASH_BITS)
929#define OWNER_HASH_MASK (OWNER_HASH_SIZE - 1)
930
931#define ownerid_hashval(id) \
932 ((id) & OWNER_HASH_MASK)
933#define ownerstr_hashval(clientid, ownername) \
934 (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
935
936static struct list_head ownerid_hashtbl[OWNER_HASH_SIZE];
937static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
938
939/* hash table for nfs4_file */
940#define FILE_HASH_BITS 8
941#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
942#define FILE_HASH_MASK (FILE_HASH_SIZE - 1)
943/* hash table for (open)nfs4_stateid */
944#define STATEID_HASH_BITS 10
945#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
946#define STATEID_HASH_MASK (STATEID_HASH_SIZE - 1)
947
948#define file_hashval(x) \
949 hash_ptr(x, FILE_HASH_BITS)
950#define stateid_hashval(owner_id, file_id) \
951 (((owner_id) + (file_id)) & STATEID_HASH_MASK)
952
953static struct list_head file_hashtbl[FILE_HASH_SIZE];
954static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
955
956/* OPEN Share state helper functions */
957static inline struct nfs4_file *
958alloc_init_file(struct inode *ino)
959{
960 struct nfs4_file *fp;
961 unsigned int hashval = file_hashval(ino);
962
963 if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
964 INIT_LIST_HEAD(&fp->fi_hash);
965 INIT_LIST_HEAD(&fp->fi_perfile);
966 INIT_LIST_HEAD(&fp->fi_del_perfile);
967 list_add(&fp->fi_hash, &file_hashtbl[hashval]);
968 fp->fi_inode = igrab(ino);
969 fp->fi_id = current_fileid++;
970 alloc_file++;
971 return fp;
972 }
973 return NULL;
974}
975
976static void
977release_all_files(void)
978{
979 int i;
980 struct nfs4_file *fp;
981
982 for (i=0;i<FILE_HASH_SIZE;i++) {
983 while (!list_empty(&file_hashtbl[i])) {
984 fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
985 /* this should never be more than once... */
986 if (!list_empty(&fp->fi_perfile) || !list_empty(&fp->fi_del_perfile)) {
987 printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
988 }
989 release_file(fp);
990 }
991 }
992}
993
994kmem_cache_t *stateowner_slab = NULL;
995
996static int
997nfsd4_init_slabs(void)
998{
999 stateowner_slab = kmem_cache_create("nfsd4_stateowners",
1000 sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
1001 if (stateowner_slab == NULL) {
1002 dprintk("nfsd4: out of memory while initializing nfsv4\n");
1003 return -ENOMEM;
1004 }
1005 return 0;
1006}
1007
1008static void
1009nfsd4_free_slabs(void)
1010{
1011 int status = 0;
1012
1013 if (stateowner_slab)
1014 status = kmem_cache_destroy(stateowner_slab);
1015 stateowner_slab = NULL;
1016 BUG_ON(status);
1017}
1018
1019void
1020nfs4_free_stateowner(struct kref *kref)
1021{
1022 struct nfs4_stateowner *sop =
1023 container_of(kref, struct nfs4_stateowner, so_ref);
1024 kfree(sop->so_owner.data);
1025 kmem_cache_free(stateowner_slab, sop);
1026}
1027
1028static inline struct nfs4_stateowner *
1029alloc_stateowner(struct xdr_netobj *owner)
1030{
1031 struct nfs4_stateowner *sop;
1032
1033 if ((sop = kmem_cache_alloc(stateowner_slab, GFP_KERNEL))) {
1034 if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
1035 memcpy(sop->so_owner.data, owner->data, owner->len);
1036 sop->so_owner.len = owner->len;
1037 kref_init(&sop->so_ref);
1038 return sop;
1039 }
1040 kmem_cache_free(stateowner_slab, sop);
1041 }
1042 return NULL;
1043}
1044
1045static struct nfs4_stateowner *
1046alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) {
1047 struct nfs4_stateowner *sop;
1048 struct nfs4_replay *rp;
1049 unsigned int idhashval;
1050
1051 if (!(sop = alloc_stateowner(&open->op_owner)))
1052 return NULL;
1053 idhashval = ownerid_hashval(current_ownerid);
1054 INIT_LIST_HEAD(&sop->so_idhash);
1055 INIT_LIST_HEAD(&sop->so_strhash);
1056 INIT_LIST_HEAD(&sop->so_perclient);
1057 INIT_LIST_HEAD(&sop->so_perfilestate);
1058 INIT_LIST_HEAD(&sop->so_perlockowner); /* not used */
1059 INIT_LIST_HEAD(&sop->so_close_lru);
1060 sop->so_time = 0;
1061 list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
1062 list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
1063 list_add(&sop->so_perclient, &clp->cl_perclient);
1064 add_perclient++;
1065 sop->so_is_open_owner = 1;
1066 sop->so_id = current_ownerid++;
1067 sop->so_client = clp;
1068 sop->so_seqid = open->op_seqid;
1069 sop->so_confirmed = 0;
1070 rp = &sop->so_replay;
1071 rp->rp_status = NFSERR_SERVERFAULT;
1072 rp->rp_buflen = 0;
1073 rp->rp_buf = rp->rp_ibuf;
1074 return sop;
1075}
1076
1077static void
1078release_stateid_lockowners(struct nfs4_stateid *open_stp)
1079{
1080 struct nfs4_stateowner *lock_sop;
1081
1082 while (!list_empty(&open_stp->st_perlockowner)) {
1083 lock_sop = list_entry(open_stp->st_perlockowner.next,
1084 struct nfs4_stateowner, so_perlockowner);
1085 /* list_del(&open_stp->st_perlockowner); */
1086 BUG_ON(lock_sop->so_is_open_owner);
1087 release_stateowner(lock_sop);
1088 }
1089}
1090
1091static void
1092unhash_stateowner(struct nfs4_stateowner *sop)
1093{
1094 struct nfs4_stateid *stp;
1095
1096 list_del(&sop->so_idhash);
1097 list_del(&sop->so_strhash);
1098 if (sop->so_is_open_owner) {
1099 list_del(&sop->so_perclient);
1100 del_perclient++;
1101 }
1102 list_del(&sop->so_perlockowner);
1103 while (!list_empty(&sop->so_perfilestate)) {
1104 stp = list_entry(sop->so_perfilestate.next,
1105 struct nfs4_stateid, st_perfilestate);
1106 if (sop->so_is_open_owner)
1107 release_stateid(stp, OPEN_STATE);
1108 else
1109 release_stateid(stp, LOCK_STATE);
1110 }
1111}
1112
1113static void
1114release_stateowner(struct nfs4_stateowner *sop)
1115{
1116 unhash_stateowner(sop);
1117 list_del(&sop->so_close_lru);
1118 nfs4_put_stateowner(sop);
1119}
1120
1121static inline void
1122init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
1123 struct nfs4_stateowner *sop = open->op_stateowner;
1124 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
1125
1126 INIT_LIST_HEAD(&stp->st_hash);
1127 INIT_LIST_HEAD(&stp->st_perfilestate);
1128 INIT_LIST_HEAD(&stp->st_perlockowner);
1129 INIT_LIST_HEAD(&stp->st_perfile);
1130 list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
1131 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
1132 list_add_perfile++;
1133 list_add(&stp->st_perfile, &fp->fi_perfile);
1134 stp->st_stateowner = sop;
1135 stp->st_file = fp;
1136 stp->st_stateid.si_boot = boot_time;
1137 stp->st_stateid.si_stateownerid = sop->so_id;
1138 stp->st_stateid.si_fileid = fp->fi_id;
1139 stp->st_stateid.si_generation = 0;
1140 stp->st_access_bmap = 0;
1141 stp->st_deny_bmap = 0;
1142 __set_bit(open->op_share_access, &stp->st_access_bmap);
1143 __set_bit(open->op_share_deny, &stp->st_deny_bmap);
1144}
1145
1146static void
1147release_stateid(struct nfs4_stateid *stp, int flags)
1148{
1149 struct file *filp = stp->st_vfs_file;
1150
1151 list_del(&stp->st_hash);
1152 list_del_perfile++;
1153 list_del(&stp->st_perfile);
1154 list_del(&stp->st_perfilestate);
1155 if (flags & OPEN_STATE) {
1156 release_stateid_lockowners(stp);
1157 stp->st_vfs_file = NULL;
1158 nfsd_close(filp);
1159 vfsclose++;
1160 } else if (flags & LOCK_STATE)
1161 locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
1162 kfree(stp);
1163 stp = NULL;
1164}
1165
1166static void
1167release_file(struct nfs4_file *fp)
1168{
1169 free_file++;
1170 list_del(&fp->fi_hash);
1171 iput(fp->fi_inode);
1172 kfree(fp);
1173}
1174
1175void
1176move_to_close_lru(struct nfs4_stateowner *sop)
1177{
1178 dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
1179
1180 unhash_stateowner(sop);
1181 list_add_tail(&sop->so_close_lru, &close_lru);
1182 sop->so_time = get_seconds();
1183}
1184
1185void
1186release_state_owner(struct nfs4_stateid *stp, int flag)
1187{
1188 struct nfs4_stateowner *sop = stp->st_stateowner;
1189 struct nfs4_file *fp = stp->st_file;
1190
1191 dprintk("NFSD: release_state_owner\n");
1192 release_stateid(stp, flag);
1193
1194 /* place unused nfs4_stateowners on so_close_lru list to be
1195 * released by the laundromat service after the lease period
1196 * to enable us to handle CLOSE replay
1197 */
1198 if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
1199 move_to_close_lru(sop);
1200 /* unused nfs4_file's are releseed. XXX slab cache? */
1201 if (list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) {
1202 release_file(fp);
1203 }
1204}
1205
1206static int
1207cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
1208 return ((sop->so_owner.len == owner->len) &&
1209 !memcmp(sop->so_owner.data, owner->data, owner->len) &&
1210 (sop->so_client->cl_clientid.cl_id == clid->cl_id));
1211}
1212
1213static struct nfs4_stateowner *
1214find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open)
1215{
1216 struct nfs4_stateowner *so = NULL;
1217
1218 list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
1219 if (cmp_owner_str(so, &open->op_owner, &open->op_clientid))
1220 return so;
1221 }
1222 return NULL;
1223}
1224
1225/* search file_hashtbl[] for file */
1226static struct nfs4_file *
1227find_file(struct inode *ino)
1228{
1229 unsigned int hashval = file_hashval(ino);
1230 struct nfs4_file *fp;
1231
1232 list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
1233 if (fp->fi_inode == ino)
1234 return fp;
1235 }
1236 return NULL;
1237}
1238
1239#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
1240#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
1241
1242void
1243set_access(unsigned int *access, unsigned long bmap) {
1244 int i;
1245
1246 *access = 0;
1247 for (i = 1; i < 4; i++) {
1248 if (test_bit(i, &bmap))
1249 *access |= i;
1250 }
1251}
1252
1253void
1254set_deny(unsigned int *deny, unsigned long bmap) {
1255 int i;
1256
1257 *deny = 0;
1258 for (i = 0; i < 4; i++) {
1259 if (test_bit(i, &bmap))
1260 *deny |= i ;
1261 }
1262}
1263
1264static int
1265test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
1266 unsigned int access, deny;
1267
1268 set_access(&access, stp->st_access_bmap);
1269 set_deny(&deny, stp->st_deny_bmap);
1270 if ((access & open->op_share_deny) || (deny & open->op_share_access))
1271 return 0;
1272 return 1;
1273}
1274
1275/*
1276 * Called to check deny when READ with all zero stateid or
1277 * WRITE with all zero or all one stateid
1278 */
1279int
1280nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
1281{
1282 struct inode *ino = current_fh->fh_dentry->d_inode;
1283 struct nfs4_file *fp;
1284 struct nfs4_stateid *stp;
1285
1286 dprintk("NFSD: nfs4_share_conflict\n");
1287
1288 fp = find_file(ino);
1289 if (fp) {
1290 /* Search for conflicting share reservations */
1291 list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
1292 if (test_bit(deny_type, &stp->st_deny_bmap) ||
1293 test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
1294 return nfserr_share_denied;
1295 }
1296 }
1297 return nfs_ok;
1298}
1299
1300static inline void
1301nfs4_file_downgrade(struct file *filp, unsigned int share_access)
1302{
1303 if (share_access & NFS4_SHARE_ACCESS_WRITE) {
1304 put_write_access(filp->f_dentry->d_inode);
1305 filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
1306 }
1307}
1308
1309/*
1310 * Recall a delegation
1311 */
1312static int
1313do_recall(void *__dp)
1314{
1315 struct nfs4_delegation *dp = __dp;
1316
1317 daemonize("nfsv4-recall");
1318
1319 nfsd4_cb_recall(dp);
1320 return 0;
1321}
1322
1323/*
1324 * Spawn a thread to perform a recall on the delegation represented
1325 * by the lease (file_lock)
1326 *
1327 * Called from break_lease() with lock_kernel() held.
1328 * Note: we assume break_lease will only call this *once* for any given
1329 * lease.
1330 */
1331static
1332void nfsd_break_deleg_cb(struct file_lock *fl)
1333{
1334 struct nfs4_delegation *dp= (struct nfs4_delegation *)fl->fl_owner;
1335 struct task_struct *t;
1336
1337 dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
1338 if (!dp)
1339 return;
1340
1341 /* We're assuming the state code never drops its reference
1342 * without first removing the lease. Since we're in this lease
1343 * callback (and since the lease code is serialized by the kernel
1344 * lock) we know the server hasn't removed the lease yet, we know
1345 * it's safe to take a reference: */
1346 atomic_inc(&dp->dl_count);
1347
1348 spin_lock(&recall_lock);
1349 list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
1350 spin_unlock(&recall_lock);
1351
1352 /* only place dl_time is set. protected by lock_kernel*/
1353 dp->dl_time = get_seconds();
1354
1355 /* XXX need to merge NFSD_LEASE_TIME with fs/locks.c:lease_break_time */
1356 fl->fl_break_time = jiffies + NFSD_LEASE_TIME * HZ;
1357
1358 t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall");
1359 if (IS_ERR(t)) {
1360 struct nfs4_client *clp = dp->dl_client;
1361
1362 printk(KERN_INFO "NFSD: Callback thread failed for "
1363 "for client (clientid %08x/%08x)\n",
1364 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
1365 nfs4_put_delegation(dp);
1366 }
1367}
1368
1369/*
1370 * The file_lock is being reapd.
1371 *
1372 * Called by locks_free_lock() with lock_kernel() held.
1373 */
1374static
1375void nfsd_release_deleg_cb(struct file_lock *fl)
1376{
1377 struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
1378
1379 dprintk("NFSD nfsd_release_deleg_cb: fl %p dp %p dl_count %d\n", fl,dp, atomic_read(&dp->dl_count));
1380
1381 if (!(fl->fl_flags & FL_LEASE) || !dp)
1382 return;
1383 dp->dl_flock = NULL;
1384}
1385
1386/*
1387 * Set the delegation file_lock back pointer.
1388 *
1389 * Called from __setlease() with lock_kernel() held.
1390 */
1391static
1392void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl)
1393{
1394 struct nfs4_delegation *dp = (struct nfs4_delegation *)new->fl_owner;
1395
1396 dprintk("NFSD: nfsd_copy_lock_deleg_cb: new fl %p dp %p\n", new, dp);
1397 if (!dp)
1398 return;
1399 dp->dl_flock = new;
1400}
1401
1402/*
1403 * Called from __setlease() with lock_kernel() held
1404 */
1405static
1406int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try)
1407{
1408 struct nfs4_delegation *onlistd =
1409 (struct nfs4_delegation *)onlist->fl_owner;
1410 struct nfs4_delegation *tryd =
1411 (struct nfs4_delegation *)try->fl_owner;
1412
1413 if (onlist->fl_lmops != try->fl_lmops)
1414 return 0;
1415
1416 return onlistd->dl_client == tryd->dl_client;
1417}
1418
1419
1420static
1421int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
1422{
1423 if (arg & F_UNLCK)
1424 return lease_modify(onlist, arg);
1425 else
1426 return -EAGAIN;
1427}
1428
1429struct lock_manager_operations nfsd_lease_mng_ops = {
1430 .fl_break = nfsd_break_deleg_cb,
1431 .fl_release_private = nfsd_release_deleg_cb,
1432 .fl_copy_lock = nfsd_copy_lock_deleg_cb,
1433 .fl_mylease = nfsd_same_client_deleg_cb,
1434 .fl_change = nfsd_change_deleg_cb,
1435};
1436
1437
1438/*
1439 * nfsd4_process_open1()
1440 * lookup stateowner.
1441 * found:
1442 * check confirmed
1443 * confirmed:
1444 * check seqid
1445 * not confirmed:
1446 * delete owner
1447 * create new owner
1448 * notfound:
1449 * verify clientid
1450 * create new owner
1451 *
1452 * called with nfs4_lock_state() held.
1453 */
1454int
1455nfsd4_process_open1(struct nfsd4_open *open)
1456{
1457 int status;
1458 clientid_t *clientid = &open->op_clientid;
1459 struct nfs4_client *clp = NULL;
1460 unsigned int strhashval;
1461 struct nfs4_stateowner *sop = NULL;
1462
1463 status = nfserr_inval;
1464 if (!check_name(open->op_owner))
1465 goto out;
1466
1467 if (STALE_CLIENTID(&open->op_clientid))
1468 return nfserr_stale_clientid;
1469
1470 strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
1471 sop = find_openstateowner_str(strhashval, open);
1472 if (sop) {
1473 open->op_stateowner = sop;
1474 /* check for replay */
1475 if (open->op_seqid == sop->so_seqid){
1476 if (sop->so_replay.rp_buflen)
1477 return NFSERR_REPLAY_ME;
1478 else {
1479 /* The original OPEN failed so spectacularly
1480 * that we don't even have replay data saved!
1481 * Therefore, we have no choice but to continue
1482 * processing this OPEN; presumably, we'll
1483 * fail again for the same reason.
1484 */
1485 dprintk("nfsd4_process_open1:"
1486 " replay with no replay cache\n");
1487 goto renew;
1488 }
1489 } else if (sop->so_confirmed) {
1490 if (open->op_seqid == sop->so_seqid + 1)
1491 goto renew;
1492 status = nfserr_bad_seqid;
1493 goto out;
1494 } else {
1495 /* If we get here, we received an OPEN for an
1496 * unconfirmed nfs4_stateowner. Since the seqid's are
1497 * different, purge the existing nfs4_stateowner, and
1498 * instantiate a new one.
1499 */
1500 clp = sop->so_client;
1501 release_stateowner(sop);
1502 }
1503 } else {
1504 /* nfs4_stateowner not found.
1505 * Verify clientid and instantiate new nfs4_stateowner.
1506 * If verify fails this is presumably the result of the
1507 * client's lease expiring.
1508 */
1509 status = nfserr_expired;
1510 clp = find_confirmed_client(clientid);
1511 if (clp == NULL)
1512 goto out;
1513 }
1514 status = nfserr_resource;
1515 sop = alloc_init_open_stateowner(strhashval, clp, open);
1516 if (sop == NULL)
1517 goto out;
1518 open->op_stateowner = sop;
1519renew:
1520 status = nfs_ok;
1521 renew_client(sop->so_client);
1522out:
1523 if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
1524 status = nfserr_reclaim_bad;
1525 return status;
1526}
1527
1528static int
1529nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
1530{
1531 struct nfs4_stateid *local;
1532 int status = nfserr_share_denied;
1533 struct nfs4_stateowner *sop = open->op_stateowner;
1534
1535 list_for_each_entry(local, &fp->fi_perfile, st_perfile) {
1536 /* ignore lock owners */
1537 if (local->st_stateowner->so_is_open_owner == 0)
1538 continue;
1539 /* remember if we have seen this open owner */
1540 if (local->st_stateowner == sop)
1541 *stpp = local;
1542 /* check for conflicting share reservations */
1543 if (!test_share(local, open))
1544 goto out;
1545 }
1546 status = 0;
1547out:
1548 return status;
1549}
1550
1551static int
1552nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
1553 struct svc_fh *cur_fh, int flags)
1554{
1555 struct nfs4_stateid *stp;
1556 int status;
1557
1558 stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL);
1559 if (stp == NULL)
1560 return nfserr_resource;
1561
1562 status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file);
1563 if (status) {
1564 if (status == nfserr_dropit)
1565 status = nfserr_jukebox;
1566 kfree(stp);
1567 return status;
1568 }
1569 vfsopen++;
1570 *stpp = stp;
1571 return 0;
1572}
1573
1574static inline int
1575nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
1576 struct nfsd4_open *open)
1577{
1578 struct iattr iattr = {
1579 .ia_valid = ATTR_SIZE,
1580 .ia_size = 0,
1581 };
1582 if (!open->op_truncate)
1583 return 0;
1584 if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
1585 return -EINVAL;
1586 return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
1587}
1588
1589static int
1590nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
1591{
1592 struct file *filp = stp->st_vfs_file;
1593 struct inode *inode = filp->f_dentry->d_inode;
1594 unsigned int share_access;
1595 int status;
1596
1597 set_access(&share_access, stp->st_access_bmap);
1598 share_access = ~share_access;
1599 share_access &= open->op_share_access;
1600
1601 if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
1602 return nfsd4_truncate(rqstp, cur_fh, open);
1603
1604 status = get_write_access(inode);
1605 if (status)
1606 return nfserrno(status);
1607 status = nfsd4_truncate(rqstp, cur_fh, open);
1608 if (status) {
1609 put_write_access(inode);
1610 return status;
1611 }
1612 /* remember the open */
1613 filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
1614 set_bit(open->op_share_access, &stp->st_access_bmap);
1615 set_bit(open->op_share_deny, &stp->st_deny_bmap);
1616
1617 return nfs_ok;
1618}
1619
1620
1621/* decrement seqid on successful reclaim, it will be bumped in encode_open */
1622static void
1623nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
1624{
1625 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
1626 if (*status)
1627 *status = nfserr_reclaim_bad;
1628 else {
1629 open->op_stateowner->so_confirmed = 1;
1630 open->op_stateowner->so_seqid--;
1631 }
1632 }
1633}
1634
1635/*
1636 * Attempt to hand out a delegation.
1637 */
1638static void
1639nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_stateid *stp)
1640{
1641 struct nfs4_delegation *dp;
1642 struct nfs4_stateowner *sop = stp->st_stateowner;
1643 struct nfs4_callback *cb = &sop->so_client->cl_callback;
1644 struct file_lock fl, *flp = &fl;
1645 int status, flag = 0;
1646
1647 flag = NFS4_OPEN_DELEGATE_NONE;
1648 if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL
1649 || !atomic_read(&cb->cb_set) || !sop->so_confirmed)
1650 goto out;
1651
1652 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1653 flag = NFS4_OPEN_DELEGATE_WRITE;
1654 else
1655 flag = NFS4_OPEN_DELEGATE_READ;
1656
1657 dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
1658 if (dp == NULL) {
1659 flag = NFS4_OPEN_DELEGATE_NONE;
1660 goto out;
1661 }
1662 locks_init_lock(&fl);
1663 fl.fl_lmops = &nfsd_lease_mng_ops;
1664 fl.fl_flags = FL_LEASE;
1665 fl.fl_end = OFFSET_MAX;
1666 fl.fl_owner = (fl_owner_t)dp;
1667 fl.fl_file = stp->st_vfs_file;
1668 fl.fl_pid = current->tgid;
1669
1670 /* setlease checks to see if delegation should be handed out.
1671 * the lock_manager callbacks fl_mylease and fl_change are used
1672 */
1673 if ((status = setlease(stp->st_vfs_file,
1674 flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
1675 dprintk("NFSD: setlease failed [%d], no delegation\n", status);
1676 list_del(&dp->dl_del_perfile);
1677 list_del(&dp->dl_del_perclnt);
1678 nfs4_put_delegation(dp);
1679 free_delegation++;
1680 flag = NFS4_OPEN_DELEGATE_NONE;
1681 goto out;
1682 }
1683
1684 memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid));
1685
1686 dprintk("NFSD: delegation stateid=(%08x/%08x/%08x/%08x)\n\n",
1687 dp->dl_stateid.si_boot,
1688 dp->dl_stateid.si_stateownerid,
1689 dp->dl_stateid.si_fileid,
1690 dp->dl_stateid.si_generation);
1691out:
1692 open->op_delegate_type = flag;
1693}
1694
1695/*
1696 * called with nfs4_lock_state() held.
1697 */
1698int
1699nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
1700{
1701 struct nfs4_file *fp = NULL;
1702 struct inode *ino = current_fh->fh_dentry->d_inode;
1703 struct nfs4_stateid *stp = NULL;
1704 int status;
1705
1706 status = nfserr_inval;
1707 if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
1708 goto out;
1709 /*
1710 * Lookup file; if found, lookup stateid and check open request,
1711 * and check for delegations in the process of being recalled.
1712 * If not found, create the nfs4_file struct
1713 */
1714 fp = find_file(ino);
1715 if (fp) {
1716 if ((status = nfs4_check_open(fp, open, &stp)))
1717 goto out;
1718 } else {
1719 status = nfserr_resource;
1720 fp = alloc_init_file(ino);
1721 if (fp == NULL)
1722 goto out;
1723 }
1724
1725 /*
1726 * OPEN the file, or upgrade an existing OPEN.
1727 * If truncate fails, the OPEN fails.
1728 */
1729 if (stp) {
1730 /* Stateid was found, this is an OPEN upgrade */
1731 status = nfs4_upgrade_open(rqstp, current_fh, stp, open);
1732 if (status)
1733 goto out;
1734 } else {
1735 /* Stateid was not found, this is a new OPEN */
1736 int flags = 0;
1737 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
1738 flags = MAY_WRITE;
1739 else
1740 flags = MAY_READ;
1741 if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags)))
1742 goto out;
1743 init_stateid(stp, fp, open);
1744 status = nfsd4_truncate(rqstp, current_fh, open);
1745 if (status) {
1746 release_stateid(stp, OPEN_STATE);
1747 goto out;
1748 }
1749 }
1750 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
1751
1752 /*
1753 * Attempt to hand out a delegation. No error return, because the
1754 * OPEN succeeds even if we fail.
1755 */
1756 nfs4_open_delegation(current_fh, open, stp);
1757
1758 status = nfs_ok;
1759
1760 dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n",
1761 stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
1762 stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
1763out:
1764 /* take the opportunity to clean up unused state */
1765 if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile))
1766 release_file(fp);
1767
1768 /* CLAIM_PREVIOUS has different error returns */
1769 nfs4_set_claim_prev(open, &status);
1770 /*
1771 * To finish the open response, we just need to set the rflags.
1772 */
1773 open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
1774 if (!open->op_stateowner->so_confirmed)
1775 open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
1776
1777 return status;
1778}
1779
1780static struct work_struct laundromat_work;
1781static void laundromat_main(void *);
1782static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
1783
1784int
1785nfsd4_renew(clientid_t *clid)
1786{
1787 struct nfs4_client *clp;
1788 int status;
1789
1790 nfs4_lock_state();
1791 dprintk("process_renew(%08x/%08x): starting\n",
1792 clid->cl_boot, clid->cl_id);
1793 status = nfserr_stale_clientid;
1794 if (STALE_CLIENTID(clid))
1795 goto out;
1796 clp = find_confirmed_client(clid);
1797 status = nfserr_expired;
1798 if (clp == NULL) {
1799 /* We assume the client took too long to RENEW. */
1800 dprintk("nfsd4_renew: clientid not found!\n");
1801 goto out;
1802 }
1803 renew_client(clp);
1804 status = nfserr_cb_path_down;
1805 if (!list_empty(&clp->cl_del_perclnt)
1806 && !atomic_read(&clp->cl_callback.cb_set))
1807 goto out;
1808 status = nfs_ok;
1809out:
1810 nfs4_unlock_state();
1811 return status;
1812}
1813
1814time_t
1815nfs4_laundromat(void)
1816{
1817 struct nfs4_client *clp;
1818 struct nfs4_stateowner *sop;
1819 struct nfs4_delegation *dp;
1820 struct list_head *pos, *next, reaplist;
1821 time_t cutoff = get_seconds() - NFSD_LEASE_TIME;
1822 time_t t, clientid_val = NFSD_LEASE_TIME;
1823 time_t u, test_val = NFSD_LEASE_TIME;
1824
1825 nfs4_lock_state();
1826
1827 dprintk("NFSD: laundromat service - starting\n");
1828 list_for_each_safe(pos, next, &client_lru) {
1829 clp = list_entry(pos, struct nfs4_client, cl_lru);
1830 if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
1831 t = clp->cl_time - cutoff;
1832 if (clientid_val > t)
1833 clientid_val = t;
1834 break;
1835 }
1836 dprintk("NFSD: purging unused client (clientid %08x)\n",
1837 clp->cl_clientid.cl_id);
1838 expire_client(clp);
1839 }
1840 INIT_LIST_HEAD(&reaplist);
1841 spin_lock(&recall_lock);
1842 list_for_each_safe(pos, next, &del_recall_lru) {
1843 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
1844 if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) {
1845 u = dp->dl_time - cutoff;
1846 if (test_val > u)
1847 test_val = u;
1848 break;
1849 }
1850 dprintk("NFSD: purging unused delegation dp %p, fp %p\n",
1851 dp, dp->dl_flock);
1852 list_move(&dp->dl_recall_lru, &reaplist);
1853 }
1854 spin_unlock(&recall_lock);
1855 list_for_each_safe(pos, next, &reaplist) {
1856 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
1857 list_del_init(&dp->dl_recall_lru);
1858 unhash_delegation(dp);
1859 }
1860 test_val = NFSD_LEASE_TIME;
1861 list_for_each_safe(pos, next, &close_lru) {
1862 sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
1863 if (time_after((unsigned long)sop->so_time, (unsigned long)cutoff)) {
1864 u = sop->so_time - cutoff;
1865 if (test_val > u)
1866 test_val = u;
1867 break;
1868 }
1869 dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
1870 sop->so_id);
1871 list_del(&sop->so_close_lru);
1872 nfs4_put_stateowner(sop);
1873 }
1874 if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
1875 clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
1876 nfs4_unlock_state();
1877 return clientid_val;
1878}
1879
1880void
1881laundromat_main(void *not_used)
1882{
1883 time_t t;
1884
1885 t = nfs4_laundromat();
1886 dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
1887 schedule_delayed_work(&laundromat_work, t*HZ);
1888}
1889
1890/* search ownerid_hashtbl[] and close_lru for stateid owner
1891 * (stateid->si_stateownerid)
1892 */
1893struct nfs4_stateowner *
1894find_openstateowner_id(u32 st_id, int flags) {
1895 struct nfs4_stateowner *local = NULL;
1896
1897 dprintk("NFSD: find_openstateowner_id %d\n", st_id);
1898 if (flags & CLOSE_STATE) {
1899 list_for_each_entry(local, &close_lru, so_close_lru) {
1900 if (local->so_id == st_id)
1901 return local;
1902 }
1903 }
1904 return NULL;
1905}
1906
1907static inline int
1908nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
1909{
1910 return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode;
1911}
1912
1913static int
1914STALE_STATEID(stateid_t *stateid)
1915{
1916 if (stateid->si_boot == boot_time)
1917 return 0;
1918 printk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
1919 stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
1920 stateid->si_generation);
1921 return 1;
1922}
1923
1924static inline int
1925access_permit_read(unsigned long access_bmap)
1926{
1927 return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
1928 test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap) ||
1929 test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap);
1930}
1931
1932static inline int
1933access_permit_write(unsigned long access_bmap)
1934{
1935 return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) ||
1936 test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
1937}
1938
1939static
1940int nfs4_check_openmode(struct nfs4_stateid *stp, int flags)
1941{
1942 int status = nfserr_openmode;
1943
1944 if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap)))
1945 goto out;
1946 if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap)))
1947 goto out;
1948 status = nfs_ok;
1949out:
1950 return status;
1951}
1952
1953static inline int
1954nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
1955{
1956 if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
1957 return nfserr_openmode;
1958 else
1959 return nfs_ok;
1960}
1961
1962static inline int
1963check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
1964{
1965 /* Trying to call delegreturn with a special stateid? Yuch: */
1966 if (!(flags & (RD_STATE | WR_STATE)))
1967 return nfserr_bad_stateid;
1968 else if (ONE_STATEID(stateid) && (flags & RD_STATE))
1969 return nfs_ok;
1970 else if (nfs4_in_grace()) {
1971 /* Answer in remaining cases depends on existance of
1972 * conflicting state; so we must wait out the grace period. */
1973 return nfserr_grace;
1974 } else if (flags & WR_STATE)
1975 return nfs4_share_conflict(current_fh,
1976 NFS4_SHARE_DENY_WRITE);
1977 else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */
1978 return nfs4_share_conflict(current_fh,
1979 NFS4_SHARE_DENY_READ);
1980}
1981
1982/*
1983 * Allow READ/WRITE during grace period on recovered state only for files
1984 * that are not able to provide mandatory locking.
1985 */
1986static inline int
1987io_during_grace_disallowed(struct inode *inode, int flags)
1988{
1989 return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
1990 && MANDATORY_LOCK(inode);
1991}
1992
1993/*
1994* Checks for stateid operations
1995*/
1996int
1997nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct file **filpp)
1998{
1999 struct nfs4_stateid *stp = NULL;
2000 struct nfs4_delegation *dp = NULL;
2001 stateid_t *stidp;
2002 struct inode *ino = current_fh->fh_dentry->d_inode;
2003 int status;
2004
2005 dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
2006 stateid->si_boot, stateid->si_stateownerid,
2007 stateid->si_fileid, stateid->si_generation);
2008 if (filpp)
2009 *filpp = NULL;
2010
2011 if (io_during_grace_disallowed(ino, flags))
2012 return nfserr_grace;
2013
2014 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
2015 return check_special_stateids(current_fh, stateid, flags);
2016
2017 /* STALE STATEID */
2018 status = nfserr_stale_stateid;
2019 if (STALE_STATEID(stateid))
2020 goto out;
2021
2022 /* BAD STATEID */
2023 status = nfserr_bad_stateid;
2024 if (!stateid->si_fileid) { /* delegation stateid */
2025 if(!(dp = find_delegation_stateid(ino, stateid))) {
2026 dprintk("NFSD: delegation stateid not found\n");
2027 if (nfs4_in_grace())
2028 status = nfserr_grace;
2029 goto out;
2030 }
2031 stidp = &dp->dl_stateid;
2032 } else { /* open or lock stateid */
2033 if (!(stp = find_stateid(stateid, flags))) {
2034 dprintk("NFSD: open or lock stateid not found\n");
2035 if (nfs4_in_grace())
2036 status = nfserr_grace;
2037 goto out;
2038 }
2039 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
2040 goto out;
2041 if (!stp->st_stateowner->so_confirmed)
2042 goto out;
2043 stidp = &stp->st_stateid;
2044 }
2045 if (stateid->si_generation > stidp->si_generation)
2046 goto out;
2047
2048 /* OLD STATEID */
2049 status = nfserr_old_stateid;
2050 if (stateid->si_generation < stidp->si_generation)
2051 goto out;
2052 if (stp) {
2053 if ((status = nfs4_check_openmode(stp,flags)))
2054 goto out;
2055 renew_client(stp->st_stateowner->so_client);
2056 if (filpp)
2057 *filpp = stp->st_vfs_file;
2058 } else if (dp) {
2059 if ((status = nfs4_check_delegmode(dp, flags)))
2060 goto out;
2061 renew_client(dp->dl_client);
2062 if (flags & DELEG_RET)
2063 unhash_delegation(dp);
2064 if (filpp)
2065 *filpp = dp->dl_vfs_file;
2066 }
2067 status = nfs_ok;
2068out:
2069 return status;
2070}
2071
2072
2073/*
2074 * Checks for sequence id mutating operations.
2075 */
2076int
2077nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
2078{
2079 int status;
2080 struct nfs4_stateid *stp;
2081 struct nfs4_stateowner *sop;
2082
2083 dprintk("NFSD: preprocess_seqid_op: seqid=%d "
2084 "stateid = (%08x/%08x/%08x/%08x)\n", seqid,
2085 stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
2086 stateid->si_generation);
2087
2088 *stpp = NULL;
2089 *sopp = NULL;
2090
2091 status = nfserr_bad_stateid;
2092 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
2093 printk("NFSD: preprocess_seqid_op: magic stateid!\n");
2094 goto out;
2095 }
2096
2097 status = nfserr_stale_stateid;
2098 if (STALE_STATEID(stateid))
2099 goto out;
2100 /*
2101 * We return BAD_STATEID if filehandle doesn't match stateid,
2102 * the confirmed flag is incorrecly set, or the generation
2103 * number is incorrect.
2104 * If there is no entry in the openfile table for this id,
2105 * we can't always return BAD_STATEID;
2106 * this might be a retransmitted CLOSE which has arrived after
2107 * the openfile has been released.
2108 */
2109 if (!(stp = find_stateid(stateid, flags)))
2110 goto no_nfs4_stateid;
2111
2112 status = nfserr_bad_stateid;
2113
2114 /* for new lock stateowners:
2115 * check that the lock->v.new.open_stateid
2116 * refers to an open stateowner
2117 *
2118 * check that the lockclid (nfs4_lock->v.new.clientid) is the same
2119 * as the open_stateid->st_stateowner->so_client->clientid
2120 */
2121 if (lockclid) {
2122 struct nfs4_stateowner *sop = stp->st_stateowner;
2123 struct nfs4_client *clp = sop->so_client;
2124
2125 if (!sop->so_is_open_owner)
2126 goto out;
2127 if (!cmp_clid(&clp->cl_clientid, lockclid))
2128 goto out;
2129 }
2130
2131 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
2132 printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
2133 goto out;
2134 }
2135
2136 *stpp = stp;
2137 *sopp = sop = stp->st_stateowner;
2138
2139 /*
2140 * We now validate the seqid and stateid generation numbers.
2141 * For the moment, we ignore the possibility of
2142 * generation number wraparound.
2143 */
2144 if (seqid != sop->so_seqid + 1)
2145 goto check_replay;
2146
2147 if (sop->so_confirmed) {
2148 if (flags & CONFIRM) {
2149 printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n");
2150 goto out;
2151 }
2152 }
2153 else {
2154 if (!(flags & CONFIRM)) {
2155 printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n");
2156 goto out;
2157 }
2158 }
2159 if (stateid->si_generation > stp->st_stateid.si_generation) {
2160 printk("NFSD: preprocess_seqid_op: future stateid?!\n");
2161 goto out;
2162 }
2163
2164 status = nfserr_old_stateid;
2165 if (stateid->si_generation < stp->st_stateid.si_generation) {
2166 printk("NFSD: preprocess_seqid_op: old stateid!\n");
2167 goto out;
2168 }
2169 /* XXX renew the client lease here */
2170 status = nfs_ok;
2171
2172out:
2173 return status;
2174
2175no_nfs4_stateid:
2176
2177 /*
2178 * We determine whether this is a bad stateid or a replay,
2179 * starting by trying to look up the stateowner.
2180 * If stateowner is not found - stateid is bad.
2181 */
2182 if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) {
2183 printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n");
2184 status = nfserr_bad_stateid;
2185 goto out;
2186 }
2187 *sopp = sop;
2188
2189check_replay:
2190 if (seqid == sop->so_seqid) {
2191 printk("NFSD: preprocess_seqid_op: retransmission?\n");
2192 /* indicate replay to calling function */
2193 status = NFSERR_REPLAY_ME;
2194 } else {
2195 printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid);
2196
2197 *sopp = NULL;
2198 status = nfserr_bad_seqid;
2199 }
2200 goto out;
2201}
2202
2203int
2204nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
2205{
2206 int status;
2207 struct nfs4_stateowner *sop;
2208 struct nfs4_stateid *stp;
2209
2210 dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
2211 (int)current_fh->fh_dentry->d_name.len,
2212 current_fh->fh_dentry->d_name.name);
2213
2214 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
2215 goto out;
2216
2217 nfs4_lock_state();
2218
2219 if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
2220 &oc->oc_req_stateid,
2221 CHECK_FH | CONFIRM | OPEN_STATE,
2222 &oc->oc_stateowner, &stp, NULL)))
2223 goto out;
2224
2225 sop = oc->oc_stateowner;
2226 sop->so_confirmed = 1;
2227 update_stateid(&stp->st_stateid);
2228 memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));
2229 dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d "
2230 "stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid,
2231 stp->st_stateid.si_boot,
2232 stp->st_stateid.si_stateownerid,
2233 stp->st_stateid.si_fileid,
2234 stp->st_stateid.si_generation);
2235out:
2236 if (oc->oc_stateowner)
2237 nfs4_get_stateowner(oc->oc_stateowner);
2238 nfs4_unlock_state();
2239 return status;
2240}
2241
2242
2243/*
2244 * unset all bits in union bitmap (bmap) that
2245 * do not exist in share (from successful OPEN_DOWNGRADE)
2246 */
2247static void
2248reset_union_bmap_access(unsigned long access, unsigned long *bmap)
2249{
2250 int i;
2251 for (i = 1; i < 4; i++) {
2252 if ((i & access) != i)
2253 __clear_bit(i, bmap);
2254 }
2255}
2256
2257static void
2258reset_union_bmap_deny(unsigned long deny, unsigned long *bmap)
2259{
2260 int i;
2261 for (i = 0; i < 4; i++) {
2262 if ((i & deny) != i)
2263 __clear_bit(i, bmap);
2264 }
2265}
2266
2267int
2268nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od)
2269{
2270 int status;
2271 struct nfs4_stateid *stp;
2272 unsigned int share_access;
2273
2274 dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
2275 (int)current_fh->fh_dentry->d_name.len,
2276 current_fh->fh_dentry->d_name.name);
2277
2278 if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny))
2279 return nfserr_inval;
2280
2281 nfs4_lock_state();
2282 if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid,
2283 &od->od_stateid,
2284 CHECK_FH | OPEN_STATE,
2285 &od->od_stateowner, &stp, NULL)))
2286 goto out;
2287
2288 status = nfserr_inval;
2289 if (!test_bit(od->od_share_access, &stp->st_access_bmap)) {
2290 dprintk("NFSD:access not a subset current bitmap: 0x%lx, input access=%08x\n",
2291 stp->st_access_bmap, od->od_share_access);
2292 goto out;
2293 }
2294 if (!test_bit(od->od_share_deny, &stp->st_deny_bmap)) {
2295 dprintk("NFSD:deny not a subset current bitmap: 0x%lx, input deny=%08x\n",
2296 stp->st_deny_bmap, od->od_share_deny);
2297 goto out;
2298 }
2299 set_access(&share_access, stp->st_access_bmap);
2300 nfs4_file_downgrade(stp->st_vfs_file,
2301 share_access & ~od->od_share_access);
2302
2303 reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
2304 reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
2305
2306 update_stateid(&stp->st_stateid);
2307 memcpy(&od->od_stateid, &stp->st_stateid, sizeof(stateid_t));
2308 status = nfs_ok;
2309out:
2310 if (od->od_stateowner)
2311 nfs4_get_stateowner(od->od_stateowner);
2312 nfs4_unlock_state();
2313 return status;
2314}
2315
2316/*
2317 * nfs4_unlock_state() called after encode
2318 */
2319int
2320nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close)
2321{
2322 int status;
2323 struct nfs4_stateid *stp;
2324
2325 dprintk("NFSD: nfsd4_close on file %.*s\n",
2326 (int)current_fh->fh_dentry->d_name.len,
2327 current_fh->fh_dentry->d_name.name);
2328
2329 nfs4_lock_state();
2330 /* check close_lru for replay */
2331 if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid,
2332 &close->cl_stateid,
2333 CHECK_FH | OPEN_STATE | CLOSE_STATE,
2334 &close->cl_stateowner, &stp, NULL)))
2335 goto out;
2336 /*
2337 * Return success, but first update the stateid.
2338 */
2339 status = nfs_ok;
2340 update_stateid(&stp->st_stateid);
2341 memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
2342
2343 /* release_state_owner() calls nfsd_close() if needed */
2344 release_state_owner(stp, OPEN_STATE);
2345out:
2346 if (close->cl_stateowner)
2347 nfs4_get_stateowner(close->cl_stateowner);
2348 nfs4_unlock_state();
2349 return status;
2350}
2351
2352int
2353nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr)
2354{
2355 int status;
2356
2357 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
2358 goto out;
2359
2360 nfs4_lock_state();
2361 status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL);
2362 nfs4_unlock_state();
2363out:
2364 return status;
2365}
2366
2367
2368/*
2369 * Lock owner state (byte-range locks)
2370 */
2371#define LOFF_OVERFLOW(start, len) ((u64)(len) > ~(u64)(start))
2372#define LOCK_HASH_BITS 8
2373#define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS)
2374#define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1)
2375
2376#define lockownerid_hashval(id) \
2377 ((id) & LOCK_HASH_MASK)
2378
2379static inline unsigned int
2380lock_ownerstr_hashval(struct inode *inode, u32 cl_id,
2381 struct xdr_netobj *ownername)
2382{
2383 return (file_hashval(inode) + cl_id
2384 + opaque_hashval(ownername->data, ownername->len))
2385 & LOCK_HASH_MASK;
2386}
2387
2388static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
2389static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
2390static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
2391
2392struct nfs4_stateid *
2393find_stateid(stateid_t *stid, int flags)
2394{
2395 struct nfs4_stateid *local = NULL;
2396 u32 st_id = stid->si_stateownerid;
2397 u32 f_id = stid->si_fileid;
2398 unsigned int hashval;
2399
2400 dprintk("NFSD: find_stateid flags 0x%x\n",flags);
2401 if ((flags & LOCK_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) {
2402 hashval = stateid_hashval(st_id, f_id);
2403 list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
2404 if ((local->st_stateid.si_stateownerid == st_id) &&
2405 (local->st_stateid.si_fileid == f_id))
2406 return local;
2407 }
2408 }
2409 if ((flags & OPEN_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) {
2410 hashval = stateid_hashval(st_id, f_id);
2411 list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
2412 if ((local->st_stateid.si_stateownerid == st_id) &&
2413 (local->st_stateid.si_fileid == f_id))
2414 return local;
2415 }
2416 } else
2417 printk("NFSD: find_stateid: ERROR: no state flag\n");
2418 return NULL;
2419}
2420
2421static struct nfs4_delegation *
2422find_delegation_stateid(struct inode *ino, stateid_t *stid)
2423{
2424 struct nfs4_delegation *dp = NULL;
2425 struct nfs4_file *fp = NULL;
2426 u32 st_id;
2427
2428 dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
2429 stid->si_boot, stid->si_stateownerid,
2430 stid->si_fileid, stid->si_generation);
2431
2432 st_id = stid->si_stateownerid;
2433 fp = find_file(ino);
2434 if (fp) {
2435 list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
2436 if(dp->dl_stateid.si_stateownerid == st_id) {
2437 dprintk("NFSD: find_delegation dp %p\n",dp);
2438 return dp;
2439 }
2440 }
2441 }
2442 return NULL;
2443}
2444
2445/*
2446 * TODO: Linux file offsets are _signed_ 64-bit quantities, which means that
2447 * we can't properly handle lock requests that go beyond the (2^63 - 1)-th
2448 * byte, because of sign extension problems. Since NFSv4 calls for 64-bit
2449 * locking, this prevents us from being completely protocol-compliant. The
2450 * real solution to this problem is to start using unsigned file offsets in
2451 * the VFS, but this is a very deep change!
2452 */
2453static inline void
2454nfs4_transform_lock_offset(struct file_lock *lock)
2455{
2456 if (lock->fl_start < 0)
2457 lock->fl_start = OFFSET_MAX;
2458 if (lock->fl_end < 0)
2459 lock->fl_end = OFFSET_MAX;
2460}
2461
2462int
2463nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
2464{
2465 struct nfs4_stateowner *local = NULL;
2466 int status = 0;
2467
2468 if (hashval >= LOCK_HASH_SIZE)
2469 goto out;
2470 list_for_each_entry(local, &lock_ownerid_hashtbl[hashval], so_idhash) {
2471 if (local == sop) {
2472 status = 1;
2473 goto out;
2474 }
2475 }
2476out:
2477 return status;
2478}
2479
2480
2481static inline void
2482nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
2483{
2484 struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
2485 unsigned int hval = lockownerid_hashval(sop->so_id);
2486
2487 deny->ld_sop = NULL;
2488 if (nfs4_verify_lock_stateowner(sop, hval)) {
2489 kref_get(&sop->so_ref);
2490 deny->ld_sop = sop;
2491 deny->ld_clientid = sop->so_client->cl_clientid;
2492 }
2493 deny->ld_start = fl->fl_start;
2494 deny->ld_length = ~(u64)0;
2495 if (fl->fl_end != ~(u64)0)
2496 deny->ld_length = fl->fl_end - fl->fl_start + 1;
2497 deny->ld_type = NFS4_READ_LT;
2498 if (fl->fl_type != F_RDLCK)
2499 deny->ld_type = NFS4_WRITE_LT;
2500}
2501
2502static struct nfs4_stateowner *
2503find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
2504{
2505 struct nfs4_stateowner *local = NULL;
2506 int i;
2507
2508 for (i = 0; i < LOCK_HASH_SIZE; i++) {
2509 list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
2510 if (!cmp_owner_str(local, owner, clid))
2511 continue;
2512 return local;
2513 }
2514 }
2515 return NULL;
2516}
2517
2518static struct nfs4_stateowner *
2519find_lockstateowner_str(struct inode *inode, clientid_t *clid,
2520 struct xdr_netobj *owner)
2521{
2522 unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner);
2523 struct nfs4_stateowner *op;
2524
2525 list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) {
2526 if (cmp_owner_str(op, owner, clid))
2527 return op;
2528 }
2529 return NULL;
2530}
2531
2532/*
2533 * Alloc a lock owner structure.
2534 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has
2535 * occured.
2536 *
2537 * strhashval = lock_ownerstr_hashval
2538 * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode
2539 */
2540
2541static struct nfs4_stateowner *
2542alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfs4_stateid *open_stp, struct nfsd4_lock *lock) {
2543 struct nfs4_stateowner *sop;
2544 struct nfs4_replay *rp;
2545 unsigned int idhashval;
2546
2547 if (!(sop = alloc_stateowner(&lock->lk_new_owner)))
2548 return NULL;
2549 idhashval = lockownerid_hashval(current_ownerid);
2550 INIT_LIST_HEAD(&sop->so_idhash);
2551 INIT_LIST_HEAD(&sop->so_strhash);
2552 INIT_LIST_HEAD(&sop->so_perclient);
2553 INIT_LIST_HEAD(&sop->so_perfilestate);
2554 INIT_LIST_HEAD(&sop->so_perlockowner);
2555 INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
2556 sop->so_time = 0;
2557 list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
2558 list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
2559 list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
2560 sop->so_is_open_owner = 0;
2561 sop->so_id = current_ownerid++;
2562 sop->so_client = clp;
2563 sop->so_seqid = lock->lk_new_lock_seqid - 1;
2564 sop->so_confirmed = 1;
2565 rp = &sop->so_replay;
2566 rp->rp_status = NFSERR_SERVERFAULT;
2567 rp->rp_buflen = 0;
2568 rp->rp_buf = rp->rp_ibuf;
2569 return sop;
2570}
2571
2572struct nfs4_stateid *
2573alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
2574{
2575 struct nfs4_stateid *stp;
2576 unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
2577
2578 if ((stp = kmalloc(sizeof(struct nfs4_stateid),
2579 GFP_KERNEL)) == NULL)
2580 goto out;
2581 INIT_LIST_HEAD(&stp->st_hash);
2582 INIT_LIST_HEAD(&stp->st_perfile);
2583 INIT_LIST_HEAD(&stp->st_perfilestate);
2584 INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
2585 list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
2586 list_add(&stp->st_perfile, &fp->fi_perfile);
2587 list_add_perfile++;
2588 list_add(&stp->st_perfilestate, &sop->so_perfilestate);
2589 stp->st_stateowner = sop;
2590 stp->st_file = fp;
2591 stp->st_stateid.si_boot = boot_time;
2592 stp->st_stateid.si_stateownerid = sop->so_id;
2593 stp->st_stateid.si_fileid = fp->fi_id;
2594 stp->st_stateid.si_generation = 0;
2595 stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
2596 stp->st_access_bmap = open_stp->st_access_bmap;
2597 stp->st_deny_bmap = open_stp->st_deny_bmap;
2598
2599out:
2600 return stp;
2601}
2602
2603int
2604check_lock_length(u64 offset, u64 length)
2605{
2606 return ((length == 0) || ((length != ~(u64)0) &&
2607 LOFF_OVERFLOW(offset, length)));
2608}
2609
2610/*
2611 * LOCK operation
2612 */
2613int
2614nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
2615{
2616 struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL;
2617 struct nfs4_stateid *lock_stp;
2618 struct file *filp;
2619 struct file_lock file_lock;
2620 struct file_lock *conflock;
2621 int status = 0;
2622 unsigned int strhashval;
2623
2624 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
2625 (long long) lock->lk_offset,
2626 (long long) lock->lk_length);
2627
2628 if (nfs4_in_grace() && !lock->lk_reclaim)
2629 return nfserr_grace;
2630 if (!nfs4_in_grace() && lock->lk_reclaim)
2631 return nfserr_no_grace;
2632
2633 if (check_lock_length(lock->lk_offset, lock->lk_length))
2634 return nfserr_inval;
2635
2636 nfs4_lock_state();
2637
2638 if (lock->lk_is_new) {
2639 /*
2640 * Client indicates that this is a new lockowner.
2641 * Use open owner and open stateid to create lock owner and lock
2642 * stateid.
2643 */
2644 struct nfs4_stateid *open_stp = NULL;
2645 struct nfs4_file *fp;
2646
2647 status = nfserr_stale_clientid;
2648 if (STALE_CLIENTID(&lock->lk_new_clientid)) {
2649 printk("NFSD: nfsd4_lock: clientid is stale!\n");
2650 goto out;
2651 }
2652
2653 /* is the new lock seqid presented by the client zero? */
2654 status = nfserr_bad_seqid;
2655 if (lock->v.new.lock_seqid != 0)
2656 goto out;
2657
2658 /* validate and update open stateid and open seqid */
2659 status = nfs4_preprocess_seqid_op(current_fh,
2660 lock->lk_new_open_seqid,
2661 &lock->lk_new_open_stateid,
2662 CHECK_FH | OPEN_STATE,
2663 &open_sop, &open_stp,
2664 &lock->v.new.clientid);
2665 if (status) {
2666 if (lock->lk_reclaim)
2667 status = nfserr_reclaim_bad;
2668 goto out;
2669 }
2670 /* create lockowner and lock stateid */
2671 fp = open_stp->st_file;
2672 strhashval = lock_ownerstr_hashval(fp->fi_inode,
2673 open_sop->so_client->cl_clientid.cl_id,
2674 &lock->v.new.owner);
2675 /*
2676 * If we already have this lock owner, the client is in
2677 * error (or our bookeeping is wrong!)
2678 * for asking for a 'new lock'.
2679 */
2680 status = nfserr_bad_stateid;
2681 lock_sop = find_lockstateowner(&lock->v.new.owner,
2682 &lock->v.new.clientid);
2683 if (lock_sop)
2684 goto out;
2685 status = nfserr_resource;
2686 if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
2687 goto out;
2688 if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner,
2689 fp, open_stp)) == NULL) {
2690 release_stateowner(lock->lk_stateowner);
2691 lock->lk_stateowner = NULL;
2692 goto out;
2693 }
2694 /* bump the open seqid used to create the lock */
2695 open_sop->so_seqid++;
2696 } else {
2697 /* lock (lock owner + lock stateid) already exists */
2698 status = nfs4_preprocess_seqid_op(current_fh,
2699 lock->lk_old_lock_seqid,
2700 &lock->lk_old_lock_stateid,
2701 CHECK_FH | LOCK_STATE,
2702 &lock->lk_stateowner, &lock_stp, NULL);
2703 if (status)
2704 goto out;
2705 }
2706 /* lock->lk_stateowner and lock_stp have been created or found */
2707 filp = lock_stp->st_vfs_file;
2708
2709 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
2710 printk("NFSD: nfsd4_lock: permission denied!\n");
2711 goto out;
2712 }
2713
2714 locks_init_lock(&file_lock);
2715 switch (lock->lk_type) {
2716 case NFS4_READ_LT:
2717 case NFS4_READW_LT:
2718 file_lock.fl_type = F_RDLCK;
2719 break;
2720 case NFS4_WRITE_LT:
2721 case NFS4_WRITEW_LT:
2722 file_lock.fl_type = F_WRLCK;
2723 break;
2724 default:
2725 status = nfserr_inval;
2726 goto out;
2727 }
2728 file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
2729 file_lock.fl_pid = current->tgid;
2730 file_lock.fl_file = filp;
2731 file_lock.fl_flags = FL_POSIX;
2732
2733 file_lock.fl_start = lock->lk_offset;
2734 if ((lock->lk_length == ~(u64)0) ||
2735 LOFF_OVERFLOW(lock->lk_offset, lock->lk_length))
2736 file_lock.fl_end = ~(u64)0;
2737 else
2738 file_lock.fl_end = lock->lk_offset + lock->lk_length - 1;
2739 nfs4_transform_lock_offset(&file_lock);
2740
2741 /*
2742 * Try to lock the file in the VFS.
2743 * Note: locks.c uses the BKL to protect the inode's lock list.
2744 */
2745
2746 status = posix_lock_file(filp, &file_lock);
2747 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2748 file_lock.fl_ops->fl_release_private(&file_lock);
2749 dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
2750 switch (-status) {
2751 case 0: /* success! */
2752 update_stateid(&lock_stp->st_stateid);
2753 memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid,
2754 sizeof(stateid_t));
2755 goto out;
2756 case (EAGAIN):
2757 goto conflicting_lock;
2758 case (EDEADLK):
2759 status = nfserr_deadlock;
2760 default:
2761 dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
2762 goto out_destroy_new_stateid;
2763 }
2764
2765conflicting_lock:
2766 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
2767 status = nfserr_denied;
2768 /* XXX There is a race here. Future patch needed to provide
2769 * an atomic posix_lock_and_test_file
2770 */
2771 if (!(conflock = posix_test_lock(filp, &file_lock))) {
2772 status = nfserr_serverfault;
2773 goto out;
2774 }
2775 nfs4_set_lock_denied(conflock, &lock->lk_denied);
2776
2777out_destroy_new_stateid:
2778 if (lock->lk_is_new) {
2779 dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
2780 /*
2781 * An error encountered after instantiation of the new
2782 * stateid has forced us to destroy it.
2783 */
2784 if (!seqid_mutating_err(status))
2785 open_sop->so_seqid--;
2786
2787 release_state_owner(lock_stp, LOCK_STATE);
2788 }
2789out:
2790 if (lock->lk_stateowner)
2791 nfs4_get_stateowner(lock->lk_stateowner);
2792 nfs4_unlock_state();
2793 return status;
2794}
2795
2796/*
2797 * LOCKT operation
2798 */
2799int
2800nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
2801{
2802 struct inode *inode;
2803 struct file file;
2804 struct file_lock file_lock;
2805 struct file_lock *conflicting_lock;
2806 int status;
2807
2808 if (nfs4_in_grace())
2809 return nfserr_grace;
2810
2811 if (check_lock_length(lockt->lt_offset, lockt->lt_length))
2812 return nfserr_inval;
2813
2814 lockt->lt_stateowner = NULL;
2815 nfs4_lock_state();
2816
2817 status = nfserr_stale_clientid;
2818 if (STALE_CLIENTID(&lockt->lt_clientid)) {
2819 printk("NFSD: nfsd4_lockt: clientid is stale!\n");
2820 goto out;
2821 }
2822
2823 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
2824 printk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
2825 if (status == nfserr_symlink)
2826 status = nfserr_inval;
2827 goto out;
2828 }
2829
2830 inode = current_fh->fh_dentry->d_inode;
2831 locks_init_lock(&file_lock);
2832 switch (lockt->lt_type) {
2833 case NFS4_READ_LT:
2834 case NFS4_READW_LT:
2835 file_lock.fl_type = F_RDLCK;
2836 break;
2837 case NFS4_WRITE_LT:
2838 case NFS4_WRITEW_LT:
2839 file_lock.fl_type = F_WRLCK;
2840 break;
2841 default:
2842 printk("NFSD: nfs4_lockt: bad lock type!\n");
2843 status = nfserr_inval;
2844 goto out;
2845 }
2846
2847 lockt->lt_stateowner = find_lockstateowner_str(inode,
2848 &lockt->lt_clientid, &lockt->lt_owner);
2849 if (lockt->lt_stateowner)
2850 file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
2851 file_lock.fl_pid = current->tgid;
2852 file_lock.fl_flags = FL_POSIX;
2853
2854 file_lock.fl_start = lockt->lt_offset;
2855 if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length))
2856 file_lock.fl_end = ~(u64)0;
2857 else
2858 file_lock.fl_end = lockt->lt_offset + lockt->lt_length - 1;
2859
2860 nfs4_transform_lock_offset(&file_lock);
2861
2862 /* posix_test_lock uses the struct file _only_ to resolve the inode.
2863 * since LOCKT doesn't require an OPEN, and therefore a struct
2864 * file may not exist, pass posix_test_lock a struct file with
2865 * only the dentry:inode set.
2866 */
2867 memset(&file, 0, sizeof (struct file));
2868 file.f_dentry = current_fh->fh_dentry;
2869
2870 status = nfs_ok;
2871 conflicting_lock = posix_test_lock(&file, &file_lock);
2872 if (conflicting_lock) {
2873 status = nfserr_denied;
2874 nfs4_set_lock_denied(conflicting_lock, &lockt->lt_denied);
2875 }
2876out:
2877 nfs4_unlock_state();
2878 return status;
2879}
2880
2881int
2882nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku)
2883{
2884 struct nfs4_stateid *stp;
2885 struct file *filp = NULL;
2886 struct file_lock file_lock;
2887 int status;
2888
2889 dprintk("NFSD: nfsd4_locku: start=%Ld length=%Ld\n",
2890 (long long) locku->lu_offset,
2891 (long long) locku->lu_length);
2892
2893 if (check_lock_length(locku->lu_offset, locku->lu_length))
2894 return nfserr_inval;
2895
2896 nfs4_lock_state();
2897
2898 if ((status = nfs4_preprocess_seqid_op(current_fh,
2899 locku->lu_seqid,
2900 &locku->lu_stateid,
2901 CHECK_FH | LOCK_STATE,
2902 &locku->lu_stateowner, &stp, NULL)))
2903 goto out;
2904
2905 filp = stp->st_vfs_file;
2906 BUG_ON(!filp);
2907 locks_init_lock(&file_lock);
2908 file_lock.fl_type = F_UNLCK;
2909 file_lock.fl_owner = (fl_owner_t) locku->lu_stateowner;
2910 file_lock.fl_pid = current->tgid;
2911 file_lock.fl_file = filp;
2912 file_lock.fl_flags = FL_POSIX;
2913 file_lock.fl_start = locku->lu_offset;
2914
2915 if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
2916 file_lock.fl_end = ~(u64)0;
2917 else
2918 file_lock.fl_end = locku->lu_offset + locku->lu_length - 1;
2919 nfs4_transform_lock_offset(&file_lock);
2920
2921 /*
2922 * Try to unlock the file in the VFS.
2923 */
2924 status = posix_lock_file(filp, &file_lock);
2925 if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
2926 file_lock.fl_ops->fl_release_private(&file_lock);
2927 if (status) {
2928 printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
2929 goto out_nfserr;
2930 }
2931 /*
2932 * OK, unlock succeeded; the only thing left to do is update the stateid.
2933 */
2934 update_stateid(&stp->st_stateid);
2935 memcpy(&locku->lu_stateid, &stp->st_stateid, sizeof(stateid_t));
2936
2937out:
2938 if (locku->lu_stateowner)
2939 nfs4_get_stateowner(locku->lu_stateowner);
2940 nfs4_unlock_state();
2941 return status;
2942
2943out_nfserr:
2944 status = nfserrno(status);
2945 goto out;
2946}
2947
2948/*
2949 * returns
2950 * 1: locks held by lockowner
2951 * 0: no locks held by lockowner
2952 */
2953static int
2954check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
2955{
2956 struct file_lock **flpp;
2957 struct inode *inode = filp->f_dentry->d_inode;
2958 int status = 0;
2959
2960 lock_kernel();
2961 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
2962 if ((*flpp)->fl_owner == (fl_owner_t)lowner)
2963 status = 1;
2964 goto out;
2965 }
2966out:
2967 unlock_kernel();
2968 return status;
2969}
2970
2971int
2972nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
2973{
2974 clientid_t *clid = &rlockowner->rl_clientid;
2975 struct nfs4_stateowner *local = NULL;
2976 struct xdr_netobj *owner = &rlockowner->rl_owner;
2977 int status;
2978
2979 dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
2980 clid->cl_boot, clid->cl_id);
2981
2982 /* XXX check for lease expiration */
2983
2984 status = nfserr_stale_clientid;
2985 if (STALE_CLIENTID(clid)) {
2986 printk("NFSD: nfsd4_release_lockowner: clientid is stale!\n");
2987 return status;
2988 }
2989
2990 nfs4_lock_state();
2991
2992 status = nfs_ok;
2993 local = find_lockstateowner(owner, clid);
2994 if (local) {
2995 struct nfs4_stateid *stp;
2996
2997 /* check for any locks held by any stateid
2998 * associated with the (lock) stateowner */
2999 status = nfserr_locks_held;
3000 list_for_each_entry(stp, &local->so_perfilestate,
3001 st_perfilestate) {
3002 if (check_for_locks(stp->st_vfs_file, local))
3003 goto out;
3004 }
3005 /* no locks held by (lock) stateowner */
3006 status = nfs_ok;
3007 release_stateowner(local);
3008 }
3009out:
3010 nfs4_unlock_state();
3011 return status;
3012}
3013
3014static inline struct nfs4_client_reclaim *
3015alloc_reclaim(int namelen)
3016{
3017 struct nfs4_client_reclaim *crp = NULL;
3018
3019 crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
3020 if (!crp)
3021 return NULL;
3022 crp->cr_name.data = kmalloc(namelen, GFP_KERNEL);
3023 if (!crp->cr_name.data) {
3024 kfree(crp);
3025 return NULL;
3026 }
3027 return crp;
3028}
3029
3030/*
3031 * failure => all reset bets are off, nfserr_no_grace...
3032 */
3033static int
3034nfs4_client_to_reclaim(char *name, int namlen)
3035{
3036 unsigned int strhashval;
3037 struct nfs4_client_reclaim *crp = NULL;
3038
3039 dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name);
3040 crp = alloc_reclaim(namlen);
3041 if (!crp)
3042 return 0;
3043 strhashval = clientstr_hashval(name, namlen);
3044 INIT_LIST_HEAD(&crp->cr_strhash);
3045 list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
3046 memcpy(crp->cr_name.data, name, namlen);
3047 crp->cr_name.len = namlen;
3048 reclaim_str_hashtbl_size++;
3049 return 1;
3050}
3051
3052static void
3053nfs4_release_reclaim(void)
3054{
3055 struct nfs4_client_reclaim *crp = NULL;
3056 int i;
3057
3058 BUG_ON(!nfs4_reclaim_init);
3059 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3060 while (!list_empty(&reclaim_str_hashtbl[i])) {
3061 crp = list_entry(reclaim_str_hashtbl[i].next,
3062 struct nfs4_client_reclaim, cr_strhash);
3063 list_del(&crp->cr_strhash);
3064 kfree(crp->cr_name.data);
3065 kfree(crp);
3066 reclaim_str_hashtbl_size--;
3067 }
3068 }
3069 BUG_ON(reclaim_str_hashtbl_size);
3070}
3071
3072/*
3073 * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
3074struct nfs4_client_reclaim *
3075nfs4_find_reclaim_client(clientid_t *clid)
3076{
3077 unsigned int strhashval;
3078 struct nfs4_client *clp;
3079 struct nfs4_client_reclaim *crp = NULL;
3080
3081
3082 /* find clientid in conf_id_hashtbl */
3083 clp = find_confirmed_client(clid);
3084 if (clp == NULL)
3085 return NULL;
3086
3087 dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n",
3088 clp->cl_name.len, clp->cl_name.data);
3089
3090 /* find clp->cl_name in reclaim_str_hashtbl */
3091 strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
3092 list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
3093 if (cmp_name(&crp->cr_name, &clp->cl_name)) {
3094 return crp;
3095 }
3096 }
3097 return NULL;
3098}
3099
3100/*
3101* Called from OPEN. Look for clientid in reclaim list.
3102*/
3103int
3104nfs4_check_open_reclaim(clientid_t *clid)
3105{
3106 struct nfs4_client_reclaim *crp;
3107
3108 if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
3109 return nfserr_reclaim_bad;
3110 return nfs_ok;
3111}
3112
3113
3114/*
3115 * Start and stop routines
3116 */
3117
3118static void
3119__nfs4_state_init(void)
3120{
3121 int i;
3122 time_t grace_time;
3123
3124 if (!nfs4_reclaim_init) {
3125 for (i = 0; i < CLIENT_HASH_SIZE; i++)
3126 INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
3127 reclaim_str_hashtbl_size = 0;
3128 nfs4_reclaim_init = 1;
3129 }
3130 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3131 INIT_LIST_HEAD(&conf_id_hashtbl[i]);
3132 INIT_LIST_HEAD(&conf_str_hashtbl[i]);
3133 INIT_LIST_HEAD(&unconf_str_hashtbl[i]);
3134 INIT_LIST_HEAD(&unconf_id_hashtbl[i]);
3135 }
3136 for (i = 0; i < FILE_HASH_SIZE; i++) {
3137 INIT_LIST_HEAD(&file_hashtbl[i]);
3138 }
3139 for (i = 0; i < OWNER_HASH_SIZE; i++) {
3140 INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
3141 INIT_LIST_HEAD(&ownerid_hashtbl[i]);
3142 }
3143 for (i = 0; i < STATEID_HASH_SIZE; i++) {
3144 INIT_LIST_HEAD(&stateid_hashtbl[i]);
3145 INIT_LIST_HEAD(&lockstateid_hashtbl[i]);
3146 }
3147 for (i = 0; i < LOCK_HASH_SIZE; i++) {
3148 INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
3149 INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
3150 }
3151 memset(&zerostateid, 0, sizeof(stateid_t));
3152 memset(&onestateid, ~0, sizeof(stateid_t));
3153
3154 INIT_LIST_HEAD(&close_lru);
3155 INIT_LIST_HEAD(&client_lru);
3156 INIT_LIST_HEAD(&del_recall_lru);
3157 spin_lock_init(&recall_lock);
3158 boot_time = get_seconds();
3159 grace_time = max(old_lease_time, lease_time);
3160 if (reclaim_str_hashtbl_size == 0)
3161 grace_time = 0;
3162 if (grace_time)
3163 printk("NFSD: starting %ld-second grace period\n", grace_time);
3164 grace_end = boot_time + grace_time;
3165 INIT_WORK(&laundromat_work,laundromat_main, NULL);
3166 schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
3167}
3168
3169int
3170nfs4_state_init(void)
3171{
3172 int status;
3173
3174 if (nfs4_init)
3175 return 0;
3176 status = nfsd4_init_slabs();
3177 if (status)
3178 return status;
3179 __nfs4_state_init();
3180 nfs4_init = 1;
3181 return 0;
3182}
3183
3184int
3185nfs4_in_grace(void)
3186{
3187 return get_seconds() < grace_end;
3188}
3189
3190void
3191set_no_grace(void)
3192{
3193 printk("NFSD: ERROR in reboot recovery. State reclaims will fail.\n");
3194 grace_end = get_seconds();
3195}
3196
3197time_t
3198nfs4_lease_time(void)
3199{
3200 return lease_time;
3201}
3202
3203static void
3204__nfs4_state_shutdown(void)
3205{
3206 int i;
3207 struct nfs4_client *clp = NULL;
3208 struct nfs4_delegation *dp = NULL;
3209 struct nfs4_stateowner *sop = NULL;
3210 struct list_head *pos, *next, reaplist;
3211
3212 list_for_each_safe(pos, next, &close_lru) {
3213 sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
3214 list_del(&sop->so_close_lru);
3215 nfs4_put_stateowner(sop);
3216 }
3217
3218 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3219 while (!list_empty(&conf_id_hashtbl[i])) {
3220 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
3221 expire_client(clp);
3222 }
3223 while (!list_empty(&unconf_str_hashtbl[i])) {
3224 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
3225 expire_client(clp);
3226 }
3227 }
3228 INIT_LIST_HEAD(&reaplist);
3229 spin_lock(&recall_lock);
3230 list_for_each_safe(pos, next, &del_recall_lru) {
3231 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
3232 list_move(&dp->dl_recall_lru, &reaplist);
3233 }
3234 spin_unlock(&recall_lock);
3235 list_for_each_safe(pos, next, &reaplist) {
3236 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
3237 list_del_init(&dp->dl_recall_lru);
3238 unhash_delegation(dp);
3239 }
3240
3241 release_all_files();
3242 cancel_delayed_work(&laundromat_work);
3243 flush_scheduled_work();
3244 nfs4_init = 0;
3245 dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
3246 list_add_perfile, list_del_perfile);
3247 dprintk("NFSD: add_perclient %d del_perclient %d\n",
3248 add_perclient, del_perclient);
3249 dprintk("NFSD: alloc_file %d free_file %d\n",
3250 alloc_file, free_file);
3251 dprintk("NFSD: vfsopen %d vfsclose %d\n",
3252 vfsopen, vfsclose);
3253 dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
3254 alloc_delegation, free_delegation);
3255
3256}
3257
3258void
3259nfs4_state_shutdown(void)
3260{
3261 nfs4_lock_state();
3262 nfs4_release_reclaim();
3263 __nfs4_state_shutdown();
3264 nfsd4_free_slabs();
3265 nfs4_unlock_state();
3266}
3267
3268/*
3269 * Called when leasetime is changed.
3270 *
3271 * if nfsd is not started, simply set the global lease.
3272 *
3273 * if nfsd(s) are running, lease change requires nfsv4 state to be reset.
3274 * e.g: boot_time is reset, existing nfs4_client structs are
3275 * used to fill reclaim_str_hashtbl, then all state (except for the
3276 * reclaim_str_hashtbl) is re-initialized.
3277 *
3278 * if the old lease time is greater than the new lease time, the grace
3279 * period needs to be set to the old lease time to allow clients to reclaim
3280 * their state. XXX - we may want to set the grace period == lease time
3281 * after an initial grace period == old lease time
3282 *
3283 * if an error occurs in this process, the new lease is set, but the server
3284 * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
3285 * which means OPEN/LOCK/READ/WRITE will fail during grace period.
3286 *
3287 * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
3288 * OPEN and LOCK reclaims.
3289 */
3290void
3291nfs4_reset_lease(time_t leasetime)
3292{
3293 struct nfs4_client *clp;
3294 int i;
3295
3296 printk("NFSD: New leasetime %ld\n",leasetime);
3297 if (!nfs4_init)
3298 return;
3299 nfs4_lock_state();
3300 old_lease_time = lease_time;
3301 lease_time = leasetime;
3302
3303 nfs4_release_reclaim();
3304
3305 /* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
3306 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
3307 list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
3308 if (!nfs4_client_to_reclaim(clp->cl_name.data,
3309 clp->cl_name.len)) {
3310 nfs4_release_reclaim();
3311 goto init_state;
3312 }
3313 }
3314 }
3315init_state:
3316 __nfs4_state_shutdown();
3317 __nfs4_state_init();
3318 nfs4_unlock_state();
3319}
3320
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
new file mode 100644
index 000000000000..36a058a112d5
--- /dev/null
+++ b/fs/nfsd/nfs4xdr.c
@@ -0,0 +1,2536 @@
1/*
2 * fs/nfs/nfs4xdr.c
3 *
4 * Server-side XDR for NFSv4
5 *
6 * Copyright (c) 2002 The Regents of the University of Michigan.
7 * All rights reserved.
8 *
9 * Kendrick Smith <kmsmith@umich.edu>
10 * Andy Adamson <andros@umich.edu>
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * TODO: Neil Brown made the following observation: We currently
38 * initially reserve NFSD_BUFSIZE space on the transmit queue and
39 * never release any of that until the request is complete.
40 * It would be good to calculate a new maximum response size while
41 * decoding the COMPOUND, and call svc_reserve with this number
42 * at the end of nfs4svc_decode_compoundargs.
43 */
44
45#include <linux/param.h>
46#include <linux/smp.h>
47#include <linux/smp_lock.h>
48#include <linux/fs.h>
49#include <linux/namei.h>
50#include <linux/vfs.h>
51#include <linux/sunrpc/xdr.h>
52#include <linux/sunrpc/svc.h>
53#include <linux/sunrpc/clnt.h>
54#include <linux/nfsd/nfsd.h>
55#include <linux/nfsd/state.h>
56#include <linux/nfsd/xdr4.h>
57#include <linux/nfsd_idmap.h>
58#include <linux/nfs4.h>
59#include <linux/nfs4_acl.h>
60
61#define NFSDDBG_FACILITY NFSDDBG_XDR
62
63static int
64check_filename(char *str, int len, int err)
65{
66 int i;
67
68 if (len == 0)
69 return nfserr_inval;
70 if (isdotent(str, len))
71 return err;
72 for (i = 0; i < len; i++)
73 if (str[i] == '/')
74 return err;
75 return 0;
76}
77
78/*
79 * START OF "GENERIC" DECODE ROUTINES.
80 * These may look a little ugly since they are imported from a "generic"
81 * set of XDR encode/decode routines which are intended to be shared by
82 * all of our NFSv4 implementations (OpenBSD, MacOS X...).
83 *
84 * If the pain of reading these is too great, it should be a straightforward
85 * task to translate them into Linux-specific versions which are more
86 * consistent with the style used in NFSv2/v3...
87 */
88#define DECODE_HEAD \
89 u32 *p; \
90 int status
91#define DECODE_TAIL \
92 status = 0; \
93out: \
94 return status; \
95xdr_error: \
96 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
97 status = nfserr_bad_xdr; \
98 goto out
99
100#define READ32(x) (x) = ntohl(*p++)
101#define READ64(x) do { \
102 (x) = (u64)ntohl(*p++) << 32; \
103 (x) |= ntohl(*p++); \
104} while (0)
105#define READTIME(x) do { \
106 p++; \
107 (x) = ntohl(*p++); \
108 p++; \
109} while (0)
110#define READMEM(x,nbytes) do { \
111 x = (char *)p; \
112 p += XDR_QUADLEN(nbytes); \
113} while (0)
114#define SAVEMEM(x,nbytes) do { \
115 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
116 savemem(argp, p, nbytes) : \
117 (char *)p)) { \
118 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
119 goto xdr_error; \
120 } \
121 p += XDR_QUADLEN(nbytes); \
122} while (0)
123#define COPYMEM(x,nbytes) do { \
124 memcpy((x), p, nbytes); \
125 p += XDR_QUADLEN(nbytes); \
126} while (0)
127
128/* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */
129#define READ_BUF(nbytes) do { \
130 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \
131 p = argp->p; \
132 argp->p += XDR_QUADLEN(nbytes); \
133 } else if (!(p = read_buf(argp, nbytes))) { \
134 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
135 goto xdr_error; \
136 } \
137} while (0)
138
139u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
140{
141 /* We want more bytes than seem to be available.
142 * Maybe we need a new page, maybe we have just run out
143 */
144 int avail = (char*)argp->end - (char*)argp->p;
145 u32 *p;
146 if (avail + argp->pagelen < nbytes)
147 return NULL;
148 if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
149 return NULL;
150 /* ok, we can do it with the current plus the next page */
151 if (nbytes <= sizeof(argp->tmp))
152 p = argp->tmp;
153 else {
154 if (argp->tmpp)
155 kfree(argp->tmpp);
156 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
157 if (!p)
158 return NULL;
159
160 }
161 memcpy(p, argp->p, avail);
162 /* step to next page */
163 argp->p = page_address(argp->pagelist[0]);
164 argp->pagelist++;
165 if (argp->pagelen < PAGE_SIZE) {
166 argp->end = p + (argp->pagelen>>2);
167 argp->pagelen = 0;
168 } else {
169 argp->end = p + (PAGE_SIZE>>2);
170 argp->pagelen -= PAGE_SIZE;
171 }
172 memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
173 argp->p += XDR_QUADLEN(nbytes - avail);
174 return p;
175}
176
177static int
178defer_free(struct nfsd4_compoundargs *argp,
179 void (*release)(const void *), void *p)
180{
181 struct tmpbuf *tb;
182
183 tb = kmalloc(sizeof(*tb), GFP_KERNEL);
184 if (!tb)
185 return -ENOMEM;
186 tb->buf = p;
187 tb->release = release;
188 tb->next = argp->to_free;
189 argp->to_free = tb;
190 return 0;
191}
192
193char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
194{
195 void *new = NULL;
196 if (p == argp->tmp) {
197 new = kmalloc(nbytes, GFP_KERNEL);
198 if (!new) return NULL;
199 p = new;
200 memcpy(p, argp->tmp, nbytes);
201 } else {
202 if (p != argp->tmpp)
203 BUG();
204 argp->tmpp = NULL;
205 }
206 if (defer_free(argp, kfree, p)) {
207 kfree(new);
208 return NULL;
209 } else
210 return (char *)p;
211}
212
213
214static int
215nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
216{
217 u32 bmlen;
218 DECODE_HEAD;
219
220 bmval[0] = 0;
221 bmval[1] = 0;
222
223 READ_BUF(4);
224 READ32(bmlen);
225 if (bmlen > 1000)
226 goto xdr_error;
227
228 READ_BUF(bmlen << 2);
229 if (bmlen > 0)
230 READ32(bmval[0]);
231 if (bmlen > 1)
232 READ32(bmval[1]);
233
234 DECODE_TAIL;
235}
236
237static int
238nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr,
239 struct nfs4_acl **acl)
240{
241 int expected_len, len = 0;
242 u32 dummy32;
243 char *buf;
244
245 DECODE_HEAD;
246 iattr->ia_valid = 0;
247 if ((status = nfsd4_decode_bitmap(argp, bmval)))
248 return status;
249
250 /*
251 * According to spec, unsupported attributes return ERR_NOTSUPP;
252 * read-only attributes return ERR_INVAL.
253 */
254 if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
255 return nfserr_attrnotsupp;
256 if ((bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0) || (bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1))
257 return nfserr_inval;
258
259 READ_BUF(4);
260 READ32(expected_len);
261
262 if (bmval[0] & FATTR4_WORD0_SIZE) {
263 READ_BUF(8);
264 len += 8;
265 READ64(iattr->ia_size);
266 iattr->ia_valid |= ATTR_SIZE;
267 }
268 if (bmval[0] & FATTR4_WORD0_ACL) {
269 int nace, i;
270 struct nfs4_ace ace;
271
272 READ_BUF(4); len += 4;
273 READ32(nace);
274
275 *acl = nfs4_acl_new();
276 if (*acl == NULL) {
277 status = -ENOMEM;
278 goto out_nfserr;
279 }
280 defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl);
281
282 for (i = 0; i < nace; i++) {
283 READ_BUF(16); len += 16;
284 READ32(ace.type);
285 READ32(ace.flag);
286 READ32(ace.access_mask);
287 READ32(dummy32);
288 READ_BUF(dummy32);
289 len += XDR_QUADLEN(dummy32) << 2;
290 READMEM(buf, dummy32);
291 ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
292 status = 0;
293 if (ace.whotype != NFS4_ACL_WHO_NAMED)
294 ace.who = 0;
295 else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP)
296 status = nfsd_map_name_to_gid(argp->rqstp,
297 buf, dummy32, &ace.who);
298 else
299 status = nfsd_map_name_to_uid(argp->rqstp,
300 buf, dummy32, &ace.who);
301 if (status)
302 goto out_nfserr;
303 if (nfs4_acl_add_ace(*acl, ace.type, ace.flag,
304 ace.access_mask, ace.whotype, ace.who) != 0) {
305 status = -ENOMEM;
306 goto out_nfserr;
307 }
308 }
309 } else
310 *acl = NULL;
311 if (bmval[1] & FATTR4_WORD1_MODE) {
312 READ_BUF(4);
313 len += 4;
314 READ32(iattr->ia_mode);
315 iattr->ia_mode &= (S_IFMT | S_IALLUGO);
316 iattr->ia_valid |= ATTR_MODE;
317 }
318 if (bmval[1] & FATTR4_WORD1_OWNER) {
319 READ_BUF(4);
320 len += 4;
321 READ32(dummy32);
322 READ_BUF(dummy32);
323 len += (XDR_QUADLEN(dummy32) << 2);
324 READMEM(buf, dummy32);
325 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
326 goto out_nfserr;
327 iattr->ia_valid |= ATTR_UID;
328 }
329 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
330 READ_BUF(4);
331 len += 4;
332 READ32(dummy32);
333 READ_BUF(dummy32);
334 len += (XDR_QUADLEN(dummy32) << 2);
335 READMEM(buf, dummy32);
336 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
337 goto out_nfserr;
338 iattr->ia_valid |= ATTR_GID;
339 }
340 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
341 READ_BUF(4);
342 len += 4;
343 READ32(dummy32);
344 switch (dummy32) {
345 case NFS4_SET_TO_CLIENT_TIME:
346 /* We require the high 32 bits of 'seconds' to be 0, and we ignore
347 all 32 bits of 'nseconds'. */
348 READ_BUF(12);
349 len += 12;
350 READ32(dummy32);
351 if (dummy32)
352 return nfserr_inval;
353 READ32(iattr->ia_atime.tv_sec);
354 READ32(iattr->ia_atime.tv_nsec);
355 if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
356 return nfserr_inval;
357 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
358 break;
359 case NFS4_SET_TO_SERVER_TIME:
360 iattr->ia_valid |= ATTR_ATIME;
361 break;
362 default:
363 goto xdr_error;
364 }
365 }
366 if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
367 /* We require the high 32 bits of 'seconds' to be 0, and we ignore
368 all 32 bits of 'nseconds'. */
369 READ_BUF(12);
370 len += 12;
371 READ32(dummy32);
372 if (dummy32)
373 return nfserr_inval;
374 READ32(iattr->ia_ctime.tv_sec);
375 READ32(iattr->ia_ctime.tv_nsec);
376 if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
377 return nfserr_inval;
378 iattr->ia_valid |= ATTR_CTIME;
379 }
380 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
381 READ_BUF(4);
382 len += 4;
383 READ32(dummy32);
384 switch (dummy32) {
385 case NFS4_SET_TO_CLIENT_TIME:
386 /* We require the high 32 bits of 'seconds' to be 0, and we ignore
387 all 32 bits of 'nseconds'. */
388 READ_BUF(12);
389 len += 12;
390 READ32(dummy32);
391 if (dummy32)
392 return nfserr_inval;
393 READ32(iattr->ia_mtime.tv_sec);
394 READ32(iattr->ia_mtime.tv_nsec);
395 if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
396 return nfserr_inval;
397 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
398 break;
399 case NFS4_SET_TO_SERVER_TIME:
400 iattr->ia_valid |= ATTR_MTIME;
401 break;
402 default:
403 goto xdr_error;
404 }
405 }
406 if (len != expected_len)
407 goto xdr_error;
408
409 DECODE_TAIL;
410
411out_nfserr:
412 status = nfserrno(status);
413 goto out;
414}
415
416static int
417nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
418{
419 DECODE_HEAD;
420
421 READ_BUF(4);
422 READ32(access->ac_req_access);
423
424 DECODE_TAIL;
425}
426
427static int
428nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
429{
430 DECODE_HEAD;
431
432 close->cl_stateowner = NULL;
433 READ_BUF(4 + sizeof(stateid_t));
434 READ32(close->cl_seqid);
435 READ32(close->cl_stateid.si_generation);
436 COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
437
438 DECODE_TAIL;
439}
440
441
442static int
443nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
444{
445 DECODE_HEAD;
446
447 READ_BUF(12);
448 READ64(commit->co_offset);
449 READ32(commit->co_count);
450
451 DECODE_TAIL;
452}
453
454static int
455nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
456{
457 DECODE_HEAD;
458
459 READ_BUF(4);
460 READ32(create->cr_type);
461 switch (create->cr_type) {
462 case NF4LNK:
463 READ_BUF(4);
464 READ32(create->cr_linklen);
465 READ_BUF(create->cr_linklen);
466 SAVEMEM(create->cr_linkname, create->cr_linklen);
467 break;
468 case NF4BLK:
469 case NF4CHR:
470 READ_BUF(8);
471 READ32(create->cr_specdata1);
472 READ32(create->cr_specdata2);
473 break;
474 case NF4SOCK:
475 case NF4FIFO:
476 case NF4DIR:
477 default:
478 break;
479 }
480
481 READ_BUF(4);
482 READ32(create->cr_namelen);
483 READ_BUF(create->cr_namelen);
484 SAVEMEM(create->cr_name, create->cr_namelen);
485 if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
486 return status;
487
488 if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, &create->cr_acl)))
489 goto out;
490
491 DECODE_TAIL;
492}
493
494static inline int
495nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
496{
497 DECODE_HEAD;
498
499 READ_BUF(sizeof(stateid_t));
500 READ32(dr->dr_stateid.si_generation);
501 COPYMEM(&dr->dr_stateid.si_opaque, sizeof(stateid_opaque_t));
502
503 DECODE_TAIL;
504}
505
506static inline int
507nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
508{
509 return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
510}
511
512static int
513nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
514{
515 DECODE_HEAD;
516
517 READ_BUF(4);
518 READ32(link->li_namelen);
519 READ_BUF(link->li_namelen);
520 SAVEMEM(link->li_name, link->li_namelen);
521 if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval)))
522 return status;
523
524 DECODE_TAIL;
525}
526
527static int
528nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
529{
530 DECODE_HEAD;
531
532 lock->lk_stateowner = NULL;
533 /*
534 * type, reclaim(boolean), offset, length, new_lock_owner(boolean)
535 */
536 READ_BUF(28);
537 READ32(lock->lk_type);
538 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
539 goto xdr_error;
540 READ32(lock->lk_reclaim);
541 READ64(lock->lk_offset);
542 READ64(lock->lk_length);
543 READ32(lock->lk_is_new);
544
545 if (lock->lk_is_new) {
546 READ_BUF(36);
547 READ32(lock->lk_new_open_seqid);
548 READ32(lock->lk_new_open_stateid.si_generation);
549
550 COPYMEM(&lock->lk_new_open_stateid.si_opaque, sizeof(stateid_opaque_t));
551 READ32(lock->lk_new_lock_seqid);
552 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
553 READ32(lock->lk_new_owner.len);
554 READ_BUF(lock->lk_new_owner.len);
555 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
556 } else {
557 READ_BUF(20);
558 READ32(lock->lk_old_lock_stateid.si_generation);
559 COPYMEM(&lock->lk_old_lock_stateid.si_opaque, sizeof(stateid_opaque_t));
560 READ32(lock->lk_old_lock_seqid);
561 }
562
563 DECODE_TAIL;
564}
565
566static int
567nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
568{
569 DECODE_HEAD;
570
571 READ_BUF(32);
572 READ32(lockt->lt_type);
573 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
574 goto xdr_error;
575 READ64(lockt->lt_offset);
576 READ64(lockt->lt_length);
577 COPYMEM(&lockt->lt_clientid, 8);
578 READ32(lockt->lt_owner.len);
579 READ_BUF(lockt->lt_owner.len);
580 READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
581
582 DECODE_TAIL;
583}
584
585static int
586nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
587{
588 DECODE_HEAD;
589
590 locku->lu_stateowner = NULL;
591 READ_BUF(24 + sizeof(stateid_t));
592 READ32(locku->lu_type);
593 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
594 goto xdr_error;
595 READ32(locku->lu_seqid);
596 READ32(locku->lu_stateid.si_generation);
597 COPYMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
598 READ64(locku->lu_offset);
599 READ64(locku->lu_length);
600
601 DECODE_TAIL;
602}
603
604static int
605nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
606{
607 DECODE_HEAD;
608
609 READ_BUF(4);
610 READ32(lookup->lo_len);
611 READ_BUF(lookup->lo_len);
612 SAVEMEM(lookup->lo_name, lookup->lo_len);
613 if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent)))
614 return status;
615
616 DECODE_TAIL;
617}
618
619static int
620nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
621{
622 DECODE_HEAD;
623
624 memset(open->op_bmval, 0, sizeof(open->op_bmval));
625 open->op_iattr.ia_valid = 0;
626 open->op_stateowner = NULL;
627
628 /* seqid, share_access, share_deny, clientid, ownerlen */
629 READ_BUF(16 + sizeof(clientid_t));
630 READ32(open->op_seqid);
631 READ32(open->op_share_access);
632 READ32(open->op_share_deny);
633 COPYMEM(&open->op_clientid, sizeof(clientid_t));
634 READ32(open->op_owner.len);
635
636 /* owner, open_flag */
637 READ_BUF(open->op_owner.len + 4);
638 SAVEMEM(open->op_owner.data, open->op_owner.len);
639 READ32(open->op_create);
640 switch (open->op_create) {
641 case NFS4_OPEN_NOCREATE:
642 break;
643 case NFS4_OPEN_CREATE:
644 READ_BUF(4);
645 READ32(open->op_createmode);
646 switch (open->op_createmode) {
647 case NFS4_CREATE_UNCHECKED:
648 case NFS4_CREATE_GUARDED:
649 if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr, &open->op_acl)))
650 goto out;
651 break;
652 case NFS4_CREATE_EXCLUSIVE:
653 READ_BUF(8);
654 COPYMEM(open->op_verf.data, 8);
655 break;
656 default:
657 goto xdr_error;
658 }
659 break;
660 default:
661 goto xdr_error;
662 }
663
664 /* open_claim */
665 READ_BUF(4);
666 READ32(open->op_claim_type);
667 switch (open->op_claim_type) {
668 case NFS4_OPEN_CLAIM_NULL:
669 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
670 READ_BUF(4);
671 READ32(open->op_fname.len);
672 READ_BUF(open->op_fname.len);
673 SAVEMEM(open->op_fname.data, open->op_fname.len);
674 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
675 return status;
676 break;
677 case NFS4_OPEN_CLAIM_PREVIOUS:
678 READ_BUF(4);
679 READ32(open->op_delegate_type);
680 break;
681 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
682 READ_BUF(sizeof(stateid_t) + 4);
683 COPYMEM(&open->op_delegate_stateid, sizeof(stateid_t));
684 READ32(open->op_fname.len);
685 READ_BUF(open->op_fname.len);
686 SAVEMEM(open->op_fname.data, open->op_fname.len);
687 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
688 return status;
689 break;
690 default:
691 goto xdr_error;
692 }
693
694 DECODE_TAIL;
695}
696
697static int
698nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
699{
700 DECODE_HEAD;
701
702 open_conf->oc_stateowner = NULL;
703 READ_BUF(4 + sizeof(stateid_t));
704 READ32(open_conf->oc_req_stateid.si_generation);
705 COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t));
706 READ32(open_conf->oc_seqid);
707
708 DECODE_TAIL;
709}
710
711static int
712nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
713{
714 DECODE_HEAD;
715
716 open_down->od_stateowner = NULL;
717 READ_BUF(12 + sizeof(stateid_t));
718 READ32(open_down->od_stateid.si_generation);
719 COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t));
720 READ32(open_down->od_seqid);
721 READ32(open_down->od_share_access);
722 READ32(open_down->od_share_deny);
723
724 DECODE_TAIL;
725}
726
727static int
728nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
729{
730 DECODE_HEAD;
731
732 READ_BUF(4);
733 READ32(putfh->pf_fhlen);
734 if (putfh->pf_fhlen > NFS4_FHSIZE)
735 goto xdr_error;
736 READ_BUF(putfh->pf_fhlen);
737 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
738
739 DECODE_TAIL;
740}
741
742static int
743nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
744{
745 DECODE_HEAD;
746
747 READ_BUF(sizeof(stateid_t) + 12);
748 READ32(read->rd_stateid.si_generation);
749 COPYMEM(&read->rd_stateid.si_opaque, sizeof(stateid_opaque_t));
750 READ64(read->rd_offset);
751 READ32(read->rd_length);
752
753 DECODE_TAIL;
754}
755
756static int
757nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
758{
759 DECODE_HEAD;
760
761 READ_BUF(24);
762 READ64(readdir->rd_cookie);
763 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
764 READ32(readdir->rd_dircount); /* just in case you needed a useless field... */
765 READ32(readdir->rd_maxcount);
766 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
767 goto out;
768
769 DECODE_TAIL;
770}
771
772static int
773nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
774{
775 DECODE_HEAD;
776
777 READ_BUF(4);
778 READ32(remove->rm_namelen);
779 READ_BUF(remove->rm_namelen);
780 SAVEMEM(remove->rm_name, remove->rm_namelen);
781 if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent)))
782 return status;
783
784 DECODE_TAIL;
785}
786
787static int
788nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
789{
790 DECODE_HEAD;
791
792 READ_BUF(4);
793 READ32(rename->rn_snamelen);
794 READ_BUF(rename->rn_snamelen + 4);
795 SAVEMEM(rename->rn_sname, rename->rn_snamelen);
796 READ32(rename->rn_tnamelen);
797 READ_BUF(rename->rn_tnamelen);
798 SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
799 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent)))
800 return status;
801 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval)))
802 return status;
803
804 DECODE_TAIL;
805}
806
807static int
808nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
809{
810 DECODE_HEAD;
811
812 READ_BUF(sizeof(clientid_t));
813 COPYMEM(clientid, sizeof(clientid_t));
814
815 DECODE_TAIL;
816}
817
818static int
819nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
820{
821 DECODE_HEAD;
822
823 READ_BUF(sizeof(stateid_t));
824 READ32(setattr->sa_stateid.si_generation);
825 COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
826 if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl)))
827 goto out;
828
829 DECODE_TAIL;
830}
831
832static int
833nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
834{
835 DECODE_HEAD;
836
837 READ_BUF(12);
838 COPYMEM(setclientid->se_verf.data, 8);
839 READ32(setclientid->se_namelen);
840
841 READ_BUF(setclientid->se_namelen + 8);
842 SAVEMEM(setclientid->se_name, setclientid->se_namelen);
843 READ32(setclientid->se_callback_prog);
844 READ32(setclientid->se_callback_netid_len);
845
846 READ_BUF(setclientid->se_callback_netid_len + 4);
847 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
848 READ32(setclientid->se_callback_addr_len);
849
850 READ_BUF(setclientid->se_callback_addr_len + 4);
851 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
852 READ32(setclientid->se_callback_ident);
853
854 DECODE_TAIL;
855}
856
857static int
858nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
859{
860 DECODE_HEAD;
861
862 READ_BUF(8 + sizeof(nfs4_verifier));
863 COPYMEM(&scd_c->sc_clientid, 8);
864 COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
865
866 DECODE_TAIL;
867}
868
869/* Also used for NVERIFY */
870static int
871nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
872{
873#if 0
874 struct nfsd4_compoundargs save = {
875 .p = argp->p,
876 .end = argp->end,
877 .rqstp = argp->rqstp,
878 };
879 u32 ve_bmval[2];
880 struct iattr ve_iattr; /* request */
881 struct nfs4_acl *ve_acl; /* request */
882#endif
883 DECODE_HEAD;
884
885 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
886 goto out;
887
888 /* For convenience's sake, we compare raw xdr'd attributes in
889 * nfsd4_proc_verify; however we still decode here just to return
890 * correct error in case of bad xdr. */
891#if 0
892 status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
893 if (status == nfserr_inval) {
894 status = nfserrno(status);
895 goto out;
896 }
897#endif
898 READ_BUF(4);
899 READ32(verify->ve_attrlen);
900 READ_BUF(verify->ve_attrlen);
901 SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
902
903 DECODE_TAIL;
904}
905
906static int
907nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
908{
909 int avail;
910 int v;
911 int len;
912 DECODE_HEAD;
913
914 READ_BUF(sizeof(stateid_opaque_t) + 20);
915 READ32(write->wr_stateid.si_generation);
916 COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t));
917 READ64(write->wr_offset);
918 READ32(write->wr_stable_how);
919 if (write->wr_stable_how > 2)
920 goto xdr_error;
921 READ32(write->wr_buflen);
922
923 /* Sorry .. no magic macros for this.. *
924 * READ_BUF(write->wr_buflen);
925 * SAVEMEM(write->wr_buf, write->wr_buflen);
926 */
927 avail = (char*)argp->end - (char*)argp->p;
928 if (avail + argp->pagelen < write->wr_buflen) {
929 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__);
930 goto xdr_error;
931 }
932 write->wr_vec[0].iov_base = p;
933 write->wr_vec[0].iov_len = avail;
934 v = 0;
935 len = write->wr_buflen;
936 while (len > write->wr_vec[v].iov_len) {
937 len -= write->wr_vec[v].iov_len;
938 v++;
939 write->wr_vec[v].iov_base = page_address(argp->pagelist[0]);
940 argp->pagelist++;
941 if (argp->pagelen >= PAGE_SIZE) {
942 write->wr_vec[v].iov_len = PAGE_SIZE;
943 argp->pagelen -= PAGE_SIZE;
944 } else {
945 write->wr_vec[v].iov_len = argp->pagelen;
946 argp->pagelen -= len;
947 }
948 }
949 argp->end = (u32*) (write->wr_vec[v].iov_base + write->wr_vec[v].iov_len);
950 argp->p = (u32*) (write->wr_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
951 write->wr_vec[v].iov_len = len;
952 write->wr_vlen = v+1;
953
954 DECODE_TAIL;
955}
956
957static int
958nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
959{
960 DECODE_HEAD;
961
962 READ_BUF(12);
963 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
964 READ32(rlockowner->rl_owner.len);
965 READ_BUF(rlockowner->rl_owner.len);
966 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
967
968 DECODE_TAIL;
969}
970
971static int
972nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
973{
974 DECODE_HEAD;
975 struct nfsd4_op *op;
976 int i;
977
978 /*
979 * XXX: According to spec, we should check the tag
980 * for UTF-8 compliance. I'm postponing this for
981 * now because it seems that some clients do use
982 * binary tags.
983 */
984 READ_BUF(4);
985 READ32(argp->taglen);
986 READ_BUF(argp->taglen + 8);
987 SAVEMEM(argp->tag, argp->taglen);
988 READ32(argp->minorversion);
989 READ32(argp->opcnt);
990
991 if (argp->taglen > NFSD4_MAX_TAGLEN)
992 goto xdr_error;
993 if (argp->opcnt > 100)
994 goto xdr_error;
995
996 if (argp->opcnt > sizeof(argp->iops)/sizeof(argp->iops[0])) {
997 argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
998 if (!argp->ops) {
999 argp->ops = argp->iops;
1000 printk(KERN_INFO "nfsd: couldn't allocate room for COMPOUND\n");
1001 goto xdr_error;
1002 }
1003 }
1004
1005 for (i = 0; i < argp->opcnt; i++) {
1006 op = &argp->ops[i];
1007 op->replay = NULL;
1008
1009 /*
1010 * We can't use READ_BUF() here because we need to handle
1011 * a missing opcode as an OP_WRITE + 1. So we need to check
1012 * to see if we're truly at the end of our buffer or if there
1013 * is another page we need to flip to.
1014 */
1015
1016 if (argp->p == argp->end) {
1017 if (argp->pagelen < 4) {
1018 /* There isn't an opcode still on the wire */
1019 op->opnum = OP_WRITE + 1;
1020 op->status = nfserr_bad_xdr;
1021 argp->opcnt = i+1;
1022 break;
1023 }
1024
1025 /*
1026 * False alarm. We just hit a page boundary, but there
1027 * is still data available. Move pointer across page
1028 * boundary. *snip from READ_BUF*
1029 */
1030 argp->p = page_address(argp->pagelist[0]);
1031 argp->pagelist++;
1032 if (argp->pagelen < PAGE_SIZE) {
1033 argp->end = p + (argp->pagelen>>2);
1034 argp->pagelen = 0;
1035 } else {
1036 argp->end = p + (PAGE_SIZE>>2);
1037 argp->pagelen -= PAGE_SIZE;
1038 }
1039 }
1040 op->opnum = ntohl(*argp->p++);
1041
1042 switch (op->opnum) {
1043 case 2: /* Reserved operation */
1044 op->opnum = OP_ILLEGAL;
1045 if (argp->minorversion == 0)
1046 op->status = nfserr_op_illegal;
1047 else
1048 op->status = nfserr_minor_vers_mismatch;
1049 break;
1050 case OP_ACCESS:
1051 op->status = nfsd4_decode_access(argp, &op->u.access);
1052 break;
1053 case OP_CLOSE:
1054 op->status = nfsd4_decode_close(argp, &op->u.close);
1055 break;
1056 case OP_COMMIT:
1057 op->status = nfsd4_decode_commit(argp, &op->u.commit);
1058 break;
1059 case OP_CREATE:
1060 op->status = nfsd4_decode_create(argp, &op->u.create);
1061 break;
1062 case OP_DELEGRETURN:
1063 op->status = nfsd4_decode_delegreturn(argp, &op->u.delegreturn);
1064 break;
1065 case OP_GETATTR:
1066 op->status = nfsd4_decode_getattr(argp, &op->u.getattr);
1067 break;
1068 case OP_GETFH:
1069 op->status = nfs_ok;
1070 break;
1071 case OP_LINK:
1072 op->status = nfsd4_decode_link(argp, &op->u.link);
1073 break;
1074 case OP_LOCK:
1075 op->status = nfsd4_decode_lock(argp, &op->u.lock);
1076 break;
1077 case OP_LOCKT:
1078 op->status = nfsd4_decode_lockt(argp, &op->u.lockt);
1079 break;
1080 case OP_LOCKU:
1081 op->status = nfsd4_decode_locku(argp, &op->u.locku);
1082 break;
1083 case OP_LOOKUP:
1084 op->status = nfsd4_decode_lookup(argp, &op->u.lookup);
1085 break;
1086 case OP_LOOKUPP:
1087 op->status = nfs_ok;
1088 break;
1089 case OP_NVERIFY:
1090 op->status = nfsd4_decode_verify(argp, &op->u.nverify);
1091 break;
1092 case OP_OPEN:
1093 op->status = nfsd4_decode_open(argp, &op->u.open);
1094 break;
1095 case OP_OPEN_CONFIRM:
1096 op->status = nfsd4_decode_open_confirm(argp, &op->u.open_confirm);
1097 break;
1098 case OP_OPEN_DOWNGRADE:
1099 op->status = nfsd4_decode_open_downgrade(argp, &op->u.open_downgrade);
1100 break;
1101 case OP_PUTFH:
1102 op->status = nfsd4_decode_putfh(argp, &op->u.putfh);
1103 break;
1104 case OP_PUTROOTFH:
1105 op->status = nfs_ok;
1106 break;
1107 case OP_READ:
1108 op->status = nfsd4_decode_read(argp, &op->u.read);
1109 break;
1110 case OP_READDIR:
1111 op->status = nfsd4_decode_readdir(argp, &op->u.readdir);
1112 break;
1113 case OP_READLINK:
1114 op->status = nfs_ok;
1115 break;
1116 case OP_REMOVE:
1117 op->status = nfsd4_decode_remove(argp, &op->u.remove);
1118 break;
1119 case OP_RENAME:
1120 op->status = nfsd4_decode_rename(argp, &op->u.rename);
1121 break;
1122 case OP_RESTOREFH:
1123 op->status = nfs_ok;
1124 break;
1125 case OP_RENEW:
1126 op->status = nfsd4_decode_renew(argp, &op->u.renew);
1127 break;
1128 case OP_SAVEFH:
1129 op->status = nfs_ok;
1130 break;
1131 case OP_SETATTR:
1132 op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
1133 break;
1134 case OP_SETCLIENTID:
1135 op->status = nfsd4_decode_setclientid(argp, &op->u.setclientid);
1136 break;
1137 case OP_SETCLIENTID_CONFIRM:
1138 op->status = nfsd4_decode_setclientid_confirm(argp, &op->u.setclientid_confirm);
1139 break;
1140 case OP_VERIFY:
1141 op->status = nfsd4_decode_verify(argp, &op->u.verify);
1142 break;
1143 case OP_WRITE:
1144 op->status = nfsd4_decode_write(argp, &op->u.write);
1145 break;
1146 case OP_RELEASE_LOCKOWNER:
1147 op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner);
1148 break;
1149 default:
1150 op->opnum = OP_ILLEGAL;
1151 op->status = nfserr_op_illegal;
1152 break;
1153 }
1154
1155 if (op->status) {
1156 argp->opcnt = i+1;
1157 break;
1158 }
1159 }
1160
1161 DECODE_TAIL;
1162}
1163/*
1164 * END OF "GENERIC" DECODE ROUTINES.
1165 */
1166
1167/*
1168 * START OF "GENERIC" ENCODE ROUTINES.
1169 * These may look a little ugly since they are imported from a "generic"
1170 * set of XDR encode/decode routines which are intended to be shared by
1171 * all of our NFSv4 implementations (OpenBSD, MacOS X...).
1172 *
1173 * If the pain of reading these is too great, it should be a straightforward
1174 * task to translate them into Linux-specific versions which are more
1175 * consistent with the style used in NFSv2/v3...
1176 */
1177#define ENCODE_HEAD u32 *p
1178
1179#define WRITE32(n) *p++ = htonl(n)
1180#define WRITE64(n) do { \
1181 *p++ = htonl((u32)((n) >> 32)); \
1182 *p++ = htonl((u32)(n)); \
1183} while (0)
1184#define WRITEMEM(ptr,nbytes) do { \
1185 *(p + XDR_QUADLEN(nbytes) -1) = 0; \
1186 memcpy(p, ptr, nbytes); \
1187 p += XDR_QUADLEN(nbytes); \
1188} while (0)
1189#define WRITECINFO(c) do { \
1190 *p++ = htonl(c.atomic); \
1191 *p++ = htonl(c.before_ctime_sec); \
1192 *p++ = htonl(c.before_ctime_nsec); \
1193 *p++ = htonl(c.after_ctime_sec); \
1194 *p++ = htonl(c.after_ctime_nsec); \
1195} while (0)
1196
1197#define RESERVE_SPACE(nbytes) do { \
1198 p = resp->p; \
1199 BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end); \
1200} while (0)
1201#define ADJUST_ARGS() resp->p = p
1202
1203/*
1204 * Header routine to setup seqid operation replay cache
1205 */
1206#define ENCODE_SEQID_OP_HEAD \
1207 u32 *p; \
1208 u32 *save; \
1209 \
1210 save = resp->p;
1211
1212/*
1213 * Routine for encoding the result of a
1214 * "seqid-mutating" NFSv4 operation. This is
1215 * where seqids are incremented, and the
1216 * replay cache is filled.
1217 */
1218
1219#define ENCODE_SEQID_OP_TAIL(stateowner) do { \
1220 if (seqid_mutating_err(nfserr) && stateowner) { \
1221 if (stateowner->so_confirmed) \
1222 stateowner->so_seqid++; \
1223 stateowner->so_replay.rp_status = nfserr; \
1224 stateowner->so_replay.rp_buflen = \
1225 (((char *)(resp)->p - (char *)save)); \
1226 memcpy(stateowner->so_replay.rp_buf, save, \
1227 stateowner->so_replay.rp_buflen); \
1228 } } while (0);
1229
1230
1231static u32 nfs4_ftypes[16] = {
1232 NF4BAD, NF4FIFO, NF4CHR, NF4BAD,
1233 NF4DIR, NF4BAD, NF4BLK, NF4BAD,
1234 NF4REG, NF4BAD, NF4LNK, NF4BAD,
1235 NF4SOCK, NF4BAD, NF4LNK, NF4BAD,
1236};
1237
1238static int
1239nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1240 u32 **p, int *buflen)
1241{
1242 int status;
1243
1244 if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1245 return nfserr_resource;
1246 if (whotype != NFS4_ACL_WHO_NAMED)
1247 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
1248 else if (group)
1249 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
1250 else
1251 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
1252 if (status < 0)
1253 return nfserrno(status);
1254 *p = xdr_encode_opaque(*p, NULL, status);
1255 *buflen -= (XDR_QUADLEN(status) << 2) + 4;
1256 BUG_ON(*buflen < 0);
1257 return 0;
1258}
1259
1260static inline int
1261nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen)
1262{
1263 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
1264}
1265
1266static inline int
1267nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen)
1268{
1269 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
1270}
1271
1272static inline int
1273nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1274 u32 **p, int *buflen)
1275{
1276 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
1277}
1278
1279
1280/*
1281 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
1282 * ourselves.
1283 *
1284 * @countp is the buffer size in _words_; upon successful return this becomes
1285 * replaced with the number of words written.
1286 */
1287int
1288nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1289 struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval,
1290 struct svc_rqst *rqstp)
1291{
1292 u32 bmval0 = bmval[0];
1293 u32 bmval1 = bmval[1];
1294 struct kstat stat;
1295 struct svc_fh tempfh;
1296 struct kstatfs statfs;
1297 int buflen = *countp << 2;
1298 u32 *attrlenp;
1299 u32 dummy;
1300 u64 dummy64;
1301 u32 *p = buffer;
1302 int status;
1303 int aclsupport = 0;
1304 struct nfs4_acl *acl = NULL;
1305
1306 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
1307 BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
1308 BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
1309
1310 status = vfs_getattr(exp->ex_mnt, dentry, &stat);
1311 if (status)
1312 goto out_nfserr;
1313 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
1314 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
1315 FATTR4_WORD1_SPACE_TOTAL))) {
1316 status = vfs_statfs(dentry->d_inode->i_sb, &statfs);
1317 if (status)
1318 goto out_nfserr;
1319 }
1320 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
1321 fh_init(&tempfh, NFS4_FHSIZE);
1322 status = fh_compose(&tempfh, exp, dentry, NULL);
1323 if (status)
1324 goto out;
1325 fhp = &tempfh;
1326 }
1327 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1328 | FATTR4_WORD0_SUPPORTED_ATTRS)) {
1329 status = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1330 aclsupport = (status == 0);
1331 if (bmval0 & FATTR4_WORD0_ACL) {
1332 if (status == -EOPNOTSUPP)
1333 bmval0 &= ~FATTR4_WORD0_ACL;
1334 else if (status == -EINVAL) {
1335 status = nfserr_attrnotsupp;
1336 goto out;
1337 } else if (status != 0)
1338 goto out_nfserr;
1339 }
1340 }
1341 if ((buflen -= 16) < 0)
1342 goto out_resource;
1343
1344 WRITE32(2);
1345 WRITE32(bmval0);
1346 WRITE32(bmval1);
1347 attrlenp = p++; /* to be backfilled later */
1348
1349 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1350 if ((buflen -= 12) < 0)
1351 goto out_resource;
1352 WRITE32(2);
1353 WRITE32(aclsupport ?
1354 NFSD_SUPPORTED_ATTRS_WORD0 :
1355 NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL);
1356 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
1357 }
1358 if (bmval0 & FATTR4_WORD0_TYPE) {
1359 if ((buflen -= 4) < 0)
1360 goto out_resource;
1361 dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12];
1362 if (dummy == NF4BAD)
1363 goto out_serverfault;
1364 WRITE32(dummy);
1365 }
1366 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1367 if ((buflen -= 4) < 0)
1368 goto out_resource;
1369 WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME );
1370 }
1371 if (bmval0 & FATTR4_WORD0_CHANGE) {
1372 /*
1373 * Note: This _must_ be consistent with the scheme for writing
1374 * change_info, so any changes made here must be reflected there
1375 * as well. (See xdr4.h:set_change_info() and the WRITECINFO()
1376 * macro above.)
1377 */
1378 if ((buflen -= 8) < 0)
1379 goto out_resource;
1380 WRITE32(stat.ctime.tv_sec);
1381 WRITE32(stat.ctime.tv_nsec);
1382 }
1383 if (bmval0 & FATTR4_WORD0_SIZE) {
1384 if ((buflen -= 8) < 0)
1385 goto out_resource;
1386 WRITE64(stat.size);
1387 }
1388 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
1389 if ((buflen -= 4) < 0)
1390 goto out_resource;
1391 WRITE32(1);
1392 }
1393 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
1394 if ((buflen -= 4) < 0)
1395 goto out_resource;
1396 WRITE32(1);
1397 }
1398 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
1399 if ((buflen -= 4) < 0)
1400 goto out_resource;
1401 WRITE32(0);
1402 }
1403 if (bmval0 & FATTR4_WORD0_FSID) {
1404 if ((buflen -= 16) < 0)
1405 goto out_resource;
1406 if (is_fsid(fhp, rqstp->rq_reffh)) {
1407 WRITE64((u64)exp->ex_fsid);
1408 WRITE64((u64)0);
1409 } else {
1410 WRITE32(0);
1411 WRITE32(MAJOR(stat.dev));
1412 WRITE32(0);
1413 WRITE32(MINOR(stat.dev));
1414 }
1415 }
1416 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
1417 if ((buflen -= 4) < 0)
1418 goto out_resource;
1419 WRITE32(0);
1420 }
1421 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
1422 if ((buflen -= 4) < 0)
1423 goto out_resource;
1424 WRITE32(NFSD_LEASE_TIME);
1425 }
1426 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
1427 if ((buflen -= 4) < 0)
1428 goto out_resource;
1429 WRITE32(0);
1430 }
1431 if (bmval0 & FATTR4_WORD0_ACL) {
1432 struct nfs4_ace *ace;
1433 struct list_head *h;
1434
1435 if (acl == NULL) {
1436 if ((buflen -= 4) < 0)
1437 goto out_resource;
1438
1439 WRITE32(0);
1440 goto out_acl;
1441 }
1442 if ((buflen -= 4) < 0)
1443 goto out_resource;
1444 WRITE32(acl->naces);
1445
1446 list_for_each(h, &acl->ace_head) {
1447 ace = list_entry(h, struct nfs4_ace, l_ace);
1448
1449 if ((buflen -= 4*3) < 0)
1450 goto out_resource;
1451 WRITE32(ace->type);
1452 WRITE32(ace->flag);
1453 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
1454 status = nfsd4_encode_aclname(rqstp, ace->whotype,
1455 ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
1456 &p, &buflen);
1457 if (status == nfserr_resource)
1458 goto out_resource;
1459 if (status)
1460 goto out;
1461 }
1462 }
1463out_acl:
1464 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
1465 if ((buflen -= 4) < 0)
1466 goto out_resource;
1467 WRITE32(aclsupport ?
1468 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
1469 }
1470 if (bmval0 & FATTR4_WORD0_CANSETTIME) {
1471 if ((buflen -= 4) < 0)
1472 goto out_resource;
1473 WRITE32(1);
1474 }
1475 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
1476 if ((buflen -= 4) < 0)
1477 goto out_resource;
1478 WRITE32(1);
1479 }
1480 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
1481 if ((buflen -= 4) < 0)
1482 goto out_resource;
1483 WRITE32(1);
1484 }
1485 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
1486 if ((buflen -= 4) < 0)
1487 goto out_resource;
1488 WRITE32(1);
1489 }
1490 if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
1491 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4;
1492 if (buflen < 0)
1493 goto out_resource;
1494 WRITE32(fhp->fh_handle.fh_size);
1495 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
1496 }
1497 if (bmval0 & FATTR4_WORD0_FILEID) {
1498 if ((buflen -= 8) < 0)
1499 goto out_resource;
1500 WRITE64((u64) stat.ino);
1501 }
1502 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
1503 if ((buflen -= 8) < 0)
1504 goto out_resource;
1505 WRITE64((u64) statfs.f_ffree);
1506 }
1507 if (bmval0 & FATTR4_WORD0_FILES_FREE) {
1508 if ((buflen -= 8) < 0)
1509 goto out_resource;
1510 WRITE64((u64) statfs.f_ffree);
1511 }
1512 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
1513 if ((buflen -= 8) < 0)
1514 goto out_resource;
1515 WRITE64((u64) statfs.f_files);
1516 }
1517 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
1518 if ((buflen -= 4) < 0)
1519 goto out_resource;
1520 WRITE32(1);
1521 }
1522 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
1523 if ((buflen -= 8) < 0)
1524 goto out_resource;
1525 WRITE64(~(u64)0);
1526 }
1527 if (bmval0 & FATTR4_WORD0_MAXLINK) {
1528 if ((buflen -= 4) < 0)
1529 goto out_resource;
1530 WRITE32(255);
1531 }
1532 if (bmval0 & FATTR4_WORD0_MAXNAME) {
1533 if ((buflen -= 4) < 0)
1534 goto out_resource;
1535 WRITE32(~(u32) 0);
1536 }
1537 if (bmval0 & FATTR4_WORD0_MAXREAD) {
1538 if ((buflen -= 8) < 0)
1539 goto out_resource;
1540 WRITE64((u64) NFSSVC_MAXBLKSIZE);
1541 }
1542 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
1543 if ((buflen -= 8) < 0)
1544 goto out_resource;
1545 WRITE64((u64) NFSSVC_MAXBLKSIZE);
1546 }
1547 if (bmval1 & FATTR4_WORD1_MODE) {
1548 if ((buflen -= 4) < 0)
1549 goto out_resource;
1550 WRITE32(stat.mode & S_IALLUGO);
1551 }
1552 if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
1553 if ((buflen -= 4) < 0)
1554 goto out_resource;
1555 WRITE32(1);
1556 }
1557 if (bmval1 & FATTR4_WORD1_NUMLINKS) {
1558 if ((buflen -= 4) < 0)
1559 goto out_resource;
1560 WRITE32(stat.nlink);
1561 }
1562 if (bmval1 & FATTR4_WORD1_OWNER) {
1563 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen);
1564 if (status == nfserr_resource)
1565 goto out_resource;
1566 if (status)
1567 goto out;
1568 }
1569 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
1570 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen);
1571 if (status == nfserr_resource)
1572 goto out_resource;
1573 if (status)
1574 goto out;
1575 }
1576 if (bmval1 & FATTR4_WORD1_RAWDEV) {
1577 if ((buflen -= 8) < 0)
1578 goto out_resource;
1579 WRITE32((u32) MAJOR(stat.rdev));
1580 WRITE32((u32) MINOR(stat.rdev));
1581 }
1582 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
1583 if ((buflen -= 8) < 0)
1584 goto out_resource;
1585 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
1586 WRITE64(dummy64);
1587 }
1588 if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
1589 if ((buflen -= 8) < 0)
1590 goto out_resource;
1591 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
1592 WRITE64(dummy64);
1593 }
1594 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
1595 if ((buflen -= 8) < 0)
1596 goto out_resource;
1597 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
1598 WRITE64(dummy64);
1599 }
1600 if (bmval1 & FATTR4_WORD1_SPACE_USED) {
1601 if ((buflen -= 8) < 0)
1602 goto out_resource;
1603 dummy64 = (u64)stat.blocks << 9;
1604 WRITE64(dummy64);
1605 }
1606 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
1607 if ((buflen -= 12) < 0)
1608 goto out_resource;
1609 WRITE32(0);
1610 WRITE32(stat.atime.tv_sec);
1611 WRITE32(stat.atime.tv_nsec);
1612 }
1613 if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
1614 if ((buflen -= 12) < 0)
1615 goto out_resource;
1616 WRITE32(0);
1617 WRITE32(1);
1618 WRITE32(0);
1619 }
1620 if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
1621 if ((buflen -= 12) < 0)
1622 goto out_resource;
1623 WRITE32(0);
1624 WRITE32(stat.ctime.tv_sec);
1625 WRITE32(stat.ctime.tv_nsec);
1626 }
1627 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
1628 if ((buflen -= 12) < 0)
1629 goto out_resource;
1630 WRITE32(0);
1631 WRITE32(stat.mtime.tv_sec);
1632 WRITE32(stat.mtime.tv_nsec);
1633 }
1634 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
1635 struct dentry *mnt_pnt, *mnt_root;
1636
1637 if ((buflen -= 8) < 0)
1638 goto out_resource;
1639 mnt_root = exp->ex_mnt->mnt_root;
1640 if (mnt_root->d_inode == dentry->d_inode) {
1641 mnt_pnt = exp->ex_mnt->mnt_mountpoint;
1642 WRITE64((u64) mnt_pnt->d_inode->i_ino);
1643 } else
1644 WRITE64((u64) stat.ino);
1645 }
1646 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1647 *countp = p - buffer;
1648 status = nfs_ok;
1649
1650out:
1651 nfs4_acl_free(acl);
1652 if (fhp == &tempfh)
1653 fh_put(&tempfh);
1654 return status;
1655out_nfserr:
1656 status = nfserrno(status);
1657 goto out;
1658out_resource:
1659 *countp = 0;
1660 status = nfserr_resource;
1661 goto out;
1662out_serverfault:
1663 status = nfserr_serverfault;
1664 goto out;
1665}
1666
1667static int
1668nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
1669 const char *name, int namlen, u32 *p, int *buflen)
1670{
1671 struct svc_export *exp = cd->rd_fhp->fh_export;
1672 struct dentry *dentry;
1673 int nfserr;
1674
1675 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
1676 if (IS_ERR(dentry))
1677 return nfserrno(PTR_ERR(dentry));
1678
1679 exp_get(exp);
1680 if (d_mountpoint(dentry)) {
1681 if (nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp)) {
1682 /*
1683 * -EAGAIN is the only error returned from
1684 * nfsd_cross_mnt() and it indicates that an
1685 * up-call has been initiated to fill in the export
1686 * options on exp. When the answer comes back,
1687 * this call will be retried.
1688 */
1689 nfserr = nfserr_dropit;
1690 goto out_put;
1691 }
1692
1693 }
1694 nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
1695 cd->rd_rqstp);
1696out_put:
1697 dput(dentry);
1698 exp_put(exp);
1699 return nfserr;
1700}
1701
1702static u32 *
1703nfsd4_encode_rdattr_error(u32 *p, int buflen, int nfserr)
1704{
1705 u32 *attrlenp;
1706
1707 if (buflen < 6)
1708 return NULL;
1709 *p++ = htonl(2);
1710 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
1711 *p++ = htonl(0); /* bmval1 */
1712
1713 attrlenp = p++;
1714 *p++ = nfserr; /* no htonl */
1715 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1716 return p;
1717}
1718
1719static int
1720nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
1721 loff_t offset, ino_t ino, unsigned int d_type)
1722{
1723 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
1724 int buflen;
1725 u32 *p = cd->buffer;
1726 int nfserr = nfserr_toosmall;
1727
1728 /* In nfsv4, "." and ".." never make it onto the wire.. */
1729 if (name && isdotent(name, namlen)) {
1730 cd->common.err = nfs_ok;
1731 return 0;
1732 }
1733
1734 if (cd->offset)
1735 xdr_encode_hyper(cd->offset, (u64) offset);
1736
1737 buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
1738 if (buflen < 0)
1739 goto fail;
1740
1741 *p++ = xdr_one; /* mark entry present */
1742 cd->offset = p; /* remember pointer */
1743 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
1744 p = xdr_encode_array(p, name, namlen); /* name length & name */
1745
1746 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen);
1747 switch (nfserr) {
1748 case nfs_ok:
1749 p += buflen;
1750 break;
1751 case nfserr_resource:
1752 nfserr = nfserr_toosmall;
1753 goto fail;
1754 case nfserr_dropit:
1755 goto fail;
1756 default:
1757 /*
1758 * If the client requested the RDATTR_ERROR attribute,
1759 * we stuff the error code into this attribute
1760 * and continue. If this attribute was not requested,
1761 * then in accordance with the spec, we fail the
1762 * entire READDIR operation(!)
1763 */
1764 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
1765 goto fail;
1766 nfserr = nfserr_toosmall;
1767 p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
1768 if (p == NULL)
1769 goto fail;
1770 }
1771 cd->buflen -= (p - cd->buffer);
1772 cd->buffer = p;
1773 cd->common.err = nfs_ok;
1774 return 0;
1775fail:
1776 cd->common.err = nfserr;
1777 return -EINVAL;
1778}
1779
1780static void
1781nfsd4_encode_access(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_access *access)
1782{
1783 ENCODE_HEAD;
1784
1785 if (!nfserr) {
1786 RESERVE_SPACE(8);
1787 WRITE32(access->ac_supported);
1788 WRITE32(access->ac_resp_access);
1789 ADJUST_ARGS();
1790 }
1791}
1792
1793static void
1794nfsd4_encode_close(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_close *close)
1795{
1796 ENCODE_SEQID_OP_HEAD;
1797
1798 if (!nfserr) {
1799 RESERVE_SPACE(sizeof(stateid_t));
1800 WRITE32(close->cl_stateid.si_generation);
1801 WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
1802 ADJUST_ARGS();
1803 }
1804 ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
1805}
1806
1807
1808static void
1809nfsd4_encode_commit(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_commit *commit)
1810{
1811 ENCODE_HEAD;
1812
1813 if (!nfserr) {
1814 RESERVE_SPACE(8);
1815 WRITEMEM(commit->co_verf.data, 8);
1816 ADJUST_ARGS();
1817 }
1818}
1819
1820static void
1821nfsd4_encode_create(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_create *create)
1822{
1823 ENCODE_HEAD;
1824
1825 if (!nfserr) {
1826 RESERVE_SPACE(32);
1827 WRITECINFO(create->cr_cinfo);
1828 WRITE32(2);
1829 WRITE32(create->cr_bmval[0]);
1830 WRITE32(create->cr_bmval[1]);
1831 ADJUST_ARGS();
1832 }
1833}
1834
1835static int
1836nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_getattr *getattr)
1837{
1838 struct svc_fh *fhp = getattr->ga_fhp;
1839 int buflen;
1840
1841 if (nfserr)
1842 return nfserr;
1843
1844 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
1845 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
1846 resp->p, &buflen, getattr->ga_bmval,
1847 resp->rqstp);
1848
1849 if (!nfserr)
1850 resp->p += buflen;
1851 return nfserr;
1852}
1853
1854static void
1855nfsd4_encode_getfh(struct nfsd4_compoundres *resp, int nfserr, struct svc_fh *fhp)
1856{
1857 unsigned int len;
1858 ENCODE_HEAD;
1859
1860 if (!nfserr) {
1861 len = fhp->fh_handle.fh_size;
1862 RESERVE_SPACE(len + 4);
1863 WRITE32(len);
1864 WRITEMEM(&fhp->fh_handle.fh_base, len);
1865 ADJUST_ARGS();
1866 }
1867}
1868
1869/*
1870* Including all fields other than the name, a LOCK4denied structure requires
1871* 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.
1872*/
1873static void
1874nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
1875{
1876 ENCODE_HEAD;
1877
1878 RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0));
1879 WRITE64(ld->ld_start);
1880 WRITE64(ld->ld_length);
1881 WRITE32(ld->ld_type);
1882 if (ld->ld_sop) {
1883 WRITEMEM(&ld->ld_clientid, 8);
1884 WRITE32(ld->ld_sop->so_owner.len);
1885 WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
1886 kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner);
1887 } else { /* non - nfsv4 lock in conflict, no clientid nor owner */
1888 WRITE64((u64)0); /* clientid */
1889 WRITE32(0); /* length of owner name */
1890 }
1891 ADJUST_ARGS();
1892}
1893
1894static void
1895nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
1896{
1897
1898 ENCODE_SEQID_OP_HEAD;
1899
1900 if (!nfserr) {
1901 RESERVE_SPACE(4 + sizeof(stateid_t));
1902 WRITE32(lock->lk_resp_stateid.si_generation);
1903 WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
1904 ADJUST_ARGS();
1905 } else if (nfserr == nfserr_denied)
1906 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
1907
1908 ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
1909}
1910
1911static void
1912nfsd4_encode_lockt(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lockt *lockt)
1913{
1914 if (nfserr == nfserr_denied)
1915 nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
1916}
1917
1918static void
1919nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_locku *locku)
1920{
1921 ENCODE_SEQID_OP_HEAD;
1922
1923 if (!nfserr) {
1924 RESERVE_SPACE(sizeof(stateid_t));
1925 WRITE32(locku->lu_stateid.si_generation);
1926 WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
1927 ADJUST_ARGS();
1928 }
1929
1930 ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
1931}
1932
1933
1934static void
1935nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link *link)
1936{
1937 ENCODE_HEAD;
1938
1939 if (!nfserr) {
1940 RESERVE_SPACE(20);
1941 WRITECINFO(link->li_cinfo);
1942 ADJUST_ARGS();
1943 }
1944}
1945
1946
1947static void
1948nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open *open)
1949{
1950 ENCODE_SEQID_OP_HEAD;
1951
1952 if (nfserr)
1953 goto out;
1954
1955 RESERVE_SPACE(36 + sizeof(stateid_t));
1956 WRITE32(open->op_stateid.si_generation);
1957 WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
1958 WRITECINFO(open->op_cinfo);
1959 WRITE32(open->op_rflags);
1960 WRITE32(2);
1961 WRITE32(open->op_bmval[0]);
1962 WRITE32(open->op_bmval[1]);
1963 WRITE32(open->op_delegate_type);
1964 ADJUST_ARGS();
1965
1966 switch (open->op_delegate_type) {
1967 case NFS4_OPEN_DELEGATE_NONE:
1968 break;
1969 case NFS4_OPEN_DELEGATE_READ:
1970 RESERVE_SPACE(20 + sizeof(stateid_t));
1971 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
1972 WRITE32(0);
1973
1974 /*
1975 * TODO: ACE's in delegations
1976 */
1977 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
1978 WRITE32(0);
1979 WRITE32(0);
1980 WRITE32(0); /* XXX: is NULL principal ok? */
1981 ADJUST_ARGS();
1982 break;
1983 case NFS4_OPEN_DELEGATE_WRITE:
1984 RESERVE_SPACE(32 + sizeof(stateid_t));
1985 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
1986 WRITE32(0);
1987
1988 /*
1989 * TODO: space_limit's in delegations
1990 */
1991 WRITE32(NFS4_LIMIT_SIZE);
1992 WRITE32(~(u32)0);
1993 WRITE32(~(u32)0);
1994
1995 /*
1996 * TODO: ACE's in delegations
1997 */
1998 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
1999 WRITE32(0);
2000 WRITE32(0);
2001 WRITE32(0); /* XXX: is NULL principal ok? */
2002 ADJUST_ARGS();
2003 break;
2004 default:
2005 BUG();
2006 }
2007 /* XXX save filehandle here */
2008out:
2009 ENCODE_SEQID_OP_TAIL(open->op_stateowner);
2010}
2011
2012static void
2013nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_confirm *oc)
2014{
2015 ENCODE_SEQID_OP_HEAD;
2016
2017 if (!nfserr) {
2018 RESERVE_SPACE(sizeof(stateid_t));
2019 WRITE32(oc->oc_resp_stateid.si_generation);
2020 WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
2021 ADJUST_ARGS();
2022 }
2023
2024 ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
2025}
2026
2027static void
2028nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_downgrade *od)
2029{
2030 ENCODE_SEQID_OP_HEAD;
2031
2032 if (!nfserr) {
2033 RESERVE_SPACE(sizeof(stateid_t));
2034 WRITE32(od->od_stateid.si_generation);
2035 WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
2036 ADJUST_ARGS();
2037 }
2038
2039 ENCODE_SEQID_OP_TAIL(od->od_stateowner);
2040}
2041
2042static int
2043nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read)
2044{
2045 u32 eof;
2046 int v, pn;
2047 unsigned long maxcount;
2048 long len;
2049 ENCODE_HEAD;
2050
2051 if (nfserr)
2052 return nfserr;
2053 if (resp->xbuf->page_len)
2054 return nfserr_resource;
2055
2056 RESERVE_SPACE(8); /* eof flag and byte count */
2057
2058 maxcount = NFSSVC_MAXBLKSIZE;
2059 if (maxcount > read->rd_length)
2060 maxcount = read->rd_length;
2061
2062 len = maxcount;
2063 v = 0;
2064 while (len > 0) {
2065 pn = resp->rqstp->rq_resused;
2066 svc_take_page(resp->rqstp);
2067 read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]);
2068 read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE;
2069 v++;
2070 len -= PAGE_SIZE;
2071 }
2072 read->rd_vlen = v;
2073
2074 nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp,
2075 read->rd_offset, read->rd_iov, read->rd_vlen,
2076 &maxcount);
2077
2078 if (nfserr == nfserr_symlink)
2079 nfserr = nfserr_inval;
2080 if (nfserr)
2081 return nfserr;
2082 eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size);
2083
2084 WRITE32(eof);
2085 WRITE32(maxcount);
2086 ADJUST_ARGS();
2087 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2088
2089 resp->xbuf->page_len = maxcount;
2090
2091 /* read zero bytes -> don't set up tail */
2092 if(!maxcount)
2093 return 0;
2094
2095 /* set up page for remaining responses */
2096 svc_take_page(resp->rqstp);
2097 resp->xbuf->tail[0].iov_base =
2098 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2099 resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2100 resp->xbuf->tail[0].iov_len = 0;
2101 resp->p = resp->xbuf->tail[0].iov_base;
2102 resp->end = resp->p + PAGE_SIZE/4;
2103
2104 if (maxcount&3) {
2105 *(resp->p)++ = 0;
2106 resp->xbuf->tail[0].iov_base += maxcount&3;
2107 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2108 }
2109 return 0;
2110}
2111
2112static int
2113nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readlink *readlink)
2114{
2115 int maxcount;
2116 char *page;
2117 ENCODE_HEAD;
2118
2119 if (nfserr)
2120 return nfserr;
2121 if (resp->xbuf->page_len)
2122 return nfserr_resource;
2123
2124 svc_take_page(resp->rqstp);
2125 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2126
2127 maxcount = PAGE_SIZE;
2128 RESERVE_SPACE(4);
2129
2130 /*
2131 * XXX: By default, the ->readlink() VFS op will truncate symlinks
2132 * if they would overflow the buffer. Is this kosher in NFSv4? If
2133 * not, one easy fix is: if ->readlink() precisely fills the buffer,
2134 * assume that truncation occurred, and return NFS4ERR_RESOURCE.
2135 */
2136 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2137 if (nfserr == nfserr_isdir)
2138 return nfserr_inval;
2139 if (nfserr)
2140 return nfserr;
2141
2142 WRITE32(maxcount);
2143 ADJUST_ARGS();
2144 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2145
2146 svc_take_page(resp->rqstp);
2147 resp->xbuf->tail[0].iov_base =
2148 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2149 resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2150 resp->xbuf->tail[0].iov_len = 0;
2151 resp->p = resp->xbuf->tail[0].iov_base;
2152 resp->end = resp->p + PAGE_SIZE/4;
2153
2154 resp->xbuf->page_len = maxcount;
2155 if (maxcount&3) {
2156 *(resp->p)++ = 0;
2157 resp->xbuf->tail[0].iov_base += maxcount&3;
2158 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2159 }
2160 return 0;
2161}
2162
2163static int
2164nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readdir *readdir)
2165{
2166 int maxcount;
2167 loff_t offset;
2168 u32 *page, *savep;
2169 ENCODE_HEAD;
2170
2171 if (nfserr)
2172 return nfserr;
2173 if (resp->xbuf->page_len)
2174 return nfserr_resource;
2175
2176 RESERVE_SPACE(8); /* verifier */
2177 savep = p;
2178
2179 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
2180 WRITE32(0);
2181 WRITE32(0);
2182 ADJUST_ARGS();
2183 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2184
2185 maxcount = PAGE_SIZE;
2186 if (maxcount > readdir->rd_maxcount)
2187 maxcount = readdir->rd_maxcount;
2188
2189 /*
2190 * Convert from bytes to words, account for the two words already
2191 * written, make sure to leave two words at the end for the next
2192 * pointer and eof field.
2193 */
2194 maxcount = (maxcount >> 2) - 4;
2195 if (maxcount < 0) {
2196 nfserr = nfserr_toosmall;
2197 goto err_no_verf;
2198 }
2199
2200 svc_take_page(resp->rqstp);
2201 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2202 readdir->common.err = 0;
2203 readdir->buflen = maxcount;
2204 readdir->buffer = page;
2205 readdir->offset = NULL;
2206
2207 offset = readdir->rd_cookie;
2208 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
2209 &offset,
2210 &readdir->common, nfsd4_encode_dirent);
2211 if (nfserr == nfs_ok &&
2212 readdir->common.err == nfserr_toosmall &&
2213 readdir->buffer == page)
2214 nfserr = nfserr_toosmall;
2215 if (nfserr == nfserr_symlink)
2216 nfserr = nfserr_notdir;
2217 if (nfserr)
2218 goto err_no_verf;
2219
2220 if (readdir->offset)
2221 xdr_encode_hyper(readdir->offset, offset);
2222
2223 p = readdir->buffer;
2224 *p++ = 0; /* no more entries */
2225 *p++ = htonl(readdir->common.err == nfserr_eof);
2226 resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2227
2228 /* allocate a page for the tail */
2229 svc_take_page(resp->rqstp);
2230 resp->xbuf->tail[0].iov_base =
2231 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2232 resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2233 resp->xbuf->tail[0].iov_len = 0;
2234 resp->p = resp->xbuf->tail[0].iov_base;
2235 resp->end = resp->p + PAGE_SIZE/4;
2236
2237 return 0;
2238err_no_verf:
2239 p = savep;
2240 ADJUST_ARGS();
2241 return nfserr;
2242}
2243
2244static void
2245nfsd4_encode_remove(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_remove *remove)
2246{
2247 ENCODE_HEAD;
2248
2249 if (!nfserr) {
2250 RESERVE_SPACE(20);
2251 WRITECINFO(remove->rm_cinfo);
2252 ADJUST_ARGS();
2253 }
2254}
2255
2256static void
2257nfsd4_encode_rename(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_rename *rename)
2258{
2259 ENCODE_HEAD;
2260
2261 if (!nfserr) {
2262 RESERVE_SPACE(40);
2263 WRITECINFO(rename->rn_sinfo);
2264 WRITECINFO(rename->rn_tinfo);
2265 ADJUST_ARGS();
2266 }
2267}
2268
2269/*
2270 * The SETATTR encode routine is special -- it always encodes a bitmap,
2271 * regardless of the error status.
2272 */
2273static void
2274nfsd4_encode_setattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setattr *setattr)
2275{
2276 ENCODE_HEAD;
2277
2278 RESERVE_SPACE(12);
2279 if (nfserr) {
2280 WRITE32(2);
2281 WRITE32(0);
2282 WRITE32(0);
2283 }
2284 else {
2285 WRITE32(2);
2286 WRITE32(setattr->sa_bmval[0]);
2287 WRITE32(setattr->sa_bmval[1]);
2288 }
2289 ADJUST_ARGS();
2290}
2291
2292static void
2293nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setclientid *scd)
2294{
2295 ENCODE_HEAD;
2296
2297 if (!nfserr) {
2298 RESERVE_SPACE(8 + sizeof(nfs4_verifier));
2299 WRITEMEM(&scd->se_clientid, 8);
2300 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
2301 ADJUST_ARGS();
2302 }
2303 else if (nfserr == nfserr_clid_inuse) {
2304 RESERVE_SPACE(8);
2305 WRITE32(0);
2306 WRITE32(0);
2307 ADJUST_ARGS();
2308 }
2309}
2310
2311static void
2312nfsd4_encode_write(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_write *write)
2313{
2314 ENCODE_HEAD;
2315
2316 if (!nfserr) {
2317 RESERVE_SPACE(16);
2318 WRITE32(write->wr_bytes_written);
2319 WRITE32(write->wr_how_written);
2320 WRITEMEM(write->wr_verifier.data, 8);
2321 ADJUST_ARGS();
2322 }
2323}
2324
2325void
2326nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2327{
2328 u32 *statp;
2329 ENCODE_HEAD;
2330
2331 RESERVE_SPACE(8);
2332 WRITE32(op->opnum);
2333 statp = p++; /* to be backfilled at the end */
2334 ADJUST_ARGS();
2335
2336 switch (op->opnum) {
2337 case OP_ACCESS:
2338 nfsd4_encode_access(resp, op->status, &op->u.access);
2339 break;
2340 case OP_CLOSE:
2341 nfsd4_encode_close(resp, op->status, &op->u.close);
2342 break;
2343 case OP_COMMIT:
2344 nfsd4_encode_commit(resp, op->status, &op->u.commit);
2345 break;
2346 case OP_CREATE:
2347 nfsd4_encode_create(resp, op->status, &op->u.create);
2348 break;
2349 case OP_DELEGRETURN:
2350 break;
2351 case OP_GETATTR:
2352 op->status = nfsd4_encode_getattr(resp, op->status, &op->u.getattr);
2353 break;
2354 case OP_GETFH:
2355 nfsd4_encode_getfh(resp, op->status, op->u.getfh);
2356 break;
2357 case OP_LINK:
2358 nfsd4_encode_link(resp, op->status, &op->u.link);
2359 break;
2360 case OP_LOCK:
2361 nfsd4_encode_lock(resp, op->status, &op->u.lock);
2362 break;
2363 case OP_LOCKT:
2364 nfsd4_encode_lockt(resp, op->status, &op->u.lockt);
2365 break;
2366 case OP_LOCKU:
2367 nfsd4_encode_locku(resp, op->status, &op->u.locku);
2368 break;
2369 case OP_LOOKUP:
2370 break;
2371 case OP_LOOKUPP:
2372 break;
2373 case OP_NVERIFY:
2374 break;
2375 case OP_OPEN:
2376 nfsd4_encode_open(resp, op->status, &op->u.open);
2377 break;
2378 case OP_OPEN_CONFIRM:
2379 nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm);
2380 break;
2381 case OP_OPEN_DOWNGRADE:
2382 nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade);
2383 break;
2384 case OP_PUTFH:
2385 break;
2386 case OP_PUTROOTFH:
2387 break;
2388 case OP_READ:
2389 op->status = nfsd4_encode_read(resp, op->status, &op->u.read);
2390 break;
2391 case OP_READDIR:
2392 op->status = nfsd4_encode_readdir(resp, op->status, &op->u.readdir);
2393 break;
2394 case OP_READLINK:
2395 op->status = nfsd4_encode_readlink(resp, op->status, &op->u.readlink);
2396 break;
2397 case OP_REMOVE:
2398 nfsd4_encode_remove(resp, op->status, &op->u.remove);
2399 break;
2400 case OP_RENAME:
2401 nfsd4_encode_rename(resp, op->status, &op->u.rename);
2402 break;
2403 case OP_RENEW:
2404 break;
2405 case OP_RESTOREFH:
2406 break;
2407 case OP_SAVEFH:
2408 break;
2409 case OP_SETATTR:
2410 nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
2411 break;
2412 case OP_SETCLIENTID:
2413 nfsd4_encode_setclientid(resp, op->status, &op->u.setclientid);
2414 break;
2415 case OP_SETCLIENTID_CONFIRM:
2416 break;
2417 case OP_VERIFY:
2418 break;
2419 case OP_WRITE:
2420 nfsd4_encode_write(resp, op->status, &op->u.write);
2421 break;
2422 case OP_RELEASE_LOCKOWNER:
2423 break;
2424 default:
2425 break;
2426 }
2427
2428 /*
2429 * Note: We write the status directly, instead of using WRITE32(),
2430 * since it is already in network byte order.
2431 */
2432 *statp = op->status;
2433}
2434
2435/*
2436 * Encode the reply stored in the stateowner reply cache
2437 *
2438 * XDR note: do not encode rp->rp_buflen: the buffer contains the
2439 * previously sent already encoded operation.
2440 *
2441 * called with nfs4_lock_state() held
2442 */
2443void
2444nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2445{
2446 ENCODE_HEAD;
2447 struct nfs4_replay *rp = op->replay;
2448
2449 BUG_ON(!rp);
2450
2451 RESERVE_SPACE(8);
2452 WRITE32(op->opnum);
2453 *p++ = rp->rp_status; /* already xdr'ed */
2454 ADJUST_ARGS();
2455
2456 RESERVE_SPACE(rp->rp_buflen);
2457 WRITEMEM(rp->rp_buf, rp->rp_buflen);
2458 ADJUST_ARGS();
2459}
2460
2461/*
2462 * END OF "GENERIC" ENCODE ROUTINES.
2463 */
2464
2465int
2466nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
2467{
2468 return xdr_ressize_check(rqstp, p);
2469}
2470
2471void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
2472{
2473 if (args->ops != args->iops) {
2474 kfree(args->ops);
2475 args->ops = args->iops;
2476 }
2477 if (args->tmpp) {
2478 kfree(args->tmpp);
2479 args->tmpp = NULL;
2480 }
2481 while (args->to_free) {
2482 struct tmpbuf *tb = args->to_free;
2483 args->to_free = tb->next;
2484 tb->release(tb->buf);
2485 kfree(tb);
2486 }
2487}
2488
2489int
2490nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundargs *args)
2491{
2492 int status;
2493
2494 args->p = p;
2495 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
2496 args->pagelist = rqstp->rq_arg.pages;
2497 args->pagelen = rqstp->rq_arg.page_len;
2498 args->tmpp = NULL;
2499 args->to_free = NULL;
2500 args->ops = args->iops;
2501 args->rqstp = rqstp;
2502
2503 status = nfsd4_decode_compound(args);
2504 if (status) {
2505 nfsd4_release_compoundargs(args);
2506 }
2507 return !status;
2508}
2509
2510int
2511nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundres *resp)
2512{
2513 /*
2514 * All that remains is to write the tag and operation count...
2515 */
2516 struct kvec *iov;
2517 p = resp->tagp;
2518 *p++ = htonl(resp->taglen);
2519 memcpy(p, resp->tag, resp->taglen);
2520 p += XDR_QUADLEN(resp->taglen);
2521 *p++ = htonl(resp->opcnt);
2522
2523 if (rqstp->rq_res.page_len)
2524 iov = &rqstp->rq_res.tail[0];
2525 else
2526 iov = &rqstp->rq_res.head[0];
2527 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
2528 BUG_ON(iov->iov_len > PAGE_SIZE);
2529 return 1;
2530}
2531
2532/*
2533 * Local variables:
2534 * c-basic-offset: 8
2535 * End:
2536 */
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
new file mode 100644
index 000000000000..119e4d4495b8
--- /dev/null
+++ b/fs/nfsd/nfscache.c
@@ -0,0 +1,328 @@
1/*
2 * linux/fs/nfsd/nfscache.c
3 *
4 * Request reply cache. This is currently a global cache, but this may
5 * change in the future and be a per-client cache.
6 *
7 * This code is heavily inspired by the 44BSD implementation, although
8 * it does things a bit differently.
9 *
10 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
11 */
12
13#include <linux/kernel.h>
14#include <linux/time.h>
15#include <linux/slab.h>
16#include <linux/string.h>
17#include <linux/spinlock.h>
18#include <linux/list.h>
19
20#include <linux/sunrpc/svc.h>
21#include <linux/nfsd/nfsd.h>
22#include <linux/nfsd/cache.h>
23
24/* Size of reply cache. Common values are:
25 * 4.3BSD: 128
26 * 4.4BSD: 256
27 * Solaris2: 1024
28 * DEC Unix: 512-4096
29 */
30#define CACHESIZE 1024
31#define HASHSIZE 64
32#define REQHASH(xid) ((((xid) >> 24) ^ (xid)) & (HASHSIZE-1))
33
34static struct hlist_head * hash_list;
35static struct list_head lru_head;
36static int cache_disabled = 1;
37
38static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
39
40/*
41 * locking for the reply cache:
42 * A cache entry is "single use" if c_state == RC_INPROG
43 * Otherwise, it when accessing _prev or _next, the lock must be held.
44 */
45static DEFINE_SPINLOCK(cache_lock);
46
47void
48nfsd_cache_init(void)
49{
50 struct svc_cacherep *rp;
51 int i;
52
53 INIT_LIST_HEAD(&lru_head);
54 i = CACHESIZE;
55 while(i) {
56 rp = kmalloc(sizeof(*rp), GFP_KERNEL);
57 if (!rp) break;
58 list_add(&rp->c_lru, &lru_head);
59 rp->c_state = RC_UNUSED;
60 rp->c_type = RC_NOCACHE;
61 INIT_HLIST_NODE(&rp->c_hash);
62 i--;
63 }
64
65 if (i)
66 printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n",
67 CACHESIZE, CACHESIZE-i);
68
69 hash_list = kmalloc (HASHSIZE * sizeof(struct hlist_head), GFP_KERNEL);
70 if (!hash_list) {
71 nfsd_cache_shutdown();
72 printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
73 HASHSIZE * sizeof(struct hlist_head));
74 return;
75 }
76 memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head));
77
78 cache_disabled = 0;
79}
80
81void
82nfsd_cache_shutdown(void)
83{
84 struct svc_cacherep *rp;
85
86 while (!list_empty(&lru_head)) {
87 rp = list_entry(lru_head.next, struct svc_cacherep, c_lru);
88 if (rp->c_state == RC_DONE && rp->c_type == RC_REPLBUFF)
89 kfree(rp->c_replvec.iov_base);
90 list_del(&rp->c_lru);
91 kfree(rp);
92 }
93
94 cache_disabled = 1;
95
96 if (hash_list)
97 kfree (hash_list);
98 hash_list = NULL;
99}
100
101/*
102 * Move cache entry to end of LRU list
103 */
104static void
105lru_put_end(struct svc_cacherep *rp)
106{
107 list_del(&rp->c_lru);
108 list_add_tail(&rp->c_lru, &lru_head);
109}
110
111/*
112 * Move a cache entry from one hash list to another
113 */
114static void
115hash_refile(struct svc_cacherep *rp)
116{
117 hlist_del_init(&rp->c_hash);
118 hlist_add_head(&rp->c_hash, hash_list + REQHASH(rp->c_xid));
119}
120
121/*
122 * Try to find an entry matching the current call in the cache. When none
123 * is found, we grab the oldest unlocked entry off the LRU list.
124 * Note that no operation within the loop may sleep.
125 */
126int
127nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
128{
129 struct hlist_node *hn;
130 struct hlist_head *rh;
131 struct svc_cacherep *rp;
132 u32 xid = rqstp->rq_xid,
133 proto = rqstp->rq_prot,
134 vers = rqstp->rq_vers,
135 proc = rqstp->rq_proc;
136 unsigned long age;
137 int rtn;
138
139 rqstp->rq_cacherep = NULL;
140 if (cache_disabled || type == RC_NOCACHE) {
141 nfsdstats.rcnocache++;
142 return RC_DOIT;
143 }
144
145 spin_lock(&cache_lock);
146 rtn = RC_DOIT;
147
148 rh = &hash_list[REQHASH(xid)];
149 hlist_for_each_entry(rp, hn, rh, c_hash) {
150 if (rp->c_state != RC_UNUSED &&
151 xid == rp->c_xid && proc == rp->c_proc &&
152 proto == rp->c_prot && vers == rp->c_vers &&
153 time_before(jiffies, rp->c_timestamp + 120*HZ) &&
154 memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, sizeof(rp->c_addr))==0) {
155 nfsdstats.rchits++;
156 goto found_entry;
157 }
158 }
159 nfsdstats.rcmisses++;
160
161 /* This loop shouldn't take more than a few iterations normally */
162 {
163 int safe = 0;
164 list_for_each_entry(rp, &lru_head, c_lru) {
165 if (rp->c_state != RC_INPROG)
166 break;
167 if (safe++ > CACHESIZE) {
168 printk("nfsd: loop in repcache LRU list\n");
169 cache_disabled = 1;
170 goto out;
171 }
172 }
173 }
174
175 /* This should not happen */
176 if (rp == NULL) {
177 static int complaints;
178
179 printk(KERN_WARNING "nfsd: all repcache entries locked!\n");
180 if (++complaints > 5) {
181 printk(KERN_WARNING "nfsd: disabling repcache.\n");
182 cache_disabled = 1;
183 }
184 goto out;
185 }
186
187 rqstp->rq_cacherep = rp;
188 rp->c_state = RC_INPROG;
189 rp->c_xid = xid;
190 rp->c_proc = proc;
191 rp->c_addr = rqstp->rq_addr;
192 rp->c_prot = proto;
193 rp->c_vers = vers;
194 rp->c_timestamp = jiffies;
195
196 hash_refile(rp);
197
198 /* release any buffer */
199 if (rp->c_type == RC_REPLBUFF) {
200 kfree(rp->c_replvec.iov_base);
201 rp->c_replvec.iov_base = NULL;
202 }
203 rp->c_type = RC_NOCACHE;
204 out:
205 spin_unlock(&cache_lock);
206 return rtn;
207
208found_entry:
209 /* We found a matching entry which is either in progress or done. */
210 age = jiffies - rp->c_timestamp;
211 rp->c_timestamp = jiffies;
212 lru_put_end(rp);
213
214 rtn = RC_DROPIT;
215 /* Request being processed or excessive rexmits */
216 if (rp->c_state == RC_INPROG || age < RC_DELAY)
217 goto out;
218
219 /* From the hall of fame of impractical attacks:
220 * Is this a user who tries to snoop on the cache? */
221 rtn = RC_DOIT;
222 if (!rqstp->rq_secure && rp->c_secure)
223 goto out;
224
225 /* Compose RPC reply header */
226 switch (rp->c_type) {
227 case RC_NOCACHE:
228 break;
229 case RC_REPLSTAT:
230 svc_putu32(&rqstp->rq_res.head[0], rp->c_replstat);
231 rtn = RC_REPLY;
232 break;
233 case RC_REPLBUFF:
234 if (!nfsd_cache_append(rqstp, &rp->c_replvec))
235 goto out; /* should not happen */
236 rtn = RC_REPLY;
237 break;
238 default:
239 printk(KERN_WARNING "nfsd: bad repcache type %d\n", rp->c_type);
240 rp->c_state = RC_UNUSED;
241 }
242
243 goto out;
244}
245
246/*
247 * Update a cache entry. This is called from nfsd_dispatch when
248 * the procedure has been executed and the complete reply is in
249 * rqstp->rq_res.
250 *
251 * We're copying around data here rather than swapping buffers because
252 * the toplevel loop requires max-sized buffers, which would be a waste
253 * of memory for a cache with a max reply size of 100 bytes (diropokres).
254 *
255 * If we should start to use different types of cache entries tailored
256 * specifically for attrstat and fh's, we may save even more space.
257 *
258 * Also note that a cachetype of RC_NOCACHE can legally be passed when
259 * nfsd failed to encode a reply that otherwise would have been cached.
260 * In this case, nfsd_cache_update is called with statp == NULL.
261 */
262void
263nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, u32 *statp)
264{
265 struct svc_cacherep *rp;
266 struct kvec *resv = &rqstp->rq_res.head[0], *cachv;
267 int len;
268
269 if (!(rp = rqstp->rq_cacherep) || cache_disabled)
270 return;
271
272 len = resv->iov_len - ((char*)statp - (char*)resv->iov_base);
273 len >>= 2;
274
275 /* Don't cache excessive amounts of data and XDR failures */
276 if (!statp || len > (256 >> 2)) {
277 rp->c_state = RC_UNUSED;
278 return;
279 }
280
281 switch (cachetype) {
282 case RC_REPLSTAT:
283 if (len != 1)
284 printk("nfsd: RC_REPLSTAT/reply len %d!\n",len);
285 rp->c_replstat = *statp;
286 break;
287 case RC_REPLBUFF:
288 cachv = &rp->c_replvec;
289 cachv->iov_base = kmalloc(len << 2, GFP_KERNEL);
290 if (!cachv->iov_base) {
291 spin_lock(&cache_lock);
292 rp->c_state = RC_UNUSED;
293 spin_unlock(&cache_lock);
294 return;
295 }
296 cachv->iov_len = len << 2;
297 memcpy(cachv->iov_base, statp, len << 2);
298 break;
299 }
300 spin_lock(&cache_lock);
301 lru_put_end(rp);
302 rp->c_secure = rqstp->rq_secure;
303 rp->c_type = cachetype;
304 rp->c_state = RC_DONE;
305 rp->c_timestamp = jiffies;
306 spin_unlock(&cache_lock);
307 return;
308}
309
310/*
311 * Copy cached reply to current reply buffer. Should always fit.
312 * FIXME as reply is in a page, we should just attach the page, and
313 * keep a refcount....
314 */
315static int
316nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data)
317{
318 struct kvec *vec = &rqstp->rq_res.head[0];
319
320 if (vec->iov_len + data->iov_len > PAGE_SIZE) {
321 printk(KERN_WARNING "nfsd: cached reply too large (%Zd).\n",
322 data->iov_len);
323 return 0;
324 }
325 memcpy((char*)vec->iov_base + vec->iov_len, data->iov_base, data->iov_len);
326 vec->iov_len += data->iov_len;
327 return 1;
328}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
new file mode 100644
index 000000000000..161afdcb8f7d
--- /dev/null
+++ b/fs/nfsd/nfsctl.c
@@ -0,0 +1,438 @@
1/*
2 * linux/fs/nfsd/nfsctl.c
3 *
4 * Syscall interface to knfsd.
5 *
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */
8
9#include <linux/config.h>
10#include <linux/module.h>
11
12#include <linux/linkage.h>
13#include <linux/time.h>
14#include <linux/errno.h>
15#include <linux/fs.h>
16#include <linux/fcntl.h>
17#include <linux/net.h>
18#include <linux/in.h>
19#include <linux/syscalls.h>
20#include <linux/unistd.h>
21#include <linux/slab.h>
22#include <linux/proc_fs.h>
23#include <linux/seq_file.h>
24#include <linux/pagemap.h>
25#include <linux/init.h>
26
27#include <linux/nfs.h>
28#include <linux/nfsd_idmap.h>
29#include <linux/sunrpc/svc.h>
30#include <linux/nfsd/nfsd.h>
31#include <linux/nfsd/cache.h>
32#include <linux/nfsd/xdr.h>
33#include <linux/nfsd/syscall.h>
34#include <linux/nfsd/interface.h>
35
36#include <asm/uaccess.h>
37
38/*
39 * We have a single directory with 9 nodes in it.
40 */
41enum {
42 NFSD_Root = 1,
43 NFSD_Svc,
44 NFSD_Add,
45 NFSD_Del,
46 NFSD_Export,
47 NFSD_Unexport,
48 NFSD_Getfd,
49 NFSD_Getfs,
50 NFSD_List,
51 NFSD_Fh,
52 NFSD_Threads,
53 NFSD_Leasetime,
54};
55
56/*
57 * write() for these nodes.
58 */
59static ssize_t write_svc(struct file *file, char *buf, size_t size);
60static ssize_t write_add(struct file *file, char *buf, size_t size);
61static ssize_t write_del(struct file *file, char *buf, size_t size);
62static ssize_t write_export(struct file *file, char *buf, size_t size);
63static ssize_t write_unexport(struct file *file, char *buf, size_t size);
64static ssize_t write_getfd(struct file *file, char *buf, size_t size);
65static ssize_t write_getfs(struct file *file, char *buf, size_t size);
66static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
67static ssize_t write_threads(struct file *file, char *buf, size_t size);
68static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
69
70static ssize_t (*write_op[])(struct file *, char *, size_t) = {
71 [NFSD_Svc] = write_svc,
72 [NFSD_Add] = write_add,
73 [NFSD_Del] = write_del,
74 [NFSD_Export] = write_export,
75 [NFSD_Unexport] = write_unexport,
76 [NFSD_Getfd] = write_getfd,
77 [NFSD_Getfs] = write_getfs,
78 [NFSD_Fh] = write_filehandle,
79 [NFSD_Threads] = write_threads,
80 [NFSD_Leasetime] = write_leasetime,
81};
82
83static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
84{
85 ino_t ino = file->f_dentry->d_inode->i_ino;
86 char *data;
87 ssize_t rv;
88
89 if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
90 return -EINVAL;
91
92 data = simple_transaction_get(file, buf, size);
93 if (IS_ERR(data))
94 return PTR_ERR(data);
95
96 rv = write_op[ino](file, data, size);
97 if (rv>0) {
98 simple_transaction_set(file, rv);
99 rv = size;
100 }
101 return rv;
102}
103
104static struct file_operations transaction_ops = {
105 .write = nfsctl_transaction_write,
106 .read = simple_transaction_read,
107 .release = simple_transaction_release,
108};
109
110extern struct seq_operations nfs_exports_op;
111static int exports_open(struct inode *inode, struct file *file)
112{
113 return seq_open(file, &nfs_exports_op);
114}
115
116static struct file_operations exports_operations = {
117 .open = exports_open,
118 .read = seq_read,
119 .llseek = seq_lseek,
120 .release = seq_release,
121};
122
123/*----------------------------------------------------------------------------*/
124/*
125 * payload - write methods
126 * If the method has a response, the response should be put in buf,
127 * and the length returned. Otherwise return 0 or and -error.
128 */
129
130static ssize_t write_svc(struct file *file, char *buf, size_t size)
131{
132 struct nfsctl_svc *data;
133 if (size < sizeof(*data))
134 return -EINVAL;
135 data = (struct nfsctl_svc*) buf;
136 return nfsd_svc(data->svc_port, data->svc_nthreads);
137}
138
139static ssize_t write_add(struct file *file, char *buf, size_t size)
140{
141 struct nfsctl_client *data;
142 if (size < sizeof(*data))
143 return -EINVAL;
144 data = (struct nfsctl_client *)buf;
145 return exp_addclient(data);
146}
147
148static ssize_t write_del(struct file *file, char *buf, size_t size)
149{
150 struct nfsctl_client *data;
151 if (size < sizeof(*data))
152 return -EINVAL;
153 data = (struct nfsctl_client *)buf;
154 return exp_delclient(data);
155}
156
157static ssize_t write_export(struct file *file, char *buf, size_t size)
158{
159 struct nfsctl_export *data;
160 if (size < sizeof(*data))
161 return -EINVAL;
162 data = (struct nfsctl_export*)buf;
163 return exp_export(data);
164}
165
166static ssize_t write_unexport(struct file *file, char *buf, size_t size)
167{
168 struct nfsctl_export *data;
169
170 if (size < sizeof(*data))
171 return -EINVAL;
172 data = (struct nfsctl_export*)buf;
173 return exp_unexport(data);
174}
175
176static ssize_t write_getfs(struct file *file, char *buf, size_t size)
177{
178 struct nfsctl_fsparm *data;
179 struct sockaddr_in *sin;
180 struct auth_domain *clp;
181 int err = 0;
182 struct knfsd_fh *res;
183
184 if (size < sizeof(*data))
185 return -EINVAL;
186 data = (struct nfsctl_fsparm*)buf;
187 err = -EPROTONOSUPPORT;
188 if (data->gd_addr.sa_family != AF_INET)
189 goto out;
190 sin = (struct sockaddr_in *)&data->gd_addr;
191 if (data->gd_maxlen > NFS3_FHSIZE)
192 data->gd_maxlen = NFS3_FHSIZE;
193
194 res = (struct knfsd_fh*)buf;
195
196 exp_readlock();
197 if (!(clp = auth_unix_lookup(sin->sin_addr)))
198 err = -EPERM;
199 else {
200 err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
201 auth_domain_put(clp);
202 }
203 exp_readunlock();
204 if (err == 0)
205 err = res->fh_size + (int)&((struct knfsd_fh*)0)->fh_base;
206 out:
207 return err;
208}
209
210static ssize_t write_getfd(struct file *file, char *buf, size_t size)
211{
212 struct nfsctl_fdparm *data;
213 struct sockaddr_in *sin;
214 struct auth_domain *clp;
215 int err = 0;
216 struct knfsd_fh fh;
217 char *res;
218
219 if (size < sizeof(*data))
220 return -EINVAL;
221 data = (struct nfsctl_fdparm*)buf;
222 err = -EPROTONOSUPPORT;
223 if (data->gd_addr.sa_family != AF_INET)
224 goto out;
225 err = -EINVAL;
226 if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
227 goto out;
228
229 res = buf;
230 sin = (struct sockaddr_in *)&data->gd_addr;
231 exp_readlock();
232 if (!(clp = auth_unix_lookup(sin->sin_addr)))
233 err = -EPERM;
234 else {
235 err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
236 auth_domain_put(clp);
237 }
238 exp_readunlock();
239
240 if (err == 0) {
241 memset(res,0, NFS_FHSIZE);
242 memcpy(res, &fh.fh_base, fh.fh_size);
243 err = NFS_FHSIZE;
244 }
245 out:
246 return err;
247}
248
249static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
250{
251 /* request is:
252 * domain path maxsize
253 * response is
254 * filehandle
255 *
256 * qword quoting is used, so filehandle will be \x....
257 */
258 char *dname, *path;
259 int maxsize;
260 char *mesg = buf;
261 int len;
262 struct auth_domain *dom;
263 struct knfsd_fh fh;
264
265 if (buf[size-1] != '\n')
266 return -EINVAL;
267 buf[size-1] = 0;
268
269 dname = mesg;
270 len = qword_get(&mesg, dname, size);
271 if (len <= 0) return -EINVAL;
272
273 path = dname+len+1;
274 len = qword_get(&mesg, path, size);
275 if (len <= 0) return -EINVAL;
276
277 len = get_int(&mesg, &maxsize);
278 if (len)
279 return len;
280
281 if (maxsize < NFS_FHSIZE)
282 return -EINVAL;
283 if (maxsize > NFS3_FHSIZE)
284 maxsize = NFS3_FHSIZE;
285
286 if (qword_get(&mesg, mesg, size)>0)
287 return -EINVAL;
288
289 /* we have all the words, they are in buf.. */
290 dom = unix_domain_find(dname);
291 if (!dom)
292 return -ENOMEM;
293
294 len = exp_rootfh(dom, path, &fh, maxsize);
295 auth_domain_put(dom);
296 if (len)
297 return len;
298
299 mesg = buf; len = SIMPLE_TRANSACTION_LIMIT;
300 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
301 mesg[-1] = '\n';
302 return mesg - buf;
303}
304
305extern int nfsd_nrthreads(void);
306
307static ssize_t write_threads(struct file *file, char *buf, size_t size)
308{
309 /* if size > 0, look for a number of threads and call nfsd_svc
310 * then write out number of threads as reply
311 */
312 char *mesg = buf;
313 int rv;
314 if (size > 0) {
315 int newthreads;
316 rv = get_int(&mesg, &newthreads);
317 if (rv)
318 return rv;
319 if (newthreads <0)
320 return -EINVAL;
321 rv = nfsd_svc(2049, newthreads);
322 if (rv)
323 return rv;
324 }
325 sprintf(buf, "%d\n", nfsd_nrthreads());
326 return strlen(buf);
327}
328
329extern time_t nfs4_leasetime(void);
330
331static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
332{
333 /* if size > 10 seconds, call
334 * nfs4_reset_lease() then write out the new lease (seconds) as reply
335 */
336 char *mesg = buf;
337 int rv;
338
339 if (size > 0) {
340 int lease;
341 rv = get_int(&mesg, &lease);
342 if (rv)
343 return rv;
344 if (lease < 10 || lease > 3600)
345 return -EINVAL;
346 nfs4_reset_lease(lease);
347 }
348 sprintf(buf, "%ld\n", nfs4_lease_time());
349 return strlen(buf);
350}
351
352/*----------------------------------------------------------------------------*/
353/*
354 * populating the filesystem.
355 */
356
357static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
358{
359 static struct tree_descr nfsd_files[] = {
360 [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
361 [NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
362 [NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
363 [NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
364 [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
365 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
366 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
367 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
368 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
369 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
370#ifdef CONFIG_NFSD_V4
371 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
372#endif
373 /* last one */ {""}
374 };
375 return simple_fill_super(sb, 0x6e667364, nfsd_files);
376}
377
378static struct super_block *nfsd_get_sb(struct file_system_type *fs_type,
379 int flags, const char *dev_name, void *data)
380{
381 return get_sb_single(fs_type, flags, data, nfsd_fill_super);
382}
383
384static struct file_system_type nfsd_fs_type = {
385 .owner = THIS_MODULE,
386 .name = "nfsd",
387 .get_sb = nfsd_get_sb,
388 .kill_sb = kill_litter_super,
389};
390
391static int __init init_nfsd(void)
392{
393 int retval;
394 printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
395
396 nfsd_stat_init(); /* Statistics */
397 nfsd_cache_init(); /* RPC reply cache */
398 nfsd_export_init(); /* Exports table */
399 nfsd_lockd_init(); /* lockd->nfsd callbacks */
400#ifdef CONFIG_NFSD_V4
401 nfsd_idmap_init(); /* Name to ID mapping */
402#endif /* CONFIG_NFSD_V4 */
403 if (proc_mkdir("fs/nfs", NULL)) {
404 struct proc_dir_entry *entry;
405 entry = create_proc_entry("fs/nfs/exports", 0, NULL);
406 if (entry)
407 entry->proc_fops = &exports_operations;
408 }
409 retval = register_filesystem(&nfsd_fs_type);
410 if (retval) {
411 nfsd_export_shutdown();
412 nfsd_cache_shutdown();
413 remove_proc_entry("fs/nfs/exports", NULL);
414 remove_proc_entry("fs/nfs", NULL);
415 nfsd_stat_shutdown();
416 nfsd_lockd_shutdown();
417 }
418 return retval;
419}
420
421static void __exit exit_nfsd(void)
422{
423 nfsd_export_shutdown();
424 nfsd_cache_shutdown();
425 remove_proc_entry("fs/nfs/exports", NULL);
426 remove_proc_entry("fs/nfs", NULL);
427 nfsd_stat_shutdown();
428 nfsd_lockd_shutdown();
429#ifdef CONFIG_NFSD_V4
430 nfsd_idmap_shutdown();
431#endif /* CONFIG_NFSD_V4 */
432 unregister_filesystem(&nfsd_fs_type);
433}
434
435MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
436MODULE_LICENSE("GPL");
437module_init(init_nfsd)
438module_exit(exit_nfsd)
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
new file mode 100644
index 000000000000..7a3e397b4ed3
--- /dev/null
+++ b/fs/nfsd/nfsfh.c
@@ -0,0 +1,532 @@
1/*
2 * linux/fs/nfsd/nfsfh.c
3 *
4 * NFS server file handle treatment.
5 *
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 * Portions Copyright (C) 1999 G. Allen Morris III <gam3@acm.org>
8 * Extensive rewrite by Neil Brown <neilb@cse.unsw.edu.au> Southern-Spring 1999
9 * ... and again Southern-Winter 2001 to support export_operations
10 */
11
12#include <linux/sched.h>
13#include <linux/slab.h>
14#include <linux/smp_lock.h>
15#include <linux/fs.h>
16#include <linux/unistd.h>
17#include <linux/string.h>
18#include <linux/stat.h>
19#include <linux/dcache.h>
20#include <linux/mount.h>
21#include <asm/pgtable.h>
22
23#include <linux/sunrpc/svc.h>
24#include <linux/nfsd/nfsd.h>
25
26#define NFSDDBG_FACILITY NFSDDBG_FH
27#define NFSD_PARANOIA 1
28/* #define NFSD_DEBUG_VERBOSE 1 */
29
30
31static int nfsd_nr_verified;
32static int nfsd_nr_put;
33
34extern struct export_operations export_op_default;
35
36#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
37
38/*
39 * our acceptability function.
40 * if NOSUBTREECHECK, accept anything
41 * if not, require that we can walk up to exp->ex_dentry
42 * doing some checks on the 'x' bits
43 */
44static int nfsd_acceptable(void *expv, struct dentry *dentry)
45{
46 struct svc_export *exp = expv;
47 int rv;
48 struct dentry *tdentry;
49 struct dentry *parent;
50
51 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
52 return 1;
53
54 tdentry = dget(dentry);
55 while (tdentry != exp->ex_dentry && ! IS_ROOT(tdentry)) {
56 /* make sure parents give x permission to user */
57 int err;
58 parent = dget_parent(tdentry);
59 err = permission(parent->d_inode, MAY_EXEC, NULL);
60 if (err < 0) {
61 dput(parent);
62 break;
63 }
64 dput(tdentry);
65 tdentry = parent;
66 }
67 if (tdentry != exp->ex_dentry)
68 dprintk("nfsd_acceptable failed at %p %s\n", tdentry, tdentry->d_name.name);
69 rv = (tdentry == exp->ex_dentry);
70 dput(tdentry);
71 return rv;
72}
73
74/* Type check. The correct error return for type mismatches does not seem to be
75 * generally agreed upon. SunOS seems to use EISDIR if file isn't S_IFREG; a
76 * comment in the NFSv3 spec says this is incorrect (implementation notes for
77 * the write call).
78 */
79static inline int
80nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
81{
82 /* Type can be negative when creating hardlinks - not to a dir */
83 if (type > 0 && (mode & S_IFMT) != type) {
84 if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
85 return nfserr_symlink;
86 else if (type == S_IFDIR)
87 return nfserr_notdir;
88 else if ((mode & S_IFMT) == S_IFDIR)
89 return nfserr_isdir;
90 else
91 return nfserr_inval;
92 }
93 if (type < 0 && (mode & S_IFMT) == -type) {
94 if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
95 return nfserr_symlink;
96 else if (type == -S_IFDIR)
97 return nfserr_isdir;
98 else
99 return nfserr_notdir;
100 }
101 return 0;
102}
103
104/*
105 * Perform sanity checks on the dentry in a client's file handle.
106 *
107 * Note that the file handle dentry may need to be freed even after
108 * an error return.
109 *
110 * This is only called at the start of an nfsproc call, so fhp points to
111 * a svc_fh which is all 0 except for the over-the-wire file handle.
112 */
113u32
114fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
115{
116 struct knfsd_fh *fh = &fhp->fh_handle;
117 struct svc_export *exp = NULL;
118 struct dentry *dentry;
119 u32 error = 0;
120
121 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
122
123 /* keep this filehandle for possible reference when encoding attributes */
124 rqstp->rq_reffh = fh;
125
126 if (!fhp->fh_dentry) {
127 __u32 *datap=NULL;
128 __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
129 int fileid_type;
130 int data_left = fh->fh_size/4;
131
132 error = nfserr_stale;
133 if (rqstp->rq_client == NULL)
134 goto out;
135 if (rqstp->rq_vers > 2)
136 error = nfserr_badhandle;
137 if (rqstp->rq_vers == 4 && fh->fh_size == 0)
138 return nfserr_nofilehandle;
139
140 if (fh->fh_version == 1) {
141 int len;
142 datap = fh->fh_auth;
143 if (--data_left<0) goto out;
144 switch (fh->fh_auth_type) {
145 case 0: break;
146 default: goto out;
147 }
148 len = key_len(fh->fh_fsid_type) / 4;
149 if (len == 0) goto out;
150 if (fh->fh_fsid_type == 2) {
151 /* deprecated, convert to type 3 */
152 len = 3;
153 fh->fh_fsid_type = 3;
154 fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
155 fh->fh_fsid[1] = fh->fh_fsid[2];
156 }
157 if ((data_left -= len)<0) goto out;
158 exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap, &rqstp->rq_chandle);
159 datap += len;
160 } else {
161 dev_t xdev;
162 ino_t xino;
163 if (fh->fh_size != NFS_FHSIZE)
164 goto out;
165 /* assume old filehandle format */
166 xdev = old_decode_dev(fh->ofh_xdev);
167 xino = u32_to_ino_t(fh->ofh_xino);
168 mk_fsid_v0(tfh, xdev, xino);
169 exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
170 }
171
172 error = nfserr_dropit;
173 if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
174 goto out;
175
176 error = nfserr_stale;
177 if (!exp || IS_ERR(exp))
178 goto out;
179
180 /* Check if the request originated from a secure port. */
181 error = nfserr_perm;
182 if (!rqstp->rq_secure && EX_SECURE(exp)) {
183 printk(KERN_WARNING
184 "nfsd: request from insecure port (%u.%u.%u.%u:%d)!\n",
185 NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
186 ntohs(rqstp->rq_addr.sin_port));
187 goto out;
188 }
189
190 /* Set user creds for this exportpoint */
191 error = nfsd_setuser(rqstp, exp);
192 if (error) {
193 error = nfserrno(error);
194 goto out;
195 }
196
197 /*
198 * Look up the dentry using the NFS file handle.
199 */
200 error = nfserr_stale;
201 if (rqstp->rq_vers > 2)
202 error = nfserr_badhandle;
203
204 if (fh->fh_version != 1) {
205 tfh[0] = fh->ofh_ino;
206 tfh[1] = fh->ofh_generation;
207 tfh[2] = fh->ofh_dirino;
208 datap = tfh;
209 data_left = 3;
210 if (fh->ofh_dirino == 0)
211 fileid_type = 1;
212 else
213 fileid_type = 2;
214 } else
215 fileid_type = fh->fh_fileid_type;
216
217 if (fileid_type == 0)
218 dentry = dget(exp->ex_dentry);
219 else {
220 struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
221 dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
222 datap, data_left,
223 fileid_type,
224 nfsd_acceptable, exp);
225 }
226 if (dentry == NULL)
227 goto out;
228 if (IS_ERR(dentry)) {
229 if (PTR_ERR(dentry) != -EINVAL)
230 error = nfserrno(PTR_ERR(dentry));
231 goto out;
232 }
233#ifdef NFSD_PARANOIA
234 if (S_ISDIR(dentry->d_inode->i_mode) &&
235 (dentry->d_flags & DCACHE_DISCONNECTED)) {
236 printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
237 dentry->d_parent->d_name.name, dentry->d_name.name);
238 }
239#endif
240
241 fhp->fh_dentry = dentry;
242 fhp->fh_export = exp;
243 nfsd_nr_verified++;
244 } else {
245 /* just rechecking permissions
246 * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
247 */
248 dprintk("nfsd: fh_verify - just checking\n");
249 dentry = fhp->fh_dentry;
250 exp = fhp->fh_export;
251 }
252 cache_get(&exp->h);
253
254 error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
255 if (error)
256 goto out;
257
258 /* Finally, check access permissions. */
259 error = nfsd_permission(exp, dentry, access);
260
261#ifdef NFSD_PARANOIA_EXTREME
262 if (error) {
263 printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
264 dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
265 }
266#endif
267out:
268 if (exp && !IS_ERR(exp))
269 exp_put(exp);
270 if (error == nfserr_stale)
271 nfsdstats.fh_stale++;
272 return error;
273}
274
275
276/*
277 * Compose a file handle for an NFS reply.
278 *
279 * Note that when first composed, the dentry may not yet have
280 * an inode. In this case a call to fh_update should be made
281 * before the fh goes out on the wire ...
282 */
283static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
284 __u32 *datap, int *maxsize)
285{
286 struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
287
288 if (dentry == exp->ex_dentry) {
289 *maxsize = 0;
290 return 0;
291 }
292
293 return CALL(nop,encode_fh)(dentry, datap, maxsize,
294 !(exp->ex_flags&NFSEXP_NOSUBTREECHECK));
295}
296
297/*
298 * for composing old style file handles
299 */
300static inline void _fh_update_old(struct dentry *dentry,
301 struct svc_export *exp,
302 struct knfsd_fh *fh)
303{
304 fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
305 fh->ofh_generation = dentry->d_inode->i_generation;
306 if (S_ISDIR(dentry->d_inode->i_mode) ||
307 (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
308 fh->ofh_dirino = 0;
309}
310
311int
312fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
313{
314 /* ref_fh is a reference file handle.
315 * if it is non-null, then we should compose a filehandle which is
316 * of the same version, where possible.
317 * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
318 * Then create a 32byte filehandle using nfs_fhbase_old
319 *
320 */
321
322 u8 ref_fh_version = 0;
323 u8 ref_fh_fsid_type = 0;
324 struct inode * inode = dentry->d_inode;
325 struct dentry *parent = dentry->d_parent;
326 __u32 *datap;
327 dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev;
328
329 dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
330 MAJOR(ex_dev), MINOR(ex_dev),
331 (long) exp->ex_dentry->d_inode->i_ino,
332 parent->d_name.name, dentry->d_name.name,
333 (inode ? inode->i_ino : 0));
334
335 if (ref_fh) {
336 ref_fh_version = ref_fh->fh_handle.fh_version;
337 if (ref_fh_version == 0xca)
338 ref_fh_fsid_type = 0;
339 else
340 ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type;
341 if (ref_fh_fsid_type > 3)
342 ref_fh_fsid_type = 0;
343
344 /* make sure ref_fh type works for given export */
345 if (ref_fh_fsid_type == 1 &&
346 !(exp->ex_flags & NFSEXP_FSID)) {
347 /* if we don't have an fsid, we cannot provide one... */
348 ref_fh_fsid_type = 0;
349 }
350 } else if (exp->ex_flags & NFSEXP_FSID)
351 ref_fh_fsid_type = 1;
352
353 if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) {
354 /* for newer device numbers, we must use a newer fsid format */
355 ref_fh_version = 1;
356 ref_fh_fsid_type = 3;
357 }
358 if (old_valid_dev(ex_dev) &&
359 (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3))
360 /* must use type1 for smaller device numbers */
361 ref_fh_fsid_type = 0;
362
363 if (ref_fh == fhp)
364 fh_put(ref_fh);
365
366 if (fhp->fh_locked || fhp->fh_dentry) {
367 printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
368 parent->d_name.name, dentry->d_name.name);
369 }
370 if (fhp->fh_maxsize < NFS_FHSIZE)
371 printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
372 fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
373
374 fhp->fh_dentry = dget(dentry); /* our internal copy */
375 fhp->fh_export = exp;
376 cache_get(&exp->h);
377
378 if (ref_fh_version == 0xca) {
379 /* old style filehandle please */
380 memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
381 fhp->fh_handle.fh_size = NFS_FHSIZE;
382 fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
383 fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev);
384 fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
385 fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
386 fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
387 if (inode)
388 _fh_update_old(dentry, exp, &fhp->fh_handle);
389 } else {
390 int len;
391 fhp->fh_handle.fh_version = 1;
392 fhp->fh_handle.fh_auth_type = 0;
393 datap = fhp->fh_handle.fh_auth+0;
394 fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type;
395 switch (ref_fh_fsid_type) {
396 case 0:
397 /*
398 * fsid_type 0:
399 * 2byte major, 2byte minor, 4byte inode
400 */
401 mk_fsid_v0(datap, ex_dev,
402 exp->ex_dentry->d_inode->i_ino);
403 break;
404 case 1:
405 /* fsid_type 1 == 4 bytes filesystem id */
406 mk_fsid_v1(datap, exp->ex_fsid);
407 break;
408 case 2:
409 /*
410 * fsid_type 2:
411 * 4byte major, 4byte minor, 4byte inode
412 */
413 mk_fsid_v2(datap, ex_dev,
414 exp->ex_dentry->d_inode->i_ino);
415 break;
416 case 3:
417 /*
418 * fsid_type 3:
419 * 4byte devicenumber, 4byte inode
420 */
421 mk_fsid_v3(datap, ex_dev,
422 exp->ex_dentry->d_inode->i_ino);
423 break;
424 }
425 len = key_len(ref_fh_fsid_type);
426 datap += len/4;
427 fhp->fh_handle.fh_size = 4 + len;
428
429 if (inode) {
430 int size = (fhp->fh_maxsize-len-4)/4;
431 fhp->fh_handle.fh_fileid_type =
432 _fh_update(dentry, exp, datap, &size);
433 fhp->fh_handle.fh_size += size*4;
434 }
435 if (fhp->fh_handle.fh_fileid_type == 255)
436 return nfserr_opnotsupp;
437 }
438
439 nfsd_nr_verified++;
440 return 0;
441}
442
443/*
444 * Update file handle information after changing a dentry.
445 * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
446 */
447int
448fh_update(struct svc_fh *fhp)
449{
450 struct dentry *dentry;
451 __u32 *datap;
452
453 if (!fhp->fh_dentry)
454 goto out_bad;
455
456 dentry = fhp->fh_dentry;
457 if (!dentry->d_inode)
458 goto out_negative;
459 if (fhp->fh_handle.fh_version != 1) {
460 _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
461 } else {
462 int size;
463 if (fhp->fh_handle.fh_fileid_type != 0)
464 goto out_uptodate;
465 datap = fhp->fh_handle.fh_auth+
466 fhp->fh_handle.fh_size/4 -1;
467 size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
468 fhp->fh_handle.fh_fileid_type =
469 _fh_update(dentry, fhp->fh_export, datap, &size);
470 fhp->fh_handle.fh_size += size*4;
471 if (fhp->fh_handle.fh_fileid_type == 255)
472 return nfserr_opnotsupp;
473 }
474out:
475 return 0;
476
477out_bad:
478 printk(KERN_ERR "fh_update: fh not verified!\n");
479 goto out;
480out_negative:
481 printk(KERN_ERR "fh_update: %s/%s still negative!\n",
482 dentry->d_parent->d_name.name, dentry->d_name.name);
483 goto out;
484out_uptodate:
485 printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
486 dentry->d_parent->d_name.name, dentry->d_name.name);
487 goto out;
488}
489
490/*
491 * Release a file handle.
492 */
493void
494fh_put(struct svc_fh *fhp)
495{
496 struct dentry * dentry = fhp->fh_dentry;
497 struct svc_export * exp = fhp->fh_export;
498 if (dentry) {
499 fh_unlock(fhp);
500 fhp->fh_dentry = NULL;
501 dput(dentry);
502#ifdef CONFIG_NFSD_V3
503 fhp->fh_pre_saved = 0;
504 fhp->fh_post_saved = 0;
505#endif
506 nfsd_nr_put++;
507 }
508 if (exp) {
509 svc_export_put(&exp->h, &svc_export_cache);
510 fhp->fh_export = NULL;
511 }
512 return;
513}
514
515/*
516 * Shorthand for dprintk()'s
517 */
518char * SVCFH_fmt(struct svc_fh *fhp)
519{
520 struct knfsd_fh *fh = &fhp->fh_handle;
521
522 static char buf[80];
523 sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x",
524 fh->fh_size,
525 fh->fh_base.fh_pad[0],
526 fh->fh_base.fh_pad[1],
527 fh->fh_base.fh_pad[2],
528 fh->fh_base.fh_pad[3],
529 fh->fh_base.fh_pad[4],
530 fh->fh_base.fh_pad[5]);
531 return buf;
532}
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
new file mode 100644
index 000000000000..757f9d208034
--- /dev/null
+++ b/fs/nfsd/nfsproc.c
@@ -0,0 +1,605 @@
1/*
2 * nfsproc2.c Process version 2 NFS requests.
3 * linux/fs/nfsd/nfs2proc.c
4 *
5 * Process version 2 NFS requests.
6 *
7 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
8 */
9
10#include <linux/linkage.h>
11#include <linux/time.h>
12#include <linux/errno.h>
13#include <linux/fs.h>
14#include <linux/stat.h>
15#include <linux/fcntl.h>
16#include <linux/net.h>
17#include <linux/in.h>
18#include <linux/namei.h>
19#include <linux/unistd.h>
20#include <linux/slab.h>
21
22#include <linux/sunrpc/svc.h>
23#include <linux/nfsd/nfsd.h>
24#include <linux/nfsd/cache.h>
25#include <linux/nfsd/xdr.h>
26
27typedef struct svc_rqst svc_rqst;
28typedef struct svc_buf svc_buf;
29
30#define NFSDDBG_FACILITY NFSDDBG_PROC
31
32
33static int
34nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
35{
36 return nfs_ok;
37}
38
39/*
40 * Get a file's attributes
41 * N.B. After this call resp->fh needs an fh_put
42 */
43static int
44nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
45 struct nfsd_attrstat *resp)
46{
47 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
48
49 fh_copy(&resp->fh, &argp->fh);
50 return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
51}
52
53/*
54 * Set a file's attributes
55 * N.B. After this call resp->fh needs an fh_put
56 */
57static int
58nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
59 struct nfsd_attrstat *resp)
60{
61 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
62 SVCFH_fmt(&argp->fh),
63 argp->attrs.ia_valid, (long) argp->attrs.ia_size);
64
65 fh_copy(&resp->fh, &argp->fh);
66 return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
67}
68
69/*
70 * Look up a path name component
71 * Note: the dentry in the resp->fh may be negative if the file
72 * doesn't exist yet.
73 * N.B. After this call resp->fh needs an fh_put
74 */
75static int
76nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
77 struct nfsd_diropres *resp)
78{
79 int nfserr;
80
81 dprintk("nfsd: LOOKUP %s %.*s\n",
82 SVCFH_fmt(&argp->fh), argp->len, argp->name);
83
84 fh_init(&resp->fh, NFS_FHSIZE);
85 nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
86 &resp->fh);
87
88 fh_put(&argp->fh);
89 return nfserr;
90}
91
92/*
93 * Read a symlink.
94 */
95static int
96nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_readlinkargs *argp,
97 struct nfsd_readlinkres *resp)
98{
99 int nfserr;
100
101 dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
102
103 /* Read the symlink. */
104 resp->len = NFS_MAXPATHLEN;
105 nfserr = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len);
106
107 fh_put(&argp->fh);
108 return nfserr;
109}
110
111/*
112 * Read a portion of a file.
113 * N.B. After this call resp->fh needs an fh_put
114 */
115static int
116nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
117 struct nfsd_readres *resp)
118{
119 int nfserr;
120
121 dprintk("nfsd: READ %s %d bytes at %d\n",
122 SVCFH_fmt(&argp->fh),
123 argp->count, argp->offset);
124
125 /* Obtain buffer pointer for payload. 19 is 1 word for
126 * status, 17 words for fattr, and 1 word for the byte count.
127 */
128
129 if (NFSSVC_MAXBLKSIZE < argp->count) {
130 printk(KERN_NOTICE
131 "oversized read request from %u.%u.%u.%u:%d (%d bytes)\n",
132 NIPQUAD(rqstp->rq_addr.sin_addr.s_addr),
133 ntohs(rqstp->rq_addr.sin_port),
134 argp->count);
135 argp->count = NFSSVC_MAXBLKSIZE;
136 }
137 svc_reserve(rqstp, (19<<2) + argp->count + 4);
138
139 resp->count = argp->count;
140 nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
141 argp->offset,
142 argp->vec, argp->vlen,
143 &resp->count);
144
145 return nfserr;
146}
147
148/*
149 * Write data to a file
150 * N.B. After this call resp->fh needs an fh_put
151 */
152static int
153nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
154 struct nfsd_attrstat *resp)
155{
156 int nfserr;
157 int stable = 1;
158
159 dprintk("nfsd: WRITE %s %d bytes at %d\n",
160 SVCFH_fmt(&argp->fh),
161 argp->len, argp->offset);
162
163 nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
164 argp->offset,
165 argp->vec, argp->vlen,
166 argp->len,
167 &stable);
168 return nfserr;
169}
170
171/*
172 * CREATE processing is complicated. The keyword here is `overloaded.'
173 * The parent directory is kept locked between the check for existence
174 * and the actual create() call in compliance with VFS protocols.
175 * N.B. After this call _both_ argp->fh and resp->fh need an fh_put
176 */
177static int
178nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
179 struct nfsd_diropres *resp)
180{
181 svc_fh *dirfhp = &argp->fh;
182 svc_fh *newfhp = &resp->fh;
183 struct iattr *attr = &argp->attrs;
184 struct inode *inode;
185 struct dentry *dchild;
186 int nfserr, type, mode;
187 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size);
188
189 dprintk("nfsd: CREATE %s %.*s\n",
190 SVCFH_fmt(dirfhp), argp->len, argp->name);
191
192 /* First verify the parent file handle */
193 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
194 if (nfserr)
195 goto done; /* must fh_put dirfhp even on error */
196
197 /* Check for MAY_WRITE in nfsd_create if necessary */
198
199 nfserr = nfserr_acces;
200 if (!argp->len)
201 goto done;
202 nfserr = nfserr_exist;
203 if (isdotent(argp->name, argp->len))
204 goto done;
205 fh_lock(dirfhp);
206 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
207 if (IS_ERR(dchild)) {
208 nfserr = nfserrno(PTR_ERR(dchild));
209 goto out_unlock;
210 }
211 fh_init(newfhp, NFS_FHSIZE);
212 nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
213 if (!nfserr && !dchild->d_inode)
214 nfserr = nfserr_noent;
215 dput(dchild);
216 if (nfserr) {
217 if (nfserr != nfserr_noent)
218 goto out_unlock;
219 /*
220 * If the new file handle wasn't verified, we can't tell
221 * whether the file exists or not. Time to bail ...
222 */
223 nfserr = nfserr_acces;
224 if (!newfhp->fh_dentry) {
225 printk(KERN_WARNING
226 "nfsd_proc_create: file handle not verified\n");
227 goto out_unlock;
228 }
229 }
230
231 inode = newfhp->fh_dentry->d_inode;
232
233 /* Unfudge the mode bits */
234 if (attr->ia_valid & ATTR_MODE) {
235 type = attr->ia_mode & S_IFMT;
236 mode = attr->ia_mode & ~S_IFMT;
237 if (!type) {
238 /* no type, so if target exists, assume same as that,
239 * else assume a file */
240 if (inode) {
241 type = inode->i_mode & S_IFMT;
242 switch(type) {
243 case S_IFCHR:
244 case S_IFBLK:
245 /* reserve rdev for later checking */
246 rdev = inode->i_rdev;
247 attr->ia_valid |= ATTR_SIZE;
248
249 /* FALLTHROUGH */
250 case S_IFIFO:
251 /* this is probably a permission check..
252 * at least IRIX implements perm checking on
253 * echo thing > device-special-file-or-pipe
254 * by doing a CREATE with type==0
255 */
256 nfserr = nfsd_permission(newfhp->fh_export,
257 newfhp->fh_dentry,
258 MAY_WRITE|MAY_LOCAL_ACCESS);
259 if (nfserr && nfserr != nfserr_rofs)
260 goto out_unlock;
261 }
262 } else
263 type = S_IFREG;
264 }
265 } else if (inode) {
266 type = inode->i_mode & S_IFMT;
267 mode = inode->i_mode & ~S_IFMT;
268 } else {
269 type = S_IFREG;
270 mode = 0; /* ??? */
271 }
272
273 attr->ia_valid |= ATTR_MODE;
274 attr->ia_mode = mode;
275
276 /* Special treatment for non-regular files according to the
277 * gospel of sun micro
278 */
279 if (type != S_IFREG) {
280 int is_borc = 0;
281 if (type != S_IFBLK && type != S_IFCHR) {
282 rdev = 0;
283 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
284 /* If you think you've seen the worst, grok this. */
285 type = S_IFIFO;
286 } else {
287 /* Okay, char or block special */
288 is_borc = 1;
289 if (!rdev)
290 rdev = wanted;
291 }
292
293 /* we've used the SIZE information, so discard it */
294 attr->ia_valid &= ~ATTR_SIZE;
295
296 /* Make sure the type and device matches */
297 nfserr = nfserr_exist;
298 if (inode && type != (inode->i_mode & S_IFMT))
299 goto out_unlock;
300 }
301
302 nfserr = 0;
303 if (!inode) {
304 /* File doesn't exist. Create it and set attrs */
305 nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
306 attr, type, rdev, newfhp);
307 } else if (type == S_IFREG) {
308 dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
309 argp->name, attr->ia_valid, (long) attr->ia_size);
310 /* File already exists. We ignore all attributes except
311 * size, so that creat() behaves exactly like
312 * open(..., O_CREAT|O_TRUNC|O_WRONLY).
313 */
314 attr->ia_valid &= ATTR_SIZE;
315 if (attr->ia_valid)
316 nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0);
317 }
318
319out_unlock:
320 /* We don't really need to unlock, as fh_put does it. */
321 fh_unlock(dirfhp);
322
323done:
324 fh_put(dirfhp);
325 return nfserr;
326}
327
328static int
329nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
330 void *resp)
331{
332 int nfserr;
333
334 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh),
335 argp->len, argp->name);
336
337 /* Unlink. -SIFDIR means file must not be a directory */
338 nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
339 fh_put(&argp->fh);
340 return nfserr;
341}
342
343static int
344nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp,
345 void *resp)
346{
347 int nfserr;
348
349 dprintk("nfsd: RENAME %s %.*s -> \n",
350 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
351 dprintk("nfsd: -> %s %.*s\n",
352 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
353
354 nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
355 &argp->tfh, argp->tname, argp->tlen);
356 fh_put(&argp->ffh);
357 fh_put(&argp->tfh);
358 return nfserr;
359}
360
361static int
362nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp,
363 void *resp)
364{
365 int nfserr;
366
367 dprintk("nfsd: LINK %s ->\n",
368 SVCFH_fmt(&argp->ffh));
369 dprintk("nfsd: %s %.*s\n",
370 SVCFH_fmt(&argp->tfh),
371 argp->tlen,
372 argp->tname);
373
374 nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
375 &argp->ffh);
376 fh_put(&argp->ffh);
377 fh_put(&argp->tfh);
378 return nfserr;
379}
380
381static int
382nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
383 void *resp)
384{
385 struct svc_fh newfh;
386 int nfserr;
387
388 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n",
389 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
390 argp->tlen, argp->tname);
391
392 fh_init(&newfh, NFS_FHSIZE);
393 /*
394 * Create the link, look up new file and set attrs.
395 */
396 nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
397 argp->tname, argp->tlen,
398 &newfh, &argp->attrs);
399
400
401 fh_put(&argp->ffh);
402 fh_put(&newfh);
403 return nfserr;
404}
405
406/*
407 * Make directory. This operation is not idempotent.
408 * N.B. After this call resp->fh needs an fh_put
409 */
410static int
411nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
412 struct nfsd_diropres *resp)
413{
414 int nfserr;
415
416 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
417
418 if (resp->fh.fh_dentry) {
419 printk(KERN_WARNING
420 "nfsd_proc_mkdir: response already verified??\n");
421 }
422
423 argp->attrs.ia_valid &= ~ATTR_SIZE;
424 fh_init(&resp->fh, NFS_FHSIZE);
425 nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
426 &argp->attrs, S_IFDIR, 0, &resp->fh);
427 fh_put(&argp->fh);
428 return nfserr;
429}
430
431/*
432 * Remove a directory
433 */
434static int
435nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
436 void *resp)
437{
438 int nfserr;
439
440 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
441
442 nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
443 fh_put(&argp->fh);
444 return nfserr;
445}
446
447/*
448 * Read a portion of a directory.
449 */
450static int
451nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
452 struct nfsd_readdirres *resp)
453{
454 int nfserr, count;
455 loff_t offset;
456
457 dprintk("nfsd: READDIR %s %d bytes at %d\n",
458 SVCFH_fmt(&argp->fh),
459 argp->count, argp->cookie);
460
461 /* Shrink to the client read size */
462 count = (argp->count >> 2) - 2;
463
464 /* Make sure we've room for the NULL ptr & eof flag */
465 count -= 2;
466 if (count < 0)
467 count = 0;
468
469 resp->buffer = argp->buffer;
470 resp->offset = NULL;
471 resp->buflen = count;
472 resp->common.err = nfs_ok;
473 /* Read directory and encode entries on the fly */
474 offset = argp->cookie;
475 nfserr = nfsd_readdir(rqstp, &argp->fh, &offset,
476 &resp->common, nfssvc_encode_entry);
477
478 resp->count = resp->buffer - argp->buffer;
479 if (resp->offset)
480 *resp->offset = htonl(offset);
481
482 fh_put(&argp->fh);
483 return nfserr;
484}
485
486/*
487 * Get file system info
488 */
489static int
490nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
491 struct nfsd_statfsres *resp)
492{
493 int nfserr;
494
495 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
496
497 nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
498 fh_put(&argp->fh);
499 return nfserr;
500}
501
502/*
503 * NFSv2 Server procedures.
504 * Only the results of non-idempotent operations are cached.
505 */
506#define nfsd_proc_none NULL
507#define nfssvc_release_none NULL
508struct nfsd_void { int dummy; };
509
510#define PROC(name, argt, rest, relt, cache, respsize) \
511 { (svc_procfunc) nfsd_proc_##name, \
512 (kxdrproc_t) nfssvc_decode_##argt, \
513 (kxdrproc_t) nfssvc_encode_##rest, \
514 (kxdrproc_t) nfssvc_release_##relt, \
515 sizeof(struct nfsd_##argt), \
516 sizeof(struct nfsd_##rest), \
517 0, \
518 cache, \
519 respsize, \
520 }
521
522#define ST 1 /* status */
523#define FH 8 /* filehandle */
524#define AT 18 /* attributes */
525
526static struct svc_procedure nfsd_procedures2[18] = {
527 PROC(null, void, void, none, RC_NOCACHE, ST),
528 PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
529 PROC(setattr, sattrargs, attrstat, fhandle, RC_REPLBUFF, ST+AT),
530 PROC(none, void, void, none, RC_NOCACHE, ST),
531 PROC(lookup, diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT),
532 PROC(readlink, readlinkargs, readlinkres, none, RC_NOCACHE, ST+1+NFS_MAXPATHLEN/4),
533 PROC(read, readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
534 PROC(none, void, void, none, RC_NOCACHE, ST),
535 PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT),
536 PROC(create, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
537 PROC(remove, diropargs, void, none, RC_REPLSTAT, ST),
538 PROC(rename, renameargs, void, none, RC_REPLSTAT, ST),
539 PROC(link, linkargs, void, none, RC_REPLSTAT, ST),
540 PROC(symlink, symlinkargs, void, none, RC_REPLSTAT, ST),
541 PROC(mkdir, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
542 PROC(rmdir, diropargs, void, none, RC_REPLSTAT, ST),
543 PROC(readdir, readdirargs, readdirres, none, RC_NOCACHE, 0),
544 PROC(statfs, fhandle, statfsres, none, RC_NOCACHE, ST+5),
545};
546
547
548struct svc_version nfsd_version2 = {
549 .vs_vers = 2,
550 .vs_nproc = 18,
551 .vs_proc = nfsd_procedures2,
552 .vs_dispatch = nfsd_dispatch,
553 .vs_xdrsize = NFS2_SVC_XDRSIZE,
554};
555
556/*
557 * Map errnos to NFS errnos.
558 */
559int
560nfserrno (int errno)
561{
562 static struct {
563 int nfserr;
564 int syserr;
565 } nfs_errtbl[] = {
566 { nfs_ok, 0 },
567 { nfserr_perm, -EPERM },
568 { nfserr_noent, -ENOENT },
569 { nfserr_io, -EIO },
570 { nfserr_nxio, -ENXIO },
571 { nfserr_acces, -EACCES },
572 { nfserr_exist, -EEXIST },
573 { nfserr_xdev, -EXDEV },
574 { nfserr_mlink, -EMLINK },
575 { nfserr_nodev, -ENODEV },
576 { nfserr_notdir, -ENOTDIR },
577 { nfserr_isdir, -EISDIR },
578 { nfserr_inval, -EINVAL },
579 { nfserr_fbig, -EFBIG },
580 { nfserr_nospc, -ENOSPC },
581 { nfserr_rofs, -EROFS },
582 { nfserr_mlink, -EMLINK },
583 { nfserr_nametoolong, -ENAMETOOLONG },
584 { nfserr_notempty, -ENOTEMPTY },
585#ifdef EDQUOT
586 { nfserr_dquot, -EDQUOT },
587#endif
588 { nfserr_stale, -ESTALE },
589 { nfserr_jukebox, -ETIMEDOUT },
590 { nfserr_dropit, -EAGAIN },
591 { nfserr_dropit, -ENOMEM },
592 { nfserr_badname, -ESRCH },
593 { nfserr_io, -ETXTBSY },
594 { -1, -EIO }
595 };
596 int i;
597
598 for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
599 if (nfs_errtbl[i].syserr == errno)
600 return nfs_errtbl[i].nfserr;
601 }
602 printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
603 return nfserr_io;
604}
605
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
new file mode 100644
index 000000000000..39551657e656
--- /dev/null
+++ b/fs/nfsd/nfssvc.c
@@ -0,0 +1,385 @@
1/*
2 * linux/fs/nfsd/nfssvc.c
3 *
4 * Central processing for nfsd.
5 *
6 * Authors: Olaf Kirch (okir@monad.swb.de)
7 *
8 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
9 */
10
11#include <linux/config.h>
12#include <linux/module.h>
13
14#include <linux/time.h>
15#include <linux/errno.h>
16#include <linux/nfs.h>
17#include <linux/in.h>
18#include <linux/uio.h>
19#include <linux/unistd.h>
20#include <linux/slab.h>
21#include <linux/smp.h>
22#include <linux/smp_lock.h>
23#include <linux/fs_struct.h>
24
25#include <linux/sunrpc/types.h>
26#include <linux/sunrpc/stats.h>
27#include <linux/sunrpc/svc.h>
28#include <linux/sunrpc/svcsock.h>
29#include <linux/sunrpc/cache.h>
30#include <linux/nfsd/nfsd.h>
31#include <linux/nfsd/stats.h>
32#include <linux/nfsd/cache.h>
33#include <linux/lockd/bind.h>
34
35#define NFSDDBG_FACILITY NFSDDBG_SVC
36
37/* these signals will be delivered to an nfsd thread
38 * when handling a request
39 */
40#define ALLOWED_SIGS (sigmask(SIGKILL))
41/* these signals will be delivered to an nfsd thread
42 * when not handling a request. i.e. when waiting
43 */
44#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT))
45/* if the last thread dies with SIGHUP, then the exports table is
46 * left unchanged ( like 2.4-{0-9} ). Any other signal will clear
47 * the exports table (like 2.2).
48 */
49#define SIG_NOCLEAN SIGHUP
50
51extern struct svc_program nfsd_program;
52static void nfsd(struct svc_rqst *rqstp);
53struct timeval nfssvc_boot;
54static struct svc_serv *nfsd_serv;
55static atomic_t nfsd_busy;
56static unsigned long nfsd_last_call;
57static DEFINE_SPINLOCK(nfsd_call_lock);
58
59struct nfsd_list {
60 struct list_head list;
61 struct task_struct *task;
62};
63static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
64
65/*
66 * Maximum number of nfsd processes
67 */
68#define NFSD_MAXSERVS 8192
69
70int nfsd_nrthreads(void)
71{
72 if (nfsd_serv == NULL)
73 return 0;
74 else
75 return nfsd_serv->sv_nrthreads;
76}
77
78int
79nfsd_svc(unsigned short port, int nrservs)
80{
81 int error;
82 int none_left;
83 struct list_head *victim;
84
85 lock_kernel();
86 dprintk("nfsd: creating service\n");
87 error = -EINVAL;
88 if (nrservs <= 0)
89 nrservs = 0;
90 if (nrservs > NFSD_MAXSERVS)
91 nrservs = NFSD_MAXSERVS;
92
93 /* Readahead param cache - will no-op if it already exists */
94 error = nfsd_racache_init(2*nrservs);
95 if (error<0)
96 goto out;
97 error = nfs4_state_init();
98 if (error<0)
99 goto out;
100 if (!nfsd_serv) {
101 atomic_set(&nfsd_busy, 0);
102 error = -ENOMEM;
103 nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
104 if (nfsd_serv == NULL)
105 goto out;
106 error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
107 if (error < 0)
108 goto failure;
109
110#ifdef CONFIG_NFSD_TCP
111 error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
112 if (error < 0)
113 goto failure;
114#endif
115 do_gettimeofday(&nfssvc_boot); /* record boot time */
116 } else
117 nfsd_serv->sv_nrthreads++;
118 nrservs -= (nfsd_serv->sv_nrthreads-1);
119 while (nrservs > 0) {
120 nrservs--;
121 __module_get(THIS_MODULE);
122 error = svc_create_thread(nfsd, nfsd_serv);
123 if (error < 0) {
124 module_put(THIS_MODULE);
125 break;
126 }
127 }
128 victim = nfsd_list.next;
129 while (nrservs < 0 && victim != &nfsd_list) {
130 struct nfsd_list *nl =
131 list_entry(victim,struct nfsd_list, list);
132 victim = victim->next;
133 send_sig(SIG_NOCLEAN, nl->task, 1);
134 nrservs++;
135 }
136 failure:
137 none_left = (nfsd_serv->sv_nrthreads == 1);
138 svc_destroy(nfsd_serv); /* Release server */
139 if (none_left) {
140 nfsd_serv = NULL;
141 nfsd_racache_shutdown();
142 nfs4_state_shutdown();
143 }
144 out:
145 unlock_kernel();
146 return error;
147}
148
149static inline void
150update_thread_usage(int busy_threads)
151{
152 unsigned long prev_call;
153 unsigned long diff;
154 int decile;
155
156 spin_lock(&nfsd_call_lock);
157 prev_call = nfsd_last_call;
158 nfsd_last_call = jiffies;
159 decile = busy_threads*10/nfsdstats.th_cnt;
160 if (decile>0 && decile <= 10) {
161 diff = nfsd_last_call - prev_call;
162 if ( (nfsdstats.th_usage[decile-1] += diff) >= NFSD_USAGE_WRAP)
163 nfsdstats.th_usage[decile-1] -= NFSD_USAGE_WRAP;
164 if (decile == 10)
165 nfsdstats.th_fullcnt++;
166 }
167 spin_unlock(&nfsd_call_lock);
168}
169
170/*
171 * This is the NFS server kernel thread
172 */
173static void
174nfsd(struct svc_rqst *rqstp)
175{
176 struct svc_serv *serv = rqstp->rq_server;
177 struct fs_struct *fsp;
178 int err;
179 struct nfsd_list me;
180 sigset_t shutdown_mask, allowed_mask;
181
182 /* Lock module and set up kernel thread */
183 lock_kernel();
184 daemonize("nfsd");
185
186 /* After daemonize() this kernel thread shares current->fs
187 * with the init process. We need to create files with a
188 * umask of 0 instead of init's umask. */
189 fsp = copy_fs_struct(current->fs);
190 if (!fsp) {
191 printk("Unable to start nfsd thread: out of memory\n");
192 goto out;
193 }
194 exit_fs(current);
195 current->fs = fsp;
196 current->fs->umask = 0;
197
198 siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS);
199 siginitsetinv(&allowed_mask, ALLOWED_SIGS);
200
201 nfsdstats.th_cnt++;
202
203 lockd_up(); /* start lockd */
204
205 me.task = current;
206 list_add(&me.list, &nfsd_list);
207
208 unlock_kernel();
209
210 /*
211 * We want less throttling in balance_dirty_pages() so that nfs to
212 * localhost doesn't cause nfsd to lock up due to all the client's
213 * dirty pages.
214 */
215 current->flags |= PF_LESS_THROTTLE;
216
217 /*
218 * The main request loop
219 */
220 for (;;) {
221 /* Block all but the shutdown signals */
222 sigprocmask(SIG_SETMASK, &shutdown_mask, NULL);
223
224 /*
225 * Find a socket with data available and call its
226 * recvfrom routine.
227 */
228 while ((err = svc_recv(serv, rqstp,
229 60*60*HZ)) == -EAGAIN)
230 ;
231 if (err < 0)
232 break;
233 update_thread_usage(atomic_read(&nfsd_busy));
234 atomic_inc(&nfsd_busy);
235
236 /* Lock the export hash tables for reading. */
237 exp_readlock();
238
239 /* Process request with signals blocked. */
240 sigprocmask(SIG_SETMASK, &allowed_mask, NULL);
241
242 svc_process(serv, rqstp);
243
244 /* Unlock export hash tables */
245 exp_readunlock();
246 update_thread_usage(atomic_read(&nfsd_busy));
247 atomic_dec(&nfsd_busy);
248 }
249
250 if (err != -EINTR) {
251 printk(KERN_WARNING "nfsd: terminating on error %d\n", -err);
252 } else {
253 unsigned int signo;
254
255 for (signo = 1; signo <= _NSIG; signo++)
256 if (sigismember(&current->pending.signal, signo) &&
257 !sigismember(&current->blocked, signo))
258 break;
259 err = signo;
260 }
261
262 lock_kernel();
263
264 /* Release lockd */
265 lockd_down();
266
267 /* Check if this is last thread */
268 if (serv->sv_nrthreads==1) {
269
270 printk(KERN_WARNING "nfsd: last server has exited\n");
271 if (err != SIG_NOCLEAN) {
272 printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
273 nfsd_export_flush();
274 }
275 nfsd_serv = NULL;
276 nfsd_racache_shutdown(); /* release read-ahead cache */
277 nfs4_state_shutdown();
278 }
279 list_del(&me.list);
280 nfsdstats.th_cnt --;
281
282out:
283 /* Release the thread */
284 svc_exit_thread(rqstp);
285
286 /* Release module */
287 module_put_and_exit(0);
288}
289
290int
291nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
292{
293 struct svc_procedure *proc;
294 kxdrproc_t xdr;
295 u32 nfserr;
296 u32 *nfserrp;
297
298 dprintk("nfsd_dispatch: vers %d proc %d\n",
299 rqstp->rq_vers, rqstp->rq_proc);
300 proc = rqstp->rq_procinfo;
301
302 /* Check whether we have this call in the cache. */
303 switch (nfsd_cache_lookup(rqstp, proc->pc_cachetype)) {
304 case RC_INTR:
305 case RC_DROPIT:
306 return 0;
307 case RC_REPLY:
308 return 1;
309 case RC_DOIT:;
310 /* do it */
311 }
312
313 /* Decode arguments */
314 xdr = proc->pc_decode;
315 if (xdr && !xdr(rqstp, (u32*)rqstp->rq_arg.head[0].iov_base,
316 rqstp->rq_argp)) {
317 dprintk("nfsd: failed to decode arguments!\n");
318 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
319 *statp = rpc_garbage_args;
320 return 1;
321 }
322
323 /* need to grab the location to store the status, as
324 * nfsv4 does some encoding while processing
325 */
326 nfserrp = rqstp->rq_res.head[0].iov_base
327 + rqstp->rq_res.head[0].iov_len;
328 rqstp->rq_res.head[0].iov_len += sizeof(u32);
329
330 /* Now call the procedure handler, and encode NFS status. */
331 nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
332 if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
333 nfserr = nfserr_dropit;
334 if (nfserr == nfserr_dropit) {
335 dprintk("nfsd: Dropping request due to malloc failure!\n");
336 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
337 return 0;
338 }
339
340 if (rqstp->rq_proc != 0)
341 *nfserrp++ = nfserr;
342
343 /* Encode result.
344 * For NFSv2, additional info is never returned in case of an error.
345 */
346 if (!(nfserr && rqstp->rq_vers == 2)) {
347 xdr = proc->pc_encode;
348 if (xdr && !xdr(rqstp, nfserrp,
349 rqstp->rq_resp)) {
350 /* Failed to encode result. Release cache entry */
351 dprintk("nfsd: failed to encode result!\n");
352 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
353 *statp = rpc_system_err;
354 return 1;
355 }
356 }
357
358 /* Store reply in cache. */
359 nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
360 return 1;
361}
362
363extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
364
365static struct svc_version * nfsd_version[] = {
366 [2] = &nfsd_version2,
367#if defined(CONFIG_NFSD_V3)
368 [3] = &nfsd_version3,
369#endif
370#if defined(CONFIG_NFSD_V4)
371 [4] = &nfsd_version4,
372#endif
373};
374
375#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0]))
376struct svc_program nfsd_program = {
377 .pg_prog = NFS_PROGRAM, /* program number */
378 .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
379 .pg_vers = nfsd_version, /* version table */
380 .pg_name = "nfsd", /* program name */
381 .pg_class = "nfsd", /* authentication class */
382 .pg_stats = &nfsd_svcstats, /* version table */
383 .pg_authenticate = &svc_set_client, /* export authentication */
384
385};
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
new file mode 100644
index 000000000000..948b08287c99
--- /dev/null
+++ b/fs/nfsd/nfsxdr.c
@@ -0,0 +1,511 @@
1/*
2 * linux/fs/nfsd/xdr.c
3 *
4 * XDR support for nfsd
5 *
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */
8
9#include <linux/types.h>
10#include <linux/time.h>
11#include <linux/nfs.h>
12#include <linux/vfs.h>
13#include <linux/sunrpc/xdr.h>
14#include <linux/sunrpc/svc.h>
15#include <linux/nfsd/nfsd.h>
16#include <linux/nfsd/xdr.h>
17#include <linux/mm.h>
18
19#define NFSDDBG_FACILITY NFSDDBG_XDR
20
21
22#ifdef NFSD_OPTIMIZE_SPACE
23# define inline
24#endif
25
26/*
27 * Mapping of S_IF* types to NFS file types
28 */
29static u32 nfs_ftypes[] = {
30 NFNON, NFCHR, NFCHR, NFBAD,
31 NFDIR, NFBAD, NFBLK, NFBAD,
32 NFREG, NFBAD, NFLNK, NFBAD,
33 NFSOCK, NFBAD, NFLNK, NFBAD,
34};
35
36
37/*
38 * XDR functions for basic NFS types
39 */
40static inline u32 *
41decode_fh(u32 *p, struct svc_fh *fhp)
42{
43 fh_init(fhp, NFS_FHSIZE);
44 memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
45 fhp->fh_handle.fh_size = NFS_FHSIZE;
46
47 /* FIXME: Look up export pointer here and verify
48 * Sun Secure RPC if requested */
49 return p + (NFS_FHSIZE >> 2);
50}
51
52static inline u32 *
53encode_fh(u32 *p, struct svc_fh *fhp)
54{
55 memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
56 return p + (NFS_FHSIZE>> 2);
57}
58
59/*
60 * Decode a file name and make sure that the path contains
61 * no slashes or null bytes.
62 */
63static inline u32 *
64decode_filename(u32 *p, char **namp, int *lenp)
65{
66 char *name;
67 int i;
68
69 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
70 for (i = 0, name = *namp; i < *lenp; i++, name++) {
71 if (*name == '\0' || *name == '/')
72 return NULL;
73 }
74 }
75
76 return p;
77}
78
79static inline u32 *
80decode_pathname(u32 *p, char **namp, int *lenp)
81{
82 char *name;
83 int i;
84
85 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) {
86 for (i = 0, name = *namp; i < *lenp; i++, name++) {
87 if (*name == '\0')
88 return NULL;
89 }
90 }
91
92 return p;
93}
94
95static inline u32 *
96decode_sattr(u32 *p, struct iattr *iap)
97{
98 u32 tmp, tmp1;
99
100 iap->ia_valid = 0;
101
102 /* Sun client bug compatibility check: some sun clients seem to
103 * put 0xffff in the mode field when they mean 0xffffffff.
104 * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
105 */
106 if ((tmp = ntohl(*p++)) != (u32)-1 && tmp != 0xffff) {
107 iap->ia_valid |= ATTR_MODE;
108 iap->ia_mode = tmp;
109 }
110 if ((tmp = ntohl(*p++)) != (u32)-1) {
111 iap->ia_valid |= ATTR_UID;
112 iap->ia_uid = tmp;
113 }
114 if ((tmp = ntohl(*p++)) != (u32)-1) {
115 iap->ia_valid |= ATTR_GID;
116 iap->ia_gid = tmp;
117 }
118 if ((tmp = ntohl(*p++)) != (u32)-1) {
119 iap->ia_valid |= ATTR_SIZE;
120 iap->ia_size = tmp;
121 }
122 tmp = ntohl(*p++); tmp1 = ntohl(*p++);
123 if (tmp != (u32)-1 && tmp1 != (u32)-1) {
124 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
125 iap->ia_atime.tv_sec = tmp;
126 iap->ia_atime.tv_nsec = tmp1 * 1000;
127 }
128 tmp = ntohl(*p++); tmp1 = ntohl(*p++);
129 if (tmp != (u32)-1 && tmp1 != (u32)-1) {
130 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
131 iap->ia_mtime.tv_sec = tmp;
132 iap->ia_mtime.tv_nsec = tmp1 * 1000;
133 /*
134 * Passing the invalid value useconds=1000000 for mtime
135 * is a Sun convention for "set both mtime and atime to
136 * current server time". It's needed to make permissions
137 * checks for the "touch" program across v2 mounts to
138 * Solaris and Irix boxes work correctly. See description of
139 * sattr in section 6.1 of "NFS Illustrated" by
140 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
141 */
142 if (tmp1 == 1000000)
143 iap->ia_valid &= ~(ATTR_ATIME_SET|ATTR_MTIME_SET);
144 }
145 return p;
146}
147
148static inline u32 *
149encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
150{
151 struct vfsmount *mnt = fhp->fh_export->ex_mnt;
152 struct dentry *dentry = fhp->fh_dentry;
153 struct kstat stat;
154 int type;
155 struct timespec time;
156
157 vfs_getattr(mnt, dentry, &stat);
158 type = (stat.mode & S_IFMT);
159
160 *p++ = htonl(nfs_ftypes[type >> 12]);
161 *p++ = htonl((u32) stat.mode);
162 *p++ = htonl((u32) stat.nlink);
163 *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid));
164 *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
165
166 if (S_ISLNK(type) && stat.size > NFS_MAXPATHLEN) {
167 *p++ = htonl(NFS_MAXPATHLEN);
168 } else {
169 *p++ = htonl((u32) stat.size);
170 }
171 *p++ = htonl((u32) stat.blksize);
172 if (S_ISCHR(type) || S_ISBLK(type))
173 *p++ = htonl(new_encode_dev(stat.rdev));
174 else
175 *p++ = htonl(0xffffffff);
176 *p++ = htonl((u32) stat.blocks);
177 if (is_fsid(fhp, rqstp->rq_reffh))
178 *p++ = htonl((u32) fhp->fh_export->ex_fsid);
179 else
180 *p++ = htonl(new_encode_dev(stat.dev));
181 *p++ = htonl((u32) stat.ino);
182 *p++ = htonl((u32) stat.atime.tv_sec);
183 *p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0);
184 lease_get_mtime(dentry->d_inode, &time);
185 *p++ = htonl((u32) time.tv_sec);
186 *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0);
187 *p++ = htonl((u32) stat.ctime.tv_sec);
188 *p++ = htonl(stat.ctime.tv_nsec ? stat.ctime.tv_nsec / 1000 : 0);
189
190 return p;
191}
192
193
194/*
195 * XDR decode functions
196 */
197int
198nfssvc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
199{
200 return xdr_argsize_check(rqstp, p);
201}
202
203int
204nfssvc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args)
205{
206 if (!(p = decode_fh(p, &args->fh)))
207 return 0;
208 return xdr_argsize_check(rqstp, p);
209}
210
211int
212nfssvc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
213 struct nfsd_sattrargs *args)
214{
215 if (!(p = decode_fh(p, &args->fh))
216 || !(p = decode_sattr(p, &args->attrs)))
217 return 0;
218
219 return xdr_argsize_check(rqstp, p);
220}
221
222int
223nfssvc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
224 struct nfsd_diropargs *args)
225{
226 if (!(p = decode_fh(p, &args->fh))
227 || !(p = decode_filename(p, &args->name, &args->len)))
228 return 0;
229
230 return xdr_argsize_check(rqstp, p);
231}
232
233int
234nfssvc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
235 struct nfsd_readargs *args)
236{
237 unsigned int len;
238 int v,pn;
239 if (!(p = decode_fh(p, &args->fh)))
240 return 0;
241
242 args->offset = ntohl(*p++);
243 len = args->count = ntohl(*p++);
244 p++; /* totalcount - unused */
245
246 if (len > NFSSVC_MAXBLKSIZE)
247 len = NFSSVC_MAXBLKSIZE;
248
249 /* set up somewhere to store response.
250 * We take pages, put them on reslist and include in iovec
251 */
252 v=0;
253 while (len > 0) {
254 pn=rqstp->rq_resused;
255 svc_take_page(rqstp);
256 args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
257 args->vec[v].iov_len = len < PAGE_SIZE?len:PAGE_SIZE;
258 len -= args->vec[v].iov_len;
259 v++;
260 }
261 args->vlen = v;
262 return xdr_argsize_check(rqstp, p);
263}
264
265int
266nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
267 struct nfsd_writeargs *args)
268{
269 unsigned int len;
270 int v;
271 if (!(p = decode_fh(p, &args->fh)))
272 return 0;
273
274 p++; /* beginoffset */
275 args->offset = ntohl(*p++); /* offset */
276 p++; /* totalcount */
277 len = args->len = ntohl(*p++);
278 args->vec[0].iov_base = (void*)p;
279 args->vec[0].iov_len = rqstp->rq_arg.head[0].iov_len -
280 (((void*)p) - rqstp->rq_arg.head[0].iov_base);
281 if (len > NFSSVC_MAXBLKSIZE)
282 len = NFSSVC_MAXBLKSIZE;
283 v = 0;
284 while (len > args->vec[v].iov_len) {
285 len -= args->vec[v].iov_len;
286 v++;
287 args->vec[v].iov_base = page_address(rqstp->rq_argpages[v]);
288 args->vec[v].iov_len = PAGE_SIZE;
289 }
290 args->vec[v].iov_len = len;
291 args->vlen = v+1;
292 return args->vec[0].iov_len > 0;
293}
294
295int
296nfssvc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
297 struct nfsd_createargs *args)
298{
299 if (!(p = decode_fh(p, &args->fh))
300 || !(p = decode_filename(p, &args->name, &args->len))
301 || !(p = decode_sattr(p, &args->attrs)))
302 return 0;
303
304 return xdr_argsize_check(rqstp, p);
305}
306
307int
308nfssvc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
309 struct nfsd_renameargs *args)
310{
311 if (!(p = decode_fh(p, &args->ffh))
312 || !(p = decode_filename(p, &args->fname, &args->flen))
313 || !(p = decode_fh(p, &args->tfh))
314 || !(p = decode_filename(p, &args->tname, &args->tlen)))
315 return 0;
316
317 return xdr_argsize_check(rqstp, p);
318}
319
320int
321nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, u32 *p, struct nfsd_readlinkargs *args)
322{
323 if (!(p = decode_fh(p, &args->fh)))
324 return 0;
325 svc_take_page(rqstp);
326 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]);
327
328 return xdr_argsize_check(rqstp, p);
329}
330
331int
332nfssvc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
333 struct nfsd_linkargs *args)
334{
335 if (!(p = decode_fh(p, &args->ffh))
336 || !(p = decode_fh(p, &args->tfh))
337 || !(p = decode_filename(p, &args->tname, &args->tlen)))
338 return 0;
339
340 return xdr_argsize_check(rqstp, p);
341}
342
343int
344nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
345 struct nfsd_symlinkargs *args)
346{
347 if (!(p = decode_fh(p, &args->ffh))
348 || !(p = decode_filename(p, &args->fname, &args->flen))
349 || !(p = decode_pathname(p, &args->tname, &args->tlen))
350 || !(p = decode_sattr(p, &args->attrs)))
351 return 0;
352
353 return xdr_argsize_check(rqstp, p);
354}
355
356int
357nfssvc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
358 struct nfsd_readdirargs *args)
359{
360 if (!(p = decode_fh(p, &args->fh)))
361 return 0;
362 args->cookie = ntohl(*p++);
363 args->count = ntohl(*p++);
364 if (args->count > PAGE_SIZE)
365 args->count = PAGE_SIZE;
366
367 svc_take_page(rqstp);
368 args->buffer = page_address(rqstp->rq_respages[rqstp->rq_resused-1]);
369
370 return xdr_argsize_check(rqstp, p);
371}
372
373/*
374 * XDR encode functions
375 */
376int
377nfssvc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
378{
379 return xdr_ressize_check(rqstp, p);
380}
381
382int
383nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
384 struct nfsd_attrstat *resp)
385{
386 p = encode_fattr(rqstp, p, &resp->fh);
387 return xdr_ressize_check(rqstp, p);
388}
389
390int
391nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
392 struct nfsd_diropres *resp)
393{
394 p = encode_fh(p, &resp->fh);
395 p = encode_fattr(rqstp, p, &resp->fh);
396 return xdr_ressize_check(rqstp, p);
397}
398
399int
400nfssvc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
401 struct nfsd_readlinkres *resp)
402{
403 *p++ = htonl(resp->len);
404 xdr_ressize_check(rqstp, p);
405 rqstp->rq_res.page_len = resp->len;
406 if (resp->len & 3) {
407 /* need to pad the tail */
408 rqstp->rq_restailpage = 0;
409 rqstp->rq_res.tail[0].iov_base = p;
410 *p = 0;
411 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
412 }
413 return 1;
414}
415
416int
417nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
418 struct nfsd_readres *resp)
419{
420 p = encode_fattr(rqstp, p, &resp->fh);
421 *p++ = htonl(resp->count);
422 xdr_ressize_check(rqstp, p);
423
424 /* now update rqstp->rq_res to reflect data aswell */
425 rqstp->rq_res.page_len = resp->count;
426 if (resp->count & 3) {
427 /* need to pad the tail */
428 rqstp->rq_restailpage = 0;
429 rqstp->rq_res.tail[0].iov_base = p;
430 *p = 0;
431 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3);
432 }
433 return 1;
434}
435
436int
437nfssvc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
438 struct nfsd_readdirres *resp)
439{
440 xdr_ressize_check(rqstp, p);
441 p = resp->buffer;
442 *p++ = 0; /* no more entries */
443 *p++ = htonl((resp->common.err == nfserr_eof));
444 rqstp->rq_res.page_len = (((unsigned long)p-1) & ~PAGE_MASK)+1;
445
446 return 1;
447}
448
449int
450nfssvc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
451 struct nfsd_statfsres *resp)
452{
453 struct kstatfs *stat = &resp->stats;
454
455 *p++ = htonl(NFSSVC_MAXBLKSIZE); /* max transfer size */
456 *p++ = htonl(stat->f_bsize);
457 *p++ = htonl(stat->f_blocks);
458 *p++ = htonl(stat->f_bfree);
459 *p++ = htonl(stat->f_bavail);
460 return xdr_ressize_check(rqstp, p);
461}
462
463int
464nfssvc_encode_entry(struct readdir_cd *ccd, const char *name,
465 int namlen, loff_t offset, ino_t ino, unsigned int d_type)
466{
467 struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common);
468 u32 *p = cd->buffer;
469 int buflen, slen;
470
471 /*
472 dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
473 namlen, name, offset, ino);
474 */
475
476 if (offset > ~((u32) 0)) {
477 cd->common.err = nfserr_fbig;
478 return -EINVAL;
479 }
480 if (cd->offset)
481 *cd->offset = htonl(offset);
482 if (namlen > NFS2_MAXNAMLEN)
483 namlen = NFS2_MAXNAMLEN;/* truncate filename */
484
485 slen = XDR_QUADLEN(namlen);
486 if ((buflen = cd->buflen - slen - 4) < 0) {
487 cd->common.err = nfserr_toosmall;
488 return -EINVAL;
489 }
490 *p++ = xdr_one; /* mark entry present */
491 *p++ = htonl((u32) ino); /* file id */
492 p = xdr_encode_array(p, name, namlen);/* name length & name */
493 cd->offset = p; /* remember pointer */
494 *p++ = ~(u32) 0; /* offset of next entry */
495
496 cd->buflen = buflen;
497 cd->buffer = p;
498 cd->common.err = nfs_ok;
499 return 0;
500}
501
502/*
503 * XDR release functions
504 */
505int
506nfssvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
507 struct nfsd_fhandle *resp)
508{
509 fh_put(&resp->fh);
510 return 1;
511}
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
new file mode 100644
index 000000000000..1cf955bcc526
--- /dev/null
+++ b/fs/nfsd/stats.c
@@ -0,0 +1,101 @@
1/*
2 * linux/fs/nfsd/stats.c
3 *
4 * procfs-based user access to knfsd statistics
5 *
6 * /proc/net/rpc/nfsd
7 *
8 * Format:
9 * rc <hits> <misses> <nocache>
10 * Statistsics for the reply cache
11 * fh <stale> <total-lookups> <anonlookups> <dir-not-in-dcache> <nondir-not-in-dcache>
12 * statistics for filehandle lookup
13 * io <bytes-read> <bytes-writtten>
14 * statistics for IO throughput
15 * th <threads> <fullcnt> <10%-20%> <20%-30%> ... <90%-100%> <100%>
16 * time (seconds) when nfsd thread usage above thresholds
17 * and number of times that all threads were in use
18 * ra cache-size <10% <20% <30% ... <100% not-found
19 * number of times that read-ahead entry was found that deep in
20 * the cache.
21 * plus generic RPC stats (see net/sunrpc/stats.c)
22 *
23 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
24 */
25
26#include <linux/kernel.h>
27#include <linux/time.h>
28#include <linux/proc_fs.h>
29#include <linux/seq_file.h>
30#include <linux/stat.h>
31#include <linux/module.h>
32
33#include <linux/sunrpc/svc.h>
34#include <linux/sunrpc/stats.h>
35#include <linux/nfsd/nfsd.h>
36#include <linux/nfsd/stats.h>
37
38struct nfsd_stats nfsdstats;
39struct svc_stat nfsd_svcstats = {
40 .program = &nfsd_program,
41};
42
43static int nfsd_proc_show(struct seq_file *seq, void *v)
44{
45 int i;
46
47 seq_printf(seq, "rc %u %u %u\nfh %u %u %u %u %u\nio %u %u\n",
48 nfsdstats.rchits,
49 nfsdstats.rcmisses,
50 nfsdstats.rcnocache,
51 nfsdstats.fh_stale,
52 nfsdstats.fh_lookup,
53 nfsdstats.fh_anon,
54 nfsdstats.fh_nocache_dir,
55 nfsdstats.fh_nocache_nondir,
56 nfsdstats.io_read,
57 nfsdstats.io_write);
58 /* thread usage: */
59 seq_printf(seq, "th %u %u", nfsdstats.th_cnt, nfsdstats.th_fullcnt);
60 for (i=0; i<10; i++) {
61 unsigned int jifs = nfsdstats.th_usage[i];
62 unsigned int sec = jifs / HZ, msec = (jifs % HZ)*1000/HZ;
63 seq_printf(seq, " %u.%03u", sec, msec);
64 }
65
66 /* newline and ra-cache */
67 seq_printf(seq, "\nra %u", nfsdstats.ra_size);
68 for (i=0; i<11; i++)
69 seq_printf(seq, " %u", nfsdstats.ra_depth[i]);
70 seq_putc(seq, '\n');
71
72 /* show my rpc info */
73 svc_seq_show(seq, &nfsd_svcstats);
74
75 return 0;
76}
77
78static int nfsd_proc_open(struct inode *inode, struct file *file)
79{
80 return single_open(file, nfsd_proc_show, NULL);
81}
82
83static struct file_operations nfsd_proc_fops = {
84 .owner = THIS_MODULE,
85 .open = nfsd_proc_open,
86 .read = seq_read,
87 .llseek = seq_lseek,
88 .release = single_release,
89};
90
91void
92nfsd_stat_init(void)
93{
94 svc_proc_register(&nfsd_svcstats, &nfsd_proc_fops);
95}
96
97void
98nfsd_stat_shutdown(void)
99{
100 svc_proc_unregister("nfsd");
101}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
new file mode 100644
index 000000000000..e3e9d217236e
--- /dev/null
+++ b/fs/nfsd/vfs.c
@@ -0,0 +1,1859 @@
1#define MSNFS /* HACK HACK */
2/*
3 * linux/fs/nfsd/vfs.c
4 *
5 * File operations used by nfsd. Some of these have been ripped from
6 * other parts of the kernel because they weren't exported, others
7 * are partial duplicates with added or changed functionality.
8 *
9 * Note that several functions dget() the dentry upon which they want
10 * to act, most notably those that create directory entries. Response
11 * dentry's are dput()'d if necessary in the release callback.
12 * So if you notice code paths that apparently fail to dput() the
13 * dentry, don't worry--they have been taken care of.
14 *
15 * Copyright (C) 1995-1999 Olaf Kirch <okir@monad.swb.de>
16 * Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp>
17 */
18
19#include <linux/config.h>
20#include <linux/string.h>
21#include <linux/time.h>
22#include <linux/errno.h>
23#include <linux/fs.h>
24#include <linux/file.h>
25#include <linux/mount.h>
26#include <linux/major.h>
27#include <linux/ext2_fs.h>
28#include <linux/proc_fs.h>
29#include <linux/stat.h>
30#include <linux/fcntl.h>
31#include <linux/net.h>
32#include <linux/unistd.h>
33#include <linux/slab.h>
34#include <linux/pagemap.h>
35#include <linux/in.h>
36#include <linux/module.h>
37#include <linux/namei.h>
38#include <linux/vfs.h>
39#include <linux/delay.h>
40#include <linux/sunrpc/svc.h>
41#include <linux/nfsd/nfsd.h>
42#ifdef CONFIG_NFSD_V3
43#include <linux/nfs3.h>
44#include <linux/nfsd/xdr3.h>
45#endif /* CONFIG_NFSD_V3 */
46#include <linux/nfsd/nfsfh.h>
47#include <linux/quotaops.h>
48#include <linux/dnotify.h>
49#ifdef CONFIG_NFSD_V4
50#include <linux/posix_acl.h>
51#include <linux/posix_acl_xattr.h>
52#include <linux/xattr_acl.h>
53#include <linux/xattr.h>
54#include <linux/nfs4.h>
55#include <linux/nfs4_acl.h>
56#include <linux/nfsd_idmap.h>
57#include <linux/security.h>
58#endif /* CONFIG_NFSD_V4 */
59
60#include <asm/uaccess.h>
61
62#define NFSDDBG_FACILITY NFSDDBG_FILEOP
63#define NFSD_PARANOIA
64
65
66/* We must ignore files (but only files) which might have mandatory
67 * locks on them because there is no way to know if the accesser has
68 * the lock.
69 */
70#define IS_ISMNDLK(i) (S_ISREG((i)->i_mode) && MANDATORY_LOCK(i))
71
72/*
73 * This is a cache of readahead params that help us choose the proper
74 * readahead strategy. Initially, we set all readahead parameters to 0
75 * and let the VFS handle things.
76 * If you increase the number of cached files very much, you'll need to
77 * add a hash table here.
78 */
79struct raparms {
80 struct raparms *p_next;
81 unsigned int p_count;
82 ino_t p_ino;
83 dev_t p_dev;
84 int p_set;
85 struct file_ra_state p_ra;
86};
87
88static struct raparms * raparml;
89static struct raparms * raparm_cache;
90
91/*
92 * Called from nfsd_lookup and encode_dirent. Check if we have crossed
93 * a mount point.
94 * Returns -EAGAIN leaving *dpp and *expp unchanged,
95 * or nfs_ok having possibly changed *dpp and *expp
96 */
97int
98nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
99 struct svc_export **expp)
100{
101 struct svc_export *exp = *expp, *exp2 = NULL;
102 struct dentry *dentry = *dpp;
103 struct vfsmount *mnt = mntget(exp->ex_mnt);
104 struct dentry *mounts = dget(dentry);
105 int err = nfs_ok;
106
107 while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts));
108
109 exp2 = exp_get_by_name(exp->ex_client, mnt, mounts, &rqstp->rq_chandle);
110 if (IS_ERR(exp2)) {
111 err = PTR_ERR(exp2);
112 dput(mounts);
113 mntput(mnt);
114 goto out;
115 }
116 if (exp2 && ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2))) {
117 /* successfully crossed mount point */
118 exp_put(exp);
119 *expp = exp2;
120 dput(dentry);
121 *dpp = mounts;
122 } else {
123 if (exp2) exp_put(exp2);
124 dput(mounts);
125 }
126 mntput(mnt);
127out:
128 return err;
129}
130
131/*
132 * Look up one component of a pathname.
133 * N.B. After this call _both_ fhp and resfh need an fh_put
134 *
135 * If the lookup would cross a mountpoint, and the mounted filesystem
136 * is exported to the client with NFSEXP_NOHIDE, then the lookup is
137 * accepted as it stands and the mounted directory is
138 * returned. Otherwise the covered directory is returned.
139 * NOTE: this mountpoint crossing is not supported properly by all
140 * clients and is explicitly disallowed for NFSv3
141 * NeilBrown <neilb@cse.unsw.edu.au>
142 */
143int
144nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
145 int len, struct svc_fh *resfh)
146{
147 struct svc_export *exp;
148 struct dentry *dparent;
149 struct dentry *dentry;
150 int err;
151
152 dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name);
153
154 /* Obtain dentry and export. */
155 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC);
156 if (err)
157 return err;
158
159 dparent = fhp->fh_dentry;
160 exp = fhp->fh_export;
161 exp_get(exp);
162
163 err = nfserr_acces;
164
165 /* Lookup the name, but don't follow links */
166 if (isdotent(name, len)) {
167 if (len==1)
168 dentry = dget(dparent);
169 else if (dparent != exp->ex_dentry) {
170 dentry = dget_parent(dparent);
171 } else if (!EX_NOHIDE(exp))
172 dentry = dget(dparent); /* .. == . just like at / */
173 else {
174 /* checking mountpoint crossing is very different when stepping up */
175 struct svc_export *exp2 = NULL;
176 struct dentry *dp;
177 struct vfsmount *mnt = mntget(exp->ex_mnt);
178 dentry = dget(dparent);
179 while(dentry == mnt->mnt_root && follow_up(&mnt, &dentry))
180 ;
181 dp = dget_parent(dentry);
182 dput(dentry);
183 dentry = dp;
184
185 exp2 = exp_parent(exp->ex_client, mnt, dentry,
186 &rqstp->rq_chandle);
187 if (IS_ERR(exp2)) {
188 err = PTR_ERR(exp2);
189 dput(dentry);
190 mntput(mnt);
191 goto out_nfserr;
192 }
193 if (!exp2) {
194 dput(dentry);
195 dentry = dget(dparent);
196 } else {
197 exp_put(exp);
198 exp = exp2;
199 }
200 mntput(mnt);
201 }
202 } else {
203 fh_lock(fhp);
204 dentry = lookup_one_len(name, dparent, len);
205 err = PTR_ERR(dentry);
206 if (IS_ERR(dentry))
207 goto out_nfserr;
208 /*
209 * check if we have crossed a mount point ...
210 */
211 if (d_mountpoint(dentry)) {
212 if ((err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
213 dput(dentry);
214 goto out_nfserr;
215 }
216 }
217 }
218 /*
219 * Note: we compose the file handle now, but as the
220 * dentry may be negative, it may need to be updated.
221 */
222 err = fh_compose(resfh, exp, dentry, fhp);
223 if (!err && !dentry->d_inode)
224 err = nfserr_noent;
225 dput(dentry);
226out:
227 exp_put(exp);
228 return err;
229
230out_nfserr:
231 err = nfserrno(err);
232 goto out;
233}
234
235/*
236 * Set various file attributes.
237 * N.B. After this call fhp needs an fh_put
238 */
239int
240nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
241 int check_guard, time_t guardtime)
242{
243 struct dentry *dentry;
244 struct inode *inode;
245 int accmode = MAY_SATTR;
246 int ftype = 0;
247 int imode;
248 int err;
249 int size_change = 0;
250
251 if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
252 accmode |= MAY_WRITE|MAY_OWNER_OVERRIDE;
253 if (iap->ia_valid & ATTR_SIZE)
254 ftype = S_IFREG;
255
256 /* Get inode */
257 err = fh_verify(rqstp, fhp, ftype, accmode);
258 if (err || !iap->ia_valid)
259 goto out;
260
261 dentry = fhp->fh_dentry;
262 inode = dentry->d_inode;
263
264 /* NFSv2 does not differentiate between "set-[ac]time-to-now"
265 * which only requires access, and "set-[ac]time-to-X" which
266 * requires ownership.
267 * So if it looks like it might be "set both to the same time which
268 * is close to now", and if inode_change_ok fails, then we
269 * convert to "set to now" instead of "set to explicit time"
270 *
271 * We only call inode_change_ok as the last test as technically
272 * it is not an interface that we should be using. It is only
273 * valid if the filesystem does not define it's own i_op->setattr.
274 */
275#define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
276#define MAX_TOUCH_TIME_ERROR (30*60)
277 if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET
278 && iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec
279 ) {
280 /* Looks probable. Now just make sure time is in the right ballpark.
281 * Solaris, at least, doesn't seem to care what the time request is.
282 * We require it be within 30 minutes of now.
283 */
284 time_t delta = iap->ia_atime.tv_sec - get_seconds();
285 if (delta<0) delta = -delta;
286 if (delta < MAX_TOUCH_TIME_ERROR &&
287 inode_change_ok(inode, iap) != 0) {
288 /* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME
289 * this will cause notify_change to set these times to "now"
290 */
291 iap->ia_valid &= ~BOTH_TIME_SET;
292 }
293 }
294
295 /* The size case is special. It changes the file as well as the attributes. */
296 if (iap->ia_valid & ATTR_SIZE) {
297 if (iap->ia_size < inode->i_size) {
298 err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
299 if (err)
300 goto out;
301 }
302
303 /*
304 * If we are changing the size of the file, then
305 * we need to break all leases.
306 */
307 err = break_lease(inode, FMODE_WRITE | O_NONBLOCK);
308 if (err == -EWOULDBLOCK)
309 err = -ETIMEDOUT;
310 if (err) /* ENOMEM or EWOULDBLOCK */
311 goto out_nfserr;
312
313 err = get_write_access(inode);
314 if (err)
315 goto out_nfserr;
316
317 size_change = 1;
318 err = locks_verify_truncate(inode, NULL, iap->ia_size);
319 if (err) {
320 put_write_access(inode);
321 goto out_nfserr;
322 }
323 DQUOT_INIT(inode);
324 }
325
326 imode = inode->i_mode;
327 if (iap->ia_valid & ATTR_MODE) {
328 iap->ia_mode &= S_IALLUGO;
329 imode = iap->ia_mode |= (imode & ~S_IALLUGO);
330 }
331
332 /* Revoke setuid/setgid bit on chown/chgrp */
333 if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
334 iap->ia_valid |= ATTR_KILL_SUID;
335 if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
336 iap->ia_valid |= ATTR_KILL_SGID;
337
338 /* Change the attributes. */
339
340 iap->ia_valid |= ATTR_CTIME;
341
342 err = nfserr_notsync;
343 if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
344 fh_lock(fhp);
345 err = notify_change(dentry, iap);
346 err = nfserrno(err);
347 fh_unlock(fhp);
348 }
349 if (size_change)
350 put_write_access(inode);
351 if (!err)
352 if (EX_ISSYNC(fhp->fh_export))
353 write_inode_now(inode, 1);
354out:
355 return err;
356
357out_nfserr:
358 err = nfserrno(err);
359 goto out;
360}
361
362#if defined(CONFIG_NFSD_V4)
363
364static int
365set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
366{
367 int len;
368 size_t buflen;
369 char *buf = NULL;
370 int error = 0;
371 struct inode *inode = dentry->d_inode;
372
373 buflen = posix_acl_xattr_size(pacl->a_count);
374 buf = kmalloc(buflen, GFP_KERNEL);
375 error = -ENOMEM;
376 if (buf == NULL)
377 goto out;
378
379 len = posix_acl_to_xattr(pacl, buf, buflen);
380 if (len < 0) {
381 error = len;
382 goto out;
383 }
384
385 error = -EOPNOTSUPP;
386 if (inode->i_op && inode->i_op->setxattr) {
387 down(&inode->i_sem);
388 security_inode_setxattr(dentry, key, buf, len, 0);
389 error = inode->i_op->setxattr(dentry, key, buf, len, 0);
390 if (!error)
391 security_inode_post_setxattr(dentry, key, buf, len, 0);
392 up(&inode->i_sem);
393 }
394out:
395 kfree(buf);
396 return error;
397}
398
399int
400nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
401 struct nfs4_acl *acl)
402{
403 int error;
404 struct dentry *dentry;
405 struct inode *inode;
406 struct posix_acl *pacl = NULL, *dpacl = NULL;
407 unsigned int flags = 0;
408
409 /* Get inode */
410 error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR);
411 if (error)
412 goto out;
413
414 dentry = fhp->fh_dentry;
415 inode = dentry->d_inode;
416 if (S_ISDIR(inode->i_mode))
417 flags = NFS4_ACL_DIR;
418
419 error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
420 if (error == -EINVAL) {
421 error = nfserr_attrnotsupp;
422 goto out;
423 } else if (error < 0)
424 goto out_nfserr;
425
426 if (pacl) {
427 error = set_nfsv4_acl_one(dentry, pacl, XATTR_NAME_ACL_ACCESS);
428 if (error < 0)
429 goto out_nfserr;
430 }
431
432 if (dpacl) {
433 error = set_nfsv4_acl_one(dentry, dpacl, XATTR_NAME_ACL_DEFAULT);
434 if (error < 0)
435 goto out_nfserr;
436 }
437
438 error = nfs_ok;
439
440out:
441 posix_acl_release(pacl);
442 posix_acl_release(dpacl);
443 return (error);
444out_nfserr:
445 error = nfserrno(error);
446 goto out;
447}
448
449static struct posix_acl *
450_get_posix_acl(struct dentry *dentry, char *key)
451{
452 struct inode *inode = dentry->d_inode;
453 char *buf = NULL;
454 int buflen, error = 0;
455 struct posix_acl *pacl = NULL;
456
457 error = -EOPNOTSUPP;
458 if (inode->i_op == NULL)
459 goto out_err;
460 if (inode->i_op->getxattr == NULL)
461 goto out_err;
462
463 error = security_inode_getxattr(dentry, key);
464 if (error)
465 goto out_err;
466
467 buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
468 if (buflen <= 0) {
469 error = buflen < 0 ? buflen : -ENODATA;
470 goto out_err;
471 }
472
473 buf = kmalloc(buflen, GFP_KERNEL);
474 if (buf == NULL) {
475 error = -ENOMEM;
476 goto out_err;
477 }
478
479 error = inode->i_op->getxattr(dentry, key, buf, buflen);
480 if (error < 0)
481 goto out_err;
482
483 pacl = posix_acl_from_xattr(buf, buflen);
484 out:
485 kfree(buf);
486 return pacl;
487 out_err:
488 pacl = ERR_PTR(error);
489 goto out;
490}
491
492int
493nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
494{
495 struct inode *inode = dentry->d_inode;
496 int error = 0;
497 struct posix_acl *pacl = NULL, *dpacl = NULL;
498 unsigned int flags = 0;
499
500 pacl = _get_posix_acl(dentry, XATTR_NAME_ACL_ACCESS);
501 if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
502 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
503 if (IS_ERR(pacl)) {
504 error = PTR_ERR(pacl);
505 pacl = NULL;
506 goto out;
507 }
508
509 if (S_ISDIR(inode->i_mode)) {
510 dpacl = _get_posix_acl(dentry, XATTR_NAME_ACL_DEFAULT);
511 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
512 dpacl = NULL;
513 else if (IS_ERR(dpacl)) {
514 error = PTR_ERR(dpacl);
515 dpacl = NULL;
516 goto out;
517 }
518 flags = NFS4_ACL_DIR;
519 }
520
521 *acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
522 if (IS_ERR(*acl)) {
523 error = PTR_ERR(*acl);
524 *acl = NULL;
525 }
526 out:
527 posix_acl_release(pacl);
528 posix_acl_release(dpacl);
529 return error;
530}
531
532#endif /* defined(CONFIG_NFS_V4) */
533
534#ifdef CONFIG_NFSD_V3
535/*
536 * Check server access rights to a file system object
537 */
538struct accessmap {
539 u32 access;
540 int how;
541};
542static struct accessmap nfs3_regaccess[] = {
543 { NFS3_ACCESS_READ, MAY_READ },
544 { NFS3_ACCESS_EXECUTE, MAY_EXEC },
545 { NFS3_ACCESS_MODIFY, MAY_WRITE|MAY_TRUNC },
546 { NFS3_ACCESS_EXTEND, MAY_WRITE },
547
548 { 0, 0 }
549};
550
551static struct accessmap nfs3_diraccess[] = {
552 { NFS3_ACCESS_READ, MAY_READ },
553 { NFS3_ACCESS_LOOKUP, MAY_EXEC },
554 { NFS3_ACCESS_MODIFY, MAY_EXEC|MAY_WRITE|MAY_TRUNC },
555 { NFS3_ACCESS_EXTEND, MAY_EXEC|MAY_WRITE },
556 { NFS3_ACCESS_DELETE, MAY_REMOVE },
557
558 { 0, 0 }
559};
560
561static struct accessmap nfs3_anyaccess[] = {
562 /* Some clients - Solaris 2.6 at least, make an access call
563 * to the server to check for access for things like /dev/null
564 * (which really, the server doesn't care about). So
565 * We provide simple access checking for them, looking
566 * mainly at mode bits, and we make sure to ignore read-only
567 * filesystem checks
568 */
569 { NFS3_ACCESS_READ, MAY_READ },
570 { NFS3_ACCESS_EXECUTE, MAY_EXEC },
571 { NFS3_ACCESS_MODIFY, MAY_WRITE|MAY_LOCAL_ACCESS },
572 { NFS3_ACCESS_EXTEND, MAY_WRITE|MAY_LOCAL_ACCESS },
573
574 { 0, 0 }
575};
576
577int
578nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *supported)
579{
580 struct accessmap *map;
581 struct svc_export *export;
582 struct dentry *dentry;
583 u32 query, result = 0, sresult = 0;
584 unsigned int error;
585
586 error = fh_verify(rqstp, fhp, 0, MAY_NOP);
587 if (error)
588 goto out;
589
590 export = fhp->fh_export;
591 dentry = fhp->fh_dentry;
592
593 if (S_ISREG(dentry->d_inode->i_mode))
594 map = nfs3_regaccess;
595 else if (S_ISDIR(dentry->d_inode->i_mode))
596 map = nfs3_diraccess;
597 else
598 map = nfs3_anyaccess;
599
600
601 query = *access;
602 for (; map->access; map++) {
603 if (map->access & query) {
604 unsigned int err2;
605
606 sresult |= map->access;
607
608 err2 = nfsd_permission(export, dentry, map->how);
609 switch (err2) {
610 case nfs_ok:
611 result |= map->access;
612 break;
613
614 /* the following error codes just mean the access was not allowed,
615 * rather than an error occurred */
616 case nfserr_rofs:
617 case nfserr_acces:
618 case nfserr_perm:
619 /* simply don't "or" in the access bit. */
620 break;
621 default:
622 error = err2;
623 goto out;
624 }
625 }
626 }
627 *access = result;
628 if (supported)
629 *supported = sresult;
630
631 out:
632 return error;
633}
634#endif /* CONFIG_NFSD_V3 */
635
636
637
638/*
639 * Open an existing file or directory.
640 * The access argument indicates the type of open (read/write/lock)
641 * N.B. After this call fhp needs an fh_put
642 */
643int
644nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
645 int access, struct file **filp)
646{
647 struct dentry *dentry;
648 struct inode *inode;
649 int flags = O_RDONLY|O_LARGEFILE, err;
650
651 /*
652 * If we get here, then the client has already done an "open",
653 * and (hopefully) checked permission - so allow OWNER_OVERRIDE
654 * in case a chmod has now revoked permission.
655 */
656 err = fh_verify(rqstp, fhp, type, access | MAY_OWNER_OVERRIDE);
657 if (err)
658 goto out;
659
660 dentry = fhp->fh_dentry;
661 inode = dentry->d_inode;
662
663 /* Disallow write access to files with the append-only bit set
664 * or any access when mandatory locking enabled
665 */
666 err = nfserr_perm;
667 if (IS_APPEND(inode) && (access & MAY_WRITE))
668 goto out;
669 if (IS_ISMNDLK(inode))
670 goto out;
671
672 if (!inode->i_fop)
673 goto out;
674
675 /*
676 * Check to see if there are any leases on this file.
677 * This may block while leases are broken.
678 */
679 err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0));
680 if (err == -EWOULDBLOCK)
681 err = -ETIMEDOUT;
682 if (err) /* NOMEM or WOULDBLOCK */
683 goto out_nfserr;
684
685 if (access & MAY_WRITE) {
686 flags = O_WRONLY|O_LARGEFILE;
687
688 DQUOT_INIT(inode);
689 }
690 *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags);
691 if (IS_ERR(*filp))
692 err = PTR_ERR(*filp);
693out_nfserr:
694 if (err)
695 err = nfserrno(err);
696out:
697 return err;
698}
699
700/*
701 * Close a file.
702 */
703void
704nfsd_close(struct file *filp)
705{
706 fput(filp);
707}
708
709/*
710 * Sync a file
711 * As this calls fsync (not fdatasync) there is no need for a write_inode
712 * after it.
713 */
714static inline void nfsd_dosync(struct file *filp, struct dentry *dp,
715 struct file_operations *fop)
716{
717 struct inode *inode = dp->d_inode;
718 int (*fsync) (struct file *, struct dentry *, int);
719
720 filemap_fdatawrite(inode->i_mapping);
721 if (fop && (fsync = fop->fsync))
722 fsync(filp, dp, 0);
723 filemap_fdatawait(inode->i_mapping);
724}
725
726
727static void
728nfsd_sync(struct file *filp)
729{
730 struct inode *inode = filp->f_dentry->d_inode;
731 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
732 down(&inode->i_sem);
733 nfsd_dosync(filp, filp->f_dentry, filp->f_op);
734 up(&inode->i_sem);
735}
736
737static void
738nfsd_sync_dir(struct dentry *dp)
739{
740 nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
741}
742
743/*
744 * Obtain the readahead parameters for the file
745 * specified by (dev, ino).
746 */
747static DEFINE_SPINLOCK(ra_lock);
748
749static inline struct raparms *
750nfsd_get_raparms(dev_t dev, ino_t ino)
751{
752 struct raparms *ra, **rap, **frap = NULL;
753 int depth = 0;
754
755 spin_lock(&ra_lock);
756 for (rap = &raparm_cache; (ra = *rap); rap = &ra->p_next) {
757 if (ra->p_ino == ino && ra->p_dev == dev)
758 goto found;
759 depth++;
760 if (ra->p_count == 0)
761 frap = rap;
762 }
763 depth = nfsdstats.ra_size*11/10;
764 if (!frap) {
765 spin_unlock(&ra_lock);
766 return NULL;
767 }
768 rap = frap;
769 ra = *frap;
770 ra->p_dev = dev;
771 ra->p_ino = ino;
772 ra->p_set = 0;
773found:
774 if (rap != &raparm_cache) {
775 *rap = ra->p_next;
776 ra->p_next = raparm_cache;
777 raparm_cache = ra;
778 }
779 ra->p_count++;
780 nfsdstats.ra_depth[depth*10/nfsdstats.ra_size]++;
781 spin_unlock(&ra_lock);
782 return ra;
783}
784
785/*
786 * Grab and keep cached pages assosiated with a file in the svc_rqst
787 * so that they can be passed to the netowork sendmsg/sendpage routines
788 * directrly. They will be released after the sending has completed.
789 */
790static int
791nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
792{
793 unsigned long count = desc->count;
794 struct svc_rqst *rqstp = desc->arg.data;
795
796 if (size > count)
797 size = count;
798
799 if (rqstp->rq_res.page_len == 0) {
800 get_page(page);
801 rqstp->rq_respages[rqstp->rq_resused++] = page;
802 rqstp->rq_res.page_base = offset;
803 rqstp->rq_res.page_len = size;
804 } else if (page != rqstp->rq_respages[rqstp->rq_resused-1]) {
805 get_page(page);
806 rqstp->rq_respages[rqstp->rq_resused++] = page;
807 rqstp->rq_res.page_len += size;
808 } else {
809 rqstp->rq_res.page_len += size;
810 }
811
812 desc->count = count - size;
813 desc->written += size;
814 return size;
815}
816
817static inline int
818nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
819 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
820{
821 struct inode *inode;
822 struct raparms *ra;
823 mm_segment_t oldfs;
824 int err;
825
826 err = nfserr_perm;
827 inode = file->f_dentry->d_inode;
828#ifdef MSNFS
829 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
830 (!lock_may_read(inode, offset, *count)))
831 goto out;
832#endif
833
834 /* Get readahead parameters */
835 ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
836
837 if (ra && ra->p_set)
838 file->f_ra = ra->p_ra;
839
840 if (file->f_op->sendfile) {
841 svc_pushback_unused_pages(rqstp);
842 err = file->f_op->sendfile(file, &offset, *count,
843 nfsd_read_actor, rqstp);
844 } else {
845 oldfs = get_fs();
846 set_fs(KERNEL_DS);
847 err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset);
848 set_fs(oldfs);
849 }
850
851 /* Write back readahead params */
852 if (ra) {
853 spin_lock(&ra_lock);
854 ra->p_ra = file->f_ra;
855 ra->p_set = 1;
856 ra->p_count--;
857 spin_unlock(&ra_lock);
858 }
859
860 if (err >= 0) {
861 nfsdstats.io_read += err;
862 *count = err;
863 err = 0;
864 dnotify_parent(file->f_dentry, DN_ACCESS);
865 } else
866 err = nfserrno(err);
867out:
868 return err;
869}
870
871static inline int
872nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
873 loff_t offset, struct kvec *vec, int vlen,
874 unsigned long cnt, int *stablep)
875{
876 struct svc_export *exp;
877 struct dentry *dentry;
878 struct inode *inode;
879 mm_segment_t oldfs;
880 int err = 0;
881 int stable = *stablep;
882
883 err = nfserr_perm;
884
885#ifdef MSNFS
886 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
887 (!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
888 goto out;
889#endif
890
891 dentry = file->f_dentry;
892 inode = dentry->d_inode;
893 exp = fhp->fh_export;
894
895 /*
896 * Request sync writes if
897 * - the sync export option has been set, or
898 * - the client requested O_SYNC behavior (NFSv3 feature).
899 * - The file system doesn't support fsync().
900 * When gathered writes have been configured for this volume,
901 * flushing the data to disk is handled separately below.
902 */
903
904 if (file->f_op->fsync == 0) {/* COMMIT3 cannot work */
905 stable = 2;
906 *stablep = 2; /* FILE_SYNC */
907 }
908
909 if (!EX_ISSYNC(exp))
910 stable = 0;
911 if (stable && !EX_WGATHER(exp))
912 file->f_flags |= O_SYNC;
913
914 /* Write the data. */
915 oldfs = get_fs(); set_fs(KERNEL_DS);
916 err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
917 set_fs(oldfs);
918 if (err >= 0) {
919 nfsdstats.io_write += cnt;
920 dnotify_parent(file->f_dentry, DN_MODIFY);
921 }
922
923 /* clear setuid/setgid flag after write */
924 if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
925 struct iattr ia;
926 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
927
928 down(&inode->i_sem);
929 notify_change(dentry, &ia);
930 up(&inode->i_sem);
931 }
932
933 if (err >= 0 && stable) {
934 static ino_t last_ino;
935 static dev_t last_dev;
936
937 /*
938 * Gathered writes: If another process is currently
939 * writing to the file, there's a high chance
940 * this is another nfsd (triggered by a bulk write
941 * from a client's biod). Rather than syncing the
942 * file with each write request, we sleep for 10 msec.
943 *
944 * I don't know if this roughly approximates
945 * C. Juszak's idea of gathered writes, but it's a
946 * nice and simple solution (IMHO), and it seems to
947 * work:-)
948 */
949 if (EX_WGATHER(exp)) {
950 if (atomic_read(&inode->i_writecount) > 1
951 || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
952 dprintk("nfsd: write defer %d\n", current->pid);
953 msleep(10);
954 dprintk("nfsd: write resume %d\n", current->pid);
955 }
956
957 if (inode->i_state & I_DIRTY) {
958 dprintk("nfsd: write sync %d\n", current->pid);
959 nfsd_sync(file);
960 }
961#if 0
962 wake_up(&inode->i_wait);
963#endif
964 }
965 last_ino = inode->i_ino;
966 last_dev = inode->i_sb->s_dev;
967 }
968
969 dprintk("nfsd: write complete err=%d\n", err);
970 if (err >= 0)
971 err = 0;
972 else
973 err = nfserrno(err);
974out:
975 return err;
976}
977
978/*
979 * Read data from a file. count must contain the requested read count
980 * on entry. On return, *count contains the number of bytes actually read.
981 * N.B. After this call fhp needs an fh_put
982 */
983int
984nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
985 loff_t offset, struct kvec *vec, int vlen,
986 unsigned long *count)
987{
988 int err;
989
990 if (file) {
991 err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
992 MAY_READ|MAY_OWNER_OVERRIDE);
993 if (err)
994 goto out;
995 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
996 } else {
997 err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
998 if (err)
999 goto out;
1000 err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
1001 nfsd_close(file);
1002 }
1003out:
1004 return err;
1005}
1006
1007/*
1008 * Write data to a file.
1009 * The stable flag requests synchronous writes.
1010 * N.B. After this call fhp needs an fh_put
1011 */
1012int
1013nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1014 loff_t offset, struct kvec *vec, int vlen, unsigned long cnt,
1015 int *stablep)
1016{
1017 int err = 0;
1018
1019 if (file) {
1020 err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
1021 MAY_WRITE|MAY_OWNER_OVERRIDE);
1022 if (err)
1023 goto out;
1024 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt,
1025 stablep);
1026 } else {
1027 err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);
1028 if (err)
1029 goto out;
1030
1031 if (cnt)
1032 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen,
1033 cnt, stablep);
1034 nfsd_close(file);
1035 }
1036out:
1037 return err;
1038}
1039
1040#ifdef CONFIG_NFSD_V3
1041/*
1042 * Commit all pending writes to stable storage.
1043 * Strictly speaking, we could sync just the indicated file region here,
1044 * but there's currently no way we can ask the VFS to do so.
1045 *
1046 * Unfortunately we cannot lock the file to make sure we return full WCC
1047 * data to the client, as locking happens lower down in the filesystem.
1048 */
1049int
1050nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
1051 loff_t offset, unsigned long count)
1052{
1053 struct file *file;
1054 int err;
1055
1056 if ((u64)count > ~(u64)offset)
1057 return nfserr_inval;
1058
1059 if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
1060 return err;
1061 if (EX_ISSYNC(fhp->fh_export)) {
1062 if (file->f_op && file->f_op->fsync) {
1063 nfsd_sync(file);
1064 } else {
1065 err = nfserr_notsupp;
1066 }
1067 }
1068
1069 nfsd_close(file);
1070 return err;
1071}
1072#endif /* CONFIG_NFSD_V3 */
1073
1074/*
1075 * Create a file (regular, directory, device, fifo); UNIX sockets
1076 * not yet implemented.
1077 * If the response fh has been verified, the parent directory should
1078 * already be locked. Note that the parent directory is left locked.
1079 *
1080 * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
1081 */
1082int
1083nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1084 char *fname, int flen, struct iattr *iap,
1085 int type, dev_t rdev, struct svc_fh *resfhp)
1086{
1087 struct dentry *dentry, *dchild = NULL;
1088 struct inode *dirp;
1089 int err;
1090
1091 err = nfserr_perm;
1092 if (!flen)
1093 goto out;
1094 err = nfserr_exist;
1095 if (isdotent(fname, flen))
1096 goto out;
1097
1098 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
1099 if (err)
1100 goto out;
1101
1102 dentry = fhp->fh_dentry;
1103 dirp = dentry->d_inode;
1104
1105 err = nfserr_notdir;
1106 if(!dirp->i_op || !dirp->i_op->lookup)
1107 goto out;
1108 /*
1109 * Check whether the response file handle has been verified yet.
1110 * If it has, the parent directory should already be locked.
1111 */
1112 if (!resfhp->fh_dentry) {
1113 /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
1114 fh_lock(fhp);
1115 dchild = lookup_one_len(fname, dentry, flen);
1116 err = PTR_ERR(dchild);
1117 if (IS_ERR(dchild))
1118 goto out_nfserr;
1119 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1120 if (err)
1121 goto out;
1122 } else {
1123 /* called from nfsd_proc_create */
1124 dchild = dget(resfhp->fh_dentry);
1125 if (!fhp->fh_locked) {
1126 /* not actually possible */
1127 printk(KERN_ERR
1128 "nfsd_create: parent %s/%s not locked!\n",
1129 dentry->d_parent->d_name.name,
1130 dentry->d_name.name);
1131 err = -EIO;
1132 goto out;
1133 }
1134 }
1135 /*
1136 * Make sure the child dentry is still negative ...
1137 */
1138 err = nfserr_exist;
1139 if (dchild->d_inode) {
1140 dprintk("nfsd_create: dentry %s/%s not negative!\n",
1141 dentry->d_name.name, dchild->d_name.name);
1142 goto out;
1143 }
1144
1145 if (!(iap->ia_valid & ATTR_MODE))
1146 iap->ia_mode = 0;
1147 iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
1148
1149 /*
1150 * Get the dir op function pointer.
1151 */
1152 err = nfserr_perm;
1153 switch (type) {
1154 case S_IFREG:
1155 err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1156 break;
1157 case S_IFDIR:
1158 err = vfs_mkdir(dirp, dchild, iap->ia_mode);
1159 break;
1160 case S_IFCHR:
1161 case S_IFBLK:
1162 case S_IFIFO:
1163 case S_IFSOCK:
1164 err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
1165 break;
1166 default:
1167 printk("nfsd: bad file type %o in nfsd_create\n", type);
1168 err = -EINVAL;
1169 }
1170 if (err < 0)
1171 goto out_nfserr;
1172
1173 if (EX_ISSYNC(fhp->fh_export)) {
1174 nfsd_sync_dir(dentry);
1175 write_inode_now(dchild->d_inode, 1);
1176 }
1177
1178
1179 /* Set file attributes. Mode has already been set and
1180 * setting uid/gid works only for root. Irix appears to
1181 * send along the gid when it tries to implement setgid
1182 * directories via NFS.
1183 */
1184 err = 0;
1185 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
1186 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1187 /*
1188 * Update the file handle to get the new inode info.
1189 */
1190 if (!err)
1191 err = fh_update(resfhp);
1192out:
1193 if (dchild && !IS_ERR(dchild))
1194 dput(dchild);
1195 return err;
1196
1197out_nfserr:
1198 err = nfserrno(err);
1199 goto out;
1200}
1201
1202#ifdef CONFIG_NFSD_V3
1203/*
1204 * NFSv3 version of nfsd_create
1205 */
1206int
1207nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1208 char *fname, int flen, struct iattr *iap,
1209 struct svc_fh *resfhp, int createmode, u32 *verifier,
1210 int *truncp)
1211{
1212 struct dentry *dentry, *dchild = NULL;
1213 struct inode *dirp;
1214 int err;
1215 __u32 v_mtime=0, v_atime=0;
1216 int v_mode=0;
1217
1218 err = nfserr_perm;
1219 if (!flen)
1220 goto out;
1221 err = nfserr_exist;
1222 if (isdotent(fname, flen))
1223 goto out;
1224 if (!(iap->ia_valid & ATTR_MODE))
1225 iap->ia_mode = 0;
1226 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
1227 if (err)
1228 goto out;
1229
1230 dentry = fhp->fh_dentry;
1231 dirp = dentry->d_inode;
1232
1233 /* Get all the sanity checks out of the way before
1234 * we lock the parent. */
1235 err = nfserr_notdir;
1236 if(!dirp->i_op || !dirp->i_op->lookup)
1237 goto out;
1238 fh_lock(fhp);
1239
1240 /*
1241 * Compose the response file handle.
1242 */
1243 dchild = lookup_one_len(fname, dentry, flen);
1244 err = PTR_ERR(dchild);
1245 if (IS_ERR(dchild))
1246 goto out_nfserr;
1247
1248 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1249 if (err)
1250 goto out;
1251
1252 if (createmode == NFS3_CREATE_EXCLUSIVE) {
1253 /* while the verifier would fit in mtime+atime,
1254 * solaris7 gets confused (bugid 4218508) if these have
1255 * the high bit set, so we use the mode as well
1256 */
1257 v_mtime = verifier[0]&0x7fffffff;
1258 v_atime = verifier[1]&0x7fffffff;
1259 v_mode = S_IFREG
1260 | ((verifier[0]&0x80000000) >> (32-7)) /* u+x */
1261 | ((verifier[1]&0x80000000) >> (32-9)) /* u+r */
1262 ;
1263 }
1264
1265 if (dchild->d_inode) {
1266 err = 0;
1267
1268 switch (createmode) {
1269 case NFS3_CREATE_UNCHECKED:
1270 if (! S_ISREG(dchild->d_inode->i_mode))
1271 err = nfserr_exist;
1272 else if (truncp) {
1273 /* in nfsv4, we need to treat this case a little
1274 * differently. we don't want to truncate the
1275 * file now; this would be wrong if the OPEN
1276 * fails for some other reason. furthermore,
1277 * if the size is nonzero, we should ignore it
1278 * according to spec!
1279 */
1280 *truncp = (iap->ia_valid & ATTR_SIZE) && !iap->ia_size;
1281 }
1282 else {
1283 iap->ia_valid &= ATTR_SIZE;
1284 goto set_attr;
1285 }
1286 break;
1287 case NFS3_CREATE_EXCLUSIVE:
1288 if ( dchild->d_inode->i_mtime.tv_sec == v_mtime
1289 && dchild->d_inode->i_atime.tv_sec == v_atime
1290 && dchild->d_inode->i_mode == v_mode
1291 && dchild->d_inode->i_size == 0 )
1292 break;
1293 /* fallthru */
1294 case NFS3_CREATE_GUARDED:
1295 err = nfserr_exist;
1296 }
1297 goto out;
1298 }
1299
1300 err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1301 if (err < 0)
1302 goto out_nfserr;
1303
1304 if (EX_ISSYNC(fhp->fh_export)) {
1305 nfsd_sync_dir(dentry);
1306 /* setattr will sync the child (or not) */
1307 }
1308
1309 /*
1310 * Update the filehandle to get the new inode info.
1311 */
1312 err = fh_update(resfhp);
1313 if (err)
1314 goto out;
1315
1316 if (createmode == NFS3_CREATE_EXCLUSIVE) {
1317 /* Cram the verifier into atime/mtime/mode */
1318 iap->ia_valid = ATTR_MTIME|ATTR_ATIME
1319 | ATTR_MTIME_SET|ATTR_ATIME_SET
1320 | ATTR_MODE;
1321 /* XXX someone who knows this better please fix it for nsec */
1322 iap->ia_mtime.tv_sec = v_mtime;
1323 iap->ia_atime.tv_sec = v_atime;
1324 iap->ia_mtime.tv_nsec = 0;
1325 iap->ia_atime.tv_nsec = 0;
1326 iap->ia_mode = v_mode;
1327 }
1328
1329 /* Set file attributes.
1330 * Mode has already been set but we might need to reset it
1331 * for CREATE_EXCLUSIVE
1332 * Irix appears to send along the gid when it tries to
1333 * implement setgid directories via NFS. Clear out all that cruft.
1334 */
1335 set_attr:
1336 if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0)
1337 err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
1338
1339 out:
1340 fh_unlock(fhp);
1341 if (dchild && !IS_ERR(dchild))
1342 dput(dchild);
1343 return err;
1344
1345 out_nfserr:
1346 err = nfserrno(err);
1347 goto out;
1348}
1349#endif /* CONFIG_NFSD_V3 */
1350
1351/*
1352 * Read a symlink. On entry, *lenp must contain the maximum path length that
1353 * fits into the buffer. On return, it contains the true length.
1354 * N.B. After this call fhp needs an fh_put
1355 */
1356int
1357nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
1358{
1359 struct dentry *dentry;
1360 struct inode *inode;
1361 mm_segment_t oldfs;
1362 int err;
1363
1364 err = fh_verify(rqstp, fhp, S_IFLNK, MAY_NOP);
1365 if (err)
1366 goto out;
1367
1368 dentry = fhp->fh_dentry;
1369 inode = dentry->d_inode;
1370
1371 err = nfserr_inval;
1372 if (!inode->i_op || !inode->i_op->readlink)
1373 goto out;
1374
1375 touch_atime(fhp->fh_export->ex_mnt, dentry);
1376 /* N.B. Why does this call need a get_fs()??
1377 * Remove the set_fs and watch the fireworks:-) --okir
1378 */
1379
1380 oldfs = get_fs(); set_fs(KERNEL_DS);
1381 err = inode->i_op->readlink(dentry, buf, *lenp);
1382 set_fs(oldfs);
1383
1384 if (err < 0)
1385 goto out_nfserr;
1386 *lenp = err;
1387 err = 0;
1388out:
1389 return err;
1390
1391out_nfserr:
1392 err = nfserrno(err);
1393 goto out;
1394}
1395
1396/*
1397 * Create a symlink and look up its inode
1398 * N.B. After this call _both_ fhp and resfhp need an fh_put
1399 */
1400int
1401nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1402 char *fname, int flen,
1403 char *path, int plen,
1404 struct svc_fh *resfhp,
1405 struct iattr *iap)
1406{
1407 struct dentry *dentry, *dnew;
1408 int err, cerr;
1409 umode_t mode;
1410
1411 err = nfserr_noent;
1412 if (!flen || !plen)
1413 goto out;
1414 err = nfserr_exist;
1415 if (isdotent(fname, flen))
1416 goto out;
1417
1418 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
1419 if (err)
1420 goto out;
1421 fh_lock(fhp);
1422 dentry = fhp->fh_dentry;
1423 dnew = lookup_one_len(fname, dentry, flen);
1424 err = PTR_ERR(dnew);
1425 if (IS_ERR(dnew))
1426 goto out_nfserr;
1427
1428 mode = S_IALLUGO;
1429 /* Only the MODE ATTRibute is even vaguely meaningful */
1430 if (iap && (iap->ia_valid & ATTR_MODE))
1431 mode = iap->ia_mode & S_IALLUGO;
1432
1433 if (unlikely(path[plen] != 0)) {
1434 char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
1435 if (path_alloced == NULL)
1436 err = -ENOMEM;
1437 else {
1438 strncpy(path_alloced, path, plen);
1439 path_alloced[plen] = 0;
1440 err = vfs_symlink(dentry->d_inode, dnew, path_alloced, mode);
1441 kfree(path_alloced);
1442 }
1443 } else
1444 err = vfs_symlink(dentry->d_inode, dnew, path, mode);
1445
1446 if (!err) {
1447 if (EX_ISSYNC(fhp->fh_export))
1448 nfsd_sync_dir(dentry);
1449 } else
1450 err = nfserrno(err);
1451 fh_unlock(fhp);
1452
1453 cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
1454 dput(dnew);
1455 if (err==0) err = cerr;
1456out:
1457 return err;
1458
1459out_nfserr:
1460 err = nfserrno(err);
1461 goto out;
1462}
1463
1464/*
1465 * Create a hardlink
1466 * N.B. After this call _both_ ffhp and tfhp need an fh_put
1467 */
1468int
1469nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1470 char *name, int len, struct svc_fh *tfhp)
1471{
1472 struct dentry *ddir, *dnew, *dold;
1473 struct inode *dirp, *dest;
1474 int err;
1475
1476 err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE);
1477 if (err)
1478 goto out;
1479 err = fh_verify(rqstp, tfhp, -S_IFDIR, MAY_NOP);
1480 if (err)
1481 goto out;
1482
1483 err = nfserr_perm;
1484 if (!len)
1485 goto out;
1486 err = nfserr_exist;
1487 if (isdotent(name, len))
1488 goto out;
1489
1490 fh_lock(ffhp);
1491 ddir = ffhp->fh_dentry;
1492 dirp = ddir->d_inode;
1493
1494 dnew = lookup_one_len(name, ddir, len);
1495 err = PTR_ERR(dnew);
1496 if (IS_ERR(dnew))
1497 goto out_nfserr;
1498
1499 dold = tfhp->fh_dentry;
1500 dest = dold->d_inode;
1501
1502 err = vfs_link(dold, dirp, dnew);
1503 if (!err) {
1504 if (EX_ISSYNC(ffhp->fh_export)) {
1505 nfsd_sync_dir(ddir);
1506 write_inode_now(dest, 1);
1507 }
1508 } else {
1509 if (err == -EXDEV && rqstp->rq_vers == 2)
1510 err = nfserr_acces;
1511 else
1512 err = nfserrno(err);
1513 }
1514
1515 fh_unlock(ffhp);
1516 dput(dnew);
1517out:
1518 return err;
1519
1520out_nfserr:
1521 err = nfserrno(err);
1522 goto out;
1523}
1524
1525/*
1526 * Rename a file
1527 * N.B. After this call _both_ ffhp and tfhp need an fh_put
1528 */
1529int
1530nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1531 struct svc_fh *tfhp, char *tname, int tlen)
1532{
1533 struct dentry *fdentry, *tdentry, *odentry, *ndentry, *trap;
1534 struct inode *fdir, *tdir;
1535 int err;
1536
1537 err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_REMOVE);
1538 if (err)
1539 goto out;
1540 err = fh_verify(rqstp, tfhp, S_IFDIR, MAY_CREATE);
1541 if (err)
1542 goto out;
1543
1544 fdentry = ffhp->fh_dentry;
1545 fdir = fdentry->d_inode;
1546
1547 tdentry = tfhp->fh_dentry;
1548 tdir = tdentry->d_inode;
1549
1550 err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
1551 if (fdir->i_sb != tdir->i_sb)
1552 goto out;
1553
1554 err = nfserr_perm;
1555 if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen))
1556 goto out;
1557
1558 /* cannot use fh_lock as we need deadlock protective ordering
1559 * so do it by hand */
1560 trap = lock_rename(tdentry, fdentry);
1561 ffhp->fh_locked = tfhp->fh_locked = 1;
1562 fill_pre_wcc(ffhp);
1563 fill_pre_wcc(tfhp);
1564
1565 odentry = lookup_one_len(fname, fdentry, flen);
1566 err = PTR_ERR(odentry);
1567 if (IS_ERR(odentry))
1568 goto out_nfserr;
1569
1570 err = -ENOENT;
1571 if (!odentry->d_inode)
1572 goto out_dput_old;
1573 err = -EINVAL;
1574 if (odentry == trap)
1575 goto out_dput_old;
1576
1577 ndentry = lookup_one_len(tname, tdentry, tlen);
1578 err = PTR_ERR(ndentry);
1579 if (IS_ERR(ndentry))
1580 goto out_dput_old;
1581 err = -ENOTEMPTY;
1582 if (ndentry == trap)
1583 goto out_dput_new;
1584
1585#ifdef MSNFS
1586 if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1587 ((atomic_read(&odentry->d_count) > 1)
1588 || (atomic_read(&ndentry->d_count) > 1))) {
1589 err = nfserr_perm;
1590 } else
1591#endif
1592 err = vfs_rename(fdir, odentry, tdir, ndentry);
1593 if (!err && EX_ISSYNC(tfhp->fh_export)) {
1594 nfsd_sync_dir(tdentry);
1595 nfsd_sync_dir(fdentry);
1596 }
1597
1598 out_dput_new:
1599 dput(ndentry);
1600 out_dput_old:
1601 dput(odentry);
1602 out_nfserr:
1603 if (err)
1604 err = nfserrno(err);
1605
1606 /* we cannot reply on fh_unlock on the two filehandles,
1607 * as that would do the wrong thing if the two directories
1608 * were the same, so again we do it by hand
1609 */
1610 fill_post_wcc(ffhp);
1611 fill_post_wcc(tfhp);
1612 unlock_rename(tdentry, fdentry);
1613 ffhp->fh_locked = tfhp->fh_locked = 0;
1614
1615out:
1616 return err;
1617}
1618
1619/*
1620 * Unlink a file or directory
1621 * N.B. After this call fhp needs an fh_put
1622 */
1623int
1624nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1625 char *fname, int flen)
1626{
1627 struct dentry *dentry, *rdentry;
1628 struct inode *dirp;
1629 int err;
1630
1631 err = nfserr_acces;
1632 if (!flen || isdotent(fname, flen))
1633 goto out;
1634 err = fh_verify(rqstp, fhp, S_IFDIR, MAY_REMOVE);
1635 if (err)
1636 goto out;
1637
1638 fh_lock(fhp);
1639 dentry = fhp->fh_dentry;
1640 dirp = dentry->d_inode;
1641
1642 rdentry = lookup_one_len(fname, dentry, flen);
1643 err = PTR_ERR(rdentry);
1644 if (IS_ERR(rdentry))
1645 goto out_nfserr;
1646
1647 if (!rdentry->d_inode) {
1648 dput(rdentry);
1649 err = nfserr_noent;
1650 goto out;
1651 }
1652
1653 if (!type)
1654 type = rdentry->d_inode->i_mode & S_IFMT;
1655
1656 if (type != S_IFDIR) { /* It's UNLINK */
1657#ifdef MSNFS
1658 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1659 (atomic_read(&rdentry->d_count) > 1)) {
1660 err = nfserr_perm;
1661 } else
1662#endif
1663 err = vfs_unlink(dirp, rdentry);
1664 } else { /* It's RMDIR */
1665 err = vfs_rmdir(dirp, rdentry);
1666 }
1667
1668 dput(rdentry);
1669
1670 if (err)
1671 goto out_nfserr;
1672 if (EX_ISSYNC(fhp->fh_export))
1673 nfsd_sync_dir(dentry);
1674
1675out:
1676 return err;
1677
1678out_nfserr:
1679 err = nfserrno(err);
1680 goto out;
1681}
1682
1683/*
1684 * Read entries from a directory.
1685 * The NFSv3/4 verifier we ignore for now.
1686 */
1687int
1688nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
1689 struct readdir_cd *cdp, encode_dent_fn func)
1690{
1691 int err;
1692 struct file *file;
1693 loff_t offset = *offsetp;
1694
1695 err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
1696 if (err)
1697 goto out;
1698
1699 offset = vfs_llseek(file, offset, 0);
1700 if (offset < 0) {
1701 err = nfserrno((int)offset);
1702 goto out_close;
1703 }
1704
1705 /*
1706 * Read the directory entries. This silly loop is necessary because
1707 * readdir() is not guaranteed to fill up the entire buffer, but
1708 * may choose to do less.
1709 */
1710
1711 do {
1712 cdp->err = nfserr_eof; /* will be cleared on successful read */
1713 err = vfs_readdir(file, (filldir_t) func, cdp);
1714 } while (err >=0 && cdp->err == nfs_ok);
1715 if (err)
1716 err = nfserrno(err);
1717 else
1718 err = cdp->err;
1719 *offsetp = vfs_llseek(file, 0, 1);
1720
1721 if (err == nfserr_eof || err == nfserr_toosmall)
1722 err = nfs_ok; /* can still be found in ->err */
1723out_close:
1724 nfsd_close(file);
1725out:
1726 return err;
1727}
1728
1729/*
1730 * Get file system stats
1731 * N.B. After this call fhp needs an fh_put
1732 */
1733int
1734nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
1735{
1736 int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
1737 if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat))
1738 err = nfserr_io;
1739 return err;
1740}
1741
1742/*
1743 * Check for a user's access permissions to this inode.
1744 */
1745int
1746nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
1747{
1748 struct inode *inode = dentry->d_inode;
1749 int err;
1750
1751 if (acc == MAY_NOP)
1752 return 0;
1753#if 0
1754 dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
1755 acc,
1756 (acc & MAY_READ)? " read" : "",
1757 (acc & MAY_WRITE)? " write" : "",
1758 (acc & MAY_EXEC)? " exec" : "",
1759 (acc & MAY_SATTR)? " sattr" : "",
1760 (acc & MAY_TRUNC)? " trunc" : "",
1761 (acc & MAY_LOCK)? " lock" : "",
1762 (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",
1763 inode->i_mode,
1764 IS_IMMUTABLE(inode)? " immut" : "",
1765 IS_APPEND(inode)? " append" : "",
1766 IS_RDONLY(inode)? " ro" : "");
1767 dprintk(" owner %d/%d user %d/%d\n",
1768 inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
1769#endif
1770
1771 /* Normally we reject any write/sattr etc access on a read-only file
1772 * system. But if it is IRIX doing check on write-access for a
1773 * device special file, we ignore rofs.
1774 */
1775 if (!(acc & MAY_LOCAL_ACCESS))
1776 if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
1777 if (EX_RDONLY(exp) || IS_RDONLY(inode))
1778 return nfserr_rofs;
1779 if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
1780 return nfserr_perm;
1781 }
1782 if ((acc & MAY_TRUNC) && IS_APPEND(inode))
1783 return nfserr_perm;
1784
1785 if (acc & MAY_LOCK) {
1786 /* If we cannot rely on authentication in NLM requests,
1787 * just allow locks, otherwise require read permission, or
1788 * ownership
1789 */
1790 if (exp->ex_flags & NFSEXP_NOAUTHNLM)
1791 return 0;
1792 else
1793 acc = MAY_READ | MAY_OWNER_OVERRIDE;
1794 }
1795 /*
1796 * The file owner always gets access permission for accesses that
1797 * would normally be checked at open time. This is to make
1798 * file access work even when the client has done a fchmod(fd, 0).
1799 *
1800 * However, `cp foo bar' should fail nevertheless when bar is
1801 * readonly. A sensible way to do this might be to reject all
1802 * attempts to truncate a read-only file, because a creat() call
1803 * always implies file truncation.
1804 * ... but this isn't really fair. A process may reasonably call
1805 * ftruncate on an open file descriptor on a file with perm 000.
1806 * We must trust the client to do permission checking - using "ACCESS"
1807 * with NFSv3.
1808 */
1809 if ((acc & MAY_OWNER_OVERRIDE) &&
1810 inode->i_uid == current->fsuid)
1811 return 0;
1812
1813 err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
1814
1815 /* Allow read access to binaries even when mode 111 */
1816 if (err == -EACCES && S_ISREG(inode->i_mode) &&
1817 acc == (MAY_READ | MAY_OWNER_OVERRIDE))
1818 err = permission(inode, MAY_EXEC, NULL);
1819
1820 return err? nfserrno(err) : 0;
1821}
1822
1823void
1824nfsd_racache_shutdown(void)
1825{
1826 if (!raparm_cache)
1827 return;
1828 dprintk("nfsd: freeing readahead buffers.\n");
1829 kfree(raparml);
1830 raparm_cache = raparml = NULL;
1831}
1832/*
1833 * Initialize readahead param cache
1834 */
1835int
1836nfsd_racache_init(int cache_size)
1837{
1838 int i;
1839
1840 if (raparm_cache)
1841 return 0;
1842 raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL);
1843
1844 if (raparml != NULL) {
1845 dprintk("nfsd: allocating %d readahead buffers.\n",
1846 cache_size);
1847 memset(raparml, 0, sizeof(struct raparms) * cache_size);
1848 for (i = 0; i < cache_size - 1; i++) {
1849 raparml[i].p_next = raparml + i + 1;
1850 }
1851 raparm_cache = raparml;
1852 } else {
1853 printk(KERN_WARNING
1854 "nfsd: Could not allocate memory read-ahead cache.\n");
1855 return -ENOMEM;
1856 }
1857 nfsdstats.ra_size = cache_size;
1858 return 0;
1859}