]> Git Repo - linux.git/blob - fs/nfsd/nfs3proc.c
KVM: x86/xen: intercept EVTCHNOP_send from guests
[linux.git] / fs / nfsd / nfs3proc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Process version 3 NFS requests.
4  *
5  * Copyright (C) 1996, 1997, 1998 Olaf Kirch <[email protected]>
6  */
7
8 #include <linux/fs.h>
9 #include <linux/ext2_fs.h>
10 #include <linux/magic.h>
11
12 #include "cache.h"
13 #include "xdr3.h"
14 #include "vfs.h"
15
16 #define NFSDDBG_FACILITY                NFSDDBG_PROC
17
18 static int      nfs3_ftypes[] = {
19         0,                      /* NF3NON */
20         S_IFREG,                /* NF3REG */
21         S_IFDIR,                /* NF3DIR */
22         S_IFBLK,                /* NF3BLK */
23         S_IFCHR,                /* NF3CHR */
24         S_IFLNK,                /* NF3LNK */
25         S_IFSOCK,               /* NF3SOCK */
26         S_IFIFO,                /* NF3FIFO */
27 };
28
29 /*
30  * NULL call.
31  */
32 static __be32
33 nfsd3_proc_null(struct svc_rqst *rqstp)
34 {
35         return rpc_success;
36 }
37
38 /*
39  * Get a file's attributes
40  */
41 static __be32
42 nfsd3_proc_getattr(struct svc_rqst *rqstp)
43 {
44         struct nfsd_fhandle *argp = rqstp->rq_argp;
45         struct nfsd3_attrstat *resp = rqstp->rq_resp;
46
47         dprintk("nfsd: GETATTR(3)  %s\n",
48                 SVCFH_fmt(&argp->fh));
49
50         fh_copy(&resp->fh, &argp->fh);
51         resp->status = fh_verify(rqstp, &resp->fh, 0,
52                                  NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
53         if (resp->status != nfs_ok)
54                 goto out;
55
56         resp->status = fh_getattr(&resp->fh, &resp->stat);
57 out:
58         return rpc_success;
59 }
60
61 /*
62  * Set a file's attributes
63  */
64 static __be32
65 nfsd3_proc_setattr(struct svc_rqst *rqstp)
66 {
67         struct nfsd3_sattrargs *argp = rqstp->rq_argp;
68         struct nfsd3_attrstat *resp = rqstp->rq_resp;
69
70         dprintk("nfsd: SETATTR(3)  %s\n",
71                                 SVCFH_fmt(&argp->fh));
72
73         fh_copy(&resp->fh, &argp->fh);
74         resp->status = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
75                                     argp->check_guard, argp->guardtime);
76         return rpc_success;
77 }
78
79 /*
80  * Look up a path name component
81  */
82 static __be32
83 nfsd3_proc_lookup(struct svc_rqst *rqstp)
84 {
85         struct nfsd3_diropargs *argp = rqstp->rq_argp;
86         struct nfsd3_diropres  *resp = rqstp->rq_resp;
87
88         dprintk("nfsd: LOOKUP(3)   %s %.*s\n",
89                                 SVCFH_fmt(&argp->fh),
90                                 argp->len,
91                                 argp->name);
92
93         fh_copy(&resp->dirfh, &argp->fh);
94         fh_init(&resp->fh, NFS3_FHSIZE);
95
96         resp->status = nfsd_lookup(rqstp, &resp->dirfh,
97                                    argp->name, argp->len,
98                                    &resp->fh);
99         return rpc_success;
100 }
101
102 /*
103  * Check file access
104  */
105 static __be32
106 nfsd3_proc_access(struct svc_rqst *rqstp)
107 {
108         struct nfsd3_accessargs *argp = rqstp->rq_argp;
109         struct nfsd3_accessres *resp = rqstp->rq_resp;
110
111         dprintk("nfsd: ACCESS(3)   %s 0x%x\n",
112                                 SVCFH_fmt(&argp->fh),
113                                 argp->access);
114
115         fh_copy(&resp->fh, &argp->fh);
116         resp->access = argp->access;
117         resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
118         return rpc_success;
119 }
120
121 /*
122  * Read a symlink.
123  */
124 static __be32
125 nfsd3_proc_readlink(struct svc_rqst *rqstp)
126 {
127         struct nfsd_fhandle *argp = rqstp->rq_argp;
128         struct nfsd3_readlinkres *resp = rqstp->rq_resp;
129
130         dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
131
132         /* Read the symlink. */
133         fh_copy(&resp->fh, &argp->fh);
134         resp->len = NFS3_MAXPATHLEN;
135         resp->pages = rqstp->rq_next_page++;
136         resp->status = nfsd_readlink(rqstp, &resp->fh,
137                                      page_address(*resp->pages), &resp->len);
138         return rpc_success;
139 }
140
141 /*
142  * Read a portion of a file.
143  */
144 static __be32
145 nfsd3_proc_read(struct svc_rqst *rqstp)
146 {
147         struct nfsd3_readargs *argp = rqstp->rq_argp;
148         struct nfsd3_readres *resp = rqstp->rq_resp;
149         u32 max_blocksize = svc_max_payload(rqstp);
150         unsigned int len;
151         int v;
152
153         argp->count = min_t(u32, argp->count, max_blocksize);
154
155         dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
156                                 SVCFH_fmt(&argp->fh),
157                                 (unsigned long) argp->count,
158                                 (unsigned long long) argp->offset);
159
160         v = 0;
161         len = argp->count;
162         resp->pages = rqstp->rq_next_page;
163         while (len > 0) {
164                 struct page *page = *(rqstp->rq_next_page++);
165
166                 rqstp->rq_vec[v].iov_base = page_address(page);
167                 rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
168                 len -= rqstp->rq_vec[v].iov_len;
169                 v++;
170         }
171
172         /* Obtain buffer pointer for payload.
173          * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
174          * + 1 (xdr opaque byte count) = 26
175          */
176         resp->count = argp->count;
177         svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
178
179         fh_copy(&resp->fh, &argp->fh);
180         resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
181                                  rqstp->rq_vec, v, &resp->count, &resp->eof);
182         return rpc_success;
183 }
184
185 /*
186  * Write data to a file
187  */
188 static __be32
189 nfsd3_proc_write(struct svc_rqst *rqstp)
190 {
191         struct nfsd3_writeargs *argp = rqstp->rq_argp;
192         struct nfsd3_writeres *resp = rqstp->rq_resp;
193         unsigned long cnt = argp->len;
194         unsigned int nvecs;
195
196         dprintk("nfsd: WRITE(3)    %s %d bytes at %Lu%s\n",
197                                 SVCFH_fmt(&argp->fh),
198                                 argp->len,
199                                 (unsigned long long) argp->offset,
200                                 argp->stable? " stable" : "");
201
202         fh_copy(&resp->fh, &argp->fh);
203         resp->committed = argp->stable;
204         nvecs = svc_fill_write_vector(rqstp, &argp->payload);
205
206         resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
207                                   rqstp->rq_vec, nvecs, &cnt,
208                                   resp->committed, resp->verf);
209         resp->count = cnt;
210         return rpc_success;
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  */
218 static __be32
219 nfsd3_proc_create(struct svc_rqst *rqstp)
220 {
221         struct nfsd3_createargs *argp = rqstp->rq_argp;
222         struct nfsd3_diropres *resp = rqstp->rq_resp;
223         svc_fh          *dirfhp, *newfhp = NULL;
224         struct iattr    *attr;
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         /* Unfudge the mode bits */
236         attr->ia_mode &= ~S_IFMT;
237         if (!(attr->ia_valid & ATTR_MODE)) { 
238                 attr->ia_valid |= ATTR_MODE;
239                 attr->ia_mode = S_IFREG;
240         } else {
241                 attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
242         }
243
244         /* Now create the file and set attributes */
245         resp->status = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
246                                       attr, newfhp, argp->createmode,
247                                       (u32 *)argp->verf, NULL, NULL);
248         return rpc_success;
249 }
250
251 /*
252  * Make directory. This operation is not idempotent.
253  */
254 static __be32
255 nfsd3_proc_mkdir(struct svc_rqst *rqstp)
256 {
257         struct nfsd3_createargs *argp = rqstp->rq_argp;
258         struct nfsd3_diropres *resp = rqstp->rq_resp;
259
260         dprintk("nfsd: MKDIR(3)    %s %.*s\n",
261                                 SVCFH_fmt(&argp->fh),
262                                 argp->len,
263                                 argp->name);
264
265         argp->attrs.ia_valid &= ~ATTR_SIZE;
266         fh_copy(&resp->dirfh, &argp->fh);
267         fh_init(&resp->fh, NFS3_FHSIZE);
268         resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
269                                    &argp->attrs, S_IFDIR, 0, &resp->fh);
270         fh_unlock(&resp->dirfh);
271         return rpc_success;
272 }
273
274 static __be32
275 nfsd3_proc_symlink(struct svc_rqst *rqstp)
276 {
277         struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
278         struct nfsd3_diropres *resp = rqstp->rq_resp;
279
280         if (argp->tlen == 0) {
281                 resp->status = nfserr_inval;
282                 goto out;
283         }
284         if (argp->tlen > NFS3_MAXPATHLEN) {
285                 resp->status = nfserr_nametoolong;
286                 goto out;
287         }
288
289         argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
290                                                 page_address(rqstp->rq_arg.pages[0]),
291                                                 argp->tlen);
292         if (IS_ERR(argp->tname)) {
293                 resp->status = nfserrno(PTR_ERR(argp->tname));
294                 goto out;
295         }
296
297         dprintk("nfsd: SYMLINK(3)  %s %.*s -> %.*s\n",
298                                 SVCFH_fmt(&argp->ffh),
299                                 argp->flen, argp->fname,
300                                 argp->tlen, argp->tname);
301
302         fh_copy(&resp->dirfh, &argp->ffh);
303         fh_init(&resp->fh, NFS3_FHSIZE);
304         resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
305                                     argp->flen, argp->tname, &resp->fh);
306         kfree(argp->tname);
307 out:
308         return rpc_success;
309 }
310
311 /*
312  * Make socket/fifo/device.
313  */
314 static __be32
315 nfsd3_proc_mknod(struct svc_rqst *rqstp)
316 {
317         struct nfsd3_mknodargs *argp = rqstp->rq_argp;
318         struct nfsd3_diropres  *resp = rqstp->rq_resp;
319         int type;
320         dev_t   rdev = 0;
321
322         dprintk("nfsd: MKNOD(3)    %s %.*s\n",
323                                 SVCFH_fmt(&argp->fh),
324                                 argp->len,
325                                 argp->name);
326
327         fh_copy(&resp->dirfh, &argp->fh);
328         fh_init(&resp->fh, NFS3_FHSIZE);
329
330         if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
331                 rdev = MKDEV(argp->major, argp->minor);
332                 if (MAJOR(rdev) != argp->major ||
333                     MINOR(rdev) != argp->minor) {
334                         resp->status = nfserr_inval;
335                         goto out;
336                 }
337         } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
338                 resp->status = nfserr_badtype;
339                 goto out;
340         }
341
342         type = nfs3_ftypes[argp->ftype];
343         resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
344                                    &argp->attrs, type, rdev, &resp->fh);
345         fh_unlock(&resp->dirfh);
346 out:
347         return rpc_success;
348 }
349
350 /*
351  * Remove file/fifo/socket etc.
352  */
353 static __be32
354 nfsd3_proc_remove(struct svc_rqst *rqstp)
355 {
356         struct nfsd3_diropargs *argp = rqstp->rq_argp;
357         struct nfsd3_attrstat *resp = rqstp->rq_resp;
358
359         dprintk("nfsd: REMOVE(3)   %s %.*s\n",
360                                 SVCFH_fmt(&argp->fh),
361                                 argp->len,
362                                 argp->name);
363
364         /* Unlink. -S_IFDIR means file must not be a directory */
365         fh_copy(&resp->fh, &argp->fh);
366         resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
367                                    argp->name, argp->len);
368         fh_unlock(&resp->fh);
369         return rpc_success;
370 }
371
372 /*
373  * Remove a directory
374  */
375 static __be32
376 nfsd3_proc_rmdir(struct svc_rqst *rqstp)
377 {
378         struct nfsd3_diropargs *argp = rqstp->rq_argp;
379         struct nfsd3_attrstat *resp = rqstp->rq_resp;
380
381         dprintk("nfsd: RMDIR(3)    %s %.*s\n",
382                                 SVCFH_fmt(&argp->fh),
383                                 argp->len,
384                                 argp->name);
385
386         fh_copy(&resp->fh, &argp->fh);
387         resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
388                                    argp->name, argp->len);
389         fh_unlock(&resp->fh);
390         return rpc_success;
391 }
392
393 static __be32
394 nfsd3_proc_rename(struct svc_rqst *rqstp)
395 {
396         struct nfsd3_renameargs *argp = rqstp->rq_argp;
397         struct nfsd3_renameres *resp = rqstp->rq_resp;
398
399         dprintk("nfsd: RENAME(3)   %s %.*s ->\n",
400                                 SVCFH_fmt(&argp->ffh),
401                                 argp->flen,
402                                 argp->fname);
403         dprintk("nfsd: -> %s %.*s\n",
404                                 SVCFH_fmt(&argp->tfh),
405                                 argp->tlen,
406                                 argp->tname);
407
408         fh_copy(&resp->ffh, &argp->ffh);
409         fh_copy(&resp->tfh, &argp->tfh);
410         resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
411                                    &resp->tfh, argp->tname, argp->tlen);
412         return rpc_success;
413 }
414
415 static __be32
416 nfsd3_proc_link(struct svc_rqst *rqstp)
417 {
418         struct nfsd3_linkargs *argp = rqstp->rq_argp;
419         struct nfsd3_linkres  *resp = rqstp->rq_resp;
420
421         dprintk("nfsd: LINK(3)     %s ->\n",
422                                 SVCFH_fmt(&argp->ffh));
423         dprintk("nfsd:   -> %s %.*s\n",
424                                 SVCFH_fmt(&argp->tfh),
425                                 argp->tlen,
426                                 argp->tname);
427
428         fh_copy(&resp->fh,  &argp->ffh);
429         fh_copy(&resp->tfh, &argp->tfh);
430         resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
431                                  &resp->fh);
432         return rpc_success;
433 }
434
435 static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
436                                      struct nfsd3_readdirres *resp,
437                                      u32 count)
438 {
439         struct xdr_buf *buf = &resp->dirlist;
440         struct xdr_stream *xdr = &resp->xdr;
441
442         count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp));
443
444         memset(buf, 0, sizeof(*buf));
445
446         /* Reserve room for the NULL ptr & eof flag (-2 words) */
447         buf->buflen = count - XDR_UNIT * 2;
448         buf->pages = rqstp->rq_next_page;
449         rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
450
451         /* This is xdr_init_encode(), but it assumes that
452          * the head kvec has already been consumed. */
453         xdr_set_scratch_buffer(xdr, NULL, 0);
454         xdr->buf = buf;
455         xdr->page_ptr = buf->pages;
456         xdr->iov = NULL;
457         xdr->p = page_address(*buf->pages);
458         xdr->end = (void *)xdr->p + min_t(u32, buf->buflen, PAGE_SIZE);
459         xdr->rqst = NULL;
460 }
461
462 /*
463  * Read a portion of a directory.
464  */
465 static __be32
466 nfsd3_proc_readdir(struct svc_rqst *rqstp)
467 {
468         struct nfsd3_readdirargs *argp = rqstp->rq_argp;
469         struct nfsd3_readdirres  *resp = rqstp->rq_resp;
470         loff_t          offset;
471
472         dprintk("nfsd: READDIR(3)  %s %d bytes at %d\n",
473                                 SVCFH_fmt(&argp->fh),
474                                 argp->count, (u32) argp->cookie);
475
476         nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
477
478         fh_copy(&resp->fh, &argp->fh);
479         resp->common.err = nfs_ok;
480         resp->cookie_offset = 0;
481         resp->rqstp = rqstp;
482         offset = argp->cookie;
483         resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
484                                     &resp->common, nfs3svc_encode_entry3);
485         memcpy(resp->verf, argp->verf, 8);
486         nfs3svc_encode_cookie3(resp, offset);
487
488         /* Recycle only pages that were part of the reply */
489         rqstp->rq_next_page = resp->xdr.page_ptr + 1;
490
491         return rpc_success;
492 }
493
494 /*
495  * Read a portion of a directory, including file handles and attrs.
496  * For now, we choose to ignore the dircount parameter.
497  */
498 static __be32
499 nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
500 {
501         struct nfsd3_readdirargs *argp = rqstp->rq_argp;
502         struct nfsd3_readdirres  *resp = rqstp->rq_resp;
503         loff_t  offset;
504
505         dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
506                                 SVCFH_fmt(&argp->fh),
507                                 argp->count, (u32) argp->cookie);
508
509         nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
510
511         fh_copy(&resp->fh, &argp->fh);
512         resp->common.err = nfs_ok;
513         resp->cookie_offset = 0;
514         resp->rqstp = rqstp;
515         offset = argp->cookie;
516
517         resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
518         if (resp->status != nfs_ok)
519                 goto out;
520
521         if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) {
522                 resp->status = nfserr_notsupp;
523                 goto out;
524         }
525
526         resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
527                                     &resp->common, nfs3svc_encode_entryplus3);
528         memcpy(resp->verf, argp->verf, 8);
529         nfs3svc_encode_cookie3(resp, offset);
530
531         /* Recycle only pages that were part of the reply */
532         rqstp->rq_next_page = resp->xdr.page_ptr + 1;
533
534 out:
535         return rpc_success;
536 }
537
538 /*
539  * Get file system stats
540  */
541 static __be32
542 nfsd3_proc_fsstat(struct svc_rqst *rqstp)
543 {
544         struct nfsd_fhandle *argp = rqstp->rq_argp;
545         struct nfsd3_fsstatres *resp = rqstp->rq_resp;
546
547         dprintk("nfsd: FSSTAT(3)   %s\n",
548                                 SVCFH_fmt(&argp->fh));
549
550         resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
551         fh_put(&argp->fh);
552         return rpc_success;
553 }
554
555 /*
556  * Get file system info
557  */
558 static __be32
559 nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
560 {
561         struct nfsd_fhandle *argp = rqstp->rq_argp;
562         struct nfsd3_fsinfores *resp = rqstp->rq_resp;
563         u32     max_blocksize = svc_max_payload(rqstp);
564
565         dprintk("nfsd: FSINFO(3)   %s\n",
566                                 SVCFH_fmt(&argp->fh));
567
568         resp->f_rtmax  = max_blocksize;
569         resp->f_rtpref = max_blocksize;
570         resp->f_rtmult = PAGE_SIZE;
571         resp->f_wtmax  = max_blocksize;
572         resp->f_wtpref = max_blocksize;
573         resp->f_wtmult = PAGE_SIZE;
574         resp->f_dtpref = max_blocksize;
575         resp->f_maxfilesize = ~(u32) 0;
576         resp->f_properties = NFS3_FSF_DEFAULT;
577
578         resp->status = fh_verify(rqstp, &argp->fh, 0,
579                                  NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
580
581         /* Check special features of the file system. May request
582          * different read/write sizes for file systems known to have
583          * problems with large blocks */
584         if (resp->status == nfs_ok) {
585                 struct super_block *sb = argp->fh.fh_dentry->d_sb;
586
587                 /* Note that we don't care for remote fs's here */
588                 if (sb->s_magic == MSDOS_SUPER_MAGIC) {
589                         resp->f_properties = NFS3_FSF_BILLYBOY;
590                 }
591                 resp->f_maxfilesize = sb->s_maxbytes;
592         }
593
594         fh_put(&argp->fh);
595         return rpc_success;
596 }
597
598 /*
599  * Get pathconf info for the specified file
600  */
601 static __be32
602 nfsd3_proc_pathconf(struct svc_rqst *rqstp)
603 {
604         struct nfsd_fhandle *argp = rqstp->rq_argp;
605         struct nfsd3_pathconfres *resp = rqstp->rq_resp;
606
607         dprintk("nfsd: PATHCONF(3) %s\n",
608                                 SVCFH_fmt(&argp->fh));
609
610         /* Set default pathconf */
611         resp->p_link_max = 255;         /* at least */
612         resp->p_name_max = 255;         /* at least */
613         resp->p_no_trunc = 0;
614         resp->p_chown_restricted = 1;
615         resp->p_case_insensitive = 0;
616         resp->p_case_preserving = 1;
617
618         resp->status = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
619
620         if (resp->status == nfs_ok) {
621                 struct super_block *sb = argp->fh.fh_dentry->d_sb;
622
623                 /* Note that we don't care for remote fs's here */
624                 switch (sb->s_magic) {
625                 case EXT2_SUPER_MAGIC:
626                         resp->p_link_max = EXT2_LINK_MAX;
627                         resp->p_name_max = EXT2_NAME_LEN;
628                         break;
629                 case MSDOS_SUPER_MAGIC:
630                         resp->p_case_insensitive = 1;
631                         resp->p_case_preserving  = 0;
632                         break;
633                 }
634         }
635
636         fh_put(&argp->fh);
637         return rpc_success;
638 }
639
640 /*
641  * Commit a file (range) to stable storage.
642  */
643 static __be32
644 nfsd3_proc_commit(struct svc_rqst *rqstp)
645 {
646         struct nfsd3_commitargs *argp = rqstp->rq_argp;
647         struct nfsd3_commitres *resp = rqstp->rq_resp;
648
649         dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
650                                 SVCFH_fmt(&argp->fh),
651                                 argp->count,
652                                 (unsigned long long) argp->offset);
653
654         if (argp->offset > NFS_OFFSET_MAX) {
655                 resp->status = nfserr_inval;
656                 goto out;
657         }
658
659         fh_copy(&resp->fh, &argp->fh);
660         resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset,
661                                    argp->count, resp->verf);
662 out:
663         return rpc_success;
664 }
665
666
667 /*
668  * NFSv3 Server procedures.
669  * Only the results of non-idempotent operations are cached.
670  */
671 #define nfs3svc_encode_attrstatres      nfs3svc_encode_attrstat
672 #define nfs3svc_encode_wccstatres       nfs3svc_encode_wccstat
673 #define nfsd3_mkdirargs                 nfsd3_createargs
674 #define nfsd3_readdirplusargs           nfsd3_readdirargs
675 #define nfsd3_fhandleargs               nfsd_fhandle
676 #define nfsd3_attrstatres               nfsd3_attrstat
677 #define nfsd3_wccstatres                nfsd3_attrstat
678 #define nfsd3_createres                 nfsd3_diropres
679
680 #define ST 1            /* status*/
681 #define FH 17           /* filehandle with length */
682 #define AT 21           /* attributes */
683 #define pAT (1+AT)      /* post attributes - conditional */
684 #define WC (7+pAT)      /* WCC attributes */
685
686 static const struct svc_procedure nfsd_procedures3[22] = {
687         [NFS3PROC_NULL] = {
688                 .pc_func = nfsd3_proc_null,
689                 .pc_decode = nfssvc_decode_voidarg,
690                 .pc_encode = nfssvc_encode_voidres,
691                 .pc_argsize = sizeof(struct nfsd_voidargs),
692                 .pc_ressize = sizeof(struct nfsd_voidres),
693                 .pc_cachetype = RC_NOCACHE,
694                 .pc_xdrressize = ST,
695                 .pc_name = "NULL",
696         },
697         [NFS3PROC_GETATTR] = {
698                 .pc_func = nfsd3_proc_getattr,
699                 .pc_decode = nfs3svc_decode_fhandleargs,
700                 .pc_encode = nfs3svc_encode_getattrres,
701                 .pc_release = nfs3svc_release_fhandle,
702                 .pc_argsize = sizeof(struct nfsd_fhandle),
703                 .pc_ressize = sizeof(struct nfsd3_attrstatres),
704                 .pc_cachetype = RC_NOCACHE,
705                 .pc_xdrressize = ST+AT,
706                 .pc_name = "GETATTR",
707         },
708         [NFS3PROC_SETATTR] = {
709                 .pc_func = nfsd3_proc_setattr,
710                 .pc_decode = nfs3svc_decode_sattrargs,
711                 .pc_encode = nfs3svc_encode_wccstatres,
712                 .pc_release = nfs3svc_release_fhandle,
713                 .pc_argsize = sizeof(struct nfsd3_sattrargs),
714                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
715                 .pc_cachetype = RC_REPLBUFF,
716                 .pc_xdrressize = ST+WC,
717                 .pc_name = "SETATTR",
718         },
719         [NFS3PROC_LOOKUP] = {
720                 .pc_func = nfsd3_proc_lookup,
721                 .pc_decode = nfs3svc_decode_diropargs,
722                 .pc_encode = nfs3svc_encode_lookupres,
723                 .pc_release = nfs3svc_release_fhandle2,
724                 .pc_argsize = sizeof(struct nfsd3_diropargs),
725                 .pc_ressize = sizeof(struct nfsd3_diropres),
726                 .pc_cachetype = RC_NOCACHE,
727                 .pc_xdrressize = ST+FH+pAT+pAT,
728                 .pc_name = "LOOKUP",
729         },
730         [NFS3PROC_ACCESS] = {
731                 .pc_func = nfsd3_proc_access,
732                 .pc_decode = nfs3svc_decode_accessargs,
733                 .pc_encode = nfs3svc_encode_accessres,
734                 .pc_release = nfs3svc_release_fhandle,
735                 .pc_argsize = sizeof(struct nfsd3_accessargs),
736                 .pc_ressize = sizeof(struct nfsd3_accessres),
737                 .pc_cachetype = RC_NOCACHE,
738                 .pc_xdrressize = ST+pAT+1,
739                 .pc_name = "ACCESS",
740         },
741         [NFS3PROC_READLINK] = {
742                 .pc_func = nfsd3_proc_readlink,
743                 .pc_decode = nfs3svc_decode_fhandleargs,
744                 .pc_encode = nfs3svc_encode_readlinkres,
745                 .pc_release = nfs3svc_release_fhandle,
746                 .pc_argsize = sizeof(struct nfsd_fhandle),
747                 .pc_ressize = sizeof(struct nfsd3_readlinkres),
748                 .pc_cachetype = RC_NOCACHE,
749                 .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
750                 .pc_name = "READLINK",
751         },
752         [NFS3PROC_READ] = {
753                 .pc_func = nfsd3_proc_read,
754                 .pc_decode = nfs3svc_decode_readargs,
755                 .pc_encode = nfs3svc_encode_readres,
756                 .pc_release = nfs3svc_release_fhandle,
757                 .pc_argsize = sizeof(struct nfsd3_readargs),
758                 .pc_ressize = sizeof(struct nfsd3_readres),
759                 .pc_cachetype = RC_NOCACHE,
760                 .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
761                 .pc_name = "READ",
762         },
763         [NFS3PROC_WRITE] = {
764                 .pc_func = nfsd3_proc_write,
765                 .pc_decode = nfs3svc_decode_writeargs,
766                 .pc_encode = nfs3svc_encode_writeres,
767                 .pc_release = nfs3svc_release_fhandle,
768                 .pc_argsize = sizeof(struct nfsd3_writeargs),
769                 .pc_ressize = sizeof(struct nfsd3_writeres),
770                 .pc_cachetype = RC_REPLBUFF,
771                 .pc_xdrressize = ST+WC+4,
772                 .pc_name = "WRITE",
773         },
774         [NFS3PROC_CREATE] = {
775                 .pc_func = nfsd3_proc_create,
776                 .pc_decode = nfs3svc_decode_createargs,
777                 .pc_encode = nfs3svc_encode_createres,
778                 .pc_release = nfs3svc_release_fhandle2,
779                 .pc_argsize = sizeof(struct nfsd3_createargs),
780                 .pc_ressize = sizeof(struct nfsd3_createres),
781                 .pc_cachetype = RC_REPLBUFF,
782                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
783                 .pc_name = "CREATE",
784         },
785         [NFS3PROC_MKDIR] = {
786                 .pc_func = nfsd3_proc_mkdir,
787                 .pc_decode = nfs3svc_decode_mkdirargs,
788                 .pc_encode = nfs3svc_encode_createres,
789                 .pc_release = nfs3svc_release_fhandle2,
790                 .pc_argsize = sizeof(struct nfsd3_mkdirargs),
791                 .pc_ressize = sizeof(struct nfsd3_createres),
792                 .pc_cachetype = RC_REPLBUFF,
793                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
794                 .pc_name = "MKDIR",
795         },
796         [NFS3PROC_SYMLINK] = {
797                 .pc_func = nfsd3_proc_symlink,
798                 .pc_decode = nfs3svc_decode_symlinkargs,
799                 .pc_encode = nfs3svc_encode_createres,
800                 .pc_release = nfs3svc_release_fhandle2,
801                 .pc_argsize = sizeof(struct nfsd3_symlinkargs),
802                 .pc_ressize = sizeof(struct nfsd3_createres),
803                 .pc_cachetype = RC_REPLBUFF,
804                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
805                 .pc_name = "SYMLINK",
806         },
807         [NFS3PROC_MKNOD] = {
808                 .pc_func = nfsd3_proc_mknod,
809                 .pc_decode = nfs3svc_decode_mknodargs,
810                 .pc_encode = nfs3svc_encode_createres,
811                 .pc_release = nfs3svc_release_fhandle2,
812                 .pc_argsize = sizeof(struct nfsd3_mknodargs),
813                 .pc_ressize = sizeof(struct nfsd3_createres),
814                 .pc_cachetype = RC_REPLBUFF,
815                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
816                 .pc_name = "MKNOD",
817         },
818         [NFS3PROC_REMOVE] = {
819                 .pc_func = nfsd3_proc_remove,
820                 .pc_decode = nfs3svc_decode_diropargs,
821                 .pc_encode = nfs3svc_encode_wccstatres,
822                 .pc_release = nfs3svc_release_fhandle,
823                 .pc_argsize = sizeof(struct nfsd3_diropargs),
824                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
825                 .pc_cachetype = RC_REPLBUFF,
826                 .pc_xdrressize = ST+WC,
827                 .pc_name = "REMOVE",
828         },
829         [NFS3PROC_RMDIR] = {
830                 .pc_func = nfsd3_proc_rmdir,
831                 .pc_decode = nfs3svc_decode_diropargs,
832                 .pc_encode = nfs3svc_encode_wccstatres,
833                 .pc_release = nfs3svc_release_fhandle,
834                 .pc_argsize = sizeof(struct nfsd3_diropargs),
835                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
836                 .pc_cachetype = RC_REPLBUFF,
837                 .pc_xdrressize = ST+WC,
838                 .pc_name = "RMDIR",
839         },
840         [NFS3PROC_RENAME] = {
841                 .pc_func = nfsd3_proc_rename,
842                 .pc_decode = nfs3svc_decode_renameargs,
843                 .pc_encode = nfs3svc_encode_renameres,
844                 .pc_release = nfs3svc_release_fhandle2,
845                 .pc_argsize = sizeof(struct nfsd3_renameargs),
846                 .pc_ressize = sizeof(struct nfsd3_renameres),
847                 .pc_cachetype = RC_REPLBUFF,
848                 .pc_xdrressize = ST+WC+WC,
849                 .pc_name = "RENAME",
850         },
851         [NFS3PROC_LINK] = {
852                 .pc_func = nfsd3_proc_link,
853                 .pc_decode = nfs3svc_decode_linkargs,
854                 .pc_encode = nfs3svc_encode_linkres,
855                 .pc_release = nfs3svc_release_fhandle2,
856                 .pc_argsize = sizeof(struct nfsd3_linkargs),
857                 .pc_ressize = sizeof(struct nfsd3_linkres),
858                 .pc_cachetype = RC_REPLBUFF,
859                 .pc_xdrressize = ST+pAT+WC,
860                 .pc_name = "LINK",
861         },
862         [NFS3PROC_READDIR] = {
863                 .pc_func = nfsd3_proc_readdir,
864                 .pc_decode = nfs3svc_decode_readdirargs,
865                 .pc_encode = nfs3svc_encode_readdirres,
866                 .pc_release = nfs3svc_release_fhandle,
867                 .pc_argsize = sizeof(struct nfsd3_readdirargs),
868                 .pc_ressize = sizeof(struct nfsd3_readdirres),
869                 .pc_cachetype = RC_NOCACHE,
870                 .pc_name = "READDIR",
871         },
872         [NFS3PROC_READDIRPLUS] = {
873                 .pc_func = nfsd3_proc_readdirplus,
874                 .pc_decode = nfs3svc_decode_readdirplusargs,
875                 .pc_encode = nfs3svc_encode_readdirres,
876                 .pc_release = nfs3svc_release_fhandle,
877                 .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
878                 .pc_ressize = sizeof(struct nfsd3_readdirres),
879                 .pc_cachetype = RC_NOCACHE,
880                 .pc_name = "READDIRPLUS",
881         },
882         [NFS3PROC_FSSTAT] = {
883                 .pc_func = nfsd3_proc_fsstat,
884                 .pc_decode = nfs3svc_decode_fhandleargs,
885                 .pc_encode = nfs3svc_encode_fsstatres,
886                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
887                 .pc_ressize = sizeof(struct nfsd3_fsstatres),
888                 .pc_cachetype = RC_NOCACHE,
889                 .pc_xdrressize = ST+pAT+2*6+1,
890                 .pc_name = "FSSTAT",
891         },
892         [NFS3PROC_FSINFO] = {
893                 .pc_func = nfsd3_proc_fsinfo,
894                 .pc_decode = nfs3svc_decode_fhandleargs,
895                 .pc_encode = nfs3svc_encode_fsinfores,
896                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
897                 .pc_ressize = sizeof(struct nfsd3_fsinfores),
898                 .pc_cachetype = RC_NOCACHE,
899                 .pc_xdrressize = ST+pAT+12,
900                 .pc_name = "FSINFO",
901         },
902         [NFS3PROC_PATHCONF] = {
903                 .pc_func = nfsd3_proc_pathconf,
904                 .pc_decode = nfs3svc_decode_fhandleargs,
905                 .pc_encode = nfs3svc_encode_pathconfres,
906                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
907                 .pc_ressize = sizeof(struct nfsd3_pathconfres),
908                 .pc_cachetype = RC_NOCACHE,
909                 .pc_xdrressize = ST+pAT+6,
910                 .pc_name = "PATHCONF",
911         },
912         [NFS3PROC_COMMIT] = {
913                 .pc_func = nfsd3_proc_commit,
914                 .pc_decode = nfs3svc_decode_commitargs,
915                 .pc_encode = nfs3svc_encode_commitres,
916                 .pc_release = nfs3svc_release_fhandle,
917                 .pc_argsize = sizeof(struct nfsd3_commitargs),
918                 .pc_ressize = sizeof(struct nfsd3_commitres),
919                 .pc_cachetype = RC_NOCACHE,
920                 .pc_xdrressize = ST+WC+2,
921                 .pc_name = "COMMIT",
922         },
923 };
924
925 static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures3)];
926 const struct svc_version nfsd_version3 = {
927         .vs_vers        = 3,
928         .vs_nproc       = 22,
929         .vs_proc        = nfsd_procedures3,
930         .vs_dispatch    = nfsd_dispatch,
931         .vs_count       = nfsd_count3,
932         .vs_xdrsize     = NFS3_SVC_XDRSIZE,
933 };
This page took 0.084502 seconds and 4 git commands to generate.