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