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