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