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