patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / nfsd / nfs4proc.c
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
56 #define NFSDDBG_FACILITY                NFSDDBG_PROC
57
58 static inline void
59 fh_dup2(struct svc_fh *dst, struct svc_fh *src)
60 {
61         fh_put(dst);
62         dget(src->fh_dentry);
63         if (src->fh_export)
64                 cache_get(&src->fh_export->h);
65         *dst = *src;
66 }
67
68 static int
69 do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
70 {
71         int accmode, status;
72
73         if (open->op_truncate &&
74                 !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
75                 return nfserr_inval;
76
77         accmode = MAY_NOP;
78         if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
79                 accmode = MAY_READ;
80         if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE)
81                 accmode |= (MAY_WRITE | MAY_TRUNC);
82         accmode |= MAY_OWNER_OVERRIDE;
83
84         status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
85
86         return status;
87 }
88
89 static int
90 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
91 {
92         struct svc_fh resfh;
93         int status;
94
95         fh_init(&resfh, NFS4_FHSIZE);
96         open->op_truncate = 0;
97
98         if (open->op_create) {
99                 /*
100                  * Note: create modes (UNCHECKED,GUARDED...) are the same
101                  * in NFSv4 as in v3.
102                  */
103                 status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
104                                         open->op_fname.len, &open->op_iattr,
105                                         &resfh, open->op_createmode,
106                                         (u32 *)open->op_verf.data, &open->op_truncate);
107         }
108         else {
109                 status = nfsd_lookup(rqstp, current_fh,
110                                      open->op_fname.data, open->op_fname.len, &resfh);
111                 fh_unlock(current_fh);
112         }
113
114         if (!status) {
115                 set_change_info(&open->op_cinfo, current_fh);
116
117                 /* set reply cache */
118                 fh_dup2(current_fh, &resfh);
119                 /* XXXJBF: keep a saved svc_fh struct instead?? */
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
133 static int
134 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
135 {
136         int status;
137
138         dprintk("NFSD: do_open_fhandle\n");
139
140         /* we don't know the target directory, and therefore can not
141         * set the change info
142         */
143
144         memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
145
146         /* set replay cache */
147         open->op_stateowner->so_replay.rp_openfh_len = current_fh->fh_handle.fh_size;
148         memcpy(open->op_stateowner->so_replay.rp_openfh,
149                 &current_fh->fh_handle.fh_base,
150                 current_fh->fh_handle.fh_size);
151
152         open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
153         !open->op_iattr.ia_size;
154
155         status = do_open_permission(rqstp, current_fh, open);
156
157         return status;
158 }
159
160
161 /*
162  * nfs4_unlock_state() called in encode
163  */
164 static inline int
165 nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
166 {
167         int status;
168         dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
169                 (int)open->op_fname.len, open->op_fname.data,
170                 open->op_stateowner);
171
172         if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
173                 return nfserr_grace;
174
175         if (nfs4_in_no_grace() &&
176                            open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
177                 return nfserr_no_grace;
178
179         /* This check required by spec. */
180         if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
181                 return nfserr_inval;
182
183         open->op_stateowner = NULL;
184         nfs4_lock_state();
185
186         /* check seqid for replay. set nfs4_owner */
187         status = nfsd4_process_open1(open);
188         if (status == NFSERR_REPLAY_ME) {
189                 struct nfs4_replay *rp = &open->op_stateowner->so_replay;
190                 fh_put(current_fh);
191                 current_fh->fh_handle.fh_size = rp->rp_openfh_len;
192                 memcpy(&current_fh->fh_handle.fh_base, rp->rp_openfh,
193                                 rp->rp_openfh_len);
194                 status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
195                 if (status)
196                         dprintk("nfsd4_open: replay failed"
197                                 " restoring previous filehandle\n");
198                 else
199                         status = NFSERR_REPLAY_ME;
200         }
201         if (status)
202                 return status;
203         if (open->op_claim_type == NFS4_OPEN_CLAIM_NULL) {
204         /*
205          * This block of code will (1) set CURRENT_FH to the file being opened,
206          * creating it if necessary, (2) set open->op_cinfo, 
207          * (3) set open->op_truncate if the file is to be truncated 
208          * after opening, (4) do permission checking.
209          */
210                 status = do_open_lookup(rqstp, current_fh, open);
211                 if (status)
212                         return status;
213         } else if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
214         /*
215         * The CURRENT_FH is already set to the file being opened. This
216         * block of code will (1) set open->op_cinfo, (2) set
217         * open->op_truncate if the file is to be truncated after opening,
218         * (3) do permission checking.
219         */
220                 status = do_open_fhandle(rqstp, current_fh, open);
221                 if (status)
222                         return status;
223         } else {
224                 printk("NFSD: unsupported OPEN claim type\n");
225                 return nfserr_inval;
226         }
227         /*
228          * nfsd4_process_open2() does the actual opening of the file.  If
229          * successful, it (1) truncates the file if open->op_truncate was
230          * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
231          */
232         status = nfsd4_process_open2(rqstp, current_fh, open);
233         if (status)
234                 return status;
235         return 0;
236 }
237
238 /*
239  * filehandle-manipulating ops.
240  */
241 static inline int
242 nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh)
243 {
244         if (!current_fh->fh_dentry)
245                 return nfserr_nofilehandle;
246
247         *getfh = current_fh;
248         return nfs_ok;
249 }
250
251 static inline int
252 nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh)
253 {
254         fh_put(current_fh);
255         current_fh->fh_handle.fh_size = putfh->pf_fhlen;
256         memcpy(&current_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen);
257         return fh_verify(rqstp, current_fh, 0, MAY_NOP);
258 }
259
260 static inline int
261 nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
262 {
263         int status;
264
265         fh_put(current_fh);
266         status = exp_pseudoroot(rqstp->rq_client, current_fh,
267                               &rqstp->rq_chandle);
268         if (!status)
269                 status = nfsd_setuser(rqstp, current_fh->fh_export);
270         return status;
271 }
272
273 static inline int
274 nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
275 {
276         if (!save_fh->fh_dentry)
277                 return nfserr_restorefh;
278
279         fh_dup2(current_fh, save_fh);
280         return nfs_ok;
281 }
282
283 static inline int
284 nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
285 {
286         if (!current_fh->fh_dentry)
287                 return nfserr_nofilehandle;
288
289         fh_dup2(save_fh, current_fh);
290         return nfs_ok;
291 }
292
293 /*
294  * misc nfsv4 ops
295  */
296 static inline int
297 nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access)
298 {
299         if (access->ac_req_access & ~NFS3_ACCESS_FULL)
300                 return nfserr_inval;
301
302         access->ac_resp_access = access->ac_req_access;
303         return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported);
304 }
305
306 static inline int
307 nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
308 {
309         int status;
310
311         u32 *p = (u32 *)commit->co_verf.data;
312         *p++ = nfssvc_boot.tv_sec;
313         *p++ = nfssvc_boot.tv_usec;
314
315         status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
316         if (status == nfserr_symlink)
317                 status = nfserr_inval;
318         return status;
319 }
320
321 static inline int
322 nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
323 {
324         struct svc_fh resfh;
325         int status;
326         dev_t rdev;
327
328         fh_init(&resfh, NFS4_FHSIZE);
329
330         status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE);
331         if (status == nfserr_symlink)
332                 status = nfserr_notdir;
333         if (status)
334                 return status;
335
336         switch (create->cr_type) {
337         case NF4LNK:
338                 /* ugh! we have to null-terminate the linktext, or
339                  * vfs_symlink() will choke.  it is always safe to
340                  * null-terminate by brute force, since at worst we
341                  * will overwrite the first byte of the create namelen
342                  * in the XDR buffer, which has already been extracted
343                  * during XDR decode.
344                  */
345                 create->cr_linkname[create->cr_linklen] = 0;
346
347                 status = nfsd_symlink(rqstp, current_fh, create->cr_name,
348                                       create->cr_namelen, create->cr_linkname,
349                                       create->cr_linklen, &resfh, &create->cr_iattr);
350                 break;
351
352         case NF4BLK:
353                 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
354                 if (MAJOR(rdev) != create->cr_specdata1 ||
355                     MINOR(rdev) != create->cr_specdata2)
356                         return nfserr_inval;
357                 status = nfsd_create(rqstp, current_fh, create->cr_name,
358                                      create->cr_namelen, &create->cr_iattr,
359                                      S_IFBLK, rdev, &resfh);
360                 break;
361
362         case NF4CHR:
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_IFCHR, rdev, &resfh);
370                 break;
371
372         case NF4SOCK:
373                 status = nfsd_create(rqstp, current_fh, create->cr_name,
374                                      create->cr_namelen, &create->cr_iattr,
375                                      S_IFSOCK, 0, &resfh);
376                 break;
377
378         case NF4FIFO:
379                 status = nfsd_create(rqstp, current_fh, create->cr_name,
380                                      create->cr_namelen, &create->cr_iattr,
381                                      S_IFIFO, 0, &resfh);
382                 break;
383
384         case NF4DIR:
385                 create->cr_iattr.ia_valid &= ~ATTR_SIZE;
386                 status = nfsd_create(rqstp, current_fh, create->cr_name,
387                                      create->cr_namelen, &create->cr_iattr,
388                                      S_IFDIR, 0, &resfh);
389                 break;
390
391         default:
392                 status = nfserr_badtype;
393         }
394
395         if (!status) {
396                 fh_unlock(current_fh);
397                 set_change_info(&create->cr_cinfo, current_fh);
398                 fh_dup2(current_fh, &resfh);
399         }
400
401         fh_put(&resfh);
402         return status;
403 }
404
405 static inline int
406 nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr)
407 {
408         int status;
409
410         status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
411         if (status)
412                 return status;
413
414         if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
415                 return nfserr_inval;
416
417         getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
418         getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
419
420         getattr->ga_fhp = current_fh;
421         return nfs_ok;
422 }
423
424 static inline int
425 nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
426            struct svc_fh *save_fh, struct nfsd4_link *link)
427 {
428         int status = nfserr_nofilehandle;
429
430         if (!save_fh->fh_dentry)
431                 return status;
432         status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
433         if (!status)
434                 set_change_info(&link->li_cinfo, current_fh);
435         return status;
436 }
437
438 static inline int
439 nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
440 {
441         struct svc_fh tmp_fh;
442         int ret;
443
444         fh_init(&tmp_fh, NFS4_FHSIZE);
445         if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
446                               &rqstp->rq_chandle)) != 0)
447                 return ret;
448         if (tmp_fh.fh_dentry == current_fh->fh_dentry) {
449                 fh_put(&tmp_fh);
450                 return nfserr_noent;
451         }
452         fh_put(&tmp_fh);
453         return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
454 }
455
456 static inline int
457 nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup)
458 {
459         return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
460 }
461
462 static inline int
463 access_bits_permit_read(unsigned long access_bmap)
464 {
465         return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
466                 test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
467 }
468
469 static inline int
470 access_bits_permit_write(unsigned long access_bmap)
471 {
472         return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) ||
473                 test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
474 }
475
476 static inline int
477 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
478 {
479         struct nfs4_stateid *stp;
480         int status;
481
482         /* no need to check permission - this will be done in nfsd_read() */
483         if (nfs4_in_grace())
484                 return nfserr_grace;
485
486         if (read->rd_offset >= OFFSET_MAX)
487                 return nfserr_inval;
488
489         nfs4_lock_state();
490         status = nfs_ok;
491         /* For stateid -1, we don't check share reservations.  */
492         if (ONE_STATEID(&read->rd_stateid)) {
493                 dprintk("NFSD: nfsd4_read: -1 stateid...\n");
494                 goto out;
495         }
496         /*
497         * For stateid 0, the client doesn't have to have the file open, but
498         * we still check for share reservation conflicts. 
499         */
500         if (ZERO_STATEID(&read->rd_stateid)) {
501                 dprintk("NFSD: nfsd4_read: zero stateid...\n");
502                 if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_READ))) {
503                         dprintk("NFSD: nfsd4_read: conflicting share reservation!\n");
504                         goto out;
505                 }
506                 status = nfs_ok;
507                 goto out;
508         }
509         /* check stateid */
510         if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 
511                                         CHECK_FH | RDWR_STATE, &stp))) {
512                 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
513                 goto out;
514         }
515         status = nfserr_openmode;
516         if (!access_bits_permit_read(stp->st_access_bmap)) {
517                 dprintk("NFSD: nfsd4_read: file not opened for read!\n");
518                 goto out;
519         }
520         status = nfs_ok;
521 out:
522         nfs4_unlock_state();
523         read->rd_rqstp = rqstp;
524         read->rd_fhp = current_fh;
525         return status;
526 }
527
528 static inline int
529 nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
530 {
531         u64 cookie = readdir->rd_cookie;
532         static const nfs4_verifier zeroverf;
533
534         /* no need to check permission - this will be done in nfsd_readdir() */
535
536         if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
537                 return nfserr_inval;
538
539         readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
540         readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
541
542         if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
543             (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
544                 return nfserr_bad_cookie;
545
546         readdir->rd_rqstp = rqstp;
547         readdir->rd_fhp = current_fh;
548         return nfs_ok;
549 }
550
551 static inline int
552 nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink)
553 {
554         readlink->rl_rqstp = rqstp;
555         readlink->rl_fhp = current_fh;
556         return nfs_ok;
557 }
558
559 static inline int
560 nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove)
561 {
562         int status;
563
564         status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
565         if (status == nfserr_symlink)
566                 return nfserr_notdir;
567         if (!status) {
568                 fh_unlock(current_fh);
569                 set_change_info(&remove->rm_cinfo, current_fh);
570         }
571         return status;
572 }
573
574 static inline int
575 nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
576              struct svc_fh *save_fh, struct nfsd4_rename *rename)
577 {
578         int status = nfserr_nofilehandle;
579
580         if (!save_fh->fh_dentry)
581                 return status;
582         status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
583                              rename->rn_snamelen, current_fh,
584                              rename->rn_tname, rename->rn_tnamelen);
585
586         /* the underlying filesystem returns different error's than required
587          * by NFSv4. both save_fh and current_fh have been verified.. */
588         if (status == nfserr_isdir)
589                 status = nfserr_exist;
590         else if ((status == nfserr_notdir) &&
591                   (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) &&
592                    S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
593                 status = nfserr_exist;
594         else if (status == nfserr_symlink)
595                 status = nfserr_notdir;
596
597         if (!status) {
598                 set_change_info(&rename->rn_sinfo, current_fh);
599                 set_change_info(&rename->rn_tinfo, save_fh);
600         }
601         return status;
602 }
603
604 static inline int
605 nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
606 {
607         struct nfs4_stateid *stp;
608         int status = nfs_ok;
609
610         if (nfs4_in_grace())
611                 return nfserr_grace;
612
613         if (!current_fh->fh_dentry)
614                 return nfserr_nofilehandle;
615
616         status = nfs_ok;
617         if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
618
619                 status = nfserr_bad_stateid;
620                 if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
621                         dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
622                         return status;
623                 }
624
625                 nfs4_lock_state();
626                 if ((status = nfs4_preprocess_stateid_op(current_fh, 
627                                                 &setattr->sa_stateid, 
628                                                 CHECK_FH | RDWR_STATE, &stp))) {
629                         dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
630                         goto out;
631                 }
632                 status = nfserr_openmode;
633                 if (!access_bits_permit_write(stp->st_access_bmap)) {
634                         dprintk("NFSD: nfsd4_setattr: not opened for write!\n");
635                         goto out;
636                 }
637                 nfs4_unlock_state();
638         }
639         return (nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0));
640 out:
641         nfs4_unlock_state();
642         return status;
643 }
644
645 static inline int
646 nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
647 {
648         struct nfs4_stateid *stp;
649         stateid_t *stateid = &write->wr_stateid;
650         u32 *p;
651         int status = nfs_ok;
652
653         if (nfs4_in_grace())
654                 return nfserr_grace;
655
656         /* no need to check permission - this will be done in nfsd_write() */
657
658         if (write->wr_offset >= OFFSET_MAX)
659                 return nfserr_inval;
660
661         nfs4_lock_state();
662         if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
663                 dprintk("NFSD: nfsd4_write: zero stateid...\n");
664                 if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE))) {
665                         dprintk("NFSD: nfsd4_write: conflicting share reservation!\n");
666                         goto out;
667                 }
668                 goto zero_stateid;
669         }
670         if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, 
671                                         CHECK_FH | RDWR_STATE, &stp))) {
672                 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
673                 goto out;
674         }
675
676         status = nfserr_openmode;
677         if (!access_bits_permit_write(stp->st_access_bmap)) {
678                 dprintk("NFSD: nfsd4_write: file not open for write!\n");
679                 goto out;
680         }
681
682 zero_stateid:
683         nfs4_unlock_state();
684         write->wr_bytes_written = write->wr_buflen;
685         write->wr_how_written = write->wr_stable_how;
686         p = (u32 *)write->wr_verifier.data;
687         *p++ = nfssvc_boot.tv_sec;
688         *p++ = nfssvc_boot.tv_usec;
689
690         status =  nfsd_write(rqstp, current_fh, write->wr_offset,
691                           write->wr_vec, write->wr_vlen, write->wr_buflen,
692                           &write->wr_how_written);
693         if (status == nfserr_symlink)
694                 status = nfserr_inval;
695         return status;
696 out:
697         nfs4_unlock_state();
698         return status;
699 }
700
701 /* This routine never returns NFS_OK!  If there are no other errors, it
702  * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the
703  * attributes matched.  VERIFY is implemented by mapping NFSERR_SAME
704  * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
705  */
706 static int
707 nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify)
708 {
709         u32 *buf, *p;
710         int count;
711         int status;
712
713         status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
714         if (status)
715                 return status;
716
717         if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)
718             || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
719                 return nfserr_attrnotsupp;
720         if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
721             || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
722                 return nfserr_inval;
723         if (verify->ve_attrlen & 3)
724                 return nfserr_inval;
725
726         /* count in words:
727          *   bitmap_len(1) + bitmap(2) + attr_len(1) = 4
728          */
729         count = 4 + (verify->ve_attrlen >> 2);
730         buf = kmalloc(count << 2, GFP_KERNEL);
731         if (!buf)
732                 return nfserr_resource;
733
734         status = nfsd4_encode_fattr(current_fh, current_fh->fh_export,
735                                     current_fh->fh_dentry, buf,
736                                     &count, verify->ve_bmval,
737                                     rqstp);
738
739         /* this means that nfsd4_encode_fattr() ran out of space */
740         if (status == nfserr_resource && count == 0)
741                 status = nfserr_not_same;
742         if (status)
743                 goto out_kfree;
744
745         p = buf + 3;
746         status = nfserr_not_same;
747         if (ntohl(*p++) != verify->ve_attrlen)
748                 goto out_kfree;
749         if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen))
750                 status = nfserr_same;
751
752 out_kfree:
753         kfree(buf);
754         return status;
755 }
756
757 /*
758  * NULL call.
759  */
760 static int
761 nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
762 {
763         return nfs_ok;
764 }
765
766
767 /*
768  * COMPOUND call.
769  */
770 static int
771 nfsd4_proc_compound(struct svc_rqst *rqstp,
772                     struct nfsd4_compoundargs *args,
773                     struct nfsd4_compoundres *resp)
774 {
775         struct nfsd4_op *op;
776         struct svc_fh   current_fh;
777         struct svc_fh   save_fh;
778         int             slack_space;    /* in words, not bytes! */
779         int             status;
780
781         fh_init(&current_fh, NFS4_FHSIZE);
782         fh_init(&save_fh, NFS4_FHSIZE);
783
784         resp->xbuf = &rqstp->rq_res;
785         resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
786         resp->tagp = resp->p;
787         /* reserve space for: taglen, tag, and opcnt */
788         resp->p += 2 + XDR_QUADLEN(args->taglen);
789         resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
790         resp->taglen = args->taglen;
791         resp->tag = args->tag;
792         resp->opcnt = 0;
793         resp->rqstp = rqstp;
794
795         /*
796          * According to RFC3010, this takes precedence over all other errors.
797          */
798         status = nfserr_minor_vers_mismatch;
799         if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
800                 goto out;
801
802         status = nfs_ok;
803         while (!status && resp->opcnt < args->opcnt) {
804                 op = &args->ops[resp->opcnt++];
805
806                 /*
807                  * The XDR decode routines may have pre-set op->status;
808                  * for example, if there is a miscellaneous XDR error
809                  * it will be set to nfserr_bad_xdr.
810                  */
811                 if (op->status)
812                         goto encode_op;
813
814                 /* We must be able to encode a successful response to
815                  * this operation, with enough room left over to encode a
816                  * failed response to the next operation.  If we don't
817                  * have enough room, fail with ERR_RESOURCE.
818                  */
819 /* FIXME - is slack_space *really* words, or bytes??? - neilb */
820                 slack_space = (char *)resp->end - (char *)resp->p;
821                 if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) {
822                         BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE);
823                         op->status = nfserr_resource;
824                         goto encode_op;
825                 }
826
827                 /* All operations except RENEW, SETCLIENTID, RESTOREFH
828                 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
829                 * require a valid current filehandle
830                 *
831                 * SETATTR NOFILEHANDLE error handled in nfsd4_setattr
832                 * due to required returned bitmap argument
833                 */
834                 if ((!current_fh.fh_dentry) &&
835                    !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
836                    (op->opnum == OP_SETCLIENTID) ||
837                    (op->opnum == OP_SETCLIENTID_CONFIRM) ||
838                    (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
839                    (op->opnum == OP_RELEASE_LOCKOWNER) ||
840                    (op->opnum == OP_SETATTR))) {
841                         op->status = nfserr_nofilehandle;
842                         goto encode_op;
843                 }
844                 switch (op->opnum) {
845                 case OP_ACCESS:
846                         op->status = nfsd4_access(rqstp, &current_fh, &op->u.access);
847                         break;
848                 case OP_CLOSE:
849                         op->status = nfsd4_close(rqstp, &current_fh, &op->u.close);
850                         if (op->u.close.cl_stateowner)
851                                 op->replay =
852                                         &op->u.close.cl_stateowner->so_replay;
853                         break;
854                 case OP_COMMIT:
855                         op->status = nfsd4_commit(rqstp, &current_fh, &op->u.commit);
856                         break;
857                 case OP_CREATE:
858                         op->status = nfsd4_create(rqstp, &current_fh, &op->u.create);
859                         break;
860                 case OP_GETATTR:
861                         op->status = nfsd4_getattr(rqstp, &current_fh, &op->u.getattr);
862                         break;
863                 case OP_GETFH:
864                         op->status = nfsd4_getfh(&current_fh, &op->u.getfh);
865                         break;
866                 case OP_LINK:
867                         op->status = nfsd4_link(rqstp, &current_fh, &save_fh, &op->u.link);
868                         break;
869                 case OP_LOCK:
870                         op->status = nfsd4_lock(rqstp, &current_fh, &op->u.lock);
871                         if (op->u.lock.lk_stateowner)
872                                 op->replay =
873                                         &op->u.lock.lk_stateowner->so_replay;
874                         break;
875                 case OP_LOCKT:
876                         op->status = nfsd4_lockt(rqstp, &current_fh, &op->u.lockt);
877                         break;
878                 case OP_LOCKU:
879                         op->status = nfsd4_locku(rqstp, &current_fh, &op->u.locku);
880                         if (op->u.locku.lu_stateowner)
881                                 op->replay =
882                                         &op->u.locku.lu_stateowner->so_replay;
883                         break;
884                 case OP_LOOKUP:
885                         op->status = nfsd4_lookup(rqstp, &current_fh, &op->u.lookup);
886                         break;
887                 case OP_LOOKUPP:
888                         op->status = nfsd4_lookupp(rqstp, &current_fh);
889                         break;
890                 case OP_NVERIFY:
891                         op->status = nfsd4_verify(rqstp, &current_fh, &op->u.nverify);
892                         if (op->status == nfserr_not_same)
893                                 op->status = nfs_ok;
894                         break;
895                 case OP_OPEN:
896                         op->status = nfsd4_open(rqstp, &current_fh, &op->u.open);
897                         if (op->u.open.op_stateowner)
898                                 op->replay =
899                                         &op->u.open.op_stateowner->so_replay;
900                         break;
901                 case OP_OPEN_CONFIRM:
902                         op->status = nfsd4_open_confirm(rqstp, &current_fh, &op->u.open_confirm);
903                         if (op->u.open_confirm.oc_stateowner)
904                                 op->replay =
905                                         &op->u.open_confirm.oc_stateowner->so_replay;
906                         break;
907                 case OP_OPEN_DOWNGRADE:
908                         op->status = nfsd4_open_downgrade(rqstp, &current_fh, &op->u.open_downgrade);
909                         if (op->u.open_downgrade.od_stateowner)
910                                 op->replay =
911                                         &op->u.open_downgrade.od_stateowner->so_replay;
912                         break;
913                 case OP_PUTFH:
914                         op->status = nfsd4_putfh(rqstp, &current_fh, &op->u.putfh);
915                         break;
916                 case OP_PUTROOTFH:
917                         op->status = nfsd4_putrootfh(rqstp, &current_fh);
918                         break;
919                 case OP_READ:
920                         op->status = nfsd4_read(rqstp, &current_fh, &op->u.read);
921                         break;
922                 case OP_READDIR:
923                         op->status = nfsd4_readdir(rqstp, &current_fh, &op->u.readdir);
924                         break;
925                 case OP_READLINK:
926                         op->status = nfsd4_readlink(rqstp, &current_fh, &op->u.readlink);
927                         break;
928                 case OP_REMOVE:
929                         op->status = nfsd4_remove(rqstp, &current_fh, &op->u.remove);
930                         break;
931                 case OP_RENAME:
932                         op->status = nfsd4_rename(rqstp, &current_fh, &save_fh, &op->u.rename);
933                         break;
934                 case OP_RENEW:
935                         op->status = nfsd4_renew(&op->u.renew);
936                         break;
937                 case OP_RESTOREFH:
938                         op->status = nfsd4_restorefh(&current_fh, &save_fh);
939                         break;
940                 case OP_SAVEFH:
941                         op->status = nfsd4_savefh(&current_fh, &save_fh);
942                         break;
943                 case OP_SETATTR:
944                         op->status = nfsd4_setattr(rqstp, &current_fh, &op->u.setattr);
945                         break;
946                 case OP_SETCLIENTID:
947                         op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
948                         break;
949                 case OP_SETCLIENTID_CONFIRM:
950                         op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
951                         break;
952                 case OP_VERIFY:
953                         op->status = nfsd4_verify(rqstp, &current_fh, &op->u.verify);
954                         if (op->status == nfserr_same)
955                                 op->status = nfs_ok;
956                         break;
957                 case OP_WRITE:
958                         op->status = nfsd4_write(rqstp, &current_fh, &op->u.write);
959                         break;
960                 case OP_RELEASE_LOCKOWNER:
961                         op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
962                         break;
963                 default:
964                         BUG_ON(op->status == nfs_ok);
965                         break;
966                 }
967
968 encode_op:
969                 if (op->status == NFSERR_REPLAY_ME) {
970                         nfsd4_encode_replay(resp, op);
971                         status = op->status = op->replay->rp_status;
972                 } else {
973                         nfsd4_encode_operation(resp, op);
974                         status = op->status;
975                 }
976         }
977
978 out:
979         if (args->ops != args->iops) {
980                 kfree(args->ops);
981                 args->ops = args->iops;
982         }
983         if (args->tmpp) {
984                 kfree(args->tmpp);
985                 args->tmpp = NULL;
986         }
987         while (args->to_free) {
988                 struct tmpbuf *tb = args->to_free;
989                 args->to_free = tb->next;
990                 kfree(tb->buf);
991                 kfree(tb);
992         }
993         fh_put(&current_fh);
994         fh_put(&save_fh);
995         return status;
996 }
997
998 #define nfs4svc_decode_voidargs         NULL
999 #define nfs4svc_release_void            NULL
1000 #define nfsd4_voidres                   nfsd4_voidargs
1001 #define nfs4svc_release_compound        NULL
1002 struct nfsd4_voidargs { int dummy; };
1003
1004 #define PROC(name, argt, rest, relt, cache, respsize)   \
1005  { (svc_procfunc) nfsd4_proc_##name,            \
1006    (kxdrproc_t) nfs4svc_decode_##argt##args,    \
1007    (kxdrproc_t) nfs4svc_encode_##rest##res,     \
1008    (kxdrproc_t) nfs4svc_release_##relt,         \
1009    sizeof(struct nfsd4_##argt##args),           \
1010    sizeof(struct nfsd4_##rest##res),            \
1011    0,                                           \
1012    cache,                                       \
1013    respsize,                                    \
1014  }
1015
1016 /*
1017  * TODO: At the present time, the NFSv4 server does not do XID caching
1018  * of requests.  Implementing XID caching would not be a serious problem,
1019  * although it would require a mild change in interfaces since one
1020  * doesn't know whether an NFSv4 request is idempotent until after the
1021  * XDR decode.  However, XID caching totally confuses pynfs (Peter
1022  * Astrand's regression testsuite for NFSv4 servers), which reuses
1023  * XID's liberally, so I've left it unimplemented until pynfs generates
1024  * better XID's.
1025  */
1026 static struct svc_procedure             nfsd_procedures4[2] = {
1027   PROC(null,     void,          void,           void,     RC_NOCACHE, 1),
1028   PROC(compound, compound,      compound,       compound, RC_NOCACHE, NFSD_BUFSIZE)
1029 };
1030
1031 struct svc_version      nfsd_version4 = {
1032                 .vs_vers        = 4,
1033                 .vs_nproc       = 2,
1034                 .vs_proc        = nfsd_procedures4,
1035                 .vs_dispatch    = nfsd_dispatch,
1036                 .vs_xdrsize     = NFS4_SVC_XDRSIZE,
1037 };
1038
1039 /*
1040  * Local variables:
1041  *  c-basic-offset: 8
1042  * End:
1043  */