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