]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs_vnops.c
dcc4d31dcec021702be2f76e91e8d5382100cbdb
[apple/xnu.git] / bsd / nfs / nfs_vnops.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26 /*
27 * Copyright (c) 1989, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * This code is derived from software contributed to Berkeley by
31 * Rick Macklem at The University of Guelph.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
62 * FreeBSD-Id: nfs_vnops.c,v 1.72 1997/11/07 09:20:48 phk Exp $
63 */
64
65
66 /*
67 * vnode op calls for Sun NFS version 2 and 3
68 */
69 #include <sys/param.h>
70 #include <sys/kernel.h>
71 #include <sys/systm.h>
72 #include <sys/resourcevar.h>
73 #include <sys/proc.h>
74 #include <sys/mount.h>
75 #include <sys/buf.h>
76 #include <sys/malloc.h>
77 #include <sys/mbuf.h>
78 #include <sys/conf.h>
79 #include <sys/namei.h>
80 #include <sys/vnode.h>
81 #include <sys/dirent.h>
82 #include <sys/fcntl.h>
83 #include <sys/lockf.h>
84 #include <sys/ubc.h>
85
86 #include <ufs/ufs/dir.h>
87 #include <vfs/vfs_support.h>
88
89 #include <sys/vm.h>
90 #include <machine/spl.h>
91 #include <vm/vm_pageout.h>
92
93 #include <sys/time.h>
94 #include <kern/clock.h>
95
96 #include <miscfs/fifofs/fifo.h>
97 #include <miscfs/specfs/specdev.h>
98
99 #include <nfs/rpcv2.h>
100 #include <nfs/nfsproto.h>
101 #include <nfs/nfs.h>
102 #include <nfs/nfsnode.h>
103 #include <nfs/nfsmount.h>
104 #include <nfs/xdr_subs.h>
105 #include <nfs/nfsm_subs.h>
106 #include <nfs/nqnfs.h>
107
108 #include <net/if.h>
109 #include <netinet/in.h>
110 #include <netinet/in_var.h>
111 #include <vm/vm_kern.h>
112
113 #include <kern/task.h>
114 #include <kern/sched_prim.h>
115
116 #include <sys/kdebug.h>
117
118 #define FSDBG(A, B, C, D, E) \
119 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_NONE, \
120 (int)(B), (int)(C), (int)(D), (int)(E), 0)
121 #define FSDBG_TOP(A, B, C, D, E) \
122 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_START, \
123 (int)(B), (int)(C), (int)(D), (int)(E), 0)
124 #define FSDBG_BOT(A, B, C, D, E) \
125 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_END, \
126 (int)(B), (int)(C), (int)(D), (int)(E), 0)
127
128 #define TRUE 1
129 #define FALSE 0
130
131 static int nfsspec_read __P((struct vop_read_args *));
132 static int nfsspec_write __P((struct vop_write_args *));
133 static int nfsfifo_read __P((struct vop_read_args *));
134 static int nfsfifo_write __P((struct vop_write_args *));
135 static int nfsspec_close __P((struct vop_close_args *));
136 static int nfsfifo_close __P((struct vop_close_args *));
137 #define nfs_poll vop_nopoll
138 static int nfs_ioctl __P((struct vop_ioctl_args *));
139 static int nfs_select __P((struct vop_select_args *));
140 static int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
141 static int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
142 static int nfs_lookup __P((struct vop_lookup_args *));
143 static int nfs_create __P((struct vop_create_args *));
144 static int nfs_mknod __P((struct vop_mknod_args *));
145 static int nfs_open __P((struct vop_open_args *));
146 static int nfs_close __P((struct vop_close_args *));
147 static int nfs_access __P((struct vop_access_args *));
148 static int nfs_getattr __P((struct vop_getattr_args *));
149 static int nfs_setattr __P((struct vop_setattr_args *));
150 static int nfs_read __P((struct vop_read_args *));
151 static int nfs_mmap __P((struct vop_mmap_args *));
152 static int nfs_fsync __P((struct vop_fsync_args *));
153 static int nfs_remove __P((struct vop_remove_args *));
154 static int nfs_link __P((struct vop_link_args *));
155 static int nfs_rename __P((struct vop_rename_args *));
156 static int nfs_mkdir __P((struct vop_mkdir_args *));
157 static int nfs_rmdir __P((struct vop_rmdir_args *));
158 static int nfs_symlink __P((struct vop_symlink_args *));
159 static int nfs_readdir __P((struct vop_readdir_args *));
160 static int nfs_bmap __P((struct vop_bmap_args *));
161 static int nfs_strategy __P((struct vop_strategy_args *));
162 static int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
163 static int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
164 static int nfsspec_access __P((struct vop_access_args *));
165 static int nfs_readlink __P((struct vop_readlink_args *));
166 static int nfs_print __P((struct vop_print_args *));
167 static int nfs_pathconf __P((struct vop_pathconf_args *));
168 static int nfs_advlock __P((struct vop_advlock_args *));
169 static int nfs_blkatoff __P((struct vop_blkatoff_args *));
170 static int nfs_bwrite __P((struct vop_bwrite_args *));
171 static int nfs_valloc __P((struct vop_valloc_args *));
172 static int nfs_vfree __P((struct vop_vfree_args *));
173 static int nfs_truncate __P((struct vop_truncate_args *));
174 static int nfs_update __P((struct vop_update_args *));
175 static int nfs_pagein __P((struct vop_pagein_args *));
176 static int nfs_pageout __P((struct vop_pageout_args *));
177 static int nfs_blktooff __P((struct vop_blktooff_args *));
178 static int nfs_offtoblk __P((struct vop_offtoblk_args *));
179 static int nfs_cmap __P((struct vop_cmap_args *));
180
181 /*
182 * Global vfs data structures for nfs
183 */
184 vop_t **nfsv2_vnodeop_p;
185 static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
186 { &vop_default_desc, (vop_t *)vn_default_error },
187 { &vop_lookup_desc, (vop_t *)nfs_lookup }, /* lookup */
188 { &vop_create_desc, (vop_t *)nfs_create }, /* create */
189 { &vop_mknod_desc, (vop_t *)nfs_mknod }, /* mknod */
190 { &vop_open_desc, (vop_t *)nfs_open }, /* open */
191 { &vop_close_desc, (vop_t *)nfs_close }, /* close */
192 { &vop_access_desc, (vop_t *)nfs_access }, /* access */
193 { &vop_getattr_desc, (vop_t *)nfs_getattr }, /* getattr */
194 { &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
195 { &vop_read_desc, (vop_t *)nfs_read }, /* read */
196 { &vop_write_desc, (vop_t *)nfs_write }, /* write */
197 { &vop_lease_desc, (vop_t *)nfs_lease_check }, /* lease */
198 { &vop_ioctl_desc, (vop_t *)nfs_ioctl }, /* ioctl */
199 { &vop_select_desc, (vop_t *)nfs_select }, /* select */
200 { &vop_revoke_desc, (vop_t *)nfs_revoke }, /* revoke */
201 { &vop_mmap_desc, (vop_t *)nfs_mmap }, /* mmap */
202 { &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
203 { &vop_seek_desc, (vop_t *)nfs_seek }, /* seek */
204 { &vop_remove_desc, (vop_t *)nfs_remove }, /* remove */
205 { &vop_link_desc, (vop_t *)nfs_link }, /* link */
206 { &vop_rename_desc, (vop_t *)nfs_rename }, /* rename */
207 { &vop_mkdir_desc, (vop_t *)nfs_mkdir }, /* mkdir */
208 { &vop_rmdir_desc, (vop_t *)nfs_rmdir }, /* rmdir */
209 { &vop_symlink_desc, (vop_t *)nfs_symlink }, /* symlink */
210 { &vop_readdir_desc, (vop_t *)nfs_readdir }, /* readdir */
211 { &vop_readlink_desc, (vop_t *)nfs_readlink }, /* readlink */
212 { &vop_abortop_desc, (vop_t *)nfs_abortop }, /* abortop */
213 { &vop_inactive_desc, (vop_t *)nfs_inactive }, /* inactive */
214 { &vop_reclaim_desc, (vop_t *)nfs_reclaim }, /* reclaim */
215 { &vop_lock_desc, (vop_t *)nfs_lock }, /* lock */
216 { &vop_unlock_desc, (vop_t *)nfs_unlock }, /* unlock */
217 { &vop_bmap_desc, (vop_t *)nfs_bmap }, /* bmap */
218 { &vop_strategy_desc, (vop_t *)nfs_strategy }, /* strategy */
219 { &vop_print_desc, (vop_t *)nfs_print }, /* print */
220 { &vop_islocked_desc, (vop_t *)nfs_islocked }, /* islocked */
221 { &vop_pathconf_desc, (vop_t *)nfs_pathconf }, /* pathconf */
222 { &vop_advlock_desc, (vop_t *)nfs_advlock }, /* advlock */
223 { &vop_blkatoff_desc, (vop_t *)nfs_blkatoff }, /* blkatoff */
224 { &vop_valloc_desc, (vop_t *)nfs_valloc }, /* valloc */
225 { &vop_reallocblks_desc, (vop_t *)nfs_reallocblks }, /* reallocblks */
226 { &vop_vfree_desc, (vop_t *)nfs_vfree }, /* vfree */
227 { &vop_truncate_desc, (vop_t *)nfs_truncate }, /* truncate */
228 { &vop_update_desc, (vop_t *)nfs_update }, /* update */
229 { &vop_bwrite_desc, (vop_t *)nfs_bwrite }, /* bwrite */
230 { &vop_pagein_desc, (vop_t *)nfs_pagein }, /* Pagein */
231 { &vop_pageout_desc, (vop_t *)nfs_pageout }, /* Pageout */
232 { &vop_copyfile_desc, (vop_t *)err_copyfile }, /* Copyfile */
233 { &vop_blktooff_desc, (vop_t *)nfs_blktooff }, /* blktooff */
234 { &vop_offtoblk_desc, (vop_t *)nfs_offtoblk }, /* offtoblk */
235 { &vop_cmap_desc, (vop_t *)nfs_cmap }, /* cmap */
236 { NULL, NULL }
237 };
238 struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
239 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
240 #ifdef __FreeBSD__
241 VNODEOP_SET(nfsv2_vnodeop_opv_desc);
242 #endif
243
244 /*
245 * Special device vnode ops
246 */
247 vop_t **spec_nfsv2nodeop_p;
248 static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
249 { &vop_default_desc, (vop_t *)vn_default_error },
250 { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */
251 { &vop_create_desc, (vop_t *)spec_create }, /* create */
252 { &vop_mknod_desc, (vop_t *)spec_mknod }, /* mknod */
253 { &vop_open_desc, (vop_t *)spec_open }, /* open */
254 { &vop_close_desc, (vop_t *)nfsspec_close }, /* close */
255 { &vop_access_desc, (vop_t *)nfsspec_access }, /* access */
256 { &vop_getattr_desc, (vop_t *)nfs_getattr }, /* getattr */
257 { &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
258 { &vop_read_desc, (vop_t *)nfsspec_read }, /* read */
259 { &vop_write_desc, (vop_t *)nfsspec_write }, /* write */
260 { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */
261 { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */
262 { &vop_select_desc, (vop_t *)spec_select }, /* select */
263 { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */
264 { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */
265 { &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
266 { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */
267 { &vop_remove_desc, (vop_t *)spec_remove }, /* remove */
268 { &vop_link_desc, (vop_t *)spec_link }, /* link */
269 { &vop_rename_desc, (vop_t *)spec_rename }, /* rename */
270 { &vop_mkdir_desc, (vop_t *)spec_mkdir }, /* mkdir */
271 { &vop_rmdir_desc, (vop_t *)spec_rmdir }, /* rmdir */
272 { &vop_symlink_desc, (vop_t *)spec_symlink }, /* symlink */
273 { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */
274 { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */
275 { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */
276 { &vop_inactive_desc, (vop_t *)nfs_inactive }, /* inactive */
277 { &vop_reclaim_desc, (vop_t *)nfs_reclaim }, /* reclaim */
278 { &vop_lock_desc, (vop_t *)nfs_lock }, /* lock */
279 { &vop_unlock_desc, (vop_t *)nfs_unlock }, /* unlock */
280 { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */
281 { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */
282 { &vop_print_desc, (vop_t *)nfs_print }, /* print */
283 { &vop_islocked_desc, (vop_t *)nfs_islocked }, /* islocked */
284 { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */
285 { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */
286 { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */
287 { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */
288 { &vop_reallocblks_desc, (vop_t *)spec_reallocblks }, /* reallocblks */
289 { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */
290 { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */
291 { &vop_update_desc, (vop_t *)nfs_update }, /* update */
292 { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
293 { &vop_devblocksize_desc, (vop_t *)spec_devblocksize }, /* devblocksize */
294 { &vop_pagein_desc, (vop_t *)nfs_pagein }, /* Pagein */
295 { &vop_pageout_desc, (vop_t *)nfs_pageout }, /* Pageout */
296 { &vop_blktooff_desc, (vop_t *)nfs_blktooff }, /* blktooff */
297 { &vop_offtoblk_desc, (vop_t *)nfs_offtoblk }, /* offtoblk */
298 { &vop_cmap_desc, (vop_t *)nfs_cmap }, /* cmap */
299 { NULL, NULL }
300 };
301 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
302 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };
303 #ifdef __FreeBSD__
304 VNODEOP_SET(spec_nfsv2nodeop_opv_desc);
305 #endif
306
307 vop_t **fifo_nfsv2nodeop_p;
308 static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
309 { &vop_default_desc, (vop_t *)vn_default_error },
310 { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */
311 { &vop_create_desc, (vop_t *)fifo_create }, /* create */
312 { &vop_mknod_desc, (vop_t *)fifo_mknod }, /* mknod */
313 { &vop_open_desc, (vop_t *)fifo_open }, /* open */
314 { &vop_close_desc, (vop_t *)nfsfifo_close }, /* close */
315 { &vop_access_desc, (vop_t *)nfsspec_access }, /* access */
316 { &vop_getattr_desc, (vop_t *)nfs_getattr }, /* getattr */
317 { &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */
318 { &vop_read_desc, (vop_t *)nfsfifo_read }, /* read */
319 { &vop_write_desc, (vop_t *)nfsfifo_write }, /* write */
320 { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */
321 { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */
322 { &vop_select_desc, (vop_t *)fifo_select }, /* select */
323 { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */
324 { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */
325 { &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */
326 { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */
327 { &vop_remove_desc, (vop_t *)fifo_remove }, /* remove */
328 { &vop_link_desc, (vop_t *)fifo_link }, /* link */
329 { &vop_rename_desc, (vop_t *)fifo_rename }, /* rename */
330 { &vop_mkdir_desc, (vop_t *)fifo_mkdir }, /* mkdir */
331 { &vop_rmdir_desc, (vop_t *)fifo_rmdir }, /* rmdir */
332 { &vop_symlink_desc, (vop_t *)fifo_symlink }, /* symlink */
333 { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */
334 { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */
335 { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */
336 { &vop_inactive_desc, (vop_t *)nfs_inactive }, /* inactive */
337 { &vop_reclaim_desc, (vop_t *)nfs_reclaim }, /* reclaim */
338 { &vop_lock_desc, (vop_t *)nfs_lock }, /* lock */
339 { &vop_unlock_desc, (vop_t *)nfs_unlock }, /* unlock */
340 { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */
341 { &vop_strategy_desc, (vop_t *)fifo_strategy }, /* strategy */
342 { &vop_print_desc, (vop_t *)nfs_print }, /* print */
343 { &vop_islocked_desc, (vop_t *)nfs_islocked }, /* islocked */
344 { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */
345 { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */
346 { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */
347 { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */
348 { &vop_reallocblks_desc, (vop_t *)fifo_reallocblks }, /* reallocblks */
349 { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */
350 { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */
351 { &vop_update_desc, (vop_t *)nfs_update }, /* update */
352 { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */
353 { &vop_pagein_desc, (vop_t *)nfs_pagein }, /* Pagein */
354 { &vop_pageout_desc, (vop_t *)nfs_pageout }, /* Pageout */
355 { &vop_blktooff_desc, (vop_t *)nfs_blktooff }, /* blktooff */
356 { &vop_offtoblk_desc, (vop_t *)nfs_offtoblk }, /* offtoblk */
357 { &vop_cmap_desc, (vop_t *)nfs_cmap }, /* cmap */
358 { NULL, NULL }
359 };
360 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
361 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
362 #ifdef __FreeBSD__
363 VNODEOP_SET(fifo_nfsv2nodeop_opv_desc);
364 #endif
365
366 static int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
367 struct ucred *cred, struct proc *procp));
368 static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp,
369 struct componentname *cnp,
370 struct vattr *vap));
371 static int nfs_removerpc __P((struct vnode *dvp, char *name, int namelen,
372 struct ucred *cred, struct proc *proc));
373 static int nfs_renamerpc __P((struct vnode *fdvp, char *fnameptr,
374 int fnamelen, struct vnode *tdvp,
375 char *tnameptr, int tnamelen,
376 struct ucred *cred, struct proc *proc));
377 static int nfs_renameit __P((struct vnode *sdvp,
378 struct componentname *scnp,
379 struct sillyrename *sp));
380
381 /*
382 * Global variables
383 */
384 extern u_long nfs_true, nfs_false;
385 extern struct nfsstats nfsstats;
386 extern nfstype nfsv3_type[9];
387 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
388 struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
389 int nfs_numasync = 0;
390 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
391
392 static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
393 /* SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
394 &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
395 */
396 #define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY \
397 | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \
398 | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
399
400
401 /*
402 * the following are needed only by nfs_pageout to know how to handle errors
403 * see nfs_pageout comments on explanation of actions.
404 * the errors here are copied from errno.h and errors returned by servers
405 * are expected to match the same numbers here. If not, our actions maybe
406 * erroneous.
407 */
408 enum actiontype {NOACTION, DUMP, DUMPANDLOG, RETRY, RETRYWITHSLEEP, SEVER};
409
410 static int errorcount[ELAST+1]; /* better be zeros when initialized */
411
412 static const short errortooutcome[ELAST+1] = {
413 NOACTION,
414 DUMP, /* EPERM 1 Operation not permitted */
415 DUMP, /* ENOENT 2 No such file or directory */
416 DUMPANDLOG, /* ESRCH 3 No such process */
417 RETRY, /* EINTR 4 Interrupted system call */
418 DUMP, /* EIO 5 Input/output error */
419 DUMP, /* ENXIO 6 Device not configured */
420 DUMPANDLOG, /* E2BIG 7 Argument list too long */
421 DUMPANDLOG, /* ENOEXEC 8 Exec format error */
422 DUMPANDLOG, /* EBADF 9 Bad file descriptor */
423 DUMPANDLOG, /* ECHILD 10 No child processes */
424 DUMPANDLOG, /* EDEADLK 11 Resource deadlock avoided - was EAGAIN */
425 RETRY, /* ENOMEM 12 Cannot allocate memory */
426 DUMP, /* EACCES 13 Permission denied */
427 DUMPANDLOG, /* EFAULT 14 Bad address */
428 DUMPANDLOG, /* ENOTBLK 15 POSIX - Block device required */
429 RETRY, /* EBUSY 16 Device busy */
430 DUMP, /* EEXIST 17 File exists */
431 DUMP, /* EXDEV 18 Cross-device link */
432 DUMP, /* ENODEV 19 Operation not supported by device */
433 DUMP, /* ENOTDIR 20 Not a directory */
434 DUMP, /* EISDIR 21 Is a directory */
435 DUMP, /* EINVAL 22 Invalid argument */
436 DUMPANDLOG, /* ENFILE 23 Too many open files in system */
437 DUMPANDLOG, /* EMFILE 24 Too many open files */
438 DUMPANDLOG, /* ENOTTY 25 Inappropriate ioctl for device */
439 DUMPANDLOG, /* ETXTBSY 26 Text file busy - POSIX */
440 DUMP, /* EFBIG 27 File too large */
441 DUMP, /* ENOSPC 28 No space left on device */
442 DUMPANDLOG, /* ESPIPE 29 Illegal seek */
443 DUMP, /* EROFS 30 Read-only file system */
444 DUMP, /* EMLINK 31 Too many links */
445 RETRY, /* EPIPE 32 Broken pipe */
446 /* math software */
447 DUMPANDLOG, /* EDOM 33 Numerical argument out of domain */
448 DUMPANDLOG, /* ERANGE 34 Result too large */
449 RETRY, /* EAGAIN/EWOULDBLOCK 35 Resource temporarily unavailable */
450 DUMPANDLOG, /* EINPROGRESS 36 Operation now in progress */
451 DUMPANDLOG, /* EALREADY 37 Operation already in progress */
452 /* ipc/network software -- argument errors */
453 DUMPANDLOG, /* ENOTSOC 38 Socket operation on non-socket */
454 DUMPANDLOG, /* EDESTADDRREQ 39 Destination address required */
455 DUMPANDLOG, /* EMSGSIZE 40 Message too long */
456 DUMPANDLOG, /* EPROTOTYPE 41 Protocol wrong type for socket */
457 DUMPANDLOG, /* ENOPROTOOPT 42 Protocol not available */
458 DUMPANDLOG, /* EPROTONOSUPPORT 43 Protocol not supported */
459 DUMPANDLOG, /* ESOCKTNOSUPPORT 44 Socket type not supported */
460 DUMPANDLOG, /* ENOTSUP 45 Operation not supported */
461 DUMPANDLOG, /* EPFNOSUPPORT 46 Protocol family not supported */
462 DUMPANDLOG, /* EAFNOSUPPORT 47 Address family not supported by protocol family */
463 DUMPANDLOG, /* EADDRINUSE 48 Address already in use */
464 DUMPANDLOG, /* EADDRNOTAVAIL 49 Can't assign requested address */
465 /* ipc/network software -- operational errors */
466 RETRY, /* ENETDOWN 50 Network is down */
467 RETRY, /* ENETUNREACH 51 Network is unreachable */
468 RETRY, /* ENETRESET 52 Network dropped connection on reset */
469 RETRY, /* ECONNABORTED 53 Software caused connection abort */
470 RETRY, /* ECONNRESET 54 Connection reset by peer */
471 RETRY, /* ENOBUFS 55 No buffer space available */
472 RETRY, /* EISCONN 56 Socket is already connected */
473 RETRY, /* ENOTCONN 57 Socket is not connected */
474 RETRY, /* ESHUTDOWN 58 Can't send after socket shutdown */
475 RETRY, /* ETOOMANYREFS 59 Too many references: can't splice */
476 RETRY, /* ETIMEDOUT 60 Operation timed out */
477 RETRY, /* ECONNREFUSED 61 Connection refused */
478
479 DUMPANDLOG, /* ELOOP 62 Too many levels of symbolic links */
480 DUMP, /* ENAMETOOLONG 63 File name too long */
481 RETRY, /* EHOSTDOWN 64 Host is down */
482 RETRY, /* EHOSTUNREACH 65 No route to host */
483 DUMP, /* ENOTEMPTY 66 Directory not empty */
484 /* quotas & mush */
485 DUMPANDLOG, /* PROCLIM 67 Too many processes */
486 DUMPANDLOG, /* EUSERS 68 Too many users */
487 DUMPANDLOG, /* EDQUOT 69 Disc quota exceeded */
488 /* Network File System */
489 DUMP, /* ESTALE 70 Stale NFS file handle */
490 DUMP, /* EREMOTE 71 Too many levels of remote in path */
491 DUMPANDLOG, /* EBADRPC 72 RPC struct is bad */
492 DUMPANDLOG, /* ERPCMISMATCH 73 RPC version wrong */
493 DUMPANDLOG, /* EPROGUNAVAIL 74 RPC prog. not avail */
494 DUMPANDLOG, /* EPROGMISMATCH 75 Program version wrong */
495 DUMPANDLOG, /* EPROCUNAVAIL 76 Bad procedure for program */
496
497 DUMPANDLOG, /* ENOLCK 77 No locks available */
498 DUMPANDLOG, /* ENOSYS 78 Function not implemented */
499 DUMPANDLOG, /* EFTYPE 79 Inappropriate file type or format */
500 DUMPANDLOG, /* EAUTH 80 Authentication error */
501 DUMPANDLOG, /* ENEEDAUTH 81 Need authenticator */
502 /* Intelligent device errors */
503 DUMPANDLOG, /* EPWROFF 82 Device power is off */
504 DUMPANDLOG, /* EDEVERR 83 Device error, e.g. paper out */
505 DUMPANDLOG, /* EOVERFLOW 84 Value too large to be stored in data type */
506 /* Program loading errors */
507 DUMPANDLOG, /* EBADEXEC 85 Bad executable */
508 DUMPANDLOG, /* EBADARCH 86 Bad CPU type in executable */
509 DUMPANDLOG, /* ESHLIBVERS 87 Shared library version mismatch */
510 DUMPANDLOG, /* EBADMACHO 88 Malformed Macho file */
511 };
512
513
514 static short
515 nfs_pageouterrorhandler(error)
516 int error;
517 {
518 if (error > ELAST)
519 return(DUMP);
520 else
521 return(errortooutcome[error]);
522 }
523
524 static int
525 nfs3_access_otw(struct vnode *vp,
526 int wmode,
527 struct proc *p,
528 struct ucred *cred)
529 {
530 const int v3 = 1;
531 u_int32_t *tl;
532 int error = 0, attrflag;
533
534 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
535 caddr_t bpos, dpos, cp2;
536 register int32_t t1, t2;
537 register caddr_t cp;
538 u_int32_t rmode;
539 struct nfsnode *np = VTONFS(vp);
540 u_int64_t xid;
541
542 nfsstats.rpccnt[NFSPROC_ACCESS]++;
543 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
544 nfsm_fhtom(vp, v3);
545 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
546 *tl = txdr_unsigned(wmode);
547 nfsm_request(vp, NFSPROC_ACCESS, p, cred, &xid);
548 nfsm_postop_attr(vp, attrflag, &xid);
549 if (!error) {
550 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
551 rmode = fxdr_unsigned(u_int32_t, *tl);
552 np->n_mode = rmode;
553 np->n_modeuid = cred->cr_uid;
554 np->n_modestamp = time_second;
555 }
556 nfsm_reqdone;
557 return error;
558 }
559
560 /*
561 * nfs access vnode op.
562 * For nfs version 2, just return ok. File accesses may fail later.
563 * For nfs version 3, use the access rpc to check accessibility. If file modes
564 * are changed on the server, accesses might still fail later.
565 */
566 static int
567 nfs_access(ap)
568 struct vop_access_args /* {
569 struct vnode *a_vp;
570 int a_mode;
571 struct ucred *a_cred;
572 struct proc *a_p;
573 } */ *ap;
574 {
575 register struct vnode *vp = ap->a_vp;
576 int error = 0;
577 u_long mode, wmode;
578 int v3 = NFS_ISV3(vp);
579 struct nfsnode *np = VTONFS(vp);
580
581 /*
582 * For nfs v3, do an access rpc, otherwise you are stuck emulating
583 * ufs_access() locally using the vattr. This may not be correct,
584 * since the server may apply other access criteria such as
585 * client uid-->server uid mapping that we do not know about, but
586 * this is better than just returning anything that is lying about
587 * in the cache.
588 */
589 if (v3) {
590 if (ap->a_mode & VREAD)
591 mode = NFSV3ACCESS_READ;
592 else
593 mode = 0;
594 if (vp->v_type == VDIR) {
595 if (ap->a_mode & VWRITE)
596 mode |= NFSV3ACCESS_MODIFY |
597 NFSV3ACCESS_EXTEND | NFSV3ACCESS_DELETE;
598 if (ap->a_mode & VEXEC)
599 mode |= NFSV3ACCESS_LOOKUP;
600 } else {
601 if (ap->a_mode & VWRITE)
602 mode |= NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND;
603 if (ap->a_mode & VEXEC)
604 mode |= NFSV3ACCESS_EXECUTE;
605 }
606 /* XXX safety belt, only make blanket request if caching */
607 if (nfsaccess_cache_timeout > 0) {
608 wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY |
609 NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE |
610 NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP;
611 } else
612 wmode = mode;
613
614 /*
615 * Does our cached result allow us to give a definite yes to
616 * this request?
617 */
618 if (time_second < np->n_modestamp + nfsaccess_cache_timeout &&
619 ap->a_cred->cr_uid == np->n_modeuid &&
620 (np->n_mode & mode) == mode) {
621 /* nfsstats.accesscache_hits++; */
622 } else {
623 /*
624 * Either a no, or a don't know. Go to the wire.
625 */
626 /* nfsstats.accesscache_misses++; */
627 error = nfs3_access_otw(vp, wmode, ap->a_p,ap->a_cred);
628 if (!error) {
629 if ((np->n_mode & mode) != mode)
630 error = EACCES;
631 }
632 }
633 } else
634 return (nfsspec_access(ap)); /* NFSv2 case checks for EROFS here */
635 /*
636 * Disallow write attempts on filesystems mounted read-only;
637 * unless the file is a socket, fifo, or a block or character
638 * device resident on the filesystem.
639 * CSM - moved EROFS check down per NetBSD rev 1.71. So you
640 * get the correct error value with layered filesystems.
641 * EKN - moved the return(error) below this so it does get called.
642 */
643 if (!error && (ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
644 switch (vp->v_type) {
645 case VREG: case VDIR: case VLNK:
646 error = EROFS;
647 default:
648 break;
649 }
650 }
651 return (error);
652 }
653
654 /*
655 * nfs open vnode op
656 * Check to see if the type is ok
657 * and that deletion is not in progress.
658 * For paged in text files, you will need to flush the page cache
659 * if consistency is lost.
660 */
661 /* ARGSUSED */
662
663 static int
664 nfs_open(ap)
665 struct vop_open_args /* {
666 struct vnode *a_vp;
667 int a_mode;
668 struct ucred *a_cred;
669 struct proc *a_p;
670 } */ *ap;
671 {
672 register struct vnode *vp = ap->a_vp;
673 struct nfsnode *np = VTONFS(vp);
674 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
675 struct vattr vattr;
676 int error;
677
678 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
679 return (EACCES);
680 }
681 /*
682 * Get a valid lease. If cached data is stale, flush it.
683 */
684 if (nmp->nm_flag & NFSMNT_NQNFS) {
685 if (NQNFS_CKINVALID(vp, np, ND_READ)) {
686 do {
687 error = nqnfs_getlease(vp, ND_READ, ap->a_cred,
688 ap->a_p);
689 } while (error == NQNFS_EXPIRED);
690 if (error)
691 return (error);
692 if (np->n_lrev != np->n_brev ||
693 (np->n_flag & NQNFSNONCACHE)) {
694 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
695 ap->a_p, 1)) == EINTR)
696 return (error);
697 np->n_brev = np->n_lrev;
698 }
699 }
700 } else {
701 if (np->n_flag & NMODIFIED) {
702 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
703 ap->a_p, 1)) == EINTR)
704 return (error);
705 np->n_attrstamp = 0;
706 if (vp->v_type == VDIR)
707 np->n_direofoffset = 0;
708 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
709 if (error)
710 return (error);
711 np->n_mtime = vattr.va_mtime.tv_sec;
712 } else {
713 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
714 if (error)
715 return (error);
716 if (np->n_mtime != vattr.va_mtime.tv_sec) {
717 if (vp->v_type == VDIR)
718 np->n_direofoffset = 0;
719 if ((error = nfs_vinvalbuf(vp, V_SAVE,
720 ap->a_cred, ap->a_p, 1)) == EINTR)
721 return (error);
722 np->n_mtime = vattr.va_mtime.tv_sec;
723 }
724 }
725 }
726 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
727 np->n_attrstamp = 0; /* For Open/Close consistency */
728 return (0);
729 }
730
731 /*
732 * nfs close vnode op
733 * What an NFS client should do upon close after writing is a debatable issue.
734 * Most NFS clients push delayed writes to the server upon close, basically for
735 * two reasons:
736 * 1 - So that any write errors may be reported back to the client process
737 * doing the close system call. By far the two most likely errors are
738 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
739 * 2 - To put a worst case upper bound on cache inconsistency between
740 * multiple clients for the file.
741 * There is also a consistency problem for Version 2 of the protocol w.r.t.
742 * not being able to tell if other clients are writing a file concurrently,
743 * since there is no way of knowing if the changed modify time in the reply
744 * is only due to the write for this client.
745 * (NFS Version 3 provides weak cache consistency data in the reply that
746 * should be sufficient to detect and handle this case.)
747 *
748 * The current code does the following:
749 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
750 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
751 * or commit them (this satisfies 1 and 2 except for the
752 * case where the server crashes after this close but
753 * before the commit RPC, which is felt to be "good
754 * enough". Changing the last argument to nfs_flush() to
755 * a 1 would force a commit operation, if it is felt a
756 * commit is necessary now.
757 * for NQNFS - do nothing now, since 2 is dealt with via leases and
758 * 1 should be dealt with via an fsync() system call for
759 * cases where write errors are important.
760 */
761 /* ARGSUSED */
762 static int
763 nfs_close(ap)
764 struct vop_close_args /* {
765 struct vnodeop_desc *a_desc;
766 struct vnode *a_vp;
767 int a_fflag;
768 struct ucred *a_cred;
769 struct proc *a_p;
770 } */ *ap;
771 {
772 register struct vnode *vp = ap->a_vp;
773 register struct nfsnode *np = VTONFS(vp);
774 int error = 0;
775
776 if (vp->v_type == VREG) {
777 #if DIAGNOSTIC
778 register struct sillyrename *sp = np->n_sillyrename;
779 if (sp)
780 kprintf("nfs_close: %s, dvp=%x, vp=%x, ap=%x, np=%x, sp=%x\n",
781 &sp->s_name[0], (unsigned)(sp->s_dvp), (unsigned)vp,
782 (unsigned)ap, (unsigned)np, (unsigned)sp);
783 #endif
784 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
785 (np->n_flag & NMODIFIED)) {
786 if (NFS_ISV3(vp)) {
787 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 1);
788 /*
789 * We cannot clear the NMODIFIED bit in np->n_flag due to
790 * potential races with other processes
791 * NMODIFIED is a hint
792 */
793 /* np->n_flag &= ~NMODIFIED; */
794 } else
795 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
796 np->n_attrstamp = 0;
797 }
798 if (np->n_flag & NWRITEERR) {
799 np->n_flag &= ~NWRITEERR;
800 error = np->n_error;
801 }
802 }
803 return (error);
804 }
805
806 /*
807 * nfs getattr call from vfs.
808 */
809 static int
810 nfs_getattr(ap)
811 struct vop_getattr_args /* {
812 struct vnode *a_vp;
813 struct vattr *a_vap;
814 struct ucred *a_cred;
815 struct proc *a_p;
816 } */ *ap;
817 {
818 register struct vnode *vp = ap->a_vp;
819 register struct nfsnode *np = VTONFS(vp);
820 register caddr_t cp;
821 register u_long *tl;
822 register int t1, t2;
823 caddr_t bpos, dpos;
824 int error = 0;
825 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
826 int v3 = NFS_ISV3(vp);
827 u_int64_t xid;
828 int avoidfloods;
829
830 FSDBG_TOP(513, np->n_size, np, np->n_vattr.va_size, np->n_flag);
831 /*
832 * Update local times for special files.
833 */
834 if (np->n_flag & (NACC | NUPD))
835 np->n_flag |= NCHG;
836 /*
837 * First look in the cache.
838 */
839 if ((error = nfs_getattrcache(vp, ap->a_vap)) == 0) {
840 FSDBG_BOT(513, np->n_size, 0, np->n_vattr.va_size, np->n_flag);
841 return (0);
842 }
843 if (error != ENOENT) {
844 FSDBG_BOT(513, np->n_size, error, np->n_vattr.va_size,
845 np->n_flag);
846 return (error);
847 }
848 error = 0;
849
850 if (v3 && nfsaccess_cache_timeout > 0) {
851 /* nfsstats.accesscache_misses++; */
852 if (error = nfs3_access_otw(vp, NFSV3ACCESS_ALL, ap->a_p,
853 ap->a_cred))
854 return (error);
855 if ((error = nfs_getattrcache(vp, ap->a_vap)) == 0)
856 return (0);
857 if (error != ENOENT)
858 return (error);
859 error = 0;
860 }
861 avoidfloods = 0;
862 tryagain:
863 nfsstats.rpccnt[NFSPROC_GETATTR]++;
864 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
865 nfsm_fhtom(vp, v3);
866 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred, &xid);
867 if (!error) {
868 nfsm_loadattr(vp, ap->a_vap, &xid);
869 if (!xid) { /* out-of-order rpc - attributes were dropped */
870 m_freem(mrep);
871 FSDBG(513, -1, np, np->n_xid << 32, np->n_xid);
872 if (avoidfloods++ < 100)
873 goto tryagain;
874 /*
875 * avoidfloods>1 is bizarre. at 100 pull the plug
876 */
877 panic("nfs_getattr: getattr flood\n");
878 }
879 if (np->n_mtime != ap->a_vap->va_mtime.tv_sec) {
880 FSDBG(513, -1, np, -1, vp);
881 if (vp->v_type == VDIR)
882 nfs_invaldir(vp);
883 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
884 ap->a_p, 1);
885 FSDBG(513, -1, np, -2, error);
886 if (!error)
887 np->n_mtime = ap->a_vap->va_mtime.tv_sec;
888 }
889 }
890 nfsm_reqdone;
891
892 FSDBG_BOT(513, np->n_size, -1, np->n_vattr.va_size, error);
893 return (error);
894 }
895
896 /*
897 * nfs setattr call.
898 */
899 static int
900 nfs_setattr(ap)
901 struct vop_setattr_args /* {
902 struct vnodeop_desc *a_desc;
903 struct vnode *a_vp;
904 struct vattr *a_vap;
905 struct ucred *a_cred;
906 struct proc *a_p;
907 } */ *ap;
908 {
909 register struct vnode *vp = ap->a_vp;
910 register struct nfsnode *np = VTONFS(vp);
911 register struct vattr *vap = ap->a_vap;
912 int error = 0;
913 u_quad_t tsize;
914
915 #ifndef nolint
916 tsize = (u_quad_t)0;
917 #endif
918
919 #ifdef XXX /* enable this code soon! (but test it first) */
920 /*
921 * Setting of flags is not supported.
922 */
923 if (vap->va_flags != VNOVAL)
924 return (EOPNOTSUPP);
925 #endif
926
927 /*
928 * Disallow write attempts if the filesystem is mounted read-only.
929 */
930 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
931 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
932 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
933 (vp->v_mount->mnt_flag & MNT_RDONLY))
934 return (EROFS);
935 if (vap->va_size != VNOVAL) {
936 switch (vp->v_type) {
937 case VDIR:
938 return (EISDIR);
939 case VCHR:
940 case VBLK:
941 case VSOCK:
942 case VFIFO:
943 if (vap->va_mtime.tv_sec == VNOVAL &&
944 vap->va_atime.tv_sec == VNOVAL &&
945 vap->va_mode == (u_short)VNOVAL &&
946 vap->va_uid == (uid_t)VNOVAL &&
947 vap->va_gid == (gid_t)VNOVAL)
948 return (0);
949 vap->va_size = VNOVAL;
950 break;
951 default:
952 /*
953 * Disallow write attempts if the filesystem is
954 * mounted read-only.
955 */
956 if (vp->v_mount->mnt_flag & MNT_RDONLY)
957 return (EROFS);
958 FSDBG_TOP(512, np->n_size, vap->va_size,
959 np->n_vattr.va_size, np->n_flag);
960 if (np->n_flag & NMODIFIED) {
961 if (vap->va_size == 0)
962 error = nfs_vinvalbuf(vp, 0,
963 ap->a_cred, ap->a_p, 1);
964 else
965 error = nfs_vinvalbuf(vp, V_SAVE,
966 ap->a_cred, ap->a_p, 1);
967 if (error) {
968 printf("nfs_setattr: nfs_vinvalbuf %d\n", error);
969 FSDBG_BOT(512, np->n_size, vap->va_size,
970 np->n_vattr.va_size, -1);
971 return (error);
972 }
973 } else if (np->n_size > vap->va_size) { /* shrinking? */
974 daddr_t obn, bn;
975 int biosize;
976 struct buf *bp;
977
978 biosize = min(vp->v_mount->mnt_stat.f_iosize,
979 PAGE_SIZE);
980 obn = (np->n_size - 1) / biosize;
981 bn = vap->va_size / biosize;
982 for ( ; obn >= bn; obn--)
983 if (incore(vp, obn)) {
984 bp = getblk(vp, obn, biosize, 0,
985 0, BLK_READ);
986 FSDBG(512, bp, bp->b_flags,
987 0, obn);
988 SET(bp->b_flags, B_INVAL);
989 brelse(bp);
990 }
991 }
992 tsize = np->n_size;
993 np->n_size = np->n_vattr.va_size = vap->va_size;
994 ubc_setsize(vp, (off_t)vap->va_size); /* XXX */
995 };
996 } else if ((vap->va_mtime.tv_sec != VNOVAL ||
997 vap->va_atime.tv_sec != VNOVAL) &&
998 (np->n_flag & NMODIFIED) && vp->v_type == VREG &&
999 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
1000 ap->a_p, 1)) == EINTR)
1001 return (error);
1002 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
1003 FSDBG_BOT(512, np->n_size, vap->va_size, np->n_vattr.va_size, error);
1004 if (error && vap->va_size != VNOVAL) {
1005 /* make every effort to resync file size w/ server... */
1006 int err = 0; /* preserve "error" for return */
1007
1008 printf("nfs_setattr: nfs_setattrrpc %d\n", error);
1009 np->n_size = np->n_vattr.va_size = tsize;
1010 ubc_setsize(vp, (off_t)np->n_size); /* XXX check error */
1011 vap->va_size = tsize;
1012 err = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
1013 if (err)
1014 printf("nfs_setattr1: nfs_setattrrpc %d\n", err);
1015 }
1016 return (error);
1017 }
1018
1019 /*
1020 * Do an nfs setattr rpc.
1021 */
1022 static int
1023 nfs_setattrrpc(vp, vap, cred, procp)
1024 register struct vnode *vp;
1025 register struct vattr *vap;
1026 struct ucred *cred;
1027 struct proc *procp;
1028 {
1029 register struct nfsv2_sattr *sp;
1030 register caddr_t cp;
1031 register long t1, t2;
1032 caddr_t bpos, dpos, cp2;
1033 u_long *tl;
1034 int error = 0, wccflag = NFSV3_WCCRATTR;
1035 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1036 int v3 = NFS_ISV3(vp);
1037 u_int64_t xid;
1038
1039 nfsstats.rpccnt[NFSPROC_SETATTR]++;
1040 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
1041 nfsm_fhtom(vp, v3);
1042 if (v3) {
1043 if (vap->va_mode != (u_short)VNOVAL) {
1044 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1045 *tl++ = nfs_true;
1046 *tl = txdr_unsigned(vap->va_mode);
1047 } else {
1048 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1049 *tl = nfs_false;
1050 }
1051 if (vap->va_uid != (uid_t)VNOVAL) {
1052 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1053 *tl++ = nfs_true;
1054 *tl = txdr_unsigned(vap->va_uid);
1055 } else {
1056 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1057 *tl = nfs_false;
1058 }
1059 if (vap->va_gid != (gid_t)VNOVAL) {
1060 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1061 *tl++ = nfs_true;
1062 *tl = txdr_unsigned(vap->va_gid);
1063 } else {
1064 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1065 *tl = nfs_false;
1066 }
1067 if (vap->va_size != VNOVAL) {
1068 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
1069 *tl++ = nfs_true;
1070 txdr_hyper(&vap->va_size, tl);
1071 } else {
1072 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1073 *tl = nfs_false;
1074 }
1075 if (vap->va_atime.tv_sec != VNOVAL) {
1076 if (vap->va_atime.tv_sec != time.tv_sec) {
1077 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
1078 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
1079 txdr_nfsv3time(&vap->va_atime, tl);
1080 } else {
1081 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1082 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
1083 }
1084 } else {
1085 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1086 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
1087 }
1088 if (vap->va_mtime.tv_sec != VNOVAL) {
1089 if (vap->va_mtime.tv_sec != time.tv_sec) {
1090 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
1091 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
1092 txdr_nfsv3time(&vap->va_mtime, tl);
1093 } else {
1094 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1095 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
1096 }
1097 } else {
1098 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1099 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
1100 }
1101 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1102 *tl = nfs_false;
1103 } else {
1104 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1105 if (vap->va_mode == (u_short)VNOVAL)
1106 sp->sa_mode = VNOVAL;
1107 else
1108 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
1109 if (vap->va_uid == (uid_t)VNOVAL)
1110 sp->sa_uid = VNOVAL;
1111 else
1112 sp->sa_uid = txdr_unsigned(vap->va_uid);
1113 if (vap->va_gid == (gid_t)VNOVAL)
1114 sp->sa_gid = VNOVAL;
1115 else
1116 sp->sa_gid = txdr_unsigned(vap->va_gid);
1117 sp->sa_size = txdr_unsigned(vap->va_size);
1118 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1119 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1120 }
1121 nfsm_request(vp, NFSPROC_SETATTR, procp, cred, &xid);
1122 if (v3) {
1123 nfsm_wcc_data(vp, wccflag, &xid);
1124 if (!wccflag && vp->v_type != VBAD) /* EINVAL on VBAD node */
1125 VTONFS(vp)->n_attrstamp = 0;
1126 } else
1127 nfsm_loadattr(vp, (struct vattr *)0, &xid);
1128 nfsm_reqdone;
1129 return (error);
1130 }
1131
1132 /*
1133 * nfs lookup call, one step at a time...
1134 * First look in cache
1135 * If not found, unlock the directory nfsnode and do the rpc
1136 */
1137 static int
1138 nfs_lookup(ap)
1139 struct vop_lookup_args /* {
1140 struct vnodeop_desc *a_desc;
1141 struct vnode *a_dvp;
1142 struct vnode **a_vpp;
1143 struct componentname *a_cnp;
1144 } */ *ap;
1145 {
1146 register struct componentname *cnp = ap->a_cnp;
1147 register struct vnode *dvp = ap->a_dvp;
1148 register struct vnode **vpp = ap->a_vpp;
1149 register int flags = cnp->cn_flags;
1150 register struct vnode *newvp;
1151 register u_long *tl;
1152 register caddr_t cp;
1153 register long t1, t2;
1154 struct nfsmount *nmp;
1155 caddr_t bpos, dpos, cp2;
1156 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1157 long len;
1158 nfsfh_t *fhp;
1159 struct nfsnode *np;
1160 int lockparent, wantparent, error = 0, attrflag, fhsize;
1161 int v3 = NFS_ISV3(dvp);
1162 struct proc *p = cnp->cn_proc;
1163 int worldbuildworkaround = 1;
1164 u_int64_t xid;
1165
1166 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
1167 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1168 return (EROFS);
1169 *vpp = NULLVP;
1170 if (dvp->v_type != VDIR)
1171 return (ENOTDIR);
1172 lockparent = flags & LOCKPARENT;
1173 wantparent = flags & (LOCKPARENT|WANTPARENT);
1174 nmp = VFSTONFS(dvp->v_mount);
1175 np = VTONFS(dvp);
1176
1177 if (worldbuildworkaround) {
1178 /*
1179 * Temporary workaround for world builds to not have dvp go
1180 * VBAD on during server calls in this routine. When
1181 * the real ref counting problem is found take this out.
1182 * Note if this was later and before the nfsm_request
1183 * set up, the workaround did not work (NOTE other difference
1184 * was I only put one VREF in that time. Thus it needs
1185 * to be above the cache_lookup branch or with 2 VREFS. Not
1186 * sure which. Can't play with world builds right now to see
1187 * which. VOP_ACCESS could also make it go to server. - EKN
1188 */
1189 VREF(dvp); /* hang on to this dvp - EKN */
1190 VREF(dvp); /* hang on tight - EKN */
1191 }
1192
1193 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
1194 struct vattr vattr;
1195 int vpid;
1196
1197 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p))) {
1198 *vpp = NULLVP;
1199 goto error_return;
1200 }
1201
1202 /* got to check to make sure the vnode didn't go away if access went to server */
1203 if ((*vpp)->v_type == VBAD) {
1204 error = EINVAL;
1205 goto error_return;
1206 }
1207
1208 newvp = *vpp;
1209 vpid = newvp->v_id;
1210 /*
1211 * See the comment starting `Step through' in ufs/ufs_lookup.c
1212 * for an explanation of the locking protocol
1213 */
1214 if (dvp == newvp) {
1215 VREF(newvp);
1216 error = 0;
1217 } else if (flags & ISDOTDOT) {
1218 VOP_UNLOCK(dvp, 0, p);
1219 error = vget(newvp, LK_EXCLUSIVE, p);
1220 if (!error && lockparent && (flags & ISLASTCN))
1221 error = vn_lock(dvp, LK_EXCLUSIVE, p);
1222 } else {
1223 error = vget(newvp, LK_EXCLUSIVE, p);
1224 if (!lockparent || error || !(flags & ISLASTCN))
1225 VOP_UNLOCK(dvp, 0, p);
1226 }
1227 if (!error) {
1228 if (vpid == newvp->v_id) {
1229 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p)
1230 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
1231 nfsstats.lookupcache_hits++;
1232 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1233 cnp->cn_flags |= SAVENAME;
1234 error = 0; /* ignore any from VOP_GETATTR */
1235 goto error_return;
1236 }
1237 cache_purge(newvp);
1238 }
1239 vput(newvp);
1240 if (lockparent && dvp != newvp && (flags & ISLASTCN))
1241 VOP_UNLOCK(dvp, 0, p);
1242 }
1243 error = vn_lock(dvp, LK_EXCLUSIVE, p);
1244 *vpp = NULLVP;
1245 if (error)
1246 goto error_return;
1247 }
1248
1249 /*
1250 * Got to check to make sure the vnode didn't go away if VOP_GETATTR went to server
1251 * or callers prior to this blocked and had it go VBAD.
1252 */
1253 if (dvp->v_type == VBAD) {
1254 error = EINVAL;
1255 goto error_return;
1256 }
1257
1258 error = 0;
1259 newvp = NULLVP;
1260 nfsstats.lookupcache_misses++;
1261 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1262 len = cnp->cn_namelen;
1263 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
1264 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
1265 nfsm_fhtom(dvp, v3);
1266 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1267 /* nfsm_request for NFSv2 causes you to goto to nfsmout upon errors */
1268 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred, &xid);
1269
1270 if (error) {
1271 nfsm_postop_attr(dvp, attrflag, &xid);
1272 m_freem(mrep);
1273 goto nfsmout;
1274 }
1275 nfsm_getfh(fhp, fhsize, v3);
1276
1277 /*
1278 * Handle RENAME case...
1279 */
1280 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
1281 if (NFS_CMPFH(np, fhp, fhsize)) {
1282 m_freem(mrep);
1283 error = EISDIR;
1284 goto error_return;
1285 }
1286 if ((error = nfs_nget(dvp->v_mount, fhp, fhsize, &np))) {
1287 m_freem(mrep);
1288 goto error_return;
1289 }
1290 newvp = NFSTOV(np);
1291 if (v3) {
1292 u_int64_t dxid = xid;
1293
1294 nfsm_postop_attr(newvp, attrflag, &xid);
1295 nfsm_postop_attr(dvp, attrflag, &dxid);
1296 } else
1297 nfsm_loadattr(newvp, (struct vattr *)0, &xid);
1298 *vpp = newvp;
1299 m_freem(mrep);
1300 cnp->cn_flags |= SAVENAME;
1301 if (!lockparent)
1302 VOP_UNLOCK(dvp, 0, p);
1303 error = 0;
1304 goto error_return;
1305 }
1306
1307 if (flags & ISDOTDOT) {
1308 VOP_UNLOCK(dvp, 0, p);
1309 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1310 if (error) {
1311 vn_lock(dvp, LK_EXCLUSIVE + LK_RETRY, p);
1312 goto error_return;
1313 }
1314 newvp = NFSTOV(np);
1315 if (lockparent && (flags & ISLASTCN) &&
1316 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
1317 vput(newvp);
1318 goto error_return;
1319 }
1320 } else if (NFS_CMPFH(np, fhp, fhsize)) {
1321 VREF(dvp);
1322 newvp = dvp;
1323 } else {
1324 if ((error = nfs_nget(dvp->v_mount, fhp, fhsize, &np))) {
1325 m_freem(mrep);
1326 goto error_return;
1327 }
1328 if (!lockparent || !(flags & ISLASTCN))
1329 VOP_UNLOCK(dvp, 0, p);
1330 newvp = NFSTOV(np);
1331 }
1332 if (v3) {
1333 u_int64_t dxid = xid;
1334
1335 nfsm_postop_attr(newvp, attrflag, &xid);
1336 nfsm_postop_attr(dvp, attrflag, &dxid);
1337 } else
1338 nfsm_loadattr(newvp, (struct vattr *)0, &xid);
1339 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1340 cnp->cn_flags |= SAVENAME;
1341 if ((cnp->cn_flags & MAKEENTRY) &&
1342 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
1343 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
1344 cache_enter(dvp, newvp, cnp);
1345 }
1346 *vpp = newvp;
1347 nfsm_reqdone;
1348 if (error) {
1349 if (newvp != NULLVP) {
1350 vrele(newvp);
1351 *vpp = NULLVP;
1352 }
1353 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
1354 (flags & ISLASTCN) && error == ENOENT) {
1355 if (!lockparent)
1356 VOP_UNLOCK(dvp, 0, p);
1357 if (dvp->v_mount->mnt_flag & MNT_RDONLY)
1358 error = EROFS;
1359 else
1360 error = EJUSTRETURN;
1361 }
1362 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1363 cnp->cn_flags |= SAVENAME;
1364 }
1365 error_return:
1366 /*
1367 * These "vreles" set dvp refcounts back to where they were
1368 * before we took extra 2 VREFS to avoid VBAD vnode on dvp
1369 * during server calls for world builds. Remove when real
1370 * fix is found. - EKN
1371 */
1372 if (worldbuildworkaround) {
1373 vrele(dvp); /* end of hanging on tight to dvp - EKN */
1374 vrele(dvp); /* end of hanging on tight to dvp - EKN */
1375 }
1376
1377 return (error);
1378 }
1379
1380 /*
1381 * nfs read call.
1382 * Just call nfs_bioread() to do the work.
1383 */
1384 static int
1385 nfs_read(ap)
1386 struct vop_read_args /* {
1387 struct vnode *a_vp;
1388 struct uio *a_uio;
1389 int a_ioflag;
1390 struct ucred *a_cred;
1391 } */ *ap;
1392 {
1393 register struct vnode *vp = ap->a_vp;
1394
1395 if (vp->v_type != VREG)
1396 return (EPERM);
1397 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
1398 }
1399
1400
1401 /*
1402 * nfs readlink call
1403 */
1404 static int
1405 nfs_readlink(ap)
1406 struct vop_readlink_args /* {
1407 struct vnode *a_vp;
1408 struct uio *a_uio;
1409 struct ucred *a_cred;
1410 } */ *ap;
1411 {
1412 register struct vnode *vp = ap->a_vp;
1413
1414 if (vp->v_type != VLNK)
1415 return (EPERM);
1416 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0));
1417 }
1418
1419 /*
1420 * Do a readlink rpc.
1421 * Called by nfs_doio() from below the buffer cache.
1422 */
1423 int
1424 nfs_readlinkrpc(vp, uiop, cred)
1425 register struct vnode *vp;
1426 struct uio *uiop;
1427 struct ucred *cred;
1428 {
1429 register u_long *tl;
1430 register caddr_t cp;
1431 register long t1, t2;
1432 caddr_t bpos, dpos, cp2;
1433 int error = 0, len, attrflag;
1434 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1435 int v3 = NFS_ISV3(vp);
1436 u_int64_t xid;
1437
1438 nfsstats.rpccnt[NFSPROC_READLINK]++;
1439 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
1440 nfsm_fhtom(vp, v3);
1441 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred, &xid);
1442 if (v3)
1443 nfsm_postop_attr(vp, attrflag, &xid);
1444 if (!error) {
1445 nfsm_strsiz(len, NFS_MAXPATHLEN);
1446 if (len == NFS_MAXPATHLEN) {
1447 struct nfsnode *np = VTONFS(vp);
1448 #if DIAGNOSTIC
1449 if (!np)
1450 panic("nfs_readlinkrpc: null np");
1451 #endif
1452 if (np->n_size && np->n_size < NFS_MAXPATHLEN)
1453 len = np->n_size;
1454 }
1455 nfsm_mtouio(uiop, len);
1456 }
1457 nfsm_reqdone;
1458 return (error);
1459 }
1460
1461 /*
1462 * nfs read rpc call
1463 * Ditto above
1464 */
1465 int
1466 nfs_readrpc(vp, uiop, cred)
1467 register struct vnode *vp;
1468 struct uio *uiop;
1469 struct ucred *cred;
1470 {
1471 register u_long *tl;
1472 register caddr_t cp;
1473 register long t1, t2;
1474 caddr_t bpos, dpos, cp2;
1475 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1476 struct nfsmount *nmp;
1477 int error = 0, len, retlen, tsiz, eof, attrflag;
1478 int v3 = NFS_ISV3(vp);
1479 u_int64_t xid;
1480
1481 #ifndef nolint
1482 eof = 0;
1483 #endif
1484 nmp = VFSTONFS(vp->v_mount);
1485 tsiz = uiop->uio_resid;
1486 if (((u_int64_t)uiop->uio_offset + (unsigned int)tsiz > 0xffffffff) &&
1487 !v3)
1488 return (EFBIG);
1489 while (tsiz > 0) {
1490 nfsstats.rpccnt[NFSPROC_READ]++;
1491 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
1492 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
1493 nfsm_fhtom(vp, v3);
1494 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3);
1495 if (v3) {
1496 txdr_hyper(&uiop->uio_offset, tl);
1497 *(tl + 2) = txdr_unsigned(len);
1498 } else {
1499 *tl++ = txdr_unsigned(uiop->uio_offset);
1500 *tl++ = txdr_unsigned(len);
1501 *tl = 0;
1502 }
1503 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred, &xid);
1504 if (v3) {
1505 nfsm_postop_attr(vp, attrflag, &xid);
1506 if (error) {
1507 m_freem(mrep);
1508 goto nfsmout;
1509 }
1510 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
1511 eof = fxdr_unsigned(int, *(tl + 1));
1512 } else
1513 nfsm_loadattr(vp, (struct vattr *)0, &xid);
1514 nfsm_strsiz(retlen, nmp->nm_rsize);
1515 nfsm_mtouio(uiop, retlen);
1516 m_freem(mrep);
1517 tsiz -= retlen;
1518 if (v3) {
1519 if (eof || retlen == 0)
1520 tsiz = 0;
1521 } else if (retlen < len)
1522 tsiz = 0;
1523 }
1524 nfsmout:
1525 return (error);
1526 }
1527
1528 /*
1529 * nfs write call
1530 */
1531 int
1532 nfs_writerpc(vp, uiop, cred, iomode, must_commit)
1533 register struct vnode *vp;
1534 register struct uio *uiop;
1535 struct ucred *cred;
1536 int *iomode, *must_commit;
1537 {
1538 register u_long *tl;
1539 register caddr_t cp;
1540 register int t1, t2, backup;
1541 caddr_t bpos, dpos, cp2;
1542 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1543 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1544 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
1545 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
1546 u_int64_t xid;
1547
1548 #if DIAGNOSTIC
1549 if (uiop->uio_iovcnt != 1)
1550 panic("nfs_writerpc: iovcnt > 1");
1551 #endif
1552 *must_commit = 0;
1553 tsiz = uiop->uio_resid;
1554 if (((u_int64_t)uiop->uio_offset + (unsigned int)tsiz > 0xffffffff) && !v3)
1555 return (EFBIG);
1556 while (tsiz > 0) {
1557 nfsstats.rpccnt[NFSPROC_WRITE]++;
1558 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1559 nfsm_reqhead(vp, NFSPROC_WRITE,
1560 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1561 nfsm_fhtom(vp, v3);
1562 if (v3) {
1563 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
1564 txdr_hyper(&uiop->uio_offset, tl);
1565 tl += 2;
1566 *tl++ = txdr_unsigned(len);
1567 *tl++ = txdr_unsigned(*iomode);
1568 } else {
1569 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
1570 *++tl = txdr_unsigned(uiop->uio_offset);
1571 tl += 2;
1572 }
1573 *tl = txdr_unsigned(len);
1574 nfsm_uiotom(uiop, len);
1575 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred, &xid);
1576 if (v3) {
1577 wccflag = NFSV3_WCCCHK;
1578 nfsm_wcc_data(vp, wccflag, &xid);
1579 if (!error) {
1580 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED +
1581 NFSX_V3WRITEVERF);
1582 rlen = fxdr_unsigned(int, *tl++);
1583 if (rlen <= 0) {
1584 error = NFSERR_IO;
1585 break;
1586 } else if (rlen < len) {
1587 backup = len - rlen;
1588 uiop->uio_iov->iov_base -= backup;
1589 uiop->uio_iov->iov_len += backup;
1590 uiop->uio_offset -= backup;
1591 uiop->uio_resid += backup;
1592 len = rlen;
1593 }
1594 commit = fxdr_unsigned(int, *tl++);
1595
1596 /*
1597 * Return the lowest committment level
1598 * obtained by any of the RPCs.
1599 */
1600 if (committed == NFSV3WRITE_FILESYNC)
1601 committed = commit;
1602 else if (committed == NFSV3WRITE_DATASYNC &&
1603 commit == NFSV3WRITE_UNSTABLE)
1604 committed = commit;
1605 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) {
1606 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1607 NFSX_V3WRITEVERF);
1608 nmp->nm_flag |= NFSMNT_HASWRITEVERF;
1609 } else if (bcmp((caddr_t)tl,
1610 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
1611 *must_commit = 1;
1612 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1613 NFSX_V3WRITEVERF);
1614 }
1615 }
1616 } else
1617 nfsm_loadattr(vp, (struct vattr *)0, &xid);
1618
1619 if (wccflag && vp->v_type != VBAD) /* EINVAL set on VBAD node */
1620 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
1621 m_freem(mrep);
1622 /*
1623 * we seem to have a case where we end up looping on shutdown
1624 * and taking down nfs servers. For V3, error cases, there is
1625 * no way to terminate loop, if the len was 0, meaning,
1626 * nmp->nm_wsize was trashed. FreeBSD has this fix in it.
1627 * Let's try it.
1628 */
1629 if (error)
1630 break;
1631 tsiz -= len;
1632 }
1633 nfsmout:
1634 /* EKN
1635 * does it make sense to even say it was committed if we had an error?
1636 * okay well just don't on bad vnodes then. EINVAL will be
1637 * returned on bad vnodes
1638 */
1639 if (vp->v_type != VBAD && (vp->v_mount->mnt_flag & MNT_ASYNC))
1640 committed = NFSV3WRITE_FILESYNC;
1641 *iomode = committed;
1642 if (error)
1643 uiop->uio_resid = tsiz;
1644 return (error);
1645 }
1646
1647 /*
1648 * nfs mknod rpc
1649 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1650 * mode set to specify the file type and the size field for rdev.
1651 */
1652 static int
1653 nfs_mknodrpc(dvp, vpp, cnp, vap)
1654 register struct vnode *dvp;
1655 register struct vnode **vpp;
1656 register struct componentname *cnp;
1657 register struct vattr *vap;
1658 {
1659 register struct nfsv2_sattr *sp;
1660 register struct nfsv3_sattr *sp3;
1661 register u_long *tl;
1662 register caddr_t cp;
1663 register long t1, t2;
1664 struct vnode *newvp = (struct vnode *)0;
1665 struct nfsnode *np = (struct nfsnode *)0;
1666 struct vattr vattr;
1667 char *cp2;
1668 caddr_t bpos, dpos;
1669 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1670 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1671 u_long rdev;
1672 u_int64_t xid;
1673 int v3 = NFS_ISV3(dvp);
1674
1675 if (vap->va_type == VCHR || vap->va_type == VBLK)
1676 rdev = txdr_unsigned(vap->va_rdev);
1677 else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1678 rdev = 0xffffffff;
1679 else {
1680 VOP_ABORTOP(dvp, cnp);
1681 vput(dvp);
1682 return (EOPNOTSUPP);
1683 }
1684 if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc))) {
1685 VOP_ABORTOP(dvp, cnp);
1686 vput(dvp);
1687 return (error);
1688 }
1689 nfsstats.rpccnt[NFSPROC_MKNOD]++;
1690 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
1691 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1692 nfsm_fhtom(dvp, v3);
1693 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1694 if (v3) {
1695 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR);
1696 *tl++ = vtonfsv3_type(vap->va_type);
1697 sp3 = (struct nfsv3_sattr *)tl;
1698 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1699 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1700 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1701 *tl++ = txdr_unsigned(major(vap->va_rdev));
1702 *tl = txdr_unsigned(minor(vap->va_rdev));
1703 }
1704 } else {
1705 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1706 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1707 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1708 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1709 sp->sa_size = rdev;
1710 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1711 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1712 }
1713 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred, &xid);
1714 if (!error) {
1715 nfsm_mtofh(dvp, newvp, v3, gotvp, &xid);
1716 if (!gotvp) {
1717 if (newvp) {
1718 vput(newvp);
1719 newvp = (struct vnode *)0;
1720 }
1721 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1722 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1723 if (!error)
1724 newvp = NFSTOV(np);
1725 }
1726 }
1727 if (v3)
1728 nfsm_wcc_data(dvp, wccflag, &xid);
1729 nfsm_reqdone;
1730 if (error) {
1731 if (newvp)
1732 vput(newvp);
1733 } else {
1734 if (cnp->cn_flags & MAKEENTRY)
1735 cache_enter(dvp, newvp, cnp);
1736 *vpp = newvp;
1737 }
1738 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1739 if (dvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */
1740 VTONFS(dvp)->n_flag |= NMODIFIED;
1741 if (!wccflag)
1742 VTONFS(dvp)->n_attrstamp = 0;
1743 }
1744 vput(dvp);
1745 return (error);
1746 }
1747
1748 /*
1749 * nfs mknod vop
1750 * just call nfs_mknodrpc() to do the work.
1751 */
1752 /* ARGSUSED */
1753 static int
1754 nfs_mknod(ap)
1755 struct vop_mknod_args /* {
1756 struct vnode *a_dvp;
1757 struct vnode **a_vpp;
1758 struct componentname *a_cnp;
1759 struct vattr *a_vap;
1760 } */ *ap;
1761 {
1762 struct vnode *newvp;
1763 int error;
1764
1765 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap);
1766 if (!error && newvp)
1767 vput(newvp);
1768 *ap->a_vpp = 0;
1769 return (error);
1770 }
1771
1772 static u_long create_verf;
1773 /*
1774 * nfs file create call
1775 */
1776 static int
1777 nfs_create(ap)
1778 struct vop_create_args /* {
1779 struct vnode *a_dvp;
1780 struct vnode **a_vpp;
1781 struct componentname *a_cnp;
1782 struct vattr *a_vap;
1783 } */ *ap;
1784 {
1785 register struct vnode *dvp = ap->a_dvp;
1786 register struct vattr *vap = ap->a_vap;
1787 register struct componentname *cnp = ap->a_cnp;
1788 register struct nfsv2_sattr *sp;
1789 register struct nfsv3_sattr *sp3;
1790 register u_long *tl;
1791 register caddr_t cp;
1792 register long t1, t2;
1793 struct nfsnode *np = (struct nfsnode *)0;
1794 struct vnode *newvp = (struct vnode *)0;
1795 caddr_t bpos, dpos, cp2;
1796 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1797 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1798 struct vattr vattr;
1799 int v3 = NFS_ISV3(dvp);
1800 u_int64_t xid;
1801
1802 /*
1803 * Oops, not for me..
1804 */
1805 if (vap->va_type == VSOCK)
1806 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1807
1808 if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc))) {
1809 VOP_ABORTOP(dvp, cnp);
1810 vput(dvp);
1811 return (error);
1812 }
1813 if (vap->va_vaflags & VA_EXCLUSIVE)
1814 fmode |= O_EXCL;
1815 again:
1816 nfsstats.rpccnt[NFSPROC_CREATE]++;
1817 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
1818 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1819 nfsm_fhtom(dvp, v3);
1820 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1821 if (v3) {
1822 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1823 if (fmode & O_EXCL) {
1824 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1825 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF);
1826 if (!TAILQ_EMPTY(&in_ifaddrhead))
1827 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr;
1828 else
1829 *tl++ = create_verf;
1830 *tl = ++create_verf;
1831 } else {
1832 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1833 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR);
1834 sp3 = (struct nfsv3_sattr *)tl;
1835 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1836 }
1837 } else {
1838 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1839 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1840 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1841 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1842 sp->sa_size = 0;
1843 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1844 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1845 }
1846 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred, &xid);
1847 if (!error) {
1848 nfsm_mtofh(dvp, newvp, v3, gotvp, &xid);
1849 if (!gotvp) {
1850 if (newvp) {
1851 vput(newvp);
1852 newvp = (struct vnode *)0;
1853 }
1854 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1855 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1856 if (!error)
1857 newvp = NFSTOV(np);
1858 }
1859 }
1860 if (v3)
1861 nfsm_wcc_data(dvp, wccflag, &xid);
1862 nfsm_reqdone;
1863 if (error) {
1864 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1865 fmode &= ~O_EXCL;
1866 goto again;
1867 }
1868 if (newvp)
1869 vput(newvp);
1870 } else if (v3 && (fmode & O_EXCL))
1871 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
1872 if (!error) {
1873 if (cnp->cn_flags & MAKEENTRY)
1874 cache_enter(dvp, newvp, cnp);
1875 *ap->a_vpp = newvp;
1876 }
1877 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1878 if (dvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */
1879 VTONFS(dvp)->n_flag |= NMODIFIED;
1880 if (!wccflag)
1881 VTONFS(dvp)->n_attrstamp = 0;
1882 }
1883 vput(dvp);
1884 return (error);
1885 }
1886
1887 /*
1888 * nfs file remove call
1889 * To try and make nfs semantics closer to ufs semantics, a file that has
1890 * other processes using the vnode is renamed instead of removed and then
1891 * removed later on the last close.
1892 * - If v_usecount > 1
1893 * If a rename is not already in the works
1894 * call nfs_sillyrename() to set it up
1895 * else
1896 * do the remove rpc
1897 */
1898 static int
1899 nfs_remove(ap)
1900 struct vop_remove_args /* {
1901 struct vnodeop_desc *a_desc;
1902 struct vnode * a_dvp;
1903 struct vnode * a_vp;
1904 struct componentname * a_cnp;
1905 } */ *ap;
1906 {
1907 register struct vnode *vp = ap->a_vp;
1908 register struct vnode *dvp = ap->a_dvp;
1909 register struct componentname *cnp = ap->a_cnp;
1910 register struct nfsnode *np = VTONFS(vp);
1911 int error = 0, gofree = 0;
1912 struct vattr vattr;
1913
1914 #if DIAGNOSTIC
1915 if ((cnp->cn_flags & HASBUF) == 0)
1916 panic("nfs_remove: no name");
1917 if (vp->v_usecount < 1)
1918 panic("nfs_remove: bad v_usecount");
1919 #endif
1920
1921 if (UBCISVALID(vp)) {
1922 /* regular files */
1923 if (UBCINFOEXISTS(vp))
1924 gofree = (ubc_isinuse(vp, 1)) ? 0 : 1;
1925 else {
1926 /* dead or dying vnode.With vnode locking panic instead of error */
1927 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1928 vput(dvp);
1929 vput(vp);
1930 return (EIO);
1931 }
1932 } else {
1933 /* UBC not in play */
1934 if (vp->v_usecount == 1)
1935 gofree = 1;
1936 }
1937 if (gofree || (np->n_sillyrename &&
1938 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 &&
1939 vattr.va_nlink > 1)) {
1940 /*
1941 * Purge the name cache so that the chance of a lookup for
1942 * the name succeeding while the remove is in progress is
1943 * minimized. Without node locking it can still happen, such
1944 * that an I/O op returns ESTALE, but since you get this if
1945 * another host removes the file..
1946 */
1947 cache_purge(vp);
1948 /*
1949 * throw away biocache buffers, mainly to avoid
1950 * unnecessary delayed writes later.
1951 */
1952 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1);
1953 np->n_size = 0;
1954 ubc_setsize(vp, (off_t)0); /* XXX check error */
1955 /* Do the rpc */
1956 if (error != EINTR)
1957 error = nfs_removerpc(dvp, cnp->cn_nameptr,
1958 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc);
1959 /*
1960 * Kludge City: If the first reply to the remove rpc is lost..
1961 * the reply to the retransmitted request will be ENOENT
1962 * since the file was in fact removed
1963 * Therefore, we cheat and return success.
1964 */
1965 if (error == ENOENT)
1966 error = 0;
1967 } else if (!np->n_sillyrename) {
1968 error = nfs_sillyrename(dvp, vp, cnp);
1969 }
1970
1971 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1972 np->n_attrstamp = 0;
1973 vput(dvp);
1974
1975 VOP_UNLOCK(vp, 0, cnp->cn_proc);
1976 ubc_uncache(vp);
1977 vrele(vp);
1978
1979 return (error);
1980 }
1981
1982 /*
1983 * nfs file remove rpc called from nfs_inactive
1984 */
1985 int
1986 nfs_removeit(sp)
1987 register struct sillyrename *sp;
1988 {
1989
1990 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1991 (struct proc *)0));
1992 }
1993
1994 /*
1995 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1996 */
1997 static int
1998 nfs_removerpc(dvp, name, namelen, cred, proc)
1999 register struct vnode *dvp;
2000 char *name;
2001 int namelen;
2002 struct ucred *cred;
2003 struct proc *proc;
2004 {
2005 register u_long *tl;
2006 register caddr_t cp;
2007 register long t1, t2;
2008 caddr_t bpos, dpos, cp2;
2009 int error = 0, wccflag = NFSV3_WCCRATTR;
2010 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2011 int v3 = NFS_ISV3(dvp);
2012 u_int64_t xid;
2013
2014 nfsstats.rpccnt[NFSPROC_REMOVE]++;
2015 nfsm_reqhead(dvp, NFSPROC_REMOVE,
2016 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
2017 nfsm_fhtom(dvp, v3);
2018 nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
2019 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred, &xid);
2020 if (v3)
2021 nfsm_wcc_data(dvp, wccflag, &xid);
2022 nfsm_reqdone;
2023 if (dvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */
2024 VTONFS(dvp)->n_flag |= NMODIFIED;
2025 if (!wccflag)
2026 VTONFS(dvp)->n_attrstamp = 0;
2027 }
2028 return (error);
2029 }
2030
2031 /*
2032 * nfs file rename call
2033 */
2034 static int
2035 nfs_rename(ap)
2036 struct vop_rename_args /* {
2037 struct vnode *a_fdvp;
2038 struct vnode *a_fvp;
2039 struct componentname *a_fcnp;
2040 struct vnode *a_tdvp;
2041 struct vnode *a_tvp;
2042 struct componentname *a_tcnp;
2043 } */ *ap;
2044 {
2045 register struct vnode *fvp = ap->a_fvp;
2046 register struct vnode *tvp = ap->a_tvp;
2047 register struct vnode *fdvp = ap->a_fdvp;
2048 register struct vnode *tdvp = ap->a_tdvp;
2049 register struct componentname *tcnp = ap->a_tcnp;
2050 register struct componentname *fcnp = ap->a_fcnp;
2051 int error, purged=0, inuse=0;
2052
2053 #if DIAGNOSTIC
2054 if ((tcnp->cn_flags & HASBUF) == 0 ||
2055 (fcnp->cn_flags & HASBUF) == 0)
2056 panic("nfs_rename: no name");
2057 #endif
2058 /* Check for cross-device rename */
2059 if ((fvp->v_mount != tdvp->v_mount) ||
2060 (tvp && (fvp->v_mount != tvp->v_mount))) {
2061 error = EXDEV;
2062 if (tvp)
2063 VOP_UNLOCK(tvp, 0, tcnp->cn_proc);
2064 goto out;
2065 }
2066
2067 /*
2068 * If the tvp exists and is in use, sillyrename it before doing the
2069 * rename of the new file over it.
2070 * XXX Can't sillyrename a directory.
2071 * Don't sillyrename if source and target are same vnode (hard
2072 * links or case-variants)
2073 */
2074 if (tvp && tvp != fvp) {
2075 if (UBCISVALID(tvp)) {
2076 /* regular files */
2077 if (UBCINFOEXISTS(tvp))
2078 inuse = (ubc_isinuse(tvp, 1)) ? 1 : 0;
2079 else {
2080 /* dead or dying vnode.With vnode locking panic instead of error */
2081 error = EIO;
2082 VOP_UNLOCK(tvp, 0, tcnp->cn_proc);
2083 goto out;
2084 }
2085 } else {
2086 /* UBC not in play */
2087 if (tvp->v_usecount > 1)
2088 inuse = 1;
2089 }
2090 }
2091 if (inuse && !VTONFS(tvp)->n_sillyrename && tvp->v_type != VDIR) {
2092 if (error = nfs_sillyrename(tdvp, tvp, tcnp)) {
2093 /* sillyrename failed. Instead of pressing on, return error */
2094 goto out; /* should not be ENOENT. */
2095 } else {
2096 /* sillyrename succeeded.*/
2097 VOP_UNLOCK(tvp, 0, tcnp->cn_proc);
2098 ubc_uncache(tvp); /* get the nfs turd file to disappear */
2099 vrele(tvp);
2100 tvp = NULL;
2101 }
2102 }
2103
2104 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
2105 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
2106 tcnp->cn_proc);
2107
2108 if (fvp->v_type == VDIR) {
2109 if (tvp != NULL && tvp->v_type == VDIR) {
2110 cache_purge(tdvp);
2111 if (tvp == tdvp)
2112 purged = 1;
2113 }
2114 cache_purge(fdvp);
2115 }
2116
2117 cache_purge(fvp);
2118 if (tvp) {
2119 if (!purged)
2120 cache_purge(tvp);
2121 VOP_UNLOCK(tvp, 0, tcnp->cn_proc);
2122 ubc_uncache(tvp); /* get the nfs turd file to disappear */
2123 }
2124
2125 out:
2126 if (tdvp == tvp)
2127 vrele(tdvp);
2128 else
2129 vput(tdvp);
2130 if (tvp)
2131 vrele(tvp); /* already unlocked */
2132 vrele(fdvp);
2133 vrele(fvp);
2134 /*
2135 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
2136 */
2137 if (error == ENOENT)
2138 error = 0;
2139 return (error);
2140 }
2141
2142 /*
2143 * nfs file rename rpc called from nfs_remove() above
2144 */
2145 static int
2146 nfs_renameit(sdvp, scnp, sp)
2147 struct vnode *sdvp;
2148 struct componentname *scnp;
2149 register struct sillyrename *sp;
2150 {
2151 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
2152 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc));
2153 }
2154
2155 /*
2156 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
2157 */
2158 static int
2159 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc)
2160 register struct vnode *fdvp;
2161 char *fnameptr;
2162 int fnamelen;
2163 register struct vnode *tdvp;
2164 char *tnameptr;
2165 int tnamelen;
2166 struct ucred *cred;
2167 struct proc *proc;
2168 {
2169 register u_long *tl;
2170 register caddr_t cp;
2171 register long t1, t2;
2172 caddr_t bpos, dpos, cp2;
2173 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
2174 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2175 int v3 = NFS_ISV3(fdvp);
2176 u_int64_t xid;
2177
2178 nfsstats.rpccnt[NFSPROC_RENAME]++;
2179 nfsm_reqhead(fdvp, NFSPROC_RENAME,
2180 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
2181 nfsm_rndup(tnamelen));
2182 nfsm_fhtom(fdvp, v3);
2183 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
2184 nfsm_fhtom(tdvp, v3);
2185 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
2186 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred, &xid);
2187 if (v3) {
2188 u_int64_t txid = xid;
2189
2190 nfsm_wcc_data(fdvp, fwccflag, &xid);
2191 nfsm_wcc_data(tdvp, twccflag, &txid);
2192 }
2193 nfsm_reqdone;
2194 if (fdvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */
2195 VTONFS(fdvp)->n_flag |= NMODIFIED;
2196 if (!fwccflag)
2197 VTONFS(fdvp)->n_attrstamp = 0;
2198 }
2199 if (tdvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */
2200 VTONFS(tdvp)->n_flag |= NMODIFIED;
2201 if (!twccflag)
2202 VTONFS(tdvp)->n_attrstamp = 0;
2203 }
2204 return (error);
2205 }
2206
2207 /*
2208 * nfs hard link create call
2209 */
2210 static int
2211 nfs_link(ap)
2212 struct vop_link_args /* {
2213 struct vnode *a_vp;
2214 struct vnode *a_tdvp;
2215 struct componentname *a_cnp;
2216 } */ *ap;
2217 {
2218 register struct vnode *vp = ap->a_vp;
2219 register struct vnode *tdvp = ap->a_tdvp;
2220 register struct componentname *cnp = ap->a_cnp;
2221 register u_long *tl;
2222 register caddr_t cp;
2223 register long t1, t2;
2224 caddr_t bpos, dpos, cp2;
2225 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
2226 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2227 int v3 = NFS_ISV3(vp);
2228 u_int64_t xid;
2229
2230 if (vp->v_mount != tdvp->v_mount) {
2231 VOP_ABORTOP(vp, cnp);
2232 if (tdvp == vp)
2233 vrele(tdvp);
2234 else
2235 vput(tdvp);
2236 return (EXDEV);
2237 }
2238
2239 /*
2240 * Push all writes to the server, so that the attribute cache
2241 * doesn't get "out of sync" with the server.
2242 * XXX There should be a better way!
2243 */
2244 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
2245
2246 nfsstats.rpccnt[NFSPROC_LINK]++;
2247 nfsm_reqhead(vp, NFSPROC_LINK,
2248 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
2249 nfsm_fhtom(vp, v3);
2250 nfsm_fhtom(tdvp, v3);
2251 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
2252 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred, &xid);
2253 if (v3) {
2254 u_int64_t txid = xid;
2255
2256 nfsm_postop_attr(vp, attrflag, &xid);
2257 nfsm_wcc_data(tdvp, wccflag, &txid);
2258 }
2259 nfsm_reqdone;
2260 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
2261
2262 VTONFS(tdvp)->n_flag |= NMODIFIED;
2263 if (!attrflag && vp->v_type != VBAD) /* EINVAL set on VBAD vnode */
2264 VTONFS(vp)->n_attrstamp = 0;
2265 if (!wccflag && tdvp->v_type != VBAD) /* EINVAL set on VBAD vnode */
2266 VTONFS(tdvp)->n_attrstamp = 0;
2267 vput(tdvp);
2268 /*
2269 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2270 */
2271 if (error == EEXIST)
2272 error = 0;
2273 return (error);
2274 }
2275
2276 /*
2277 * nfs symbolic link create call
2278 */
2279 static int
2280 nfs_symlink(ap)
2281 struct vop_symlink_args /* {
2282 struct vnode *a_dvp;
2283 struct vnode **a_vpp;
2284 struct componentname *a_cnp;
2285 struct vattr *a_vap;
2286 char *a_target;
2287 } */ *ap;
2288 {
2289 register struct vnode *dvp = ap->a_dvp;
2290 register struct vattr *vap = ap->a_vap;
2291 register struct componentname *cnp = ap->a_cnp;
2292 register struct nfsv2_sattr *sp;
2293 register struct nfsv3_sattr *sp3;
2294 register u_long *tl;
2295 register caddr_t cp;
2296 register long t1, t2;
2297 caddr_t bpos, dpos, cp2;
2298 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
2299 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2300 struct vnode *newvp = (struct vnode *)0;
2301 int v3 = NFS_ISV3(dvp);
2302 u_int64_t xid;
2303
2304 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
2305 slen = strlen(ap->a_target);
2306 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
2307 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
2308 nfsm_fhtom(dvp, v3);
2309 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
2310 if (v3) {
2311 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR);
2312 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid,
2313 cnp->cn_cred->cr_gid);
2314 }
2315 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
2316 if (!v3) {
2317 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2318 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
2319 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
2320 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
2321 sp->sa_size = -1;
2322 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
2323 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
2324 }
2325 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred, &xid);
2326 if (v3) {
2327 u_int64_t dxid = xid;
2328
2329 if (!error)
2330 nfsm_mtofh(dvp, newvp, v3, gotvp, &xid);
2331 nfsm_wcc_data(dvp, wccflag, &dxid);
2332 }
2333 nfsm_reqdone;
2334 if (newvp)
2335 vput(newvp);
2336 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
2337 if (dvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */
2338 VTONFS(dvp)->n_flag |= NMODIFIED;
2339 if (!wccflag)
2340 VTONFS(dvp)->n_attrstamp = 0;
2341 }
2342 vput(dvp);
2343 /*
2344 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2345 */
2346 if (error == EEXIST)
2347 error = 0;
2348 return (error);
2349 }
2350
2351 /*
2352 * nfs make dir call
2353 */
2354 static int
2355 nfs_mkdir(ap)
2356 struct vop_mkdir_args /* {
2357 struct vnode *a_dvp;
2358 struct vnode **a_vpp;
2359 struct componentname *a_cnp;
2360 struct vattr *a_vap;
2361 } */ *ap;
2362 {
2363 register struct vnode *dvp = ap->a_dvp;
2364 register struct vattr *vap = ap->a_vap;
2365 register struct componentname *cnp = ap->a_cnp;
2366 register struct nfsv2_sattr *sp;
2367 register struct nfsv3_sattr *sp3;
2368 register u_long *tl;
2369 register caddr_t cp;
2370 register long t1, t2;
2371 register int len;
2372 struct nfsnode *np = (struct nfsnode *)0;
2373 struct vnode *newvp = (struct vnode *)0;
2374 caddr_t bpos, dpos, cp2;
2375 int error = 0, wccflag = NFSV3_WCCRATTR;
2376 int gotvp = 0;
2377 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2378 struct vattr vattr;
2379 int v3 = NFS_ISV3(dvp);
2380 u_int64_t xid, dxid;
2381
2382 if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc))) {
2383 VOP_ABORTOP(dvp, cnp);
2384 vput(dvp);
2385 return (error);
2386 }
2387 len = cnp->cn_namelen;
2388 nfsstats.rpccnt[NFSPROC_MKDIR]++;
2389 nfsm_reqhead(dvp, NFSPROC_MKDIR,
2390 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
2391 nfsm_fhtom(dvp, v3);
2392 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
2393 if (v3) {
2394 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR);
2395 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
2396 } else {
2397 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2398 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
2399 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
2400 sp->sa_gid = txdr_unsigned(vattr.va_gid);
2401 sp->sa_size = -1;
2402 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
2403 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
2404 }
2405 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred, &xid);
2406 dxid = xid;
2407 if (!error)
2408 nfsm_mtofh(dvp, newvp, v3, gotvp, &xid);
2409 if (v3)
2410 nfsm_wcc_data(dvp, wccflag, &dxid);
2411 nfsm_reqdone;
2412 if (dvp->v_type != VBAD) { /* EINVAL set on this case */
2413 VTONFS(dvp)->n_flag |= NMODIFIED;
2414 if (!wccflag)
2415 VTONFS(dvp)->n_attrstamp = 0;
2416 }
2417 /*
2418 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
2419 * if we can succeed in looking up the directory.
2420 */
2421 if (error == EEXIST || (!error && !gotvp)) {
2422 if (newvp) {
2423 vrele(newvp);
2424 newvp = (struct vnode *)0;
2425 }
2426 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
2427 cnp->cn_proc, &np);
2428 if (!error) {
2429 newvp = NFSTOV(np);
2430 if (newvp->v_type != VDIR)
2431 error = EEXIST;
2432 }
2433 }
2434 if (error) {
2435 if (newvp)
2436 vrele(newvp);
2437 } else
2438 *ap->a_vpp = newvp;
2439 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
2440 vput(dvp);
2441 return (error);
2442 }
2443
2444 /*
2445 * nfs remove directory call
2446 */
2447 static int
2448 nfs_rmdir(ap)
2449 struct vop_rmdir_args /* {
2450 struct vnode *a_dvp;
2451 struct vnode *a_vp;
2452 struct componentname *a_cnp;
2453 } */ *ap;
2454 {
2455 register struct vnode *vp = ap->a_vp;
2456 register struct vnode *dvp = ap->a_dvp;
2457 register struct componentname *cnp = ap->a_cnp;
2458 register u_long *tl;
2459 register caddr_t cp;
2460 register long t1, t2;
2461 caddr_t bpos, dpos, cp2;
2462 int error = 0, wccflag = NFSV3_WCCRATTR;
2463 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2464 int v3 = NFS_ISV3(dvp);
2465 u_int64_t xid;
2466
2467 nfsstats.rpccnt[NFSPROC_RMDIR]++;
2468 nfsm_reqhead(dvp, NFSPROC_RMDIR,
2469 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
2470 nfsm_fhtom(dvp, v3);
2471 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
2472 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred, &xid);
2473 if (v3)
2474 nfsm_wcc_data(dvp, wccflag, &xid);
2475 nfsm_reqdone;
2476 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
2477 if (dvp->v_type != VBAD) { /* EINVAL set on this case */
2478 VTONFS(dvp)->n_flag |= NMODIFIED;
2479 if (!wccflag)
2480 VTONFS(dvp)->n_attrstamp = 0;
2481 }
2482 cache_purge(dvp);
2483 cache_purge(vp);
2484 vput(vp);
2485 vput(dvp);
2486 /*
2487 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2488 */
2489 if (error == ENOENT)
2490 error = 0;
2491 return (error);
2492 }
2493
2494 /*
2495 * nfs readdir call
2496 */
2497 static int
2498 nfs_readdir(ap)
2499 struct vop_readdir_args /* {
2500 struct vnode *a_vp;
2501 struct uio *a_uio;
2502 struct ucred *a_cred;
2503 } */ *ap;
2504 {
2505 register struct vnode *vp = ap->a_vp;
2506 register struct nfsnode *np = VTONFS(vp);
2507 register struct uio *uio = ap->a_uio;
2508 int tresid, error;
2509 struct vattr vattr;
2510
2511 if (vp->v_type != VDIR)
2512 return (EPERM);
2513 /*
2514 * First, check for hit on the EOF offset cache
2515 */
2516 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
2517 (np->n_flag & NMODIFIED) == 0) {
2518 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
2519 if (NQNFS_CKCACHABLE(vp, ND_READ)) {
2520 nfsstats.direofcache_hits++;
2521 return (0);
2522 }
2523 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
2524 np->n_mtime == vattr.va_mtime.tv_sec) {
2525 nfsstats.direofcache_hits++;
2526 return (0);
2527 }
2528 }
2529
2530 /*
2531 * Call nfs_bioread() to do the real work.
2532 */
2533 tresid = uio->uio_resid;
2534 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0);
2535
2536 if (!error && uio->uio_resid == tresid)
2537 nfsstats.direofcache_misses++;
2538 return (error);
2539 }
2540
2541 /*
2542 * Readdir rpc call.
2543 * Called from below the buffer cache by nfs_doio().
2544 */
2545 int
2546 nfs_readdirrpc(vp, uiop, cred)
2547 struct vnode *vp;
2548 register struct uio *uiop;
2549 struct ucred *cred;
2550
2551 {
2552 register int len, left;
2553 register struct dirent *dp;
2554 register u_long *tl;
2555 register caddr_t cp;
2556 register long t1, t2;
2557 register nfsuint64 *cookiep;
2558 caddr_t bpos, dpos, cp2;
2559 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2560 nfsuint64 cookie;
2561 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2562 struct nfsnode *dnp = VTONFS(vp);
2563 u_quad_t fileno;
2564 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2565 int attrflag;
2566 int v3 = NFS_ISV3(vp);
2567 u_int64_t xid;
2568
2569 #ifndef nolint
2570 dp = (struct dirent *)0;
2571 #endif
2572 #if DIAGNOSTIC
2573 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) ||
2574 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2575 panic("nfs_readdirrpc: bad uio");
2576 #endif
2577
2578 /*
2579 * If there is no cookie, assume directory was stale.
2580 */
2581 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2582 if (cookiep)
2583 cookie = *cookiep;
2584 else
2585 return (NFSERR_BAD_COOKIE);
2586 /*
2587 * Loop around doing readdir rpc's of size nm_readdirsize
2588 * truncated to a multiple of DIRBLKSIZ.
2589 * The stopping criteria is EOF or buffer full.
2590 */
2591 while (more_dirs && bigenough) {
2592 nfsstats.rpccnt[NFSPROC_READDIR]++;
2593 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
2594 NFSX_READDIR(v3));
2595 nfsm_fhtom(vp, v3);
2596 if (v3) {
2597 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
2598 *tl++ = cookie.nfsuquad[0];
2599 *tl++ = cookie.nfsuquad[1];
2600 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2601 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2602 } else {
2603 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
2604 *tl++ = cookie.nfsuquad[0];
2605 }
2606 *tl = txdr_unsigned(nmp->nm_readdirsize);
2607 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred, &xid);
2608 if (v3) {
2609 nfsm_postop_attr(vp, attrflag, &xid);
2610 if (!error) {
2611 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2612 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2613 dnp->n_cookieverf.nfsuquad[1] = *tl;
2614 } else {
2615 m_freem(mrep);
2616 goto nfsmout;
2617 }
2618 }
2619 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2620 more_dirs = fxdr_unsigned(int, *tl);
2621
2622 /* loop thru the dir entries, doctoring them to 4bsd form */
2623 while (more_dirs && bigenough) {
2624 if (v3) {
2625 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2626 fxdr_hyper(tl, &fileno);
2627 len = fxdr_unsigned(int, *(tl + 2));
2628 } else {
2629 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2630 fileno = fxdr_unsigned(u_quad_t, *tl++);
2631 len = fxdr_unsigned(int, *tl);
2632 }
2633 if (len <= 0 || len > NFS_MAXNAMLEN) {
2634 error = EBADRPC;
2635 m_freem(mrep);
2636 goto nfsmout;
2637 }
2638 tlen = nfsm_rndup(len);
2639 if (tlen == len)
2640 tlen += 4; /* To ensure null termination */
2641 left = DIRBLKSIZ - blksiz;
2642 if ((tlen + DIRHDSIZ) > left) {
2643 dp->d_reclen += left;
2644 uiop->uio_iov->iov_base += left;
2645 uiop->uio_iov->iov_len -= left;
2646 uiop->uio_offset += left;
2647 uiop->uio_resid -= left;
2648 blksiz = 0;
2649 }
2650 if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2651 bigenough = 0;
2652 if (bigenough) {
2653 dp = (struct dirent *)uiop->uio_iov->iov_base;
2654 dp->d_fileno = (int)fileno;
2655 dp->d_namlen = len;
2656 dp->d_reclen = tlen + DIRHDSIZ;
2657 dp->d_type = DT_UNKNOWN;
2658 blksiz += dp->d_reclen;
2659 if (blksiz == DIRBLKSIZ)
2660 blksiz = 0;
2661 uiop->uio_offset += DIRHDSIZ;
2662 uiop->uio_resid -= DIRHDSIZ;
2663 uiop->uio_iov->iov_base += DIRHDSIZ;
2664 uiop->uio_iov->iov_len -= DIRHDSIZ;
2665 nfsm_mtouio(uiop, len);
2666 cp = uiop->uio_iov->iov_base;
2667 tlen -= len;
2668 *cp = '\0'; /* null terminate */
2669 uiop->uio_iov->iov_base += tlen;
2670 uiop->uio_iov->iov_len -= tlen;
2671 uiop->uio_offset += tlen;
2672 uiop->uio_resid -= tlen;
2673 } else
2674 nfsm_adv(nfsm_rndup(len));
2675 if (v3) {
2676 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2677 } else {
2678 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2679 }
2680 if (bigenough) {
2681 cookie.nfsuquad[0] = *tl++;
2682 if (v3)
2683 cookie.nfsuquad[1] = *tl++;
2684 } else if (v3)
2685 tl += 2;
2686 else
2687 tl++;
2688 more_dirs = fxdr_unsigned(int, *tl);
2689 }
2690 /*
2691 * If at end of rpc data, get the eof boolean
2692 */
2693 if (!more_dirs) {
2694 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2695 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2696 }
2697 m_freem(mrep);
2698 }
2699 /*
2700 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2701 * by increasing d_reclen for the last record.
2702 */
2703 if (blksiz > 0) {
2704 left = DIRBLKSIZ - blksiz;
2705 dp->d_reclen += left;
2706 uiop->uio_iov->iov_base += left;
2707 uiop->uio_iov->iov_len -= left;
2708 uiop->uio_offset += left;
2709 uiop->uio_resid -= left;
2710 }
2711
2712 /*
2713 * We are now either at the end of the directory or have filled the
2714 * block.
2715 */
2716 if (bigenough)
2717 dnp->n_direofoffset = uiop->uio_offset;
2718 else {
2719 if (uiop->uio_resid > 0)
2720 printf("EEK! readdirrpc resid > 0\n");
2721 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2722 *cookiep = cookie;
2723 }
2724 nfsmout:
2725 return (error);
2726 }
2727
2728 /*
2729 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2730 */
2731 int
2732 nfs_readdirplusrpc(vp, uiop, cred)
2733 struct vnode *vp;
2734 register struct uio *uiop;
2735 struct ucred *cred;
2736 {
2737 register int len, left;
2738 register struct dirent *dp;
2739 register u_long *tl;
2740 register caddr_t cp;
2741 register long t1, t2;
2742 register struct vnode *newvp;
2743 register nfsuint64 *cookiep;
2744 caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
2745 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
2746 struct nameidata nami, *ndp = &nami;
2747 struct componentname *cnp = &ndp->ni_cnd;
2748 nfsuint64 cookie;
2749 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2750 struct nfsnode *dnp = VTONFS(vp), *np;
2751 nfsfh_t *fhp;
2752 u_quad_t fileno;
2753 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2754 int attrflag, fhsize;
2755 u_int64_t xid, savexid;
2756
2757 #ifndef nolint
2758 dp = (struct dirent *)0;
2759 #endif
2760 #if DIAGNOSTIC
2761 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
2762 (uiop->uio_resid & (DIRBLKSIZ - 1)))
2763 panic("nfs_readdirplusrpc: bad uio");
2764 #endif
2765 ndp->ni_dvp = vp;
2766 newvp = NULLVP;
2767
2768 /*
2769 * If there is no cookie, assume directory was stale.
2770 */
2771 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2772 if (cookiep)
2773 cookie = *cookiep;
2774 else
2775 return (NFSERR_BAD_COOKIE);
2776 /*
2777 * Loop around doing readdir rpc's of size nm_readdirsize
2778 * truncated to a multiple of DIRBLKSIZ.
2779 * The stopping criteria is EOF or buffer full.
2780 */
2781 while (more_dirs && bigenough) {
2782 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2783 nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
2784 NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2785 nfsm_fhtom(vp, 1);
2786 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED);
2787 *tl++ = cookie.nfsuquad[0];
2788 *tl++ = cookie.nfsuquad[1];
2789 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2790 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2791 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
2792 *tl = txdr_unsigned(nmp->nm_rsize);
2793 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred,
2794 &xid);
2795 savexid = xid;
2796 nfsm_postop_attr(vp, attrflag, &xid);
2797 if (error) {
2798 m_freem(mrep);
2799 goto nfsmout;
2800 }
2801 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2802 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2803 dnp->n_cookieverf.nfsuquad[1] = *tl++;
2804 more_dirs = fxdr_unsigned(int, *tl);
2805
2806 /* loop thru the dir entries, doctoring them to 4bsd form */
2807 while (more_dirs && bigenough) {
2808 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2809 fxdr_hyper(tl, &fileno);
2810 len = fxdr_unsigned(int, *(tl + 2));
2811 if (len <= 0 || len > NFS_MAXNAMLEN) {
2812 error = EBADRPC;
2813 m_freem(mrep);
2814 goto nfsmout;
2815 }
2816 tlen = nfsm_rndup(len);
2817 if (tlen == len)
2818 tlen += 4; /* To ensure null termination*/
2819 left = DIRBLKSIZ - blksiz;
2820 if ((tlen + DIRHDSIZ) > left) {
2821 dp->d_reclen += left;
2822 uiop->uio_iov->iov_base += left;
2823 uiop->uio_iov->iov_len -= left;
2824 uiop->uio_offset += left;
2825 uiop->uio_resid -= left;
2826 blksiz = 0;
2827 }
2828 if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2829 bigenough = 0;
2830 if (bigenough) {
2831 dp = (struct dirent *)uiop->uio_iov->iov_base;
2832 dp->d_fileno = (int)fileno;
2833 dp->d_namlen = len;
2834 dp->d_reclen = tlen + DIRHDSIZ;
2835 dp->d_type = DT_UNKNOWN;
2836 blksiz += dp->d_reclen;
2837 if (blksiz == DIRBLKSIZ)
2838 blksiz = 0;
2839 uiop->uio_offset += DIRHDSIZ;
2840 uiop->uio_resid -= DIRHDSIZ;
2841 uiop->uio_iov->iov_base += DIRHDSIZ;
2842 uiop->uio_iov->iov_len -= DIRHDSIZ;
2843 cnp->cn_nameptr = uiop->uio_iov->iov_base;
2844 cnp->cn_namelen = len;
2845 nfsm_mtouio(uiop, len);
2846 cp = uiop->uio_iov->iov_base;
2847 tlen -= len;
2848 *cp = '\0';
2849 uiop->uio_iov->iov_base += tlen;
2850 uiop->uio_iov->iov_len -= tlen;
2851 uiop->uio_offset += tlen;
2852 uiop->uio_resid -= tlen;
2853 } else
2854 nfsm_adv(nfsm_rndup(len));
2855 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2856 if (bigenough) {
2857 cookie.nfsuquad[0] = *tl++;
2858 cookie.nfsuquad[1] = *tl++;
2859 } else
2860 tl += 2;
2861
2862 /*
2863 * Since the attributes are before the file handle
2864 * (sigh), we must skip over the attributes and then
2865 * come back and get them.
2866 */
2867 attrflag = fxdr_unsigned(int, *tl);
2868 if (attrflag) {
2869 dpossav1 = dpos;
2870 mdsav1 = md;
2871 nfsm_adv(NFSX_V3FATTR);
2872 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2873 doit = fxdr_unsigned(int, *tl);
2874 if (doit) {
2875 nfsm_getfh(fhp, fhsize, 1);
2876 if (NFS_CMPFH(dnp, fhp, fhsize)) {
2877 VREF(vp);
2878 newvp = vp;
2879 np = dnp;
2880 } else {
2881 if ((error = nfs_nget(vp->v_mount, fhp,
2882 fhsize, &np)))
2883 doit = 0;
2884 else
2885 newvp = NFSTOV(np);
2886 }
2887 }
2888 if (doit) {
2889 dpossav2 = dpos;
2890 dpos = dpossav1;
2891 mdsav2 = md;
2892 md = mdsav1;
2893 xid = savexid;
2894 nfsm_loadattr(newvp, (struct vattr *)0, &xid);
2895 dpos = dpossav2;
2896 md = mdsav2;
2897 dp->d_type =
2898 IFTODT(VTTOIF(np->n_vattr.va_type));
2899 ndp->ni_vp = newvp;
2900 cnp->cn_hash = 0;
2901 for (cp = cnp->cn_nameptr, i = 1; i <= len;
2902 i++, cp++)
2903 cnp->cn_hash += (unsigned char)*cp * i;
2904 if (cnp->cn_namelen <= NCHNAMLEN)
2905 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
2906 }
2907 } else {
2908 /* Just skip over the file handle */
2909 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2910 i = fxdr_unsigned(int, *tl);
2911 nfsm_adv(nfsm_rndup(i));
2912 }
2913 if (newvp != NULLVP) {
2914 vrele(newvp);
2915 newvp = NULLVP;
2916 }
2917 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2918 more_dirs = fxdr_unsigned(int, *tl);
2919 }
2920 /*
2921 * If at end of rpc data, get the eof boolean
2922 */
2923 if (!more_dirs) {
2924 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2925 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2926 }
2927 m_freem(mrep);
2928 }
2929 /*
2930 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
2931 * by increasing d_reclen for the last record.
2932 */
2933 if (blksiz > 0) {
2934 left = DIRBLKSIZ - blksiz;
2935 dp->d_reclen += left;
2936 uiop->uio_iov->iov_base += left;
2937 uiop->uio_iov->iov_len -= left;
2938 uiop->uio_offset += left;
2939 uiop->uio_resid -= left;
2940 }
2941
2942 /*
2943 * We are now either at the end of the directory or have filled the
2944 * block.
2945 */
2946 if (bigenough)
2947 dnp->n_direofoffset = uiop->uio_offset;
2948 else {
2949 if (uiop->uio_resid > 0)
2950 printf("EEK! readdirplusrpc resid > 0\n");
2951 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2952 *cookiep = cookie;
2953 }
2954 nfsmout:
2955 if (newvp != NULLVP) {
2956 if (newvp == vp)
2957 vrele(newvp);
2958 else
2959 vput(newvp);
2960 newvp = NULLVP;
2961 }
2962 return (error);
2963 }
2964
2965 /*
2966 * Silly rename. To make the NFS filesystem that is stateless look a little
2967 * more like the "ufs" a remove of an active vnode is translated to a rename
2968 * to a funny looking filename that is removed by nfs_inactive on the
2969 * nfsnode. There is the potential for another process on a different client
2970 * to create the same funny name between the nfs_lookitup() fails and the
2971 * nfs_rename() completes, but...
2972 */
2973 static int
2974 nfs_sillyrename(dvp, vp, cnp)
2975 struct vnode *dvp, *vp;
2976 struct componentname *cnp;
2977 {
2978 register struct sillyrename *sp;
2979 struct nfsnode *np;
2980 int error;
2981 short pid;
2982 struct ucred *cred;
2983
2984 cache_purge(dvp);
2985 np = VTONFS(vp);
2986 #if DIAGNOSTIC
2987 if (vp->v_type == VDIR)
2988 panic("nfs_sillyrename: dir");
2989 #endif
2990 MALLOC_ZONE(sp, struct sillyrename *,
2991 sizeof (struct sillyrename), M_NFSREQ, M_WAITOK);
2992 sp->s_cred = crdup(cnp->cn_cred);
2993 sp->s_dvp = dvp;
2994 VREF(dvp);
2995
2996 /* Fudge together a funny name */
2997 pid = cnp->cn_proc->p_pid;
2998 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid);
2999
3000 /* Try lookitups until we get one that isn't there */
3001 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
3002 cnp->cn_proc, (struct nfsnode **)0) == 0) {
3003 sp->s_name[4]++;
3004 if (sp->s_name[4] > 'z') {
3005 error = EINVAL;
3006 goto bad;
3007 }
3008 }
3009 if ((error = nfs_renameit(dvp, cnp, sp)))
3010 goto bad;
3011 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
3012 cnp->cn_proc, &np);
3013 #if DIAGNOSTIC
3014 kprintf("sillyrename: %s, vp=%x, np=%x, dvp=%x\n",
3015 &sp->s_name[0], (unsigned)vp, (unsigned)np, (unsigned)dvp);
3016 #endif
3017 np->n_sillyrename = sp;
3018 return (0);
3019 bad:
3020 vrele(sp->s_dvp);
3021 cred = sp->s_cred;
3022 sp->s_cred = NOCRED;
3023 crfree(cred);
3024 _FREE_ZONE((caddr_t)sp, sizeof (struct sillyrename), M_NFSREQ);
3025 return (error);
3026 }
3027
3028 /*
3029 * Look up a file name and optionally either update the file handle or
3030 * allocate an nfsnode, depending on the value of npp.
3031 * npp == NULL --> just do the lookup
3032 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
3033 * handled too
3034 * *npp != NULL --> update the file handle in the vnode
3035 */
3036 static int
3037 nfs_lookitup(dvp, name, len, cred, procp, npp)
3038 register struct vnode *dvp;
3039 char *name;
3040 int len;
3041 struct ucred *cred;
3042 struct proc *procp;
3043 struct nfsnode **npp;
3044 {
3045 register u_long *tl;
3046 register caddr_t cp;
3047 register long t1, t2;
3048 struct vnode *newvp = (struct vnode *)0;
3049 struct nfsnode *np, *dnp = VTONFS(dvp);
3050 caddr_t bpos, dpos, cp2;
3051 int error = 0, fhlen, attrflag;
3052 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
3053 nfsfh_t *nfhp;
3054 int v3 = NFS_ISV3(dvp);
3055 u_int64_t xid;
3056
3057 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
3058 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
3059 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
3060 nfsm_fhtom(dvp, v3);
3061 nfsm_strtom(name, len, NFS_MAXNAMLEN);
3062 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred, &xid);
3063 if (npp && !error) {
3064 nfsm_getfh(nfhp, fhlen, v3);
3065 if (*npp) {
3066 np = *npp;
3067 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
3068 _FREE_ZONE((caddr_t)np->n_fhp,
3069 np->n_fhsize, M_NFSBIGFH);
3070 np->n_fhp = &np->n_fh;
3071 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
3072 MALLOC_ZONE(np->n_fhp, nfsfh_t *,
3073 fhlen, M_NFSBIGFH, M_WAITOK);
3074 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
3075 np->n_fhsize = fhlen;
3076 newvp = NFSTOV(np);
3077 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
3078 VREF(dvp);
3079 newvp = dvp;
3080 } else {
3081 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
3082 if (error) {
3083 m_freem(mrep);
3084 return (error);
3085 }
3086 newvp = NFSTOV(np);
3087 }
3088 if (v3) {
3089 nfsm_postop_attr(newvp, attrflag, &xid);
3090 if (!attrflag && *npp == NULL) {
3091 m_freem(mrep);
3092 if (newvp == dvp)
3093 vrele(newvp);
3094 else
3095 vput(newvp);
3096 return (ENOENT);
3097 }
3098 } else
3099 nfsm_loadattr(newvp, (struct vattr *)0, &xid);
3100 }
3101 nfsm_reqdone;
3102 if (npp && *npp == NULL) {
3103 if (error) {
3104 if (newvp)
3105 if (newvp == dvp)
3106 vrele(newvp);
3107 else
3108 vput(newvp);
3109 } else
3110 *npp = np;
3111 }
3112 return (error);
3113 }
3114
3115 /*
3116 * Nfs Version 3 commit rpc
3117 */
3118 static int
3119 nfs_commit(vp, offset, cnt, cred, procp)
3120 register struct vnode *vp;
3121 u_quad_t offset;
3122 int cnt;
3123 struct ucred *cred;
3124 struct proc *procp;
3125 {
3126 register caddr_t cp;
3127 register u_long *tl;
3128 register int t1, t2;
3129 register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
3130 caddr_t bpos, dpos, cp2;
3131 int error = 0, wccflag = NFSV3_WCCRATTR;
3132 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
3133 u_int64_t xid;
3134
3135 FSDBG(521, vp, offset, cnt, nmp->nm_flag);
3136 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0)
3137 return (0);
3138 nfsstats.rpccnt[NFSPROC_COMMIT]++;
3139 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
3140 nfsm_fhtom(vp, 1);
3141 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
3142 txdr_hyper(&offset, tl);
3143 tl += 2;
3144 *tl = txdr_unsigned(cnt);
3145 nfsm_request(vp, NFSPROC_COMMIT, procp, cred, &xid);
3146 nfsm_wcc_data(vp, wccflag, &xid);
3147 if (!error) {
3148 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF);
3149 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
3150 NFSX_V3WRITEVERF)) {
3151 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
3152 NFSX_V3WRITEVERF);
3153 error = NFSERR_STALEWRITEVERF;
3154 }
3155 }
3156 nfsm_reqdone;
3157 return (error);
3158 }
3159
3160 /*
3161 * Kludge City..
3162 * - make nfs_bmap() essentially a no-op that does no translation
3163 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
3164 * (Maybe I could use the process's page mapping, but I was concerned that
3165 * Kernel Write might not be enabled and also figured copyout() would do
3166 * a lot more work than bcopy() and also it currently happens in the
3167 * context of the swapper process (2).
3168 */
3169 static int
3170 nfs_bmap(ap)
3171 struct vop_bmap_args /* {
3172 struct vnode *a_vp;
3173 daddr_t a_bn;
3174 struct vnode **a_vpp;
3175 daddr_t *a_bnp;
3176 int *a_runp;
3177 int *a_runb;
3178 } */ *ap;
3179 {
3180 register struct vnode *vp = ap->a_vp;
3181 int devBlockSize = DEV_BSIZE;
3182
3183 if (ap->a_vpp != NULL)
3184 *ap->a_vpp = vp;
3185 if (ap->a_bnp != NULL)
3186 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize,
3187 devBlockSize);
3188 if (ap->a_runp != NULL)
3189 *ap->a_runp = 0;
3190 #ifdef notyet
3191 if (ap->a_runb != NULL)
3192 *ap->a_runb = 0;
3193 #endif
3194 return (0);
3195 }
3196
3197 /*
3198 * Strategy routine.
3199 * For async requests when nfsiod(s) are running, queue the request by
3200 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
3201 * request.
3202 */
3203 static int
3204 nfs_strategy(ap)
3205 struct vop_strategy_args *ap;
3206 {
3207 register struct buf *bp = ap->a_bp;
3208 struct ucred *cr;
3209 struct proc *p;
3210 int error = 0;
3211
3212 if (ISSET(bp->b_flags, B_PHYS))
3213 panic("nfs_strategy: physio");
3214 if (ISSET(bp->b_flags, B_ASYNC))
3215 p = (struct proc *)0;
3216 else
3217 p = current_proc(); /* XXX */
3218 if (ISSET(bp->b_flags, B_READ))
3219 cr = bp->b_rcred;
3220 else
3221 cr = bp->b_wcred;
3222 /*
3223 * If the op is asynchronous and an i/o daemon is waiting
3224 * queue the request, wake it up and wait for completion
3225 * otherwise just do it ourselves.
3226 */
3227 if (!ISSET(bp->b_flags, B_ASYNC) || nfs_asyncio(bp, NOCRED))
3228 error = nfs_doio(bp, cr, p);
3229 return (error);
3230 }
3231
3232 /*
3233 * Mmap a file
3234 *
3235 * NB Currently unsupported.
3236 */
3237 /* ARGSUSED */
3238 static int
3239 nfs_mmap(ap)
3240 struct vop_mmap_args /* {
3241 struct vnode *a_vp;
3242 int a_fflags;
3243 struct ucred *a_cred;
3244 struct proc *a_p;
3245 } */ *ap;
3246 {
3247
3248 return (EINVAL);
3249 }
3250
3251 /*
3252 * fsync vnode op. Just call nfs_flush() with commit == 1.
3253 */
3254 /* ARGSUSED */
3255 static int
3256 nfs_fsync(ap)
3257 struct vop_fsync_args /* {
3258 struct vnodeop_desc *a_desc;
3259 struct vnode * a_vp;
3260 struct ucred * a_cred;
3261 int a_waitfor;
3262 struct proc * a_p;
3263 } */ *ap;
3264 {
3265 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));
3266 }
3267
3268 /*
3269 * Flush all the blocks associated with a vnode.
3270 * Walk through the buffer pool and push any dirty pages
3271 * associated with the vnode.
3272 */
3273 static int
3274 nfs_flush(vp, cred, waitfor, p, commit)
3275 register struct vnode *vp;
3276 struct ucred *cred;
3277 int waitfor;
3278 struct proc *p;
3279 int commit;
3280 {
3281 register struct nfsnode *np = VTONFS(vp);
3282 register struct buf *bp;
3283 register int i;
3284 struct buf *nbp;
3285 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
3286 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos, err;
3287 int passone = 1;
3288 u_quad_t off, endoff, toff;
3289 struct ucred* wcred = NULL;
3290 struct buf **bvec = NULL;
3291 #ifndef NFS_COMMITBVECSIZ
3292 #define NFS_COMMITBVECSIZ 20
3293 #endif
3294 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ];
3295 int bvecsize = 0, bveccount;
3296 kern_return_t kret;
3297 upl_t upl;
3298
3299 FSDBG_TOP(517, vp, np, waitfor, commit);
3300
3301 if (nmp->nm_flag & NFSMNT_INT)
3302 slpflag = PCATCH;
3303 if (!commit)
3304 passone = 0;
3305
3306 /*
3307 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
3308 * server, but nas not been committed to stable storage on the server
3309 * yet. On the first pass, the byte range is worked out and the commit
3310 * rpc is done. On the second pass, nfs_writebp() is called to do the
3311 * job.
3312 */
3313 again:
3314 FSDBG(518, vp->v_dirtyblkhd.lh_first, np->n_flag, 0, 0);
3315 if (vp->v_dirtyblkhd.lh_first)
3316 np->n_flag |= NMODIFIED;
3317 off = (u_quad_t)-1;
3318 endoff = 0;
3319 bvecpos = 0;
3320 if (NFS_ISV3(vp) && commit) {
3321 s = splbio();
3322 /*
3323 * Count up how many buffers waiting for a commit.
3324 * This is an upper bound - any with dirty pages must be
3325 * written not commited.
3326 */
3327 bveccount = 0;
3328 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
3329 nbp = bp->b_vnbufs.le_next;
3330 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
3331 == (B_DELWRI | B_NEEDCOMMIT))
3332 bveccount++;
3333 FSDBG(519, bp, bp->b_flags, bveccount, 0);
3334 }
3335 /*
3336 * Allocate space to remember the list of bufs to commit. It is
3337 * important to use M_NOWAIT here to avoid a race with nfs_write
3338 * If we can't get memory (for whatever reason), we will end up
3339 * committing the buffers one-by-one in the loop below.
3340 */
3341 if (bvec != NULL && bvec != bvec_on_stack)
3342 _FREE(bvec, M_TEMP);
3343 if (bveccount > NFS_COMMITBVECSIZ) {
3344 MALLOC(bvec, struct buf **,
3345 bveccount * sizeof(struct buf *), M_TEMP,
3346 M_NOWAIT);
3347 if (bvec == NULL) {
3348 bvec = bvec_on_stack;
3349 bvecsize = NFS_COMMITBVECSIZ;
3350 } else
3351 bvecsize = bveccount;
3352 } else {
3353 bvec = bvec_on_stack;
3354 bvecsize = NFS_COMMITBVECSIZ;
3355 }
3356 FSDBG(519, 0, bvecsize, bveccount, 0);
3357
3358 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
3359 nbp = bp->b_vnbufs.le_next;
3360
3361 FSDBG(520, bp, bp->b_flags, bvecpos, bp->b_bufsize);
3362 FSDBG(520, bp->b_validoff, bp->b_validend,
3363 bp->b_dirtyoff, bp->b_dirtyend);
3364 if (bvecpos >= bvecsize)
3365 break;
3366 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
3367 != (B_DELWRI | B_NEEDCOMMIT))
3368 continue;
3369
3370 bremfree(bp);
3371 SET(bp->b_flags, B_BUSY);
3372 /*
3373 * we need a upl to see if the page has been
3374 * dirtied (think mmap) since the unstable write, and
3375 * so to prevent vm from paging during our commit rpc
3376 */
3377 if (ISSET(bp->b_flags, B_PAGELIST)) {
3378 upl = bp->b_pagelist;
3379 } else {
3380 kret = ubc_create_upl(vp, ubc_blktooff(vp, bp->b_lblkno),
3381 bp->b_bufsize, &upl,
3382 NULL, UPL_PRECIOUS);
3383 if (kret != KERN_SUCCESS)
3384 panic("nfs_flush: create upl %d", kret);
3385 #ifdef UBC_DEBUG
3386 upl_ubc_alias_set(upl, current_act(), 1);
3387 #endif /* UBC_DEBUG */
3388 }
3389 if (upl_dirty_page(ubc_upl_pageinfo(upl), 0)) {
3390 if (!ISSET(bp->b_flags, B_PAGELIST)) {
3391 err = ubc_upl_abort(upl, NULL);
3392 if (err)
3393 printf("nfs_flush: upl abort %d\n", err);
3394 }
3395 /*
3396 * Any/all of it may be modified...
3397 */
3398 bp->b_dirtyoff = bp->b_validoff;
3399 bp->b_dirtyend = bp->b_validend;
3400 CLR(bp->b_flags, B_NEEDCOMMIT);
3401 /* blocking calls were made, re-evaluate nbp */
3402 nbp = bp->b_vnbufs.le_next;
3403 brelse(bp); /* XXX may block. Is using nbp ok??? */
3404 continue;
3405 }
3406 if (!ISSET(bp->b_flags, B_PAGELIST)) {
3407 bp->b_pagelist = upl;
3408 SET(bp->b_flags, B_PAGELIST);
3409 ubc_upl_map(upl, (vm_address_t *)&bp->b_data);
3410 }
3411
3412 /* blocking calls were made, re-evaluate nbp */
3413 nbp = bp->b_vnbufs.le_next;
3414
3415 /*
3416 * Work out if all buffers are using the same cred
3417 * so we can deal with them all with one commit.
3418 */
3419 if (wcred == NULL)
3420 wcred = bp->b_wcred;
3421 else if (wcred != bp->b_wcred)
3422 wcred = NOCRED;
3423 SET(bp->b_flags, B_WRITEINPROG);
3424
3425 /*
3426 * A list of these buffers is kept so that the
3427 * second loop knows which buffers have actually
3428 * been committed. This is necessary, since there
3429 * may be a race between the commit rpc and new
3430 * uncommitted writes on the file.
3431 */
3432 bvec[bvecpos++] = bp;
3433 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
3434 bp->b_dirtyoff;
3435 if (toff < off)
3436 off = toff;
3437 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
3438 if (toff > endoff)
3439 endoff = toff;
3440 }
3441 splx(s);
3442 }
3443 if (bvecpos > 0) {
3444 /*
3445 * Commit data on the server, as required.
3446 * If all bufs are using the same wcred, then use that with
3447 * one call for all of them, otherwise commit each one
3448 * separately.
3449 */
3450 if (wcred != NOCRED)
3451 retv = nfs_commit(vp, off, (int)(endoff - off),
3452 wcred, p);
3453 else {
3454 retv = 0;
3455 for (i = 0; i < bvecpos; i++) {
3456 off_t off, size;
3457 bp = bvec[i];
3458 FSDBG(522, bp, bp->b_blkno * DEV_BSIZE,
3459 bp->b_dirtyoff, bp->b_dirtyend);
3460 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
3461 bp->b_dirtyoff;
3462 size = (u_quad_t)(bp->b_dirtyend
3463 - bp->b_dirtyoff);
3464 retv = nfs_commit(vp, off, (int)size,
3465 bp->b_wcred, p);
3466 if (retv) break;
3467 }
3468 }
3469
3470 if (retv == NFSERR_STALEWRITEVERF)
3471 nfs_clearcommit(vp->v_mount);
3472
3473 /*
3474 * Now, either mark the blocks I/O done or mark the
3475 * blocks dirty, depending on whether the commit
3476 * succeeded.
3477 */
3478 for (i = 0; i < bvecpos; i++) {
3479 bp = bvec[i];
3480 FSDBG(523, bp, retv, bp->b_flags, 0);
3481 CLR(bp->b_flags, (B_NEEDCOMMIT | B_WRITEINPROG));
3482 if (retv) {
3483 brelse(bp);
3484 } else {
3485 int oldflags = bp->b_flags;
3486
3487 s = splbio();
3488 vp->v_numoutput++;
3489 SET(bp->b_flags, B_ASYNC);
3490 CLR(bp->b_flags,
3491 (B_READ|B_DONE|B_ERROR|B_DELWRI));
3492 if (ISSET(oldflags, B_DELWRI)) {
3493 extern int nbdwrite;
3494 nbdwrite--;
3495 wakeup((caddr_t)&nbdwrite);
3496 }
3497 bp->b_dirtyoff = bp->b_dirtyend = 0;
3498 reassignbuf(bp, vp);
3499 splx(s);
3500 biodone(bp);
3501 }
3502 }
3503
3504 }
3505 /*
3506 * Start/do any write(s) that are required. There is a window here
3507 * where B_BUSY protects the buffer. The vm pages have been freed up,
3508 * yet B_BUSY is set. Don't think you will hit any busy/incore problems
3509 * while we sleep, but not absolutely sure. Keep an eye on it. Otherwise
3510 * we will have to hold vm page across this locked. - EKN
3511 */
3512 loop:
3513 if (current_thread_aborted()) {
3514 error = EINTR;
3515 goto done;
3516 }
3517 s = splbio();
3518 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
3519 nbp = bp->b_vnbufs.le_next;
3520 if (ISSET(bp->b_flags, B_BUSY)) {
3521 FSDBG(524, bp, waitfor, passone, bp->b_flags);
3522 if (waitfor != MNT_WAIT || passone)
3523 continue;
3524 SET(bp->b_flags, B_WANTED);
3525 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
3526 "nfsfsync", slptimeo);
3527 splx(s);
3528 if (error) {
3529 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
3530 error = EINTR;
3531 goto done;
3532 }
3533 if (slpflag == PCATCH) {
3534 slpflag = 0;
3535 slptimeo = 2 * hz;
3536 }
3537 }
3538 goto loop;
3539 }
3540 if (!ISSET(bp->b_flags, B_DELWRI))
3541 panic("nfs_fsync: not dirty");
3542 FSDBG(525, bp, passone, commit, bp->b_flags);
3543 if ((passone || !commit) && ISSET(bp->b_flags, B_NEEDCOMMIT))
3544 continue;
3545 bremfree(bp);
3546 if (passone || !commit)
3547 SET(bp->b_flags, B_BUSY|B_ASYNC);
3548 else
3549 SET(bp->b_flags,
3550 B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
3551 splx(s);
3552 VOP_BWRITE(bp);
3553 goto loop;
3554 }
3555 splx(s);
3556 if (passone) {
3557 passone = 0;
3558 goto again;
3559 }
3560 if (waitfor == MNT_WAIT) {
3561 while (vp->v_numoutput) {
3562 vp->v_flag |= VBWAIT;
3563 error = tsleep((caddr_t)&vp->v_numoutput,
3564 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);
3565 if (error) {
3566 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
3567 error = EINTR;
3568 goto done;
3569 }
3570 if (slpflag == PCATCH) {
3571 slpflag = 0;
3572 slptimeo = 2 * hz;
3573 }
3574 }
3575 }
3576 if (vp->v_dirtyblkhd.lh_first && commit) {
3577 goto loop;
3578 }
3579 }
3580 FSDBG(526, np->n_flag, np->n_error, 0, 0);
3581 if (np->n_flag & NWRITEERR) {
3582 error = np->n_error;
3583 np->n_flag &= ~NWRITEERR;
3584 }
3585 done:
3586 FSDBG_BOT(517, vp, np, error, 0);
3587 if (bvec != NULL && bvec != bvec_on_stack)
3588 _FREE(bvec, M_TEMP);
3589 return (error);
3590 }
3591
3592 /*
3593 * Return POSIX pathconf information applicable to nfs.
3594 *
3595 * The NFS V2 protocol doesn't support this, so just return EINVAL
3596 * for V2.
3597 */
3598 /* ARGSUSED */
3599 static int
3600 nfs_pathconf(ap)
3601 struct vop_pathconf_args /* {
3602 struct vnode *a_vp;
3603 int a_name;
3604 int *a_retval;
3605 } */ *ap;
3606 {
3607
3608 return (EINVAL);
3609 }
3610
3611 /*
3612 * NFS advisory byte-level locks.
3613 * Currently unsupported.
3614 */
3615 static int
3616 nfs_advlock(ap)
3617 struct vop_advlock_args /* {
3618 struct vnode *a_vp;
3619 caddr_t a_id;
3620 int a_op;
3621 struct flock *a_fl;
3622 int a_flags;
3623 } */ *ap;
3624 {
3625 #ifdef __FreeBSD__
3626 register struct nfsnode *np = VTONFS(ap->a_vp);
3627
3628 /*
3629 * The following kludge is to allow diskless support to work
3630 * until a real NFS lockd is implemented. Basically, just pretend
3631 * that this is a local lock.
3632 */
3633 return (lf_advlock(ap, &(np->n_lockf), np->n_size));
3634 #else
3635 #if DIAGNOSTIC
3636 printf("nfs_advlock: pid %d comm %s\n", current_proc()->p_pid, current_proc()->p_comm);
3637 #endif
3638 return (EOPNOTSUPP);
3639 #endif
3640 }
3641
3642 /*
3643 * Print out the contents of an nfsnode.
3644 */
3645 static int
3646 nfs_print(ap)
3647 struct vop_print_args /* {
3648 struct vnode *a_vp;
3649 } */ *ap;
3650 {
3651 register struct vnode *vp = ap->a_vp;
3652 register struct nfsnode *np = VTONFS(vp);
3653
3654 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
3655 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
3656 if (vp->v_type == VFIFO)
3657 fifo_printinfo(vp);
3658 printf("\n");
3659 return (0);
3660 }
3661
3662 /*
3663 * NFS directory offset lookup.
3664 * Currently unsupported.
3665 */
3666 static int
3667 nfs_blkatoff(ap)
3668 struct vop_blkatoff_args /* {
3669 struct vnode *a_vp;
3670 off_t a_offset;
3671 char **a_res;
3672 struct buf **a_bpp;
3673 } */ *ap;
3674 {
3675
3676 #if DIAGNOSTIC
3677 printf("nfs_blkatoff: unimplemented!!");
3678 #endif
3679 return (EOPNOTSUPP);
3680 }
3681
3682 /*
3683 * NFS flat namespace allocation.
3684 * Currently unsupported.
3685 */
3686 static int
3687 nfs_valloc(ap)
3688 struct vop_valloc_args /* {
3689 struct vnode *a_pvp;
3690 int a_mode;
3691 struct ucred *a_cred;
3692 struct vnode **a_vpp;
3693 } */ *ap;
3694 {
3695
3696 return (EOPNOTSUPP);
3697 }
3698
3699 /*
3700 * NFS flat namespace free.
3701 * Currently unsupported.
3702 */
3703 static int
3704 nfs_vfree(ap)
3705 struct vop_vfree_args /* {
3706 struct vnode *a_pvp;
3707 ino_t a_ino;
3708 int a_mode;
3709 } */ *ap;
3710 {
3711
3712 #if DIAGNOSTIC
3713 printf("nfs_vfree: unimplemented!!");
3714 #endif
3715 return (EOPNOTSUPP);
3716 }
3717
3718 /*
3719 * NFS file truncation.
3720 */
3721 static int
3722 nfs_truncate(ap)
3723 struct vop_truncate_args /* {
3724 struct vnode *a_vp;
3725 off_t a_length;
3726 int a_flags;
3727 struct ucred *a_cred;
3728 struct proc *a_p;
3729 } */ *ap;
3730 {
3731
3732 /* Use nfs_setattr */
3733 #if DIAGNOSTIC
3734 printf("nfs_truncate: unimplemented!!");
3735 #endif
3736 return (EOPNOTSUPP);
3737 }
3738
3739 /*
3740 * NFS update.
3741 */
3742 static int
3743 nfs_update(ap)
3744 struct vop_update_args /* {
3745 struct vnode *a_vp;
3746 struct timeval *a_ta;
3747 struct timeval *a_tm;
3748 int a_waitfor;
3749 } */ *ap;
3750 {
3751
3752 /* Use nfs_setattr */
3753 #if DIAGNOSTIC
3754 printf("nfs_update: unimplemented!!");
3755 #endif
3756 return (EOPNOTSUPP);
3757 }
3758
3759 int nfs_aio_threads = 0; /* 1 per nfd (arbitrary) */
3760 struct slock nfs_aio_slock;
3761 TAILQ_HEAD(bqueues, buf) nfs_aio_bufq;
3762 int nfs_aio_bufq_len = 0; /* diagnostic only */
3763
3764 void
3765 nfs_aio_thread()
3766 { /* see comment below in nfs_bwrite() for some rationale */
3767 struct buf *bp;
3768 boolean_t funnel_state;
3769
3770 funnel_state = thread_funnel_set(kernel_flock, TRUE);
3771 for(;;) {
3772 simple_lock(&nfs_aio_slock);
3773 if ((bp = nfs_aio_bufq.tqh_first)) {
3774 TAILQ_REMOVE(&nfs_aio_bufq, bp, b_freelist);
3775 nfs_aio_bufq_len--;
3776 simple_unlock(&nfs_aio_slock);
3777 nfs_writebp(bp, 1);
3778 } else { /* nothing to do - goodnight */
3779 assert_wait(&nfs_aio_bufq, THREAD_UNINT);
3780 simple_unlock(&nfs_aio_slock);
3781 (void)tsleep((caddr_t)0, PRIBIO+1, "nfs_aio_bufq", 0);
3782 }
3783 }
3784 (void) thread_funnel_set(kernel_flock, FALSE);
3785 }
3786
3787
3788 void
3789 nfs_aio_thread_init()
3790 {
3791 if (nfs_aio_threads++ == 0) {
3792 simple_lock_init(&nfs_aio_slock);
3793 TAILQ_INIT(&nfs_aio_bufq);
3794 }
3795 kernel_thread(kernel_task, nfs_aio_thread);
3796 }
3797
3798
3799 /*
3800 * Just call nfs_writebp() with the force argument set to 1.
3801 */
3802 static int
3803 nfs_bwrite(ap)
3804 struct vop_bwrite_args /* {
3805 struct vnode *a_bp;
3806 } */ *ap;
3807 {
3808 extern void wakeup_one(caddr_t chan);
3809
3810 /*
3811 * nfs_writebp will issue a synchronous rpc to if B_ASYNC then
3812 * to avoid distributed deadlocks we handoff the write to the
3813 * nfs_aio threads. Doing so allows us to complete the
3814 * current request, rather than blocking on a server which may
3815 * be ourself (or blocked on ourself).
3816 *
3817 * Note the loopback deadlocks happened when the thread
3818 * invoking us was nfsd, and also when it was the pagedaemon.
3819 *
3820 * This solution has one known problem. If *ALL* buffers get
3821 * on the nfs_aio queue then no forward progress can be made
3822 * until one of those writes complete. And if the current
3823 * nfs_aio writes-in-progress block due to a non-responsive server we
3824 * are in a deadlock circle. Probably the cure is to limit the
3825 * async write concurrency in getnewbuf as in FreeBSD 3.2.
3826 */
3827 if (nfs_aio_threads && ISSET(ap->a_bp->b_flags, B_ASYNC)) {
3828 simple_lock(&nfs_aio_slock);
3829 nfs_aio_bufq_len++;
3830 TAILQ_INSERT_TAIL(&nfs_aio_bufq, ap->a_bp, b_freelist);
3831 simple_unlock(&nfs_aio_slock);
3832 wakeup_one((caddr_t)&nfs_aio_bufq);
3833 return (0);
3834 }
3835 return (nfs_writebp(ap->a_bp, 1));
3836 }
3837
3838 /*
3839 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless
3840 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
3841 */
3842 int
3843 nfs_writebp(bp, force)
3844 register struct buf *bp;
3845 int force;
3846 {
3847 int s;
3848 register int oldflags = bp->b_flags, retv = 1;
3849 off_t off;
3850 upl_t upl;
3851 kern_return_t kret;
3852 struct vnode *vp = bp->b_vp;
3853 upl_page_info_t *pl;
3854
3855 if(!ISSET(bp->b_flags, B_BUSY))
3856 panic("nfs_writebp: buffer is not busy???");
3857
3858 s = splbio();
3859 CLR(bp->b_flags, (B_READ|B_DONE|B_ERROR|B_DELWRI));
3860 if (ISSET(oldflags, B_DELWRI)) {
3861 extern int nbdwrite;
3862 nbdwrite--;
3863 wakeup((caddr_t)&nbdwrite);
3864 }
3865
3866 if (ISSET(oldflags, (B_ASYNC|B_DELWRI))) {
3867 reassignbuf(bp, vp);
3868 }
3869
3870 vp->v_numoutput++;
3871 current_proc()->p_stats->p_ru.ru_oublock++;
3872 splx(s);
3873
3874 /*
3875 * Since the B_BUSY flag is set, we need to lock the page before doing
3876 * nfs_commit. Otherwise we may block and get a busy incore pages
3877 * during a vm pageout. Move the existing code up before the commit.
3878 */
3879 if (!ISSET(bp->b_flags, B_META) && UBCISVALID(vp) &&
3880 !ISSET(bp->b_flags, B_PAGELIST)) {
3881 kret = ubc_create_upl(vp, ubc_blktooff(vp, bp->b_lblkno),
3882 bp->b_bufsize, &upl, &pl, UPL_PRECIOUS);
3883 if (kret != KERN_SUCCESS)
3884 panic("nfs_writebp: ubc_create_upl %d", kret);
3885 #ifdef UBC_DEBUG
3886 upl_ubc_alias_set(upl, current_act(), 2);
3887 #endif /* UBC_DEBUG */
3888 s = splbio();
3889 bp->b_pagelist = upl;
3890 SET(bp->b_flags, B_PAGELIST);
3891 splx(s);
3892
3893 kret = ubc_upl_map(upl, (vm_address_t *)&(bp->b_data));
3894 if (kret != KERN_SUCCESS)
3895 panic("nfs_writebp: ubc_upl_map %d", kret);
3896 if(bp->b_data == 0)
3897 panic("nfs_writebp: ubc_upl_map mapped 0");
3898 if (!upl_page_present(pl, 0)) /* even more paranoia */
3899 panic("nfs_writebp: nopage");
3900 }
3901
3902 /*
3903 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3904 * an actual write will have to be scheduled via. VOP_STRATEGY().
3905 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3906 */
3907 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
3908 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
3909 SET(bp->b_flags, B_WRITEINPROG);
3910 retv = nfs_commit(vp, off, bp->b_dirtyend-bp->b_dirtyoff,
3911 bp->b_wcred, bp->b_proc);
3912 CLR(bp->b_flags, B_WRITEINPROG);
3913 if (!retv) {
3914 bp->b_dirtyoff = bp->b_dirtyend = 0;
3915 CLR(bp->b_flags, B_NEEDCOMMIT);
3916 biodone(bp); /* on B_ASYNC will brelse the buffer */
3917
3918 } else if (retv == NFSERR_STALEWRITEVERF)
3919 nfs_clearcommit(vp->v_mount);
3920 }
3921 if (retv) {
3922 if (force)
3923 SET(bp->b_flags, B_WRITEINPROG);
3924 VOP_STRATEGY(bp);
3925 }
3926
3927 if( (oldflags & B_ASYNC) == 0) {
3928 int rtval = biowait(bp);
3929
3930 if (oldflags & B_DELWRI) {
3931 s = splbio();
3932 reassignbuf(bp, vp);
3933 splx(s);
3934 }
3935 brelse(bp);
3936 return (rtval);
3937 }
3938
3939 return (0);
3940 }
3941
3942 /*
3943 * nfs special file access vnode op.
3944 * Essentially just get vattr and then imitate iaccess() since the device is
3945 * local to the client.
3946 */
3947 static int
3948 nfsspec_access(ap)
3949 struct vop_access_args /* {
3950 struct vnode *a_vp;
3951 int a_mode;
3952 struct ucred *a_cred;
3953 struct proc *a_p;
3954 } */ *ap;
3955 {
3956 register struct vattr *vap;
3957 register gid_t *gp;
3958 register struct ucred *cred = ap->a_cred;
3959 struct vnode *vp = ap->a_vp;
3960 mode_t mode = ap->a_mode;
3961 struct vattr vattr;
3962 register int i;
3963 int error;
3964
3965 /*
3966 * Disallow write attempts on filesystems mounted read-only;
3967 * unless the file is a socket, fifo, or a block or character
3968 * device resident on the filesystem.
3969 */
3970 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3971 switch (vp->v_type) {
3972 case VREG: case VDIR: case VLNK:
3973 return (EROFS);
3974 }
3975 }
3976 /*
3977 * If you're the super-user,
3978 * you always get access.
3979 */
3980 if (cred->cr_uid == 0)
3981 return (0);
3982 vap = &vattr;
3983 error = VOP_GETATTR(vp, vap, cred, ap->a_p);
3984 if (error)
3985 return (error);
3986 /*
3987 * Access check is based on only one of owner, group, public.
3988 * If not owner, then check group. If not a member of the
3989 * group, then check public access.
3990 */
3991 if (cred->cr_uid != vap->va_uid) {
3992 mode >>= 3;
3993 gp = cred->cr_groups;
3994 for (i = 0; i < cred->cr_ngroups; i++, gp++)
3995 if (vap->va_gid == *gp)
3996 goto found;
3997 mode >>= 3;
3998 found:
3999 ;
4000 }
4001 error = (vap->va_mode & mode) == mode ? 0 : EACCES;
4002 return (error);
4003 }
4004
4005 /*
4006 * Read wrapper for special devices.
4007 */
4008 static int
4009 nfsspec_read(ap)
4010 struct vop_read_args /* {
4011 struct vnode *a_vp;
4012 struct uio *a_uio;
4013 int a_ioflag;
4014 struct ucred *a_cred;
4015 } */ *ap;
4016 {
4017 register struct nfsnode *np = VTONFS(ap->a_vp);
4018
4019 /*
4020 * Set access flag.
4021 */
4022 np->n_flag |= NACC;
4023 np->n_atim.tv_sec = time.tv_sec;
4024 np->n_atim.tv_nsec = time.tv_usec * 1000;
4025 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
4026 }
4027
4028 /*
4029 * Write wrapper for special devices.
4030 */
4031 static int
4032 nfsspec_write(ap)
4033 struct vop_write_args /* {
4034 struct vnode *a_vp;
4035 struct uio *a_uio;
4036 int a_ioflag;
4037 struct ucred *a_cred;
4038 } */ *ap;
4039 {
4040 register struct nfsnode *np = VTONFS(ap->a_vp);
4041
4042 /*
4043 * Set update flag.
4044 */
4045 np->n_flag |= NUPD;
4046 np->n_mtim.tv_sec = time.tv_sec;
4047 np->n_mtim.tv_nsec = time.tv_usec * 1000;
4048 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
4049 }
4050
4051 /*
4052 * Close wrapper for special devices.
4053 *
4054 * Update the times on the nfsnode then do device close.
4055 */
4056 static int
4057 nfsspec_close(ap)
4058 struct vop_close_args /* {
4059 struct vnode *a_vp;
4060 int a_fflag;
4061 struct ucred *a_cred;
4062 struct proc *a_p;
4063 } */ *ap;
4064 {
4065 register struct vnode *vp = ap->a_vp;
4066 register struct nfsnode *np = VTONFS(vp);
4067 struct vattr vattr;
4068
4069 if (np->n_flag & (NACC | NUPD)) {
4070 np->n_flag |= NCHG;
4071 if (vp->v_usecount == 1 &&
4072 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
4073 VATTR_NULL(&vattr);
4074 if (np->n_flag & NACC)
4075 vattr.va_atime = np->n_atim;
4076 if (np->n_flag & NUPD)
4077 vattr.va_mtime = np->n_mtim;
4078 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
4079 }
4080 }
4081 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
4082 }
4083
4084 /*
4085 * Read wrapper for fifos.
4086 */
4087 static int
4088 nfsfifo_read(ap)
4089 struct vop_read_args /* {
4090 struct vnode *a_vp;
4091 struct uio *a_uio;
4092 int a_ioflag;
4093 struct ucred *a_cred;
4094 } */ *ap;
4095 {
4096 extern vop_t **fifo_vnodeop_p;
4097 register struct nfsnode *np = VTONFS(ap->a_vp);
4098
4099 /*
4100 * Set access flag.
4101 */
4102 np->n_flag |= NACC;
4103 np->n_atim.tv_sec = time.tv_sec;
4104 np->n_atim.tv_nsec = time.tv_usec * 1000;
4105 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
4106 }
4107
4108 /*
4109 * Write wrapper for fifos.
4110 */
4111 static int
4112 nfsfifo_write(ap)
4113 struct vop_write_args /* {
4114 struct vnode *a_vp;
4115 struct uio *a_uio;
4116 int a_ioflag;
4117 struct ucred *a_cred;
4118 } */ *ap;
4119 {
4120 extern vop_t **fifo_vnodeop_p;
4121 register struct nfsnode *np = VTONFS(ap->a_vp);
4122
4123 /*
4124 * Set update flag.
4125 */
4126 np->n_flag |= NUPD;
4127 np->n_mtim.tv_sec = time.tv_sec;
4128 np->n_mtim.tv_nsec = time.tv_usec * 1000;
4129 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
4130 }
4131
4132 /*
4133 * Close wrapper for fifos.
4134 *
4135 * Update the times on the nfsnode then do fifo close.
4136 */
4137 static int
4138 nfsfifo_close(ap)
4139 struct vop_close_args /* {
4140 struct vnode *a_vp;
4141 int a_fflag;
4142 struct ucred *a_cred;
4143 struct proc *a_p;
4144 } */ *ap;
4145 {
4146 register struct vnode *vp = ap->a_vp;
4147 register struct nfsnode *np = VTONFS(vp);
4148 struct vattr vattr;
4149 extern vop_t **fifo_vnodeop_p;
4150
4151 if (np->n_flag & (NACC | NUPD)) {
4152 if (np->n_flag & NACC) {
4153 np->n_atim.tv_sec = time.tv_sec;
4154 np->n_atim.tv_nsec = time.tv_usec * 1000;
4155 }
4156 if (np->n_flag & NUPD) {
4157 np->n_mtim.tv_sec = time.tv_sec;
4158 np->n_mtim.tv_nsec = time.tv_usec * 1000;
4159 }
4160 np->n_flag |= NCHG;
4161 if (vp->v_usecount == 1 &&
4162 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
4163 VATTR_NULL(&vattr);
4164 if (np->n_flag & NACC)
4165 vattr.va_atime = np->n_atim;
4166 if (np->n_flag & NUPD)
4167 vattr.va_mtime = np->n_mtim;
4168 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
4169 }
4170 }
4171 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
4172 }
4173
4174 static int
4175 nfs_ioctl(ap)
4176 struct vop_ioctl_args *ap;
4177 {
4178
4179 /*
4180 * XXX we were once bogusly enoictl() which returned this (ENOTTY).
4181 * Probably we should return ENODEV.
4182 */
4183 return (ENOTTY);
4184 }
4185
4186 static int
4187 nfs_select(ap)
4188 struct vop_select_args *ap;
4189 {
4190
4191 /*
4192 * We were once bogusly seltrue() which returns 1. Is this right?
4193 */
4194 return (1);
4195 }
4196
4197 /* XXX Eliminate use of struct bp here */
4198 /*
4199 * Vnode op for pagein using getblk_pages
4200 * derived from nfs_bioread()
4201 * No read aheads are started from pagein operation
4202 */
4203 static int
4204 nfs_pagein(ap)
4205 struct vop_pagein_args /* {
4206 struct vnode *a_vp,
4207 upl_t a_pl,
4208 vm_offset_t a_pl_offset,
4209 off_t a_f_offset,
4210 size_t a_size,
4211 struct ucred *a_cred,
4212 int a_flags
4213 } */ *ap;
4214 {
4215 register struct vnode *vp = ap->a_vp;
4216 upl_t pl = ap->a_pl;
4217 size_t size= ap->a_size;
4218 off_t f_offset = ap->a_f_offset;
4219 vm_offset_t pl_offset = ap->a_pl_offset;
4220 int flags = ap->a_flags;
4221 struct ucred *cred;
4222 register struct nfsnode *np = VTONFS(vp);
4223 register int biosize;
4224 register int iosize;
4225 register int xsize;
4226 struct vattr vattr;
4227 struct proc *p = current_proc();
4228 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
4229 int error = 0;
4230 vm_offset_t ioaddr;
4231 struct uio auio;
4232 struct iovec aiov;
4233 struct uio * uio = &auio;
4234 int nofreeupl = flags & UPL_NOCOMMIT;
4235
4236 FSDBG(322, f_offset, size, pl, pl_offset);
4237 if (pl == (upl_t)NULL)
4238 panic("nfs_pagein: no upl");
4239
4240 if (UBCINVALID(vp)) {
4241 printf("nfs_pagein: invalid vnode 0x%x", (int)vp);
4242 if (!nofreeupl)
4243 (void) ubc_upl_abort(pl, NULL);
4244 return (EPERM);
4245 }
4246 UBCINFOCHECK("nfs_pagein", vp);
4247
4248 if (size <= 0) {
4249 printf("nfs_pagein: invalid size %d", size);
4250 if (!nofreeupl)
4251 (void) ubc_upl_abort(pl, NULL);
4252 return (EINVAL);
4253 }
4254 if (f_offset < 0 || f_offset >= np->n_size ||
4255 (f_offset & PAGE_MASK_64)) {
4256 if (!nofreeupl)
4257 ubc_upl_abort_range(pl, pl_offset, size,
4258 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
4259 return (EINVAL);
4260 }
4261 cred = ubc_getcred(vp);
4262 if (cred == NOCRED)
4263 cred = ap->a_cred;
4264
4265 auio.uio_offset = f_offset;
4266 auio.uio_segflg = UIO_SYSSPACE;
4267 auio.uio_rw = UIO_READ;
4268 auio.uio_procp = NULL;
4269
4270 if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
4271 (void)nfs_fsinfo(nmp, vp, cred, p);
4272 biosize = min(vp->v_mount->mnt_stat.f_iosize, size);
4273
4274 if (biosize & PAGE_MASK)
4275 panic("nfs_pagein(%x): biosize not page aligned", biosize);
4276
4277 ubc_upl_map(pl, &ioaddr);
4278 ioaddr += pl_offset;
4279 xsize = size;
4280
4281 do {
4282 iosize = min(biosize, xsize);
4283 uio->uio_resid = iosize;
4284 auio.uio_iov = &aiov;
4285 auio.uio_iovcnt = 1;
4286 aiov.iov_len = iosize;
4287 aiov.iov_base = (caddr_t)ioaddr;
4288
4289 FSDBG(322, uio->uio_offset, uio->uio_resid, ioaddr, xsize);
4290 #warning our nfs_pagein does not support NQNFS
4291 /*
4292 * With UBC we get here only when the file data is not in the VM
4293 * page cache, so go ahead and read in.
4294 */
4295 #ifdef UBC_DEBUG
4296 upl_ubc_alias_set(pl, current_act(), 2);
4297 #endif /* UBC_DEBUG */
4298 nfsstats.pageins++;
4299
4300 error = nfs_readrpc(vp, uio, cred);
4301
4302 if (!error) {
4303 if (uio->uio_resid) {
4304 /*
4305 * If uio_resid > 0, there is a hole in the file
4306 * and no writes after the hole have been pushed
4307 * to the server yet... or we're at the EOF
4308 * Just zero fill the rest of the valid area.
4309 */
4310 int zcnt = uio->uio_resid;
4311 int zoff = iosize - zcnt;
4312 bzero((char *)ioaddr + zoff, zcnt);
4313
4314 FSDBG(324, uio->uio_offset, zoff, zcnt, ioaddr);
4315 uio->uio_offset += zcnt;
4316 }
4317 ioaddr += iosize;
4318 xsize -= iosize;
4319 } else
4320 FSDBG(322, uio->uio_offset, uio->uio_resid, error, -1);
4321
4322 if (p && (vp->v_flag & VTEXT) &&
4323 ((nmp->nm_flag & NFSMNT_NQNFS &&
4324 NQNFS_CKINVALID(vp, np, ND_READ) &&
4325 np->n_lrev != np->n_brev) ||
4326 (!(nmp->nm_flag & NFSMNT_NQNFS) &&
4327 np->n_mtime != np->n_vattr.va_mtime.tv_sec))) {
4328 uprintf("Process killed due to text file modification\n");
4329 psignal(p, SIGKILL);
4330 p->p_flag |= P_NOSWAP;
4331 }
4332
4333 } while (error == 0 && xsize > 0);
4334
4335 ubc_upl_unmap(pl);
4336
4337 if (!nofreeupl) {
4338 if (error)
4339 ubc_upl_abort_range(pl, pl_offset, size,
4340 UPL_ABORT_ERROR |
4341 UPL_ABORT_FREE_ON_EMPTY);
4342 else
4343 ubc_upl_commit_range(pl, pl_offset, size,
4344 UPL_COMMIT_CLEAR_DIRTY |
4345 UPL_COMMIT_FREE_ON_EMPTY);
4346 }
4347 return (error);
4348 }
4349
4350
4351 /*
4352 * Vnode op for pageout using UPL
4353 * Derived from nfs_write()
4354 * File size changes are not permitted in pageout.
4355 */
4356 static int
4357 nfs_pageout(ap)
4358 struct vop_pageout_args /* {
4359 struct vnode *a_vp,
4360 upl_t a_pl,
4361 vm_offset_t a_pl_offset,
4362 off_t a_f_offset,
4363 size_t a_size,
4364 struct ucred *a_cred,
4365 int a_flags
4366 } */ *ap;
4367 {
4368 register struct vnode *vp = ap->a_vp;
4369 upl_t pl = ap->a_pl;
4370 size_t size= ap->a_size;
4371 off_t f_offset = ap->a_f_offset;
4372 vm_offset_t pl_offset = ap->a_pl_offset;
4373 int flags = ap->a_flags;
4374 int ioflag = ap->a_flags;
4375 register int biosize;
4376 struct proc *p = current_proc();
4377 struct nfsnode *np = VTONFS(vp);
4378 register struct ucred *cred;
4379 struct buf *bp;
4380 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
4381 daddr_t lbn;
4382 int n = 0, on, error = 0, iomode, must_commit, s;
4383 off_t off;
4384 vm_offset_t ioaddr;
4385 struct uio auio;
4386 struct iovec aiov;
4387 struct uio * uio = &auio;
4388 int nofreeupl = flags & UPL_NOCOMMIT;
4389 int iosize;
4390 int pgsize;
4391
4392 FSDBG(323, f_offset, size, pl, pl_offset);
4393
4394 if (pl == (upl_t)NULL)
4395 panic("nfs_pageout: no upl");
4396
4397 if (UBCINVALID(vp)) {
4398 printf("nfs_pageout: invalid vnode 0x%x", (int)vp);
4399 if (!nofreeupl)
4400 (void) ubc_upl_abort(pl, NULL);
4401 return (EIO);
4402 }
4403 UBCINFOCHECK("nfs_pageout", vp);
4404
4405 if (size <= 0) {
4406 printf("nfs_pageout: invalid size %d", size);
4407 if (!nofreeupl)
4408 (void) ubc_upl_abort(pl, NULL);
4409 return (EINVAL);
4410 }
4411
4412 /*
4413 * I use nm_rsize, not nm_wsize so that all buffer cache blocks
4414 * will be the same size within a filesystem. nfs_writerpc will
4415 * still use nm_wsize when sizing the rpc's.
4416 */
4417 biosize = min(vp->v_mount->mnt_stat.f_iosize, size);
4418
4419 if (biosize & PAGE_MASK)
4420 panic("nfs_pageout(%x): biosize not page aligned", biosize);
4421
4422 /*
4423 * Check to see whether the buffer is incore
4424 * If incore and not busy invalidate it from the cache
4425 * we should not find it BUSY, since we always do a
4426 * vm_fault_list_request in 'getblk' before returning
4427 * which would block on the page busy status
4428 */
4429 lbn = f_offset / PAGE_SIZE; /* to match the size getblk uses */
4430
4431 for (iosize = size; iosize > 0; iosize -= PAGE_SIZE, lbn++) {
4432 s = splbio();
4433 if (bp = incore(vp, lbn)) {
4434 FSDBG(323, lbn*PAGE_SIZE, 1, bp, bp->b_flags);
4435 if (ISSET(bp->b_flags, B_BUSY)) {
4436 /* no panic. just tell vm we are busy */
4437 if (!nofreeupl)
4438 (void) ubc_upl_abort(pl, NULL);
4439 return(EBUSY);
4440 }
4441 bremfree(bp);
4442 SET(bp->b_flags, (B_BUSY | B_INVAL));
4443 brelse(bp);
4444 }
4445 splx(s);
4446 }
4447
4448 cred = ubc_getcred(vp);
4449 if (cred == NOCRED)
4450 cred = ap->a_cred;
4451
4452 if (np->n_flag & NWRITEERR) {
4453 np->n_flag &= ~NWRITEERR;
4454 if (!nofreeupl)
4455 ubc_upl_abort_range(pl, pl_offset, size,
4456 UPL_ABORT_FREE_ON_EMPTY);
4457 return (np->n_error);
4458 }
4459 if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
4460 (void)nfs_fsinfo(nmp, vp, cred, p);
4461
4462 if (f_offset < 0 || f_offset >= np->n_size ||
4463 f_offset & PAGE_MASK_64 || size & PAGE_MASK) {
4464 if (!nofreeupl)
4465 ubc_upl_abort_range(pl, pl_offset, size,
4466 UPL_ABORT_FREE_ON_EMPTY);
4467 return (EINVAL);
4468 }
4469
4470 ubc_upl_map(pl, &ioaddr);
4471
4472 if (f_offset + size > np->n_size)
4473 iosize = np->n_size - f_offset;
4474 else
4475 iosize = size;
4476
4477 pgsize = (iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK;
4478
4479 if (size > pgsize) {
4480 if (!nofreeupl)
4481 ubc_upl_abort_range(pl, pl_offset + pgsize,
4482 size - pgsize,
4483 UPL_ABORT_FREE_ON_EMPTY);
4484 }
4485 auio.uio_iov = &aiov;
4486 auio.uio_iovcnt = 1;
4487 auio.uio_offset = f_offset;
4488 auio.uio_segflg = UIO_SYSSPACE;
4489 auio.uio_rw = UIO_READ;
4490 auio.uio_resid = iosize;
4491 auio.uio_procp = NULL;
4492
4493 aiov.iov_len = iosize;
4494 aiov.iov_base = (caddr_t)ioaddr + pl_offset;
4495 /*
4496 * check for partial page and clear the
4497 * contents past end of the file before
4498 * releasing it in the VM page cache
4499 */
4500 if (f_offset < np->n_size && f_offset + size > np->n_size) {
4501 size_t io = np->n_size - f_offset;
4502
4503 bzero((caddr_t)(ioaddr + pl_offset + io), size - io);
4504
4505 FSDBG(321, np->n_size, f_offset, f_offset + io, size - io);
4506 }
4507
4508 do {
4509 #warning our nfs_pageout does not support NQNFS
4510 nfsstats.pageouts++;
4511 lbn = uio->uio_offset / biosize;
4512 on = uio->uio_offset & (biosize-1);
4513 n = min((unsigned)(biosize - on), uio->uio_resid);
4514 again:
4515 #if 0
4516 /* (removed for UBC) */
4517 bufsize = biosize;
4518 if ((off_t)(lbn + 1) * biosize > np->n_size) {
4519 bufsize = np->n_size - (off_t)lbn * biosize;
4520 bufsize = (bufsize + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1);
4521 }
4522 #endif
4523 vp->v_numoutput++;
4524 /* NMODIFIED would be set here if doing unstable writes */
4525 iomode = NFSV3WRITE_FILESYNC;
4526 error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
4527 if (must_commit)
4528 nfs_clearcommit(vp->v_mount);
4529 vpwakeup(vp);
4530
4531 if (error)
4532 goto cleanup;
4533
4534 if (n > 0) {
4535 uio->uio_resid -= n;
4536 uio->uio_offset += n;
4537 uio->uio_iov->iov_base += n;
4538 uio->uio_iov->iov_len -= n;
4539 }
4540 } while (uio->uio_resid > 0 && n > 0);
4541
4542 cleanup:
4543 ubc_upl_unmap(pl);
4544 /*
4545 * We've had several different solutions on what to do when the pageout
4546 * gets an error. If we don't handle it, and return an error to the
4547 * caller, vm, it will retry . This can end in endless looping
4548 * between vm and here doing retries of the same page. Doing a dump
4549 * back to vm, will get it out of vm's knowledge and we lose whatever
4550 * data existed. This is risky, but in some cases necessary. For
4551 * example, the initial fix here was to do that for ESTALE. In that case
4552 * the server is telling us that the file is no longer the same. We
4553 * would not want to keep paging out to that. We also saw some 151
4554 * errors from Auspex server and NFSv3 can return errors higher than
4555 * ELAST. Those along with NFS known server errors we will "dump" from
4556 * vm. Errors we don't expect to occur, we dump and log for further
4557 * analysis. Errors that could be transient, networking ones,
4558 * we let vm "retry". Lastly, errors that we retry, but may have potential
4559 * to storm the network, we "retrywithsleep". "sever" will be used in
4560 * in the future to dump all pages of object for cases like ESTALE.
4561 * All this is the basis for the states returned and first guesses on
4562 * error handling. Tweaking expected as more statistics are gathered.
4563 * Note, in the long run we may need another more robust solution to
4564 * have some kind of persistant store when the vm cannot dump nor keep
4565 * retrying as a solution, but this would be a file architectural change
4566 */
4567
4568 if (!nofreeupl) { /* otherwise stacked file system has to handle this */
4569 if (error) {
4570 int abortflags;
4571 short action = nfs_pageouterrorhandler(error);
4572
4573 switch (action) {
4574 case DUMP:
4575 abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY;
4576 break;
4577 case DUMPANDLOG:
4578 abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY;
4579 if (error <= ELAST &&
4580 (errorcount[error] % 100 == 0))
4581 printf("nfs_pageout: unexpected error %d. dumping vm page\n", error);
4582 errorcount[error]++;
4583 break;
4584 case RETRY:
4585 abortflags = UPL_ABORT_FREE_ON_EMPTY;
4586 break;
4587 case RETRYWITHSLEEP:
4588 abortflags = UPL_ABORT_FREE_ON_EMPTY;
4589 /* pri unused. PSOCK for placeholder. */
4590 (void) tsleep(&lbolt, PSOCK,
4591 "nfspageout", 0);
4592 break;
4593 case SEVER: /* not implemented */
4594 default:
4595 printf("nfs_pageout: action %d not expected\n", action);
4596 break;
4597 }
4598
4599 ubc_upl_abort_range(pl, pl_offset, size, abortflags);
4600 /* return error in all cases above */
4601
4602 } else
4603 ubc_upl_commit_range(pl, pl_offset, pgsize,
4604 UPL_COMMIT_CLEAR_DIRTY |
4605 UPL_COMMIT_FREE_ON_EMPTY);
4606 }
4607 return (error);
4608 }
4609
4610 /* Blktooff derives file offset given a logical block number */
4611 static int
4612 nfs_blktooff(ap)
4613 struct vop_blktooff_args /* {
4614 struct vnode *a_vp;
4615 daddr_t a_lblkno;
4616 off_t *a_offset;
4617 } */ *ap;
4618 {
4619 int biosize;
4620 register struct vnode *vp = ap->a_vp;
4621
4622 biosize = min(vp->v_mount->mnt_stat.f_iosize, PAGE_SIZE); /* nfs_bio.c */
4623
4624 *ap->a_offset = (off_t)ap->a_lblkno * biosize;
4625
4626 return (0);
4627 }
4628
4629 static int
4630 nfs_offtoblk(ap)
4631 struct vop_offtoblk_args /* {
4632 struct vnode *a_vp;
4633 off_t a_offset;
4634 daddr_t *a_lblkno;
4635 } */ *ap;
4636 {
4637 int biosize;
4638 register struct vnode *vp = ap->a_vp;
4639
4640 biosize = min(vp->v_mount->mnt_stat.f_iosize, PAGE_SIZE); /* nfs_bio.c */
4641
4642 *ap->a_lblkno = (daddr_t)(ap->a_offset / biosize);
4643
4644 return (0);
4645 }
4646 static int
4647 nfs_cmap(ap)
4648 struct vop_cmap_args /* {
4649 struct vnode *a_vp;
4650 off_t a_offset;
4651 size_t a_size;
4652 daddr_t *a_bpn;
4653 size_t *a_run;
4654 void *a_poff;
4655 } */ *ap;
4656 {
4657 return (EOPNOTSUPP);
4658 }