]> Git Repo - linux.git/blame - fs/nfsd/nfs3proc.c
Linux 6.14-rc3
[linux.git] / fs / nfsd / nfs3proc.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4 2/*
1da177e4
LT
3 * Process version 3 NFS requests.
4 *
5 * Copyright (C) 1996, 1997, 1998 Olaf Kirch <[email protected]>
6 */
7
1da177e4
LT
8#include <linux/fs.h>
9#include <linux/ext2_fs.h>
12214cb7 10#include <linux/magic.h>
df9606ab 11#include <linux/namei.h>
1da177e4 12
9a74af21
BH
13#include "cache.h"
14#include "xdr3.h"
0a3adade 15#include "vfs.h"
c2528490 16#include "filecache.h"
1da177e4
LT
17
18#define NFSDDBG_FACILITY NFSDDBG_PROC
19
1da177e4
LT
20static int nfs3_ftypes[] = {
21 0, /* NF3NON */
22 S_IFREG, /* NF3REG */
23 S_IFDIR, /* NF3DIR */
24 S_IFBLK, /* NF3BLK */
25 S_IFCHR, /* NF3CHR */
26 S_IFLNK, /* NF3LNK */
27 S_IFSOCK, /* NF3SOCK */
28 S_IFIFO, /* NF3FIFO */
29};
30
1459ad57
N
31static __be32 nfsd3_map_status(__be32 status)
32{
33 switch (status) {
34 case nfs_ok:
35 break;
36 case nfserr_nofilehandle:
37 status = nfserr_badhandle;
38 break;
39 case nfserr_wrongsec:
40 case nfserr_file_open:
41 status = nfserr_acces;
42 break;
438f81e0
N
43 case nfserr_symlink_not_dir:
44 status = nfserr_notdir;
45 break;
46 case nfserr_symlink:
47 case nfserr_wrong_type:
48 status = nfserr_inval;
49 break;
1459ad57
N
50 }
51 return status;
52}
53
1da177e4
LT
54/*
55 * NULL call.
56 */
7111c66e 57static __be32
a6beb732 58nfsd3_proc_null(struct svc_rqst *rqstp)
1da177e4 59{
cc028a10 60 return rpc_success;
1da177e4
LT
61}
62
63/*
64 * Get a file's attributes
65 */
7111c66e 66static __be32
a6beb732 67nfsd3_proc_getattr(struct svc_rqst *rqstp)
1da177e4 68{
a6beb732
CH
69 struct nfsd_fhandle *argp = rqstp->rq_argp;
70 struct nfsd3_attrstat *resp = rqstp->rq_resp;
1da177e4
LT
71
72 dprintk("nfsd: GETATTR(3) %s\n",
a334de28 73 SVCFH_fmt(&argp->fh));
1da177e4
LT
74
75 fh_copy(&resp->fh, &argp->fh);
14168d67
CL
76 resp->status = fh_verify(rqstp, &resp->fh, 0,
77 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
78 if (resp->status != nfs_ok)
79 goto out;
80
81 resp->status = fh_getattr(&resp->fh, &resp->stat);
82out:
1459ad57 83 resp->status = nfsd3_map_status(resp->status);
cc028a10 84 return rpc_success;
1da177e4
LT
85}
86
87/*
88 * Set a file's attributes
89 */
7111c66e 90static __be32
a6beb732 91nfsd3_proc_setattr(struct svc_rqst *rqstp)
1da177e4 92{
a6beb732
CH
93 struct nfsd3_sattrargs *argp = rqstp->rq_argp;
94 struct nfsd3_attrstat *resp = rqstp->rq_resp;
7fe2a71d
N
95 struct nfsd_attrs attrs = {
96 .na_iattr = &argp->attrs,
97 };
24d92de9 98 const struct timespec64 *guardtime = NULL;
1da177e4
LT
99
100 dprintk("nfsd: SETATTR(3) %s\n",
101 SVCFH_fmt(&argp->fh));
102
103 fh_copy(&resp->fh, &argp->fh);
24d92de9
TM
104 if (argp->check_guard)
105 guardtime = &argp->guardtime;
106 resp->status = nfsd_setattr(rqstp, &resp->fh, &attrs, guardtime);
1459ad57 107 resp->status = nfsd3_map_status(resp->status);
cc028a10 108 return rpc_success;
1da177e4
LT
109}
110
111/*
112 * Look up a path name component
113 */
7111c66e 114static __be32
a6beb732 115nfsd3_proc_lookup(struct svc_rqst *rqstp)
1da177e4 116{
a6beb732
CH
117 struct nfsd3_diropargs *argp = rqstp->rq_argp;
118 struct nfsd3_diropres *resp = rqstp->rq_resp;
1da177e4
LT
119
120 dprintk("nfsd: LOOKUP(3) %s %.*s\n",
121 SVCFH_fmt(&argp->fh),
122 argp->len,
123 argp->name);
124
125 fh_copy(&resp->dirfh, &argp->fh);
126 fh_init(&resp->fh, NFS3_FHSIZE);
127
14168d67
CL
128 resp->status = nfsd_lookup(rqstp, &resp->dirfh,
129 argp->name, argp->len,
130 &resp->fh);
1459ad57 131 resp->status = nfsd3_map_status(resp->status);
cc028a10 132 return rpc_success;
1da177e4
LT
133}
134
135/*
136 * Check file access
137 */
7111c66e 138static __be32
a6beb732 139nfsd3_proc_access(struct svc_rqst *rqstp)
1da177e4 140{
a6beb732
CH
141 struct nfsd3_accessargs *argp = rqstp->rq_argp;
142 struct nfsd3_accessres *resp = rqstp->rq_resp;
1da177e4
LT
143
144 dprintk("nfsd: ACCESS(3) %s 0x%x\n",
145 SVCFH_fmt(&argp->fh),
146 argp->access);
147
148 fh_copy(&resp->fh, &argp->fh);
149 resp->access = argp->access;
14168d67 150 resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
1459ad57 151 resp->status = nfsd3_map_status(resp->status);
cc028a10 152 return rpc_success;
1da177e4
LT
153}
154
155/*
156 * Read a symlink.
157 */
7111c66e 158static __be32
a6beb732 159nfsd3_proc_readlink(struct svc_rqst *rqstp)
1da177e4 160{
224c1c89 161 struct nfsd_fhandle *argp = rqstp->rq_argp;
a6beb732 162 struct nfsd3_readlinkres *resp = rqstp->rq_resp;
1da177e4
LT
163
164 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
165
166 /* Read the symlink. */
167 fh_copy(&resp->fh, &argp->fh);
168 resp->len = NFS3_MAXPATHLEN;
9a9c8923
CL
169 resp->pages = rqstp->rq_next_page++;
170 resp->status = nfsd_readlink(rqstp, &resp->fh,
171 page_address(*resp->pages), &resp->len);
1459ad57 172 resp->status = nfsd3_map_status(resp->status);
cc028a10 173 return rpc_success;
1da177e4
LT
174}
175
176/*
177 * Read a portion of a file.
178 */
7111c66e 179static __be32
a6beb732 180nfsd3_proc_read(struct svc_rqst *rqstp)
1da177e4 181{
a6beb732
CH
182 struct nfsd3_readargs *argp = rqstp->rq_argp;
183 struct nfsd3_readres *resp = rqstp->rq_resp;
be63bd2a 184
18b631f8 185 dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
1da177e4
LT
186 SVCFH_fmt(&argp->fh),
187 (unsigned long) argp->count,
18b631f8 188 (unsigned long long) argp->offset);
1da177e4 189
fa6be9cc
CL
190 argp->count = min_t(u32, argp->count, svc_max_payload(rqstp));
191 argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
0cb4d23a
CL
192 if (argp->offset > (u64)OFFSET_MAX)
193 argp->offset = (u64)OFFSET_MAX;
194 if (argp->offset + argp->count > (u64)OFFSET_MAX)
195 argp->count = (u64)OFFSET_MAX - argp->offset;
196
cc9bcdad 197 resp->pages = rqstp->rq_next_page;
be63bd2a 198
1da177e4
LT
199 /* Obtain buffer pointer for payload.
200 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
201 * + 1 (xdr opaque byte count) = 26
202 */
be63bd2a 203 resp->count = argp->count;
afb8aae5
KW
204 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3) << 2) +
205 resp->count + 4);
1da177e4
LT
206
207 fh_copy(&resp->fh, &argp->fh);
14168d67 208 resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
507df40e 209 &resp->count, &resp->eof);
1459ad57 210 resp->status = nfsd3_map_status(resp->status);
cc028a10 211 return rpc_success;
1da177e4
LT
212}
213
214/*
215 * Write data to a file
216 */
7111c66e 217static __be32
a6beb732 218nfsd3_proc_write(struct svc_rqst *rqstp)
1da177e4 219{
a6beb732
CH
220 struct nfsd3_writeargs *argp = rqstp->rq_argp;
221 struct nfsd3_writeres *resp = rqstp->rq_resp;
31dec253 222 unsigned long cnt = argp->len;
8154ef27 223 unsigned int nvecs;
1da177e4 224
18b631f8 225 dprintk("nfsd: WRITE(3) %s %d bytes at %Lu%s\n",
1da177e4
LT
226 SVCFH_fmt(&argp->fh),
227 argp->len,
18b631f8 228 (unsigned long long) argp->offset,
afb8aae5 229 argp->stable ? " stable" : "");
1da177e4 230
6260d9a5
CL
231 resp->status = nfserr_fbig;
232 if (argp->offset > (u64)OFFSET_MAX ||
233 argp->offset + argp->len > (u64)OFFSET_MAX)
234 return rpc_success;
235
1da177e4
LT
236 fh_copy(&resp->fh, &argp->fh);
237 resp->committed = argp->stable;
dae9a6ca 238 nvecs = svc_fill_write_vector(rqstp, &argp->payload);
6a2f7744 239
14168d67
CL
240 resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
241 rqstp->rq_vec, nvecs, &cnt,
242 resp->committed, resp->verf);
31dec253 243 resp->count = cnt;
1459ad57 244 resp->status = nfsd3_map_status(resp->status);
cc028a10 245 return rpc_success;
1da177e4
LT
246}
247
248/*
df9606ab
CL
249 * Implement NFSv3's unchecked, guarded, and exclusive CREATE
250 * semantics for regular files. Except for the created file,
251 * this operation is stateless on the server.
252 *
253 * Upon return, caller must release @fhp and @resfhp.
1da177e4 254 */
df9606ab
CL
255static __be32
256nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
257 struct svc_fh *resfhp, struct nfsd3_createargs *argp)
258{
259 struct iattr *iap = &argp->attrs;
260 struct dentry *parent, *child;
7fe2a71d
N
261 struct nfsd_attrs attrs = {
262 .na_iattr = iap,
263 };
df9606ab
CL
264 __u32 v_mtime, v_atime;
265 struct inode *inode;
266 __be32 status;
267 int host_err;
268
269 if (isdotent(argp->name, argp->len))
270 return nfserr_exist;
271 if (!(iap->ia_valid & ATTR_MODE))
272 iap->ia_mode = 0;
273
274 status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
275 if (status != nfs_ok)
276 return status;
277
278 parent = fhp->fh_dentry;
279 inode = d_inode(parent);
280
281 host_err = fh_want_write(fhp);
282 if (host_err)
283 return nfserrno(host_err);
284
debf16f0 285 inode_lock_nested(inode, I_MUTEX_PARENT);
df9606ab
CL
286
287 child = lookup_one_len(argp->name, parent, argp->len);
288 if (IS_ERR(child)) {
289 status = nfserrno(PTR_ERR(child));
290 goto out;
291 }
292
293 if (d_really_is_negative(child)) {
294 status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
295 if (status != nfs_ok)
296 goto out;
297 }
298
299 status = fh_compose(resfhp, fhp->fh_export, child, fhp);
300 if (status != nfs_ok)
301 goto out;
302
303 v_mtime = 0;
304 v_atime = 0;
305 if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
306 u32 *verifier = (u32 *)argp->verf;
307
308 /*
309 * Solaris 7 gets confused (bugid 4218508) if these have
310 * the high bit set, as do xfs filesystems without the
311 * "bigtime" feature. So just clear the high bits.
312 */
313 v_mtime = verifier[0] & 0x7fffffff;
314 v_atime = verifier[1] & 0x7fffffff;
315 }
316
317 if (d_really_is_positive(child)) {
318 status = nfs_ok;
319
320 switch (argp->createmode) {
321 case NFS3_CREATE_UNCHECKED:
322 if (!d_is_reg(child))
323 break;
324 iap->ia_valid &= ATTR_SIZE;
325 goto set_attr;
326 case NFS3_CREATE_GUARDED:
327 status = nfserr_exist;
328 break;
329 case NFS3_CREATE_EXCLUSIVE:
11fec9b9
JL
330 if (inode_get_mtime_sec(d_inode(child)) == v_mtime &&
331 inode_get_atime_sec(d_inode(child)) == v_atime &&
df9606ab
CL
332 d_inode(child)->i_size == 0) {
333 break;
334 }
335 status = nfserr_exist;
336 }
337 goto out;
338 }
339
340 if (!IS_POSIXACL(inode))
341 iap->ia_mode &= ~current_umask();
342
a332018a
JL
343 status = fh_fill_pre_attrs(fhp);
344 if (status != nfs_ok)
345 goto out;
abf08576 346 host_err = vfs_create(&nop_mnt_idmap, inode, child, iap->ia_mode, true);
df9606ab
CL
347 if (host_err < 0) {
348 status = nfserrno(host_err);
349 goto out;
350 }
debf16f0 351 fh_fill_post_attrs(fhp);
df9606ab
CL
352
353 /* A newly created file already has a file size of zero. */
354 if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0))
355 iap->ia_valid &= ~ATTR_SIZE;
356 if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
357 iap->ia_valid = ATTR_MTIME | ATTR_ATIME |
358 ATTR_MTIME_SET | ATTR_ATIME_SET;
359 iap->ia_mtime.tv_sec = v_mtime;
360 iap->ia_atime.tv_sec = v_atime;
361 iap->ia_mtime.tv_nsec = 0;
362 iap->ia_atime.tv_nsec = 0;
363 }
364
365set_attr:
7fe2a71d 366 status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
df9606ab
CL
367
368out:
debf16f0 369 inode_unlock(inode);
df9606ab
CL
370 if (child && !IS_ERR(child))
371 dput(child);
372 fh_drop_write(fhp);
373 return status;
374}
375
7111c66e 376static __be32
a6beb732 377nfsd3_proc_create(struct svc_rqst *rqstp)
1da177e4 378{
a6beb732
CH
379 struct nfsd3_createargs *argp = rqstp->rq_argp;
380 struct nfsd3_diropres *resp = rqstp->rq_resp;
e6156859 381 svc_fh *dirfhp, *newfhp;
1da177e4
LT
382
383 dprintk("nfsd: CREATE(3) %s %.*s\n",
384 SVCFH_fmt(&argp->fh),
385 argp->len,
386 argp->name);
387
388 dirfhp = fh_copy(&resp->dirfh, &argp->fh);
389 newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
1da177e4 390
df9606ab 391 resp->status = nfsd3_create_file(rqstp, dirfhp, newfhp, argp);
1459ad57 392 resp->status = nfsd3_map_status(resp->status);
cc028a10 393 return rpc_success;
1da177e4
LT
394}
395
396/*
397 * Make directory. This operation is not idempotent.
398 */
7111c66e 399static __be32
a6beb732 400nfsd3_proc_mkdir(struct svc_rqst *rqstp)
1da177e4 401{
a6beb732
CH
402 struct nfsd3_createargs *argp = rqstp->rq_argp;
403 struct nfsd3_diropres *resp = rqstp->rq_resp;
7fe2a71d
N
404 struct nfsd_attrs attrs = {
405 .na_iattr = &argp->attrs,
406 };
1da177e4
LT
407
408 dprintk("nfsd: MKDIR(3) %s %.*s\n",
409 SVCFH_fmt(&argp->fh),
410 argp->len,
411 argp->name);
412
413 argp->attrs.ia_valid &= ~ATTR_SIZE;
414 fh_copy(&resp->dirfh, &argp->fh);
415 fh_init(&resp->fh, NFS3_FHSIZE);
14168d67 416 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
7fe2a71d 417 &attrs, S_IFDIR, 0, &resp->fh);
1459ad57 418 resp->status = nfsd3_map_status(resp->status);
cc028a10 419 return rpc_success;
1da177e4
LT
420}
421
7111c66e 422static __be32
a6beb732 423nfsd3_proc_symlink(struct svc_rqst *rqstp)
1da177e4 424{
a6beb732
CH
425 struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
426 struct nfsd3_diropres *resp = rqstp->rq_resp;
93adc1e3
N
427 struct nfsd_attrs attrs = {
428 .na_iattr = &argp->attrs,
429 };
1da177e4 430
14168d67
CL
431 if (argp->tlen == 0) {
432 resp->status = nfserr_inval;
433 goto out;
434 }
435 if (argp->tlen > NFS3_MAXPATHLEN) {
436 resp->status = nfserr_nametoolong;
437 goto out;
438 }
38a70315
CL
439
440 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
11b4d66e 441 page_address(rqstp->rq_arg.pages[0]),
38a70315 442 argp->tlen);
14168d67
CL
443 if (IS_ERR(argp->tname)) {
444 resp->status = nfserrno(PTR_ERR(argp->tname));
445 goto out;
446 }
38a70315 447
1da177e4
LT
448 dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
449 SVCFH_fmt(&argp->ffh),
450 argp->flen, argp->fname,
451 argp->tlen, argp->tname);
452
453 fh_copy(&resp->dirfh, &argp->ffh);
454 fh_init(&resp->fh, NFS3_FHSIZE);
14168d67 455 resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
93adc1e3 456 argp->flen, argp->tname, &attrs, &resp->fh);
11b4d66e 457 kfree(argp->tname);
14168d67 458out:
1459ad57 459 resp->status = nfsd3_map_status(resp->status);
cc028a10 460 return rpc_success;
1da177e4
LT
461}
462
463/*
464 * Make socket/fifo/device.
465 */
7111c66e 466static __be32
a6beb732 467nfsd3_proc_mknod(struct svc_rqst *rqstp)
1da177e4 468{
a6beb732
CH
469 struct nfsd3_mknodargs *argp = rqstp->rq_argp;
470 struct nfsd3_diropres *resp = rqstp->rq_resp;
7fe2a71d
N
471 struct nfsd_attrs attrs = {
472 .na_iattr = &argp->attrs,
473 };
c4d987ba 474 int type;
1da177e4
LT
475 dev_t rdev = 0;
476
477 dprintk("nfsd: MKNOD(3) %s %.*s\n",
478 SVCFH_fmt(&argp->fh),
479 argp->len,
480 argp->name);
481
482 fh_copy(&resp->dirfh, &argp->fh);
483 fh_init(&resp->fh, NFS3_FHSIZE);
484
1da177e4
LT
485 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
486 rdev = MKDEV(argp->major, argp->minor);
487 if (MAJOR(rdev) != argp->major ||
14168d67
CL
488 MINOR(rdev) != argp->minor) {
489 resp->status = nfserr_inval;
490 goto out;
491 }
492 } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
66d60e3a 493 resp->status = nfserr_badtype;
14168d67
CL
494 goto out;
495 }
1da177e4
LT
496
497 type = nfs3_ftypes[argp->ftype];
14168d67 498 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
7fe2a71d 499 &attrs, type, rdev, &resp->fh);
14168d67 500out:
1459ad57 501 resp->status = nfsd3_map_status(resp->status);
cc028a10 502 return rpc_success;
1da177e4
LT
503}
504
505/*
506 * Remove file/fifo/socket etc.
507 */
7111c66e 508static __be32
a6beb732 509nfsd3_proc_remove(struct svc_rqst *rqstp)
1da177e4 510{
a6beb732
CH
511 struct nfsd3_diropargs *argp = rqstp->rq_argp;
512 struct nfsd3_attrstat *resp = rqstp->rq_resp;
1da177e4
LT
513
514 dprintk("nfsd: REMOVE(3) %s %.*s\n",
515 SVCFH_fmt(&argp->fh),
516 argp->len,
517 argp->name);
518
519 /* Unlink. -S_IFDIR means file must not be a directory */
520 fh_copy(&resp->fh, &argp->fh);
14168d67
CL
521 resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
522 argp->name, argp->len);
1459ad57 523 resp->status = nfsd3_map_status(resp->status);
cc028a10 524 return rpc_success;
1da177e4
LT
525}
526
527/*
528 * Remove a directory
529 */
7111c66e 530static __be32
a6beb732 531nfsd3_proc_rmdir(struct svc_rqst *rqstp)
1da177e4 532{
a6beb732
CH
533 struct nfsd3_diropargs *argp = rqstp->rq_argp;
534 struct nfsd3_attrstat *resp = rqstp->rq_resp;
1da177e4
LT
535
536 dprintk("nfsd: RMDIR(3) %s %.*s\n",
537 SVCFH_fmt(&argp->fh),
538 argp->len,
539 argp->name);
540
541 fh_copy(&resp->fh, &argp->fh);
14168d67
CL
542 resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
543 argp->name, argp->len);
1459ad57 544 resp->status = nfsd3_map_status(resp->status);
cc028a10 545 return rpc_success;
1da177e4
LT
546}
547
7111c66e 548static __be32
a6beb732 549nfsd3_proc_rename(struct svc_rqst *rqstp)
1da177e4 550{
a6beb732
CH
551 struct nfsd3_renameargs *argp = rqstp->rq_argp;
552 struct nfsd3_renameres *resp = rqstp->rq_resp;
1da177e4
LT
553
554 dprintk("nfsd: RENAME(3) %s %.*s ->\n",
555 SVCFH_fmt(&argp->ffh),
556 argp->flen,
557 argp->fname);
558 dprintk("nfsd: -> %s %.*s\n",
559 SVCFH_fmt(&argp->tfh),
560 argp->tlen,
561 argp->tname);
562
563 fh_copy(&resp->ffh, &argp->ffh);
564 fh_copy(&resp->tfh, &argp->tfh);
14168d67
CL
565 resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
566 &resp->tfh, argp->tname, argp->tlen);
1459ad57 567 resp->status = nfsd3_map_status(resp->status);
cc028a10 568 return rpc_success;
1da177e4
LT
569}
570
7111c66e 571static __be32
a6beb732 572nfsd3_proc_link(struct svc_rqst *rqstp)
1da177e4 573{
a6beb732
CH
574 struct nfsd3_linkargs *argp = rqstp->rq_argp;
575 struct nfsd3_linkres *resp = rqstp->rq_resp;
1da177e4
LT
576
577 dprintk("nfsd: LINK(3) %s ->\n",
578 SVCFH_fmt(&argp->ffh));
579 dprintk("nfsd: -> %s %.*s\n",
580 SVCFH_fmt(&argp->tfh),
581 argp->tlen,
582 argp->tname);
583
584 fh_copy(&resp->fh, &argp->ffh);
585 fh_copy(&resp->tfh, &argp->tfh);
14168d67
CL
586 resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
587 &resp->fh);
1459ad57 588 resp->status = nfsd3_map_status(resp->status);
cc028a10 589 return rpc_success;
1da177e4
LT
590}
591
40116ebd
CL
592static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
593 struct nfsd3_readdirres *resp,
53b1119a 594 u32 count)
40116ebd 595{
7f87fc2d
CL
596 struct xdr_buf *buf = &resp->dirlist;
597 struct xdr_stream *xdr = &resp->xdr;
640f87c1
CL
598 unsigned int sendbuf = min_t(unsigned int, rqstp->rq_res.buflen,
599 svc_max_payload(rqstp));
40116ebd 600
7f87fc2d 601 memset(buf, 0, sizeof(*buf));
40116ebd 602
7f87fc2d 603 /* Reserve room for the NULL ptr & eof flag (-2 words) */
640f87c1
CL
604 buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), sendbuf);
605 buf->buflen -= XDR_UNIT * 2;
7f87fc2d 606 buf->pages = rqstp->rq_next_page;
53b1119a 607 rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
7f87fc2d 608
98124f5b 609 xdr_init_encode_pages(xdr, buf, buf->pages, NULL);
40116ebd
CL
610}
611
1da177e4
LT
612/*
613 * Read a portion of a directory.
614 */
7111c66e 615static __be32
a6beb732 616nfsd3_proc_readdir(struct svc_rqst *rqstp)
1da177e4 617{
a6beb732
CH
618 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
619 struct nfsd3_readdirres *resp = rqstp->rq_resp;
0a8f37fb 620 loff_t offset;
1da177e4
LT
621
622 dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
623 SVCFH_fmt(&argp->fh),
624 argp->count, (u32) argp->cookie);
625
40116ebd 626 nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
1da177e4 627
1da177e4 628 fh_copy(&resp->fh, &argp->fh);
1da177e4 629 resp->common.err = nfs_ok;
7f87fc2d 630 resp->cookie_offset = 0;
1da177e4 631 resp->rqstp = rqstp;
0a8f37fb 632 offset = argp->cookie;
0a8f37fb 633 resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
7f87fc2d 634 &resp->common, nfs3svc_encode_entry3);
1da177e4 635 memcpy(resp->verf, argp->verf, 8);
a161e6c7 636 nfs3svc_encode_cookie3(resp, offset);
1da177e4 637
76ed0dd9
CL
638 /* Recycle only pages that were part of the reply */
639 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
640
1459ad57 641 resp->status = nfsd3_map_status(resp->status);
cc028a10 642 return rpc_success;
1da177e4
LT
643}
644
645/*
646 * Read a portion of a directory, including file handles and attrs.
647 * For now, we choose to ignore the dircount parameter.
648 */
7111c66e 649static __be32
a6beb732 650nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
1da177e4 651{
a6beb732
CH
652 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
653 struct nfsd3_readdirres *resp = rqstp->rq_resp;
1da177e4 654 loff_t offset;
1da177e4
LT
655
656 dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
657 SVCFH_fmt(&argp->fh),
658 argp->count, (u32) argp->cookie);
659
40116ebd 660 nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
1da177e4 661
1da177e4 662 fh_copy(&resp->fh, &argp->fh);
1da177e4 663 resp->common.err = nfs_ok;
7f87fc2d 664 resp->cookie_offset = 0;
1da177e4
LT
665 resp->rqstp = rqstp;
666 offset = argp->cookie;
18c01ab3 667
14168d67
CL
668 resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
669 if (resp->status != nfs_ok)
670 goto out;
18c01ab3 671
14168d67
CL
672 if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) {
673 resp->status = nfserr_notsupp;
674 goto out;
675 }
18c01ab3 676
14168d67 677 resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
7f87fc2d 678 &resp->common, nfs3svc_encode_entryplus3);
1da177e4 679 memcpy(resp->verf, argp->verf, 8);
a161e6c7 680 nfs3svc_encode_cookie3(resp, offset);
1da177e4 681
76ed0dd9
CL
682 /* Recycle only pages that were part of the reply */
683 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
684
14168d67 685out:
1459ad57 686 resp->status = nfsd3_map_status(resp->status);
cc028a10 687 return rpc_success;
1da177e4
LT
688}
689
690/*
691 * Get file system stats
692 */
7111c66e 693static __be32
a6beb732 694nfsd3_proc_fsstat(struct svc_rqst *rqstp)
1da177e4 695{
a6beb732
CH
696 struct nfsd_fhandle *argp = rqstp->rq_argp;
697 struct nfsd3_fsstatres *resp = rqstp->rq_resp;
1da177e4
LT
698
699 dprintk("nfsd: FSSTAT(3) %s\n",
700 SVCFH_fmt(&argp->fh));
701
14168d67 702 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
1da177e4 703 fh_put(&argp->fh);
1459ad57 704 resp->status = nfsd3_map_status(resp->status);
cc028a10 705 return rpc_success;
1da177e4
LT
706}
707
708/*
709 * Get file system info
710 */
7111c66e 711static __be32
a6beb732 712nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
1da177e4 713{
a6beb732
CH
714 struct nfsd_fhandle *argp = rqstp->rq_argp;
715 struct nfsd3_fsinfores *resp = rqstp->rq_resp;
7adae489 716 u32 max_blocksize = svc_max_payload(rqstp);
1da177e4
LT
717
718 dprintk("nfsd: FSINFO(3) %s\n",
719 SVCFH_fmt(&argp->fh));
720
7adae489
GB
721 resp->f_rtmax = max_blocksize;
722 resp->f_rtpref = max_blocksize;
1da177e4 723 resp->f_rtmult = PAGE_SIZE;
7adae489
GB
724 resp->f_wtmax = max_blocksize;
725 resp->f_wtpref = max_blocksize;
1da177e4 726 resp->f_wtmult = PAGE_SIZE;
f875a792 727 resp->f_dtpref = max_blocksize;
1da177e4
LT
728 resp->f_maxfilesize = ~(u32) 0;
729 resp->f_properties = NFS3_FSF_DEFAULT;
730
14168d67
CL
731 resp->status = fh_verify(rqstp, &argp->fh, 0,
732 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
1da177e4
LT
733
734 /* Check special features of the file system. May request
735 * different read/write sizes for file systems known to have
736 * problems with large blocks */
14168d67 737 if (resp->status == nfs_ok) {
fc64005c 738 struct super_block *sb = argp->fh.fh_dentry->d_sb;
1da177e4
LT
739
740 /* Note that we don't care for remote fs's here */
12214cb7 741 if (sb->s_magic == MSDOS_SUPER_MAGIC) {
1da177e4
LT
742 resp->f_properties = NFS3_FSF_BILLYBOY;
743 }
744 resp->f_maxfilesize = sb->s_maxbytes;
745 }
746
747 fh_put(&argp->fh);
1459ad57 748 resp->status = nfsd3_map_status(resp->status);
cc028a10 749 return rpc_success;
1da177e4
LT
750}
751
752/*
753 * Get pathconf info for the specified file
754 */
7111c66e 755static __be32
a6beb732 756nfsd3_proc_pathconf(struct svc_rqst *rqstp)
1da177e4 757{
a6beb732
CH
758 struct nfsd_fhandle *argp = rqstp->rq_argp;
759 struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1da177e4
LT
760
761 dprintk("nfsd: PATHCONF(3) %s\n",
762 SVCFH_fmt(&argp->fh));
763
764 /* Set default pathconf */
765 resp->p_link_max = 255; /* at least */
766 resp->p_name_max = 255; /* at least */
767 resp->p_no_trunc = 0;
768 resp->p_chown_restricted = 1;
769 resp->p_case_insensitive = 0;
770 resp->p_case_preserving = 1;
771
14168d67 772 resp->status = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
1da177e4 773
14168d67 774 if (resp->status == nfs_ok) {
fc64005c 775 struct super_block *sb = argp->fh.fh_dentry->d_sb;
1da177e4
LT
776
777 /* Note that we don't care for remote fs's here */
778 switch (sb->s_magic) {
779 case EXT2_SUPER_MAGIC:
780 resp->p_link_max = EXT2_LINK_MAX;
781 resp->p_name_max = EXT2_NAME_LEN;
782 break;
12214cb7 783 case MSDOS_SUPER_MAGIC:
1da177e4
LT
784 resp->p_case_insensitive = 1;
785 resp->p_case_preserving = 0;
786 break;
787 }
788 }
789
790 fh_put(&argp->fh);
1459ad57 791 resp->status = nfsd3_map_status(resp->status);
cc028a10 792 return rpc_success;
1da177e4
LT
793}
794
1da177e4
LT
795/*
796 * Commit a file (range) to stable storage.
797 */
7111c66e 798static __be32
a6beb732 799nfsd3_proc_commit(struct svc_rqst *rqstp)
1da177e4 800{
a6beb732
CH
801 struct nfsd3_commitargs *argp = rqstp->rq_argp;
802 struct nfsd3_commitres *resp = rqstp->rq_resp;
c2528490 803 struct nfsd_file *nf;
1da177e4
LT
804
805 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
806 SVCFH_fmt(&argp->fh),
807 argp->count,
808 (unsigned long long) argp->offset);
809
1da177e4 810 fh_copy(&resp->fh, &argp->fh);
4d1ea845
CL
811 resp->status = nfsd_file_acquire_gc(rqstp, &resp->fh, NFSD_MAY_WRITE |
812 NFSD_MAY_NOT_BREAK_LEASE, &nf);
c2528490
CL
813 if (resp->status)
814 goto out;
815 resp->status = nfsd_commit(rqstp, &resp->fh, nf, argp->offset,
14168d67 816 argp->count, resp->verf);
c2528490
CL
817 nfsd_file_put(nf);
818out:
1459ad57 819 resp->status = nfsd3_map_status(resp->status);
cc028a10 820 return rpc_success;
1da177e4
LT
821}
822
823
824/*
825 * NFSv3 Server procedures.
826 * Only the results of non-idempotent operations are cached.
827 */
1da177e4
LT
828#define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
829#define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
830#define nfsd3_mkdirargs nfsd3_createargs
831#define nfsd3_readdirplusargs nfsd3_readdirargs
832#define nfsd3_fhandleargs nfsd_fhandle
1da177e4
LT
833#define nfsd3_attrstatres nfsd3_attrstat
834#define nfsd3_wccstatres nfsd3_attrstat
835#define nfsd3_createres nfsd3_diropres
1da177e4 836
1da177e4
LT
837#define ST 1 /* status*/
838#define FH 17 /* filehandle with length */
839#define AT 21 /* attributes */
840#define pAT (1+AT) /* post attributes - conditional */
841#define WC (7+pAT) /* WCC attributes */
842
860bda29 843static const struct svc_procedure nfsd_procedures3[22] = {
b9081d90 844 [NFS3PROC_NULL] = {
a6beb732 845 .pc_func = nfsd3_proc_null,
788f7183
CL
846 .pc_decode = nfssvc_decode_voidarg,
847 .pc_encode = nfssvc_encode_voidres,
848 .pc_argsize = sizeof(struct nfsd_voidargs),
103cc1fa 849 .pc_argzero = sizeof(struct nfsd_voidargs),
788f7183 850 .pc_ressize = sizeof(struct nfsd_voidres),
b9081d90
YZ
851 .pc_cachetype = RC_NOCACHE,
852 .pc_xdrressize = ST,
2289e87b 853 .pc_name = "NULL",
b9081d90
YZ
854 },
855 [NFS3PROC_GETATTR] = {
a6beb732 856 .pc_func = nfsd3_proc_getattr,
026fec7e 857 .pc_decode = nfs3svc_decode_fhandleargs,
2c42f804 858 .pc_encode = nfs3svc_encode_getattrres,
8537488b 859 .pc_release = nfs3svc_release_fhandle,
9575363a 860 .pc_argsize = sizeof(struct nfsd_fhandle),
103cc1fa 861 .pc_argzero = sizeof(struct nfsd_fhandle),
b9081d90
YZ
862 .pc_ressize = sizeof(struct nfsd3_attrstatres),
863 .pc_cachetype = RC_NOCACHE,
864 .pc_xdrressize = ST+AT,
2289e87b 865 .pc_name = "GETATTR",
b9081d90
YZ
866 },
867 [NFS3PROC_SETATTR] = {
a6beb732 868 .pc_func = nfsd3_proc_setattr,
026fec7e 869 .pc_decode = nfs3svc_decode_sattrargs,
63f8de37 870 .pc_encode = nfs3svc_encode_wccstatres,
8537488b 871 .pc_release = nfs3svc_release_fhandle,
b9081d90 872 .pc_argsize = sizeof(struct nfsd3_sattrargs),
103cc1fa 873 .pc_argzero = sizeof(struct nfsd3_sattrargs),
b9081d90
YZ
874 .pc_ressize = sizeof(struct nfsd3_wccstatres),
875 .pc_cachetype = RC_REPLBUFF,
876 .pc_xdrressize = ST+WC,
2289e87b 877 .pc_name = "SETATTR",
b9081d90
YZ
878 },
879 [NFS3PROC_LOOKUP] = {
a6beb732 880 .pc_func = nfsd3_proc_lookup,
026fec7e 881 .pc_decode = nfs3svc_decode_diropargs,
5cf35335 882 .pc_encode = nfs3svc_encode_lookupres,
8537488b 883 .pc_release = nfs3svc_release_fhandle2,
b9081d90 884 .pc_argsize = sizeof(struct nfsd3_diropargs),
103cc1fa 885 .pc_argzero = sizeof(struct nfsd3_diropargs),
b9081d90
YZ
886 .pc_ressize = sizeof(struct nfsd3_diropres),
887 .pc_cachetype = RC_NOCACHE,
888 .pc_xdrressize = ST+FH+pAT+pAT,
2289e87b 889 .pc_name = "LOOKUP",
b9081d90
YZ
890 },
891 [NFS3PROC_ACCESS] = {
a6beb732 892 .pc_func = nfsd3_proc_access,
026fec7e 893 .pc_decode = nfs3svc_decode_accessargs,
63f8de37 894 .pc_encode = nfs3svc_encode_accessres,
8537488b 895 .pc_release = nfs3svc_release_fhandle,
b9081d90 896 .pc_argsize = sizeof(struct nfsd3_accessargs),
103cc1fa 897 .pc_argzero = sizeof(struct nfsd3_accessargs),
b9081d90
YZ
898 .pc_ressize = sizeof(struct nfsd3_accessres),
899 .pc_cachetype = RC_NOCACHE,
900 .pc_xdrressize = ST+pAT+1,
2289e87b 901 .pc_name = "ACCESS",
b9081d90
YZ
902 },
903 [NFS3PROC_READLINK] = {
a6beb732 904 .pc_func = nfsd3_proc_readlink,
224c1c89 905 .pc_decode = nfs3svc_decode_fhandleargs,
63f8de37 906 .pc_encode = nfs3svc_encode_readlinkres,
8537488b 907 .pc_release = nfs3svc_release_fhandle,
224c1c89 908 .pc_argsize = sizeof(struct nfsd_fhandle),
103cc1fa 909 .pc_argzero = sizeof(struct nfsd_fhandle),
b9081d90
YZ
910 .pc_ressize = sizeof(struct nfsd3_readlinkres),
911 .pc_cachetype = RC_NOCACHE,
912 .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
2289e87b 913 .pc_name = "READLINK",
b9081d90
YZ
914 },
915 [NFS3PROC_READ] = {
a6beb732 916 .pc_func = nfsd3_proc_read,
026fec7e 917 .pc_decode = nfs3svc_decode_readargs,
63f8de37 918 .pc_encode = nfs3svc_encode_readres,
8537488b 919 .pc_release = nfs3svc_release_fhandle,
b9081d90 920 .pc_argsize = sizeof(struct nfsd3_readargs),
103cc1fa 921 .pc_argzero = sizeof(struct nfsd3_readargs),
b9081d90
YZ
922 .pc_ressize = sizeof(struct nfsd3_readres),
923 .pc_cachetype = RC_NOCACHE,
924 .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
2289e87b 925 .pc_name = "READ",
b9081d90
YZ
926 },
927 [NFS3PROC_WRITE] = {
a6beb732 928 .pc_func = nfsd3_proc_write,
026fec7e 929 .pc_decode = nfs3svc_decode_writeargs,
63f8de37 930 .pc_encode = nfs3svc_encode_writeres,
8537488b 931 .pc_release = nfs3svc_release_fhandle,
b9081d90 932 .pc_argsize = sizeof(struct nfsd3_writeargs),
103cc1fa 933 .pc_argzero = sizeof(struct nfsd3_writeargs),
b9081d90
YZ
934 .pc_ressize = sizeof(struct nfsd3_writeres),
935 .pc_cachetype = RC_REPLBUFF,
936 .pc_xdrressize = ST+WC+4,
2289e87b 937 .pc_name = "WRITE",
b9081d90
YZ
938 },
939 [NFS3PROC_CREATE] = {
a6beb732 940 .pc_func = nfsd3_proc_create,
026fec7e 941 .pc_decode = nfs3svc_decode_createargs,
63f8de37 942 .pc_encode = nfs3svc_encode_createres,
8537488b 943 .pc_release = nfs3svc_release_fhandle2,
b9081d90 944 .pc_argsize = sizeof(struct nfsd3_createargs),
103cc1fa 945 .pc_argzero = sizeof(struct nfsd3_createargs),
b9081d90
YZ
946 .pc_ressize = sizeof(struct nfsd3_createres),
947 .pc_cachetype = RC_REPLBUFF,
948 .pc_xdrressize = ST+(1+FH+pAT)+WC,
2289e87b 949 .pc_name = "CREATE",
b9081d90
YZ
950 },
951 [NFS3PROC_MKDIR] = {
a6beb732 952 .pc_func = nfsd3_proc_mkdir,
026fec7e 953 .pc_decode = nfs3svc_decode_mkdirargs,
63f8de37 954 .pc_encode = nfs3svc_encode_createres,
8537488b 955 .pc_release = nfs3svc_release_fhandle2,
b9081d90 956 .pc_argsize = sizeof(struct nfsd3_mkdirargs),
103cc1fa 957 .pc_argzero = sizeof(struct nfsd3_mkdirargs),
b9081d90
YZ
958 .pc_ressize = sizeof(struct nfsd3_createres),
959 .pc_cachetype = RC_REPLBUFF,
960 .pc_xdrressize = ST+(1+FH+pAT)+WC,
2289e87b 961 .pc_name = "MKDIR",
b9081d90
YZ
962 },
963 [NFS3PROC_SYMLINK] = {
a6beb732 964 .pc_func = nfsd3_proc_symlink,
026fec7e 965 .pc_decode = nfs3svc_decode_symlinkargs,
63f8de37 966 .pc_encode = nfs3svc_encode_createres,
8537488b 967 .pc_release = nfs3svc_release_fhandle2,
b9081d90 968 .pc_argsize = sizeof(struct nfsd3_symlinkargs),
103cc1fa 969 .pc_argzero = sizeof(struct nfsd3_symlinkargs),
b9081d90
YZ
970 .pc_ressize = sizeof(struct nfsd3_createres),
971 .pc_cachetype = RC_REPLBUFF,
972 .pc_xdrressize = ST+(1+FH+pAT)+WC,
2289e87b 973 .pc_name = "SYMLINK",
b9081d90
YZ
974 },
975 [NFS3PROC_MKNOD] = {
a6beb732 976 .pc_func = nfsd3_proc_mknod,
026fec7e 977 .pc_decode = nfs3svc_decode_mknodargs,
63f8de37 978 .pc_encode = nfs3svc_encode_createres,
8537488b 979 .pc_release = nfs3svc_release_fhandle2,
b9081d90 980 .pc_argsize = sizeof(struct nfsd3_mknodargs),
103cc1fa 981 .pc_argzero = sizeof(struct nfsd3_mknodargs),
b9081d90
YZ
982 .pc_ressize = sizeof(struct nfsd3_createres),
983 .pc_cachetype = RC_REPLBUFF,
984 .pc_xdrressize = ST+(1+FH+pAT)+WC,
2289e87b 985 .pc_name = "MKNOD",
b9081d90
YZ
986 },
987 [NFS3PROC_REMOVE] = {
a6beb732 988 .pc_func = nfsd3_proc_remove,
026fec7e 989 .pc_decode = nfs3svc_decode_diropargs,
63f8de37 990 .pc_encode = nfs3svc_encode_wccstatres,
8537488b 991 .pc_release = nfs3svc_release_fhandle,
b9081d90 992 .pc_argsize = sizeof(struct nfsd3_diropargs),
103cc1fa 993 .pc_argzero = sizeof(struct nfsd3_diropargs),
b9081d90
YZ
994 .pc_ressize = sizeof(struct nfsd3_wccstatres),
995 .pc_cachetype = RC_REPLBUFF,
996 .pc_xdrressize = ST+WC,
2289e87b 997 .pc_name = "REMOVE",
b9081d90
YZ
998 },
999 [NFS3PROC_RMDIR] = {
a6beb732 1000 .pc_func = nfsd3_proc_rmdir,
026fec7e 1001 .pc_decode = nfs3svc_decode_diropargs,
63f8de37 1002 .pc_encode = nfs3svc_encode_wccstatres,
8537488b 1003 .pc_release = nfs3svc_release_fhandle,
b9081d90 1004 .pc_argsize = sizeof(struct nfsd3_diropargs),
103cc1fa 1005 .pc_argzero = sizeof(struct nfsd3_diropargs),
b9081d90
YZ
1006 .pc_ressize = sizeof(struct nfsd3_wccstatres),
1007 .pc_cachetype = RC_REPLBUFF,
1008 .pc_xdrressize = ST+WC,
2289e87b 1009 .pc_name = "RMDIR",
b9081d90
YZ
1010 },
1011 [NFS3PROC_RENAME] = {
a6beb732 1012 .pc_func = nfsd3_proc_rename,
026fec7e 1013 .pc_decode = nfs3svc_decode_renameargs,
63f8de37 1014 .pc_encode = nfs3svc_encode_renameres,
8537488b 1015 .pc_release = nfs3svc_release_fhandle2,
b9081d90 1016 .pc_argsize = sizeof(struct nfsd3_renameargs),
103cc1fa 1017 .pc_argzero = sizeof(struct nfsd3_renameargs),
b9081d90
YZ
1018 .pc_ressize = sizeof(struct nfsd3_renameres),
1019 .pc_cachetype = RC_REPLBUFF,
1020 .pc_xdrressize = ST+WC+WC,
2289e87b 1021 .pc_name = "RENAME",
b9081d90
YZ
1022 },
1023 [NFS3PROC_LINK] = {
a6beb732 1024 .pc_func = nfsd3_proc_link,
026fec7e 1025 .pc_decode = nfs3svc_decode_linkargs,
63f8de37 1026 .pc_encode = nfs3svc_encode_linkres,
8537488b 1027 .pc_release = nfs3svc_release_fhandle2,
b9081d90 1028 .pc_argsize = sizeof(struct nfsd3_linkargs),
103cc1fa 1029 .pc_argzero = sizeof(struct nfsd3_linkargs),
b9081d90
YZ
1030 .pc_ressize = sizeof(struct nfsd3_linkres),
1031 .pc_cachetype = RC_REPLBUFF,
1032 .pc_xdrressize = ST+pAT+WC,
2289e87b 1033 .pc_name = "LINK",
b9081d90
YZ
1034 },
1035 [NFS3PROC_READDIR] = {
a6beb732 1036 .pc_func = nfsd3_proc_readdir,
026fec7e 1037 .pc_decode = nfs3svc_decode_readdirargs,
63f8de37 1038 .pc_encode = nfs3svc_encode_readdirres,
8537488b 1039 .pc_release = nfs3svc_release_fhandle,
b9081d90 1040 .pc_argsize = sizeof(struct nfsd3_readdirargs),
103cc1fa 1041 .pc_argzero = sizeof(struct nfsd3_readdirargs),
b9081d90
YZ
1042 .pc_ressize = sizeof(struct nfsd3_readdirres),
1043 .pc_cachetype = RC_NOCACHE,
2289e87b 1044 .pc_name = "READDIR",
b9081d90
YZ
1045 },
1046 [NFS3PROC_READDIRPLUS] = {
a6beb732 1047 .pc_func = nfsd3_proc_readdirplus,
026fec7e 1048 .pc_decode = nfs3svc_decode_readdirplusargs,
63f8de37 1049 .pc_encode = nfs3svc_encode_readdirres,
8537488b 1050 .pc_release = nfs3svc_release_fhandle,
b9081d90 1051 .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
103cc1fa 1052 .pc_argzero = sizeof(struct nfsd3_readdirplusargs),
b9081d90
YZ
1053 .pc_ressize = sizeof(struct nfsd3_readdirres),
1054 .pc_cachetype = RC_NOCACHE,
2289e87b 1055 .pc_name = "READDIRPLUS",
b9081d90
YZ
1056 },
1057 [NFS3PROC_FSSTAT] = {
a6beb732 1058 .pc_func = nfsd3_proc_fsstat,
026fec7e 1059 .pc_decode = nfs3svc_decode_fhandleargs,
63f8de37 1060 .pc_encode = nfs3svc_encode_fsstatres,
b9081d90 1061 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
103cc1fa 1062 .pc_argzero = sizeof(struct nfsd3_fhandleargs),
b9081d90
YZ
1063 .pc_ressize = sizeof(struct nfsd3_fsstatres),
1064 .pc_cachetype = RC_NOCACHE,
1065 .pc_xdrressize = ST+pAT+2*6+1,
2289e87b 1066 .pc_name = "FSSTAT",
b9081d90
YZ
1067 },
1068 [NFS3PROC_FSINFO] = {
a6beb732 1069 .pc_func = nfsd3_proc_fsinfo,
026fec7e 1070 .pc_decode = nfs3svc_decode_fhandleargs,
63f8de37 1071 .pc_encode = nfs3svc_encode_fsinfores,
b9081d90 1072 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
103cc1fa 1073 .pc_argzero = sizeof(struct nfsd3_fhandleargs),
b9081d90
YZ
1074 .pc_ressize = sizeof(struct nfsd3_fsinfores),
1075 .pc_cachetype = RC_NOCACHE,
1076 .pc_xdrressize = ST+pAT+12,
2289e87b 1077 .pc_name = "FSINFO",
b9081d90
YZ
1078 },
1079 [NFS3PROC_PATHCONF] = {
a6beb732 1080 .pc_func = nfsd3_proc_pathconf,
026fec7e 1081 .pc_decode = nfs3svc_decode_fhandleargs,
63f8de37 1082 .pc_encode = nfs3svc_encode_pathconfres,
b9081d90 1083 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
103cc1fa 1084 .pc_argzero = sizeof(struct nfsd3_fhandleargs),
b9081d90
YZ
1085 .pc_ressize = sizeof(struct nfsd3_pathconfres),
1086 .pc_cachetype = RC_NOCACHE,
1087 .pc_xdrressize = ST+pAT+6,
2289e87b 1088 .pc_name = "PATHCONF",
b9081d90
YZ
1089 },
1090 [NFS3PROC_COMMIT] = {
a6beb732 1091 .pc_func = nfsd3_proc_commit,
026fec7e 1092 .pc_decode = nfs3svc_decode_commitargs,
63f8de37 1093 .pc_encode = nfs3svc_encode_commitres,
8537488b 1094 .pc_release = nfs3svc_release_fhandle,
b9081d90 1095 .pc_argsize = sizeof(struct nfsd3_commitargs),
103cc1fa 1096 .pc_argzero = sizeof(struct nfsd3_commitargs),
b9081d90
YZ
1097 .pc_ressize = sizeof(struct nfsd3_commitres),
1098 .pc_cachetype = RC_NOCACHE,
1099 .pc_xdrressize = ST+WC+2,
2289e87b 1100 .pc_name = "COMMIT",
b9081d90 1101 },
1da177e4
LT
1102};
1103
65ba3d24
CL
1104static DEFINE_PER_CPU_ALIGNED(unsigned long,
1105 nfsd_count3[ARRAY_SIZE(nfsd_procedures3)]);
e9679189
CH
1106const struct svc_version nfsd_version3 = {
1107 .vs_vers = 3,
65ba3d24 1108 .vs_nproc = ARRAY_SIZE(nfsd_procedures3),
e9679189
CH
1109 .vs_proc = nfsd_procedures3,
1110 .vs_dispatch = nfsd_dispatch,
1111 .vs_count = nfsd_count3,
1112 .vs_xdrsize = NFS3_SVC_XDRSIZE,
1da177e4 1113};
This page took 1.382728 seconds and 4 git commands to generate.