FreeBSD/Linux Kernel Cross Reference
sys/nfs/nfs_vnops.c
1 /* $NetBSD: nfs_vnops.c,v 1.220.2.2 2006/07/16 12:21:21 ghen 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.220.2.2 2006/07/16 12:21:21 ghen 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 int nfs_linkrpc(struct vnode *, struct vnode *, const char *,
256 size_t, struct ucred *, struct proc *);
257 static void nfs_writerpc_extfree(struct mbuf *, caddr_t, size_t, void *);
258
259 /*
260 * Global variables
261 */
262 extern u_int32_t nfs_true, nfs_false;
263 extern u_int32_t nfs_xdrneg1;
264 extern const nfstype nfsv3_type[9];
265
266 int nfs_numasync = 0;
267 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
268
269 static void nfs_cache_enter(struct vnode *, struct vnode *,
270 struct componentname *);
271
272 static void
273 nfs_cache_enter(struct vnode *dvp, struct vnode *vp,
274 struct componentname *cnp)
275 {
276 struct nfsnode *dnp = VTONFS(dvp);
277
278 if (vp != NULL) {
279 struct nfsnode *np = VTONFS(vp);
280
281 np->n_ctime = np->n_vattr->va_ctime.tv_sec;
282 }
283
284 if (!timespecisset(&dnp->n_nctime))
285 dnp->n_nctime = dnp->n_vattr->va_mtime;
286
287 cache_enter(dvp, vp, cnp);
288 }
289
290 /*
291 * nfs null call from vfs.
292 */
293 int
294 nfs_null(vp, cred, procp)
295 struct vnode *vp;
296 struct ucred *cred;
297 struct proc *procp;
298 {
299 caddr_t bpos, dpos;
300 int error = 0;
301 struct mbuf *mreq, *mrep, *md, *mb;
302 struct nfsnode *np = VTONFS(vp);
303
304 nfsm_reqhead(np, NFSPROC_NULL, 0);
305 nfsm_request(np, NFSPROC_NULL, procp, cred);
306 nfsm_reqdone;
307 return (error);
308 }
309
310 /*
311 * nfs access vnode op.
312 * For nfs version 2, just return ok. File accesses may fail later.
313 * For nfs version 3, use the access rpc to check accessibility. If file modes
314 * are changed on the server, accesses might still fail later.
315 */
316 int
317 nfs_access(v)
318 void *v;
319 {
320 struct vop_access_args /* {
321 struct vnode *a_vp;
322 int a_mode;
323 struct ucred *a_cred;
324 struct proc *a_p;
325 } */ *ap = v;
326 struct vnode *vp = ap->a_vp;
327 #ifndef NFS_V2_ONLY
328 u_int32_t *tl;
329 caddr_t cp;
330 int32_t t1, t2;
331 caddr_t bpos, dpos, cp2;
332 int error = 0, attrflag;
333 struct mbuf *mreq, *mrep, *md, *mb;
334 u_int32_t mode, rmode;
335 const int v3 = NFS_ISV3(vp);
336 #endif
337 int cachevalid;
338 struct nfsnode *np = VTONFS(vp);
339 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
340
341 cachevalid = (np->n_accstamp != -1 &&
342 (mono_time.tv_sec - np->n_accstamp) < NFS_ATTRTIMEO(nmp, np) &&
343 np->n_accuid == ap->a_cred->cr_uid);
344
345 /*
346 * Check access cache first. If this request has been made for this
347 * uid shortly before, use the cached result.
348 */
349 if (cachevalid) {
350 if (!np->n_accerror) {
351 if ((np->n_accmode & ap->a_mode) == ap->a_mode)
352 return np->n_accerror;
353 } else if ((np->n_accmode & ap->a_mode) == np->n_accmode)
354 return np->n_accerror;
355 }
356
357 #ifndef NFS_V2_ONLY
358 /*
359 * For nfs v3, do an access rpc, otherwise you are stuck emulating
360 * ufs_access() locally using the vattr. This may not be correct,
361 * since the server may apply other access criteria such as
362 * client uid-->server uid mapping that we do not know about, but
363 * this is better than just returning anything that is lying about
364 * in the cache.
365 */
366 if (v3) {
367 nfsstats.rpccnt[NFSPROC_ACCESS]++;
368 nfsm_reqhead(np, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
369 nfsm_fhtom(np, v3);
370 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
371 if (ap->a_mode & VREAD)
372 mode = NFSV3ACCESS_READ;
373 else
374 mode = 0;
375 if (vp->v_type != VDIR) {
376 if (ap->a_mode & VWRITE)
377 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
378 if (ap->a_mode & VEXEC)
379 mode |= NFSV3ACCESS_EXECUTE;
380 } else {
381 if (ap->a_mode & VWRITE)
382 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
383 NFSV3ACCESS_DELETE);
384 if (ap->a_mode & VEXEC)
385 mode |= NFSV3ACCESS_LOOKUP;
386 }
387 *tl = txdr_unsigned(mode);
388 nfsm_request(np, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
389 nfsm_postop_attr(vp, attrflag, 0);
390 if (!error) {
391 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
392 rmode = fxdr_unsigned(u_int32_t, *tl);
393 /*
394 * The NFS V3 spec does not clarify whether or not
395 * the returned access bits can be a superset of
396 * the ones requested, so...
397 */
398 if ((rmode & mode) != mode)
399 error = EACCES;
400 }
401 nfsm_reqdone;
402 } else
403 #endif
404 return (nfsspec_access(ap));
405 #ifndef NFS_V2_ONLY
406 /*
407 * Disallow write attempts on filesystems mounted read-only;
408 * unless the file is a socket, fifo, or a block or character
409 * device resident on the filesystem.
410 */
411 if (!error && (ap->a_mode & VWRITE) &&
412 (vp->v_mount->mnt_flag & MNT_RDONLY)) {
413 switch (vp->v_type) {
414 case VREG:
415 case VDIR:
416 case VLNK:
417 error = EROFS;
418 default:
419 break;
420 }
421 }
422
423 if (!error || error == EACCES) {
424 /*
425 * If we got the same result as for a previous,
426 * different request, OR it in. Don't update
427 * the timestamp in that case.
428 */
429 if (cachevalid && np->n_accstamp != -1 &&
430 error == np->n_accerror) {
431 if (!error)
432 np->n_accmode |= ap->a_mode;
433 else if ((np->n_accmode & ap->a_mode) == ap->a_mode)
434 np->n_accmode = ap->a_mode;
435 } else {
436 np->n_accstamp = mono_time.tv_sec;
437 np->n_accuid = ap->a_cred->cr_uid;
438 np->n_accmode = ap->a_mode;
439 np->n_accerror = error;
440 }
441 }
442
443 return (error);
444 #endif
445 }
446
447 /*
448 * nfs open vnode op
449 * Check to see if the type is ok
450 * and that deletion is not in progress.
451 * For paged in text files, you will need to flush the page cache
452 * if consistency is lost.
453 */
454 /* ARGSUSED */
455 int
456 nfs_open(v)
457 void *v;
458 {
459 struct vop_open_args /* {
460 struct vnode *a_vp;
461 int a_mode;
462 struct ucred *a_cred;
463 struct proc *a_p;
464 } */ *ap = v;
465 struct vnode *vp = ap->a_vp;
466 struct nfsnode *np = VTONFS(vp);
467 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
468 int error;
469
470 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
471 return (EACCES);
472 }
473
474 if (ap->a_mode & FREAD) {
475 if (np->n_rcred != NULL)
476 crfree(np->n_rcred);
477 np->n_rcred = ap->a_cred;
478 crhold(np->n_rcred);
479 }
480 if (ap->a_mode & FWRITE) {
481 if (np->n_wcred != NULL)
482 crfree(np->n_wcred);
483 np->n_wcred = ap->a_cred;
484 crhold(np->n_wcred);
485 }
486
487 #ifndef NFS_V2_ONLY
488 /*
489 * Get a valid lease. If cached data is stale, flush it.
490 */
491 if (nmp->nm_flag & NFSMNT_NQNFS) {
492 if (NQNFS_CKINVALID(vp, np, ND_READ)) {
493 do {
494 error = nqnfs_getlease(vp, ND_READ, ap->a_cred,
495 ap->a_p);
496 } while (error == NQNFS_EXPIRED);
497 if (error)
498 return (error);
499 if (np->n_lrev != np->n_brev ||
500 (np->n_flag & NQNFSNONCACHE)) {
501 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
502 ap->a_p, 1)) == EINTR)
503 return (error);
504 np->n_brev = np->n_lrev;
505 }
506 }
507 } else
508 #endif
509 {
510 error = nfs_flushstalebuf(vp, ap->a_cred, ap->a_p, 0);
511 if (error)
512 return error;
513 }
514 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
515 NFS_INVALIDATE_ATTRCACHE(np); /* For Open/Close consistency */
516 return (0);
517 }
518
519 /*
520 * nfs close vnode op
521 * What an NFS client should do upon close after writing is a debatable issue.
522 * Most NFS clients push delayed writes to the server upon close, basically for
523 * two reasons:
524 * 1 - So that any write errors may be reported back to the client process
525 * doing the close system call. By far the two most likely errors are
526 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
527 * 2 - To put a worst case upper bound on cache inconsistency between
528 * multiple clients for the file.
529 * There is also a consistency problem for Version 2 of the protocol w.r.t.
530 * not being able to tell if other clients are writing a file concurrently,
531 * since there is no way of knowing if the changed modify time in the reply
532 * is only due to the write for this client.
533 * (NFS Version 3 provides weak cache consistency data in the reply that
534 * should be sufficient to detect and handle this case.)
535 *
536 * The current code does the following:
537 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
538 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
539 * or commit them (this satisfies 1 and 2 except for the
540 * case where the server crashes after this close but
541 * before the commit RPC, which is felt to be "good
542 * enough". Changing the last argument to nfs_flush() to
543 * a 1 would force a commit operation, if it is felt a
544 * commit is necessary now.
545 * for NQNFS - do nothing now, since 2 is dealt with via leases and
546 * 1 should be dealt with via an fsync() system call for
547 * cases where write errors are important.
548 */
549 /* ARGSUSED */
550 int
551 nfs_close(v)
552 void *v;
553 {
554 struct vop_close_args /* {
555 struct vnodeop_desc *a_desc;
556 struct vnode *a_vp;
557 int a_fflag;
558 struct ucred *a_cred;
559 struct proc *a_p;
560 } */ *ap = v;
561 struct vnode *vp = ap->a_vp;
562 struct nfsnode *np = VTONFS(vp);
563 int error = 0;
564 UVMHIST_FUNC("nfs_close"); UVMHIST_CALLED(ubchist);
565
566 if (vp->v_type == VREG) {
567 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
568 (np->n_flag & NMODIFIED)) {
569 #ifndef NFS_V2_ONLY
570 if (NFS_ISV3(vp)) {
571 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0);
572 np->n_flag &= ~NMODIFIED;
573 } else
574 #endif
575 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
576 NFS_INVALIDATE_ATTRCACHE(np);
577 }
578 if (np->n_flag & NWRITEERR) {
579 np->n_flag &= ~NWRITEERR;
580 error = np->n_error;
581 }
582 }
583 UVMHIST_LOG(ubchist, "returning %d", error,0,0,0);
584 return (error);
585 }
586
587 /*
588 * nfs getattr call from vfs.
589 */
590 int
591 nfs_getattr(v)
592 void *v;
593 {
594 struct vop_getattr_args /* {
595 struct vnode *a_vp;
596 struct vattr *a_vap;
597 struct ucred *a_cred;
598 struct proc *a_p;
599 } */ *ap = v;
600 struct vnode *vp = ap->a_vp;
601 struct nfsnode *np = VTONFS(vp);
602 caddr_t cp;
603 u_int32_t *tl;
604 int32_t t1, t2;
605 caddr_t bpos, dpos;
606 int error = 0;
607 struct mbuf *mreq, *mrep, *md, *mb;
608 const int v3 = NFS_ISV3(vp);
609
610 /*
611 * Update local times for special files.
612 */
613 if (np->n_flag & (NACC | NUPD))
614 np->n_flag |= NCHG;
615
616 /*
617 * if we have delayed truncation, do it now.
618 */
619 nfs_delayedtruncate(vp);
620
621 /*
622 * First look in the cache.
623 */
624 if (nfs_getattrcache(vp, ap->a_vap) == 0)
625 return (0);
626 nfsstats.rpccnt[NFSPROC_GETATTR]++;
627 nfsm_reqhead(np, NFSPROC_GETATTR, NFSX_FH(v3));
628 nfsm_fhtom(np, v3);
629 nfsm_request(np, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
630 if (!error) {
631 nfsm_loadattr(vp, ap->a_vap, 0);
632 if (vp->v_type == VDIR &&
633 ap->a_vap->va_blocksize < NFS_DIRFRAGSIZ)
634 ap->a_vap->va_blocksize = NFS_DIRFRAGSIZ;
635 }
636 nfsm_reqdone;
637 return (error);
638 }
639
640 /*
641 * nfs setattr call.
642 */
643 int
644 nfs_setattr(v)
645 void *v;
646 {
647 struct vop_setattr_args /* {
648 struct vnodeop_desc *a_desc;
649 struct vnode *a_vp;
650 struct vattr *a_vap;
651 struct ucred *a_cred;
652 struct proc *a_p;
653 } */ *ap = v;
654 struct vnode *vp = ap->a_vp;
655 struct nfsnode *np = VTONFS(vp);
656 struct vattr *vap = ap->a_vap;
657 int error = 0;
658 u_quad_t tsize = 0;
659
660 /*
661 * Setting of flags is not supported.
662 */
663 if (vap->va_flags != VNOVAL)
664 return (EOPNOTSUPP);
665
666 /*
667 * Disallow write attempts if the filesystem is mounted read-only.
668 */
669 if ((vap->va_uid != (uid_t)VNOVAL ||
670 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
671 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
672 (vp->v_mount->mnt_flag & MNT_RDONLY))
673 return (EROFS);
674 if (vap->va_size != VNOVAL) {
675 switch (vp->v_type) {
676 case VDIR:
677 return (EISDIR);
678 case VCHR:
679 case VBLK:
680 case VSOCK:
681 case VFIFO:
682 if (vap->va_mtime.tv_sec == VNOVAL &&
683 vap->va_atime.tv_sec == VNOVAL &&
684 vap->va_mode == (mode_t)VNOVAL &&
685 vap->va_uid == (uid_t)VNOVAL &&
686 vap->va_gid == (gid_t)VNOVAL)
687 return (0);
688 vap->va_size = VNOVAL;
689 break;
690 default:
691 /*
692 * Disallow write attempts if the filesystem is
693 * mounted read-only.
694 */
695 if (vp->v_mount->mnt_flag & MNT_RDONLY)
696 return (EROFS);
697 uvm_vnp_setsize(vp, vap->va_size);
698 tsize = np->n_size;
699 np->n_size = vap->va_size;
700 if (vap->va_size == 0)
701 error = nfs_vinvalbuf(vp, 0,
702 ap->a_cred, ap->a_p, 1);
703 else
704 error = nfs_vinvalbuf(vp, V_SAVE,
705 ap->a_cred, ap->a_p, 1);
706 if (error) {
707 uvm_vnp_setsize(vp, tsize);
708 return (error);
709 }
710 np->n_vattr->va_size = vap->va_size;
711 }
712 } else if ((vap->va_mtime.tv_sec != VNOVAL ||
713 vap->va_atime.tv_sec != VNOVAL) &&
714 vp->v_type == VREG &&
715 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
716 ap->a_p, 1)) == EINTR)
717 return (error);
718 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
719 if (error && vap->va_size != VNOVAL) {
720 np->n_size = np->n_vattr->va_size = tsize;
721 uvm_vnp_setsize(vp, np->n_size);
722 }
723 VN_KNOTE(vp, NOTE_ATTRIB);
724 return (error);
725 }
726
727 /*
728 * Do an nfs setattr rpc.
729 */
730 int
731 nfs_setattrrpc(vp, vap, cred, procp)
732 struct vnode *vp;
733 struct vattr *vap;
734 struct ucred *cred;
735 struct proc *procp;
736 {
737 struct nfsv2_sattr *sp;
738 caddr_t cp;
739 int32_t t1, t2;
740 caddr_t bpos, dpos;
741 u_int32_t *tl;
742 int error = 0;
743 struct mbuf *mreq, *mrep, *md, *mb;
744 const int v3 = NFS_ISV3(vp);
745 struct nfsnode *np = VTONFS(vp);
746 #ifndef NFS_V2_ONLY
747 int wccflag = NFSV3_WCCRATTR;
748 caddr_t cp2;
749 #endif
750
751 nfsstats.rpccnt[NFSPROC_SETATTR]++;
752 nfsm_reqhead(np, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
753 nfsm_fhtom(np, v3);
754 #ifndef NFS_V2_ONLY
755 if (v3) {
756 nfsm_v3attrbuild(vap, TRUE);
757 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
758 *tl = nfs_false;
759 } else {
760 #endif
761 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
762 if (vap->va_mode == (mode_t)VNOVAL)
763 sp->sa_mode = nfs_xdrneg1;
764 else
765 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
766 if (vap->va_uid == (uid_t)VNOVAL)
767 sp->sa_uid = nfs_xdrneg1;
768 else
769 sp->sa_uid = txdr_unsigned(vap->va_uid);
770 if (vap->va_gid == (gid_t)VNOVAL)
771 sp->sa_gid = nfs_xdrneg1;
772 else
773 sp->sa_gid = txdr_unsigned(vap->va_gid);
774 sp->sa_size = txdr_unsigned(vap->va_size);
775 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
776 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
777 #ifndef NFS_V2_ONLY
778 }
779 #endif
780 nfsm_request(np, NFSPROC_SETATTR, procp, cred);
781 #ifndef NFS_V2_ONLY
782 if (v3) {
783 nfsm_wcc_data(vp, wccflag, 0, FALSE);
784 } else
785 #endif
786 nfsm_loadattr(vp, (struct vattr *)0, 0);
787 nfsm_reqdone;
788 return (error);
789 }
790
791 /*
792 * nfs lookup call, one step at a time...
793 * First look in cache
794 * If not found, unlock the directory nfsnode and do the rpc
795 *
796 * This code is full of lock/unlock statements and checks, because
797 * we continue after cache_lookup has finished (we need to check
798 * with the attr cache and do an rpc if it has timed out). This means
799 * that the locking effects of cache_lookup have to be taken into
800 * account.
801 */
802 int
803 nfs_lookup(v)
804 void *v;
805 {
806 struct vop_lookup_args /* {
807 struct vnodeop_desc *a_desc;
808 struct vnode *a_dvp;
809 struct vnode **a_vpp;
810 struct componentname *a_cnp;
811 } */ *ap = v;
812 struct componentname *cnp = ap->a_cnp;
813 struct vnode *dvp = ap->a_dvp;
814 struct vnode **vpp = ap->a_vpp;
815 int flags;
816 struct vnode *newvp;
817 u_int32_t *tl;
818 caddr_t cp;
819 int32_t t1, t2;
820 caddr_t bpos, dpos, cp2;
821 struct mbuf *mreq, *mrep, *md, *mb;
822 long len;
823 nfsfh_t *fhp;
824 struct nfsnode *np;
825 int lockparent, wantparent, error = 0, attrflag, fhsize;
826 const int v3 = NFS_ISV3(dvp);
827
828 cnp->cn_flags &= ~PDIRUNLOCK;
829 flags = cnp->cn_flags;
830
831 *vpp = NULLVP;
832 newvp = NULLVP;
833 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
834 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
835 return (EROFS);
836 if (dvp->v_type != VDIR)
837 return (ENOTDIR);
838
839 /*
840 * RFC1813(nfsv3) 3.2 says clients should handle "." by themselves.
841 */
842 if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
843 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
844 if (error)
845 return error;
846 if (cnp->cn_nameiop == RENAME && (flags & ISLASTCN))
847 return EISDIR;
848 VREF(dvp);
849 *vpp = dvp;
850 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
851 cnp->cn_flags |= SAVENAME;
852 return 0;
853 }
854
855 lockparent = flags & LOCKPARENT;
856 wantparent = flags & (LOCKPARENT|WANTPARENT);
857 np = VTONFS(dvp);
858
859 /*
860 * Before tediously performing a linear scan of the directory,
861 * check the name cache to see if the directory/name pair
862 * we are looking for is known already.
863 * If the directory/name pair is found in the name cache,
864 * we have to ensure the directory has not changed from
865 * the time the cache entry has been created. If it has,
866 * the cache entry has to be ignored.
867 */
868 error = cache_lookup_raw(dvp, vpp, cnp);
869 KASSERT(dvp != *vpp);
870 if (error >= 0) {
871 struct vattr vattr;
872 int err2;
873
874 if (error && error != ENOENT) {
875 *vpp = NULLVP;
876 return error;
877 }
878
879 err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
880 if (err2 != 0) {
881 if (error == 0)
882 vrele(*vpp);
883 *vpp = NULLVP;
884 return err2;
885 }
886
887 if (VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
888 cnp->cn_proc) || timespeccmp(&vattr.va_mtime,
889 &VTONFS(dvp)->n_nctime, !=)) {
890 if (error == 0) {
891 vrele(*vpp);
892 *vpp = NULLVP;
893 }
894 cache_purge1(dvp, NULL, PURGE_CHILDREN);
895 timespecclear(&np->n_nctime);
896 goto dorpc;
897 }
898
899 if (error == ENOENT) {
900 goto noentry;
901 }
902
903 newvp = *vpp;
904 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)
905 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
906 nfsstats.lookupcache_hits++;
907 if ((flags & ISDOTDOT) != 0 ||
908 (~flags & (LOCKPARENT|ISLASTCN)) != 0) {
909 VOP_UNLOCK(dvp, 0);
910 cnp->cn_flags |= PDIRUNLOCK;
911 }
912 error = vn_lock(newvp, LK_EXCLUSIVE);
913 if (error) {
914 /* newvp has been revoked. */
915 vrele(newvp);
916 *vpp = NULL;
917 return error;
918 }
919 if ((~flags & (LOCKPARENT|ISLASTCN)) == 0
920 && (cnp->cn_flags & PDIRUNLOCK)) {
921 KASSERT(flags & ISDOTDOT);
922 error = vn_lock(dvp, LK_EXCLUSIVE);
923 if (error) {
924 vput(newvp);
925 *vpp = NULL;
926 return error;
927 }
928 cnp->cn_flags &= ~PDIRUNLOCK;
929 }
930 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
931 cnp->cn_flags |= SAVENAME;
932 KASSERT(newvp->v_type != VNON);
933 return (0);
934 }
935 cache_purge1(newvp, NULL, PURGE_PARENTS);
936 vrele(newvp);
937 *vpp = NULLVP;
938 }
939 dorpc:
940 #if 0
941 /*
942 * because nfsv3 has the same CREATE semantics as ours,
943 * we don't have to perform LOOKUPs beforehand.
944 *
945 * XXX ideally we can do the same for nfsv2 in the case of !O_EXCL.
946 * XXX although we have no way to know if O_EXCL is requested or not.
947 */
948
949 if (v3 && cnp->cn_nameiop == CREATE &&
950 (flags & (ISLASTCN|ISDOTDOT)) == ISLASTCN &&
951 (dvp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
952 KASSERT(lockparent);
953 cnp->cn_flags |= SAVENAME;
954 return (EJUSTRETURN);
955 }
956 #endif /* 0 */
957
958 error = 0;
959 newvp = NULLVP;
960 nfsstats.lookupcache_misses++;
961 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
962 len = cnp->cn_namelen;
963 nfsm_reqhead(np, NFSPROC_LOOKUP,
964 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
965 nfsm_fhtom(np, v3);
966 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
967 nfsm_request(np, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
968 if (error) {
969 nfsm_postop_attr(dvp, attrflag, 0);
970 m_freem(mrep);
971 goto nfsmout;
972 }
973 nfsm_getfh(fhp, fhsize, v3);
974
975 /*
976 * Handle RENAME case...
977 */
978 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
979 if (NFS_CMPFH(np, fhp, fhsize)) {
980 m_freem(mrep);
981 return (EISDIR);
982 }
983 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
984 if (error) {
985 m_freem(mrep);
986 return error;
987 }
988 newvp = NFSTOV(np);
989 #ifndef NFS_V2_ONLY
990 if (v3) {
991 nfsm_postop_attr(newvp, attrflag, 0);
992 nfsm_postop_attr(dvp, attrflag, 0);
993 } else
994 #endif
995 nfsm_loadattr(newvp, (struct vattr *)0, 0);
996 *vpp = newvp;
997 m_freem(mrep);
998 cnp->cn_flags |= SAVENAME;
999 if (!lockparent) {
1000 VOP_UNLOCK(dvp, 0);
1001 cnp->cn_flags |= PDIRUNLOCK;
1002 }
1003 goto validate;
1004 }
1005
1006 /*
1007 * The postop attr handling is duplicated for each if case,
1008 * because it should be done while dvp is locked (unlocking
1009 * dvp is different for each case).
1010 */
1011
1012 if (NFS_CMPFH(np, fhp, fhsize)) {
1013 /*
1014 * "." lookup
1015 */
1016 VREF(dvp);
1017 newvp = dvp;
1018 #ifndef NFS_V2_ONLY
1019 if (v3) {
1020 nfsm_postop_attr(newvp, attrflag, 0);
1021 nfsm_postop_attr(dvp, attrflag, 0);
1022 } else
1023 #endif
1024 nfsm_loadattr(newvp, (struct vattr *)0, 0);
1025 } else if (flags & ISDOTDOT) {
1026 /*
1027 * ".." lookup
1028 */
1029 VOP_UNLOCK(dvp, 0);
1030 cnp->cn_flags |= PDIRUNLOCK;
1031
1032 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1033 if (error) {
1034 if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY) == 0)
1035 cnp->cn_flags &= ~PDIRUNLOCK;
1036 m_freem(mrep);
1037 return error;
1038 }
1039 newvp = NFSTOV(np);
1040
1041 #ifndef NFS_V2_ONLY
1042 if (v3) {
1043 nfsm_postop_attr(newvp, attrflag, 0);
1044 nfsm_postop_attr(dvp, attrflag, 0);
1045 } else
1046 #endif
1047 nfsm_loadattr(newvp, (struct vattr *)0, 0);
1048
1049 if (lockparent && (flags & ISLASTCN)) {
1050 if ((error = vn_lock(dvp, LK_EXCLUSIVE))) {
1051 m_freem(mrep);
1052 vput(newvp);
1053 return error;
1054 }
1055 cnp->cn_flags &= ~PDIRUNLOCK;
1056 }
1057 } else {
1058 /*
1059 * Other lookups.
1060 */
1061 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1062 if (error) {
1063 m_freem(mrep);
1064 return error;
1065 }
1066 newvp = NFSTOV(np);
1067 #ifndef NFS_V2_ONLY
1068 if (v3) {
1069 nfsm_postop_attr(newvp, attrflag, 0);
1070 nfsm_postop_attr(dvp, attrflag, 0);
1071 } else
1072 #endif
1073 nfsm_loadattr(newvp, (struct vattr *)0, 0);
1074 if (!lockparent || !(flags & ISLASTCN)) {
1075 VOP_UNLOCK(dvp, 0);
1076 cnp->cn_flags |= PDIRUNLOCK;
1077 }
1078 }
1079 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1080 cnp->cn_flags |= SAVENAME;
1081 if ((cnp->cn_flags & MAKEENTRY) &&
1082 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
1083 nfs_cache_enter(dvp, newvp, cnp);
1084 }
1085 *vpp = newvp;
1086 nfsm_reqdone;
1087 if (error) {
1088 /*
1089 * We get here only because of errors returned by
1090 * the RPC. Otherwise we'll have returned above
1091 * (the nfsm_* macros will jump to nfsm_reqdone
1092 * on error).
1093 */
1094 if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) &&
1095 cnp->cn_nameiop != CREATE) {
1096 nfs_cache_enter(dvp, NULL, cnp);
1097 }
1098 if (newvp != NULLVP) {
1099 vrele(newvp);
1100 if (newvp != dvp)
1101 VOP_UNLOCK(newvp, 0);
1102 }
1103 noentry:
1104 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
1105 (flags & ISLASTCN) && error == ENOENT) {
1106 if (dvp->v_mount->mnt_flag & MNT_RDONLY) {
1107 error = EROFS;
1108 } else {
1109 error = EJUSTRETURN;
1110 cnp->cn_flags |= SAVENAME;
1111 }
1112 }
1113 *vpp = NULL;
1114 return error;
1115 }
1116
1117 validate:
1118 /*
1119 * make sure we have valid type and size.
1120 */
1121
1122 newvp = *vpp;
1123 if (newvp->v_type == VNON) {
1124 struct vattr vattr; /* dummy */
1125
1126 KASSERT(VTONFS(newvp)->n_attrstamp == 0);
1127 error = VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc);
1128 if (error) {
1129 vput(newvp);
1130 *vpp = NULL;
1131 }
1132 }
1133
1134 return error;
1135 }
1136
1137 /*
1138 * nfs read call.
1139 * Just call nfs_bioread() to do the work.
1140 */
1141 int
1142 nfs_read(v)
1143 void *v;
1144 {
1145 struct vop_read_args /* {
1146 struct vnode *a_vp;
1147 struct uio *a_uio;
1148 int a_ioflag;
1149 struct ucred *a_cred;
1150 } */ *ap = v;
1151 struct vnode *vp = ap->a_vp;
1152
1153 if (vp->v_type != VREG)
1154 return (EPERM);
1155 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
1156 }
1157
1158 /*
1159 * nfs readlink call
1160 */
1161 int
1162 nfs_readlink(v)
1163 void *v;
1164 {
1165 struct vop_readlink_args /* {
1166 struct vnode *a_vp;
1167 struct uio *a_uio;
1168 struct ucred *a_cred;
1169 } */ *ap = v;
1170 struct vnode *vp = ap->a_vp;
1171
1172 if (vp->v_type != VLNK)
1173 return (EPERM);
1174 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0));
1175 }
1176
1177 /*
1178 * Do a readlink rpc.
1179 * Called by nfs_doio() from below the buffer cache.
1180 */
1181 int
1182 nfs_readlinkrpc(vp, uiop, cred)
1183 struct vnode *vp;
1184 struct uio *uiop;
1185 struct ucred *cred;
1186 {
1187 u_int32_t *tl;
1188 caddr_t cp;
1189 int32_t t1, t2;
1190 caddr_t bpos, dpos, cp2;
1191 int error = 0;
1192 uint32_t len;
1193 struct mbuf *mreq, *mrep, *md, *mb;
1194 const int v3 = NFS_ISV3(vp);
1195 struct nfsnode *np = VTONFS(vp);
1196 #ifndef NFS_V2_ONLY
1197 int attrflag;
1198 #endif
1199
1200 nfsstats.rpccnt[NFSPROC_READLINK]++;
1201 nfsm_reqhead(np, NFSPROC_READLINK, NFSX_FH(v3));
1202 nfsm_fhtom(np, v3);
1203 nfsm_request(np, NFSPROC_READLINK, uiop->uio_procp, cred);
1204 #ifndef NFS_V2_ONLY
1205 if (v3)
1206 nfsm_postop_attr(vp, attrflag, 0);
1207 #endif
1208 if (!error) {
1209 #ifndef NFS_V2_ONLY
1210 if (v3) {
1211 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
1212 len = fxdr_unsigned(uint32_t, *tl);
1213 if (len > MAXPATHLEN) {
1214 /*
1215 * this pathname is too long for us.
1216 */
1217 m_freem(mrep);
1218 /* Solaris returns EINVAL. should we follow? */
1219 error = ENAMETOOLONG;
1220 goto nfsmout;
1221 }
1222 } else
1223 #endif
1224 {
1225 nfsm_strsiz(len, NFS_MAXPATHLEN);
1226 }
1227 nfsm_mtouio(uiop, len);
1228 }
1229 nfsm_reqdone;
1230 return (error);
1231 }
1232
1233 /*
1234 * nfs read rpc call
1235 * Ditto above
1236 */
1237 int
1238 nfs_readrpc(vp, uiop)
1239 struct vnode *vp;
1240 struct uio *uiop;
1241 {
1242 u_int32_t *tl;
1243 caddr_t cp;
1244 int32_t t1, t2;
1245 caddr_t bpos, dpos, cp2;
1246 struct mbuf *mreq, *mrep, *md, *mb;
1247 struct nfsmount *nmp;
1248 int error = 0, len, retlen, tsiz, eof;
1249 const int v3 = NFS_ISV3(vp);
1250 struct nfsnode *np = VTONFS(vp);
1251 #ifndef NFS_V2_ONLY
1252 int attrflag;
1253 #endif
1254
1255 #ifndef nolint
1256 eof = 0;
1257 #endif
1258 nmp = VFSTONFS(vp->v_mount);
1259 tsiz = uiop->uio_resid;
1260 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1261 return (EFBIG);
1262 while (tsiz > 0) {
1263 nfsstats.rpccnt[NFSPROC_READ]++;
1264 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
1265 nfsm_reqhead(np, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
1266 nfsm_fhtom(np, v3);
1267 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
1268 #ifndef NFS_V2_ONLY
1269 if (v3) {
1270 txdr_hyper(uiop->uio_offset, tl);
1271 *(tl + 2) = txdr_unsigned(len);
1272 } else
1273 #endif
1274 {
1275 *tl++ = txdr_unsigned(uiop->uio_offset);
1276 *tl++ = txdr_unsigned(len);
1277 *tl = 0;
1278 }
1279 nfsm_request(np, NFSPROC_READ, uiop->uio_procp, np->n_rcred);
1280 #ifndef NFS_V2_ONLY
1281 if (v3) {
1282 nfsm_postop_attr(vp, attrflag, NAC_NOTRUNC);
1283 if (error) {
1284 m_freem(mrep);
1285 goto nfsmout;
1286 }
1287 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1288 eof = fxdr_unsigned(int, *(tl + 1));
1289 } else
1290 #endif
1291 nfsm_loadattr(vp, (struct vattr *)0, NAC_NOTRUNC);
1292 nfsm_strsiz(retlen, nmp->nm_rsize);
1293 nfsm_mtouio(uiop, retlen);
1294 m_freem(mrep);
1295 tsiz -= retlen;
1296 #ifndef NFS_V2_ONLY
1297 if (v3) {
1298 if (eof || retlen == 0)
1299 tsiz = 0;
1300 } else
1301 #endif
1302 if (retlen < len)
1303 tsiz = 0;
1304 }
1305 nfsmout:
1306 return (error);
1307 }
1308
1309 struct nfs_writerpc_context {
1310 struct simplelock nwc_slock;
1311 volatile int nwc_mbufcount;
1312 };
1313
1314 /*
1315 * free mbuf used to refer protected pages while write rpc call.
1316 * called at splvm.
1317 */
1318 static void
1319 nfs_writerpc_extfree(struct mbuf *m, caddr_t buf, size_t size, void *arg)
1320 {
1321 struct nfs_writerpc_context *ctx = arg;
1322
1323 KASSERT(m != NULL);
1324 KASSERT(ctx != NULL);
1325 pool_cache_put(&mbpool_cache, m);
1326 simple_lock(&ctx->nwc_slock);
1327 if (--ctx->nwc_mbufcount == 0) {
1328 wakeup(ctx);
1329 }
1330 simple_unlock(&ctx->nwc_slock);
1331 }
1332
1333 /*
1334 * nfs write call
1335 */
1336 int
1337 nfs_writerpc(vp, uiop, iomode, pageprotected, stalewriteverfp)
1338 struct vnode *vp;
1339 struct uio *uiop;
1340 int *iomode;
1341 boolean_t pageprotected;
1342 boolean_t *stalewriteverfp;
1343 {
1344 u_int32_t *tl;
1345 caddr_t cp;
1346 int32_t t1, t2;
1347 caddr_t bpos, dpos;
1348 struct mbuf *mreq, *mrep, *md, *mb;
1349 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1350 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR;
1351 const int v3 = NFS_ISV3(vp);
1352 int committed = NFSV3WRITE_FILESYNC;
1353 struct nfsnode *np = VTONFS(vp);
1354 struct nfs_writerpc_context ctx;
1355 int s;
1356 struct lwp *l = NULL;
1357 size_t origresid;
1358 #ifndef NFS_V2_ONLY
1359 caddr_t cp2;
1360 int rlen, commit;
1361 #endif
1362
1363 simple_lock_init(&ctx.nwc_slock);
1364 ctx.nwc_mbufcount = 1;
1365
1366 if (vp->v_mount->mnt_flag & MNT_RDONLY) {
1367 panic("writerpc readonly vp %p", vp);
1368 }
1369
1370 #ifdef DIAGNOSTIC
1371 if (uiop->uio_iovcnt != 1)
1372 panic("nfs: writerpc iovcnt > 1");
1373 #endif
1374 tsiz = uiop->uio_resid;
1375 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1376 return (EFBIG);
1377 if (pageprotected) {
1378 l = curlwp;
1379 PHOLD(l);
1380 }
1381 retry:
1382 origresid = uiop->uio_resid;
1383 KASSERT(origresid == uiop->uio_iov->iov_len);
1384 while (tsiz > 0) {
1385 uint32_t datalen; /* data bytes need to be allocated in mbuf */
1386 uint32_t backup;
1387 boolean_t stalewriteverf = FALSE;
1388
1389 nfsstats.rpccnt[NFSPROC_WRITE]++;
1390 len = min(tsiz, nmp->nm_wsize);
1391 datalen = pageprotected ? 0 : nfsm_rndup(len);
1392 nfsm_reqhead(np, NFSPROC_WRITE,
1393 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + datalen);
1394 nfsm_fhtom(np, v3);
1395 #ifndef NFS_V2_ONLY
1396 if (v3) {
1397 nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1398 txdr_hyper(uiop->uio_offset, tl);
1399 tl += 2;
1400 *tl++ = txdr_unsigned(len);
1401 *tl++ = txdr_unsigned(*iomode);
1402 *tl = txdr_unsigned(len);
1403 } else
1404 #endif
1405 {
1406 u_int32_t x;
1407
1408 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1409 /* Set both "begin" and "current" to non-garbage. */
1410 x = txdr_unsigned((u_int32_t)uiop->uio_offset);
1411 *tl++ = x; /* "begin offset" */
1412 *tl++ = x; /* "current offset" */
1413 x = txdr_unsigned(len);
1414 *tl++ = x; /* total to this offset */
1415 *tl = x; /* size of this write */
1416
1417 }
1418 if (pageprotected) {
1419 /*
1420 * since we know pages can't be modified during i/o,
1421 * no need to copy them for us.
1422 */
1423 struct mbuf *m;
1424 struct iovec *iovp = uiop->uio_iov;
1425
1426 m = m_get(M_WAIT, MT_DATA);
1427 MCLAIM(m, &nfs_mowner);
1428 MEXTADD(m, iovp->iov_base, len, M_MBUF,
1429 nfs_writerpc_extfree, &ctx);
1430 m->m_flags |= M_EXT_ROMAP;
1431 m->m_len = len;
1432 mb->m_next = m;
1433 /*
1434 * no need to maintain mb and bpos here
1435 * because no one care them later.
1436 */
1437 #if 0
1438 mb = m;
1439 bpos = mtod(caddr_t, mb) + mb->m_len;
1440 #endif
1441 iovp->iov_base = (char *)iovp->iov_base + len;
1442 iovp->iov_len -= len;
1443 uiop->uio_offset += len;
1444 uiop->uio_resid -= len;
1445 s = splvm();
1446 simple_lock(&ctx.nwc_slock);
1447 ctx.nwc_mbufcount++;
1448 simple_unlock(&ctx.nwc_slock);
1449 splx(s);
1450 nfs_zeropad(mb, 0, nfsm_padlen(len));
1451 } else {
1452 nfsm_uiotom(uiop, len);
1453 }
1454 nfsm_request(np, NFSPROC_WRITE, uiop->uio_procp, np->n_wcred);
1455 #ifndef NFS_V2_ONLY
1456 if (v3) {
1457 wccflag = NFSV3_WCCCHK;
1458 nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, !error);
1459 if (!error) {
1460 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
1461 + NFSX_V3WRITEVERF);
1462 rlen = fxdr_unsigned(int, *tl++);
1463 if (rlen == 0) {
1464 error = NFSERR_IO;
1465 m_freem(mrep);
1466 break;
1467 } else if (rlen < len) {
1468 backup = len - rlen;
1469 uiop->uio_iov->iov_base =
1470 (caddr_t)uiop->uio_iov->iov_base -
1471 backup;
1472 uiop->uio_iov->iov_len += backup;
1473 uiop->uio_offset -= backup;
1474 uiop->uio_resid += backup;
1475 len = rlen;
1476 }
1477 commit = fxdr_unsigned(int, *tl++);
1478
1479 /*
1480 * Return the lowest committment level
1481 * obtained by any of the RPCs.
1482 */
1483 if (committed == NFSV3WRITE_FILESYNC)
1484 committed = commit;
1485 else if (committed == NFSV3WRITE_DATASYNC &&
1486 commit == NFSV3WRITE_UNSTABLE)
1487 committed = commit;
1488 simple_lock(&nmp->nm_slock);
1489 if ((nmp->nm_iflag & NFSMNT_HASWRITEVERF) == 0){
1490 memcpy(nmp->nm_writeverf, tl,
1491 NFSX_V3WRITEVERF);
1492 nmp->nm_iflag |= NFSMNT_HASWRITEVERF;
1493 } else if ((nmp->nm_iflag &
1494 NFSMNT_STALEWRITEVERF) ||
1495 memcmp(tl, nmp->nm_writeverf,
1496 NFSX_V3WRITEVERF)) {
1497 memcpy(nmp->nm_writeverf, tl,
1498 NFSX_V3WRITEVERF);
1499 /*
1500 * note NFSMNT_STALEWRITEVERF
1501 * if we're the first thread to
1502 * notice it.
1503 */
1504 if ((nmp->nm_iflag &
1505 NFSMNT_STALEWRITEVERF) == 0) {
1506 stalewriteverf = TRUE;
1507 nmp->nm_iflag |=
1508 NFSMNT_STALEWRITEVERF;
1509 }
1510 }
1511 simple_unlock(&nmp->nm_slock);
1512 }
1513 } else
1514 #endif
1515 nfsm_loadattr(vp, (struct vattr *)0, NAC_NOTRUNC);
1516 if (wccflag)
1517 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr->va_mtime;
1518 m_freem(mrep);
1519 if (error)
1520 break;
1521 tsiz -= len;
1522 if (stalewriteverf) {
1523 *stalewriteverfp = TRUE;
1524 stalewriteverf = FALSE;
1525 if (committed == NFSV3WRITE_UNSTABLE &&
1526 len != origresid) {
1527 /*
1528 * if our write requests weren't atomic but
1529 * unstable, datas in previous iterations
1530 * might have already been lost now.
1531 * then, we should resend them to nfsd.
1532 */
1533 backup = origresid - tsiz;
1534 uiop->uio_iov->iov_base =
1535 (caddr_t)uiop->uio_iov->iov_base - backup;
1536 uiop->uio_iov->iov_len += backup;
1537 uiop->uio_offset -= backup;
1538 uiop->uio_resid += 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, FALSE);
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 * Have sillyrename use link instead of rename if possible,
2005 * so that we don't lose the file if the rename fails, and so
2006 * that there's no window when the "to" file doesn't exist.
2007 */
2008 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
2009 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp, TRUE)) {
2010 VN_KNOTE(tvp, NOTE_DELETE);
2011 vput(tvp);
2012 tvp = NULL;
2013 }
2014
2015 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
2016 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
2017 tcnp->cn_proc);
2018
2019 VN_KNOTE(fdvp, NOTE_WRITE);
2020 VN_KNOTE(tdvp, NOTE_WRITE);
2021 if (error == 0 || error == EEXIST) {
2022 if (fvp->v_type == VDIR)
2023 cache_purge(fvp);
2024 else
2025 cache_purge1(fdvp, fcnp, 0);
2026 if (tvp != NULL && tvp->v_type == VDIR)
2027 cache_purge(tvp);
2028 else
2029 cache_purge1(tdvp, tcnp, 0);
2030 }
2031 out:
2032 if (tdvp == tvp)
2033 vrele(tdvp);
2034 else
2035 vput(tdvp);
2036 if (tvp)
2037 vput(tvp);
2038 vrele(fdvp);
2039 vrele(fvp);
2040 return (error);
2041 }
2042
2043 /*
2044 * nfs file rename rpc called from nfs_remove() above
2045 */
2046 int
2047 nfs_renameit(sdvp, scnp, sp)
2048 struct vnode *sdvp;
2049 struct componentname *scnp;
2050 struct sillyrename *sp;
2051 {
2052 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
2053 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc));
2054 }
2055
2056 /*
2057 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
2058 */
2059 int
2060 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc)
2061 struct vnode *fdvp;
2062 const char *fnameptr;
2063 int fnamelen;
2064 struct vnode *tdvp;
2065 const char *tnameptr;
2066 int tnamelen;
2067 struct ucred *cred;
2068 struct proc *proc;
2069 {
2070 u_int32_t *tl;
2071 caddr_t cp;
2072 #ifndef NFS_V2_ONLY
2073 int32_t t1;
2074 caddr_t cp2;
2075 #endif
2076 int32_t t2;
2077 caddr_t bpos, dpos;
2078 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
2079 struct mbuf *mreq, *mrep, *md, *mb;
2080 const int v3 = NFS_ISV3(fdvp);
2081 int rexmit;
2082 struct nfsnode *fdnp = VTONFS(fdvp);
2083
2084 nfsstats.rpccnt[NFSPROC_RENAME]++;
2085 nfsm_reqhead(fdnp, NFSPROC_RENAME,
2086 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
2087 nfsm_rndup(tnamelen));
2088 nfsm_fhtom(fdnp, v3);
2089 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
2090 nfsm_fhtom(VTONFS(tdvp), v3);
2091 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
2092 nfsm_request1(fdnp, NFSPROC_RENAME, proc, cred, &rexmit);
2093 #ifndef NFS_V2_ONLY
2094 if (v3) {
2095 nfsm_wcc_data(fdvp, fwccflag, 0, !error);
2096 nfsm_wcc_data(tdvp, twccflag, 0, !error);
2097 }
2098 #endif
2099 nfsm_reqdone;
2100 VTONFS(fdvp)->n_flag |= NMODIFIED;
2101 VTONFS(tdvp)->n_flag |= NMODIFIED;
2102 if (!fwccflag)
2103 NFS_INVALIDATE_ATTRCACHE(VTONFS(fdvp));
2104 if (!twccflag)
2105 NFS_INVALIDATE_ATTRCACHE(VTONFS(tdvp));
2106 /*
2107 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
2108 */
2109 if (rexmit && error == ENOENT)
2110 error = 0;
2111 return (error);
2112 }
2113
2114 /*
2115 * NFS link RPC, called from nfs_link.
2116 * Assumes dvp and vp locked, and leaves them that way.
2117 */
2118
2119 static int
2120 nfs_linkrpc(struct vnode *dvp, struct vnode *vp, const char *name,
2121 size_t namelen, struct ucred *cred, struct proc *p)
2122 {
2123 u_int32_t *tl;
2124 caddr_t cp;
2125 #ifndef NFS_V2_ONLY
2126 int32_t t1;
2127 caddr_t cp2;
2128 #endif
2129 int32_t t2;
2130 caddr_t bpos, dpos;
2131 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
2132 struct mbuf *mreq, *mrep, *md, *mb;
2133 const int v3 = NFS_ISV3(dvp);
2134 int rexmit = 0;
2135 struct nfsnode *np = VTONFS(vp);
2136
2137 nfsstats.rpccnt[NFSPROC_LINK]++;
2138 nfsm_reqhead(np, NFSPROC_LINK,
2139 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(namelen));
2140 nfsm_fhtom(np, v3);
2141 nfsm_fhtom(VTONFS(dvp), v3);
2142 nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
2143 nfsm_request1(np, NFSPROC_LINK, p, cred, &rexmit);
2144 #ifndef NFS_V2_ONLY
2145 if (v3) {
2146 nfsm_postop_attr(vp, attrflag, 0);
2147 nfsm_wcc_data(dvp, wccflag, 0, !error);
2148 }
2149 #endif
2150 nfsm_reqdone;
2151
2152 VTONFS(dvp)->n_flag |= NMODIFIED;
2153 if (!attrflag)
2154 NFS_INVALIDATE_ATTRCACHE(VTONFS(vp));
2155 if (!wccflag)
2156 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
2157
2158 /*
2159 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2160 */
2161 if (rexmit && error == EEXIST)
2162 error = 0;
2163
2164 return error;
2165 }
2166
2167 /*
2168 * nfs hard link create call
2169 */
2170 int
2171 nfs_link(v)
2172 void *v;
2173 {
2174 struct vop_link_args /* {
2175 struct vnode *a_dvp;
2176 struct vnode *a_vp;
2177 struct componentname *a_cnp;
2178 } */ *ap = v;
2179 struct vnode *vp = ap->a_vp;
2180 struct vnode *dvp = ap->a_dvp;
2181 struct componentname *cnp = ap->a_cnp;
2182 int error = 0;
2183
2184 if (dvp->v_mount != vp->v_mount) {
2185 VOP_ABORTOP(dvp, cnp);
2186 vput(dvp);
2187 return (EXDEV);
2188 }
2189 if (dvp != vp) {
2190 error = vn_lock(vp, LK_EXCLUSIVE);
2191 if (error != 0) {
2192 VOP_ABORTOP(dvp, cnp);
2193 vput(dvp);
2194 return error;
2195 }
2196 }
2197
2198 /*
2199 * Push all writes to the server, so that the attribute cache
2200 * doesn't get "out of sync" with the server.
2201 * XXX There should be a better way!
2202 */
2203 VOP_FSYNC(vp, cnp->cn_cred, FSYNC_WAIT, 0, 0, cnp->cn_proc);
2204
2205 error = nfs_linkrpc(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen,
2206 cnp->cn_cred, cnp->cn_proc);
2207
2208 if (error == 0)
2209 cache_purge1(dvp, cnp, 0);
2210 PNBUF_PUT(cnp->cn_pnbuf);
2211 if (dvp != vp)
2212 VOP_UNLOCK(vp, 0);
2213 VN_KNOTE(vp, NOTE_LINK);
2214 VN_KNOTE(dvp, NOTE_WRITE);
2215 vput(dvp);
2216 return (error);
2217 }
2218
2219 /*
2220 * nfs symbolic link create call
2221 */
2222 int
2223 nfs_symlink(v)
2224 void *v;
2225 {
2226 struct vop_symlink_args /* {
2227 struct vnode *a_dvp;
2228 struct vnode **a_vpp;
2229 struct componentname *a_cnp;
2230 struct vattr *a_vap;
2231 char *a_target;
2232 } */ *ap = v;
2233 struct vnode *dvp = ap->a_dvp;
2234 struct vattr *vap = ap->a_vap;
2235 struct componentname *cnp = ap->a_cnp;
2236 struct nfsv2_sattr *sp;
2237 u_int32_t *tl;
2238 caddr_t cp;
2239 int32_t t1, t2;
2240 caddr_t bpos, dpos, cp2;
2241 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
2242 struct mbuf *mreq, *mrep, *md, *mb;
2243 struct vnode *newvp = (struct vnode *)0;
2244 const int v3 = NFS_ISV3(dvp);
2245 int rexmit;
2246 struct nfsnode *dnp = VTONFS(dvp);
2247
2248 *ap->a_vpp = NULL;
2249 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
2250 slen = strlen(ap->a_target);
2251 nfsm_reqhead(dnp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
2252 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
2253 nfsm_fhtom(dnp, v3);
2254 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
2255 #ifndef NFS_V2_ONlY
2256 if (v3)
2257 nfsm_v3attrbuild(vap, FALSE);
2258 #endif
2259 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
2260 #ifndef NFS_V2_ONlY
2261 if (!v3) {
2262 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2263 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
2264 sp->sa_uid = nfs_xdrneg1;
2265 sp->sa_gid = nfs_xdrneg1;
2266 sp->sa_size = nfs_xdrneg1;
2267 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
2268 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
2269 }
2270 #endif
2271 nfsm_request1(dnp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred,
2272 &rexmit);
2273 #ifndef NFS_V2_ONlY
2274 if (v3) {
2275 if (!error)
2276 nfsm_mtofh(dvp, newvp, v3, gotvp);
2277 nfsm_wcc_data(dvp, wccflag, 0, !error);
2278 }
2279 #endif
2280 nfsm_reqdone;
2281 /*
2282 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2283 */
2284 if (rexmit && error == EEXIST)
2285 error = 0;
2286 if (error == 0 || error == EEXIST)
2287 cache_purge1(dvp, cnp, 0);
2288 if (error == 0 && newvp == NULL) {
2289 struct nfsnode *np = NULL;
2290
2291 error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
2292 cnp->cn_cred, cnp->cn_proc, &np);
2293 if (error == 0)
2294 newvp = NFSTOV(np);
2295 }
2296 if (error) {
2297 if (newvp != NULL)
2298 vput(newvp);
2299 } else {
2300 *ap->a_vpp = newvp;
2301 }
2302 PNBUF_PUT(cnp->cn_pnbuf);
2303 VTONFS(dvp)->n_flag |= NMODIFIED;
2304 if (!wccflag)
2305 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
2306 VN_KNOTE(dvp, NOTE_WRITE);
2307 vput(dvp);
2308 return (error);
2309 }
2310
2311 /*
2312 * nfs make dir call
2313 */
2314 int
2315 nfs_mkdir(v)
2316 void *v;
2317 {
2318 struct vop_mkdir_args /* {
2319 struct vnode *a_dvp;
2320 struct vnode **a_vpp;
2321 struct componentname *a_cnp;
2322 struct vattr *a_vap;
2323 } */ *ap = v;
2324 struct vnode *dvp = ap->a_dvp;
2325 struct vattr *vap = ap->a_vap;
2326 struct componentname *cnp = ap->a_cnp;
2327 struct nfsv2_sattr *sp;
2328 u_int32_t *tl;
2329 caddr_t cp;
2330 int32_t t1, t2;
2331 int len;
2332 struct nfsnode *dnp = VTONFS(dvp), *np = (struct nfsnode *)0;
2333 struct vnode *newvp = (struct vnode *)0;
2334 caddr_t bpos, dpos, cp2;
2335 int error = 0, wccflag = NFSV3_WCCRATTR;
2336 int gotvp = 0;
2337 int rexmit;
2338 struct mbuf *mreq, *mrep, *md, *mb;
2339 const int v3 = NFS_ISV3(dvp);
2340
2341 len = cnp->cn_namelen;
2342 nfsstats.rpccnt[NFSPROC_MKDIR]++;
2343 nfsm_reqhead(dnp, NFSPROC_MKDIR,
2344 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
2345 nfsm_fhtom(dnp, v3);
2346 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
2347 #ifndef NFS_V2_ONLY
2348 if (v3) {
2349 nfsm_v3attrbuild(vap, FALSE);
2350 } else
2351 #endif
2352 {
2353 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2354 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
2355 sp->sa_uid = nfs_xdrneg1;
2356 sp->sa_gid = nfs_xdrneg1;
2357 sp->sa_size = nfs_xdrneg1;
2358 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
2359 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
2360 }
2361 nfsm_request1(dnp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred, &rexmit);
2362 if (!error)
2363 nfsm_mtofh(dvp, newvp, v3, gotvp);
2364 if (v3)
2365 nfsm_wcc_data(dvp, wccflag, 0, !error);
2366 nfsm_reqdone;
2367 VTONFS(dvp)->n_flag |= NMODIFIED;
2368 if (!wccflag)
2369 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
2370 /*
2371 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
2372 * if we can succeed in looking up the directory.
2373 */
2374 if ((rexmit && error == EEXIST) || (!error && !gotvp)) {
2375 if (newvp) {
2376 vput(newvp);
2377 newvp = (struct vnode *)0;
2378 }
2379 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
2380 cnp->cn_proc, &np);
2381 if (!error) {
2382 newvp = NFSTOV(np);
2383 if (newvp->v_type != VDIR || newvp == dvp)
2384 error = EEXIST;
2385 }
2386 }
2387 if (error) {
2388 if (newvp) {
2389 if (dvp != newvp)
2390 vput(newvp);
2391 else
2392 vrele(newvp);
2393 }
2394 } else {
2395 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
2396 if (cnp->cn_flags & MAKEENTRY)
2397 nfs_cache_enter(dvp, newvp, cnp);
2398 *ap->a_vpp = newvp;
2399 }
2400 PNBUF_PUT(cnp->cn_pnbuf);
2401 vput(dvp);
2402 return (error);
2403 }
2404
2405 /*
2406 * nfs remove directory call
2407 */
2408 int
2409 nfs_rmdir(v)
2410 void *v;
2411 {
2412 struct vop_rmdir_args /* {
2413 struct vnode *a_dvp;
2414 struct vnode *a_vp;
2415 struct componentname *a_cnp;
2416 } */ *ap = v;
2417 struct vnode *vp = ap->a_vp;
2418 struct vnode *dvp = ap->a_dvp;
2419 struct componentname *cnp = ap->a_cnp;
2420 u_int32_t *tl;
2421 caddr_t cp;
2422 #ifndef NFS_V2_ONLY
2423 int32_t t1;
2424 caddr_t cp2;
2425 #endif
2426 int32_t t2;
2427 caddr_t bpos, dpos;
2428 int error = 0, wccflag = NFSV3_WCCRATTR;
2429 int rexmit;
2430 struct mbuf *mreq, *mrep, *md, *mb;
2431 const int v3 = NFS_ISV3(dvp);
2432 struct nfsnode *dnp;
2433
2434 if (dvp == vp) {
2435 vrele(dvp);
2436 vput(dvp);
2437 PNBUF_PUT(cnp->cn_pnbuf);
2438 return (EINVAL);
2439 }
2440 nfsstats.rpccnt[NFSPROC_RMDIR]++;
2441 dnp = VTONFS(dvp);
2442 nfsm_reqhead(dnp, NFSPROC_RMDIR,
2443 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
2444 nfsm_fhtom(dnp, v3);
2445 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
2446 nfsm_request1(dnp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred, &rexmit);
2447 #ifndef NFS_V2_ONLY
2448 if (v3)
2449 nfsm_wcc_data(dvp, wccflag, 0, !error);
2450 #endif
2451 nfsm_reqdone;
2452 PNBUF_PUT(cnp->cn_pnbuf);
2453 VTONFS(dvp)->n_flag |= NMODIFIED;
2454 if (!wccflag)
2455 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
2456 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
2457 VN_KNOTE(vp, NOTE_DELETE);
2458 cache_purge(vp);
2459 vput(vp);
2460 vput(dvp);
2461 /*
2462 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2463 */
2464 if (rexmit && error == ENOENT)
2465 error = 0;
2466 return (error);
2467 }
2468
2469 /*
2470 * nfs readdir call
2471 */
2472 int
2473 nfs_readdir(v)
2474 void *v;
2475 {
2476 struct vop_readdir_args /* {
2477 struct vnode *a_vp;
2478 struct uio *a_uio;
2479 struct ucred *a_cred;
2480 int *a_eofflag;
2481 off_t **a_cookies;
2482 int *a_ncookies;
2483 } */ *ap = v;
2484 struct vnode *vp = ap->a_vp;
2485 struct uio *uio = ap->a_uio;
2486 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2487 char *base = uio->uio_iov->iov_base;
2488 int tresid, error;
2489 size_t count, lost;
2490 struct dirent *dp;
2491 off_t *cookies = NULL;
2492 int ncookies = 0, nc;
2493
2494 if (vp->v_type != VDIR)
2495 return (EPERM);
2496
2497 lost = uio->uio_resid & (NFS_DIRFRAGSIZ - 1);
2498 count = uio->uio_resid - lost;
2499 if (count <= 0)
2500 return (EINVAL);
2501
2502 /*
2503 * Call nfs_bioread() to do the real work.
2504 */
2505 tresid = uio->uio_resid = count;
2506 error = nfs_bioread(vp, uio, 0, ap->a_cred,
2507 ap->a_cookies ? NFSBIO_CACHECOOKIES : 0);
2508
2509 if (!error && ap->a_cookies) {
2510 ncookies = count / 16;
2511 cookies = malloc(sizeof (off_t) * ncookies, M_TEMP, M_WAITOK);
2512 *ap->a_cookies = cookies;
2513 }
2514
2515 if (!error && uio->uio_resid == tresid) {
2516 uio->uio_resid += lost;
2517 nfsstats.direofcache_misses++;
2518 if (ap->a_cookies)
2519 *ap->a_ncookies = 0;
2520 *ap->a_eofflag = 1;
2521 return (0);
2522 }
2523
2524 if (!error && ap->a_cookies) {
2525 /*
2526 * Only the NFS server and emulations use cookies, and they
2527 * load the directory block into system space, so we can
2528 * just look at it directly.
2529 */
2530 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
2531 panic("nfs_readdir: lost in space");
2532 for (nc = 0; ncookies-- &&
2533 base < (char *)uio->uio_iov->iov_base; nc++){
2534 dp = (struct dirent *) base;
2535 if (dp->d_reclen == 0)
2536 break;
2537 if (nmp->nm_flag & NFSMNT_XLATECOOKIE)
2538 *(cookies++) = (off_t)NFS_GETCOOKIE32(dp);
2539 else
2540 *(cookies++) = NFS_GETCOOKIE(dp);
2541 base += dp->d_reclen;
2542 }
2543 uio->uio_resid +=
2544 ((caddr_t)uio->uio_iov->iov_base - base);
2545 uio->uio_iov->iov_len +=
2546 ((caddr_t)uio->uio_iov->iov_base - base);
2547 uio->uio_iov->iov_base = base;
2548 *ap->a_ncookies = nc;
2549 }
2550
2551 uio->uio_resid += lost;
2552 *ap->a_eofflag = 0;
2553 return (error);
2554 }
2555
2556 /*
2557 * Readdir rpc call.
2558 * Called from below the buffer cache by nfs_doio().
2559 */
2560 int
2561 nfs_readdirrpc(vp, uiop, cred)
2562 struct vnode *vp;
2563 struct uio *uiop;
2564 struct ucred *cred;
2565 {
2566 int len, left;
2567 struct dirent *dp = NULL;
2568 u_int32_t *tl;
2569 caddr_t cp;
2570 int32_t t1, t2;
2571 caddr_t bpos, dpos, cp2;
2572 struct mbuf *mreq, *mrep, *md, *mb;
2573 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2574 struct nfsnode *dnp = VTONFS(vp);
2575 u_quad_t fileno;
2576 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2577 #ifndef NFS_V2_ONLY
2578 int attrflag;
2579 #endif
2580 int nrpcs = 0, reclen;
2581 const int v3 = NFS_ISV3(vp);
2582
2583 #ifdef DIAGNOSTIC
2584 /*
2585 * Should be called from buffer cache, so only amount of
2586 * NFS_DIRBLKSIZ will be requested.
2587 */
2588 if (uiop->uio_iovcnt != 1 || uiop->uio_resid != NFS_DIRBLKSIZ)
2589 panic("nfs readdirrpc bad uio");
2590 #endif
2591
2592 /*
2593 * Loop around doing readdir rpc's of size nm_readdirsize
2594 * truncated to a multiple of NFS_DIRFRAGSIZ.
2595 * The stopping criteria is EOF or buffer full.
2596 */
2597 while (more_dirs && bigenough) {
2598 /*
2599 * Heuristic: don't bother to do another RPC to further
2600 * fill up this block if there is not much room left. (< 50%
2601 * of the readdir RPC size). This wastes some buffer space
2602 * but can save up to 50% in RPC calls.
2603 */
2604 if (nrpcs > 0 && uiop->uio_resid < (nmp->nm_readdirsize / 2)) {
2605 bigenough = 0;
2606 break;
2607 }
2608 nfsstats.rpccnt[NFSPROC_READDIR]++;
2609 nfsm_reqhead(dnp, NFSPROC_READDIR, NFSX_FH(v3) +
2610 NFSX_READDIR(v3));
2611 nfsm_fhtom(dnp, v3);
2612 #ifndef NFS_V2_ONLY
2613 if (v3) {
2614 nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2615 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) {
2616 txdr_swapcookie3(uiop->uio_offset, tl);
2617 } else {
2618 txdr_cookie3(uiop->uio_offset, tl);
2619 }
2620 tl += 2;
2621 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2622 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2623 } else
2624 #endif
2625 {
2626 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2627 *tl++ = txdr_unsigned(uiop->uio_offset);
2628 }
2629 *tl = txdr_unsigned(nmp->nm_readdirsize);
2630 nfsm_request(dnp, NFSPROC_READDIR, uiop->uio_procp, cred);
2631 nrpcs++;
2632 #ifndef NFS_V2_ONLY
2633 if (v3) {
2634 nfsm_postop_attr(vp, attrflag, 0);
2635 if (!error) {
2636 nfsm_dissect(tl, u_int32_t *,
2637 2 * NFSX_UNSIGNED);
2638 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2639 dnp->n_cookieverf.nfsuquad[1] = *tl;
2640 } else {
2641 m_freem(mrep);
2642 goto nfsmout;
2643 }
2644 }
2645 #endif
2646 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2647 more_dirs = fxdr_unsigned(int, *tl);
2648
2649 /* loop thru the dir entries, doctoring them to 4bsd form */
2650 while (more_dirs && bigenough) {
2651 #ifndef NFS_V2_ONLY
2652 if (v3) {
2653 nfsm_dissect(tl, u_int32_t *,
2654 3 * NFSX_UNSIGNED);
2655 fileno = fxdr_hyper(tl);
2656 len = fxdr_unsigned(int, *(tl + 2));
2657 } else
2658 #endif
2659 {
2660 nfsm_dissect(tl, u_int32_t *,
2661 2 * NFSX_UNSIGNED);
2662 fileno = fxdr_unsigned(u_quad_t, *tl++);
2663 len = fxdr_unsigned(int, *tl);
2664 }
2665 if (len <= 0 || len > NFS_MAXNAMLEN) {
2666 error = EBADRPC;
2667 m_freem(mrep);
2668 goto nfsmout;
2669 }
2670 tlen = nfsm_rndup(len);
2671 if (tlen == len)
2672 tlen += 4; /* To ensure null termination */
2673 tlen += sizeof (off_t) + sizeof (int);
2674 reclen = ALIGN(tlen + DIRHDSIZ);
2675 tlen = reclen - DIRHDSIZ;
2676 left = NFS_DIRFRAGSIZ - blksiz;
2677 if (reclen > left) {
2678 memset(uiop->uio_iov->iov_base, 0, left);
2679 dp->d_reclen += left;
2680 uiop->uio_iov->iov_base =
2681 (caddr_t)uiop->uio_iov->iov_base + left;
2682 uiop->uio_iov->iov_len -= left;
2683 uiop->uio_resid -= left;
2684 blksiz = 0;
2685 NFS_STASHCOOKIE(dp, uiop->uio_offset);
2686 }
2687 if (reclen > uiop->uio_resid)
2688 bigenough = 0;
2689 if (bigenough) {
2690 dp = (struct dirent *)uiop->uio_iov->iov_base;
2691 dp->d_fileno = (int)fileno;
2692 dp->d_namlen = len;
2693 dp->d_reclen = reclen;
2694 dp->d_type = DT_UNKNOWN;
2695 blksiz += dp->d_reclen;
2696 if (blksiz == NFS_DIRFRAGSIZ)
2697 blksiz = 0;
2698 uiop->uio_resid -= DIRHDSIZ;
2699 uiop->uio_iov->iov_base =
2700 (caddr_t)uiop->uio_iov->iov_base + DIRHDSIZ;
2701 uiop->uio_iov->iov_len -= DIRHDSIZ;
2702 nfsm_mtouio(uiop, len);
2703 tlen -= len;
2704 /* null terminate */
2705 KDASSERT(tlen > 0);
2706 memset(uiop->uio_iov->iov_base, 0, tlen);
2707 uiop->uio_iov->iov_base =
2708 (caddr_t)uiop->uio_iov->iov_base + tlen;
2709 uiop->uio_iov->iov_len -= tlen;
2710 uiop->uio_resid -= tlen;
2711 } else
2712 nfsm_adv(nfsm_rndup(len));
2713 #ifndef NFS_V2_ONLY
2714 if (v3) {
2715 nfsm_dissect(tl, u_int32_t *,
2716 3 * NFSX_UNSIGNED);
2717 } else
2718 #endif
2719 {
2720 nfsm_dissect(tl, u_int32_t *,
2721 2 * NFSX_UNSIGNED);
2722 }
2723 if (bigenough) {
2724 #ifndef NFS_V2_ONLY
2725 if (v3) {
2726 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE)
2727 uiop->uio_offset =
2728 fxdr_swapcookie3(tl);
2729 else
2730 uiop->uio_offset =
2731 fxdr_cookie3(tl);
2732 }
2733 else
2734 #endif
2735 {
2736 uiop->uio_offset =
2737 fxdr_unsigned(off_t, *tl);
2738 }
2739 NFS_STASHCOOKIE(dp, uiop->uio_offset);
2740 }
2741 if (v3)
2742 tl += 2;
2743 else
2744 tl++;
2745 more_dirs = fxdr_unsigned(int, *tl);
2746 }
2747 /*
2748 * If at end of rpc data, get the eof boolean
2749 */
2750 if (!more_dirs) {
2751 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2752 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2753
2754 /*
2755 * kludge: if we got no entries, treat it as EOF.
2756 * some server sometimes send a reply without any
2757 * entries or EOF.
2758 * although it might mean the server has very long name,
2759 * we can't handle such entries anyway.
2760 */
2761
2762 if (uiop->uio_resid >= NFS_DIRBLKSIZ)
2763 more_dirs = 0;
2764 }
2765 m_freem(mrep);
2766 }
2767 /*
2768 * Fill last record, iff any, out to a multiple of NFS_DIRFRAGSIZ
2769 * by increasing d_reclen for the last record.
2770 */
2771 if (blksiz > 0) {
2772 left = NFS_DIRFRAGSIZ - blksiz;
2773 memset(uiop->uio_iov->iov_base, 0, left);
2774 dp->d_reclen += left;
2775 NFS_STASHCOOKIE(dp, uiop->uio_offset);
2776 uiop->uio_iov->iov_base = (caddr_t)uiop->uio_iov->iov_base +
2777 left;
2778 uiop->uio_iov->iov_len -= left;
2779 uiop->uio_resid -= left;
2780 }
2781
2782 /*
2783 * We are now either at the end of the directory or have filled the
2784 * block.
2785 */
2786 if (bigenough) {
2787 dnp->n_direofoffset = uiop->uio_offset;
2788 dnp->n_flag |= NEOFVALID;
2789 }
2790 nfsmout:
2791 return (error);
2792 }
2793
2794 #ifndef NFS_V2_ONLY
2795 /*
2796 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2797 */
2798 int
2799 nfs_readdirplusrpc(vp, uiop, cred)
2800 struct vnode *vp;
2801 struct uio *uiop;
2802 struct ucred *cred;
2803 {
2804 int len, left;
2805 struct dirent *dp = NULL;
2806 u_int32_t *tl;
2807 caddr_t cp;
2808 int32_t t1, t2;
2809 struct vnode *newvp;
2810 caddr_t bpos, dpos, cp2;
2811 struct mbuf *mreq, *mrep, *md, *mb;
2812 struct nameidata nami, *ndp = &nami;
2813 struct componentname *cnp = &ndp->ni_cnd;
2814 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2815 struct nfsnode *dnp = VTONFS(vp), *np;
2816 nfsfh_t *fhp;
2817 u_quad_t fileno;
2818 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2819 int attrflag, fhsize, nrpcs = 0, reclen;
2820 struct nfs_fattr fattr, *fp;
2821
2822 #ifdef DIAGNOSTIC
2823 if (uiop->uio_iovcnt != 1 || uiop->uio_resid != NFS_DIRBLKSIZ)
2824 panic("nfs readdirplusrpc bad uio");
2825 #endif
2826 ndp->ni_dvp = vp;
2827 newvp = NULLVP;
2828
2829 /*
2830 * Loop around doing readdir rpc's of size nm_readdirsize
2831 * truncated to a multiple of NFS_DIRFRAGSIZ.
2832 * The stopping criteria is EOF or buffer full.
2833 */
2834 while (more_dirs && bigenough) {
2835 if (nrpcs > 0 && uiop->uio_resid < (nmp->nm_readdirsize / 2)) {
2836 bigenough = 0;
2837 break;
2838 }
2839 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2840 nfsm_reqhead(dnp, NFSPROC_READDIRPLUS,
2841 NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2842 nfsm_fhtom(dnp, 1);
2843 nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2844 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) {
2845 txdr_swapcookie3(uiop->uio_offset, tl);
2846 } else {
2847 txdr_cookie3(uiop->uio_offset, tl);
2848 }
2849 tl += 2;
2850 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2851 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2852 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
2853 *tl = txdr_unsigned(nmp->nm_rsize);
2854 nfsm_request(dnp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred);
2855 nfsm_postop_attr(vp, attrflag, 0);
2856 if (error) {
2857 m_freem(mrep);
2858 goto nfsmout;
2859 }
2860 nrpcs++;
2861 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2862 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2863 dnp->n_cookieverf.nfsuquad[1] = *tl++;
2864 more_dirs = fxdr_unsigned(int, *tl);
2865
2866 /* loop thru the dir entries, doctoring them to 4bsd form */
2867 while (more_dirs && bigenough) {
2868 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2869 fileno = fxdr_hyper(tl);
2870 len = fxdr_unsigned(int, *(tl + 2));
2871 if (len <= 0 || len > NFS_MAXNAMLEN) {
2872 error = EBADRPC;
2873 m_freem(mrep);
2874 goto nfsmout;
2875 }
2876 tlen = nfsm_rndup(len);
2877 if (tlen == len)
2878 tlen += 4; /* To ensure null termination*/
2879 tlen += sizeof (off_t) + sizeof (int);
2880 reclen = ALIGN(tlen + DIRHDSIZ);
2881 tlen = reclen - DIRHDSIZ;
2882 left = NFS_DIRFRAGSIZ - blksiz;
2883 if (reclen > left) {
2884 /*
2885 * DIRFRAGSIZ is aligned, no need to align
2886 * again here.
2887 */
2888 memset(uiop->uio_iov->iov_base, 0, left);
2889 dp->d_reclen += left;
2890 uiop->uio_iov->iov_base =
2891 (caddr_t)uiop->uio_iov->iov_base + left;
2892 uiop->uio_iov->iov_len -= left;
2893 uiop->uio_resid -= left;
2894 NFS_STASHCOOKIE(dp, uiop->uio_offset);
2895 blksiz = 0;
2896 }
2897 if (reclen > uiop->uio_resid)
2898 bigenough = 0;
2899 if (bigenough) {
2900 dp = (struct dirent *)uiop->uio_iov->iov_base;
2901 dp->d_fileno = (int)fileno;
2902 dp->d_namlen = len;
2903 dp->d_reclen = reclen;
2904 dp->d_type = DT_UNKNOWN;
2905 blksiz += dp->d_reclen;
2906 if (blksiz == NFS_DIRFRAGSIZ)
2907 blksiz = 0;
2908 uiop->uio_resid -= DIRHDSIZ;
2909 uiop->uio_iov->iov_base =
2910 (caddr_t)uiop->uio_iov->iov_base +
2911 DIRHDSIZ;
2912 uiop->uio_iov->iov_len -= DIRHDSIZ;
2913 cnp->cn_nameptr = uiop->uio_iov->iov_base;
2914 cnp->cn_namelen = len;
2915 nfsm_mtouio(uiop, len);
2916 tlen -= len;
2917 /* null terminate */
2918 KDASSERT(tlen > 0);
2919 memset(uiop->uio_iov->iov_base, 0, tlen);
2920 uiop->uio_iov->iov_base =
2921 (caddr_t)uiop->uio_iov->iov_base + tlen;
2922 uiop->uio_iov->iov_len -= tlen;
2923 uiop->uio_resid -= tlen;
2924 } else
2925 nfsm_adv(nfsm_rndup(len));
2926 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2927 if (bigenough) {
2928 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE)
2929 uiop->uio_offset =
2930 fxdr_swapcookie3(tl);
2931 else
2932 uiop->uio_offset =
2933 fxdr_cookie3(tl);
2934 NFS_STASHCOOKIE(dp, uiop->uio_offset);
2935 }
2936 tl += 2;
2937
2938 /*
2939 * Since the attributes are before the file handle
2940 * (sigh), we must skip over the attributes and then
2941 * come back and get them.
2942 */
2943 attrflag = fxdr_unsigned(int, *tl);
2944 if (attrflag) {
2945 nfsm_dissect(fp, struct nfs_fattr *, NFSX_V3FATTR);
2946 memcpy(&fattr, fp, NFSX_V3FATTR);
2947 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2948 doit = fxdr_unsigned(int, *tl);
2949 if (doit) {
2950 nfsm_getfh(fhp, fhsize, 1);
2951 if (NFS_CMPFH(dnp, fhp, fhsize)) {
2952 VREF(vp);
2953 newvp = vp;
2954 np = dnp;
2955 } else {
2956 error = nfs_nget1(vp->v_mount, fhp,
2957 fhsize, &np, LK_NOWAIT);
2958 if (!error)
2959 newvp = NFSTOV(np);
2960 }
2961 if (!error) {
2962 const char *cp;
2963
2964 nfs_loadattrcache(&newvp, &fattr, 0, 0);
2965 if (bigenough) {
2966 dp->d_type =
2967 IFTODT(VTTOIF(np->n_vattr->va_type));
2968 if (cnp->cn_namelen <= NCHNAMLEN) {
2969 ndp->ni_vp = newvp;
2970 cp = cnp->cn_nameptr +
2971 cnp->cn_namelen;
2972 cnp->cn_hash =
2973 namei_hash(cnp->cn_nameptr, &cp);
2974 nfs_cache_enter(ndp->ni_dvp,
2975 ndp->ni_vp, cnp);
2976 }
2977 }
2978 }
2979 error = 0;
2980 }
2981 } else {
2982 /* Just skip over the file handle */
2983 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2984 i = fxdr_unsigned(int, *tl);
2985 nfsm_adv(nfsm_rndup(i));
2986 }
2987 if (newvp != NULLVP) {
2988 if (newvp == vp)
2989 vrele(newvp);
2990 else
2991 vput(newvp);
2992 newvp = NULLVP;
2993 }
2994 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2995 more_dirs = fxdr_unsigned(int, *tl);
2996 }
2997 /*
2998 * If at end of rpc data, get the eof boolean
2999 */
3000 if (!more_dirs) {
3001 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
3002 more_dirs = (fxdr_unsigned(int, *tl) == 0);
3003
3004 /*
3005 * kludge: see a comment in nfs_readdirrpc.
3006 */
3007
3008 if (uiop->uio_resid >= NFS_DIRBLKSIZ)
3009 more_dirs = 0;
3010 }
3011 m_freem(mrep);
3012 }
3013 /*
3014 * Fill last record, iff any, out to a multiple of NFS_DIRFRAGSIZ
3015 * by increasing d_reclen for the last record.
3016 */
3017 if (blksiz > 0) {
3018 left = NFS_DIRFRAGSIZ - blksiz;
3019 memset(uiop->uio_iov->iov_base, 0, left);
3020 dp->d_reclen += left;
3021 NFS_STASHCOOKIE(dp, uiop->uio_offset);
3022 uiop->uio_iov->iov_base = (caddr_t)uiop->uio_iov->iov_base +
3023 left;
3024 uiop->uio_iov->iov_len -= left;
3025 uiop->uio_resid -= left;
3026 }
3027
3028 /*
3029 * We are now either at the end of the directory or have filled the
3030 * block.
3031 */
3032 if (bigenough) {
3033 dnp->n_direofoffset = uiop->uio_offset;
3034 dnp->n_flag |= NEOFVALID;
3035 }
3036 nfsmout:
3037 if (newvp != NULLVP) {
3038 if(newvp == vp)
3039 vrele(newvp);
3040 else
3041 vput(newvp);
3042 }
3043 return (error);
3044 }
3045 #endif
3046
3047 static char hextoasc[] = "0123456789abcdef";
3048
3049 /*
3050 * Silly rename. To make the NFS filesystem that is stateless look a little
3051 * more like the "ufs" a remove of an active vnode is translated to a rename
3052 * to a funny looking filename that is removed by nfs_inactive on the
3053 * nfsnode. There is the potential for another process on a different client
3054 * to create the same funny name between the nfs_lookitup() fails and the
3055 * nfs_rename() completes, but...
3056 */
3057 int
3058 nfs_sillyrename(dvp, vp, cnp, dolink)
3059 struct vnode *dvp, *vp;
3060 struct componentname *cnp;
3061 boolean_t dolink;
3062 {
3063 struct sillyrename *sp;
3064 struct nfsnode *np;
3065 int error;
3066 short pid;
3067
3068 cache_purge(dvp);
3069 np = VTONFS(vp);
3070 #ifndef DIAGNOSTIC
3071 if (vp->v_type == VDIR)
3072 panic("nfs: sillyrename dir");
3073 #endif
3074 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
3075 M_NFSREQ, M_WAITOK);
3076 sp->s_cred = crdup(cnp->cn_cred);
3077 sp->s_dvp = dvp;
3078 VREF(dvp);
3079
3080 /* Fudge together a funny name */
3081 pid = cnp->cn_proc->p_pid;
3082 memcpy(sp->s_name, ".nfsAxxxx4.4", 13);
3083 sp->s_namlen = 12;
3084 sp->s_name[8] = hextoasc[pid & 0xf];
3085 sp->s_name[7] = hextoasc[(pid >> 4) & 0xf];
3086 sp->s_name[6] = hextoasc[(pid >> 8) & 0xf];
3087 sp->s_name[5] = hextoasc[(pid >> 12) & 0xf];
3088
3089 /* Try lookitups until we get one that isn't there */
3090 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
3091 cnp->cn_proc, (struct nfsnode **)0) == 0) {
3092 sp->s_name[4]++;
3093 if (sp->s_name[4] > 'z') {
3094 error = EINVAL;
3095 goto bad;
3096 }
3097 }
3098 if (dolink) {
3099 error = nfs_linkrpc(dvp, vp, sp->s_name, sp->s_namlen,
3100 sp->s_cred, cnp->cn_proc);
3101 /*
3102 * nfs_request maps NFSERR_NOTSUPP to ENOTSUP.
3103 */
3104 if (error == ENOTSUP) {
3105 error = nfs_renameit(dvp, cnp, sp);
3106 }
3107 } else {
3108 error = nfs_renameit(dvp, cnp, sp);
3109 }
3110 if (error)
3111 goto bad;
3112 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
3113 cnp->cn_proc, &np);
3114 np->n_sillyrename = sp;
3115 return (0);
3116 bad:
3117 vrele(sp->s_dvp);
3118 crfree(sp->s_cred);
3119 free((caddr_t)sp, M_NFSREQ);
3120 return (error);
3121 }
3122
3123 /*
3124 * Look up a file name and optionally either update the file handle or
3125 * allocate an nfsnode, depending on the value of npp.
3126 * npp == NULL --> just do the lookup
3127 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
3128 * handled too
3129 * *npp != NULL --> update the file handle in the vnode
3130 */
3131 int
3132 nfs_lookitup(dvp, name, len, cred, procp, npp)
3133 struct vnode *dvp;
3134 const char *name;
3135 int len;
3136 struct ucred *cred;
3137 struct proc *procp;
3138 struct nfsnode **npp;
3139 {
3140 u_int32_t *tl;
3141 caddr_t cp;
3142 int32_t t1, t2;
3143 struct vnode *newvp = (struct vnode *)0;
3144 struct nfsnode *np, *dnp = VTONFS(dvp);
3145 caddr_t bpos, dpos, cp2;
3146 int error = 0, fhlen;
3147 #ifndef NFS_V2_ONLY
3148 int attrflag;
3149 #endif
3150 struct mbuf *mreq, *mrep, *md, *mb;
3151 nfsfh_t *nfhp;
3152 const int v3 = NFS_ISV3(dvp);
3153
3154 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
3155 nfsm_reqhead(dnp, NFSPROC_LOOKUP,
3156 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
3157 nfsm_fhtom(dnp, v3);
3158 nfsm_strtom(name, len, NFS_MAXNAMLEN);
3159 nfsm_request(dnp, NFSPROC_LOOKUP, procp, cred);
3160 if (npp && !error) {
3161 nfsm_getfh(nfhp, fhlen, v3);
3162 if (*npp) {
3163 np = *npp;
3164 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
3165 free((caddr_t)np->n_fhp, M_NFSBIGFH);
3166 np->n_fhp = &np->n_fh;
3167 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
3168 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
3169 memcpy((caddr_t)np->n_fhp, (caddr_t)nfhp, fhlen);
3170 np->n_fhsize = fhlen;
3171 newvp = NFSTOV(np);
3172 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
3173 VREF(dvp);
3174 newvp = dvp;
3175 np = dnp;
3176 } else {
3177 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
3178 if (error) {
3179 m_freem(mrep);
3180 return (error);
3181 }
3182 newvp = NFSTOV(np);
3183 }
3184 #ifndef NFS_V2_ONLY
3185 if (v3) {
3186 nfsm_postop_attr(newvp, attrflag, 0);
3187 if (!attrflag && *npp == NULL) {
3188 m_freem(mrep);
3189 vput(newvp);
3190 return (ENOENT);
3191 }
3192 } else
3193 #endif
3194 nfsm_loadattr(newvp, (struct vattr *)0, 0);
3195 }
3196 nfsm_reqdone;
3197 if (npp && *npp == NULL) {
3198 if (error) {
3199 if (newvp)
3200 vput(newvp);
3201 } else
3202 *npp = np;
3203 }
3204 return (error);
3205 }
3206
3207 #ifndef NFS_V2_ONLY
3208 /*
3209 * Nfs Version 3 commit rpc
3210 */
3211 int
3212 nfs_commit(vp, offset, cnt, procp)
3213 struct vnode *vp;
3214 off_t offset;
3215 uint32_t cnt;
3216 struct proc *procp;
3217 {
3218 caddr_t cp;
3219 u_int32_t *tl;
3220 int32_t t1, t2;
3221 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
3222 caddr_t bpos, dpos, cp2;
3223 int error = 0, wccflag = NFSV3_WCCRATTR;
3224 struct mbuf *mreq, *mrep, *md, *mb;
3225 struct nfsnode *np;
3226
3227 KASSERT(NFS_ISV3(vp));
3228
3229 #ifdef NFS_DEBUG_COMMIT
3230 printf("commit %lu - %lu\n", (unsigned long)offset,
3231 (unsigned long)(offset + cnt));
3232 #endif
3233
3234 simple_lock(&nmp->nm_slock);
3235 if ((nmp->nm_iflag & NFSMNT_HASWRITEVERF) == 0) {
3236 simple_unlock(&nmp->nm_slock);
3237 return (0);
3238 }
3239 simple_unlock(&nmp->nm_slock);
3240 nfsstats.rpccnt[NFSPROC_COMMIT]++;
3241 np = VTONFS(vp);
3242 nfsm_reqhead(np, NFSPROC_COMMIT, NFSX_FH(1));
3243 nfsm_fhtom(np, 1);
3244 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3245 txdr_hyper(offset, tl);
3246 tl += 2;
3247 *tl = txdr_unsigned(cnt);
3248 nfsm_request(np, NFSPROC_COMMIT, procp, np->n_wcred);
3249 nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, FALSE);
3250 if (!error) {
3251 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
3252 simple_lock(&nmp->nm_slock);
3253 if ((nmp->nm_iflag & NFSMNT_STALEWRITEVERF) ||
3254 memcmp(nmp->nm_writeverf, tl, NFSX_V3WRITEVERF)) {
3255 memcpy(nmp->nm_writeverf, tl, NFSX_V3WRITEVERF);
3256 error = NFSERR_STALEWRITEVERF;
3257 nmp->nm_iflag |= NFSMNT_STALEWRITEVERF;
3258 }
3259 simple_unlock(&nmp->nm_slock);
3260 }
3261 nfsm_reqdone;
3262 return (error);
3263 }
3264 #endif
3265
3266 /*
3267 * Kludge City..
3268 * - make nfs_bmap() essentially a no-op that does no translation
3269 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
3270 * (Maybe I could use the process's page mapping, but I was concerned that
3271 * Kernel Write might not be enabled and also figured copyout() would do
3272 * a lot more work than memcpy() and also it currently happens in the
3273 * context of the swapper process (2).
3274 */
3275 int
3276 nfs_bmap(v)
3277 void *v;
3278 {
3279 struct vop_bmap_args /* {
3280 struct vnode *a_vp;
3281 daddr_t a_bn;
3282 struct vnode **a_vpp;
3283 daddr_t *a_bnp;
3284 int *a_runp;
3285 } */ *ap = v;
3286 struct vnode *vp = ap->a_vp;
3287 int bshift = vp->v_mount->mnt_fs_bshift - vp->v_mount->mnt_dev_bshift;
3288
3289 if (ap->a_vpp != NULL)
3290 *ap->a_vpp = vp;
3291 if (ap->a_bnp != NULL)
3292 *ap->a_bnp = ap->a_bn << bshift;
3293 if (ap->a_runp != NULL)
3294 *ap->a_runp = 1024 * 1024; /* XXX */
3295 return (0);
3296 }
3297
3298 /*
3299 * Strategy routine.
3300 * For async requests when nfsiod(s) are running, queue the request by
3301 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
3302 * request.
3303 */
3304 int
3305 nfs_strategy(v)
3306 void *v;
3307 {
3308 struct vop_strategy_args *ap = v;
3309 struct buf *bp = ap->a_bp;
3310 struct proc *p;
3311 int error = 0;
3312
3313 if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC))
3314 panic("nfs physio/async");
3315 if (bp->b_flags & B_ASYNC)
3316 p = NULL;
3317 else
3318 p = curproc; /* XXX */
3319
3320 /*
3321 * If the op is asynchronous and an i/o daemon is waiting
3322 * queue the request, wake it up and wait for completion
3323 * otherwise just do it ourselves.
3324 */
3325
3326 if ((bp->b_flags & B_ASYNC) == 0 ||
3327 nfs_asyncio(bp))
3328 error = nfs_doio(bp, p);
3329 return (error);
3330 }
3331
3332 /*
3333 * fsync vnode op. Just call nfs_flush() with commit == 1.
3334 */
3335 /* ARGSUSED */
3336 int
3337 nfs_fsync(v)
3338 void *v;
3339 {
3340 struct vop_fsync_args /* {
3341 struct vnodeop_desc *a_desc;
3342 struct vnode * a_vp;
3343 struct ucred * a_cred;
3344 int a_flags;
3345 off_t offlo;
3346 off_t offhi;
3347 struct proc * a_p;
3348 } */ *ap = v;
3349
3350 struct vnode *vp = ap->a_vp;
3351
3352 if (vp->v_type != VREG)
3353 return 0;
3354
3355 return (nfs_flush(vp, ap->a_cred,
3356 (ap->a_flags & FSYNC_WAIT) != 0 ? MNT_WAIT : 0, ap->a_p, 1));
3357 }
3358
3359 /*
3360 * Flush all the data associated with a vnode.
3361 */
3362 int
3363 nfs_flush(vp, cred, waitfor, p, commit)
3364 struct vnode *vp;
3365 struct ucred *cred;
3366 int waitfor;
3367 struct proc *p;
3368 int commit;
3369 {
3370 struct nfsnode *np = VTONFS(vp);
3371 int error;
3372 int flushflags = PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO;
3373 UVMHIST_FUNC("nfs_flush"); UVMHIST_CALLED(ubchist);
3374
3375 simple_lock(&vp->v_interlock);
3376 error = VOP_PUTPAGES(vp, 0, 0, flushflags);
3377 if (np->n_flag & NWRITEERR) {
3378 error = np->n_error;
3379 np->n_flag &= ~NWRITEERR;
3380 }
3381 UVMHIST_LOG(ubchist, "returning %d", error,0,0,0);
3382 return (error);
3383 }
3384
3385 /*
3386 * Return POSIX pathconf information applicable to nfs.
3387 *
3388 * N.B. The NFS V2 protocol doesn't support this RPC.
3389 */
3390 /* ARGSUSED */
3391 int
3392 nfs_pathconf(v)
3393 void *v;
3394 {
3395 struct vop_pathconf_args /* {
3396 struct vnode *a_vp;
3397 int a_name;
3398 register_t *a_retval;
3399 } */ *ap = v;
3400 struct nfsv3_pathconf *pcp;
3401 struct vnode *vp = ap->a_vp;
3402 struct mbuf *mreq, *mrep, *md, *mb;
3403 int32_t t1, t2;
3404 u_int32_t *tl;
3405 caddr_t bpos, dpos, cp, cp2;
3406 int error = 0, attrflag;
3407 #ifndef NFS_V2_ONLY
3408 struct nfsmount *nmp;
3409 unsigned int l;
3410 u_int64_t maxsize;
3411 #endif
3412 const int v3 = NFS_ISV3(vp);
3413 struct nfsnode *np = VTONFS(vp);
3414
3415 switch (ap->a_name) {
3416 /* Names that can be resolved locally. */
3417 case _PC_PIPE_BUF:
3418 *ap->a_retval = PIPE_BUF;
3419 break;
3420 case _PC_SYNC_IO:
3421 *ap->a_retval = 1;
3422 break;
3423 /* Names that cannot be resolved locally; do an RPC, if possible. */
3424 case _PC_LINK_MAX:
3425 case _PC_NAME_MAX:
3426 case _PC_CHOWN_RESTRICTED:
3427 case _PC_NO_TRUNC:
3428 if (!v3) {
3429 error = EINVAL;
3430 break;
3431 }
3432 nfsstats.rpccnt[NFSPROC_PATHCONF]++;
3433 nfsm_reqhead(np, NFSPROC_PATHCONF, NFSX_FH(1));
3434 nfsm_fhtom(np, 1);
3435 nfsm_request(np, NFSPROC_PATHCONF,
3436 curproc, curproc->p_ucred); /* XXX */
3437 nfsm_postop_attr(vp, attrflag, 0);
3438 if (!error) {
3439 nfsm_dissect(pcp, struct nfsv3_pathconf *,
3440 NFSX_V3PATHCONF);
3441 switch (ap->a_name) {
3442 case _PC_LINK_MAX:
3443 *ap->a_retval =
3444 fxdr_unsigned(register_t, pcp->pc_linkmax);
3445 break;
3446 case _PC_NAME_MAX:
3447 *ap->a_retval =
3448 fxdr_unsigned(register_t, pcp->pc_namemax);
3449 break;
3450 case _PC_CHOWN_RESTRICTED:
3451 *ap->a_retval =
3452 (pcp->pc_chownrestricted == nfs_true);
3453 break;
3454 case _PC_NO_TRUNC:
3455 *ap->a_retval =
3456 (pcp->pc_notrunc == nfs_true);
3457 break;
3458 }
3459 }
3460 nfsm_reqdone;
3461 break;
3462 case _PC_FILESIZEBITS:
3463 #ifndef NFS_V2_ONLY
3464 if (v3) {
3465 nmp = VFSTONFS(vp->v_mount);
3466 if ((nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0)
3467 if ((error = nfs_fsinfo(nmp, vp,
3468 curproc->p_ucred, curproc)) != 0) /* XXX */
3469 break;
3470 for (l = 0, maxsize = nmp->nm_maxfilesize;
3471 (maxsize >> l) > 0; l++)
3472 ;
3473 *ap->a_retval = l + 1;
3474 } else
3475 #endif
3476 {
3477 *ap->a_retval = 32; /* NFS V2 limitation */
3478 }
3479 break;
3480 default:
3481 error = EINVAL;
3482 break;
3483 }
3484
3485 return (error);
3486 }
3487
3488 /*
3489 * NFS advisory byte-level locks.
3490 */
3491 int
3492 nfs_advlock(v)
3493 void *v;
3494 {
3495 struct vop_advlock_args /* {
3496 struct vnode *a_vp;
3497 caddr_t a_id;
3498 int a_op;
3499 struct flock *a_fl;
3500 int a_flags;
3501 } */ *ap = v;
3502 struct nfsnode *np = VTONFS(ap->a_vp);
3503
3504 return lf_advlock(ap, &np->n_lockf, np->n_size);
3505 }
3506
3507 /*
3508 * Print out the contents of an nfsnode.
3509 */
3510 int
3511 nfs_print(v)
3512 void *v;
3513 {
3514 struct vop_print_args /* {
3515 struct vnode *a_vp;
3516 } */ *ap = v;
3517 struct vnode *vp = ap->a_vp;
3518 struct nfsnode *np = VTONFS(vp);
3519
3520 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
3521 np->n_vattr->va_fileid, np->n_vattr->va_fsid);
3522 if (vp->v_type == VFIFO)
3523 fifo_printinfo(vp);
3524 printf("\n");
3525 return (0);
3526 }
3527
3528 /*
3529 * nfs unlock wrapper.
3530 */
3531 int
3532 nfs_unlock(void *v)
3533 {
3534 struct vop_unlock_args /* {
3535 struct vnode *a_vp;
3536 int a_flags;
3537 } */ *ap = v;
3538 struct vnode *vp = ap->a_vp;
3539
3540 /*
3541 * VOP_UNLOCK can be called by nfs_loadattrcache
3542 * with v_data == 0.
3543 */
3544 if (VTONFS(vp)) {
3545 nfs_delayedtruncate(vp);
3546 }
3547
3548 return genfs_unlock(v);
3549 }
3550
3551 /*
3552 * nfs special file access vnode op.
3553 * Essentially just get vattr and then imitate iaccess() since the device is
3554 * local to the client.
3555 */
3556 int
3557 nfsspec_access(v)
3558 void *v;
3559 {
3560 struct vop_access_args /* {
3561 struct vnode *a_vp;
3562 int a_mode;
3563 struct ucred *a_cred;
3564 struct proc *a_p;
3565 } */ *ap = v;
3566 struct vattr va;
3567 struct vnode *vp = ap->a_vp;
3568 int error;
3569
3570 error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_p);
3571 if (error)
3572 return (error);
3573
3574 /*
3575 * Disallow write attempts on filesystems mounted read-only;
3576 * unless the file is a socket, fifo, or a block or character
3577 * device resident on the filesystem.
3578 */
3579 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3580 switch (vp->v_type) {
3581 case VREG:
3582 case VDIR:
3583 case VLNK:
3584 return (EROFS);
3585 default:
3586 break;
3587 }
3588 }
3589
3590 return (vaccess(va.va_type, va.va_mode,
3591 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
3592 }
3593
3594 /*
3595 * Read wrapper for special devices.
3596 */
3597 int
3598 nfsspec_read(v)
3599 void *v;
3600 {
3601 struct vop_read_args /* {
3602 struct vnode *a_vp;
3603 struct uio *a_uio;
3604 int a_ioflag;
3605 struct ucred *a_cred;
3606 } */ *ap = v;
3607 struct nfsnode *np = VTONFS(ap->a_vp);
3608
3609 /*
3610 * Set access flag.
3611 */
3612 np->n_flag |= NACC;
3613 np->n_atim.tv_sec = time.tv_sec;
3614 np->n_atim.tv_nsec = time.tv_usec * 1000;
3615 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
3616 }
3617
3618 /*
3619 * Write wrapper for special devices.
3620 */
3621 int
3622 nfsspec_write(v)
3623 void *v;
3624 {
3625 struct vop_write_args /* {
3626 struct vnode *a_vp;
3627 struct uio *a_uio;
3628 int a_ioflag;
3629 struct ucred *a_cred;
3630 } */ *ap = v;
3631 struct nfsnode *np = VTONFS(ap->a_vp);
3632
3633 /*
3634 * Set update flag.
3635 */
3636 np->n_flag |= NUPD;
3637 np->n_mtim.tv_sec = time.tv_sec;
3638 np->n_mtim.tv_nsec = time.tv_usec * 1000;
3639 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
3640 }
3641
3642 /*
3643 * Close wrapper for special devices.
3644 *
3645 * Update the times on the nfsnode then do device close.
3646 */
3647 int
3648 nfsspec_close(v)
3649 void *v;
3650 {
3651 struct vop_close_args /* {
3652 struct vnode *a_vp;
3653 int a_fflag;
3654 struct ucred *a_cred;
3655 struct proc *a_p;
3656 } */ *ap = v;
3657 struct vnode *vp = ap->a_vp;
3658 struct nfsnode *np = VTONFS(vp);
3659 struct vattr vattr;
3660
3661 if (np->n_flag & (NACC | NUPD)) {
3662 np->n_flag |= NCHG;
3663 if (vp->v_usecount == 1 &&
3664 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3665 VATTR_NULL(&vattr);
3666 if (np->n_flag & NACC)
3667 vattr.va_atime = np->n_atim;
3668 if (np->n_flag & NUPD)
3669 vattr.va_mtime = np->n_mtim;
3670 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3671 }
3672 }
3673 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
3674 }
3675
3676 /*
3677 * Read wrapper for fifos.
3678 */
3679 int
3680 nfsfifo_read(v)
3681 void *v;
3682 {
3683 struct vop_read_args /* {
3684 struct vnode *a_vp;
3685 struct uio *a_uio;
3686 int a_ioflag;
3687 struct ucred *a_cred;
3688 } */ *ap = v;
3689 struct nfsnode *np = VTONFS(ap->a_vp);
3690
3691 /*
3692 * Set access flag.
3693 */
3694 np->n_flag |= NACC;
3695 np->n_atim.tv_sec = time.tv_sec;
3696 np->n_atim.tv_nsec = time.tv_usec * 1000;
3697 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
3698 }
3699
3700 /*
3701 * Write wrapper for fifos.
3702 */
3703 int
3704 nfsfifo_write(v)
3705 void *v;
3706 {
3707 struct vop_write_args /* {
3708 struct vnode *a_vp;
3709 struct uio *a_uio;
3710 int a_ioflag;
3711 struct ucred *a_cred;
3712 } */ *ap = v;
3713 struct nfsnode *np = VTONFS(ap->a_vp);
3714
3715 /*
3716 * Set update flag.
3717 */
3718 np->n_flag |= NUPD;
3719 np->n_mtim.tv_sec = time.tv_sec;
3720 np->n_mtim.tv_nsec = time.tv_usec * 1000;
3721 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
3722 }
3723
3724 /*
3725 * Close wrapper for fifos.
3726 *
3727 * Update the times on the nfsnode then do fifo close.
3728 */
3729 int
3730 nfsfifo_close(v)
3731 void *v;
3732 {
3733 struct vop_close_args /* {
3734 struct vnode *a_vp;
3735 int a_fflag;
3736 struct ucred *a_cred;
3737 struct proc *a_p;
3738 } */ *ap = v;
3739 struct vnode *vp = ap->a_vp;
3740 struct nfsnode *np = VTONFS(vp);
3741 struct vattr vattr;
3742
3743 if (np->n_flag & (NACC | NUPD)) {
3744 if (np->n_flag & NACC) {
3745 np->n_atim.tv_sec = time.tv_sec;
3746 np->n_atim.tv_nsec = time.tv_usec * 1000;
3747 }
3748 if (np->n_flag & NUPD) {
3749 np->n_mtim.tv_sec = time.tv_sec;
3750 np->n_mtim.tv_nsec = time.tv_usec * 1000;
3751 }
3752 np->n_flag |= NCHG;
3753 if (vp->v_usecount == 1 &&
3754 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3755 VATTR_NULL(&vattr);
3756 if (np->n_flag & NACC)
3757 vattr.va_atime = np->n_atim;
3758 if (np->n_flag & NUPD)
3759 vattr.va_mtime = np->n_mtim;
3760 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3761 }
3762 }
3763 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
3764 }
Cache object: 9ebc57c9926ac7892b48454b97ab9392
|