1 /*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
33 */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: releng/9.0/sys/nfsserver/nfs_serv.c 225356 2011-09-03 00:28:53Z rmacklem $");
37
38 /*
39 * nfs version 2 and 3 server calls to vnode ops
40 * - these routines generally have 3 phases
41 * 1 - break down and validate rpc request in mbuf list
42 * 2 - do the vnode ops for the request
43 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
44 * 3 - build the rpc reply in an mbuf list
45 * nb:
46 * - do not mix the phases, since the nfsm_?? macros can return failures
47 * on a bad rpc or similar and do not do any vrele() or vput()'s
48 *
49 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
50 * error number iff error != 0 whereas
51 * returning an error from the server function implies a fatal error
52 * such as a badly constructed rpc request that should be dropped without
53 * a reply.
54 * For nfsm_reply(), the case where error == EBADRPC is treated
55 * specially; after constructing a reply, it does an immediate
56 * `goto nfsmout' to avoid getting any V3 post-op status appended.
57 *
58 * Other notes:
59 * Warning: always pay careful attention to resource cleanup on return
60 * and note that nfsm_*() macros can terminate a procedure on certain
61 * errors.
62 *
63 * lookup() and namei()
64 * may return garbage in various structural fields/return elements
65 * if an error is returned, and may garbage up nd.ni_dvp even if no
66 * error is returned and you did not request LOCKPARENT or WANTPARENT.
67 *
68 * We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
69 * buffer has been freed or not.
70 */
71
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/proc.h>
75 #include <sys/namei.h>
76 #include <sys/unistd.h>
77 #include <sys/vnode.h>
78 #include <sys/mount.h>
79 #include <sys/socket.h>
80 #include <sys/socketvar.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/priv.h>
84 #include <sys/dirent.h>
85 #include <sys/stat.h>
86 #include <sys/kernel.h>
87 #include <sys/sysctl.h>
88 #include <sys/bio.h>
89 #include <sys/buf.h>
90
91 #include <vm/vm.h>
92 #include <vm/vm_extern.h>
93 #include <vm/vm_object.h>
94
95 #include <nfs/nfsproto.h>
96 #include <nfsserver/nfs.h>
97 #include <nfs/xdr_subs.h>
98 #include <nfsserver/nfsm_subs.h>
99
100 FEATURE(nfsserver, "NFS server");
101
102 #ifdef NFSRV_DEBUG
103 #define nfsdbprintf(info) printf info
104 #else
105 #define nfsdbprintf(info)
106 #endif
107
108 #define MAX_COMMIT_COUNT (1024 * 1024)
109
110 #define NUM_HEURISTIC 1017
111 #define NHUSE_INIT 64
112 #define NHUSE_INC 16
113 #define NHUSE_MAX 2048
114
115 static struct nfsheur {
116 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */
117 off_t nh_nextr; /* next offset for sequential detection */
118 int nh_use; /* use count for selection */
119 int nh_seqcount; /* heuristic */
120 } nfsheur[NUM_HEURISTIC];
121
122 /* Global vars */
123
124 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
125 int nfsrvw_procrastinate_v3 = 0;
126
127 static struct timeval nfsver = { 0 };
128
129 SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
130
131 static int nfs_async;
132 static int nfs_commit_blks;
133 static int nfs_commit_miss;
134 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
135 "Tell client that writes were synced even though they were not");
136 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0,
137 "Number of completed commits");
138 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
139
140 struct nfsrvstats nfsrvstats;
141 SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RW,
142 &nfsrvstats, nfsrvstats, "S,nfsrvstats");
143
144 static int nfsrv_access(struct vnode *, accmode_t, struct ucred *,
145 int, int);
146
147 /*
148 * Clear nameidata fields that are tested in nsfmout cleanup code prior
149 * to using first nfsm macro (that might jump to the cleanup code).
150 */
151
152 static __inline void
153 ndclear(struct nameidata *nd)
154 {
155
156 nd->ni_cnd.cn_flags = 0;
157 nd->ni_vp = NULL;
158 nd->ni_dvp = NULL;
159 nd->ni_startdir = NULL;
160 nd->ni_strictrelative = 0;
161 }
162
163 /*
164 * Takes two vfslocked integers and returns with at most one
165 * reference to giant. The return value indicates whether giant
166 * is held by either lock. This simplifies nfsrv ops by allowing
167 * them to track only one vfslocked var.
168 */
169 static __inline int
170 nfsrv_lockedpair(int vfs1, int vfs2)
171 {
172
173 if (vfs1 && vfs2)
174 VFS_UNLOCK_GIANT(vfs2);
175
176 return (vfs1 | vfs2);
177 }
178
179 static __inline int
180 nfsrv_lockedpair_nd(int vfs1, struct nameidata *nd)
181 {
182 int vfs2;
183
184 vfs2 = NDHASGIANT(nd);
185
186 return nfsrv_lockedpair(vfs1, vfs2);
187 }
188
189 /*
190 * nfs v3 access service
191 */
192 int
193 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
194 struct mbuf **mrq)
195 {
196 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
197 struct sockaddr *nam = nfsd->nd_nam;
198 caddr_t dpos = nfsd->nd_dpos;
199 struct ucred *cred = nfsd->nd_cr;
200 struct vnode *vp = NULL;
201 nfsfh_t nfh;
202 fhandle_t *fhp;
203 u_int32_t *tl;
204 caddr_t bpos;
205 int error = 0, rdonly, getret;
206 struct mbuf *mb, *mreq;
207 struct vattr vattr, *vap = &vattr;
208 u_long testmode, nfsmode;
209 int v3 = (nfsd->nd_flag & ND_NFSV3);
210 int vfslocked;
211
212 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
213 if (!v3)
214 panic("nfsrv3_access: v3 proc called on a v2 connection");
215 vfslocked = 0;
216 fhp = &nfh.fh_generic;
217 nfsm_srvmtofh(fhp);
218 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
219 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
220 if (error) {
221 nfsm_reply(NFSX_UNSIGNED);
222 nfsm_srvpostop_attr(1, NULL);
223 error = 0;
224 goto nfsmout;
225 }
226 nfsmode = fxdr_unsigned(u_int32_t, *tl);
227 if ((nfsmode & NFSV3ACCESS_READ) &&
228 nfsrv_access(vp, VREAD, cred, rdonly, 0))
229 nfsmode &= ~NFSV3ACCESS_READ;
230 if (vp->v_type == VDIR)
231 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
232 NFSV3ACCESS_DELETE);
233 else
234 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
235 if ((nfsmode & testmode) &&
236 nfsrv_access(vp, VWRITE, cred, rdonly, 0))
237 nfsmode &= ~testmode;
238 if (vp->v_type == VDIR)
239 testmode = NFSV3ACCESS_LOOKUP;
240 else
241 testmode = NFSV3ACCESS_EXECUTE;
242 if ((nfsmode & testmode) &&
243 nfsrv_access(vp, VEXEC, cred, rdonly, 0))
244 nfsmode &= ~testmode;
245 getret = VOP_GETATTR(vp, vap, cred);
246 vput(vp);
247 vp = NULL;
248 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
249 nfsm_srvpostop_attr(getret, vap);
250 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
251 *tl = txdr_unsigned(nfsmode);
252 nfsmout:
253 if (vp)
254 vput(vp);
255 VFS_UNLOCK_GIANT(vfslocked);
256 return(error);
257 }
258
259 /*
260 * nfs getattr service
261 */
262 int
263 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
264 struct mbuf **mrq)
265 {
266 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
267 struct sockaddr *nam = nfsd->nd_nam;
268 caddr_t dpos = nfsd->nd_dpos;
269 struct ucred *cred = nfsd->nd_cr;
270 struct nfs_fattr *fp;
271 struct vattr va;
272 struct vattr *vap = &va;
273 struct vnode *vp = NULL;
274 nfsfh_t nfh;
275 fhandle_t *fhp;
276 caddr_t bpos;
277 int error = 0, rdonly;
278 struct mbuf *mb, *mreq;
279 int vfslocked;
280
281 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
282 vfslocked = 0;
283 fhp = &nfh.fh_generic;
284 nfsm_srvmtofh(fhp);
285 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
286 if (error) {
287 nfsm_reply(0);
288 error = 0;
289 goto nfsmout;
290 }
291 error = VOP_GETATTR(vp, vap, cred);
292 vput(vp);
293 vp = NULL;
294 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
295 if (error) {
296 error = 0;
297 goto nfsmout;
298 }
299 fp = nfsm_build(struct nfs_fattr *,
300 NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
301 nfsm_srvfillattr(vap, fp);
302 /* fall through */
303
304 nfsmout:
305 if (vp)
306 vput(vp);
307 VFS_UNLOCK_GIANT(vfslocked);
308 return(error);
309 }
310
311 /*
312 * nfs setattr service
313 */
314 int
315 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
316 struct mbuf **mrq)
317 {
318 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
319 struct sockaddr *nam = nfsd->nd_nam;
320 caddr_t dpos = nfsd->nd_dpos;
321 struct ucred *cred = nfsd->nd_cr;
322 struct vattr va, preat;
323 struct vattr *vap = &va;
324 struct nfsv2_sattr *sp;
325 struct nfs_fattr *fp;
326 struct vnode *vp = NULL;
327 nfsfh_t nfh;
328 fhandle_t *fhp;
329 u_int32_t *tl;
330 caddr_t bpos;
331 int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
332 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
333 struct mbuf *mb, *mreq;
334 struct timespec guard = { 0, 0 };
335 struct mount *mp = NULL;
336 int tvfslocked;
337 int vfslocked;
338
339 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
340 vfslocked = 0;
341 fhp = &nfh.fh_generic;
342 nfsm_srvmtofh(fhp);
343 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
344 error = ESTALE;
345 goto out;
346 }
347 vfslocked = VFS_LOCK_GIANT(mp);
348 (void) vn_start_write(NULL, &mp, V_WAIT);
349 vfs_rel(mp); /* The write holds a ref. */
350 VATTR_NULL(vap);
351 if (v3) {
352 nfsm_srvsattr(vap);
353 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
354 gcheck = fxdr_unsigned(int, *tl);
355 if (gcheck) {
356 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
357 fxdr_nfsv3time(tl, &guard);
358 }
359 } else {
360 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
361 /*
362 * Nah nah nah nah na nah
363 * There is a bug in the Sun client that puts 0xffff in the mode
364 * field of sattr when it should put in 0xffffffff. The u_short
365 * doesn't sign extend.
366 * --> check the low order 2 bytes for 0xffff
367 */
368 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
369 vap->va_mode = nfstov_mode(sp->sa_mode);
370 if (sp->sa_uid != nfsrv_nfs_xdrneg1)
371 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
372 if (sp->sa_gid != nfsrv_nfs_xdrneg1)
373 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
374 if (sp->sa_size != nfsrv_nfs_xdrneg1)
375 vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
376 if (sp->sa_atime.nfsv2_sec != nfsrv_nfs_xdrneg1) {
377 #ifdef notyet
378 fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
379 #else
380 vap->va_atime.tv_sec =
381 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
382 vap->va_atime.tv_nsec = 0;
383 #endif
384 }
385 if (sp->sa_mtime.nfsv2_sec != nfsrv_nfs_xdrneg1)
386 fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
387
388 }
389
390 /*
391 * Now that we have all the fields, lets do it.
392 */
393 error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
394 vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
395 if (error) {
396 nfsm_reply(2 * NFSX_UNSIGNED);
397 if (v3)
398 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
399 error = 0;
400 goto nfsmout;
401 }
402
403 /*
404 * vp now an active resource, pay careful attention to cleanup
405 */
406 if (v3) {
407 error = preat_ret = VOP_GETATTR(vp, &preat, cred);
408 if (!error && gcheck &&
409 (preat.va_ctime.tv_sec != guard.tv_sec ||
410 preat.va_ctime.tv_nsec != guard.tv_nsec))
411 error = NFSERR_NOT_SYNC;
412 if (error) {
413 vput(vp);
414 vp = NULL;
415 nfsm_reply(NFSX_WCCDATA(v3));
416 if (v3)
417 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
418 error = 0;
419 goto nfsmout;
420 }
421 }
422
423 /*
424 * If the size is being changed write acces is required, otherwise
425 * just check for a read only filesystem.
426 */
427 if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
428 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
429 error = EROFS;
430 goto out;
431 }
432 } else {
433 if (vp->v_type == VDIR) {
434 error = EISDIR;
435 goto out;
436 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
437 0)) != 0)
438 goto out;
439 }
440 error = VOP_SETATTR(vp, vap, cred);
441 postat_ret = VOP_GETATTR(vp, vap, cred);
442 if (!error)
443 error = postat_ret;
444 out:
445 if (vp != NULL)
446 vput(vp);
447
448 vp = NULL;
449 nfsm_reply(NFSX_WCCORFATTR(v3));
450 if (v3) {
451 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
452 } else if (!error) {
453 /* v2 non-error case. */
454 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
455 nfsm_srvfillattr(vap, fp);
456 }
457 error = 0;
458 /* fall through */
459
460 nfsmout:
461 if (vp)
462 vput(vp);
463 vn_finished_write(mp);
464 VFS_UNLOCK_GIANT(vfslocked);
465 return(error);
466 }
467
468 /*
469 * nfs lookup rpc
470 */
471 int
472 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
473 struct mbuf **mrq)
474 {
475 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
476 struct sockaddr *nam = nfsd->nd_nam;
477 caddr_t dpos = nfsd->nd_dpos;
478 struct ucred *cred = nfsd->nd_cr;
479 struct nfs_fattr *fp;
480 struct nameidata nd, ind, *ndp = &nd;
481 struct vnode *vp, *dirp = NULL;
482 nfsfh_t nfh;
483 fhandle_t *fhp;
484 caddr_t bpos;
485 int error = 0, len, dirattr_ret = 1;
486 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
487 struct mbuf *mb, *mreq;
488 struct vattr va, dirattr, *vap = &va;
489 int tvfslocked;
490 int vfslocked;
491
492 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
493 ndclear(&nd);
494 vfslocked = 0;
495
496 fhp = &nfh.fh_generic;
497 nfsm_srvmtofh(fhp);
498 nfsm_srvnamesiz(len);
499
500 pubflag = nfs_ispublicfh(fhp);
501
502 nd.ni_cnd.cn_cred = cred;
503 nd.ni_cnd.cn_nameiop = LOOKUP;
504 nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART | MPSAFE;
505 error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
506 &dirp, v3, &dirattr, &dirattr_ret, pubflag);
507 vfslocked = NDHASGIANT(&nd);
508
509 /*
510 * namei failure, only dirp to cleanup. Clear out garbarge from
511 * structure in case macros jump to nfsmout.
512 */
513
514 if (error) {
515 if (dirp) {
516 vrele(dirp);
517 dirp = NULL;
518 }
519 nfsm_reply(NFSX_POSTOPATTR(v3));
520 if (v3)
521 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
522 error = 0;
523 goto nfsmout;
524 }
525
526 /*
527 * Locate index file for public filehandle
528 *
529 * error is 0 on entry and 0 on exit from this block.
530 */
531
532 if (pubflag) {
533 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
534 /*
535 * Setup call to lookup() to see if we can find
536 * the index file. Arguably, this doesn't belong
537 * in a kernel.. Ugh. If an error occurs, do not
538 * try to install an index file and then clear the
539 * error.
540 *
541 * When we replace nd with ind and redirect ndp,
542 * maintenance of ni_startdir and ni_vp shift to
543 * ind and we have to clean them up in the old nd.
544 * However, the cnd resource continues to be maintained
545 * via the original nd. Confused? You aren't alone!
546 */
547 ind = nd;
548 VOP_UNLOCK(nd.ni_vp, 0);
549 ind.ni_pathlen = strlen(nfs_pub.np_index);
550 ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
551 nfs_pub.np_index;
552 ind.ni_startdir = nd.ni_vp;
553 VREF(ind.ni_startdir);
554 ind.ni_cnd.cn_flags &= ~GIANTHELD;
555 tvfslocked = VFS_LOCK_GIANT(ind.ni_startdir->v_mount);
556 if (tvfslocked)
557 nd.ni_cnd.cn_flags |= GIANTHELD;
558 error = lookup(&ind);
559 ind.ni_dvp = NULL;
560 vfslocked = nfsrv_lockedpair_nd(vfslocked, &ind);
561 ind.ni_cnd.cn_flags &= ~GIANTHELD;
562
563 if (error == 0) {
564 /*
565 * Found an index file. Get rid of
566 * the old references. transfer nd.ni_vp'
567 */
568 if (dirp)
569 vrele(dirp);
570 dirp = nd.ni_vp;
571 nd.ni_vp = NULL;
572 vrele(nd.ni_startdir);
573 nd.ni_startdir = NULL;
574 ndp = &ind;
575 }
576 error = 0;
577 }
578 /*
579 * If the public filehandle was used, check that this lookup
580 * didn't result in a filehandle outside the publicly exported
581 * filesystem. We clear the poor vp here to avoid lockups due
582 * to NFS I/O.
583 */
584
585 if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
586 vput(nd.ni_vp);
587 nd.ni_vp = NULL;
588 error = EPERM;
589 }
590 }
591
592 /*
593 * Resources at this point:
594 * ndp->ni_vp may not be NULL
595 */
596
597 if (error) {
598 nfsm_reply(NFSX_POSTOPATTR(v3));
599 if (v3)
600 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
601 error = 0;
602 goto nfsmout;
603 }
604
605 /*
606 * Get underlying attribute, then release remaining resources ( for
607 * the same potential blocking reason ) and reply.
608 */
609 vp = ndp->ni_vp;
610 bzero((caddr_t)fhp, sizeof(nfh));
611 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
612 error = VOP_VPTOFH(vp, &fhp->fh_fid);
613 if (!error)
614 error = VOP_GETATTR(vp, vap, cred);
615
616 vput(vp);
617 vrele(ndp->ni_startdir);
618 vrele(dirp);
619 ndp->ni_vp = NULL;
620 ndp->ni_startdir = NULL;
621 dirp = NULL;
622 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
623 if (error) {
624 if (v3)
625 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
626 error = 0;
627 goto nfsmout;
628 }
629 nfsm_srvfhtom(fhp, v3);
630 if (v3) {
631 nfsm_srvpostop_attr(0, vap);
632 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
633 } else {
634 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
635 nfsm_srvfillattr(vap, fp);
636 }
637
638 nfsmout:
639 if (ndp->ni_vp || dirp || ndp->ni_startdir) {
640 if (ndp->ni_vp)
641 vput(ndp->ni_vp);
642 if (dirp)
643 vrele(dirp);
644 if (ndp->ni_startdir)
645 vrele(ndp->ni_startdir);
646 }
647 NDFREE(&nd, NDF_ONLY_PNBUF);
648 VFS_UNLOCK_GIANT(vfslocked);
649 return (error);
650 }
651
652 /*
653 * nfs readlink service
654 */
655 int
656 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
657 struct mbuf **mrq)
658 {
659 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
660 struct sockaddr *nam = nfsd->nd_nam;
661 caddr_t dpos = nfsd->nd_dpos;
662 struct ucred *cred = nfsd->nd_cr;
663 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
664 struct iovec *ivp = iv;
665 struct mbuf *mp;
666 u_int32_t *tl;
667 caddr_t bpos;
668 int error = 0, rdonly, i, tlen, len, getret;
669 int v3 = (nfsd->nd_flag & ND_NFSV3);
670 struct mbuf *mb, *mp3, *nmp, *mreq;
671 struct vnode *vp = NULL;
672 struct vattr attr;
673 nfsfh_t nfh;
674 fhandle_t *fhp;
675 struct uio io, *uiop = &io;
676 int vfslocked;
677
678 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
679 vfslocked = 0;
680 #ifndef nolint
681 mp = NULL;
682 #endif
683 mp3 = NULL;
684 fhp = &nfh.fh_generic;
685 nfsm_srvmtofh(fhp);
686 len = 0;
687 i = 0;
688 while (len < NFS_MAXPATHLEN) {
689 MGET(nmp, M_WAIT, MT_DATA);
690 MCLGET(nmp, M_WAIT);
691 nmp->m_len = NFSMSIZ(nmp);
692 if (len == 0)
693 mp3 = mp = nmp;
694 else {
695 mp->m_next = nmp;
696 mp = nmp;
697 }
698 if ((len + mp->m_len) > NFS_MAXPATHLEN) {
699 mp->m_len = NFS_MAXPATHLEN - len;
700 len = NFS_MAXPATHLEN;
701 } else
702 len += mp->m_len;
703 ivp->iov_base = mtod(mp, caddr_t);
704 ivp->iov_len = mp->m_len;
705 i++;
706 ivp++;
707 }
708 uiop->uio_iov = iv;
709 uiop->uio_iovcnt = i;
710 uiop->uio_offset = 0;
711 uiop->uio_resid = len;
712 uiop->uio_rw = UIO_READ;
713 uiop->uio_segflg = UIO_SYSSPACE;
714 uiop->uio_td = NULL;
715 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
716 if (error) {
717 nfsm_reply(2 * NFSX_UNSIGNED);
718 if (v3)
719 nfsm_srvpostop_attr(1, NULL);
720 error = 0;
721 goto nfsmout;
722 }
723 if (vp->v_type != VLNK) {
724 if (v3)
725 error = EINVAL;
726 else
727 error = ENXIO;
728 } else
729 error = VOP_READLINK(vp, uiop, cred);
730 getret = VOP_GETATTR(vp, &attr, cred);
731 vput(vp);
732 vp = NULL;
733 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
734 if (v3)
735 nfsm_srvpostop_attr(getret, &attr);
736 if (error) {
737 error = 0;
738 goto nfsmout;
739 }
740 if (uiop->uio_resid > 0) {
741 len -= uiop->uio_resid;
742 tlen = nfsm_rndup(len);
743 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
744 }
745 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
746 *tl = txdr_unsigned(len);
747 mb->m_next = mp3;
748 mp3 = NULL;
749 nfsmout:
750 if (mp3)
751 m_freem(mp3);
752 if (vp)
753 vput(vp);
754 VFS_UNLOCK_GIANT(vfslocked);
755 return(error);
756 }
757
758 /*
759 * nfs read service
760 */
761 int
762 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
763 struct mbuf **mrq)
764 {
765 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
766 struct sockaddr *nam = nfsd->nd_nam;
767 caddr_t dpos = nfsd->nd_dpos;
768 struct ucred *cred = nfsd->nd_cr;
769 struct iovec *iv;
770 struct iovec *iv2;
771 struct mbuf *m;
772 struct nfs_fattr *fp;
773 u_int32_t *tl;
774 int i;
775 caddr_t bpos;
776 int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
777 int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
778 struct mbuf *mb, *mreq;
779 struct mbuf *m2;
780 struct vnode *vp = NULL;
781 nfsfh_t nfh;
782 fhandle_t *fhp;
783 struct uio io, *uiop = &io;
784 struct vattr va, *vap = &va;
785 struct nfsheur *nh;
786 off_t off;
787 int ioflag = 0;
788 int vfslocked;
789
790
791 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
792 vfslocked = 0;
793 fhp = &nfh.fh_generic;
794 nfsm_srvmtofh(fhp);
795 if (v3) {
796 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
797 off = fxdr_hyper(tl);
798 } else {
799 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
800 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
801 }
802 nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
803
804 /*
805 * Reference vp. If an error occurs, vp will be invalid, but we
806 * have to NULL it just in case. The macros might goto nfsmout
807 * as well.
808 */
809
810 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
811 if (error) {
812 vp = NULL;
813 nfsm_reply(2 * NFSX_UNSIGNED);
814 if (v3)
815 nfsm_srvpostop_attr(1, NULL);
816 error = 0;
817 goto nfsmout;
818 }
819
820 if (vp->v_type != VREG) {
821 if (v3)
822 error = EINVAL;
823 else
824 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
825 }
826 if (!error) {
827 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, 1)) != 0)
828 error = nfsrv_access(vp, VEXEC, cred, rdonly, 1);
829 }
830 getret = VOP_GETATTR(vp, vap, cred);
831 if (!error)
832 error = getret;
833 if (error) {
834 vput(vp);
835 vp = NULL;
836 nfsm_reply(NFSX_POSTOPATTR(v3));
837 if (v3)
838 nfsm_srvpostop_attr(getret, vap);
839 error = 0;
840 goto nfsmout;
841 }
842
843 /*
844 * Calculate byte count to read
845 */
846
847 if (off >= vap->va_size)
848 cnt = 0;
849 else if ((off + reqlen) > vap->va_size)
850 cnt = vap->va_size - off;
851 else
852 cnt = reqlen;
853
854 /*
855 * Calculate seqcount for heuristic
856 */
857
858 {
859 int hi;
860 int try = 32;
861
862 /*
863 * Locate best candidate
864 */
865
866 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
867 nh = &nfsheur[hi];
868
869 while (try--) {
870 if (nfsheur[hi].nh_vp == vp) {
871 nh = &nfsheur[hi];
872 break;
873 }
874 if (nfsheur[hi].nh_use > 0)
875 --nfsheur[hi].nh_use;
876 hi = (hi + 1) % NUM_HEURISTIC;
877 if (nfsheur[hi].nh_use < nh->nh_use)
878 nh = &nfsheur[hi];
879 }
880
881 if (nh->nh_vp != vp) {
882 nh->nh_vp = vp;
883 nh->nh_nextr = off;
884 nh->nh_use = NHUSE_INIT;
885 if (off == 0)
886 nh->nh_seqcount = 4;
887 else
888 nh->nh_seqcount = 1;
889 }
890
891 /*
892 * Calculate heuristic
893 */
894
895 if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) {
896 if (++nh->nh_seqcount > IO_SEQMAX)
897 nh->nh_seqcount = IO_SEQMAX;
898 } else if (nh->nh_seqcount > 1) {
899 nh->nh_seqcount = 1;
900 } else {
901 nh->nh_seqcount = 0;
902 }
903 nh->nh_use += NHUSE_INC;
904 if (nh->nh_use > NHUSE_MAX)
905 nh->nh_use = NHUSE_MAX;
906 ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
907 }
908
909 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
910 if (v3) {
911 tl = nfsm_build(u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
912 *tl++ = nfsrv_nfs_true;
913 fp = (struct nfs_fattr *)tl;
914 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
915 } else {
916 tl = nfsm_build(u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
917 fp = (struct nfs_fattr *)tl;
918 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
919 }
920 len = left = nfsm_rndup(cnt);
921 if (cnt > 0) {
922 /*
923 * Generate the mbuf list with the uio_iov ref. to it.
924 */
925 i = 0;
926 m = m2 = mb;
927 while (left > 0) {
928 siz = min(M_TRAILINGSPACE(m), left);
929 if (siz > 0) {
930 left -= siz;
931 i++;
932 }
933 if (left > 0) {
934 MGET(m, M_WAIT, MT_DATA);
935 MCLGET(m, M_WAIT);
936 m->m_len = 0;
937 m2->m_next = m;
938 m2 = m;
939 }
940 }
941 iv = malloc(i * sizeof (struct iovec),
942 M_TEMP, M_WAITOK);
943 uiop->uio_iov = iv2 = iv;
944 m = mb;
945 left = len;
946 i = 0;
947 while (left > 0) {
948 if (m == NULL)
949 panic("nfsrv_read iov");
950 siz = min(M_TRAILINGSPACE(m), left);
951 if (siz > 0) {
952 iv->iov_base = mtod(m, caddr_t) + m->m_len;
953 iv->iov_len = siz;
954 m->m_len += siz;
955 left -= siz;
956 iv++;
957 i++;
958 }
959 m = m->m_next;
960 }
961 uiop->uio_iovcnt = i;
962 uiop->uio_offset = off;
963 uiop->uio_resid = len;
964 uiop->uio_rw = UIO_READ;
965 uiop->uio_segflg = UIO_SYSSPACE;
966 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
967 off = uiop->uio_offset;
968 nh->nh_nextr = off;
969 free((caddr_t)iv2, M_TEMP);
970 if (error || (getret = VOP_GETATTR(vp, vap, cred))) {
971 if (!error)
972 error = getret;
973 m_freem(mreq);
974 vput(vp);
975 vp = NULL;
976 nfsm_reply(NFSX_POSTOPATTR(v3));
977 if (v3)
978 nfsm_srvpostop_attr(getret, vap);
979 error = 0;
980 goto nfsmout;
981 }
982 } else
983 uiop->uio_resid = 0;
984 vput(vp);
985 vp = NULL;
986 nfsm_srvfillattr(vap, fp);
987 tlen = len - uiop->uio_resid;
988 cnt = cnt < tlen ? cnt : tlen;
989 tlen = nfsm_rndup(cnt);
990 if (len != tlen || tlen != cnt)
991 nfsm_adj(mb, len - tlen, tlen - cnt);
992 if (v3) {
993 *tl++ = txdr_unsigned(cnt);
994 if (cnt < reqlen)
995 *tl++ = nfsrv_nfs_true;
996 else
997 *tl++ = nfsrv_nfs_false;
998 }
999 *tl = txdr_unsigned(cnt);
1000 nfsmout:
1001 if (vp)
1002 vput(vp);
1003 VFS_UNLOCK_GIANT(vfslocked);
1004 return(error);
1005 }
1006
1007 /*
1008 * nfs write service
1009 */
1010 int
1011 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1012 struct mbuf **mrq)
1013 {
1014 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1015 struct sockaddr *nam = nfsd->nd_nam;
1016 caddr_t dpos = nfsd->nd_dpos;
1017 struct ucred *cred = nfsd->nd_cr;
1018 struct iovec *ivp;
1019 int i, cnt;
1020 struct mbuf *mp;
1021 struct nfs_fattr *fp;
1022 struct iovec *iv;
1023 struct vattr va, forat;
1024 struct vattr *vap = &va;
1025 u_int32_t *tl;
1026 caddr_t bpos;
1027 int error = 0, rdonly, len, forat_ret = 1;
1028 int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
1029 int stable = NFSV3WRITE_FILESYNC;
1030 int v3 = (nfsd->nd_flag & ND_NFSV3);
1031 struct mbuf *mb, *mreq;
1032 struct vnode *vp = NULL;
1033 nfsfh_t nfh;
1034 fhandle_t *fhp;
1035 struct uio io, *uiop = &io;
1036 off_t off;
1037 struct mount *mntp = NULL;
1038 int tvfslocked;
1039 int vfslocked;
1040
1041 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1042 vfslocked = 0;
1043 if (mrep == NULL) {
1044 *mrq = NULL;
1045 error = 0;
1046 goto nfsmout;
1047 }
1048 fhp = &nfh.fh_generic;
1049 nfsm_srvmtofh(fhp);
1050 if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1051 error = ESTALE;
1052 goto ereply;
1053 }
1054 vfslocked = VFS_LOCK_GIANT(mntp);
1055 (void) vn_start_write(NULL, &mntp, V_WAIT);
1056 vfs_rel(mntp); /* The write holds a ref. */
1057 if (v3) {
1058 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
1059 off = fxdr_hyper(tl);
1060 tl += 3;
1061 stable = fxdr_unsigned(int, *tl++);
1062 } else {
1063 tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
1064 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1065 tl += 2;
1066 if (nfs_async)
1067 stable = NFSV3WRITE_UNSTABLE;
1068 }
1069 retlen = len = fxdr_unsigned(int32_t, *tl);
1070 cnt = i = 0;
1071
1072 /*
1073 * For NFS Version 2, it is not obvious what a write of zero length
1074 * should do, but I might as well be consistent with Version 3,
1075 * which is to return ok so long as there are no permission problems.
1076 */
1077 if (len > 0) {
1078 zeroing = 1;
1079 mp = mrep;
1080 while (mp) {
1081 if (mp == md) {
1082 zeroing = 0;
1083 adjust = dpos - mtod(mp, caddr_t);
1084 mp->m_len -= adjust;
1085 if (mp->m_len > 0 && adjust > 0)
1086 mp->m_data += adjust;
1087 }
1088 if (zeroing)
1089 mp->m_len = 0;
1090 else if (mp->m_len > 0) {
1091 i += mp->m_len;
1092 if (i > len) {
1093 mp->m_len -= (i - len);
1094 zeroing = 1;
1095 }
1096 if (mp->m_len > 0)
1097 cnt++;
1098 }
1099 mp = mp->m_next;
1100 }
1101 }
1102 if (len > NFS_MAXDATA || len < 0 || i < len) {
1103 error = EIO;
1104 nfsm_reply(2 * NFSX_UNSIGNED);
1105 if (v3)
1106 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1107 error = 0;
1108 goto nfsmout;
1109 }
1110 error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
1111 vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
1112 if (error) {
1113 vp = NULL;
1114 nfsm_reply(2 * NFSX_UNSIGNED);
1115 if (v3)
1116 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1117 error = 0;
1118 goto nfsmout;
1119 }
1120 if (v3)
1121 forat_ret = VOP_GETATTR(vp, &forat, cred);
1122 if (vp->v_type != VREG) {
1123 if (v3)
1124 error = EINVAL;
1125 else
1126 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1127 }
1128 if (!error)
1129 error = nfsrv_access(vp, VWRITE, cred, rdonly, 1);
1130 if (error) {
1131 vput(vp);
1132 vp = NULL;
1133 nfsm_reply(NFSX_WCCDATA(v3));
1134 if (v3)
1135 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1136 error = 0;
1137 goto nfsmout;
1138 }
1139
1140 if (len > 0) {
1141 ivp = malloc(cnt * sizeof (struct iovec), M_TEMP,
1142 M_WAITOK);
1143 uiop->uio_iov = iv = ivp;
1144 uiop->uio_iovcnt = cnt;
1145 mp = mrep;
1146 while (mp) {
1147 if (mp->m_len > 0) {
1148 ivp->iov_base = mtod(mp, caddr_t);
1149 ivp->iov_len = mp->m_len;
1150 ivp++;
1151 }
1152 mp = mp->m_next;
1153 }
1154
1155 /*
1156 * XXX
1157 * The IO_METASYNC flag indicates that all metadata (and not just
1158 * enough to ensure data integrity) mus be written to stable storage
1159 * synchronously.
1160 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1161 */
1162 if (stable == NFSV3WRITE_UNSTABLE)
1163 ioflags = IO_NODELOCKED;
1164 else if (stable == NFSV3WRITE_DATASYNC)
1165 ioflags = (IO_SYNC | IO_NODELOCKED);
1166 else
1167 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1168 uiop->uio_resid = len;
1169 uiop->uio_rw = UIO_WRITE;
1170 uiop->uio_segflg = UIO_SYSSPACE;
1171 uiop->uio_td = NULL;
1172 uiop->uio_offset = off;
1173 error = VOP_WRITE(vp, uiop, ioflags, cred);
1174 /* Unlocked write. */
1175 nfsrvstats.srvvop_writes++;
1176 free((caddr_t)iv, M_TEMP);
1177 }
1178 aftat_ret = VOP_GETATTR(vp, vap, cred);
1179 vput(vp);
1180 vp = NULL;
1181 if (!error)
1182 error = aftat_ret;
1183 ereply:
1184 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
1185 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
1186 if (v3) {
1187 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1188 if (error) {
1189 error = 0;
1190 goto nfsmout;
1191 }
1192 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
1193 *tl++ = txdr_unsigned(retlen);
1194 /*
1195 * If nfs_async is set, then pretend the write was FILESYNC.
1196 */
1197 if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
1198 *tl++ = txdr_unsigned(stable);
1199 else
1200 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1201 /*
1202 * Actually, there is no need to txdr these fields,
1203 * but it may make the values more human readable,
1204 * for debugging purposes.
1205 */
1206 if (nfsver.tv_sec == 0)
1207 nfsver = boottime;
1208 *tl++ = txdr_unsigned(nfsver.tv_sec);
1209 *tl = txdr_unsigned(nfsver.tv_usec);
1210 } else if (!error) {
1211 /* v2 non-error case. */
1212 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1213 nfsm_srvfillattr(vap, fp);
1214 }
1215 error = 0;
1216 nfsmout:
1217 if (vp)
1218 vput(vp);
1219 vn_finished_write(mntp);
1220 VFS_UNLOCK_GIANT(vfslocked);
1221 return(error);
1222 }
1223
1224 /*
1225 * nfs create service
1226 * now does a truncate to 0 length via. setattr if it already exists
1227 */
1228 int
1229 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1230 struct mbuf **mrq)
1231 {
1232 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1233 struct sockaddr *nam = nfsd->nd_nam;
1234 caddr_t dpos = nfsd->nd_dpos;
1235 struct ucred *cred = nfsd->nd_cr;
1236 struct nfs_fattr *fp;
1237 struct vattr va, dirfor, diraft;
1238 struct vattr *vap = &va;
1239 struct nfsv2_sattr *sp;
1240 u_int32_t *tl;
1241 struct nameidata nd;
1242 caddr_t bpos;
1243 int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1244 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1245 struct mbuf *mb, *mreq;
1246 struct vnode *dirp = NULL;
1247 nfsfh_t nfh;
1248 fhandle_t *fhp;
1249 u_quad_t tempsize;
1250 struct timespec cverf;
1251 struct mount *mp = NULL;
1252 int tvfslocked;
1253 int vfslocked;
1254
1255 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1256 vfslocked = 0;
1257 #ifndef nolint
1258 rdev = 0;
1259 #endif
1260 ndclear(&nd);
1261
1262 fhp = &nfh.fh_generic;
1263 nfsm_srvmtofh(fhp);
1264 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1265 error = ESTALE;
1266 goto ereply;
1267 }
1268 vfslocked = VFS_LOCK_GIANT(mp);
1269 (void) vn_start_write(NULL, &mp, V_WAIT);
1270 vfs_rel(mp); /* The write holds a ref. */
1271 nfsm_srvnamesiz(len);
1272
1273 nd.ni_cnd.cn_cred = cred;
1274 nd.ni_cnd.cn_nameiop = CREATE;
1275 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE;
1276
1277 /*
1278 * Call namei and do initial cleanup to get a few things
1279 * out of the way. If we get an initial error we cleanup
1280 * and return here to avoid special-casing the invalid nd
1281 * structure through the rest of the case. dirp may be
1282 * set even if an error occurs, but the nd structure will not
1283 * be valid at all if an error occurs so we have to invalidate it
1284 * prior to calling nfsm_reply ( which might goto nfsmout ).
1285 */
1286 error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1287 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
1288 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1289 if (dirp && !v3) {
1290 vrele(dirp);
1291 dirp = NULL;
1292 }
1293 if (error) {
1294 nfsm_reply(NFSX_WCCDATA(v3));
1295 if (v3)
1296 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1297 error = 0;
1298 goto nfsmout;
1299 }
1300
1301 /*
1302 * No error. Continue. State:
1303 *
1304 * startdir is valid ( we release this immediately )
1305 * dirp may be valid
1306 * nd.ni_vp may be valid
1307 * nd.ni_dvp is valid
1308 *
1309 * The error state is set through the code and we may also do some
1310 * opportunistic releasing of vnodes to avoid holding locks through
1311 * NFS I/O. The cleanup at the end is a catch-all
1312 */
1313
1314 VATTR_NULL(vap);
1315 if (v3) {
1316 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1317 how = fxdr_unsigned(int, *tl);
1318 switch (how) {
1319 case NFSV3CREATE_GUARDED:
1320 if (nd.ni_vp) {
1321 error = EEXIST;
1322 break;
1323 }
1324 /* fall through */
1325 case NFSV3CREATE_UNCHECKED:
1326 nfsm_srvsattr(vap);
1327 break;
1328 case NFSV3CREATE_EXCLUSIVE:
1329 tl = nfsm_dissect_nonblock(u_int32_t *,
1330 NFSX_V3CREATEVERF);
1331 /* Unique bytes, endianness is not important. */
1332 cverf.tv_sec = (int32_t)tl[0];
1333 cverf.tv_nsec = tl[1];
1334 exclusive_flag = 1;
1335 break;
1336 };
1337 vap->va_type = VREG;
1338 } else {
1339 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
1340 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1341 if (vap->va_type == VNON)
1342 vap->va_type = VREG;
1343 vap->va_mode = nfstov_mode(sp->sa_mode);
1344 switch (vap->va_type) {
1345 case VREG:
1346 tsize = fxdr_unsigned(int32_t, sp->sa_size);
1347 if (tsize != -1)
1348 vap->va_size = (u_quad_t)tsize;
1349 break;
1350 case VCHR:
1351 case VBLK:
1352 case VFIFO:
1353 rdev = fxdr_unsigned(long, sp->sa_size);
1354 break;
1355 default:
1356 break;
1357 };
1358 }
1359
1360 /*
1361 * Iff doesn't exist, create it
1362 * otherwise just truncate to 0 length
1363 * should I set the mode too ?
1364 *
1365 * The only possible error we can have at this point is EEXIST.
1366 * nd.ni_vp will also be non-NULL in that case.
1367 */
1368 if (nd.ni_vp == NULL) {
1369 if (vap->va_mode == (mode_t)VNOVAL)
1370 vap->va_mode = 0;
1371 if (vap->va_type == VREG || vap->va_type == VSOCK) {
1372 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1373 if (error)
1374 NDFREE(&nd, NDF_ONLY_PNBUF);
1375 else {
1376 if (exclusive_flag) {
1377 exclusive_flag = 0;
1378 VATTR_NULL(vap);
1379 vap->va_atime = cverf;
1380 error = VOP_SETATTR(nd.ni_vp, vap,
1381 cred);
1382 }
1383 }
1384 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
1385 vap->va_type == VFIFO) {
1386 /*
1387 * NFSv2-specific code for creating device nodes
1388 * and fifos.
1389 *
1390 * Handle SysV FIFO node special cases. All other
1391 * devices require super user to access.
1392 */
1393 if (vap->va_type == VCHR && rdev == 0xffffffff)
1394 vap->va_type = VFIFO;
1395 if (vap->va_type != VFIFO &&
1396 (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV,
1397 0))) {
1398 goto ereply;
1399 }
1400 vap->va_rdev = rdev;
1401 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1402 if (error) {
1403 NDFREE(&nd, NDF_ONLY_PNBUF);
1404 goto ereply;
1405 }
1406 vput(nd.ni_vp);
1407 nd.ni_vp = NULL;
1408
1409 /*
1410 * release dvp prior to lookup
1411 */
1412 vput(nd.ni_dvp);
1413 nd.ni_dvp = NULL;
1414 /*
1415 * Setup for lookup.
1416 *
1417 * Even though LOCKPARENT was cleared, ni_dvp may
1418 * be garbage.
1419 */
1420 nd.ni_cnd.cn_nameiop = LOOKUP;
1421 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1422 nd.ni_cnd.cn_thread = curthread;
1423 nd.ni_cnd.cn_cred = cred;
1424 tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
1425 if (tvfslocked)
1426 nd.ni_cnd.cn_flags |= GIANTHELD;
1427 error = lookup(&nd);
1428 nd.ni_dvp = NULL;
1429 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1430 nd.ni_cnd.cn_flags &= ~GIANTHELD;
1431 if (error)
1432 goto ereply;
1433
1434 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1435 error = EINVAL;
1436 goto ereply;
1437 }
1438 } else {
1439 error = ENXIO;
1440 }
1441 } else {
1442 if (vap->va_size != -1) {
1443 error = nfsrv_access(nd.ni_vp, VWRITE,
1444 cred, (nd.ni_cnd.cn_flags & RDONLY), 0);
1445 if (!error) {
1446 tempsize = vap->va_size;
1447 VATTR_NULL(vap);
1448 vap->va_size = tempsize;
1449 error = VOP_SETATTR(nd.ni_vp, vap, cred);
1450 }
1451 }
1452 }
1453
1454 if (!error) {
1455 bzero((caddr_t)fhp, sizeof(nfh));
1456 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
1457 error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
1458 if (!error)
1459 error = VOP_GETATTR(nd.ni_vp, vap, cred);
1460 }
1461 if (v3) {
1462 if (exclusive_flag && !error &&
1463 bcmp(&cverf, &vap->va_atime, sizeof (cverf)))
1464 error = EEXIST;
1465 if (dirp == nd.ni_dvp)
1466 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1467 else {
1468 /* Drop the other locks to avoid deadlock. */
1469 if (nd.ni_dvp) {
1470 if (nd.ni_dvp == nd.ni_vp)
1471 vrele(nd.ni_dvp);
1472 else
1473 vput(nd.ni_dvp);
1474 }
1475 if (nd.ni_vp)
1476 vput(nd.ni_vp);
1477 nd.ni_dvp = NULL;
1478 nd.ni_vp = NULL;
1479
1480 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1481 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1482 VOP_UNLOCK(dirp, 0);
1483 }
1484 }
1485 ereply:
1486 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1487 if (v3) {
1488 if (!error) {
1489 nfsm_srvpostop_fh(fhp);
1490 nfsm_srvpostop_attr(0, vap);
1491 }
1492 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1493 } else if (!error) {
1494 /* v2 non-error case. */
1495 nfsm_srvfhtom(fhp, v3);
1496 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1497 nfsm_srvfillattr(vap, fp);
1498 }
1499 error = 0;
1500
1501 nfsmout:
1502 if (nd.ni_dvp) {
1503 if (nd.ni_dvp == nd.ni_vp)
1504 vrele(nd.ni_dvp);
1505 else
1506 vput(nd.ni_dvp);
1507 }
1508 if (nd.ni_vp)
1509 vput(nd.ni_vp);
1510 if (nd.ni_startdir) {
1511 vrele(nd.ni_startdir);
1512 nd.ni_startdir = NULL;
1513 }
1514 if (dirp)
1515 vrele(dirp);
1516 NDFREE(&nd, NDF_ONLY_PNBUF);
1517 vn_finished_write(mp);
1518 VFS_UNLOCK_GIANT(vfslocked);
1519 return (error);
1520 }
1521
1522 /*
1523 * nfs v3 mknod service
1524 */
1525 int
1526 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1527 struct mbuf **mrq)
1528 {
1529 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1530 struct sockaddr *nam = nfsd->nd_nam;
1531 caddr_t dpos = nfsd->nd_dpos;
1532 struct ucred *cred = nfsd->nd_cr;
1533 struct vattr va, dirfor, diraft;
1534 struct vattr *vap = &va;
1535 struct thread *td = curthread;
1536 u_int32_t *tl;
1537 struct nameidata nd;
1538 caddr_t bpos;
1539 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1540 u_int32_t major, minor;
1541 enum vtype vtyp;
1542 struct mbuf *mb, *mreq;
1543 struct vnode *vp, *dirp = NULL;
1544 nfsfh_t nfh;
1545 fhandle_t *fhp;
1546 struct mount *mp = NULL;
1547 int v3 = (nfsd->nd_flag & ND_NFSV3);
1548 int tvfslocked;
1549 int vfslocked;
1550
1551 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1552 vfslocked = 0;
1553 if (!v3)
1554 panic("nfsrv_mknod: v3 proc called on a v2 connection");
1555 ndclear(&nd);
1556
1557 fhp = &nfh.fh_generic;
1558 nfsm_srvmtofh(fhp);
1559 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1560 error = ESTALE;
1561 goto ereply;
1562 }
1563 vfslocked = VFS_LOCK_GIANT(mp);
1564 (void) vn_start_write(NULL, &mp, V_WAIT);
1565 vfs_rel(mp); /* The write holds a ref. */
1566 nfsm_srvnamesiz(len);
1567
1568 nd.ni_cnd.cn_cred = cred;
1569 nd.ni_cnd.cn_nameiop = CREATE;
1570 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE;
1571
1572 /*
1573 * Handle nfs_namei() call. If an error occurs, the nd structure
1574 * is not valid. However, nfsm_*() routines may still jump to
1575 * nfsmout.
1576 */
1577
1578 error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1579 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
1580 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1581 if (error) {
1582 nfsm_reply(NFSX_WCCDATA(1));
1583 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1584 error = 0;
1585 goto nfsmout;
1586 }
1587 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1588 vtyp = nfsv3tov_type(*tl);
1589 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1590 error = NFSERR_BADTYPE;
1591 goto out;
1592 }
1593 VATTR_NULL(vap);
1594 nfsm_srvsattr(vap);
1595 if (vtyp == VCHR || vtyp == VBLK) {
1596 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
1597 major = fxdr_unsigned(u_int32_t, *tl++);
1598 minor = fxdr_unsigned(u_int32_t, *tl);
1599 vap->va_rdev = makedev(major, minor);
1600 }
1601
1602 /*
1603 * Iff doesn't exist, create it.
1604 */
1605 if (nd.ni_vp) {
1606 error = EEXIST;
1607 goto out;
1608 }
1609 vap->va_type = vtyp;
1610 if (vap->va_mode == (mode_t)VNOVAL)
1611 vap->va_mode = 0;
1612 if (vtyp == VSOCK) {
1613 vrele(nd.ni_startdir);
1614 nd.ni_startdir = NULL;
1615 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1616 if (error)
1617 NDFREE(&nd, NDF_ONLY_PNBUF);
1618 } else {
1619 if (vtyp != VFIFO && (error = priv_check_cred(cred,
1620 PRIV_VFS_MKNOD_DEV, 0)))
1621 goto out;
1622 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1623 if (error) {
1624 NDFREE(&nd, NDF_ONLY_PNBUF);
1625 goto out;
1626 }
1627 vput(nd.ni_vp);
1628 nd.ni_vp = NULL;
1629
1630 /*
1631 * Release dvp prior to lookup
1632 */
1633 vput(nd.ni_dvp);
1634 nd.ni_dvp = NULL;
1635
1636 nd.ni_cnd.cn_nameiop = LOOKUP;
1637 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1638 nd.ni_cnd.cn_thread = td;
1639 nd.ni_cnd.cn_cred = td->td_ucred;
1640 tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
1641 if (tvfslocked)
1642 nd.ni_cnd.cn_flags |= GIANTHELD;
1643 error = lookup(&nd);
1644 nd.ni_dvp = NULL;
1645 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1646 nd.ni_cnd.cn_flags &= ~GIANTHELD;
1647
1648 if (error)
1649 goto out;
1650 if (nd.ni_cnd.cn_flags & ISSYMLINK)
1651 error = EINVAL;
1652 }
1653
1654 /*
1655 * send response, cleanup, return.
1656 */
1657 out:
1658 vp = nd.ni_vp;
1659 if (!error) {
1660 bzero((caddr_t)fhp, sizeof(nfh));
1661 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1662 error = VOP_VPTOFH(vp, &fhp->fh_fid);
1663 if (!error)
1664 error = VOP_GETATTR(vp, vap, cred);
1665 }
1666 if (nd.ni_dvp) {
1667 if (nd.ni_dvp == nd.ni_vp)
1668 vrele(nd.ni_dvp);
1669 else
1670 vput(nd.ni_dvp);
1671 nd.ni_dvp = NULL;
1672 }
1673 if (vp) {
1674 vput(vp);
1675 vp = NULL;
1676 nd.ni_vp = NULL;
1677 }
1678 if (nd.ni_startdir) {
1679 vrele(nd.ni_startdir);
1680 nd.ni_startdir = NULL;
1681 }
1682 NDFREE(&nd, NDF_ONLY_PNBUF);
1683 if (dirp) {
1684 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1685 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1686 vput(dirp);
1687 }
1688 ereply:
1689 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1690 if (v3) {
1691 if (!error) {
1692 nfsm_srvpostop_fh(fhp);
1693 nfsm_srvpostop_attr(0, vap);
1694 }
1695 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1696 }
1697 vn_finished_write(mp);
1698 VFS_UNLOCK_GIANT(vfslocked);
1699 return (0);
1700 nfsmout:
1701 if (nd.ni_dvp) {
1702 if (nd.ni_dvp == nd.ni_vp)
1703 vrele(nd.ni_dvp);
1704 else
1705 vput(nd.ni_dvp);
1706 }
1707 if (nd.ni_vp)
1708 vput(nd.ni_vp);
1709 if (dirp)
1710 vrele(dirp);
1711 if (nd.ni_startdir)
1712 vrele(nd.ni_startdir);
1713 NDFREE(&nd, NDF_ONLY_PNBUF);
1714 vn_finished_write(mp);
1715 VFS_UNLOCK_GIANT(vfslocked);
1716 return (error);
1717 }
1718
1719 /*
1720 * nfs remove service
1721 */
1722 int
1723 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1724 struct mbuf **mrq)
1725 {
1726 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1727 struct sockaddr *nam = nfsd->nd_nam;
1728 caddr_t dpos = nfsd->nd_dpos;
1729 struct ucred *cred = nfsd->nd_cr;
1730 struct nameidata nd;
1731 caddr_t bpos;
1732 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1733 int v3 = (nfsd->nd_flag & ND_NFSV3);
1734 struct mbuf *mb, *mreq;
1735 struct vnode *dirp;
1736 struct vattr dirfor, diraft;
1737 nfsfh_t nfh;
1738 fhandle_t *fhp;
1739 struct mount *mp = NULL;
1740 int vfslocked;
1741
1742 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1743 ndclear(&nd);
1744 vfslocked = 0;
1745
1746 fhp = &nfh.fh_generic;
1747 nfsm_srvmtofh(fhp);
1748 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1749 error = ESTALE;
1750 goto ereply;
1751 }
1752 vfslocked = VFS_LOCK_GIANT(mp);
1753 (void) vn_start_write(NULL, &mp, V_WAIT);
1754 vfs_rel(mp); /* The write holds a ref. */
1755 nfsm_srvnamesiz(len);
1756
1757 nd.ni_cnd.cn_cred = cred;
1758 nd.ni_cnd.cn_nameiop = DELETE;
1759 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | MPSAFE;
1760 error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1761 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
1762 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1763 if (dirp && !v3) {
1764 vrele(dirp);
1765 dirp = NULL;
1766 }
1767 if (error == 0) {
1768 if (nd.ni_vp->v_type == VDIR) {
1769 error = EPERM; /* POSIX */
1770 goto out;
1771 }
1772 /*
1773 * The root of a mounted filesystem cannot be deleted.
1774 */
1775 if (nd.ni_vp->v_vflag & VV_ROOT) {
1776 error = EBUSY;
1777 goto out;
1778 }
1779 out:
1780 if (!error) {
1781 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1782 NDFREE(&nd, NDF_ONLY_PNBUF);
1783 }
1784 }
1785 if (dirp && v3) {
1786 if (dirp == nd.ni_dvp)
1787 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1788 else {
1789 /* Drop the other locks to avoid deadlock. */
1790 if (nd.ni_dvp) {
1791 if (nd.ni_dvp == nd.ni_vp)
1792 vrele(nd.ni_dvp);
1793 else
1794 vput(nd.ni_dvp);
1795 }
1796 if (nd.ni_vp)
1797 vput(nd.ni_vp);
1798 nd.ni_dvp = NULL;
1799 nd.ni_vp = NULL;
1800
1801 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1802 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1803 VOP_UNLOCK(dirp, 0);
1804 }
1805 vrele(dirp);
1806 dirp = NULL;
1807 }
1808 ereply:
1809 nfsm_reply(NFSX_WCCDATA(v3));
1810 if (v3)
1811 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1812 error = 0;
1813 nfsmout:
1814 NDFREE(&nd, NDF_ONLY_PNBUF);
1815 if (nd.ni_dvp) {
1816 if (nd.ni_dvp == nd.ni_vp)
1817 vrele(nd.ni_dvp);
1818 else
1819 vput(nd.ni_dvp);
1820 }
1821 if (nd.ni_vp)
1822 vput(nd.ni_vp);
1823 vn_finished_write(mp);
1824 VFS_UNLOCK_GIANT(vfslocked);
1825 return(error);
1826 }
1827
1828 /*
1829 * nfs rename service
1830 */
1831 int
1832 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1833 struct mbuf **mrq)
1834 {
1835 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1836 struct sockaddr *nam = nfsd->nd_nam;
1837 caddr_t dpos = nfsd->nd_dpos;
1838 struct ucred *cred = nfsd->nd_cr;
1839 caddr_t bpos;
1840 int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
1841 int tdirfor_ret = 1, tdiraft_ret = 1;
1842 int v3 = (nfsd->nd_flag & ND_NFSV3);
1843 struct mbuf *mb, *mreq;
1844 struct nameidata fromnd, tond;
1845 struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
1846 struct vnode *tdirp = NULL;
1847 struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
1848 nfsfh_t fnfh, tnfh;
1849 fhandle_t *ffhp, *tfhp;
1850 uid_t saved_uid;
1851 struct mount *mp = NULL;
1852 int vfslocked;
1853
1854 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1855 vfslocked = 0;
1856 #ifndef nolint
1857 fvp = NULL;
1858 #endif
1859 ffhp = &fnfh.fh_generic;
1860 tfhp = &tnfh.fh_generic;
1861
1862 /*
1863 * Clear fields incase goto nfsmout occurs from macro.
1864 */
1865
1866 ndclear(&fromnd);
1867 ndclear(&tond);
1868
1869 nfsm_srvmtofh(ffhp);
1870 if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
1871 error = ESTALE;
1872 goto out1;
1873 }
1874 vfslocked = VFS_LOCK_GIANT(mp);
1875 (void) vn_start_write(NULL, &mp, V_WAIT);
1876 vfs_rel(mp); /* The write holds a ref. */
1877 nfsm_srvnamesiz(len);
1878 /*
1879 * Remember our original uid so that we can reset cr_uid before
1880 * the second nfs_namei() call, in case it is remapped.
1881 */
1882 saved_uid = cred->cr_uid;
1883 fromnd.ni_cnd.cn_cred = cred;
1884 fromnd.ni_cnd.cn_nameiop = DELETE;
1885 fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART | MPSAFE;
1886 error = nfs_namei(&fromnd, nfsd, ffhp, len, slp, nam, &md,
1887 &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, FALSE);
1888 vfslocked = nfsrv_lockedpair_nd(vfslocked, &fromnd);
1889 if (fdirp && !v3) {
1890 vrele(fdirp);
1891 fdirp = NULL;
1892 }
1893 if (error) {
1894 nfsm_reply(2 * NFSX_WCCDATA(v3));
1895 if (v3) {
1896 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1897 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1898 }
1899 error = 0;
1900 goto nfsmout;
1901 }
1902 fvp = fromnd.ni_vp;
1903 nfsm_srvmtofh(tfhp);
1904 nfsm_srvnamesiz(len2);
1905 cred->cr_uid = saved_uid;
1906 tond.ni_cnd.cn_cred = cred;
1907 tond.ni_cnd.cn_nameiop = RENAME;
1908 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | MPSAFE;
1909 error = nfs_namei(&tond, nfsd, tfhp, len2, slp, nam, &md,
1910 &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, FALSE);
1911 vfslocked = nfsrv_lockedpair_nd(vfslocked, &tond);
1912 if (tdirp && !v3) {
1913 vrele(tdirp);
1914 tdirp = NULL;
1915 }
1916 if (error)
1917 goto out1;
1918
1919 tdvp = tond.ni_dvp;
1920 tvp = tond.ni_vp;
1921 if (tvp != NULL) {
1922 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1923 if (v3)
1924 error = EEXIST;
1925 else
1926 error = EISDIR;
1927 goto out;
1928 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1929 if (v3)
1930 error = EEXIST;
1931 else
1932 error = ENOTDIR;
1933 goto out;
1934 }
1935 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1936 if (v3)
1937 error = EXDEV;
1938 else
1939 error = ENOTEMPTY;
1940 goto out;
1941 }
1942 }
1943 if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1944 if (v3)
1945 error = EXDEV;
1946 else
1947 error = ENOTEMPTY;
1948 goto out;
1949 }
1950 if (fvp->v_mount != tdvp->v_mount) {
1951 if (v3)
1952 error = EXDEV;
1953 else
1954 error = ENOTEMPTY;
1955 goto out;
1956 }
1957 if (fvp == tdvp) {
1958 if (v3)
1959 error = EINVAL;
1960 else
1961 error = ENOTEMPTY;
1962 }
1963 /*
1964 * If source is the same as the destination (that is the
1965 * same vnode with the same name in the same directory),
1966 * then there is nothing to do.
1967 */
1968 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1969 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1970 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1971 fromnd.ni_cnd.cn_namelen))
1972 error = -1;
1973 out:
1974 if (!error) {
1975 /*
1976 * The VOP_RENAME function releases all vnode references &
1977 * locks prior to returning so we need to clear the pointers
1978 * to bypass cleanup code later on.
1979 */
1980 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1981 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1982 fromnd.ni_dvp = NULL;
1983 fromnd.ni_vp = NULL;
1984 tond.ni_dvp = NULL;
1985 tond.ni_vp = NULL;
1986 if (error) {
1987 NDFREE(&fromnd, NDF_ONLY_PNBUF);
1988 NDFREE(&tond, NDF_ONLY_PNBUF);
1989 }
1990 } else {
1991 if (error == -1)
1992 error = 0;
1993 }
1994 /* fall through */
1995 out1:
1996 nfsm_reply(2 * NFSX_WCCDATA(v3));
1997 if (v3) {
1998 /* Release existing locks to prevent deadlock. */
1999 if (tond.ni_dvp) {
2000 if (tond.ni_dvp == tond.ni_vp)
2001 vrele(tond.ni_dvp);
2002 else
2003 vput(tond.ni_dvp);
2004 }
2005 if (tond.ni_vp)
2006 vput(tond.ni_vp);
2007 tond.ni_dvp = NULL;
2008 tond.ni_vp = NULL;
2009
2010 if (fdirp) {
2011 vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY);
2012 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred);
2013 VOP_UNLOCK(fdirp, 0);
2014 }
2015 if (tdirp) {
2016 vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY);
2017 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred);
2018 VOP_UNLOCK(tdirp, 0);
2019 }
2020 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2021 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2022 }
2023 error = 0;
2024 /* fall through */
2025
2026 nfsmout:
2027 /*
2028 * Clear out tond related fields
2029 */
2030 if (tond.ni_dvp) {
2031 if (tond.ni_dvp == tond.ni_vp)
2032 vrele(tond.ni_dvp);
2033 else
2034 vput(tond.ni_dvp);
2035 }
2036 if (tond.ni_vp)
2037 vput(tond.ni_vp);
2038 if (tdirp)
2039 vrele(tdirp);
2040 if (tond.ni_startdir)
2041 vrele(tond.ni_startdir);
2042 NDFREE(&tond, NDF_ONLY_PNBUF);
2043 /*
2044 * Clear out fromnd related fields
2045 */
2046 if (fdirp)
2047 vrele(fdirp);
2048 if (fromnd.ni_startdir)
2049 vrele(fromnd.ni_startdir);
2050 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2051 if (fromnd.ni_dvp)
2052 vrele(fromnd.ni_dvp);
2053 if (fromnd.ni_vp)
2054 vrele(fromnd.ni_vp);
2055
2056 vn_finished_write(mp);
2057 VFS_UNLOCK_GIANT(vfslocked);
2058 return (error);
2059 }
2060
2061 /*
2062 * nfs link service
2063 */
2064 int
2065 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2066 struct mbuf **mrq)
2067 {
2068 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2069 struct sockaddr *nam = nfsd->nd_nam;
2070 caddr_t dpos = nfsd->nd_dpos;
2071 struct ucred *cred = nfsd->nd_cr;
2072 struct nameidata nd;
2073 caddr_t bpos;
2074 int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
2075 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2076 struct mbuf *mb, *mreq;
2077 struct vnode *vp = NULL, *xp, *dirp = NULL;
2078 struct vattr dirfor, diraft, at;
2079 nfsfh_t nfh, dnfh;
2080 fhandle_t *fhp, *dfhp;
2081 struct mount *mp = NULL;
2082 int tvfslocked;
2083 int vfslocked;
2084
2085 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2086 ndclear(&nd);
2087 vfslocked = 0;
2088
2089 fhp = &nfh.fh_generic;
2090 dfhp = &dnfh.fh_generic;
2091 nfsm_srvmtofh(fhp);
2092 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2093 error = ESTALE;
2094 goto ereply;
2095 }
2096 vfslocked = VFS_LOCK_GIANT(mp);
2097 (void) vn_start_write(NULL, &mp, V_WAIT);
2098 vfs_rel(mp); /* The write holds a ref. */
2099 nfsm_srvmtofh(dfhp);
2100 nfsm_srvnamesiz(len);
2101
2102 error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
2103 vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
2104 if (error) {
2105 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2106 if (v3) {
2107 nfsm_srvpostop_attr(getret, &at);
2108 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2109 }
2110 vp = NULL;
2111 error = 0;
2112 goto nfsmout;
2113 }
2114 if (v3)
2115 getret = VOP_GETATTR(vp, &at, cred);
2116 if (vp->v_type == VDIR) {
2117 error = EPERM; /* POSIX */
2118 goto out1;
2119 }
2120 VOP_UNLOCK(vp, 0);
2121 nd.ni_cnd.cn_cred = cred;
2122 nd.ni_cnd.cn_nameiop = CREATE;
2123 nd.ni_cnd.cn_flags = LOCKPARENT | MPSAFE | MPSAFE;
2124 error = nfs_namei(&nd, nfsd, dfhp, len, slp, nam, &md, &dpos,
2125 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2126 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2127 if (dirp && !v3) {
2128 vrele(dirp);
2129 dirp = NULL;
2130 }
2131 if (error) {
2132 vrele(vp);
2133 vp = NULL;
2134 goto out2;
2135 }
2136 xp = nd.ni_vp;
2137 if (xp != NULL) {
2138 error = EEXIST;
2139 vrele(vp);
2140 vp = NULL;
2141 goto out2;
2142 }
2143 xp = nd.ni_dvp;
2144 if (vp->v_mount != xp->v_mount) {
2145 error = EXDEV;
2146 vrele(vp);
2147 vp = NULL;
2148 goto out2;
2149 }
2150 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2151 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2152 NDFREE(&nd, NDF_ONLY_PNBUF);
2153 /* fall through */
2154
2155 out1:
2156 if (v3)
2157 getret = VOP_GETATTR(vp, &at, cred);
2158 out2:
2159 if (dirp) {
2160 if (dirp == nd.ni_dvp)
2161 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2162 else {
2163 /* Release existing locks to prevent deadlock. */
2164 if (nd.ni_dvp) {
2165 if (nd.ni_dvp == nd.ni_vp)
2166 vrele(nd.ni_dvp);
2167 else
2168 vput(nd.ni_dvp);
2169 }
2170 if (nd.ni_vp)
2171 vrele(nd.ni_vp);
2172 nd.ni_dvp = NULL;
2173 nd.ni_vp = NULL;
2174
2175 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2176 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2177 VOP_UNLOCK(dirp, 0);
2178 }
2179 }
2180 ereply:
2181 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2182 if (v3) {
2183 nfsm_srvpostop_attr(getret, &at);
2184 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2185 }
2186 error = 0;
2187 /* fall through */
2188
2189 nfsmout:
2190 NDFREE(&nd, NDF_ONLY_PNBUF);
2191 if (vp)
2192 vput(vp);
2193 if (nd.ni_dvp) {
2194 if (nd.ni_dvp == nd.ni_vp)
2195 vrele(nd.ni_dvp);
2196 else
2197 vput(nd.ni_dvp);
2198 }
2199 if (dirp)
2200 vrele(dirp);
2201 if (nd.ni_vp)
2202 vrele(nd.ni_vp);
2203 vn_finished_write(mp);
2204 VFS_UNLOCK_GIANT(vfslocked);
2205 return(error);
2206 }
2207
2208 /*
2209 * nfs symbolic link service
2210 */
2211 int
2212 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2213 struct mbuf **mrq)
2214 {
2215 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2216 struct sockaddr *nam = nfsd->nd_nam;
2217 caddr_t dpos = nfsd->nd_dpos;
2218 struct ucred *cred = nfsd->nd_cr;
2219 struct vattr va, dirfor, diraft;
2220 struct nameidata nd;
2221 struct vattr *vap = &va;
2222 struct nfsv2_sattr *sp;
2223 char *bpos, *pathcp = NULL;
2224 struct uio io;
2225 struct iovec iv;
2226 int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2227 int v3 = (nfsd->nd_flag & ND_NFSV3);
2228 struct mbuf *mb, *mreq;
2229 struct vnode *dirp = NULL;
2230 nfsfh_t nfh;
2231 fhandle_t *fhp;
2232 struct mount *mp = NULL;
2233 int tvfslocked;
2234 int vfslocked;
2235
2236 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2237 ndclear(&nd);
2238 vfslocked = 0;
2239
2240 fhp = &nfh.fh_generic;
2241 nfsm_srvmtofh(fhp);
2242 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2243 error = ESTALE;
2244 goto out;
2245 }
2246 vfslocked = VFS_LOCK_GIANT(mp);
2247 (void) vn_start_write(NULL, &mp, V_WAIT);
2248 vfs_rel(mp); /* The write holds a ref. */
2249 nfsm_srvnamesiz(len);
2250 nd.ni_cnd.cn_cred = cred;
2251 nd.ni_cnd.cn_nameiop = CREATE;
2252 nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART | MPSAFE;
2253 error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2254 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2255 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2256 if (error == 0) {
2257 VATTR_NULL(vap);
2258 if (v3)
2259 nfsm_srvsattr(vap);
2260 nfsm_srvpathsiz(len2);
2261 }
2262 if (dirp && !v3) {
2263 vrele(dirp);
2264 dirp = NULL;
2265 }
2266 if (error)
2267 goto out;
2268 pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
2269 iv.iov_base = pathcp;
2270 iv.iov_len = len2;
2271 io.uio_resid = len2;
2272 io.uio_offset = 0;
2273 io.uio_iov = &iv;
2274 io.uio_iovcnt = 1;
2275 io.uio_segflg = UIO_SYSSPACE;
2276 io.uio_rw = UIO_READ;
2277 io.uio_td = NULL;
2278 nfsm_mtouio(&io, len2);
2279 if (!v3) {
2280 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
2281 vap->va_mode = nfstov_mode(sp->sa_mode);
2282 }
2283 *(pathcp + len2) = '\0';
2284 if (nd.ni_vp) {
2285 error = EEXIST;
2286 goto out;
2287 }
2288
2289 /*
2290 * issue symlink op. SAVESTART is set so the underlying path component
2291 * is only freed by the VOP if an error occurs.
2292 */
2293 if (vap->va_mode == (mode_t)VNOVAL)
2294 vap->va_mode = 0;
2295 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
2296 if (error)
2297 NDFREE(&nd, NDF_ONLY_PNBUF);
2298 else
2299 vput(nd.ni_vp);
2300 nd.ni_vp = NULL;
2301 /*
2302 * releases directory prior to potential lookup op.
2303 */
2304 vput(nd.ni_dvp);
2305 nd.ni_dvp = NULL;
2306
2307 if (error == 0) {
2308 if (v3) {
2309 /*
2310 * Issue lookup. Leave SAVESTART set so we can easily free
2311 * the name buffer later on.
2312 *
2313 * since LOCKPARENT is not set, ni_dvp will be garbage on
2314 * return whether an error occurs or not.
2315 */
2316 nd.ni_cnd.cn_nameiop = LOOKUP;
2317 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
2318 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
2319 nd.ni_cnd.cn_thread = curthread;
2320 nd.ni_cnd.cn_cred = cred;
2321 tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
2322 if (tvfslocked)
2323 nd.ni_cnd.cn_flags |= GIANTHELD;
2324 error = lookup(&nd);
2325 nd.ni_dvp = NULL;
2326 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2327 nd.ni_cnd.cn_flags &= ~GIANTHELD;
2328
2329 if (error == 0) {
2330 bzero((caddr_t)fhp, sizeof(nfh));
2331 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2332 error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2333 if (!error)
2334 error = VOP_GETATTR(nd.ni_vp, vap, cred);
2335 vput(nd.ni_vp);
2336 nd.ni_vp = NULL;
2337 }
2338 }
2339 }
2340 out:
2341 /*
2342 * These releases aren't strictly required, does even doing them
2343 * make any sense? XXX can nfsm_reply() block?
2344 */
2345 if (pathcp) {
2346 free(pathcp, M_TEMP);
2347 pathcp = NULL;
2348 }
2349 if (dirp) {
2350 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2351 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2352 VOP_UNLOCK(dirp, 0);
2353 }
2354 if (nd.ni_startdir) {
2355 vrele(nd.ni_startdir);
2356 nd.ni_startdir = NULL;
2357 }
2358 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2359 if (v3) {
2360 if (!error) {
2361 nfsm_srvpostop_fh(fhp);
2362 nfsm_srvpostop_attr(0, vap);
2363 }
2364 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2365 }
2366 error = 0;
2367 /* fall through */
2368
2369 nfsmout:
2370 NDFREE(&nd, NDF_ONLY_PNBUF);
2371 if (nd.ni_dvp) {
2372 if (nd.ni_dvp == nd.ni_vp)
2373 vrele(nd.ni_dvp);
2374 else
2375 vput(nd.ni_dvp);
2376 }
2377 if (nd.ni_vp)
2378 vrele(nd.ni_vp);
2379 if (nd.ni_startdir)
2380 vrele(nd.ni_startdir);
2381 if (dirp)
2382 vrele(dirp);
2383 if (pathcp)
2384 free(pathcp, M_TEMP);
2385
2386 vn_finished_write(mp);
2387 VFS_UNLOCK_GIANT(vfslocked);
2388 return (error);
2389 }
2390
2391 /*
2392 * nfs mkdir service
2393 */
2394 int
2395 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2396 struct mbuf **mrq)
2397 {
2398 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2399 struct sockaddr *nam = nfsd->nd_nam;
2400 caddr_t dpos = nfsd->nd_dpos;
2401 struct ucred *cred = nfsd->nd_cr;
2402 struct vattr va, dirfor, diraft;
2403 struct vattr *vap = &va;
2404 struct nfs_fattr *fp;
2405 struct nameidata nd;
2406 u_int32_t *tl;
2407 caddr_t bpos;
2408 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2409 int v3 = (nfsd->nd_flag & ND_NFSV3);
2410 struct mbuf *mb, *mreq;
2411 struct vnode *dirp = NULL;
2412 int vpexcl = 0;
2413 nfsfh_t nfh;
2414 fhandle_t *fhp;
2415 struct mount *mp = NULL;
2416 int vfslocked;
2417
2418 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2419 ndclear(&nd);
2420 vfslocked = 0;
2421
2422 fhp = &nfh.fh_generic;
2423 nfsm_srvmtofh(fhp);
2424 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2425 error = ESTALE;
2426 goto out;
2427 }
2428 vfslocked = VFS_LOCK_GIANT(mp);
2429 (void) vn_start_write(NULL, &mp, V_WAIT);
2430 vfs_rel(mp); /* The write holds a ref. */
2431 nfsm_srvnamesiz(len);
2432 nd.ni_cnd.cn_cred = cred;
2433 nd.ni_cnd.cn_nameiop = CREATE;
2434 nd.ni_cnd.cn_flags = LOCKPARENT | MPSAFE;
2435
2436 error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2437 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2438 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2439 if (dirp && !v3) {
2440 vrele(dirp);
2441 dirp = NULL;
2442 }
2443 if (error) {
2444 nfsm_reply(NFSX_WCCDATA(v3));
2445 if (v3)
2446 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2447 error = 0;
2448 goto nfsmout;
2449 }
2450 VATTR_NULL(vap);
2451 if (v3) {
2452 nfsm_srvsattr(vap);
2453 } else {
2454 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
2455 vap->va_mode = nfstov_mode(*tl++);
2456 }
2457
2458 /*
2459 * At this point nd.ni_dvp is referenced and exclusively locked and
2460 * nd.ni_vp, if it exists, is referenced but not locked.
2461 */
2462
2463 vap->va_type = VDIR;
2464 if (nd.ni_vp != NULL) {
2465 NDFREE(&nd, NDF_ONLY_PNBUF);
2466 error = EEXIST;
2467 goto out;
2468 }
2469
2470 /*
2471 * Issue mkdir op. Since SAVESTART is not set, the pathname
2472 * component is freed by the VOP call. This will fill-in
2473 * nd.ni_vp, reference, and exclusively lock it.
2474 */
2475 if (vap->va_mode == (mode_t)VNOVAL)
2476 vap->va_mode = 0;
2477 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2478 NDFREE(&nd, NDF_ONLY_PNBUF);
2479 vpexcl = 1;
2480
2481 vput(nd.ni_dvp);
2482 nd.ni_dvp = NULL;
2483
2484 if (!error) {
2485 bzero((caddr_t)fhp, sizeof(nfh));
2486 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2487 error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2488 if (!error)
2489 error = VOP_GETATTR(nd.ni_vp, vap, cred);
2490 }
2491 out:
2492 if (dirp) {
2493 if (dirp == nd.ni_dvp) {
2494 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2495 } else {
2496 /* Release existing locks to prevent deadlock. */
2497 if (nd.ni_dvp) {
2498 NDFREE(&nd, NDF_ONLY_PNBUF);
2499 if (nd.ni_dvp == nd.ni_vp && vpexcl)
2500 vrele(nd.ni_dvp);
2501 else
2502 vput(nd.ni_dvp);
2503 }
2504 if (nd.ni_vp) {
2505 if (vpexcl)
2506 vput(nd.ni_vp);
2507 else
2508 vrele(nd.ni_vp);
2509 }
2510 nd.ni_dvp = NULL;
2511 nd.ni_vp = NULL;
2512 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2513 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2514 VOP_UNLOCK(dirp, 0);
2515 }
2516 }
2517 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2518 if (v3) {
2519 if (!error) {
2520 nfsm_srvpostop_fh(fhp);
2521 nfsm_srvpostop_attr(0, vap);
2522 }
2523 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2524 } else if (!error) {
2525 /* v2 non-error case. */
2526 nfsm_srvfhtom(fhp, v3);
2527 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
2528 nfsm_srvfillattr(vap, fp);
2529 }
2530 error = 0;
2531 /* fall through */
2532
2533 nfsmout:
2534 if (nd.ni_dvp) {
2535 NDFREE(&nd, NDF_ONLY_PNBUF);
2536 if (nd.ni_dvp == nd.ni_vp && vpexcl)
2537 vrele(nd.ni_dvp);
2538 else
2539 vput(nd.ni_dvp);
2540 }
2541 if (nd.ni_vp) {
2542 if (vpexcl)
2543 vput(nd.ni_vp);
2544 else
2545 vrele(nd.ni_vp);
2546 }
2547 if (dirp)
2548 vrele(dirp);
2549 vn_finished_write(mp);
2550 VFS_UNLOCK_GIANT(vfslocked);
2551 return (error);
2552 }
2553
2554 /*
2555 * nfs rmdir service
2556 */
2557 int
2558 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2559 struct mbuf **mrq)
2560 {
2561 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2562 struct sockaddr *nam = nfsd->nd_nam;
2563 caddr_t dpos = nfsd->nd_dpos;
2564 struct ucred *cred = nfsd->nd_cr;
2565 caddr_t bpos;
2566 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2567 int v3 = (nfsd->nd_flag & ND_NFSV3);
2568 struct mbuf *mb, *mreq;
2569 struct vnode *vp, *dirp = NULL;
2570 struct vattr dirfor, diraft;
2571 nfsfh_t nfh;
2572 fhandle_t *fhp;
2573 struct nameidata nd;
2574 struct mount *mp = NULL;
2575 int vfslocked;
2576
2577 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2578 ndclear(&nd);
2579 vfslocked = 0;
2580
2581 fhp = &nfh.fh_generic;
2582 nfsm_srvmtofh(fhp);
2583 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2584 error = ESTALE;
2585 goto out;
2586 }
2587 vfslocked = VFS_LOCK_GIANT(mp);
2588 (void) vn_start_write(NULL, &mp, V_WAIT);
2589 vfs_rel(mp); /* The write holds a ref. */
2590 nfsm_srvnamesiz(len);
2591 nd.ni_cnd.cn_cred = cred;
2592 nd.ni_cnd.cn_nameiop = DELETE;
2593 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | MPSAFE;
2594 error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2595 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2596 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2597 if (dirp && !v3) {
2598 vrele(dirp);
2599 dirp = NULL;
2600 }
2601 if (error) {
2602 nfsm_reply(NFSX_WCCDATA(v3));
2603 if (v3)
2604 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2605 error = 0;
2606 goto nfsmout;
2607 }
2608 vp = nd.ni_vp;
2609 if (vp->v_type != VDIR) {
2610 error = ENOTDIR;
2611 goto out;
2612 }
2613 /*
2614 * No rmdir "." please.
2615 */
2616 if (nd.ni_dvp == vp) {
2617 error = EINVAL;
2618 goto out;
2619 }
2620 /*
2621 * The root of a mounted filesystem cannot be deleted.
2622 */
2623 if (vp->v_vflag & VV_ROOT)
2624 error = EBUSY;
2625 out:
2626 /*
2627 * Issue or abort op. Since SAVESTART is not set, path name
2628 * component is freed by the VOP after either.
2629 */
2630 if (!error)
2631 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2632 NDFREE(&nd, NDF_ONLY_PNBUF);
2633
2634 if (dirp) {
2635 if (dirp == nd.ni_dvp)
2636 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2637 else {
2638 /* Release existing locks to prevent deadlock. */
2639 if (nd.ni_dvp) {
2640 if (nd.ni_dvp == nd.ni_vp)
2641 vrele(nd.ni_dvp);
2642 else
2643 vput(nd.ni_dvp);
2644 }
2645 if (nd.ni_vp)
2646 vput(nd.ni_vp);
2647 nd.ni_dvp = NULL;
2648 nd.ni_vp = NULL;
2649 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2650 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2651 VOP_UNLOCK(dirp, 0);
2652 }
2653 }
2654 nfsm_reply(NFSX_WCCDATA(v3));
2655 error = 0;
2656 if (v3)
2657 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2658 /* fall through */
2659
2660 nfsmout:
2661 NDFREE(&nd, NDF_ONLY_PNBUF);
2662 if (nd.ni_dvp) {
2663 if (nd.ni_dvp == nd.ni_vp)
2664 vrele(nd.ni_dvp);
2665 else
2666 vput(nd.ni_dvp);
2667 }
2668 if (nd.ni_vp)
2669 vput(nd.ni_vp);
2670 if (dirp)
2671 vrele(dirp);
2672
2673 vn_finished_write(mp);
2674 VFS_UNLOCK_GIANT(vfslocked);
2675 return(error);
2676 }
2677
2678 /*
2679 * nfs readdir service
2680 * - mallocs what it thinks is enough to read
2681 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2682 * - calls VOP_READDIR()
2683 * - loops around building the reply
2684 * if the output generated exceeds count break out of loop
2685 * The nfsm_clget macro is used here so that the reply will be packed
2686 * tightly in mbuf clusters.
2687 * - it only knows that it has encountered eof when the VOP_READDIR()
2688 * reads nothing
2689 * - as such one readdir rpc will return eof false although you are there
2690 * and then the next will return eof
2691 * - it trims out records with d_fileno == 0
2692 * this doesn't matter for Unix clients, but they might confuse clients
2693 * for other os'.
2694 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2695 * than requested, but this may not apply to all filesystems. For
2696 * example, client NFS does not { although it is never remote mounted
2697 * anyhow }
2698 * The alternate call nfsrv_readdirplus() does lookups as well.
2699 * PS: The NFS protocol spec. does not clarify what the "count" byte
2700 * argument is a count of.. just name strings and file id's or the
2701 * entire reply rpc or ...
2702 * I tried just file name and id sizes and it confused the Sun client,
2703 * so I am using the full rpc size now. The "paranoia.." comment refers
2704 * to including the status longwords that are not a part of the dir.
2705 * "entry" structures, but are in the rpc.
2706 */
2707 struct flrep {
2708 nfsuint64 fl_off;
2709 u_int32_t fl_postopok;
2710 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2711 u_int32_t fl_fhok;
2712 u_int32_t fl_fhsize;
2713 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2714 };
2715
2716 int
2717 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2718 struct mbuf **mrq)
2719 {
2720 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2721 struct sockaddr *nam = nfsd->nd_nam;
2722 caddr_t dpos = nfsd->nd_dpos;
2723 struct ucred *cred = nfsd->nd_cr;
2724 char *bp, *be;
2725 struct mbuf *mp;
2726 struct dirent *dp;
2727 caddr_t cp;
2728 u_int32_t *tl;
2729 caddr_t bpos;
2730 struct mbuf *mb, *mreq;
2731 char *cpos, *cend, *rbuf;
2732 struct vnode *vp = NULL;
2733 struct vattr at;
2734 nfsfh_t nfh;
2735 fhandle_t *fhp;
2736 struct uio io;
2737 struct iovec iv;
2738 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2739 int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
2740 int v3 = (nfsd->nd_flag & ND_NFSV3);
2741 u_quad_t off, toff, verf;
2742 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
2743 int vfslocked, not_zfs;
2744
2745 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2746 vfslocked = 0;
2747 fhp = &nfh.fh_generic;
2748 nfsm_srvmtofh(fhp);
2749 if (v3) {
2750 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
2751 toff = fxdr_hyper(tl);
2752 tl += 2;
2753 verf = fxdr_hyper(tl);
2754 tl += 2;
2755 } else {
2756 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
2757 toff = fxdr_unsigned(u_quad_t, *tl++);
2758 verf = 0; /* shut up gcc */
2759 }
2760 off = toff;
2761 cnt = fxdr_unsigned(int, *tl);
2762 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2763 xfer = NFS_SRVMAXDATA(nfsd);
2764 if (cnt > xfer)
2765 cnt = xfer;
2766 if (siz > xfer)
2767 siz = xfer;
2768 fullsiz = siz;
2769 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
2770 if (!error && vp->v_type != VDIR) {
2771 error = ENOTDIR;
2772 vput(vp);
2773 vp = NULL;
2774 }
2775 if (error) {
2776 nfsm_reply(NFSX_UNSIGNED);
2777 if (v3)
2778 nfsm_srvpostop_attr(getret, &at);
2779 error = 0;
2780 goto nfsmout;
2781 }
2782
2783 /*
2784 * Obtain lock on vnode for this section of the code
2785 */
2786 if (v3) {
2787 error = getret = VOP_GETATTR(vp, &at, cred);
2788 #if 0
2789 /*
2790 * XXX This check may be too strict for Solaris 2.5 clients.
2791 */
2792 if (!error && toff && verf && verf != at.va_filerev)
2793 error = NFSERR_BAD_COOKIE;
2794 #endif
2795 }
2796 if (!error)
2797 error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
2798 if (error) {
2799 vput(vp);
2800 vp = NULL;
2801 nfsm_reply(NFSX_POSTOPATTR(v3));
2802 if (v3)
2803 nfsm_srvpostop_attr(getret, &at);
2804 error = 0;
2805 goto nfsmout;
2806 }
2807 not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs") != 0;
2808 VOP_UNLOCK(vp, 0);
2809
2810 /*
2811 * end section. Allocate rbuf and continue
2812 */
2813 rbuf = malloc(siz, M_TEMP, M_WAITOK);
2814 again:
2815 iv.iov_base = rbuf;
2816 iv.iov_len = fullsiz;
2817 io.uio_iov = &iv;
2818 io.uio_iovcnt = 1;
2819 io.uio_offset = (off_t)off;
2820 io.uio_resid = fullsiz;
2821 io.uio_segflg = UIO_SYSSPACE;
2822 io.uio_rw = UIO_READ;
2823 io.uio_td = NULL;
2824 eofflag = 0;
2825 if (cookies) {
2826 free((caddr_t)cookies, M_TEMP);
2827 cookies = NULL;
2828 }
2829 vn_lock(vp, LK_SHARED | LK_RETRY);
2830 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
2831 off = (off_t)io.uio_offset;
2832 if (!cookies && !error)
2833 error = NFSERR_PERM;
2834 if (v3) {
2835 getret = VOP_GETATTR(vp, &at, cred);
2836 if (!error)
2837 error = getret;
2838 }
2839 VOP_UNLOCK(vp, 0);
2840 if (error) {
2841 vrele(vp);
2842 vp = NULL;
2843 free((caddr_t)rbuf, M_TEMP);
2844 if (cookies)
2845 free((caddr_t)cookies, M_TEMP);
2846 nfsm_reply(NFSX_POSTOPATTR(v3));
2847 if (v3)
2848 nfsm_srvpostop_attr(getret, &at);
2849 error = 0;
2850 goto nfsmout;
2851 }
2852 if (io.uio_resid) {
2853 siz -= io.uio_resid;
2854
2855 /*
2856 * If nothing read, return eof
2857 * rpc reply
2858 */
2859 if (siz == 0) {
2860 vrele(vp);
2861 vp = NULL;
2862 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2863 2 * NFSX_UNSIGNED);
2864 if (v3) {
2865 nfsm_srvpostop_attr(getret, &at);
2866 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
2867 txdr_hyper(at.va_filerev, tl);
2868 tl += 2;
2869 } else
2870 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
2871 *tl++ = nfsrv_nfs_false;
2872 *tl = nfsrv_nfs_true;
2873 free((caddr_t)rbuf, M_TEMP);
2874 free((caddr_t)cookies, M_TEMP);
2875 error = 0;
2876 goto nfsmout;
2877 }
2878 }
2879
2880 /*
2881 * Check for degenerate cases of nothing useful read.
2882 * If so go try again
2883 */
2884 cpos = rbuf;
2885 cend = rbuf + siz;
2886 dp = (struct dirent *)cpos;
2887 cookiep = cookies;
2888 /*
2889 * For some reason FreeBSD's ufs_readdir() chooses to back the
2890 * directory offset up to a block boundary, so it is necessary to
2891 * skip over the records that precede the requested offset. This
2892 * requires the assumption that file offset cookies monotonically
2893 * increase.
2894 * Since the offset cookies don't monotonically increase for ZFS,
2895 * this is not done when ZFS is the file system.
2896 */
2897 while (cpos < cend && ncookies > 0 &&
2898 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
2899 (not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff))) {
2900 cpos += dp->d_reclen;
2901 dp = (struct dirent *)cpos;
2902 cookiep++;
2903 ncookies--;
2904 }
2905 if (cpos >= cend || ncookies == 0) {
2906 toff = off;
2907 siz = fullsiz;
2908 goto again;
2909 }
2910
2911 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
2912 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
2913 if (v3) {
2914 nfsm_srvpostop_attr(getret, &at);
2915 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
2916 txdr_hyper(at.va_filerev, tl);
2917 }
2918 mp = mb;
2919 bp = bpos;
2920 be = bp + M_TRAILINGSPACE(mp);
2921
2922 /* Loop through the records and build reply */
2923 while (cpos < cend && ncookies > 0) {
2924 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
2925 nlen = dp->d_namlen;
2926 rem = nfsm_rndup(nlen) - nlen;
2927 len += (4 * NFSX_UNSIGNED + nlen + rem);
2928 if (v3)
2929 len += 2 * NFSX_UNSIGNED;
2930 if (len > cnt) {
2931 eofflag = 0;
2932 break;
2933 }
2934 /*
2935 * Build the directory record xdr from
2936 * the dirent entry.
2937 */
2938 nfsm_clget;
2939 *tl = nfsrv_nfs_true;
2940 bp += NFSX_UNSIGNED;
2941 if (v3) {
2942 nfsm_clget;
2943 *tl = 0;
2944 bp += NFSX_UNSIGNED;
2945 }
2946 nfsm_clget;
2947 *tl = txdr_unsigned(dp->d_fileno);
2948 bp += NFSX_UNSIGNED;
2949 nfsm_clget;
2950 *tl = txdr_unsigned(nlen);
2951 bp += NFSX_UNSIGNED;
2952
2953 /* And loop around copying the name */
2954 xfer = nlen;
2955 cp = dp->d_name;
2956 while (xfer > 0) {
2957 nfsm_clget;
2958 if ((bp+xfer) > be)
2959 tsiz = be-bp;
2960 else
2961 tsiz = xfer;
2962 bcopy(cp, bp, tsiz);
2963 bp += tsiz;
2964 xfer -= tsiz;
2965 if (xfer > 0)
2966 cp += tsiz;
2967 }
2968 /* And null pad to an int32_t boundary. */
2969 for (i = 0; i < rem; i++)
2970 *bp++ = '\0';
2971 nfsm_clget;
2972
2973 /* Finish off the record */
2974 if (v3) {
2975 *tl = 0;
2976 bp += NFSX_UNSIGNED;
2977 nfsm_clget;
2978 }
2979 *tl = txdr_unsigned(*cookiep);
2980 bp += NFSX_UNSIGNED;
2981 }
2982 cpos += dp->d_reclen;
2983 dp = (struct dirent *)cpos;
2984 cookiep++;
2985 ncookies--;
2986 }
2987 vrele(vp);
2988 vp = NULL;
2989 nfsm_clget;
2990 *tl = nfsrv_nfs_false;
2991 bp += NFSX_UNSIGNED;
2992 nfsm_clget;
2993 if (eofflag)
2994 *tl = nfsrv_nfs_true;
2995 else
2996 *tl = nfsrv_nfs_false;
2997 bp += NFSX_UNSIGNED;
2998 if (mp != mb) {
2999 if (bp < be)
3000 mp->m_len = bp - mtod(mp, caddr_t);
3001 } else
3002 mp->m_len += bp - bpos;
3003 free((caddr_t)rbuf, M_TEMP);
3004 free((caddr_t)cookies, M_TEMP);
3005
3006 nfsmout:
3007 if (vp)
3008 vrele(vp);
3009 VFS_UNLOCK_GIANT(vfslocked);
3010 return(error);
3011 }
3012
3013 int
3014 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3015 struct mbuf **mrq)
3016 {
3017 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3018 struct sockaddr *nam = nfsd->nd_nam;
3019 caddr_t dpos = nfsd->nd_dpos;
3020 struct ucred *cred = nfsd->nd_cr;
3021 char *bp, *be;
3022 struct mbuf *mp;
3023 struct dirent *dp;
3024 caddr_t cp;
3025 u_int32_t *tl;
3026 caddr_t bpos;
3027 struct mbuf *mb, *mreq;
3028 char *cpos, *cend, *rbuf;
3029 struct vnode *vp = NULL, *nvp;
3030 struct flrep fl;
3031 nfsfh_t nfh;
3032 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3033 struct uio io;
3034 struct iovec iv;
3035 struct vattr va, at, *vap = &va;
3036 struct nfs_fattr *fp;
3037 int len, nlen, rem, xfer, tsiz, i, error = 0, error1, getret = 1;
3038 int vp_locked;
3039 int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
3040 u_quad_t off, toff, verf;
3041 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3042 int v3 = (nfsd->nd_flag & ND_NFSV3);
3043 int usevget = 1, vfslocked;
3044 struct componentname cn;
3045 struct mount *mntp = NULL;
3046 int not_zfs;
3047
3048 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3049 vfslocked = 0;
3050 vp_locked = 0;
3051 if (!v3)
3052 panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
3053 fhp = &nfh.fh_generic;
3054 nfsm_srvmtofh(fhp);
3055 tl = nfsm_dissect_nonblock(u_int32_t *, 6 * NFSX_UNSIGNED);
3056 toff = fxdr_hyper(tl);
3057 tl += 2;
3058 verf = fxdr_hyper(tl);
3059 tl += 2;
3060 siz = fxdr_unsigned(int, *tl++);
3061 cnt = fxdr_unsigned(int, *tl);
3062 off = toff;
3063 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3064 xfer = NFS_SRVMAXDATA(nfsd);
3065 if (cnt > xfer)
3066 cnt = xfer;
3067 if (siz > xfer)
3068 siz = xfer;
3069 fullsiz = siz;
3070 error = nfsrv_fhtovp(fhp, NFSRV_FLAG_BUSY, &vp, &vfslocked, nfsd, slp,
3071 nam, &rdonly);
3072 if (!error) {
3073 vp_locked = 1;
3074 mntp = vp->v_mount;
3075 if (vp->v_type != VDIR) {
3076 error = ENOTDIR;
3077 vput(vp);
3078 vp = NULL;
3079 vp_locked = 0;
3080 }
3081 }
3082 if (error) {
3083 nfsm_reply(NFSX_UNSIGNED);
3084 nfsm_srvpostop_attr(getret, &at);
3085 error = 0;
3086 goto nfsmout;
3087 }
3088 error = getret = VOP_GETATTR(vp, &at, cred);
3089 #if 0
3090 /*
3091 * XXX This check may be too strict for Solaris 2.5 clients.
3092 */
3093 if (!error && toff && verf && verf != at.va_filerev)
3094 error = NFSERR_BAD_COOKIE;
3095 #endif
3096 if (!error)
3097 error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
3098 if (error) {
3099 vput(vp);
3100 vp_locked = 0;
3101 vp = NULL;
3102 nfsm_reply(NFSX_V3POSTOPATTR);
3103 nfsm_srvpostop_attr(getret, &at);
3104 error = 0;
3105 goto nfsmout;
3106 }
3107 not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs") != 0;
3108 VOP_UNLOCK(vp, 0);
3109 vp_locked = 0;
3110 rbuf = malloc(siz, M_TEMP, M_WAITOK);
3111 again:
3112 iv.iov_base = rbuf;
3113 iv.iov_len = fullsiz;
3114 io.uio_iov = &iv;
3115 io.uio_iovcnt = 1;
3116 io.uio_offset = (off_t)off;
3117 io.uio_resid = fullsiz;
3118 io.uio_segflg = UIO_SYSSPACE;
3119 io.uio_rw = UIO_READ;
3120 io.uio_td = NULL;
3121 eofflag = 0;
3122 vp_locked = 1;
3123 if (cookies) {
3124 free((caddr_t)cookies, M_TEMP);
3125 cookies = NULL;
3126 }
3127 vn_lock(vp, LK_SHARED | LK_RETRY);
3128 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3129 off = (u_quad_t)io.uio_offset;
3130 getret = VOP_GETATTR(vp, &at, cred);
3131 VOP_UNLOCK(vp, 0);
3132 vp_locked = 0;
3133 if (!cookies && !error)
3134 error = NFSERR_PERM;
3135 if (!error)
3136 error = getret;
3137 if (error) {
3138 vrele(vp);
3139 vp = NULL;
3140 if (cookies)
3141 free((caddr_t)cookies, M_TEMP);
3142 free((caddr_t)rbuf, M_TEMP);
3143 nfsm_reply(NFSX_V3POSTOPATTR);
3144 nfsm_srvpostop_attr(getret, &at);
3145 error = 0;
3146 goto nfsmout;
3147 }
3148 if (io.uio_resid) {
3149 siz -= io.uio_resid;
3150
3151 /*
3152 * If nothing read, return eof
3153 * rpc reply
3154 */
3155 if (siz == 0) {
3156 vrele(vp);
3157 vp = NULL;
3158 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3159 2 * NFSX_UNSIGNED);
3160 nfsm_srvpostop_attr(getret, &at);
3161 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3162 txdr_hyper(at.va_filerev, tl);
3163 tl += 2;
3164 *tl++ = nfsrv_nfs_false;
3165 *tl = nfsrv_nfs_true;
3166 free((caddr_t)cookies, M_TEMP);
3167 free((caddr_t)rbuf, M_TEMP);
3168 error = 0;
3169 goto nfsmout;
3170 }
3171 }
3172
3173 /*
3174 * Check for degenerate cases of nothing useful read.
3175 * If so go try again
3176 */
3177 cpos = rbuf;
3178 cend = rbuf + siz;
3179 dp = (struct dirent *)cpos;
3180 cookiep = cookies;
3181 /*
3182 * For some reason FreeBSD's ufs_readdir() chooses to back the
3183 * directory offset up to a block boundary, so it is necessary to
3184 * skip over the records that precede the requested offset. This
3185 * requires the assumption that file offset cookies monotonically
3186 * increase.
3187 * Since the offset cookies don't monotonically increase for ZFS,
3188 * this is not done when ZFS is the file system.
3189 */
3190 while (cpos < cend && ncookies > 0 &&
3191 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3192 (not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff))) {
3193 cpos += dp->d_reclen;
3194 dp = (struct dirent *)cpos;
3195 cookiep++;
3196 ncookies--;
3197 }
3198 if (cpos >= cend || ncookies == 0) {
3199 toff = off;
3200 siz = fullsiz;
3201 goto again;
3202 }
3203
3204 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3205 2 * NFSX_UNSIGNED;
3206 nfsm_reply(cnt);
3207 nfsm_srvpostop_attr(getret, &at);
3208 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3209 txdr_hyper(at.va_filerev, tl);
3210 mp = mb;
3211 bp = bpos;
3212 be = bp + M_TRAILINGSPACE(mp);
3213
3214 /* Loop through the records and build reply */
3215 while (cpos < cend && ncookies > 0) {
3216 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3217 nlen = dp->d_namlen;
3218 rem = nfsm_rndup(nlen)-nlen;
3219
3220 if (usevget) {
3221 /*
3222 * For readdir_and_lookup get the vnode using
3223 * the file number.
3224 */
3225 error = VFS_VGET(mntp, dp->d_fileno, LK_SHARED,
3226 &nvp);
3227 if (error != 0 && error != EOPNOTSUPP) {
3228 error = 0;
3229 goto invalid;
3230 } else if (error == EOPNOTSUPP) {
3231 /*
3232 * VFS_VGET() not supported?
3233 * Let's switch to VOP_LOOKUP().
3234 */
3235 error = 0;
3236 usevget = 0;
3237 cn.cn_nameiop = LOOKUP;
3238 cn.cn_flags = ISLASTCN | NOFOLLOW | \
3239 LOCKSHARED | LOCKLEAF | MPSAFE;
3240 cn.cn_lkflags = LK_SHARED | LK_RETRY;
3241 cn.cn_cred = cred;
3242 cn.cn_thread = curthread;
3243 }
3244 }
3245 if (!usevget) {
3246 cn.cn_nameptr = dp->d_name;
3247 cn.cn_namelen = dp->d_namlen;
3248 if (dp->d_namlen == 2 &&
3249 dp->d_name[0] == '.' &&
3250 dp->d_name[1] == '.') {
3251 cn.cn_flags |= ISDOTDOT;
3252 } else {
3253 cn.cn_flags &= ~ISDOTDOT;
3254 }
3255 if (!vp_locked) {
3256 vn_lock(vp, LK_SHARED | LK_RETRY);
3257 vp_locked = 1;
3258 }
3259 if ((vp->v_vflag & VV_ROOT) != 0 &&
3260 (cn.cn_flags & ISDOTDOT) != 0) {
3261 vref(vp);
3262 nvp = vp;
3263 } else if (VOP_LOOKUP(vp, &nvp, &cn) != 0)
3264 goto invalid;
3265 }
3266
3267 bzero((caddr_t)nfhp, NFSX_V3FH);
3268 nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid;
3269 if ((error1 = VOP_VPTOFH(nvp, &nfhp->fh_fid)) == 0)
3270 error1 = VOP_GETATTR(nvp, vap, cred);
3271 if (!usevget && vp == nvp)
3272 vunref(nvp);
3273 else
3274 vput(nvp);
3275 nvp = NULL;
3276 if (error1 != 0)
3277 goto invalid;
3278
3279 /*
3280 * If either the dircount or maxcount will be
3281 * exceeded, get out now. Both of these lengths
3282 * are calculated conservatively, including all
3283 * XDR overheads.
3284 */
3285 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3286 NFSX_V3POSTOPATTR);
3287 dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3288 if (len > cnt || dirlen > fullsiz) {
3289 eofflag = 0;
3290 break;
3291 }
3292
3293 /*
3294 * Build the directory record xdr from
3295 * the dirent entry.
3296 */
3297 fp = (struct nfs_fattr *)&fl.fl_fattr;
3298 nfsm_srvfillattr(vap, fp);
3299 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3300 fl.fl_fhok = nfsrv_nfs_true;
3301 fl.fl_postopok = nfsrv_nfs_true;
3302 fl.fl_off.nfsuquad[0] = 0;
3303 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3304
3305 nfsm_clget;
3306 *tl = nfsrv_nfs_true;
3307 bp += NFSX_UNSIGNED;
3308 nfsm_clget;
3309 *tl = 0;
3310 bp += NFSX_UNSIGNED;
3311 nfsm_clget;
3312 *tl = txdr_unsigned(dp->d_fileno);
3313 bp += NFSX_UNSIGNED;
3314 nfsm_clget;
3315 *tl = txdr_unsigned(nlen);
3316 bp += NFSX_UNSIGNED;
3317
3318 /* And loop around copying the name */
3319 xfer = nlen;
3320 cp = dp->d_name;
3321 while (xfer > 0) {
3322 nfsm_clget;
3323 if ((bp + xfer) > be)
3324 tsiz = be - bp;
3325 else
3326 tsiz = xfer;
3327 bcopy(cp, bp, tsiz);
3328 bp += tsiz;
3329 xfer -= tsiz;
3330 if (xfer > 0)
3331 cp += tsiz;
3332 }
3333 /* And null pad to an int32_t boundary. */
3334 for (i = 0; i < rem; i++)
3335 *bp++ = '\0';
3336
3337 /*
3338 * Now copy the flrep structure out.
3339 */
3340 xfer = sizeof (struct flrep);
3341 cp = (caddr_t)&fl;
3342 while (xfer > 0) {
3343 nfsm_clget;
3344 if ((bp + xfer) > be)
3345 tsiz = be - bp;
3346 else
3347 tsiz = xfer;
3348 bcopy(cp, bp, tsiz);
3349 bp += tsiz;
3350 xfer -= tsiz;
3351 if (xfer > 0)
3352 cp += tsiz;
3353 }
3354 }
3355 invalid:
3356 cpos += dp->d_reclen;
3357 dp = (struct dirent *)cpos;
3358 cookiep++;
3359 ncookies--;
3360 }
3361 if (!usevget && vp_locked)
3362 vput(vp);
3363 else
3364 vrele(vp);
3365 vp = NULL;
3366 nfsm_clget;
3367 *tl = nfsrv_nfs_false;
3368 bp += NFSX_UNSIGNED;
3369 nfsm_clget;
3370 if (eofflag)
3371 *tl = nfsrv_nfs_true;
3372 else
3373 *tl = nfsrv_nfs_false;
3374 bp += NFSX_UNSIGNED;
3375 if (mp != mb) {
3376 if (bp < be)
3377 mp->m_len = bp - mtod(mp, caddr_t);
3378 } else
3379 mp->m_len += bp - bpos;
3380 free((caddr_t)cookies, M_TEMP);
3381 free((caddr_t)rbuf, M_TEMP);
3382 nfsmout:
3383 if (vp)
3384 vrele(vp);
3385 if (mntp)
3386 vfs_unbusy(mntp);
3387 VFS_UNLOCK_GIANT(vfslocked);
3388 return(error);
3389 }
3390
3391 /*
3392 * nfs commit service
3393 */
3394 int
3395 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3396 struct mbuf **mrq)
3397 {
3398 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3399 struct sockaddr *nam = nfsd->nd_nam;
3400 caddr_t dpos = nfsd->nd_dpos;
3401 struct ucred *cred = nfsd->nd_cr;
3402 struct vattr bfor, aft;
3403 struct vnode *vp = NULL;
3404 nfsfh_t nfh;
3405 fhandle_t *fhp;
3406 u_int32_t *tl;
3407 caddr_t bpos;
3408 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
3409 struct mbuf *mb, *mreq;
3410 u_quad_t off;
3411 struct mount *mp = NULL;
3412 int v3 = (nfsd->nd_flag & ND_NFSV3);
3413 int tvfslocked;
3414 int vfslocked;
3415
3416 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3417 vfslocked = 0;
3418 if (!v3)
3419 panic("nfsrv_commit: v3 proc called on a v2 connection");
3420 fhp = &nfh.fh_generic;
3421 nfsm_srvmtofh(fhp);
3422 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3423 error = ESTALE;
3424 goto ereply;
3425 }
3426 vfslocked = VFS_LOCK_GIANT(mp);
3427 (void) vn_start_write(NULL, &mp, V_WAIT);
3428 vfs_rel(mp); /* The write holds a ref. */
3429 tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
3430
3431 /*
3432 * XXX At this time VOP_FSYNC() does not accept offset and byte
3433 * count parameters, so these arguments are useless (someday maybe).
3434 */
3435 off = fxdr_hyper(tl);
3436 tl += 2;
3437 cnt = fxdr_unsigned(int, *tl);
3438 error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
3439 vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
3440 if (error) {
3441 nfsm_reply(2 * NFSX_UNSIGNED);
3442 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3443 error = 0;
3444 goto nfsmout;
3445 }
3446 for_ret = VOP_GETATTR(vp, &bfor, cred);
3447
3448 if (cnt > MAX_COMMIT_COUNT) {
3449 /*
3450 * Give up and do the whole thing
3451 */
3452 if (vp->v_object &&
3453 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3454 VM_OBJECT_LOCK(vp->v_object);
3455 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
3456 VM_OBJECT_UNLOCK(vp->v_object);
3457 }
3458 error = VOP_FSYNC(vp, MNT_WAIT, curthread);
3459 } else {
3460 /*
3461 * Locate and synchronously write any buffers that fall
3462 * into the requested range. Note: we are assuming that
3463 * f_iosize is a power of 2.
3464 */
3465 int iosize = vp->v_mount->mnt_stat.f_iosize;
3466 int iomask = iosize - 1;
3467 struct bufobj *bo;
3468 daddr_t lblkno;
3469
3470 /*
3471 * Align to iosize boundry, super-align to page boundry.
3472 */
3473 if (off & iomask) {
3474 cnt += off & iomask;
3475 off &= ~(u_quad_t)iomask;
3476 }
3477 if (off & PAGE_MASK) {
3478 cnt += off & PAGE_MASK;
3479 off &= ~(u_quad_t)PAGE_MASK;
3480 }
3481 lblkno = off / iosize;
3482
3483 if (vp->v_object &&
3484 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3485 VM_OBJECT_LOCK(vp->v_object);
3486 vm_object_page_clean(vp->v_object, off, off + cnt,
3487 OBJPC_SYNC);
3488 VM_OBJECT_UNLOCK(vp->v_object);
3489 }
3490
3491 bo = &vp->v_bufobj;
3492 BO_LOCK(bo);
3493 while (cnt > 0) {
3494 struct buf *bp;
3495
3496 /*
3497 * If we have a buffer and it is marked B_DELWRI we
3498 * have to lock and write it. Otherwise the prior
3499 * write is assumed to have already been committed.
3500 *
3501 * gbincore() can return invalid buffers now so we
3502 * have to check that bit as well (though B_DELWRI
3503 * should not be set if B_INVAL is set there could be
3504 * a race here since we haven't locked the buffer).
3505 */
3506 if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
3507 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
3508 LK_INTERLOCK, BO_MTX(bo)) == ENOLCK) {
3509 BO_LOCK(bo);
3510 continue; /* retry */
3511 }
3512 if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
3513 B_DELWRI) {
3514 bremfree(bp);
3515 bp->b_flags &= ~B_ASYNC;
3516 bwrite(bp);
3517 ++nfs_commit_miss;
3518 } else
3519 BUF_UNLOCK(bp);
3520 BO_LOCK(bo);
3521 }
3522 ++nfs_commit_blks;
3523 if (cnt < iosize)
3524 break;
3525 cnt -= iosize;
3526 ++lblkno;
3527 }
3528 BO_UNLOCK(bo);
3529 }
3530
3531 aft_ret = VOP_GETATTR(vp, &aft, cred);
3532 vput(vp);
3533 vp = NULL;
3534 ereply:
3535 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
3536 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3537 if (!error) {
3538 tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
3539 if (nfsver.tv_sec == 0)
3540 nfsver = boottime;
3541 *tl++ = txdr_unsigned(nfsver.tv_sec);
3542 *tl = txdr_unsigned(nfsver.tv_usec);
3543 } else {
3544 error = 0;
3545 }
3546 nfsmout:
3547 if (vp)
3548 vput(vp);
3549 vn_finished_write(mp);
3550 VFS_UNLOCK_GIANT(vfslocked);
3551 return(error);
3552 }
3553
3554 /*
3555 * nfs statfs service
3556 */
3557 int
3558 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3559 struct mbuf **mrq)
3560 {
3561 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3562 struct sockaddr *nam = nfsd->nd_nam;
3563 caddr_t dpos = nfsd->nd_dpos;
3564 struct ucred *cred = nfsd->nd_cr;
3565 struct statfs *sf;
3566 struct nfs_statfs *sfp;
3567 caddr_t bpos;
3568 int error = 0, rdonly, getret = 1;
3569 int v3 = (nfsd->nd_flag & ND_NFSV3);
3570 struct mbuf *mb, *mreq;
3571 struct vnode *vp = NULL;
3572 struct vattr at;
3573 nfsfh_t nfh;
3574 fhandle_t *fhp;
3575 struct statfs statfs;
3576 u_quad_t tval;
3577 int vfslocked;
3578
3579 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3580 vfslocked = 0;
3581 fhp = &nfh.fh_generic;
3582 nfsm_srvmtofh(fhp);
3583 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
3584 if (error) {
3585 nfsm_reply(NFSX_UNSIGNED);
3586 if (v3)
3587 nfsm_srvpostop_attr(getret, &at);
3588 error = 0;
3589 goto nfsmout;
3590 }
3591 sf = &statfs;
3592 error = VFS_STATFS(vp->v_mount, sf);
3593 getret = VOP_GETATTR(vp, &at, cred);
3594 vput(vp);
3595 vp = NULL;
3596 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3597 if (v3)
3598 nfsm_srvpostop_attr(getret, &at);
3599 if (error) {
3600 error = 0;
3601 goto nfsmout;
3602 }
3603 sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
3604 if (v3) {
3605 tval = (u_quad_t)sf->f_blocks;
3606 tval *= (u_quad_t)sf->f_bsize;
3607 txdr_hyper(tval, &sfp->sf_tbytes);
3608 tval = (u_quad_t)sf->f_bfree;
3609 tval *= (u_quad_t)sf->f_bsize;
3610 txdr_hyper(tval, &sfp->sf_fbytes);
3611 /*
3612 * Don't send negative values for available space,
3613 * since this field is unsigned in the NFS protocol.
3614 * Otherwise, the client would see absurdly high
3615 * numbers for free space.
3616 */
3617 if (sf->f_bavail < 0)
3618 tval = 0;
3619 else
3620 tval = (u_quad_t)sf->f_bavail;
3621 tval *= (u_quad_t)sf->f_bsize;
3622 txdr_hyper(tval, &sfp->sf_abytes);
3623 sfp->sf_tfiles.nfsuquad[0] = 0;
3624 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
3625 sfp->sf_ffiles.nfsuquad[0] = 0;
3626 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3627 sfp->sf_afiles.nfsuquad[0] = 0;
3628 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3629 sfp->sf_invarsec = 0;
3630 } else {
3631 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3632 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3633 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3634 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3635 if (sf->f_bavail < 0)
3636 sfp->sf_bavail = 0;
3637 else
3638 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3639 }
3640 nfsmout:
3641 if (vp)
3642 vput(vp);
3643 VFS_UNLOCK_GIANT(vfslocked);
3644 return(error);
3645 }
3646
3647 /*
3648 * nfs fsinfo service
3649 */
3650 int
3651 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3652 struct mbuf **mrq)
3653 {
3654 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3655 struct sockaddr *nam = nfsd->nd_nam;
3656 caddr_t dpos = nfsd->nd_dpos;
3657 struct ucred *cred = nfsd->nd_cr;
3658 struct nfsv3_fsinfo *sip;
3659 caddr_t bpos;
3660 int error = 0, rdonly, getret = 1, pref;
3661 struct mbuf *mb, *mreq;
3662 struct vnode *vp = NULL;
3663 struct vattr at;
3664 nfsfh_t nfh;
3665 fhandle_t *fhp;
3666 u_quad_t maxfsize;
3667 struct statfs sb;
3668 int v3 = (nfsd->nd_flag & ND_NFSV3);
3669 int vfslocked;
3670
3671 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3672 if (!v3)
3673 panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
3674 fhp = &nfh.fh_generic;
3675 vfslocked = 0;
3676 nfsm_srvmtofh(fhp);
3677 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
3678 if (error) {
3679 nfsm_reply(NFSX_UNSIGNED);
3680 nfsm_srvpostop_attr(getret, &at);
3681 error = 0;
3682 goto nfsmout;
3683 }
3684
3685 /* XXX Try to make a guess on the max file size. */
3686 VFS_STATFS(vp->v_mount, &sb);
3687 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3688
3689 getret = VOP_GETATTR(vp, &at, cred);
3690 vput(vp);
3691 vp = NULL;
3692 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3693 nfsm_srvpostop_attr(getret, &at);
3694 sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3695
3696 /*
3697 * XXX
3698 * There should be filesystem VFS OP(s) to get this information.
3699 * For now, assume ufs.
3700 */
3701 pref = NFS_SRVMAXDATA(nfsd);
3702 sip->fs_rtmax = txdr_unsigned(pref);
3703 sip->fs_rtpref = txdr_unsigned(pref);
3704 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3705 sip->fs_wtmax = txdr_unsigned(pref);
3706 sip->fs_wtpref = txdr_unsigned(pref);
3707 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3708 sip->fs_dtpref = txdr_unsigned(pref);
3709 txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3710 sip->fs_timedelta.nfsv3_sec = 0;
3711 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3712 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3713 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3714 NFSV3FSINFO_CANSETTIME);
3715 nfsmout:
3716 if (vp)
3717 vput(vp);
3718 VFS_UNLOCK_GIANT(vfslocked);
3719 return(error);
3720 }
3721
3722 /*
3723 * nfs pathconf service
3724 */
3725 int
3726 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3727 struct mbuf **mrq)
3728 {
3729 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3730 struct sockaddr *nam = nfsd->nd_nam;
3731 caddr_t dpos = nfsd->nd_dpos;
3732 struct ucred *cred = nfsd->nd_cr;
3733 struct nfsv3_pathconf *pc;
3734 caddr_t bpos;
3735 int error = 0, rdonly, getret = 1;
3736 register_t linkmax, namemax, chownres, notrunc;
3737 struct mbuf *mb, *mreq;
3738 struct vnode *vp = NULL;
3739 struct vattr at;
3740 nfsfh_t nfh;
3741 fhandle_t *fhp;
3742 int v3 = (nfsd->nd_flag & ND_NFSV3);
3743 int vfslocked;
3744
3745 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3746 if (!v3)
3747 panic("nfsrv_pathconf: v3 proc called on a v2 connection");
3748 vfslocked = 0;
3749 fhp = &nfh.fh_generic;
3750 nfsm_srvmtofh(fhp);
3751 error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
3752 if (error) {
3753 nfsm_reply(NFSX_UNSIGNED);
3754 nfsm_srvpostop_attr(getret, &at);
3755 error = 0;
3756 goto nfsmout;
3757 }
3758 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3759 if (!error)
3760 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3761 if (!error)
3762 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3763 if (!error)
3764 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc);
3765 getret = VOP_GETATTR(vp, &at, cred);
3766 vput(vp);
3767 vp = NULL;
3768 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3769 nfsm_srvpostop_attr(getret, &at);
3770 if (error) {
3771 error = 0;
3772 goto nfsmout;
3773 }
3774 pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3775
3776 pc->pc_linkmax = txdr_unsigned(linkmax);
3777 pc->pc_namemax = txdr_unsigned(namemax);
3778 pc->pc_notrunc = txdr_unsigned(notrunc);
3779 pc->pc_chownrestricted = txdr_unsigned(chownres);
3780
3781 /*
3782 * These should probably be supported by VOP_PATHCONF(), but
3783 * until msdosfs is exportable (why would you want to?), the
3784 * Unix defaults should be ok.
3785 */
3786 pc->pc_caseinsensitive = nfsrv_nfs_false;
3787 pc->pc_casepreserving = nfsrv_nfs_true;
3788 nfsmout:
3789 if (vp)
3790 vput(vp);
3791 VFS_UNLOCK_GIANT(vfslocked);
3792 return(error);
3793 }
3794
3795 /*
3796 * Null operation, used by clients to ping server
3797 */
3798 /* ARGSUSED */
3799 int
3800 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3801 struct mbuf **mrq)
3802 {
3803 struct mbuf *mrep = nfsd->nd_mrep;
3804 caddr_t bpos;
3805 int error = NFSERR_RETVOID;
3806 struct mbuf *mb, *mreq;
3807
3808 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3809 nfsm_reply(0);
3810 nfsmout:
3811 return (error);
3812 }
3813
3814 /*
3815 * No operation, used for obsolete procedures
3816 */
3817 /* ARGSUSED */
3818 int
3819 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3820 struct mbuf **mrq)
3821 {
3822 struct mbuf *mrep = nfsd->nd_mrep;
3823 caddr_t bpos;
3824 int error;
3825 struct mbuf *mb, *mreq;
3826
3827 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3828 if (nfsd->nd_repstat)
3829 error = nfsd->nd_repstat;
3830 else
3831 error = EPROCUNAVAIL;
3832 nfsm_reply(0);
3833 error = 0;
3834 nfsmout:
3835 return (error);
3836 }
3837
3838 /*
3839 * Perform access checking for vnodes obtained from file handles that would
3840 * refer to files already opened by a Unix client. You cannot just use
3841 * vn_writechk() and VOP_ACCESS() for two reasons.
3842 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
3843 * case.
3844 * 2 - The owner is to be given access irrespective of mode bits for some
3845 * operations, so that processes that chmod after opening a file don't
3846 * break. I don't like this because it opens a security hole, but since
3847 * the nfs server opens a security hole the size of a barn door anyhow,
3848 * what the heck.
3849 *
3850 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3851 * will return EPERM instead of EACCES. EPERM is always an error.
3852 */
3853 static int
3854 nfsrv_access(struct vnode *vp, accmode_t accmode, struct ucred *cred,
3855 int rdonly, int override)
3856 {
3857 struct vattr vattr;
3858 int error;
3859
3860 VFS_ASSERT_GIANT(vp->v_mount);
3861
3862 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3863
3864 if (accmode & VWRITE) {
3865 /* Just vn_writechk() changed to check rdonly */
3866 /*
3867 * Disallow write attempts on read-only filesystems;
3868 * unless the file is a socket or a block or character
3869 * device resident on the filesystem.
3870 */
3871 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3872 switch (vp->v_type) {
3873 case VREG:
3874 case VDIR:
3875 case VLNK:
3876 return (EROFS);
3877 default:
3878 break;
3879 }
3880 }
3881 /*
3882 * If there's shared text associated with
3883 * the inode, we can't allow writing.
3884 */
3885 if (vp->v_vflag & VV_TEXT)
3886 return (ETXTBSY);
3887 }
3888
3889 error = VOP_GETATTR(vp, &vattr, cred);
3890 if (error)
3891 return (error);
3892 error = VOP_ACCESS(vp, accmode, cred, curthread);
3893 /*
3894 * Allow certain operations for the owner (reads and writes
3895 * on files that are already open).
3896 */
3897 if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
3898 error = 0;
3899 return (error);
3900 }
Cache object: 970d45defe39f6f35de454efbaed9f59
|