FreeBSD/Linux Kernel Cross Reference
sys/nfs/nfs_vnops.c
1 /* $OpenBSD: nfs_vnops.c,v 1.190 2022/08/12 14:30:53 visa Exp $ */
2 /* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */
3
4 /*
5 * Copyright (c) 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Rick Macklem at The University of Guelph.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
36 */
37
38
39 /*
40 * vnode op calls for Sun NFS version 2 and 3
41 */
42
43 #include <sys/param.h>
44 #include <sys/kernel.h>
45 #include <sys/systm.h>
46 #include <sys/resourcevar.h>
47 #include <sys/proc.h>
48 #include <sys/mount.h>
49 #include <sys/buf.h>
50 #include <sys/malloc.h>
51 #include <sys/pool.h>
52 #include <sys/mbuf.h>
53 #include <sys/conf.h>
54 #include <sys/namei.h>
55 #include <sys/vnode.h>
56 #include <sys/lock.h>
57 #include <sys/dirent.h>
58 #include <sys/fcntl.h>
59 #include <sys/lockf.h>
60 #include <sys/queue.h>
61 #include <sys/specdev.h>
62 #include <sys/unistd.h>
63
64 #include <miscfs/fifofs/fifo.h>
65
66 #include <nfs/rpcv2.h>
67 #include <nfs/nfsproto.h>
68 #include <nfs/nfs.h>
69 #include <nfs/nfsnode.h>
70 #include <nfs/nfsmount.h>
71 #include <nfs/xdr_subs.h>
72 #include <nfs/nfsm_subs.h>
73 #include <nfs/nfs_var.h>
74
75 #include <uvm/uvm_extern.h>
76
77 #include <netinet/in.h>
78
79 int nfs_access(void *);
80 int nfs_advlock(void *);
81 int nfs_bmap(void *);
82 int nfs_bwrite(void *);
83 int nfs_close(void *);
84 int nfs_commit(struct vnode *, u_quad_t, int, struct proc *);
85 int nfs_create(void *);
86 int nfs_flush(struct vnode *, struct ucred *, int, struct proc *, int);
87 int nfs_fsync(void *);
88 int nfs_getattr(void *);
89 int nfs_getreq(struct nfsrv_descript *, struct nfsd *, int);
90 int nfs_islocked(void *);
91 int nfs_link(void *);
92 int nfs_lock(void *);
93 int nfs_lookitup(struct vnode *, char *, int, struct ucred *, struct proc *,
94 struct nfsnode **);
95 int nfs_lookup(void *);
96 int nfs_mkdir(void *);
97 int nfs_mknod(void *);
98 int nfs_mknodrpc(struct vnode *, struct vnode **, struct componentname *,
99 struct vattr *);
100 int nfs_null(struct vnode *, struct ucred *, struct proc *);
101 int nfs_open(void *);
102 int nfs_pathconf(void *);
103 int nfs_print(void *);
104 int nfs_read(void *);
105 int nfs_readdir(void *);
106 int nfs_readdirplusrpc(struct vnode *, struct uio *, struct ucred *, int *,
107 struct proc *);
108 int nfs_readdirrpc(struct vnode *, struct uio *, struct ucred *, int *);
109 int nfs_remove(void *);
110 int nfs_removerpc(struct vnode *, char *, int, struct ucred *, struct proc *);
111 int nfs_rename(void *);
112 int nfs_renameit(struct vnode *, struct componentname *, struct sillyrename *);
113 int nfs_renamerpc(struct vnode *, char *, int, struct vnode *, char *, int,
114 struct ucred *, struct proc *);
115 int nfs_rmdir(void *);
116 int nfs_setattr(void *);
117 int nfs_setattrrpc(struct vnode *, struct vattr *, struct ucred *,
118 struct proc *);
119 int nfs_sillyrename(struct vnode *, struct vnode *,
120 struct componentname *);
121 int nfs_strategy(void *);
122 int nfs_symlink(void *);
123 int nfs_unlock(void *);
124
125 void nfs_cache_enter(struct vnode *, struct vnode *, struct componentname *);
126
127 int nfsfifo_close(void *);
128 int nfsfifo_read(void *);
129 int nfsfifo_reclaim(void *);
130 int nfsfifo_write(void *);
131
132 int nfsspec_access(void *);
133 int nfsspec_close(void *);
134 int nfsspec_read(void *);
135 int nfsspec_write(void *);
136
137 /* Global vfs data structures for nfs. */
138 const struct vops nfs_vops = {
139 .vop_lookup = nfs_lookup,
140 .vop_create = nfs_create,
141 .vop_mknod = nfs_mknod,
142 .vop_open = nfs_open,
143 .vop_close = nfs_close,
144 .vop_access = nfs_access,
145 .vop_getattr = nfs_getattr,
146 .vop_setattr = nfs_setattr,
147 .vop_read = nfs_read,
148 .vop_write = nfs_write,
149 .vop_ioctl = nfs_ioctl,
150 .vop_kqfilter = nfs_kqfilter,
151 .vop_revoke = vop_generic_revoke,
152 .vop_fsync = nfs_fsync,
153 .vop_remove = nfs_remove,
154 .vop_link = nfs_link,
155 .vop_rename = nfs_rename,
156 .vop_mkdir = nfs_mkdir,
157 .vop_rmdir = nfs_rmdir,
158 .vop_symlink = nfs_symlink,
159 .vop_readdir = nfs_readdir,
160 .vop_readlink = nfs_readlink,
161 .vop_abortop = vop_generic_abortop,
162 .vop_inactive = nfs_inactive,
163 .vop_reclaim = nfs_reclaim,
164 .vop_lock = nfs_lock,
165 .vop_unlock = nfs_unlock,
166 .vop_bmap = nfs_bmap,
167 .vop_strategy = nfs_strategy,
168 .vop_print = nfs_print,
169 .vop_islocked = nfs_islocked,
170 .vop_pathconf = nfs_pathconf,
171 .vop_advlock = nfs_advlock,
172 .vop_bwrite = nfs_bwrite
173 };
174
175 /* Special device vnode ops. */
176 const struct vops nfs_specvops = {
177 .vop_close = nfsspec_close,
178 .vop_access = nfsspec_access,
179 .vop_getattr = nfs_getattr,
180 .vop_setattr = nfs_setattr,
181 .vop_read = nfsspec_read,
182 .vop_write = nfsspec_write,
183 .vop_fsync = nfs_fsync,
184 .vop_inactive = nfs_inactive,
185 .vop_reclaim = nfs_reclaim,
186 .vop_lock = nfs_lock,
187 .vop_unlock = nfs_unlock,
188 .vop_print = nfs_print,
189 .vop_islocked = nfs_islocked,
190
191 /* XXX: Keep in sync with spec_vops. */
192 .vop_lookup = vop_generic_lookup,
193 .vop_create = vop_generic_badop,
194 .vop_mknod = vop_generic_badop,
195 .vop_open = spec_open,
196 .vop_ioctl = spec_ioctl,
197 .vop_kqfilter = spec_kqfilter,
198 .vop_revoke = vop_generic_revoke,
199 .vop_remove = vop_generic_badop,
200 .vop_link = vop_generic_badop,
201 .vop_rename = vop_generic_badop,
202 .vop_mkdir = vop_generic_badop,
203 .vop_rmdir = vop_generic_badop,
204 .vop_symlink = vop_generic_badop,
205 .vop_readdir = vop_generic_badop,
206 .vop_readlink = vop_generic_badop,
207 .vop_abortop = vop_generic_badop,
208 .vop_bmap = vop_generic_bmap,
209 .vop_strategy = spec_strategy,
210 .vop_pathconf = spec_pathconf,
211 .vop_advlock = spec_advlock,
212 .vop_bwrite = vop_generic_bwrite,
213 };
214
215 #ifdef FIFO
216 const struct vops nfs_fifovops = {
217 .vop_close = nfsfifo_close,
218 .vop_access = nfsspec_access,
219 .vop_getattr = nfs_getattr,
220 .vop_setattr = nfs_setattr,
221 .vop_read = nfsfifo_read,
222 .vop_write = nfsfifo_write,
223 .vop_fsync = nfs_fsync,
224 .vop_inactive = nfs_inactive,
225 .vop_reclaim = nfsfifo_reclaim,
226 .vop_lock = nfs_lock,
227 .vop_unlock = nfs_unlock,
228 .vop_print = nfs_print,
229 .vop_islocked = nfs_islocked,
230 .vop_bwrite = vop_generic_bwrite,
231
232 /* XXX: Keep in sync with fifo_vops. */
233 .vop_lookup = vop_generic_lookup,
234 .vop_create = vop_generic_badop,
235 .vop_mknod = vop_generic_badop,
236 .vop_open = fifo_open,
237 .vop_ioctl = fifo_ioctl,
238 .vop_kqfilter = fifo_kqfilter,
239 .vop_revoke = vop_generic_revoke,
240 .vop_remove = vop_generic_badop,
241 .vop_link = vop_generic_badop,
242 .vop_rename = vop_generic_badop,
243 .vop_mkdir = vop_generic_badop,
244 .vop_rmdir = vop_generic_badop,
245 .vop_symlink = vop_generic_badop,
246 .vop_readdir = vop_generic_badop,
247 .vop_readlink = vop_generic_badop,
248 .vop_abortop = vop_generic_badop,
249 .vop_bmap = vop_generic_bmap,
250 .vop_strategy = vop_generic_badop,
251 .vop_pathconf = fifo_pathconf,
252 .vop_advlock = fifo_advlock,
253 };
254 #endif /* FIFO */
255
256 /*
257 * Global variables
258 */
259 extern u_int32_t nfs_true, nfs_false;
260 extern u_int32_t nfs_xdrneg1;
261 extern struct nfsstats nfsstats;
262 extern nfstype nfsv3_type[9];
263 int nfs_numasync = 0;
264
265 void
266 nfs_cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
267 {
268 struct nfsnode *np;
269
270 if (vp != NULL) {
271 np = VTONFS(vp);
272 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
273 } else {
274 np = VTONFS(dvp);
275 if (!np->n_ctime)
276 np->n_ctime = np->n_vattr.va_mtime.tv_sec;
277 }
278
279 cache_enter(dvp, vp, cnp);
280 }
281
282 /*
283 * nfs null call from vfs.
284 */
285 int
286 nfs_null(struct vnode *vp, struct ucred *cred, struct proc *procp)
287 {
288 struct nfsm_info info;
289 int error = 0;
290
291 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(0);
292 error = nfs_request(vp, NFSPROC_NULL, &info);
293 m_freem(info.nmi_mrep);
294 return (error);
295 }
296
297 /*
298 * nfs access vnode op.
299 * For nfs version 2, just return ok. File accesses may fail later.
300 * For nfs version 3, use the access rpc to check accessibility. If file modes
301 * are changed on the server, accesses might still fail later.
302 */
303 int
304 nfs_access(void *v)
305 {
306 struct vop_access_args *ap = v;
307 struct vnode *vp = ap->a_vp;
308 u_int32_t *tl;
309 int32_t t1;
310 caddr_t cp2;
311 int error = 0, attrflag;
312 u_int32_t mode, rmode;
313 int v3 = NFS_ISV3(vp);
314 int cachevalid;
315 struct nfsm_info info;
316
317 struct nfsnode *np = VTONFS(vp);
318
319 /*
320 * Disallow write attempts on filesystems mounted read-only;
321 * unless the file is a socket, fifo, or a block or character
322 * device resident on the filesystem.
323 */
324 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
325 switch (vp->v_type) {
326 case VREG:
327 case VDIR:
328 case VLNK:
329 return (EROFS);
330 default:
331 break;
332 }
333 }
334
335 /*
336 * Check access cache first. If a request has been made for this uid
337 * shortly before, use the cached result.
338 */
339 cachevalid = (np->n_accstamp != -1 &&
340 (gettime() - np->n_accstamp) < nfs_attrtimeo(np) &&
341 np->n_accuid == ap->a_cred->cr_uid);
342
343 if (cachevalid) {
344 if (!np->n_accerror) {
345 if ((np->n_accmode & ap->a_mode) == ap->a_mode)
346 return (np->n_accerror);
347 } else if ((np->n_accmode & ap->a_mode) == np->n_accmode)
348 return (np->n_accerror);
349 }
350
351 /*
352 * For nfs v3, do an access rpc, otherwise you are stuck emulating
353 * ufs_access() locally using the vattr. This may not be correct,
354 * since the server may apply other access criteria such as
355 * client uid-->server uid mapping that we do not know about, but
356 * this is better than just returning anything that is lying about
357 * in the cache.
358 */
359 if (v3) {
360 nfsstats.rpccnt[NFSPROC_ACCESS]++;
361 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(v3) + NFSX_UNSIGNED);
362 nfsm_fhtom(&info, vp, v3);
363 tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED);
364 if (ap->a_mode & VREAD)
365 mode = NFSV3ACCESS_READ;
366 else
367 mode = 0;
368 if (vp->v_type == VDIR) {
369 if (ap->a_mode & VWRITE)
370 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
371 NFSV3ACCESS_DELETE);
372 if (ap->a_mode & VEXEC)
373 mode |= NFSV3ACCESS_LOOKUP;
374 } else {
375 if (ap->a_mode & VWRITE)
376 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
377 if (ap->a_mode & VEXEC)
378 mode |= NFSV3ACCESS_EXECUTE;
379 }
380 *tl = txdr_unsigned(mode);
381
382 info.nmi_procp = ap->a_p;
383 info.nmi_cred = ap->a_cred;
384 error = nfs_request(vp, NFSPROC_ACCESS, &info);
385
386 nfsm_postop_attr(vp, attrflag);
387 if (error) {
388 m_freem(info.nmi_mrep);
389 goto nfsmout;
390 }
391
392 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
393 rmode = fxdr_unsigned(u_int32_t, *tl);
394 /*
395 * The NFS V3 spec does not clarify whether or not
396 * the returned access bits can be a superset of
397 * the ones requested, so...
398 */
399 if ((rmode & mode) != mode)
400 error = EACCES;
401
402 m_freem(info.nmi_mrep);
403 } else
404 return (nfsspec_access(ap));
405
406
407 /*
408 * If we got the same result as for a previous, different request, OR
409 * it in. Don't update the timestamp in that case.
410 */
411 if (!error || error == EACCES) {
412 if (cachevalid && np->n_accstamp != -1 &&
413 error == np->n_accerror) {
414 if (!error)
415 np->n_accmode |= ap->a_mode;
416 else {
417 if ((np->n_accmode & ap->a_mode) == ap->a_mode)
418 np->n_accmode = ap->a_mode;
419 }
420 } else {
421 np->n_accstamp = gettime();
422 np->n_accuid = ap->a_cred->cr_uid;
423 np->n_accmode = ap->a_mode;
424 np->n_accerror = error;
425 }
426 }
427 nfsmout:
428 return (error);
429 }
430
431 /*
432 * nfs open vnode op
433 * Check to see if the type is ok
434 * and that deletion is not in progress.
435 * For paged in text files, you will need to flush the page cache
436 * if consistency is lost.
437 */
438 int
439 nfs_open(void *v)
440 {
441 struct vop_open_args *ap = v;
442 struct vnode *vp = ap->a_vp;
443 struct nfsnode *np = VTONFS(vp);
444 struct vattr vattr;
445 int error;
446
447 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
448 #ifdef DIAGNOSTIC
449 printf("open eacces vtyp=%d\n",vp->v_type);
450 #endif
451 return (EACCES);
452 }
453
454 /*
455 * Initialize read and write creds here, for swapfiles
456 * and other paths that don't set the creds themselves.
457 */
458
459 if (ap->a_mode & FREAD) {
460 if (np->n_rcred) {
461 crfree(np->n_rcred);
462 }
463 np->n_rcred = ap->a_cred;
464 crhold(np->n_rcred);
465 }
466 if (ap->a_mode & FWRITE) {
467 if (np->n_wcred) {
468 crfree(np->n_wcred);
469 }
470 np->n_wcred = ap->a_cred;
471 crhold(np->n_wcred);
472 }
473
474 if (np->n_flag & NMODIFIED) {
475 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p);
476 if (error == EINTR)
477 return (error);
478 uvm_vnp_uncache(vp);
479 NFS_INVALIDATE_ATTRCACHE(np);
480 if (vp->v_type == VDIR)
481 np->n_direofoffset = 0;
482 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
483 if (error)
484 return (error);
485 np->n_mtime = vattr.va_mtime;
486 } else {
487 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
488 if (error)
489 return (error);
490 if (timespeccmp(&np->n_mtime, &vattr.va_mtime, !=)) {
491 if (vp->v_type == VDIR)
492 np->n_direofoffset = 0;
493 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p);
494 if (error == EINTR)
495 return (error);
496 uvm_vnp_uncache(vp);
497 np->n_mtime = vattr.va_mtime;
498 }
499 }
500 /* For open/close consistency. */
501 NFS_INVALIDATE_ATTRCACHE(np);
502 return (0);
503 }
504
505 /*
506 * nfs close vnode op
507 * What an NFS client should do upon close after writing is a debatable issue.
508 * Most NFS clients push delayed writes to the server upon close, basically for
509 * two reasons:
510 * 1 - So that any write errors may be reported back to the client process
511 * doing the close system call. By far the two most likely errors are
512 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
513 * 2 - To put a worst case upper bound on cache inconsistency between
514 * multiple clients for the file.
515 * There is also a consistency problem for Version 2 of the protocol w.r.t.
516 * not being able to tell if other clients are writing a file concurrently,
517 * since there is no way of knowing if the changed modify time in the reply
518 * is only due to the write for this client.
519 * (NFS Version 3 provides weak cache consistency data in the reply that
520 * should be sufficient to detect and handle this case.)
521 *
522 * The current code does the following:
523 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
524 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
525 * or commit them (this satisfies 1 and 2 except for the
526 * case where the server crashes after this close but
527 * before the commit RPC, which is felt to be "good
528 * enough". Changing the last argument to nfs_flush() to
529 * a 1 would force a commit operation, if it is felt a
530 * commit is necessary now.
531 */
532 int
533 nfs_close(void *v)
534 {
535 struct vop_close_args *ap = v;
536 struct vnode *vp = ap->a_vp;
537 struct nfsnode *np = VTONFS(vp);
538 int error = 0;
539
540 if (vp->v_type == VREG) {
541 if (np->n_flag & NMODIFIED) {
542 if (NFS_ISV3(vp)) {
543 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0);
544 np->n_flag &= ~NMODIFIED;
545 } else
546 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p);
547 NFS_INVALIDATE_ATTRCACHE(np);
548 }
549 if (np->n_flag & NWRITEERR) {
550 np->n_flag &= ~NWRITEERR;
551 error = np->n_error;
552 }
553 }
554 return (error);
555 }
556
557 /*
558 * nfs getattr call from vfs.
559 */
560 int
561 nfs_getattr(void *v)
562 {
563 struct vop_getattr_args *ap = v;
564 struct vnode *vp = ap->a_vp;
565 struct nfsnode *np = VTONFS(vp);
566 struct nfsm_info info;
567 int32_t t1;
568 int error = 0;
569
570 info.nmi_v3 = NFS_ISV3(vp);
571
572 /*
573 * Update local times for special files.
574 */
575 if (np->n_flag & (NACC | NUPD))
576 np->n_flag |= NCHG;
577 /*
578 * First look in the cache.
579 */
580 if (nfs_getattrcache(vp, ap->a_vap) == 0)
581 return (0);
582
583 nfsstats.rpccnt[NFSPROC_GETATTR]++;
584 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3));
585 nfsm_fhtom(&info, vp, info.nmi_v3);
586 info.nmi_procp = ap->a_p;
587 info.nmi_cred = ap->a_cred;
588 error = nfs_request(vp, NFSPROC_GETATTR, &info);
589 if (!error)
590 nfsm_loadattr(vp, ap->a_vap);
591 m_freem(info.nmi_mrep);
592 nfsmout:
593 return (error);
594 }
595
596 /*
597 * nfs setattr call.
598 */
599 int
600 nfs_setattr(void *v)
601 {
602 struct vop_setattr_args *ap = v;
603 struct vnode *vp = ap->a_vp;
604 struct nfsnode *np = VTONFS(vp);
605 struct vattr *vap = ap->a_vap;
606 int hint = NOTE_ATTRIB;
607 int error = 0;
608 u_quad_t tsize = 0;
609
610 /*
611 * Setting of flags is not supported.
612 */
613 if (vap->va_flags != VNOVAL)
614 return (EOPNOTSUPP);
615
616 /*
617 * Disallow write attempts if the filesystem is mounted read-only.
618 */
619 if ((vap->va_uid != (uid_t)VNOVAL ||
620 vap->va_gid != (gid_t)VNOVAL ||
621 vap->va_atime.tv_nsec != VNOVAL ||
622 vap->va_mtime.tv_nsec != VNOVAL ||
623 vap->va_mode != (mode_t)VNOVAL) &&
624 (vp->v_mount->mnt_flag & MNT_RDONLY))
625 return (EROFS);
626 if (vap->va_size != VNOVAL) {
627 switch (vp->v_type) {
628 case VDIR:
629 return (EISDIR);
630 case VCHR:
631 case VBLK:
632 case VSOCK:
633 case VFIFO:
634 if (vap->va_mtime.tv_nsec == VNOVAL &&
635 vap->va_atime.tv_nsec == VNOVAL &&
636 vap->va_mode == (mode_t)VNOVAL &&
637 vap->va_uid == (uid_t)VNOVAL &&
638 vap->va_gid == (gid_t)VNOVAL)
639 return (0);
640 vap->va_size = VNOVAL;
641 break;
642 default:
643 /*
644 * Disallow write attempts if the filesystem is
645 * mounted read-only.
646 */
647 if (vp->v_mount->mnt_flag & MNT_RDONLY)
648 return (EROFS);
649 if (vap->va_size == 0)
650 error = nfs_vinvalbuf(vp, 0,
651 ap->a_cred, ap->a_p);
652 else
653 error = nfs_vinvalbuf(vp, V_SAVE,
654 ap->a_cred, ap->a_p);
655 if (error)
656 return (error);
657 tsize = np->n_size;
658 np->n_size = np->n_vattr.va_size = vap->va_size;
659 uvm_vnp_setsize(vp, np->n_size);
660 };
661 } else if ((vap->va_mtime.tv_nsec != VNOVAL ||
662 vap->va_atime.tv_nsec != VNOVAL) &&
663 vp->v_type == VREG &&
664 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
665 ap->a_p)) == EINTR)
666 return (error);
667 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
668 if (error && vap->va_size != VNOVAL) {
669 np->n_size = np->n_vattr.va_size = tsize;
670 uvm_vnp_setsize(vp, np->n_size);
671 }
672
673 if (vap->va_size != VNOVAL && vap->va_size < tsize)
674 hint |= NOTE_TRUNCATE;
675
676 VN_KNOTE(vp, hint); /* XXX setattrrpc? */
677
678 return (error);
679 }
680
681 /*
682 * Do an nfs setattr rpc.
683 */
684 int
685 nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred,
686 struct proc *procp)
687 {
688 struct nfsv2_sattr *sp;
689 struct nfsm_info info;
690 int32_t t1;
691 caddr_t cp2;
692 u_int32_t *tl;
693 int error = 0, wccflag = NFSV3_WCCRATTR;
694 int v3 = NFS_ISV3(vp);
695
696 info.nmi_v3 = NFS_ISV3(vp);
697
698 nfsstats.rpccnt[NFSPROC_SETATTR]++;
699 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(v3) + NFSX_SATTR(v3));
700 nfsm_fhtom(&info, vp, v3);
701
702 if (info.nmi_v3) {
703 nfsm_v3attrbuild(&info.nmi_mb, vap, 1);
704 tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED);
705 *tl = nfs_false;
706 } else {
707 sp = nfsm_build(&info.nmi_mb, NFSX_V2SATTR);
708 if (vap->va_mode == (mode_t)VNOVAL)
709 sp->sa_mode = nfs_xdrneg1;
710 else
711 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
712 if (vap->va_uid == (uid_t)VNOVAL)
713 sp->sa_uid = nfs_xdrneg1;
714 else
715 sp->sa_uid = txdr_unsigned(vap->va_uid);
716 if (vap->va_gid == (gid_t)VNOVAL)
717 sp->sa_gid = nfs_xdrneg1;
718 else
719 sp->sa_gid = txdr_unsigned(vap->va_gid);
720 sp->sa_size = txdr_unsigned(vap->va_size);
721 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
722 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
723 }
724
725 info.nmi_procp = procp;
726 info.nmi_cred = cred;
727 error = nfs_request(vp, NFSPROC_SETATTR, &info);
728
729 if (info.nmi_v3)
730 nfsm_wcc_data(vp, wccflag);
731 else if (error == 0)
732 nfsm_loadattr(vp, NULL);
733
734 m_freem(info.nmi_mrep);
735 nfsmout:
736 return (error);
737 }
738
739 /*
740 * nfs lookup call, one step at a time...
741 * First look in cache
742 * If not found, unlock the directory nfsnode and do the rpc
743 */
744 int
745 nfs_lookup(void *v)
746 {
747 struct vop_lookup_args *ap = v;
748 struct componentname *cnp = ap->a_cnp;
749 struct vnode *dvp = ap->a_dvp;
750 struct vnode **vpp = ap->a_vpp;
751 struct nfsm_info info;
752 int flags;
753 struct vnode *newvp;
754 u_int32_t *tl;
755 int32_t t1;
756 struct nfsmount *nmp;
757 caddr_t cp2;
758 long len;
759 nfsfh_t *fhp;
760 struct nfsnode *np;
761 int lockparent, wantparent, error = 0, attrflag, fhsize;
762
763 info.nmi_v3 = NFS_ISV3(dvp);
764
765 cnp->cn_flags &= ~PDIRUNLOCK;
766 flags = cnp->cn_flags;
767
768 *vpp = NULLVP;
769 newvp = NULLVP;
770 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
771 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
772 return (EROFS);
773 if (dvp->v_type != VDIR)
774 return (ENOTDIR);
775 lockparent = flags & LOCKPARENT;
776 wantparent = flags & (LOCKPARENT|WANTPARENT);
777 nmp = VFSTONFS(dvp->v_mount);
778 np = VTONFS(dvp);
779
780 /*
781 * Before tediously performing a linear scan of the directory,
782 * check the name cache to see if the directory/name pair
783 * we are looking for is known already.
784 * If the directory/name pair is found in the name cache,
785 * we have to ensure the directory has not changed from
786 * the time the cache entry has been created. If it has,
787 * the cache entry has to be ignored.
788 */
789 if ((error = cache_lookup(dvp, vpp, cnp)) >= 0) {
790 struct vattr vattr;
791 int err2;
792
793 if (error && error != ENOENT) {
794 *vpp = NULLVP;
795 return (error);
796 }
797
798 if (cnp->cn_flags & PDIRUNLOCK) {
799 err2 = vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
800 if (err2 != 0) {
801 *vpp = NULLVP;
802 return (err2);
803 }
804 cnp->cn_flags &= ~PDIRUNLOCK;
805 }
806
807 err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
808 if (err2 != 0) {
809 if (error == 0) {
810 if (*vpp != dvp)
811 vput(*vpp);
812 else
813 vrele(*vpp);
814 }
815 *vpp = NULLVP;
816 return (err2);
817 }
818
819 if (error == ENOENT) {
820 if (!VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
821 cnp->cn_proc) && vattr.va_mtime.tv_sec ==
822 VTONFS(dvp)->n_ctime)
823 return (ENOENT);
824 cache_purge(dvp);
825 np->n_ctime = 0;
826 goto dorpc;
827 }
828
829 newvp = *vpp;
830 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)
831 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime)
832 {
833 nfsstats.lookupcache_hits++;
834 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
835 cnp->cn_flags |= SAVENAME;
836 if ((!lockparent || !(flags & ISLASTCN)) &&
837 newvp != dvp) {
838 VOP_UNLOCK(dvp);
839 cnp->cn_flags |= PDIRUNLOCK;
840 }
841 return (0);
842 }
843 cache_purge(newvp);
844 if (newvp != dvp)
845 vput(newvp);
846 else
847 vrele(newvp);
848 *vpp = NULLVP;
849 }
850 dorpc:
851 error = 0;
852 newvp = NULLVP;
853 nfsstats.lookupcache_misses++;
854 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
855 len = cnp->cn_namelen;
856 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
857 NFSX_UNSIGNED + nfsm_rndup(len));
858 nfsm_fhtom(&info, dvp, info.nmi_v3);
859 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
860
861 info.nmi_procp = cnp->cn_proc;
862 info.nmi_cred = cnp->cn_cred;
863 error = nfs_request(dvp, NFSPROC_LOOKUP, &info);
864
865 if (error) {
866 if (info.nmi_v3)
867 nfsm_postop_attr(dvp, attrflag);
868 m_freem(info.nmi_mrep);
869 goto nfsmout;
870 }
871
872 nfsm_getfh(fhp, fhsize, info.nmi_v3);
873
874 /*
875 * Handle RENAME case...
876 */
877 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
878 if (NFS_CMPFH(np, fhp, fhsize)) {
879 m_freem(info.nmi_mrep);
880 return (EISDIR);
881 }
882 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
883 if (error) {
884 m_freem(info.nmi_mrep);
885 return (error);
886 }
887 newvp = NFSTOV(np);
888 if (info.nmi_v3) {
889 nfsm_postop_attr(newvp, attrflag);
890 nfsm_postop_attr(dvp, attrflag);
891 } else
892 nfsm_loadattr(newvp, NULL);
893 *vpp = newvp;
894 m_freem(info.nmi_mrep);
895 cnp->cn_flags |= SAVENAME;
896 if (!lockparent) {
897 VOP_UNLOCK(dvp);
898 cnp->cn_flags |= PDIRUNLOCK;
899 }
900 return (0);
901 }
902
903 /*
904 * The postop attr handling is duplicated for each if case,
905 * because it should be done while dvp is locked (unlocking
906 * dvp is different for each case).
907 */
908
909 if (NFS_CMPFH(np, fhp, fhsize)) {
910 vref(dvp);
911 newvp = dvp;
912 if (info.nmi_v3) {
913 nfsm_postop_attr(newvp, attrflag);
914 nfsm_postop_attr(dvp, attrflag);
915 } else
916 nfsm_loadattr(newvp, NULL);
917 } else if (flags & ISDOTDOT) {
918 VOP_UNLOCK(dvp);
919 cnp->cn_flags |= PDIRUNLOCK;
920
921 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
922 if (error) {
923 if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY) == 0)
924 cnp->cn_flags &= ~PDIRUNLOCK;
925 m_freem(info.nmi_mrep);
926 return (error);
927 }
928 newvp = NFSTOV(np);
929
930 if (info.nmi_v3) {
931 nfsm_postop_attr(newvp, attrflag);
932 nfsm_postop_attr(dvp, attrflag);
933 } else
934 nfsm_loadattr(newvp, NULL);
935
936 if (lockparent && (flags & ISLASTCN)) {
937 if ((error = vn_lock(dvp, LK_EXCLUSIVE))) {
938 m_freem(info.nmi_mrep);
939 vput(newvp);
940 return error;
941 }
942 cnp->cn_flags &= ~PDIRUNLOCK;
943 }
944
945 } else {
946 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
947 if (error) {
948 m_freem(info.nmi_mrep);
949 return error;
950 }
951 newvp = NFSTOV(np);
952 if (info.nmi_v3) {
953 nfsm_postop_attr(newvp, attrflag);
954 nfsm_postop_attr(dvp, attrflag);
955 } else
956 nfsm_loadattr(newvp, NULL);
957 if (!lockparent || !(flags & ISLASTCN)) {
958 VOP_UNLOCK(dvp);
959 cnp->cn_flags |= PDIRUNLOCK;
960 }
961 }
962
963 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
964 cnp->cn_flags |= SAVENAME;
965 if ((cnp->cn_flags & MAKEENTRY) &&
966 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
967 nfs_cache_enter(dvp, newvp, cnp);
968 }
969
970 *vpp = newvp;
971 m_freem(info.nmi_mrep);
972
973 nfsmout:
974 if (error) {
975 /*
976 * We get here only because of errors returned by
977 * the RPC. Otherwise we'll have returned above
978 * (the nfsm_* macros will jump to nfsmout
979 * on error).
980 */
981 if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) &&
982 cnp->cn_nameiop != CREATE) {
983 nfs_cache_enter(dvp, NULL, cnp);
984 }
985 if (newvp != NULLVP) {
986 if (newvp != dvp)
987 vput(newvp);
988 else
989 vrele(newvp);
990 }
991 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
992 (flags & ISLASTCN) && error == ENOENT) {
993 if (dvp->v_mount->mnt_flag & MNT_RDONLY)
994 error = EROFS;
995 else
996 error = EJUSTRETURN;
997 }
998 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
999 cnp->cn_flags |= SAVENAME;
1000 *vpp = NULL;
1001 }
1002 return (error);
1003 }
1004
1005 /*
1006 * nfs read call.
1007 * Just call nfs_bioread() to do the work.
1008 */
1009 int
1010 nfs_read(void *v)
1011 {
1012 struct vop_read_args *ap = v;
1013 struct vnode *vp = ap->a_vp;
1014
1015 if (vp->v_type != VREG)
1016 return (EPERM);
1017 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
1018 }
1019
1020 /*
1021 * nfs readlink call
1022 */
1023 int
1024 nfs_readlink(void *v)
1025 {
1026 struct vop_readlink_args *ap = v;
1027 struct vnode *vp = ap->a_vp;
1028
1029 if (vp->v_type != VLNK)
1030 return (EPERM);
1031 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
1032 }
1033
1034 /*
1035 * Lock an inode.
1036 */
1037 int
1038 nfs_lock(void *v)
1039 {
1040 struct vop_lock_args *ap = v;
1041 struct vnode *vp = ap->a_vp;
1042
1043 return rrw_enter(&VTONFS(vp)->n_lock, ap->a_flags & LK_RWFLAGS);
1044 }
1045
1046 /*
1047 * Unlock an inode.
1048 */
1049 int
1050 nfs_unlock(void *v)
1051 {
1052 struct vop_unlock_args *ap = v;
1053 struct vnode *vp = ap->a_vp;
1054
1055 rrw_exit(&VTONFS(vp)->n_lock);
1056 return 0;
1057 }
1058
1059 /*
1060 * Check for a locked inode.
1061 */
1062 int
1063 nfs_islocked(void *v)
1064 {
1065 struct vop_islocked_args *ap = v;
1066
1067 return rrw_status(&VTONFS(ap->a_vp)->n_lock);
1068 }
1069
1070 /*
1071 * Do a readlink rpc.
1072 * Called by nfs_doio() from below the buffer cache.
1073 */
1074 int
1075 nfs_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
1076 {
1077 struct nfsm_info info;
1078 u_int32_t *tl;
1079 int32_t t1;
1080 caddr_t cp2;
1081 int error = 0, len, attrflag;
1082
1083 info.nmi_v3 = NFS_ISV3(vp);
1084
1085 nfsstats.rpccnt[NFSPROC_READLINK]++;
1086 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3));
1087 nfsm_fhtom(&info, vp, info.nmi_v3);
1088
1089 info.nmi_procp = curproc;
1090 info.nmi_cred = cred;
1091 error = nfs_request(vp, NFSPROC_READLINK, &info);
1092
1093 if (info.nmi_v3)
1094 nfsm_postop_attr(vp, attrflag);
1095 if (!error) {
1096 nfsm_strsiz(len, NFS_MAXPATHLEN);
1097 nfsm_mtouio(uiop, len);
1098 }
1099
1100 m_freem(info.nmi_mrep);
1101
1102 nfsmout:
1103 return (error);
1104 }
1105
1106 /*
1107 * nfs read rpc call
1108 * Ditto above
1109 */
1110 int
1111 nfs_readrpc(struct vnode *vp, struct uio *uiop)
1112 {
1113 struct nfsm_info info;
1114 u_int32_t *tl;
1115 int32_t t1;
1116 caddr_t cp2;
1117 struct nfsmount *nmp;
1118 int error = 0, len, retlen, tsiz, eof, attrflag;
1119
1120 info.nmi_v3 = NFS_ISV3(vp);
1121
1122 eof = 0;
1123
1124 nmp = VFSTONFS(vp->v_mount);
1125 tsiz = uiop->uio_resid;
1126 if (uiop->uio_offset + tsiz > 0xffffffff && !info.nmi_v3)
1127 return (EFBIG);
1128 while (tsiz > 0) {
1129 nfsstats.rpccnt[NFSPROC_READ]++;
1130 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
1131 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
1132 NFSX_UNSIGNED * 3);
1133 nfsm_fhtom(&info, vp, info.nmi_v3);
1134 tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED * 3);
1135 if (info.nmi_v3) {
1136 txdr_hyper(uiop->uio_offset, tl);
1137 *(tl + 2) = txdr_unsigned(len);
1138 } else {
1139 *tl++ = txdr_unsigned(uiop->uio_offset);
1140 *tl++ = txdr_unsigned(len);
1141 *tl = 0;
1142 }
1143
1144 info.nmi_procp = curproc;
1145 info.nmi_cred = VTONFS(vp)->n_rcred;
1146 error = nfs_request(vp, NFSPROC_READ, &info);
1147 if (info.nmi_v3)
1148 nfsm_postop_attr(vp, attrflag);
1149 if (error) {
1150 m_freem(info.nmi_mrep);
1151 goto nfsmout;
1152 }
1153
1154 if (info.nmi_v3) {
1155 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1156 eof = fxdr_unsigned(int, *(tl + 1));
1157 } else {
1158 nfsm_loadattr(vp, NULL);
1159 }
1160
1161 nfsm_strsiz(retlen, nmp->nm_rsize);
1162 nfsm_mtouio(uiop, retlen);
1163 m_freem(info.nmi_mrep);
1164 tsiz -= retlen;
1165 if (info.nmi_v3) {
1166 if (eof || retlen == 0)
1167 tsiz = 0;
1168 } else if (retlen < len)
1169 tsiz = 0;
1170 }
1171
1172 nfsmout:
1173 return (error);
1174 }
1175
1176 /*
1177 * nfs write call
1178 */
1179 int
1180 nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
1181 {
1182 struct nfsm_info info;
1183 u_int32_t *tl;
1184 int32_t t1, backup;
1185 caddr_t cp2;
1186 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1187 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
1188 int committed = NFSV3WRITE_FILESYNC;
1189
1190 info.nmi_v3 = NFS_ISV3(vp);
1191
1192 #ifdef DIAGNOSTIC
1193 if (uiop->uio_iovcnt != 1)
1194 panic("nfs: writerpc iovcnt > 1");
1195 #endif
1196 *must_commit = 0;
1197 tsiz = uiop->uio_resid;
1198 if (uiop->uio_offset + tsiz > 0xffffffff && !info.nmi_v3)
1199 return (EFBIG);
1200 while (tsiz > 0) {
1201 nfsstats.rpccnt[NFSPROC_WRITE]++;
1202 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1203 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3)
1204 + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1205 nfsm_fhtom(&info, vp, info.nmi_v3);
1206 if (info.nmi_v3) {
1207 tl = nfsm_build(&info.nmi_mb, 5 * NFSX_UNSIGNED);
1208 txdr_hyper(uiop->uio_offset, tl);
1209 tl += 2;
1210 *tl++ = txdr_unsigned(len);
1211 *tl++ = txdr_unsigned(*iomode);
1212 *tl = txdr_unsigned(len);
1213 } else {
1214 u_int32_t x;
1215
1216 tl = nfsm_build(&info.nmi_mb, 4 * NFSX_UNSIGNED);
1217 /* Set both "begin" and "current" to non-garbage. */
1218 x = txdr_unsigned((u_int32_t)uiop->uio_offset);
1219 *tl++ = x; /* "begin offset" */
1220 *tl++ = x; /* "current offset" */
1221 x = txdr_unsigned(len);
1222 *tl++ = x; /* total to this offset */
1223 *tl = x; /* size of this write */
1224
1225 }
1226 nfsm_uiotombuf(&info.nmi_mb, uiop, len);
1227
1228 info.nmi_procp = curproc;
1229 info.nmi_cred = VTONFS(vp)->n_wcred;
1230 error = nfs_request(vp, NFSPROC_WRITE, &info);
1231 if (info.nmi_v3) {
1232 wccflag = NFSV3_WCCCHK;
1233 nfsm_wcc_data(vp, wccflag);
1234 }
1235
1236 if (error) {
1237 m_freem(info.nmi_mrep);
1238 goto nfsmout;
1239 }
1240
1241 if (info.nmi_v3) {
1242 wccflag = NFSV3_WCCCHK;
1243 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
1244 + NFSX_V3WRITEVERF);
1245 rlen = fxdr_unsigned(int, *tl++);
1246 if (rlen <= 0) {
1247 error = NFSERR_IO;
1248 break;
1249 } else if (rlen < len) {
1250 backup = len - rlen;
1251 uiop->uio_iov->iov_base =
1252 (char *)uiop->uio_iov->iov_base -
1253 backup;
1254 uiop->uio_iov->iov_len += backup;
1255 uiop->uio_offset -= backup;
1256 uiop->uio_resid += backup;
1257 len = rlen;
1258 }
1259 commit = fxdr_unsigned(int, *tl++);
1260
1261 /*
1262 * Return the lowest commitment level
1263 * obtained by any of the RPCs.
1264 */
1265 if (committed == NFSV3WRITE_FILESYNC)
1266 committed = commit;
1267 else if (committed == NFSV3WRITE_DATASYNC &&
1268 commit == NFSV3WRITE_UNSTABLE)
1269 committed = commit;
1270 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) {
1271 bcopy(tl, nmp->nm_verf,
1272 NFSX_V3WRITEVERF);
1273 nmp->nm_flag |= NFSMNT_HASWRITEVERF;
1274 } else if (bcmp(tl,
1275 nmp->nm_verf, NFSX_V3WRITEVERF)) {
1276 *must_commit = 1;
1277 bcopy(tl, nmp->nm_verf,
1278 NFSX_V3WRITEVERF);
1279 }
1280 } else {
1281 nfsm_loadattr(vp, NULL);
1282 }
1283 if (wccflag)
1284 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime;
1285 m_freem(info.nmi_mrep);
1286 tsiz -= len;
1287 }
1288 nfsmout:
1289 *iomode = committed;
1290 if (error)
1291 uiop->uio_resid = tsiz;
1292 return (error);
1293 }
1294
1295 /*
1296 * nfs mknod rpc
1297 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1298 * mode set to specify the file type and the size field for rdev.
1299 */
1300 int
1301 nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
1302 struct vattr *vap)
1303 {
1304 struct nfsv2_sattr *sp;
1305 struct nfsm_info info;
1306 u_int32_t *tl;
1307 int32_t t1;
1308 struct vnode *newvp = NULL;
1309 struct nfsnode *np = NULL;
1310 char *cp2;
1311 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1312 u_int32_t rdev;
1313
1314 info.nmi_v3 = NFS_ISV3(dvp);
1315
1316 if (vap->va_type == VCHR || vap->va_type == VBLK)
1317 rdev = txdr_unsigned(vap->va_rdev);
1318 else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1319 rdev = nfs_xdrneg1;
1320 else {
1321 VOP_ABORTOP(dvp, cnp);
1322 return (EOPNOTSUPP);
1323 }
1324 nfsstats.rpccnt[NFSPROC_MKNOD]++;
1325 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
1326 4 * NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen) +
1327 NFSX_SATTR(info.nmi_v3));
1328 nfsm_fhtom(&info, dvp, info.nmi_v3);
1329 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1330
1331 if (info.nmi_v3) {
1332 tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED);
1333 *tl++ = vtonfsv3_type(vap->va_type);
1334 nfsm_v3attrbuild(&info.nmi_mb, vap, 0);
1335 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1336 tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
1337 *tl++ = txdr_unsigned(major(vap->va_rdev));
1338 *tl = txdr_unsigned(minor(vap->va_rdev));
1339 }
1340 } else {
1341 sp = nfsm_build(&info.nmi_mb, NFSX_V2SATTR);
1342 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1343 sp->sa_uid = nfs_xdrneg1;
1344 sp->sa_gid = nfs_xdrneg1;
1345 sp->sa_size = rdev;
1346 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1347 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1348 }
1349
1350 KASSERT(cnp->cn_proc == curproc);
1351 info.nmi_procp = cnp->cn_proc;
1352 info.nmi_cred = cnp->cn_cred;
1353 error = nfs_request(dvp, NFSPROC_MKNOD, &info);
1354 if (!error) {
1355 nfsm_mtofh(dvp, newvp, info.nmi_v3, gotvp);
1356 if (!gotvp) {
1357 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1358 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1359 if (!error)
1360 newvp = NFSTOV(np);
1361 }
1362 }
1363 if (info.nmi_v3)
1364 nfsm_wcc_data(dvp, wccflag);
1365 m_freem(info.nmi_mrep);
1366
1367 nfsmout:
1368 if (error) {
1369 if (newvp)
1370 vput(newvp);
1371 } else {
1372 if (cnp->cn_flags & MAKEENTRY)
1373 nfs_cache_enter(dvp, newvp, cnp);
1374 *vpp = newvp;
1375 }
1376 pool_put(&namei_pool, cnp->cn_pnbuf);
1377 VTONFS(dvp)->n_flag |= NMODIFIED;
1378 if (!wccflag)
1379 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
1380 return (error);
1381 }
1382
1383 /*
1384 * nfs mknod vop
1385 * just call nfs_mknodrpc() to do the work.
1386 */
1387 int
1388 nfs_mknod(void *v)
1389 {
1390 struct vop_mknod_args *ap = v;
1391 struct vnode *newvp;
1392 int error;
1393
1394 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap);
1395 if (!error)
1396 vput(newvp);
1397
1398 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1399
1400 return (error);
1401 }
1402
1403 int
1404 nfs_create(void *v)
1405 {
1406 struct vop_create_args *ap = v;
1407 struct vnode *dvp = ap->a_dvp;
1408 struct vattr *vap = ap->a_vap;
1409 struct componentname *cnp = ap->a_cnp;
1410 struct nfsv2_sattr *sp;
1411 struct nfsm_info info;
1412 struct timespec ts;
1413 u_int32_t *tl;
1414 int32_t t1;
1415 struct nfsnode *np = NULL;
1416 struct vnode *newvp = NULL;
1417 caddr_t cp2;
1418 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1419
1420 info.nmi_v3 = NFS_ISV3(dvp);
1421
1422 /*
1423 * Oops, not for me..
1424 */
1425 if (vap->va_type == VSOCK)
1426 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1427
1428 if (vap->va_vaflags & VA_EXCLUSIVE)
1429 fmode |= O_EXCL;
1430
1431 again:
1432 nfsstats.rpccnt[NFSPROC_CREATE]++;
1433 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
1434 2 * NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen) +
1435 NFSX_SATTR(info.nmi_v3));
1436 nfsm_fhtom(&info, dvp, info.nmi_v3);
1437 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1438 if (info.nmi_v3) {
1439 tl = nfsm_build(&info.nmi_mb, NFSX_UNSIGNED);
1440 if (fmode & O_EXCL) {
1441 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1442 tl = nfsm_build(&info.nmi_mb, NFSX_V3CREATEVERF);
1443 arc4random_buf(tl, sizeof(*tl) * 2);
1444 } else {
1445 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1446 nfsm_v3attrbuild(&info.nmi_mb, vap, 0);
1447 }
1448 } else {
1449 sp = nfsm_build(&info.nmi_mb, NFSX_V2SATTR);
1450 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1451 sp->sa_uid = nfs_xdrneg1;
1452 sp->sa_gid = nfs_xdrneg1;
1453 sp->sa_size = 0;
1454 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1455 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1456 }
1457
1458 KASSERT(cnp->cn_proc == curproc);
1459 info.nmi_procp = cnp->cn_proc;
1460 info.nmi_cred = cnp->cn_cred;
1461 error = nfs_request(dvp, NFSPROC_CREATE, &info);
1462 if (!error) {
1463 nfsm_mtofh(dvp, newvp, info.nmi_v3, gotvp);
1464 if (!gotvp) {
1465 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1466 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1467 if (!error)
1468 newvp = NFSTOV(np);
1469 }
1470 }
1471 if (info.nmi_v3)
1472 nfsm_wcc_data(dvp, wccflag);
1473 m_freem(info.nmi_mrep);
1474
1475 nfsmout:
1476 if (error) {
1477 if (newvp) {
1478 vput(newvp);
1479 newvp = NULL;
1480 }
1481 if (info.nmi_v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1482 fmode &= ~O_EXCL;
1483 goto again;
1484 }
1485 } else if (info.nmi_v3 && (fmode & O_EXCL)) {
1486 getnanotime(&ts);
1487 if (vap->va_atime.tv_nsec == VNOVAL)
1488 vap->va_atime = ts;
1489 if (vap->va_mtime.tv_nsec == VNOVAL)
1490 vap->va_mtime = ts;
1491 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
1492 }
1493 if (!error) {
1494 if (cnp->cn_flags & MAKEENTRY)
1495 nfs_cache_enter(dvp, newvp, cnp);
1496 *ap->a_vpp = newvp;
1497 }
1498 pool_put(&namei_pool, cnp->cn_pnbuf);
1499 VTONFS(dvp)->n_flag |= NMODIFIED;
1500 if (!wccflag)
1501 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
1502 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1503 return (error);
1504 }
1505
1506 /*
1507 * nfs file remove call
1508 * To try and make nfs semantics closer to ufs semantics, a file that has
1509 * other processes using the vnode is renamed instead of removed and then
1510 * removed later on the last close.
1511 * - If v_usecount > 1
1512 * If a rename is not already in the works
1513 * call nfs_sillyrename() to set it up
1514 * else
1515 * do the remove rpc
1516 */
1517 int
1518 nfs_remove(void *v)
1519 {
1520 struct vop_remove_args *ap = v;
1521 struct vnode *vp = ap->a_vp;
1522 struct vnode *dvp = ap->a_dvp;
1523 struct componentname *cnp = ap->a_cnp;
1524 struct nfsnode *np = VTONFS(vp);
1525 int error = 0;
1526 struct vattr vattr;
1527
1528 #ifdef DIAGNOSTIC
1529 if ((cnp->cn_flags & HASBUF) == 0)
1530 panic("nfs_remove: no name");
1531 if (vp->v_usecount < 1)
1532 panic("nfs_remove: bad v_usecount");
1533 #endif
1534 if (vp->v_type == VDIR)
1535 error = EPERM;
1536 else if (vp->v_usecount == 1 || (np->n_sillyrename &&
1537 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 &&
1538 vattr.va_nlink > 1)) {
1539 /*
1540 * Purge the name cache so that the chance of a lookup for
1541 * the name succeeding while the remove is in progress is
1542 * minimized. Without node locking it can still happen, such
1543 * that an I/O op returns ESTALE, but since you get this if
1544 * another host removes the file..
1545 */
1546 cache_purge(vp);
1547 /*
1548 * throw away biocache buffers, mainly to avoid
1549 * unnecessary delayed writes later.
1550 */
1551 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc);
1552 /* Do the rpc */
1553 if (error != EINTR)
1554 error = nfs_removerpc(dvp, cnp->cn_nameptr,
1555 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc);
1556 /*
1557 * Kludge City: If the first reply to the remove rpc is lost..
1558 * the reply to the retransmitted request will be ENOENT
1559 * since the file was in fact removed
1560 * Therefore, we cheat and return success.
1561 */
1562 if (error == ENOENT)
1563 error = 0;
1564 } else if (!np->n_sillyrename)
1565 error = nfs_sillyrename(dvp, vp, cnp);
1566 pool_put(&namei_pool, cnp->cn_pnbuf);
1567 NFS_INVALIDATE_ATTRCACHE(np);
1568 VN_KNOTE(vp, NOTE_DELETE);
1569 VN_KNOTE(dvp, NOTE_WRITE);
1570 if (vp == dvp)
1571 vrele(vp);
1572 else
1573 vput(vp);
1574 vput(dvp);
1575 return (error);
1576 }
1577
1578 /*
1579 * nfs file remove rpc called from nfs_inactive
1580 */
1581 int
1582 nfs_removeit(struct sillyrename *sp)
1583 {
1584 KASSERT(VOP_ISLOCKED(sp->s_dvp));
1585 /*
1586 * Make sure that the directory vnode is still valid.
1587 *
1588 * NFS can potentially try to nuke a silly *after* the directory
1589 * has already been pushed out on a forced unmount. Since the silly
1590 * is going to go away anyway, this is fine.
1591 */
1592 if (sp->s_dvp->v_type == VBAD)
1593 return (0);
1594 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1595 NULL));
1596 }
1597
1598 /*
1599 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1600 */
1601 int
1602 nfs_removerpc(struct vnode *dvp, char *name, int namelen, struct ucred *cred,
1603 struct proc *proc)
1604 {
1605 struct nfsm_info info;
1606 u_int32_t *tl;
1607 int32_t t1;
1608 caddr_t cp2;
1609 int error = 0, wccflag = NFSV3_WCCRATTR;
1610
1611 info.nmi_v3 = NFS_ISV3(dvp);
1612
1613 nfsstats.rpccnt[NFSPROC_REMOVE]++;
1614 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
1615 NFSX_UNSIGNED + nfsm_rndup(namelen));
1616 nfsm_fhtom(&info, dvp, info.nmi_v3);
1617 nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
1618
1619 info.nmi_procp = proc;
1620 info.nmi_cred = cred;
1621 error = nfs_request(dvp, NFSPROC_REMOVE, &info);
1622 if (info.nmi_v3)
1623 nfsm_wcc_data(dvp, wccflag);
1624 m_freem(info.nmi_mrep);
1625
1626 nfsmout:
1627 VTONFS(dvp)->n_flag |= NMODIFIED;
1628 if (!wccflag)
1629 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
1630 return (error);
1631 }
1632
1633 /*
1634 * nfs file rename call
1635 */
1636 int
1637 nfs_rename(void *v)
1638 {
1639 struct vop_rename_args *ap = v;
1640 struct vnode *fvp = ap->a_fvp;
1641 struct vnode *tvp = ap->a_tvp;
1642 struct vnode *fdvp = ap->a_fdvp;
1643 struct vnode *tdvp = ap->a_tdvp;
1644 struct componentname *tcnp = ap->a_tcnp;
1645 struct componentname *fcnp = ap->a_fcnp;
1646 int error;
1647
1648 #ifdef DIAGNOSTIC
1649 if ((tcnp->cn_flags & HASBUF) == 0 ||
1650 (fcnp->cn_flags & HASBUF) == 0)
1651 panic("nfs_rename: no name");
1652 #endif
1653 /* Check for cross-device rename */
1654 if ((fvp->v_mount != tdvp->v_mount) ||
1655 (tvp && (fvp->v_mount != tvp->v_mount))) {
1656 error = EXDEV;
1657 goto out;
1658 }
1659
1660 /*
1661 * If the tvp exists and is in use, sillyrename it before doing the
1662 * rename of the new file over it.
1663 */
1664 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
1665 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1666 VN_KNOTE(tvp, NOTE_DELETE);
1667 vput(tvp);
1668 tvp = NULL;
1669 }
1670
1671 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1672 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1673 tcnp->cn_proc);
1674
1675 VN_KNOTE(fdvp, NOTE_WRITE);
1676 VN_KNOTE(tdvp, NOTE_WRITE);
1677
1678 if (fvp->v_type == VDIR) {
1679 if (tvp != NULL && tvp->v_type == VDIR)
1680 cache_purge(tdvp);
1681 cache_purge(fdvp);
1682 }
1683 out:
1684 if (tdvp == tvp)
1685 vrele(tdvp);
1686 else
1687 vput(tdvp);
1688 if (tvp)
1689 vput(tvp);
1690 vrele(fdvp);
1691 vrele(fvp);
1692 /*
1693 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1694 */
1695 if (error == ENOENT)
1696 error = 0;
1697 return (error);
1698 }
1699
1700 /*
1701 * nfs file rename rpc called from nfs_remove() above
1702 */
1703 int
1704 nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
1705 struct sillyrename *sp)
1706 {
1707 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
1708 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, curproc));
1709 }
1710
1711 /*
1712 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
1713 */
1714 int
1715 nfs_renamerpc(struct vnode *fdvp, char *fnameptr, int fnamelen,
1716 struct vnode *tdvp, char *tnameptr, int tnamelen, struct ucred *cred,
1717 struct proc *proc)
1718 {
1719 struct nfsm_info info;
1720 u_int32_t *tl;
1721 int32_t t1;
1722 caddr_t cp2;
1723 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
1724
1725 info.nmi_v3 = NFS_ISV3(fdvp);
1726
1727 nfsstats.rpccnt[NFSPROC_RENAME]++;
1728 info.nmi_mb = info.nmi_mreq = nfsm_reqhead((NFSX_FH(info.nmi_v3) +
1729 NFSX_UNSIGNED) * 2 + nfsm_rndup(fnamelen) + nfsm_rndup(tnamelen));
1730 nfsm_fhtom(&info, fdvp, info.nmi_v3);
1731 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
1732 nfsm_fhtom(&info, tdvp, info.nmi_v3);
1733 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
1734
1735 info.nmi_procp = proc;
1736 info.nmi_cred = cred;
1737 error = nfs_request(fdvp, NFSPROC_RENAME, &info);
1738 if (info.nmi_v3) {
1739 nfsm_wcc_data(fdvp, fwccflag);
1740 nfsm_wcc_data(tdvp, twccflag);
1741 }
1742 m_freem(info.nmi_mrep);
1743
1744 nfsmout:
1745 VTONFS(fdvp)->n_flag |= NMODIFIED;
1746 VTONFS(tdvp)->n_flag |= NMODIFIED;
1747 if (!fwccflag)
1748 NFS_INVALIDATE_ATTRCACHE(VTONFS(fdvp));
1749 if (!twccflag)
1750 NFS_INVALIDATE_ATTRCACHE(VTONFS(tdvp));
1751 return (error);
1752 }
1753
1754 /*
1755 * nfs hard link create call
1756 */
1757 int
1758 nfs_link(void *v)
1759 {
1760 struct vop_link_args *ap = v;
1761 struct vnode *vp = ap->a_vp;
1762 struct vnode *dvp = ap->a_dvp;
1763 struct componentname *cnp = ap->a_cnp;
1764 struct nfsm_info info;
1765 u_int32_t *tl;
1766 int32_t t1;
1767 caddr_t cp2;
1768 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
1769
1770 info.nmi_v3 = NFS_ISV3(vp);
1771
1772 if (dvp->v_mount != vp->v_mount) {
1773 pool_put(&namei_pool, cnp->cn_pnbuf);
1774 vput(dvp);
1775 return (EXDEV);
1776 }
1777 error = vn_lock(vp, LK_EXCLUSIVE);
1778 if (error != 0) {
1779 VOP_ABORTOP(dvp, cnp);
1780 vput(dvp);
1781 return (error);
1782 }
1783
1784 /*
1785 * Push all writes to the server, so that the attribute cache
1786 * doesn't get "out of sync" with the server.
1787 * XXX There should be a better way!
1788 */
1789 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
1790
1791 nfsstats.rpccnt[NFSPROC_LINK]++;
1792 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(2 * NFSX_FH(info.nmi_v3) +
1793 NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1794 nfsm_fhtom(&info, vp, info.nmi_v3);
1795 nfsm_fhtom(&info, dvp, info.nmi_v3);
1796 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1797
1798 info.nmi_procp = cnp->cn_proc;
1799 info.nmi_cred = cnp->cn_cred;
1800 error = nfs_request(vp, NFSPROC_LINK, &info);
1801 if (info.nmi_v3) {
1802 nfsm_postop_attr(vp, attrflag);
1803 nfsm_wcc_data(dvp, wccflag);
1804 }
1805 m_freem(info.nmi_mrep);
1806 nfsmout:
1807 pool_put(&namei_pool, cnp->cn_pnbuf);
1808 VTONFS(dvp)->n_flag |= NMODIFIED;
1809 if (!attrflag)
1810 NFS_INVALIDATE_ATTRCACHE(VTONFS(vp));
1811 if (!wccflag)
1812 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
1813
1814 VN_KNOTE(vp, NOTE_LINK);
1815 VN_KNOTE(dvp, NOTE_WRITE);
1816 VOP_UNLOCK(vp);
1817 vput(dvp);
1818 return (error);
1819 }
1820
1821 /*
1822 * nfs symbolic link create call
1823 */
1824 int
1825 nfs_symlink(void *v)
1826 {
1827 struct vop_symlink_args *ap = v;
1828 struct vnode *dvp = ap->a_dvp;
1829 struct vattr *vap = ap->a_vap;
1830 struct componentname *cnp = ap->a_cnp;
1831 struct nfsv2_sattr *sp;
1832 struct nfsm_info info;
1833 u_int32_t *tl;
1834 int32_t t1;
1835 caddr_t cp2;
1836 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
1837 struct vnode *newvp = NULL;
1838
1839 info.nmi_v3 = NFS_ISV3(dvp);
1840
1841 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1842 slen = strlen(ap->a_target);
1843 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
1844 2 * NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) +
1845 NFSX_SATTR(info.nmi_v3));
1846 nfsm_fhtom(&info, dvp, info.nmi_v3);
1847 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1848 if (info.nmi_v3)
1849 nfsm_v3attrbuild(&info.nmi_mb, vap, 0);
1850 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1851 if (!info.nmi_v3) {
1852 sp = nfsm_build(&info.nmi_mb, NFSX_V2SATTR);
1853 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
1854 sp->sa_uid = nfs_xdrneg1;
1855 sp->sa_gid = nfs_xdrneg1;
1856 sp->sa_size = nfs_xdrneg1;
1857 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1858 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1859 }
1860
1861 info.nmi_procp = cnp->cn_proc;
1862 info.nmi_cred = cnp->cn_cred;
1863 error = nfs_request(dvp, NFSPROC_SYMLINK, &info);
1864 if (info.nmi_v3) {
1865 if (!error)
1866 nfsm_mtofh(dvp, newvp, info.nmi_v3, gotvp);
1867 nfsm_wcc_data(dvp, wccflag);
1868 }
1869 m_freem(info.nmi_mrep);
1870
1871 nfsmout:
1872 if (newvp)
1873 vput(newvp);
1874 pool_put(&namei_pool, cnp->cn_pnbuf);
1875 VTONFS(dvp)->n_flag |= NMODIFIED;
1876 if (!wccflag)
1877 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
1878 VN_KNOTE(dvp, NOTE_WRITE);
1879 vput(dvp);
1880 return (error);
1881 }
1882
1883 /*
1884 * nfs make dir call
1885 */
1886 int
1887 nfs_mkdir(void *v)
1888 {
1889 struct vop_mkdir_args *ap = v;
1890 struct vnode *dvp = ap->a_dvp;
1891 struct vattr *vap = ap->a_vap;
1892 struct componentname *cnp = ap->a_cnp;
1893 struct nfsv2_sattr *sp;
1894 struct nfsm_info info;
1895 u_int32_t *tl;
1896 int32_t t1;
1897 int len;
1898 struct nfsnode *np = NULL;
1899 struct vnode *newvp = NULL;
1900 caddr_t cp2;
1901 int error = 0, wccflag = NFSV3_WCCRATTR;
1902 int gotvp = 0;
1903
1904 info.nmi_v3 = NFS_ISV3(dvp);
1905
1906 len = cnp->cn_namelen;
1907 nfsstats.rpccnt[NFSPROC_MKDIR]++;
1908 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
1909 NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(info.nmi_v3));
1910 nfsm_fhtom(&info, dvp, info.nmi_v3);
1911 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1912
1913 if (info.nmi_v3) {
1914 nfsm_v3attrbuild(&info.nmi_mb, vap, 0);
1915 } else {
1916 sp = nfsm_build(&info.nmi_mb, NFSX_V2SATTR);
1917 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
1918 sp->sa_uid = nfs_xdrneg1;
1919 sp->sa_gid = nfs_xdrneg1;
1920 sp->sa_size = nfs_xdrneg1;
1921 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1922 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1923 }
1924
1925 info.nmi_procp = cnp->cn_proc;
1926 info.nmi_cred = cnp->cn_cred;
1927 error = nfs_request(dvp, NFSPROC_MKDIR, &info);
1928 if (!error)
1929 nfsm_mtofh(dvp, newvp, info.nmi_v3, gotvp);
1930 if (info.nmi_v3)
1931 nfsm_wcc_data(dvp, wccflag);
1932 m_freem(info.nmi_mrep);
1933
1934 nfsmout:
1935 VTONFS(dvp)->n_flag |= NMODIFIED;
1936 if (!wccflag)
1937 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
1938
1939 if (error == 0 && newvp == NULL) {
1940 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
1941 cnp->cn_proc, &np);
1942 if (!error) {
1943 newvp = NFSTOV(np);
1944 if (newvp->v_type != VDIR)
1945 error = EEXIST;
1946 }
1947 }
1948 if (error) {
1949 if (newvp)
1950 vput(newvp);
1951 } else {
1952 VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
1953 if (cnp->cn_flags & MAKEENTRY)
1954 nfs_cache_enter(dvp, newvp, cnp);
1955 *ap->a_vpp = newvp;
1956 }
1957 pool_put(&namei_pool, cnp->cn_pnbuf);
1958 vput(dvp);
1959 return (error);
1960 }
1961
1962 /*
1963 * nfs remove directory call
1964 */
1965 int
1966 nfs_rmdir(void *v)
1967 {
1968 struct vop_rmdir_args *ap = v;
1969 struct vnode *vp = ap->a_vp;
1970 struct vnode *dvp = ap->a_dvp;
1971 struct componentname *cnp = ap->a_cnp;
1972 struct nfsm_info info;
1973 u_int32_t *tl;
1974 int32_t t1;
1975 caddr_t cp2;
1976 int error = 0, wccflag = NFSV3_WCCRATTR;
1977
1978 info.nmi_v3 = NFS_ISV3(dvp);
1979
1980 nfsstats.rpccnt[NFSPROC_RMDIR]++;
1981 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) +
1982 NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1983 nfsm_fhtom(&info, dvp, info.nmi_v3);
1984 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1985
1986 info.nmi_procp = cnp->cn_proc;
1987 info.nmi_cred = cnp->cn_cred;
1988 error = nfs_request(dvp, NFSPROC_RMDIR, &info);
1989 if (info.nmi_v3)
1990 nfsm_wcc_data(dvp, wccflag);
1991 m_freem(info.nmi_mrep);
1992
1993 nfsmout:
1994 pool_put(&namei_pool, cnp->cn_pnbuf);
1995 VTONFS(dvp)->n_flag |= NMODIFIED;
1996 if (!wccflag)
1997 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
1998
1999 VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
2000 VN_KNOTE(vp, NOTE_DELETE);
2001
2002 cache_purge(vp);
2003 vput(vp);
2004 vput(dvp);
2005 /*
2006 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2007 */
2008 if (error == ENOENT)
2009 error = 0;
2010 return (error);
2011 }
2012
2013
2014 /*
2015 * The readdir logic below has a big design bug. It stores the NFS cookie in
2016 * the returned uio->uio_offset but does not store the verifier (it cannot).
2017 * Instead, the code stores the verifier in the nfsnode and applies that
2018 * verifies to all cookies, no matter what verifier was originally with
2019 * the cookie.
2020 *
2021 * From a practical standpoint, this is not a problem since almost all
2022 * NFS servers do not change the validity of cookies across deletes
2023 * and inserts.
2024 */
2025
2026 struct nfs_dirent {
2027 u_int32_t cookie[2];
2028 struct dirent dirent;
2029 };
2030
2031 #define NFS_DIRHDSIZ (sizeof (struct nfs_dirent) - (MAXNAMLEN + 1))
2032 #define NFS_DIRENT_OVERHEAD offsetof(struct nfs_dirent, dirent)
2033
2034 /*
2035 * nfs readdir call
2036 */
2037 int
2038 nfs_readdir(void *v)
2039 {
2040 struct vop_readdir_args *ap = v;
2041 struct vnode *vp = ap->a_vp;
2042 struct nfsnode *np = VTONFS(vp);
2043 struct uio *uio = ap->a_uio;
2044 int tresid, error = 0;
2045 struct vattr vattr;
2046 int cnt;
2047 u_int64_t newoff = uio->uio_offset;
2048 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2049 struct uio readdir_uio;
2050 struct iovec readdir_iovec;
2051 struct proc * p = uio->uio_procp;
2052 int done = 0, eof = 0;
2053 struct ucred *cred = ap->a_cred;
2054 void *data;
2055
2056 if (vp->v_type != VDIR)
2057 return (EPERM);
2058 /*
2059 * First, check for hit on the EOF offset cache
2060 */
2061 if (np->n_direofoffset != 0 &&
2062 uio->uio_offset == np->n_direofoffset) {
2063 if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
2064 timespeccmp(&np->n_mtime, &vattr.va_mtime, ==)) {
2065 nfsstats.direofcache_hits++;
2066 *ap->a_eofflag = 1;
2067 return (0);
2068 }
2069 }
2070
2071 if (uio->uio_resid < NFS_FABLKSIZE)
2072 return (EINVAL);
2073
2074 tresid = uio->uio_resid;
2075
2076 if (uio->uio_rw != UIO_READ)
2077 return (EINVAL);
2078
2079 if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
2080 (void)nfs_fsinfo(nmp, vp, cred, p);
2081
2082 cnt = 5;
2083
2084 /* M_ZERO to avoid leaking kernel data in dirent padding */
2085 data = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK|M_ZERO);
2086 do {
2087 struct nfs_dirent *ndp = data;
2088
2089 readdir_iovec.iov_len = NFS_DIRBLKSIZ;
2090 readdir_iovec.iov_base = data;
2091 readdir_uio.uio_offset = newoff;
2092 readdir_uio.uio_iov = &readdir_iovec;
2093 readdir_uio.uio_iovcnt = 1;
2094 readdir_uio.uio_segflg = UIO_SYSSPACE;
2095 readdir_uio.uio_rw = UIO_READ;
2096 readdir_uio.uio_resid = NFS_DIRBLKSIZ;
2097 readdir_uio.uio_procp = curproc;
2098
2099 if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
2100 error = nfs_readdirplusrpc(vp, &readdir_uio, cred,
2101 &eof, p);
2102 if (error == NFSERR_NOTSUPP)
2103 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
2104 }
2105 if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
2106 error = nfs_readdirrpc(vp, &readdir_uio, cred, &eof);
2107
2108 if (error == NFSERR_BAD_COOKIE)
2109 error = EINVAL;
2110
2111 while (error == 0 &&
2112 ndp < (struct nfs_dirent *)readdir_iovec.iov_base) {
2113 struct dirent *dp = &ndp->dirent;
2114 int reclen = dp->d_reclen;
2115
2116 dp->d_reclen -= NFS_DIRENT_OVERHEAD;
2117 dp->d_off = fxdr_hyper(&ndp->cookie[0]);
2118
2119 if (uio->uio_resid < dp->d_reclen) {
2120 eof = 0;
2121 done = 1;
2122 break;
2123 }
2124
2125 if ((error = uiomove(dp, dp->d_reclen, uio)))
2126 break;
2127
2128 newoff = fxdr_hyper(&ndp->cookie[0]);
2129
2130 ndp = (struct nfs_dirent *)((u_int8_t *)ndp + reclen);
2131 }
2132 } while (!error && !done && !eof && cnt--);
2133
2134 free(data, M_TEMP, NFS_DIRBLKSIZ);
2135 data = NULL;
2136
2137 uio->uio_offset = newoff;
2138
2139 if (!error && (eof || uio->uio_resid == tresid)) {
2140 nfsstats.direofcache_misses++;
2141 *ap->a_eofflag = 1;
2142 return (0);
2143 }
2144
2145 *ap->a_eofflag = 0;
2146 return (error);
2147 }
2148
2149
2150 /*
2151 * The function below stuff the cookies in after the name
2152 */
2153
2154 /*
2155 * Readdir rpc call.
2156 */
2157 int
2158 nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
2159 int *end_of_directory)
2160 {
2161 int len, left;
2162 struct nfs_dirent *ndp = NULL;
2163 struct dirent *dp = NULL;
2164 struct nfsm_info info;
2165 u_int32_t *tl;
2166 caddr_t cp;
2167 int32_t t1;
2168 caddr_t cp2;
2169 nfsuint64 cookie;
2170 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2171 struct nfsnode *dnp = VTONFS(vp);
2172 u_quad_t fileno;
2173 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2174 int attrflag;
2175
2176 info.nmi_v3 = NFS_ISV3(vp);
2177
2178 #ifdef DIAGNOSTIC
2179 if (uiop->uio_iovcnt != 1 ||
2180 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2181 panic("nfs readdirrpc bad uio");
2182 #endif
2183
2184 txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2185
2186 /*
2187 * Loop around doing readdir rpc's of size nm_readdirsize
2188 * truncated to a multiple of NFS_READDIRBLKSIZ.
2189 * The stopping criteria is EOF or buffer full.
2190 */
2191 while (more_dirs && bigenough) {
2192 nfsstats.rpccnt[NFSPROC_READDIR]++;
2193 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3)
2194 + NFSX_READDIR(info.nmi_v3));
2195 nfsm_fhtom(&info, vp, info.nmi_v3);
2196 if (info.nmi_v3) {
2197 tl = nfsm_build(&info.nmi_mb, 5 * NFSX_UNSIGNED);
2198 *tl++ = cookie.nfsuquad[0];
2199 *tl++ = cookie.nfsuquad[1];
2200 if (cookie.nfsuquad[0] == 0 &&
2201 cookie.nfsuquad[1] == 0) {
2202 *tl++ = 0;
2203 *tl++ = 0;
2204 } else {
2205 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2206 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2207 }
2208 } else {
2209 tl = nfsm_build(&info.nmi_mb, 2 * NFSX_UNSIGNED);
2210 *tl++ = cookie.nfsuquad[1];
2211 }
2212 *tl = txdr_unsigned(nmp->nm_readdirsize);
2213
2214 info.nmi_procp = uiop->uio_procp;
2215 info.nmi_cred = cred;
2216 error = nfs_request(vp, NFSPROC_READDIR, &info);
2217 if (info.nmi_v3)
2218 nfsm_postop_attr(vp, attrflag);
2219
2220 if (error) {
2221 m_freem(info.nmi_mrep);
2222 goto nfsmout;
2223 }
2224
2225 if (info.nmi_v3) {
2226 nfsm_dissect(tl, u_int32_t *,
2227 2 * NFSX_UNSIGNED);
2228 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2229 dnp->n_cookieverf.nfsuquad[1] = *tl;
2230 }
2231
2232 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2233 more_dirs = fxdr_unsigned(int, *tl);
2234
2235 /* loop thru the dir entries, doctoring them to dirent form */
2236 while (more_dirs && bigenough) {
2237 if (info.nmi_v3) {
2238 nfsm_dissect(tl, u_int32_t *,
2239 3 * NFSX_UNSIGNED);
2240 fileno = fxdr_hyper(tl);
2241 len = fxdr_unsigned(int, *(tl + 2));
2242 } else {
2243 nfsm_dissect(tl, u_int32_t *,
2244 2 * NFSX_UNSIGNED);
2245 fileno = fxdr_unsigned(u_quad_t, *tl++);
2246 len = fxdr_unsigned(int, *tl);
2247 }
2248 if (len <= 0 || len > NFS_MAXNAMLEN) {
2249 error = EBADRPC;
2250 m_freem(info.nmi_mrep);
2251 goto nfsmout;
2252 }
2253 tlen = DIRENT_RECSIZE(len) + NFS_DIRENT_OVERHEAD;
2254 left = NFS_READDIRBLKSIZ - blksiz;
2255 if (tlen > left) {
2256 dp->d_reclen += left;
2257 uiop->uio_iov->iov_base += left;
2258 uiop->uio_iov->iov_len -= left;
2259 uiop->uio_resid -= left;
2260 blksiz = 0;
2261 }
2262 if (tlen > uiop->uio_resid)
2263 bigenough = 0;
2264 if (bigenough) {
2265 ndp = (struct nfs_dirent *)
2266 uiop->uio_iov->iov_base;
2267 dp = &ndp->dirent;
2268 dp->d_fileno = fileno;
2269 dp->d_namlen = len;
2270 dp->d_reclen = tlen;
2271 dp->d_type = DT_UNKNOWN;
2272 blksiz += tlen;
2273 if (blksiz == NFS_READDIRBLKSIZ)
2274 blksiz = 0;
2275 uiop->uio_resid -= NFS_DIRHDSIZ;
2276 uiop->uio_iov->iov_base =
2277 (char *)uiop->uio_iov->iov_base +
2278 NFS_DIRHDSIZ;
2279 uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2280 nfsm_mtouio(uiop, len);
2281 cp = uiop->uio_iov->iov_base;
2282 tlen -= NFS_DIRHDSIZ + len;
2283 *cp = '\0'; /* null terminate */
2284 uiop->uio_iov->iov_base += tlen;
2285 uiop->uio_iov->iov_len -= tlen;
2286 uiop->uio_resid -= tlen;
2287 } else
2288 nfsm_adv(nfsm_rndup(len));
2289 if (info.nmi_v3) {
2290 nfsm_dissect(tl, u_int32_t *,
2291 3 * NFSX_UNSIGNED);
2292 } else {
2293 nfsm_dissect(tl, u_int32_t *,
2294 2 * NFSX_UNSIGNED);
2295 }
2296 if (bigenough) {
2297 if (info.nmi_v3) {
2298 ndp->cookie[0] = cookie.nfsuquad[0] =
2299 *tl++;
2300 } else
2301 ndp->cookie[0] = 0;
2302
2303 ndp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2304 } else if (info.nmi_v3)
2305 tl += 2;
2306 else
2307 tl++;
2308 more_dirs = fxdr_unsigned(int, *tl);
2309 }
2310 /*
2311 * If at end of rpc data, get the eof boolean
2312 */
2313 if (!more_dirs) {
2314 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2315 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2316 }
2317 m_freem(info.nmi_mrep);
2318 }
2319 /*
2320 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ
2321 * by increasing d_reclen for the last record.
2322 */
2323 if (blksiz > 0) {
2324 left = NFS_READDIRBLKSIZ - blksiz;
2325 dp->d_reclen += left;
2326 uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base +
2327 left;
2328 uiop->uio_iov->iov_len -= left;
2329 uiop->uio_resid -= left;
2330 }
2331
2332 /*
2333 * We are now either at the end of the directory or have filled the
2334 * block.
2335 */
2336 if (bigenough) {
2337 dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2338 if (end_of_directory) *end_of_directory = 1;
2339 } else {
2340 if (uiop->uio_resid > 0)
2341 printf("EEK! readdirrpc resid > 0\n");
2342 }
2343
2344 nfsmout:
2345 return (error);
2346 }
2347
2348 /*
2349 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2350 */
2351 int
2352 nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
2353 int *end_of_directory, struct proc *p)
2354 {
2355 int len, left;
2356 struct nfs_dirent *ndirp = NULL;
2357 struct dirent *dp = NULL;
2358 struct nfsm_info info;
2359 u_int32_t *tl;
2360 caddr_t cp;
2361 int32_t t1;
2362 struct vnode *newvp;
2363 caddr_t cp2, dpossav1, dpossav2;
2364 struct mbuf *mdsav1, *mdsav2;
2365 struct nameidata nami, *ndp = &nami;
2366 struct componentname *cnp = &ndp->ni_cnd;
2367 nfsuint64 cookie;
2368 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2369 struct nfsnode *dnp = VTONFS(vp), *np;
2370 nfsfh_t *fhp;
2371 u_quad_t fileno;
2372 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2373 int attrflag, fhsize;
2374
2375 #ifdef DIAGNOSTIC
2376 if (uiop->uio_iovcnt != 1 ||
2377 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2378 panic("nfs readdirplusrpc bad uio");
2379 #endif
2380 NDINIT(ndp, 0, 0, UIO_SYSSPACE, NULL, p);
2381 ndp->ni_dvp = vp;
2382 newvp = NULLVP;
2383
2384 txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2385
2386 /*
2387 * Loop around doing readdir rpc's of size nm_readdirsize
2388 * truncated to a multiple of NFS_READDIRBLKSIZ.
2389 * The stopping criteria is EOF or buffer full.
2390 */
2391 while (more_dirs && bigenough) {
2392 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2393 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2394 nfsm_fhtom(&info, vp, 1);
2395 tl = nfsm_build(&info.nmi_mb, 6 * NFSX_UNSIGNED);
2396 *tl++ = cookie.nfsuquad[0];
2397 *tl++ = cookie.nfsuquad[1];
2398 if (cookie.nfsuquad[0] == 0 &&
2399 cookie.nfsuquad[1] == 0) {
2400 *tl++ = 0;
2401 *tl++ = 0;
2402 } else {
2403 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2404 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2405 }
2406 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
2407 *tl = txdr_unsigned(nmp->nm_rsize);
2408
2409 info.nmi_procp = uiop->uio_procp;
2410 info.nmi_cred = cred;
2411 error = nfs_request(vp, NFSPROC_READDIRPLUS, &info);
2412 nfsm_postop_attr(vp, attrflag);
2413 if (error) {
2414 m_freem(info.nmi_mrep);
2415 goto nfsmout;
2416 }
2417
2418 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2419 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2420 dnp->n_cookieverf.nfsuquad[1] = *tl++;
2421 more_dirs = fxdr_unsigned(int, *tl);
2422
2423 /* loop thru the dir entries, doctoring them to 4bsd form */
2424 while (more_dirs && bigenough) {
2425 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2426 fileno = fxdr_hyper(tl);
2427 len = fxdr_unsigned(int, *(tl + 2));
2428 if (len <= 0 || len > NFS_MAXNAMLEN) {
2429 error = EBADRPC;
2430 m_freem(info.nmi_mrep);
2431 goto nfsmout;
2432 }
2433 tlen = DIRENT_RECSIZE(len) + NFS_DIRENT_OVERHEAD;
2434 left = NFS_READDIRBLKSIZ - blksiz;
2435 if (tlen > left) {
2436 dp->d_reclen += left;
2437 uiop->uio_iov->iov_base =
2438 (char *)uiop->uio_iov->iov_base + left;
2439 uiop->uio_iov->iov_len -= left;
2440 uiop->uio_resid -= left;
2441 blksiz = 0;
2442 }
2443 if (tlen > uiop->uio_resid)
2444 bigenough = 0;
2445 if (bigenough) {
2446 ndirp = (struct nfs_dirent *)
2447 uiop->uio_iov->iov_base;
2448 dp = &ndirp->dirent;
2449 dp->d_fileno = fileno;
2450 dp->d_namlen = len;
2451 dp->d_reclen = tlen;
2452 dp->d_type = DT_UNKNOWN;
2453 blksiz += tlen;
2454 if (blksiz == NFS_READDIRBLKSIZ)
2455 blksiz = 0;
2456 uiop->uio_resid -= NFS_DIRHDSIZ;
2457 uiop->uio_iov->iov_base =
2458 (char *)uiop->uio_iov->iov_base +
2459 NFS_DIRHDSIZ;
2460 uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2461 cnp->cn_nameptr = uiop->uio_iov->iov_base;
2462 cnp->cn_namelen = len;
2463 nfsm_mtouio(uiop, len);
2464 cp = uiop->uio_iov->iov_base;
2465 tlen -= NFS_DIRHDSIZ + len;
2466 *cp = '\0';
2467 uiop->uio_iov->iov_base += tlen;
2468 uiop->uio_iov->iov_len -= tlen;
2469 uiop->uio_resid -= tlen;
2470 } else
2471 nfsm_adv(nfsm_rndup(len));
2472 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2473 if (bigenough) {
2474 ndirp->cookie[0] = cookie.nfsuquad[0] = *tl++;
2475 ndirp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2476 } else
2477 tl += 2;
2478
2479 /*
2480 * Since the attributes are before the file handle
2481 * (sigh), we must skip over the attributes and then
2482 * come back and get them.
2483 */
2484 attrflag = fxdr_unsigned(int, *tl);
2485 if (attrflag) {
2486 dpossav1 = info.nmi_dpos;
2487 mdsav1 = info.nmi_md;
2488 nfsm_adv(NFSX_V3FATTR);
2489 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2490 doit = fxdr_unsigned(int, *tl);
2491 if (doit) {
2492 nfsm_getfh(fhp, fhsize, 1);
2493 if (NFS_CMPFH(dnp, fhp, fhsize)) {
2494 vref(vp);
2495 newvp = vp;
2496 np = dnp;
2497 } else {
2498 error = nfs_nget(vp->v_mount,
2499 fhp, fhsize, &np);
2500 if (error)
2501 doit = 0;
2502 else
2503 newvp = NFSTOV(np);
2504 }
2505 }
2506 if (doit && bigenough) {
2507 dpossav2 = info.nmi_dpos;
2508 info.nmi_dpos = dpossav1;
2509 mdsav2 = info.nmi_md;
2510 info.nmi_md = mdsav1;
2511 nfsm_loadattr(newvp, NULL);
2512 info.nmi_dpos = dpossav2;
2513 info.nmi_md = mdsav2;
2514 dp->d_type = IFTODT(
2515 VTTOIF(np->n_vattr.va_type));
2516 if (cnp->cn_namelen <=
2517 NAMECACHE_MAXLEN) {
2518 ndp->ni_vp = newvp;
2519 cache_purge(ndp->ni_dvp);
2520 nfs_cache_enter(ndp->ni_dvp,
2521 ndp->ni_vp, cnp);
2522 }
2523 }
2524 } else {
2525 /* Just skip over the file handle */
2526 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2527 i = fxdr_unsigned(int, *tl);
2528 if (i > 0)
2529 nfsm_adv(nfsm_rndup(i));
2530 }
2531 if (newvp != NULLVP) {
2532 if (newvp == vp)
2533 vrele(newvp);
2534 else
2535 vput(newvp);
2536 newvp = NULLVP;
2537 }
2538 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2539 more_dirs = fxdr_unsigned(int, *tl);
2540 }
2541 /*
2542 * If at end of rpc data, get the eof boolean
2543 */
2544 if (!more_dirs) {
2545 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2546 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2547 }
2548 m_freem(info.nmi_mrep);
2549 }
2550 /*
2551 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ
2552 * by increasing d_reclen for the last record.
2553 */
2554 if (blksiz > 0) {
2555 left = NFS_READDIRBLKSIZ - blksiz;
2556 dp->d_reclen += left;
2557 uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base +
2558 left;
2559 uiop->uio_iov->iov_len -= left;
2560 uiop->uio_resid -= left;
2561 }
2562
2563 /*
2564 * We are now either at the end of the directory or have filled the
2565 * block.
2566 */
2567 if (bigenough) {
2568 dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2569 if (end_of_directory) *end_of_directory = 1;
2570 } else {
2571 if (uiop->uio_resid > 0)
2572 printf("EEK! readdirplusrpc resid > 0\n");
2573 }
2574
2575 nfsmout:
2576 if (newvp != NULLVP) {
2577 if (newvp == vp)
2578 vrele(newvp);
2579 else
2580 vput(newvp);
2581 }
2582 return (error);
2583 }
2584
2585 /*
2586 * Silly rename. To make the NFS filesystem that is stateless look a little
2587 * more like the "ufs" a remove of an active vnode is translated to a rename
2588 * to a funny looking filename that is removed by nfs_inactive on the
2589 * nfsnode. There is the potential for another process on a different client
2590 * to create the same funny name between the nfs_lookitup() fails and the
2591 * nfs_rename() completes, but...
2592 */
2593 int
2594 nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
2595 {
2596 struct sillyrename *sp;
2597 struct nfsnode *np;
2598 int error;
2599
2600 cache_purge(dvp);
2601 np = VTONFS(vp);
2602 sp = malloc(sizeof(*sp), M_NFSREQ, M_WAITOK);
2603 sp->s_cred = crdup(cnp->cn_cred);
2604 sp->s_dvp = dvp;
2605 vref(dvp);
2606
2607 if (vp->v_type == VDIR) {
2608 #ifdef DIAGNOSTIC
2609 printf("nfs: sillyrename dir\n");
2610 #endif
2611 error = EINVAL;
2612 goto bad;
2613 }
2614
2615 /* Try lookitups until we get one that isn't there */
2616 while (1) {
2617 /* Fudge together a funny name */
2618 u_int32_t rnd[2];
2619
2620 arc4random_buf(&rnd, sizeof rnd);
2621 sp->s_namlen = snprintf(sp->s_name, sizeof sp->s_name,
2622 ".nfs%08X%08X", rnd[0], rnd[1]);
2623 if (sp->s_namlen > sizeof sp->s_name)
2624 sp->s_namlen = strlen(sp->s_name);
2625
2626 if (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2627 cnp->cn_proc, NULL))
2628 break;
2629 }
2630
2631 error = nfs_renameit(dvp, cnp, sp);
2632 if (error)
2633 goto bad;
2634 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2635 cnp->cn_proc, &np);
2636 np->n_sillyrename = sp;
2637 return (0);
2638 bad:
2639 vrele(sp->s_dvp);
2640 crfree(sp->s_cred);
2641 free(sp, M_NFSREQ, sizeof(*sp));
2642 return (error);
2643 }
2644
2645 /*
2646 * Look up a file name and optionally either update the file handle or
2647 * allocate an nfsnode, depending on the value of npp.
2648 * npp == NULL --> just do the lookup
2649 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2650 * handled too
2651 * *npp != NULL --> update the file handle in the vnode
2652 */
2653 int
2654 nfs_lookitup(struct vnode *dvp, char *name, int len, struct ucred *cred,
2655 struct proc *procp, struct nfsnode **npp)
2656 {
2657 struct nfsm_info info;
2658 u_int32_t *tl;
2659 int32_t t1;
2660 struct vnode *newvp = NULL;
2661 struct nfsnode *np, *dnp = VTONFS(dvp);
2662 caddr_t cp2;
2663 int error = 0, fhlen, attrflag = 0;
2664 nfsfh_t *nfhp;
2665
2666 info.nmi_v3 = NFS_ISV3(dvp);
2667
2668 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
2669 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) + NFSX_UNSIGNED +
2670 nfsm_rndup(len));
2671 nfsm_fhtom(&info, dvp, info.nmi_v3);
2672 nfsm_strtom(name, len, NFS_MAXNAMLEN);
2673
2674 info.nmi_procp = procp;
2675 info.nmi_cred = cred;
2676 error = nfs_request(dvp, NFSPROC_LOOKUP, &info);
2677 if (error && !info.nmi_v3) {
2678 m_freem(info.nmi_mrep);
2679 goto nfsmout;
2680 }
2681
2682 if (npp && !error) {
2683 nfsm_getfh(nfhp, fhlen, info.nmi_v3);
2684 if (*npp) {
2685 np = *npp;
2686 np->n_fhp = &np->n_fh;
2687 bcopy(nfhp, np->n_fhp, fhlen);
2688 np->n_fhsize = fhlen;
2689 newvp = NFSTOV(np);
2690 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2691 vref(dvp);
2692 newvp = dvp;
2693 np = dnp;
2694 } else {
2695 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2696 if (error) {
2697 m_freem(info.nmi_mrep);
2698 return (error);
2699 }
2700 newvp = NFSTOV(np);
2701 }
2702 if (info.nmi_v3) {
2703 nfsm_postop_attr(newvp, attrflag);
2704 if (!attrflag && *npp == NULL) {
2705 m_freem(info.nmi_mrep);
2706 if (newvp == dvp)
2707 vrele(newvp);
2708 else
2709 vput(newvp);
2710 return (ENOENT);
2711 }
2712 } else
2713 nfsm_loadattr(newvp, NULL);
2714 }
2715 m_freem(info.nmi_mrep);
2716 nfsmout:
2717 if (npp && *npp == NULL) {
2718 if (error) {
2719 if (newvp == dvp)
2720 vrele(newvp);
2721 else
2722 vput(newvp);
2723 } else
2724 *npp = np;
2725 }
2726 return (error);
2727 }
2728
2729 /*
2730 * Nfs Version 3 commit rpc
2731 */
2732 int
2733 nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct proc *procp)
2734 {
2735 struct nfsm_info info;
2736 u_int32_t *tl;
2737 int32_t t1;
2738 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2739 caddr_t cp2;
2740 int error = 0, wccflag = NFSV3_WCCRATTR;
2741
2742 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0)
2743 return (0);
2744 nfsstats.rpccnt[NFSPROC_COMMIT]++;
2745 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(1));
2746 nfsm_fhtom(&info, vp, 1);
2747
2748 tl = nfsm_build(&info.nmi_mb, 3 * NFSX_UNSIGNED);
2749 txdr_hyper(offset, tl);
2750 tl += 2;
2751 *tl = txdr_unsigned(cnt);
2752
2753 info.nmi_procp = procp;
2754 info.nmi_cred = VTONFS(vp)->n_wcred;
2755 error = nfs_request(vp, NFSPROC_COMMIT, &info);
2756 nfsm_wcc_data(vp, wccflag);
2757
2758 if (!error) {
2759 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
2760 if (bcmp(nmp->nm_verf, tl,
2761 NFSX_V3WRITEVERF)) {
2762 bcopy(tl, nmp->nm_verf,
2763 NFSX_V3WRITEVERF);
2764 error = NFSERR_STALEWRITEVERF;
2765 }
2766 }
2767 m_freem(info.nmi_mrep);
2768
2769 nfsmout:
2770 return (error);
2771 }
2772
2773 /*
2774 * Kludge City..
2775 * - make nfs_bmap() essentially a no-op that does no translation
2776 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
2777 * (Maybe I could use the process's page mapping, but I was concerned that
2778 * Kernel Write might not be enabled and also figured copyout() would do
2779 * a lot more work than bcopy() and also it currently happens in the
2780 * context of the swapper process (2).
2781 */
2782 int
2783 nfs_bmap(void *v)
2784 {
2785 struct vop_bmap_args *ap = v;
2786 struct vnode *vp = ap->a_vp;
2787
2788 if (ap->a_vpp != NULL)
2789 *ap->a_vpp = vp;
2790 if (ap->a_bnp != NULL)
2791 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
2792 return (0);
2793 }
2794
2795 /*
2796 * Strategy routine.
2797 * For async requests when nfsiod(s) are running, queue the request by
2798 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2799 * request.
2800 */
2801 int
2802 nfs_strategy(void *v)
2803 {
2804 struct vop_strategy_args *ap = v;
2805 struct buf *bp = ap->a_bp;
2806 struct proc *p;
2807 int error = 0;
2808
2809 if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC))
2810 panic("nfs physio/async");
2811 if (bp->b_flags & B_ASYNC)
2812 p = NULL;
2813 else
2814 p = curproc; /* XXX */
2815 /*
2816 * If the op is asynchronous and an i/o daemon is waiting
2817 * queue the request, wake it up and wait for completion
2818 * otherwise just do it ourselves.
2819 */
2820 if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp, 0))
2821 error = nfs_doio(bp, p);
2822 return (error);
2823 }
2824
2825 /*
2826 * fsync vnode op. Just call nfs_flush() with commit == 1.
2827 */
2828 int
2829 nfs_fsync(void *v)
2830 {
2831 struct vop_fsync_args *ap = v;
2832
2833 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));
2834 }
2835
2836 /*
2837 * Flush all the blocks associated with a vnode.
2838 * Walk through the buffer pool and push any dirty pages
2839 * associated with the vnode.
2840 */
2841 int
2842 nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct proc *p,
2843 int commit)
2844 {
2845 struct nfsnode *np = VTONFS(vp);
2846 struct buf *bp;
2847 int i;
2848 struct buf *nbp;
2849 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2850 uint64_t slptimeo = INFSLP;
2851 int s, error = 0, slpflag = 0, retv, bvecpos;
2852 int dirty, passone = 1;
2853 u_quad_t off = (u_quad_t)-1, endoff = 0, toff;
2854 #ifndef NFS_COMMITBVECSIZ
2855 #define NFS_COMMITBVECSIZ 20
2856 #endif
2857 struct buf *bvec[NFS_COMMITBVECSIZ];
2858
2859 if (nmp->nm_flag & NFSMNT_INT)
2860 slpflag = PCATCH;
2861 if (!commit)
2862 passone = 0;
2863 /*
2864 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
2865 * server, but nas not been committed to stable storage on the server
2866 * yet. On the first pass, the byte range is worked out and the commit
2867 * rpc is done. On the second pass, nfs_writebp() is called to do the
2868 * job.
2869 */
2870 again:
2871 bvecpos = 0;
2872 if (NFS_ISV3(vp) && commit) {
2873 s = splbio();
2874 LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) {
2875 if (bvecpos >= NFS_COMMITBVECSIZ)
2876 break;
2877 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2878 != (B_DELWRI | B_NEEDCOMMIT))
2879 continue;
2880 bremfree(bp);
2881 bp->b_flags |= B_WRITEINPROG;
2882 buf_acquire(bp);
2883
2884 /*
2885 * A list of these buffers is kept so that the
2886 * second loop knows which buffers have actually
2887 * been committed. This is necessary, since there
2888 * may be a race between the commit rpc and new
2889 * uncommitted writes on the file.
2890 */
2891 bvec[bvecpos++] = bp;
2892 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2893 bp->b_dirtyoff;
2894 if (toff < off)
2895 off = toff;
2896 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2897 if (toff > endoff)
2898 endoff = toff;
2899 }
2900 splx(s);
2901 }
2902 if (bvecpos > 0) {
2903 /*
2904 * Commit data on the server, as required.
2905 */
2906 bcstats.pendingwrites++;
2907 bcstats.numwrites++;
2908 retv = nfs_commit(vp, off, (int)(endoff - off), p);
2909 if (retv == NFSERR_STALEWRITEVERF)
2910 nfs_clearcommit(vp->v_mount);
2911 /*
2912 * Now, either mark the blocks I/O done or mark the
2913 * blocks dirty, depending on whether the commit
2914 * succeeded.
2915 */
2916 for (i = 0; i < bvecpos; i++) {
2917 bp = bvec[i];
2918 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG);
2919 if (retv) {
2920 if (i == 0)
2921 bcstats.pendingwrites--;
2922 brelse(bp);
2923 } else {
2924 if (i > 0)
2925 bcstats.pendingwrites++;
2926 s = splbio();
2927 buf_undirty(bp);
2928 vp->v_numoutput++;
2929 bp->b_flags |= B_ASYNC;
2930 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
2931 bp->b_dirtyoff = bp->b_dirtyend = 0;
2932 biodone(bp);
2933 splx(s);
2934 }
2935 }
2936 }
2937
2938 /*
2939 * Start/do any write(s) that are required.
2940 */
2941 loop:
2942 s = splbio();
2943 LIST_FOREACH_SAFE(bp, &vp->v_dirtyblkhd, b_vnbufs, nbp) {
2944 if (bp->b_flags & B_BUSY) {
2945 if (waitfor != MNT_WAIT || passone)
2946 continue;
2947 bp->b_flags |= B_WANTED;
2948 error = tsleep_nsec(bp, slpflag | (PRIBIO + 1),
2949 "nfsfsync", slptimeo);
2950 splx(s);
2951 if (error) {
2952 if (nfs_sigintr(nmp, NULL, p))
2953 return (EINTR);
2954 if (slpflag == PCATCH) {
2955 slpflag = 0;
2956 slptimeo = SEC_TO_NSEC(2);
2957 }
2958 }
2959 goto loop;
2960 }
2961 if ((bp->b_flags & B_DELWRI) == 0)
2962 panic("nfs_fsync: not dirty");
2963 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT))
2964 continue;
2965 bremfree(bp);
2966 if (passone || !commit) {
2967 bp->b_flags |= B_ASYNC;
2968 } else {
2969 bp->b_flags |= (B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
2970 }
2971 buf_acquire(bp);
2972 splx(s);
2973 VOP_BWRITE(bp);
2974 goto loop;
2975 }
2976 splx(s);
2977 if (passone) {
2978 passone = 0;
2979 goto again;
2980 }
2981 if (waitfor == MNT_WAIT) {
2982 loop2:
2983 s = splbio();
2984 error = vwaitforio(vp, slpflag, "nfs_fsync", slptimeo);
2985 if (error) {
2986 splx(s);
2987 if (nfs_sigintr(nmp, NULL, p))
2988 return (EINTR);
2989 if (slpflag == PCATCH) {
2990 slpflag = 0;
2991 slptimeo = SEC_TO_NSEC(2);
2992 }
2993 goto loop2;
2994 }
2995 dirty = (!LIST_EMPTY(&vp->v_dirtyblkhd) && commit);
2996 splx(s);
2997 if (dirty) {
2998 #if 0
2999 vprint("nfs_fsync: dirty", vp);
3000 #endif
3001 goto loop;
3002 }
3003 }
3004 if (np->n_flag & NWRITEERR) {
3005 error = np->n_error;
3006 np->n_flag &= ~NWRITEERR;
3007 }
3008 return (error);
3009 }
3010
3011 /*
3012 * Return POSIX pathconf information applicable to nfs.
3013 * Fake it. For v3 we could ask the server, but such code
3014 * hasn't been written yet.
3015 */
3016 /* ARGSUSED */
3017 int
3018 nfs_pathconf(void *v)
3019 {
3020 struct vop_pathconf_args *ap = v;
3021 struct nfsmount *nmp = VFSTONFS(ap->a_vp->v_mount);
3022 int error = 0;
3023
3024 switch (ap->a_name) {
3025 case _PC_LINK_MAX:
3026 *ap->a_retval = LINK_MAX;
3027 break;
3028 case _PC_NAME_MAX:
3029 *ap->a_retval = NAME_MAX;
3030 break;
3031 case _PC_CHOWN_RESTRICTED:
3032 *ap->a_retval = 1;
3033 break;
3034 case _PC_NO_TRUNC:
3035 *ap->a_retval = 1;
3036 break;
3037 case _PC_ALLOC_SIZE_MIN:
3038 *ap->a_retval = NFS_FABLKSIZE;
3039 break;
3040 case _PC_FILESIZEBITS:
3041 *ap->a_retval = 64;
3042 break;
3043 case _PC_REC_INCR_XFER_SIZE:
3044 *ap->a_retval = min(nmp->nm_rsize, nmp->nm_wsize);
3045 break;
3046 case _PC_REC_MAX_XFER_SIZE:
3047 *ap->a_retval = -1; /* means ``unlimited'' */
3048 break;
3049 case _PC_REC_MIN_XFER_SIZE:
3050 *ap->a_retval = min(nmp->nm_rsize, nmp->nm_wsize);
3051 break;
3052 case _PC_REC_XFER_ALIGN:
3053 *ap->a_retval = PAGE_SIZE;
3054 break;
3055 case _PC_SYMLINK_MAX:
3056 *ap->a_retval = MAXPATHLEN;
3057 break;
3058 case _PC_2_SYMLINKS:
3059 *ap->a_retval = 1;
3060 break;
3061 case _PC_TIMESTAMP_RESOLUTION:
3062 *ap->a_retval = NFS_ISV3(ap->a_vp) ? 1 : 1000;
3063 break;
3064 default:
3065 error = EINVAL;
3066 break;
3067 }
3068
3069 return (error);
3070 }
3071
3072 /*
3073 * NFS advisory byte-level locks.
3074 */
3075 int
3076 nfs_advlock(void *v)
3077 {
3078 struct vop_advlock_args *ap = v;
3079 struct nfsnode *np = VTONFS(ap->a_vp);
3080
3081 return (lf_advlock(&np->n_lockf, np->n_size, ap->a_id, ap->a_op,
3082 ap->a_fl, ap->a_flags));
3083 }
3084
3085 /*
3086 * Print out the contents of an nfsnode.
3087 */
3088 int
3089 nfs_print(void *v)
3090 {
3091 struct vop_print_args *ap = v;
3092 struct vnode *vp = ap->a_vp;
3093 struct nfsnode *np = VTONFS(vp);
3094
3095 printf("tag VT_NFS, fileid %lld fsid 0x%lx",
3096 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
3097 #ifdef FIFO
3098 if (vp->v_type == VFIFO)
3099 fifo_printinfo(vp);
3100 #endif
3101 printf("\n");
3102 return (0);
3103 }
3104
3105 /*
3106 * Just call nfs_writebp() with the force argument set to 1.
3107 */
3108 int
3109 nfs_bwrite(void *v)
3110 {
3111 struct vop_bwrite_args *ap = v;
3112
3113 return (nfs_writebp(ap->a_bp, 1));
3114 }
3115
3116 /*
3117 * This is a clone of vop_generic_bwrite(), except that B_WRITEINPROG isn't set unless
3118 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
3119 */
3120 int
3121 nfs_writebp(struct buf *bp, int force)
3122 {
3123 int oldflags = bp->b_flags, retv = 1;
3124 struct proc *p = curproc; /* XXX */
3125 off_t off;
3126 size_t cnt;
3127 int s;
3128 struct vnode *vp;
3129 struct nfsnode *np;
3130
3131 if(!(bp->b_flags & B_BUSY))
3132 panic("bwrite: buffer is not busy???");
3133
3134 vp = bp->b_vp;
3135 np = VTONFS(vp);
3136
3137 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
3138
3139 s = splbio();
3140 buf_undirty(bp);
3141
3142 if ((oldflags & B_ASYNC) && !(oldflags & B_DELWRI) && p)
3143 ++p->p_ru.ru_oublock;
3144
3145 bp->b_vp->v_numoutput++;
3146 splx(s);
3147
3148 /*
3149 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3150 * an actual write will have to be scheduled via. VOP_STRATEGY().
3151 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3152 */
3153 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
3154 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
3155 cnt = bp->b_dirtyend - bp->b_dirtyoff;
3156
3157 rw_enter_write(&np->n_commitlock);
3158 if (!(bp->b_flags & B_NEEDCOMMIT)) {
3159 rw_exit_write(&np->n_commitlock);
3160 return (0);
3161 }
3162
3163 /*
3164 * If it's already been committed by somebody else,
3165 * bail.
3166 */
3167 if (!nfs_in_committed_range(vp, bp)) {
3168 int pushedrange = 0;
3169 /*
3170 * Since we're going to do this, push as much
3171 * as we can.
3172 */
3173
3174 if (nfs_in_tobecommitted_range(vp, bp)) {
3175 pushedrange = 1;
3176 off = np->n_pushlo;
3177 cnt = np->n_pushhi - np->n_pushlo;
3178 }
3179
3180 bp->b_flags |= B_WRITEINPROG;
3181 bcstats.pendingwrites++;
3182 bcstats.numwrites++;
3183 retv = nfs_commit(bp->b_vp, off, cnt, curproc);
3184 bp->b_flags &= ~B_WRITEINPROG;
3185
3186 if (retv == 0) {
3187 if (pushedrange)
3188 nfs_merge_commit_ranges(vp);
3189 else
3190 nfs_add_committed_range(vp, bp);
3191 } else
3192 bcstats.pendingwrites--;
3193 } else
3194 retv = 0; /* It has already been committed. */
3195
3196 rw_exit_write(&np->n_commitlock);
3197 if (!retv) {
3198 bp->b_dirtyoff = bp->b_dirtyend = 0;
3199 bp->b_flags &= ~B_NEEDCOMMIT;
3200 s = splbio();
3201 biodone(bp);
3202 splx(s);
3203 } else if (retv == NFSERR_STALEWRITEVERF)
3204 nfs_clearcommit(bp->b_vp->v_mount);
3205 }
3206 if (retv) {
3207 buf_flip_dma(bp);
3208 if (force)
3209 bp->b_flags |= B_WRITEINPROG;
3210 VOP_STRATEGY(bp->b_vp, bp);
3211 }
3212
3213 if( (oldflags & B_ASYNC) == 0) {
3214 int rtval;
3215
3216 bp->b_flags |= B_RAW;
3217 rtval = biowait(bp);
3218 if (!(oldflags & B_DELWRI) && p) {
3219 ++p->p_ru.ru_oublock;
3220 }
3221 brelse(bp);
3222 return (rtval);
3223 }
3224
3225 return (0);
3226 }
3227
3228 /*
3229 * nfs special file access vnode op.
3230 * Essentially just get vattr and then imitate iaccess() since the device is
3231 * local to the client.
3232 */
3233 int
3234 nfsspec_access(void *v)
3235 {
3236 struct vop_access_args *ap = v;
3237 struct vattr va;
3238 struct vnode *vp = ap->a_vp;
3239 int error;
3240
3241 /*
3242 * Disallow write attempts on filesystems mounted read-only;
3243 * unless the file is a socket, fifo, or a block or character
3244 * device resident on the filesystem.
3245 */
3246 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3247 switch (vp->v_type) {
3248 case VREG:
3249 case VDIR:
3250 case VLNK:
3251 return (EROFS);
3252 default:
3253 break;
3254 }
3255 }
3256
3257 error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_p);
3258 if (error)
3259 return (error);
3260
3261 return (vaccess(vp->v_type, va.va_mode, va.va_uid, va.va_gid,
3262 ap->a_mode, ap->a_cred));
3263 }
3264
3265 /*
3266 * Read wrapper for special devices.
3267 */
3268 int
3269 nfsspec_read(void *v)
3270 {
3271 struct vop_read_args *ap = v;
3272 struct nfsnode *np = VTONFS(ap->a_vp);
3273
3274 /*
3275 * Set access flag.
3276 */
3277 np->n_flag |= NACC;
3278 getnanotime(&np->n_atim);
3279 return (spec_read(ap));
3280 }
3281
3282 /*
3283 * Write wrapper for special devices.
3284 */
3285 int
3286 nfsspec_write(void *v)
3287 {
3288 struct vop_write_args *ap = v;
3289 struct nfsnode *np = VTONFS(ap->a_vp);
3290
3291 /*
3292 * Set update flag.
3293 */
3294 np->n_flag |= NUPD;
3295 getnanotime(&np->n_mtim);
3296 return (spec_write(ap));
3297 }
3298
3299 /*
3300 * Close wrapper for special devices.
3301 *
3302 * Update the times on the nfsnode then do device close.
3303 */
3304 int
3305 nfsspec_close(void *v)
3306 {
3307 struct vop_close_args *ap = v;
3308 struct vnode *vp = ap->a_vp;
3309 struct nfsnode *np = VTONFS(vp);
3310 struct vattr vattr;
3311
3312 if (np->n_flag & (NACC | NUPD)) {
3313 np->n_flag |= NCHG;
3314 if (vp->v_usecount == 1 &&
3315 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3316 VATTR_NULL(&vattr);
3317 if (np->n_flag & NACC)
3318 vattr.va_atime = np->n_atim;
3319 if (np->n_flag & NUPD)
3320 vattr.va_mtime = np->n_mtim;
3321 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3322 }
3323 }
3324 return (spec_close(ap));
3325 }
3326
3327 #ifdef FIFO
3328 /*
3329 * Read wrapper for fifos.
3330 */
3331 int
3332 nfsfifo_read(void *v)
3333 {
3334 struct vop_read_args *ap = v;
3335 struct nfsnode *np = VTONFS(ap->a_vp);
3336
3337 /*
3338 * Set access flag.
3339 */
3340 np->n_flag |= NACC;
3341 getnanotime(&np->n_atim);
3342 return (fifo_read(ap));
3343 }
3344
3345 /*
3346 * Write wrapper for fifos.
3347 */
3348 int
3349 nfsfifo_write(void *v)
3350 {
3351 struct vop_write_args *ap = v;
3352 struct nfsnode *np = VTONFS(ap->a_vp);
3353
3354 /*
3355 * Set update flag.
3356 */
3357 np->n_flag |= NUPD;
3358 getnanotime(&np->n_mtim);
3359 return (fifo_write(ap));
3360 }
3361
3362 /*
3363 * Close wrapper for fifos.
3364 *
3365 * Update the times on the nfsnode then do fifo close.
3366 */
3367 int
3368 nfsfifo_close(void *v)
3369 {
3370 struct vop_close_args *ap = v;
3371 struct vnode *vp = ap->a_vp;
3372 struct nfsnode *np = VTONFS(vp);
3373 struct vattr vattr;
3374
3375 if (np->n_flag & (NACC | NUPD)) {
3376 if (np->n_flag & NACC) {
3377 getnanotime(&np->n_atim);
3378 }
3379 if (np->n_flag & NUPD) {
3380 getnanotime(&np->n_mtim);
3381 }
3382 np->n_flag |= NCHG;
3383 if (vp->v_usecount == 1 &&
3384 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3385 VATTR_NULL(&vattr);
3386 if (np->n_flag & NACC)
3387 vattr.va_atime = np->n_atim;
3388 if (np->n_flag & NUPD)
3389 vattr.va_mtime = np->n_mtim;
3390 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3391 }
3392 }
3393 return (fifo_close(ap));
3394 }
3395
3396 int
3397 nfsfifo_reclaim(void *v)
3398 {
3399 fifo_reclaim(v);
3400 return (nfs_reclaim(v));
3401 }
3402 #endif /* ! FIFO */
Cache object: 56679604123a88dc272b4b34c016c99d
|