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