2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
27 * Copyright (c) 1989, 1993
28 * The Regents of the University of California. All rights reserved.
30 * This code is derived from software contributed to Berkeley by
31 * Rick Macklem at The University of Guelph.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
62 * FreeBSD-Id: nfs_vnops.c,v 1.72 1997/11/07 09:20:48 phk Exp $
67 * vnode op calls for Sun NFS version 2 and 3
69 #include <sys/param.h>
70 #include <sys/kernel.h>
71 #include <sys/systm.h>
72 #include <sys/resourcevar.h>
74 #include <sys/mount.h>
76 #include <sys/malloc.h>
79 #include <sys/namei.h>
80 #include <sys/vnode.h>
81 #include <sys/dirent.h>
82 #include <sys/fcntl.h>
83 #include <sys/lockf.h>
86 #include <ufs/ufs/dir.h>
87 #include <vfs/vfs_support.h>
90 #include <machine/spl.h>
91 #include <vm/vm_pageout.h>
94 #include <kern/clock.h>
96 #include <miscfs/fifofs/fifo.h>
97 #include <miscfs/specfs/specdev.h>
99 #include <nfs/rpcv2.h>
100 #include <nfs/nfsproto.h>
102 #include <nfs/nfsnode.h>
103 #include <nfs/nfsmount.h>
104 #include <nfs/xdr_subs.h>
105 #include <nfs/nfsm_subs.h>
106 #include <nfs/nqnfs.h>
109 #include <netinet/in.h>
110 #include <netinet/in_var.h>
111 #include <vm/vm_kern.h>
113 #include <kern/task.h>
114 #include <kern/sched_prim.h>
116 #include <sys/kdebug.h>
118 #define FSDBG(A, B, C, D, E) \
119 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_NONE, \
120 (int)(B), (int)(C), (int)(D), (int)(E), 0)
121 #define FSDBG_TOP(A, B, C, D, E) \
122 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_START, \
123 (int)(B), (int)(C), (int)(D), (int)(E), 0)
124 #define FSDBG_BOT(A, B, C, D, E) \
125 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_END, \
126 (int)(B), (int)(C), (int)(D), (int)(E), 0)
131 static int nfsspec_read
__P((struct vop_read_args
*));
132 static int nfsspec_write
__P((struct vop_write_args
*));
133 static int nfsfifo_read
__P((struct vop_read_args
*));
134 static int nfsfifo_write
__P((struct vop_write_args
*));
135 static int nfsspec_close
__P((struct vop_close_args
*));
136 static int nfsfifo_close
__P((struct vop_close_args
*));
137 #define nfs_poll vop_nopoll
138 static int nfs_ioctl
__P((struct vop_ioctl_args
*));
139 static int nfs_select
__P((struct vop_select_args
*));
140 static int nfs_flush
__P((struct vnode
*,struct ucred
*,int,struct proc
*,int));
141 static int nfs_setattrrpc
__P((struct vnode
*,struct vattr
*,struct ucred
*,struct proc
*));
142 static int nfs_lookup
__P((struct vop_lookup_args
*));
143 static int nfs_create
__P((struct vop_create_args
*));
144 static int nfs_mknod
__P((struct vop_mknod_args
*));
145 static int nfs_open
__P((struct vop_open_args
*));
146 static int nfs_close
__P((struct vop_close_args
*));
147 static int nfs_access
__P((struct vop_access_args
*));
148 static int nfs_getattr
__P((struct vop_getattr_args
*));
149 static int nfs_setattr
__P((struct vop_setattr_args
*));
150 static int nfs_read
__P((struct vop_read_args
*));
151 static int nfs_mmap
__P((struct vop_mmap_args
*));
152 static int nfs_fsync
__P((struct vop_fsync_args
*));
153 static int nfs_remove
__P((struct vop_remove_args
*));
154 static int nfs_link
__P((struct vop_link_args
*));
155 static int nfs_rename
__P((struct vop_rename_args
*));
156 static int nfs_mkdir
__P((struct vop_mkdir_args
*));
157 static int nfs_rmdir
__P((struct vop_rmdir_args
*));
158 static int nfs_symlink
__P((struct vop_symlink_args
*));
159 static int nfs_readdir
__P((struct vop_readdir_args
*));
160 static int nfs_bmap
__P((struct vop_bmap_args
*));
161 static int nfs_strategy
__P((struct vop_strategy_args
*));
162 static int nfs_lookitup
__P((struct vnode
*,char *,int,struct ucred
*,struct proc
*,struct nfsnode
**));
163 static int nfs_sillyrename
__P((struct vnode
*,struct vnode
*,struct componentname
*));
164 static int nfsspec_access
__P((struct vop_access_args
*));
165 static int nfs_readlink
__P((struct vop_readlink_args
*));
166 static int nfs_print
__P((struct vop_print_args
*));
167 static int nfs_pathconf
__P((struct vop_pathconf_args
*));
168 static int nfs_advlock
__P((struct vop_advlock_args
*));
169 static int nfs_blkatoff
__P((struct vop_blkatoff_args
*));
170 static int nfs_bwrite
__P((struct vop_bwrite_args
*));
171 static int nfs_valloc
__P((struct vop_valloc_args
*));
172 static int nfs_vfree
__P((struct vop_vfree_args
*));
173 static int nfs_truncate
__P((struct vop_truncate_args
*));
174 static int nfs_update
__P((struct vop_update_args
*));
175 static int nfs_pagein
__P((struct vop_pagein_args
*));
176 static int nfs_pageout
__P((struct vop_pageout_args
*));
177 static int nfs_blktooff
__P((struct vop_blktooff_args
*));
178 static int nfs_offtoblk
__P((struct vop_offtoblk_args
*));
179 static int nfs_cmap
__P((struct vop_cmap_args
*));
182 * Global vfs data structures for nfs
184 vop_t
**nfsv2_vnodeop_p
;
185 static struct vnodeopv_entry_desc nfsv2_vnodeop_entries
[] = {
186 { &vop_default_desc
, (vop_t
*)vn_default_error
},
187 { &vop_lookup_desc
, (vop_t
*)nfs_lookup
}, /* lookup */
188 { &vop_create_desc
, (vop_t
*)nfs_create
}, /* create */
189 { &vop_mknod_desc
, (vop_t
*)nfs_mknod
}, /* mknod */
190 { &vop_open_desc
, (vop_t
*)nfs_open
}, /* open */
191 { &vop_close_desc
, (vop_t
*)nfs_close
}, /* close */
192 { &vop_access_desc
, (vop_t
*)nfs_access
}, /* access */
193 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
194 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
195 { &vop_read_desc
, (vop_t
*)nfs_read
}, /* read */
196 { &vop_write_desc
, (vop_t
*)nfs_write
}, /* write */
197 { &vop_lease_desc
, (vop_t
*)nfs_lease_check
}, /* lease */
198 { &vop_ioctl_desc
, (vop_t
*)nfs_ioctl
}, /* ioctl */
199 { &vop_select_desc
, (vop_t
*)nfs_select
}, /* select */
200 { &vop_revoke_desc
, (vop_t
*)nfs_revoke
}, /* revoke */
201 { &vop_mmap_desc
, (vop_t
*)nfs_mmap
}, /* mmap */
202 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
203 { &vop_seek_desc
, (vop_t
*)nfs_seek
}, /* seek */
204 { &vop_remove_desc
, (vop_t
*)nfs_remove
}, /* remove */
205 { &vop_link_desc
, (vop_t
*)nfs_link
}, /* link */
206 { &vop_rename_desc
, (vop_t
*)nfs_rename
}, /* rename */
207 { &vop_mkdir_desc
, (vop_t
*)nfs_mkdir
}, /* mkdir */
208 { &vop_rmdir_desc
, (vop_t
*)nfs_rmdir
}, /* rmdir */
209 { &vop_symlink_desc
, (vop_t
*)nfs_symlink
}, /* symlink */
210 { &vop_readdir_desc
, (vop_t
*)nfs_readdir
}, /* readdir */
211 { &vop_readlink_desc
, (vop_t
*)nfs_readlink
}, /* readlink */
212 { &vop_abortop_desc
, (vop_t
*)nfs_abortop
}, /* abortop */
213 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
214 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
215 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
216 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
217 { &vop_bmap_desc
, (vop_t
*)nfs_bmap
}, /* bmap */
218 { &vop_strategy_desc
, (vop_t
*)nfs_strategy
}, /* strategy */
219 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
220 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
221 { &vop_pathconf_desc
, (vop_t
*)nfs_pathconf
}, /* pathconf */
222 { &vop_advlock_desc
, (vop_t
*)nfs_advlock
}, /* advlock */
223 { &vop_blkatoff_desc
, (vop_t
*)nfs_blkatoff
}, /* blkatoff */
224 { &vop_valloc_desc
, (vop_t
*)nfs_valloc
}, /* valloc */
225 { &vop_reallocblks_desc
, (vop_t
*)nfs_reallocblks
}, /* reallocblks */
226 { &vop_vfree_desc
, (vop_t
*)nfs_vfree
}, /* vfree */
227 { &vop_truncate_desc
, (vop_t
*)nfs_truncate
}, /* truncate */
228 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
229 { &vop_bwrite_desc
, (vop_t
*)nfs_bwrite
}, /* bwrite */
230 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
231 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
232 { &vop_copyfile_desc
, (vop_t
*)err_copyfile
}, /* Copyfile */
233 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
234 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
235 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
238 struct vnodeopv_desc nfsv2_vnodeop_opv_desc
=
239 { &nfsv2_vnodeop_p
, nfsv2_vnodeop_entries
};
241 VNODEOP_SET(nfsv2_vnodeop_opv_desc
);
245 * Special device vnode ops
247 vop_t
**spec_nfsv2nodeop_p
;
248 static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries
[] = {
249 { &vop_default_desc
, (vop_t
*)vn_default_error
},
250 { &vop_lookup_desc
, (vop_t
*)spec_lookup
}, /* lookup */
251 { &vop_create_desc
, (vop_t
*)spec_create
}, /* create */
252 { &vop_mknod_desc
, (vop_t
*)spec_mknod
}, /* mknod */
253 { &vop_open_desc
, (vop_t
*)spec_open
}, /* open */
254 { &vop_close_desc
, (vop_t
*)nfsspec_close
}, /* close */
255 { &vop_access_desc
, (vop_t
*)nfsspec_access
}, /* access */
256 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
257 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
258 { &vop_read_desc
, (vop_t
*)nfsspec_read
}, /* read */
259 { &vop_write_desc
, (vop_t
*)nfsspec_write
}, /* write */
260 { &vop_lease_desc
, (vop_t
*)spec_lease_check
}, /* lease */
261 { &vop_ioctl_desc
, (vop_t
*)spec_ioctl
}, /* ioctl */
262 { &vop_select_desc
, (vop_t
*)spec_select
}, /* select */
263 { &vop_revoke_desc
, (vop_t
*)spec_revoke
}, /* revoke */
264 { &vop_mmap_desc
, (vop_t
*)spec_mmap
}, /* mmap */
265 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
266 { &vop_seek_desc
, (vop_t
*)spec_seek
}, /* seek */
267 { &vop_remove_desc
, (vop_t
*)spec_remove
}, /* remove */
268 { &vop_link_desc
, (vop_t
*)spec_link
}, /* link */
269 { &vop_rename_desc
, (vop_t
*)spec_rename
}, /* rename */
270 { &vop_mkdir_desc
, (vop_t
*)spec_mkdir
}, /* mkdir */
271 { &vop_rmdir_desc
, (vop_t
*)spec_rmdir
}, /* rmdir */
272 { &vop_symlink_desc
, (vop_t
*)spec_symlink
}, /* symlink */
273 { &vop_readdir_desc
, (vop_t
*)spec_readdir
}, /* readdir */
274 { &vop_readlink_desc
, (vop_t
*)spec_readlink
}, /* readlink */
275 { &vop_abortop_desc
, (vop_t
*)spec_abortop
}, /* abortop */
276 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
277 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
278 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
279 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
280 { &vop_bmap_desc
, (vop_t
*)spec_bmap
}, /* bmap */
281 { &vop_strategy_desc
, (vop_t
*)spec_strategy
}, /* strategy */
282 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
283 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
284 { &vop_pathconf_desc
, (vop_t
*)spec_pathconf
}, /* pathconf */
285 { &vop_advlock_desc
, (vop_t
*)spec_advlock
}, /* advlock */
286 { &vop_blkatoff_desc
, (vop_t
*)spec_blkatoff
}, /* blkatoff */
287 { &vop_valloc_desc
, (vop_t
*)spec_valloc
}, /* valloc */
288 { &vop_reallocblks_desc
, (vop_t
*)spec_reallocblks
}, /* reallocblks */
289 { &vop_vfree_desc
, (vop_t
*)spec_vfree
}, /* vfree */
290 { &vop_truncate_desc
, (vop_t
*)spec_truncate
}, /* truncate */
291 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
292 { &vop_bwrite_desc
, (vop_t
*)vn_bwrite
}, /* bwrite */
293 { &vop_devblocksize_desc
, (vop_t
*)spec_devblocksize
}, /* devblocksize */
294 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
295 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
296 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
297 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
298 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
301 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc
=
302 { &spec_nfsv2nodeop_p
, spec_nfsv2nodeop_entries
};
304 VNODEOP_SET(spec_nfsv2nodeop_opv_desc
);
307 vop_t
**fifo_nfsv2nodeop_p
;
308 static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries
[] = {
309 { &vop_default_desc
, (vop_t
*)vn_default_error
},
310 { &vop_lookup_desc
, (vop_t
*)fifo_lookup
}, /* lookup */
311 { &vop_create_desc
, (vop_t
*)fifo_create
}, /* create */
312 { &vop_mknod_desc
, (vop_t
*)fifo_mknod
}, /* mknod */
313 { &vop_open_desc
, (vop_t
*)fifo_open
}, /* open */
314 { &vop_close_desc
, (vop_t
*)nfsfifo_close
}, /* close */
315 { &vop_access_desc
, (vop_t
*)nfsspec_access
}, /* access */
316 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
317 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
318 { &vop_read_desc
, (vop_t
*)nfsfifo_read
}, /* read */
319 { &vop_write_desc
, (vop_t
*)nfsfifo_write
}, /* write */
320 { &vop_lease_desc
, (vop_t
*)fifo_lease_check
}, /* lease */
321 { &vop_ioctl_desc
, (vop_t
*)fifo_ioctl
}, /* ioctl */
322 { &vop_select_desc
, (vop_t
*)fifo_select
}, /* select */
323 { &vop_revoke_desc
, (vop_t
*)fifo_revoke
}, /* revoke */
324 { &vop_mmap_desc
, (vop_t
*)fifo_mmap
}, /* mmap */
325 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
326 { &vop_seek_desc
, (vop_t
*)fifo_seek
}, /* seek */
327 { &vop_remove_desc
, (vop_t
*)fifo_remove
}, /* remove */
328 { &vop_link_desc
, (vop_t
*)fifo_link
}, /* link */
329 { &vop_rename_desc
, (vop_t
*)fifo_rename
}, /* rename */
330 { &vop_mkdir_desc
, (vop_t
*)fifo_mkdir
}, /* mkdir */
331 { &vop_rmdir_desc
, (vop_t
*)fifo_rmdir
}, /* rmdir */
332 { &vop_symlink_desc
, (vop_t
*)fifo_symlink
}, /* symlink */
333 { &vop_readdir_desc
, (vop_t
*)fifo_readdir
}, /* readdir */
334 { &vop_readlink_desc
, (vop_t
*)fifo_readlink
}, /* readlink */
335 { &vop_abortop_desc
, (vop_t
*)fifo_abortop
}, /* abortop */
336 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
337 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
338 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
339 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
340 { &vop_bmap_desc
, (vop_t
*)fifo_bmap
}, /* bmap */
341 { &vop_strategy_desc
, (vop_t
*)fifo_strategy
}, /* strategy */
342 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
343 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
344 { &vop_pathconf_desc
, (vop_t
*)fifo_pathconf
}, /* pathconf */
345 { &vop_advlock_desc
, (vop_t
*)fifo_advlock
}, /* advlock */
346 { &vop_blkatoff_desc
, (vop_t
*)fifo_blkatoff
}, /* blkatoff */
347 { &vop_valloc_desc
, (vop_t
*)fifo_valloc
}, /* valloc */
348 { &vop_reallocblks_desc
, (vop_t
*)fifo_reallocblks
}, /* reallocblks */
349 { &vop_vfree_desc
, (vop_t
*)fifo_vfree
}, /* vfree */
350 { &vop_truncate_desc
, (vop_t
*)fifo_truncate
}, /* truncate */
351 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
352 { &vop_bwrite_desc
, (vop_t
*)vn_bwrite
}, /* bwrite */
353 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
354 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
355 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
356 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
357 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
360 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc
=
361 { &fifo_nfsv2nodeop_p
, fifo_nfsv2nodeop_entries
};
363 VNODEOP_SET(fifo_nfsv2nodeop_opv_desc
);
366 static int nfs_commit
__P((struct vnode
*vp
, u_quad_t offset
, int cnt
,
367 struct ucred
*cred
, struct proc
*procp
));
368 static int nfs_mknodrpc
__P((struct vnode
*dvp
, struct vnode
**vpp
,
369 struct componentname
*cnp
,
371 static int nfs_removerpc
__P((struct vnode
*dvp
, char *name
, int namelen
,
372 struct ucred
*cred
, struct proc
*proc
));
373 static int nfs_renamerpc
__P((struct vnode
*fdvp
, char *fnameptr
,
374 int fnamelen
, struct vnode
*tdvp
,
375 char *tnameptr
, int tnamelen
,
376 struct ucred
*cred
, struct proc
*proc
));
377 static int nfs_renameit
__P((struct vnode
*sdvp
,
378 struct componentname
*scnp
,
379 struct sillyrename
*sp
));
384 extern u_long nfs_true
, nfs_false
;
385 extern struct nfsstats nfsstats
;
386 extern nfstype nfsv3_type
[9];
387 struct proc
*nfs_iodwant
[NFS_MAXASYNCDAEMON
];
388 struct nfsmount
*nfs_iodmount
[NFS_MAXASYNCDAEMON
];
389 int nfs_numasync
= 0;
390 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
392 static int nfsaccess_cache_timeout
= NFS_MAXATTRTIMO
;
393 /* SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
394 &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
396 #define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY \
397 | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \
398 | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
402 * the following are needed only by nfs_pageout to know how to handle errors
403 * see nfs_pageout comments on explanation of actions.
404 * the errors here are copied from errno.h and errors returned by servers
405 * are expected to match the same numbers here. If not, our actions maybe
408 enum actiontype
{NOACTION
, DUMP
, DUMPANDLOG
, RETRY
, RETRYWITHSLEEP
, SEVER
};
410 static int errorcount
[ELAST
+1]; /* better be zeros when initialized */
412 static const short errortooutcome
[ELAST
+1] = {
414 DUMP
, /* EPERM 1 Operation not permitted */
415 DUMP
, /* ENOENT 2 No such file or directory */
416 DUMPANDLOG
, /* ESRCH 3 No such process */
417 RETRY
, /* EINTR 4 Interrupted system call */
418 DUMP
, /* EIO 5 Input/output error */
419 DUMP
, /* ENXIO 6 Device not configured */
420 DUMPANDLOG
, /* E2BIG 7 Argument list too long */
421 DUMPANDLOG
, /* ENOEXEC 8 Exec format error */
422 DUMPANDLOG
, /* EBADF 9 Bad file descriptor */
423 DUMPANDLOG
, /* ECHILD 10 No child processes */
424 DUMPANDLOG
, /* EDEADLK 11 Resource deadlock avoided - was EAGAIN */
425 RETRY
, /* ENOMEM 12 Cannot allocate memory */
426 DUMP
, /* EACCES 13 Permission denied */
427 DUMPANDLOG
, /* EFAULT 14 Bad address */
428 DUMPANDLOG
, /* ENOTBLK 15 POSIX - Block device required */
429 RETRY
, /* EBUSY 16 Device busy */
430 DUMP
, /* EEXIST 17 File exists */
431 DUMP
, /* EXDEV 18 Cross-device link */
432 DUMP
, /* ENODEV 19 Operation not supported by device */
433 DUMP
, /* ENOTDIR 20 Not a directory */
434 DUMP
, /* EISDIR 21 Is a directory */
435 DUMP
, /* EINVAL 22 Invalid argument */
436 DUMPANDLOG
, /* ENFILE 23 Too many open files in system */
437 DUMPANDLOG
, /* EMFILE 24 Too many open files */
438 DUMPANDLOG
, /* ENOTTY 25 Inappropriate ioctl for device */
439 DUMPANDLOG
, /* ETXTBSY 26 Text file busy - POSIX */
440 DUMP
, /* EFBIG 27 File too large */
441 DUMP
, /* ENOSPC 28 No space left on device */
442 DUMPANDLOG
, /* ESPIPE 29 Illegal seek */
443 DUMP
, /* EROFS 30 Read-only file system */
444 DUMP
, /* EMLINK 31 Too many links */
445 RETRY
, /* EPIPE 32 Broken pipe */
447 DUMPANDLOG
, /* EDOM 33 Numerical argument out of domain */
448 DUMPANDLOG
, /* ERANGE 34 Result too large */
449 RETRY
, /* EAGAIN/EWOULDBLOCK 35 Resource temporarily unavailable */
450 DUMPANDLOG
, /* EINPROGRESS 36 Operation now in progress */
451 DUMPANDLOG
, /* EALREADY 37 Operation already in progress */
452 /* ipc/network software -- argument errors */
453 DUMPANDLOG
, /* ENOTSOC 38 Socket operation on non-socket */
454 DUMPANDLOG
, /* EDESTADDRREQ 39 Destination address required */
455 DUMPANDLOG
, /* EMSGSIZE 40 Message too long */
456 DUMPANDLOG
, /* EPROTOTYPE 41 Protocol wrong type for socket */
457 DUMPANDLOG
, /* ENOPROTOOPT 42 Protocol not available */
458 DUMPANDLOG
, /* EPROTONOSUPPORT 43 Protocol not supported */
459 DUMPANDLOG
, /* ESOCKTNOSUPPORT 44 Socket type not supported */
460 DUMPANDLOG
, /* ENOTSUP 45 Operation not supported */
461 DUMPANDLOG
, /* EPFNOSUPPORT 46 Protocol family not supported */
462 DUMPANDLOG
, /* EAFNOSUPPORT 47 Address family not supported by protocol family */
463 DUMPANDLOG
, /* EADDRINUSE 48 Address already in use */
464 DUMPANDLOG
, /* EADDRNOTAVAIL 49 Can't assign requested address */
465 /* ipc/network software -- operational errors */
466 RETRY
, /* ENETDOWN 50 Network is down */
467 RETRY
, /* ENETUNREACH 51 Network is unreachable */
468 RETRY
, /* ENETRESET 52 Network dropped connection on reset */
469 RETRY
, /* ECONNABORTED 53 Software caused connection abort */
470 RETRY
, /* ECONNRESET 54 Connection reset by peer */
471 RETRY
, /* ENOBUFS 55 No buffer space available */
472 RETRY
, /* EISCONN 56 Socket is already connected */
473 RETRY
, /* ENOTCONN 57 Socket is not connected */
474 RETRY
, /* ESHUTDOWN 58 Can't send after socket shutdown */
475 RETRY
, /* ETOOMANYREFS 59 Too many references: can't splice */
476 RETRY
, /* ETIMEDOUT 60 Operation timed out */
477 RETRY
, /* ECONNREFUSED 61 Connection refused */
479 DUMPANDLOG
, /* ELOOP 62 Too many levels of symbolic links */
480 DUMP
, /* ENAMETOOLONG 63 File name too long */
481 RETRY
, /* EHOSTDOWN 64 Host is down */
482 RETRY
, /* EHOSTUNREACH 65 No route to host */
483 DUMP
, /* ENOTEMPTY 66 Directory not empty */
485 DUMPANDLOG
, /* PROCLIM 67 Too many processes */
486 DUMPANDLOG
, /* EUSERS 68 Too many users */
487 DUMPANDLOG
, /* EDQUOT 69 Disc quota exceeded */
488 /* Network File System */
489 DUMP
, /* ESTALE 70 Stale NFS file handle */
490 DUMP
, /* EREMOTE 71 Too many levels of remote in path */
491 DUMPANDLOG
, /* EBADRPC 72 RPC struct is bad */
492 DUMPANDLOG
, /* ERPCMISMATCH 73 RPC version wrong */
493 DUMPANDLOG
, /* EPROGUNAVAIL 74 RPC prog. not avail */
494 DUMPANDLOG
, /* EPROGMISMATCH 75 Program version wrong */
495 DUMPANDLOG
, /* EPROCUNAVAIL 76 Bad procedure for program */
497 DUMPANDLOG
, /* ENOLCK 77 No locks available */
498 DUMPANDLOG
, /* ENOSYS 78 Function not implemented */
499 DUMPANDLOG
, /* EFTYPE 79 Inappropriate file type or format */
500 DUMPANDLOG
, /* EAUTH 80 Authentication error */
501 DUMPANDLOG
, /* ENEEDAUTH 81 Need authenticator */
502 /* Intelligent device errors */
503 DUMPANDLOG
, /* EPWROFF 82 Device power is off */
504 DUMPANDLOG
, /* EDEVERR 83 Device error, e.g. paper out */
505 DUMPANDLOG
, /* EOVERFLOW 84 Value too large to be stored in data type */
506 /* Program loading errors */
507 DUMPANDLOG
, /* EBADEXEC 85 Bad executable */
508 DUMPANDLOG
, /* EBADARCH 86 Bad CPU type in executable */
509 DUMPANDLOG
, /* ESHLIBVERS 87 Shared library version mismatch */
510 DUMPANDLOG
, /* EBADMACHO 88 Malformed Macho file */
515 nfs_pageouterrorhandler(error
)
521 return(errortooutcome
[error
]);
525 nfs3_access_otw(struct vnode
*vp
,
532 int error
= 0, attrflag
;
534 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
535 caddr_t bpos
, dpos
, cp2
;
536 register int32_t t1
, t2
;
539 struct nfsnode
*np
= VTONFS(vp
);
542 nfsstats
.rpccnt
[NFSPROC_ACCESS
]++;
543 nfsm_reqhead(vp
, NFSPROC_ACCESS
, NFSX_FH(v3
) + NFSX_UNSIGNED
);
545 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
546 *tl
= txdr_unsigned(wmode
);
547 nfsm_request(vp
, NFSPROC_ACCESS
, p
, cred
, &xid
);
548 nfsm_postop_attr(vp
, attrflag
, &xid
);
550 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
551 rmode
= fxdr_unsigned(u_int32_t
, *tl
);
553 np
->n_modeuid
= cred
->cr_uid
;
554 np
->n_modestamp
= time_second
;
561 * nfs access vnode op.
562 * For nfs version 2, just return ok. File accesses may fail later.
563 * For nfs version 3, use the access rpc to check accessibility. If file modes
564 * are changed on the server, accesses might still fail later.
568 struct vop_access_args
/* {
571 struct ucred *a_cred;
575 register struct vnode
*vp
= ap
->a_vp
;
578 int v3
= NFS_ISV3(vp
);
579 struct nfsnode
*np
= VTONFS(vp
);
582 * For nfs v3, do an access rpc, otherwise you are stuck emulating
583 * ufs_access() locally using the vattr. This may not be correct,
584 * since the server may apply other access criteria such as
585 * client uid-->server uid mapping that we do not know about, but
586 * this is better than just returning anything that is lying about
590 if (ap
->a_mode
& VREAD
)
591 mode
= NFSV3ACCESS_READ
;
594 if (vp
->v_type
== VDIR
) {
595 if (ap
->a_mode
& VWRITE
)
596 mode
|= NFSV3ACCESS_MODIFY
|
597 NFSV3ACCESS_EXTEND
| NFSV3ACCESS_DELETE
;
598 if (ap
->a_mode
& VEXEC
)
599 mode
|= NFSV3ACCESS_LOOKUP
;
601 if (ap
->a_mode
& VWRITE
)
602 mode
|= NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
;
603 if (ap
->a_mode
& VEXEC
)
604 mode
|= NFSV3ACCESS_EXECUTE
;
606 /* XXX safety belt, only make blanket request if caching */
607 if (nfsaccess_cache_timeout
> 0) {
608 wmode
= NFSV3ACCESS_READ
| NFSV3ACCESS_MODIFY
|
609 NFSV3ACCESS_EXTEND
| NFSV3ACCESS_EXECUTE
|
610 NFSV3ACCESS_DELETE
| NFSV3ACCESS_LOOKUP
;
615 * Does our cached result allow us to give a definite yes to
618 if (time_second
< np
->n_modestamp
+ nfsaccess_cache_timeout
&&
619 ap
->a_cred
->cr_uid
== np
->n_modeuid
&&
620 (np
->n_mode
& mode
) == mode
) {
621 /* nfsstats.accesscache_hits++; */
624 * Either a no, or a don't know. Go to the wire.
626 /* nfsstats.accesscache_misses++; */
627 error
= nfs3_access_otw(vp
, wmode
, ap
->a_p
,ap
->a_cred
);
629 if ((np
->n_mode
& mode
) != mode
)
634 return (nfsspec_access(ap
)); /* NFSv2 case checks for EROFS here */
636 * Disallow write attempts on filesystems mounted read-only;
637 * unless the file is a socket, fifo, or a block or character
638 * device resident on the filesystem.
639 * CSM - moved EROFS check down per NetBSD rev 1.71. So you
640 * get the correct error value with layered filesystems.
641 * EKN - moved the return(error) below this so it does get called.
643 if (!error
&& (ap
->a_mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
644 switch (vp
->v_type
) {
645 case VREG
: case VDIR
: case VLNK
:
656 * Check to see if the type is ok
657 * and that deletion is not in progress.
658 * For paged in text files, you will need to flush the page cache
659 * if consistency is lost.
665 struct vop_open_args
/* {
668 struct ucred *a_cred;
672 register struct vnode
*vp
= ap
->a_vp
;
673 struct nfsnode
*np
= VTONFS(vp
);
674 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
678 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
&& vp
->v_type
!= VLNK
) {
682 * Get a valid lease. If cached data is stale, flush it.
684 if (nmp
->nm_flag
& NFSMNT_NQNFS
) {
685 if (NQNFS_CKINVALID(vp
, np
, ND_READ
)) {
687 error
= nqnfs_getlease(vp
, ND_READ
, ap
->a_cred
,
689 } while (error
== NQNFS_EXPIRED
);
692 if (np
->n_lrev
!= np
->n_brev
||
693 (np
->n_flag
& NQNFSNONCACHE
)) {
694 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
695 ap
->a_p
, 1)) == EINTR
)
697 np
->n_brev
= np
->n_lrev
;
701 if (np
->n_flag
& NMODIFIED
) {
702 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
703 ap
->a_p
, 1)) == EINTR
)
706 if (vp
->v_type
== VDIR
)
707 np
->n_direofoffset
= 0;
708 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
711 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
713 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
716 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
717 if (vp
->v_type
== VDIR
)
718 np
->n_direofoffset
= 0;
719 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
,
720 ap
->a_cred
, ap
->a_p
, 1)) == EINTR
)
722 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
726 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) == 0)
727 np
->n_attrstamp
= 0; /* For Open/Close consistency */
733 * What an NFS client should do upon close after writing is a debatable issue.
734 * Most NFS clients push delayed writes to the server upon close, basically for
736 * 1 - So that any write errors may be reported back to the client process
737 * doing the close system call. By far the two most likely errors are
738 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
739 * 2 - To put a worst case upper bound on cache inconsistency between
740 * multiple clients for the file.
741 * There is also a consistency problem for Version 2 of the protocol w.r.t.
742 * not being able to tell if other clients are writing a file concurrently,
743 * since there is no way of knowing if the changed modify time in the reply
744 * is only due to the write for this client.
745 * (NFS Version 3 provides weak cache consistency data in the reply that
746 * should be sufficient to detect and handle this case.)
748 * The current code does the following:
749 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
750 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
751 * or commit them (this satisfies 1 and 2 except for the
752 * case where the server crashes after this close but
753 * before the commit RPC, which is felt to be "good
754 * enough". Changing the last argument to nfs_flush() to
755 * a 1 would force a commit operation, if it is felt a
756 * commit is necessary now.
757 * for NQNFS - do nothing now, since 2 is dealt with via leases and
758 * 1 should be dealt with via an fsync() system call for
759 * cases where write errors are important.
764 struct vop_close_args
/* {
765 struct vnodeop_desc *a_desc;
768 struct ucred *a_cred;
772 register struct vnode
*vp
= ap
->a_vp
;
773 register struct nfsnode
*np
= VTONFS(vp
);
776 if (vp
->v_type
== VREG
) {
778 register struct sillyrename
*sp
= np
->n_sillyrename
;
780 kprintf("nfs_close: %s, dvp=%x, vp=%x, ap=%x, np=%x, sp=%x\n",
781 &sp
->s_name
[0], (unsigned)(sp
->s_dvp
), (unsigned)vp
,
782 (unsigned)ap
, (unsigned)np
, (unsigned)sp
);
784 if ((VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) == 0 &&
785 (np
->n_flag
& NMODIFIED
)) {
787 error
= nfs_flush(vp
, ap
->a_cred
, MNT_WAIT
, ap
->a_p
, 1);
789 * We cannot clear the NMODIFIED bit in np->n_flag due to
790 * potential races with other processes
791 * NMODIFIED is a hint
793 /* np->n_flag &= ~NMODIFIED; */
795 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
, ap
->a_p
, 1);
798 if (np
->n_flag
& NWRITEERR
) {
799 np
->n_flag
&= ~NWRITEERR
;
807 * nfs getattr call from vfs.
811 struct vop_getattr_args
/* {
814 struct ucred *a_cred;
818 register struct vnode
*vp
= ap
->a_vp
;
819 register struct nfsnode
*np
= VTONFS(vp
);
825 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
826 int v3
= NFS_ISV3(vp
);
830 FSDBG_TOP(513, np
->n_size
, np
, np
->n_vattr
.va_size
, np
->n_flag
);
832 * Update local times for special files.
834 if (np
->n_flag
& (NACC
| NUPD
))
837 * First look in the cache.
839 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0) {
840 FSDBG_BOT(513, np
->n_size
, 0, np
->n_vattr
.va_size
, np
->n_flag
);
843 if (error
!= ENOENT
) {
844 FSDBG_BOT(513, np
->n_size
, error
, np
->n_vattr
.va_size
,
850 if (v3
&& nfsaccess_cache_timeout
> 0) {
851 /* nfsstats.accesscache_misses++; */
852 if (error
= nfs3_access_otw(vp
, NFSV3ACCESS_ALL
, ap
->a_p
,
855 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0)
863 nfsstats
.rpccnt
[NFSPROC_GETATTR
]++;
864 nfsm_reqhead(vp
, NFSPROC_GETATTR
, NFSX_FH(v3
));
866 nfsm_request(vp
, NFSPROC_GETATTR
, ap
->a_p
, ap
->a_cred
, &xid
);
868 nfsm_loadattr(vp
, ap
->a_vap
, &xid
);
869 if (!xid
) { /* out-of-order rpc - attributes were dropped */
871 FSDBG(513, -1, np
, np
->n_xid
<< 32, np
->n_xid
);
872 if (avoidfloods
++ < 100)
875 * avoidfloods>1 is bizarre. at 100 pull the plug
877 panic("nfs_getattr: getattr flood\n");
879 if (np
->n_mtime
!= ap
->a_vap
->va_mtime
.tv_sec
) {
880 FSDBG(513, -1, np
, -1, vp
);
881 if (vp
->v_type
== VDIR
)
883 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
885 FSDBG(513, -1, np
, -2, error
);
887 np
->n_mtime
= ap
->a_vap
->va_mtime
.tv_sec
;
892 FSDBG_BOT(513, np
->n_size
, -1, np
->n_vattr
.va_size
, error
);
901 struct vop_setattr_args
/* {
902 struct vnodeop_desc *a_desc;
905 struct ucred *a_cred;
909 register struct vnode
*vp
= ap
->a_vp
;
910 register struct nfsnode
*np
= VTONFS(vp
);
911 register struct vattr
*vap
= ap
->a_vap
;
919 #ifdef XXX /* enable this code soon! (but test it first) */
921 * Setting of flags is not supported.
923 if (vap
->va_flags
!= VNOVAL
)
928 * Disallow write attempts if the filesystem is mounted read-only.
930 if ((vap
->va_flags
!= VNOVAL
|| vap
->va_uid
!= (uid_t
)VNOVAL
||
931 vap
->va_gid
!= (gid_t
)VNOVAL
|| vap
->va_atime
.tv_sec
!= VNOVAL
||
932 vap
->va_mtime
.tv_sec
!= VNOVAL
|| vap
->va_mode
!= (mode_t
)VNOVAL
) &&
933 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
935 if (vap
->va_size
!= VNOVAL
) {
936 switch (vp
->v_type
) {
943 if (vap
->va_mtime
.tv_sec
== VNOVAL
&&
944 vap
->va_atime
.tv_sec
== VNOVAL
&&
945 vap
->va_mode
== (u_short
)VNOVAL
&&
946 vap
->va_uid
== (uid_t
)VNOVAL
&&
947 vap
->va_gid
== (gid_t
)VNOVAL
)
949 vap
->va_size
= VNOVAL
;
953 * Disallow write attempts if the filesystem is
956 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
958 FSDBG_TOP(512, np
->n_size
, vap
->va_size
,
959 np
->n_vattr
.va_size
, np
->n_flag
);
960 if (np
->n_flag
& NMODIFIED
) {
961 if (vap
->va_size
== 0)
962 error
= nfs_vinvalbuf(vp
, 0,
963 ap
->a_cred
, ap
->a_p
, 1);
965 error
= nfs_vinvalbuf(vp
, V_SAVE
,
966 ap
->a_cred
, ap
->a_p
, 1);
968 printf("nfs_setattr: nfs_vinvalbuf %d\n", error
);
969 FSDBG_BOT(512, np
->n_size
, vap
->va_size
,
970 np
->n_vattr
.va_size
, -1);
973 } else if (np
->n_size
> vap
->va_size
) { /* shrinking? */
978 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
,
980 obn
= (np
->n_size
- 1) / biosize
;
981 bn
= vap
->va_size
/ biosize
;
982 for ( ; obn
>= bn
; obn
--)
983 if (incore(vp
, obn
)) {
984 bp
= getblk(vp
, obn
, biosize
, 0,
986 FSDBG(512, bp
, bp
->b_flags
,
988 SET(bp
->b_flags
, B_INVAL
);
993 np
->n_size
= np
->n_vattr
.va_size
= vap
->va_size
;
994 ubc_setsize(vp
, (off_t
)vap
->va_size
); /* XXX */
996 } else if ((vap
->va_mtime
.tv_sec
!= VNOVAL
||
997 vap
->va_atime
.tv_sec
!= VNOVAL
) &&
998 (np
->n_flag
& NMODIFIED
) && vp
->v_type
== VREG
&&
999 (error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
1000 ap
->a_p
, 1)) == EINTR
)
1002 error
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
1003 FSDBG_BOT(512, np
->n_size
, vap
->va_size
, np
->n_vattr
.va_size
, error
);
1004 if (error
&& vap
->va_size
!= VNOVAL
) {
1005 /* make every effort to resync file size w/ server... */
1006 int err
= 0; /* preserve "error" for return */
1008 printf("nfs_setattr: nfs_setattrrpc %d\n", error
);
1009 np
->n_size
= np
->n_vattr
.va_size
= tsize
;
1010 ubc_setsize(vp
, (off_t
)np
->n_size
); /* XXX check error */
1011 vap
->va_size
= tsize
;
1012 err
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
1014 printf("nfs_setattr1: nfs_setattrrpc %d\n", err
);
1020 * Do an nfs setattr rpc.
1023 nfs_setattrrpc(vp
, vap
, cred
, procp
)
1024 register struct vnode
*vp
;
1025 register struct vattr
*vap
;
1029 register struct nfsv2_sattr
*sp
;
1030 register caddr_t cp
;
1031 register long t1
, t2
;
1032 caddr_t bpos
, dpos
, cp2
;
1034 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
1035 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1036 int v3
= NFS_ISV3(vp
);
1039 nfsstats
.rpccnt
[NFSPROC_SETATTR
]++;
1040 nfsm_reqhead(vp
, NFSPROC_SETATTR
, NFSX_FH(v3
) + NFSX_SATTR(v3
));
1043 if (vap
->va_mode
!= (u_short
)VNOVAL
) {
1044 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1046 *tl
= txdr_unsigned(vap
->va_mode
);
1048 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1051 if (vap
->va_uid
!= (uid_t
)VNOVAL
) {
1052 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1054 *tl
= txdr_unsigned(vap
->va_uid
);
1056 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1059 if (vap
->va_gid
!= (gid_t
)VNOVAL
) {
1060 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1062 *tl
= txdr_unsigned(vap
->va_gid
);
1064 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1067 if (vap
->va_size
!= VNOVAL
) {
1068 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1070 txdr_hyper(&vap
->va_size
, tl
);
1072 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1075 if (vap
->va_atime
.tv_sec
!= VNOVAL
) {
1076 if (vap
->va_atime
.tv_sec
!= time
.tv_sec
) {
1077 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1078 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
1079 txdr_nfsv3time(&vap
->va_atime
, tl
);
1081 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1082 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
1085 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1086 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
1088 if (vap
->va_mtime
.tv_sec
!= VNOVAL
) {
1089 if (vap
->va_mtime
.tv_sec
!= time
.tv_sec
) {
1090 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1091 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
1092 txdr_nfsv3time(&vap
->va_mtime
, tl
);
1094 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1095 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
1098 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1099 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
1101 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1104 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1105 if (vap
->va_mode
== (u_short
)VNOVAL
)
1106 sp
->sa_mode
= VNOVAL
;
1108 sp
->sa_mode
= vtonfsv2_mode(vp
->v_type
, vap
->va_mode
);
1109 if (vap
->va_uid
== (uid_t
)VNOVAL
)
1110 sp
->sa_uid
= VNOVAL
;
1112 sp
->sa_uid
= txdr_unsigned(vap
->va_uid
);
1113 if (vap
->va_gid
== (gid_t
)VNOVAL
)
1114 sp
->sa_gid
= VNOVAL
;
1116 sp
->sa_gid
= txdr_unsigned(vap
->va_gid
);
1117 sp
->sa_size
= txdr_unsigned(vap
->va_size
);
1118 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1119 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1121 nfsm_request(vp
, NFSPROC_SETATTR
, procp
, cred
, &xid
);
1123 nfsm_wcc_data(vp
, wccflag
, &xid
);
1124 if (!wccflag
&& vp
->v_type
!= VBAD
) /* EINVAL on VBAD node */
1125 VTONFS(vp
)->n_attrstamp
= 0;
1127 nfsm_loadattr(vp
, (struct vattr
*)0, &xid
);
1133 * nfs lookup call, one step at a time...
1134 * First look in cache
1135 * If not found, unlock the directory nfsnode and do the rpc
1139 struct vop_lookup_args
/* {
1140 struct vnodeop_desc *a_desc;
1141 struct vnode *a_dvp;
1142 struct vnode **a_vpp;
1143 struct componentname *a_cnp;
1146 register struct componentname
*cnp
= ap
->a_cnp
;
1147 register struct vnode
*dvp
= ap
->a_dvp
;
1148 register struct vnode
**vpp
= ap
->a_vpp
;
1149 register int flags
= cnp
->cn_flags
;
1150 register struct vnode
*newvp
;
1151 register u_long
*tl
;
1152 register caddr_t cp
;
1153 register long t1
, t2
;
1154 struct nfsmount
*nmp
;
1155 caddr_t bpos
, dpos
, cp2
;
1156 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1160 int lockparent
, wantparent
, error
= 0, attrflag
, fhsize
;
1161 int v3
= NFS_ISV3(dvp
);
1162 struct proc
*p
= cnp
->cn_proc
;
1163 int worldbuildworkaround
= 1;
1166 if ((flags
& ISLASTCN
) && (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
) &&
1167 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
))
1170 if (dvp
->v_type
!= VDIR
)
1172 lockparent
= flags
& LOCKPARENT
;
1173 wantparent
= flags
& (LOCKPARENT
|WANTPARENT
);
1174 nmp
= VFSTONFS(dvp
->v_mount
);
1177 if (worldbuildworkaround
) {
1179 * Temporary workaround for world builds to not have dvp go
1180 * VBAD on during server calls in this routine. When
1181 * the real ref counting problem is found take this out.
1182 * Note if this was later and before the nfsm_request
1183 * set up, the workaround did not work (NOTE other difference
1184 * was I only put one VREF in that time. Thus it needs
1185 * to be above the cache_lookup branch or with 2 VREFS. Not
1186 * sure which. Can't play with world builds right now to see
1187 * which. VOP_ACCESS could also make it go to server. - EKN
1189 VREF(dvp
); /* hang on to this dvp - EKN */
1190 VREF(dvp
); /* hang on tight - EKN */
1193 if ((error
= cache_lookup(dvp
, vpp
, cnp
)) && error
!= ENOENT
) {
1197 if ((error
= VOP_ACCESS(dvp
, VEXEC
, cnp
->cn_cred
, p
))) {
1202 /* got to check to make sure the vnode didn't go away if access went to server */
1203 if ((*vpp
)->v_type
== VBAD
) {
1211 * See the comment starting `Step through' in ufs/ufs_lookup.c
1212 * for an explanation of the locking protocol
1217 } else if (flags
& ISDOTDOT
) {
1218 VOP_UNLOCK(dvp
, 0, p
);
1219 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1220 if (!error
&& lockparent
&& (flags
& ISLASTCN
))
1221 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1223 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1224 if (!lockparent
|| error
|| !(flags
& ISLASTCN
))
1225 VOP_UNLOCK(dvp
, 0, p
);
1228 if (vpid
== newvp
->v_id
) {
1229 if (!VOP_GETATTR(newvp
, &vattr
, cnp
->cn_cred
, p
)
1230 && vattr
.va_ctime
.tv_sec
== VTONFS(newvp
)->n_ctime
) {
1231 nfsstats
.lookupcache_hits
++;
1232 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1233 cnp
->cn_flags
|= SAVENAME
;
1234 error
= 0; /* ignore any from VOP_GETATTR */
1240 if (lockparent
&& dvp
!= newvp
&& (flags
& ISLASTCN
))
1241 VOP_UNLOCK(dvp
, 0, p
);
1243 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1250 * Got to check to make sure the vnode didn't go away if VOP_GETATTR went to server
1251 * or callers prior to this blocked and had it go VBAD.
1253 if (dvp
->v_type
== VBAD
) {
1260 nfsstats
.lookupcache_misses
++;
1261 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
1262 len
= cnp
->cn_namelen
;
1263 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
1264 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
1265 nfsm_fhtom(dvp
, v3
);
1266 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
1267 /* nfsm_request for NFSv2 causes you to goto to nfsmout upon errors */
1268 nfsm_request(dvp
, NFSPROC_LOOKUP
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
1271 nfsm_postop_attr(dvp
, attrflag
, &xid
);
1275 nfsm_getfh(fhp
, fhsize
, v3
);
1278 * Handle RENAME case...
1280 if (cnp
->cn_nameiop
== RENAME
&& wantparent
&& (flags
& ISLASTCN
)) {
1281 if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1286 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1292 u_int64_t dxid
= xid
;
1294 nfsm_postop_attr(newvp
, attrflag
, &xid
);
1295 nfsm_postop_attr(dvp
, attrflag
, &dxid
);
1297 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
1300 cnp
->cn_flags
|= SAVENAME
;
1302 VOP_UNLOCK(dvp
, 0, p
);
1307 if (flags
& ISDOTDOT
) {
1308 VOP_UNLOCK(dvp
, 0, p
);
1309 error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
);
1311 vn_lock(dvp
, LK_EXCLUSIVE
+ LK_RETRY
, p
);
1315 if (lockparent
&& (flags
& ISLASTCN
) &&
1316 (error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
))) {
1320 } else if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1324 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1328 if (!lockparent
|| !(flags
& ISLASTCN
))
1329 VOP_UNLOCK(dvp
, 0, p
);
1333 u_int64_t dxid
= xid
;
1335 nfsm_postop_attr(newvp
, attrflag
, &xid
);
1336 nfsm_postop_attr(dvp
, attrflag
, &dxid
);
1338 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
1339 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1340 cnp
->cn_flags
|= SAVENAME
;
1341 if ((cnp
->cn_flags
& MAKEENTRY
) &&
1342 (cnp
->cn_nameiop
!= DELETE
|| !(flags
& ISLASTCN
))) {
1343 np
->n_ctime
= np
->n_vattr
.va_ctime
.tv_sec
;
1344 cache_enter(dvp
, newvp
, cnp
);
1349 if (newvp
!= NULLVP
) {
1353 if ((cnp
->cn_nameiop
== CREATE
|| cnp
->cn_nameiop
== RENAME
) &&
1354 (flags
& ISLASTCN
) && error
== ENOENT
) {
1356 VOP_UNLOCK(dvp
, 0, p
);
1357 if (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
)
1360 error
= EJUSTRETURN
;
1362 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1363 cnp
->cn_flags
|= SAVENAME
;
1367 * These "vreles" set dvp refcounts back to where they were
1368 * before we took extra 2 VREFS to avoid VBAD vnode on dvp
1369 * during server calls for world builds. Remove when real
1370 * fix is found. - EKN
1372 if (worldbuildworkaround
) {
1373 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1374 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1382 * Just call nfs_bioread() to do the work.
1386 struct vop_read_args
/* {
1390 struct ucred *a_cred;
1393 register struct vnode
*vp
= ap
->a_vp
;
1395 if (vp
->v_type
!= VREG
)
1397 return (nfs_bioread(vp
, ap
->a_uio
, ap
->a_ioflag
, ap
->a_cred
, 0));
1406 struct vop_readlink_args
/* {
1409 struct ucred *a_cred;
1412 register struct vnode
*vp
= ap
->a_vp
;
1414 if (vp
->v_type
!= VLNK
)
1416 return (nfs_bioread(vp
, ap
->a_uio
, 0, ap
->a_cred
, 0));
1420 * Do a readlink rpc.
1421 * Called by nfs_doio() from below the buffer cache.
1424 nfs_readlinkrpc(vp
, uiop
, cred
)
1425 register struct vnode
*vp
;
1429 register u_long
*tl
;
1430 register caddr_t cp
;
1431 register long t1
, t2
;
1432 caddr_t bpos
, dpos
, cp2
;
1433 int error
= 0, len
, attrflag
;
1434 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1435 int v3
= NFS_ISV3(vp
);
1438 nfsstats
.rpccnt
[NFSPROC_READLINK
]++;
1439 nfsm_reqhead(vp
, NFSPROC_READLINK
, NFSX_FH(v3
));
1441 nfsm_request(vp
, NFSPROC_READLINK
, uiop
->uio_procp
, cred
, &xid
);
1443 nfsm_postop_attr(vp
, attrflag
, &xid
);
1445 nfsm_strsiz(len
, NFS_MAXPATHLEN
);
1446 if (len
== NFS_MAXPATHLEN
) {
1447 struct nfsnode
*np
= VTONFS(vp
);
1450 panic("nfs_readlinkrpc: null np");
1452 if (np
->n_size
&& np
->n_size
< NFS_MAXPATHLEN
)
1455 nfsm_mtouio(uiop
, len
);
1466 nfs_readrpc(vp
, uiop
, cred
)
1467 register struct vnode
*vp
;
1471 register u_long
*tl
;
1472 register caddr_t cp
;
1473 register long t1
, t2
;
1474 caddr_t bpos
, dpos
, cp2
;
1475 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1476 struct nfsmount
*nmp
;
1477 int error
= 0, len
, retlen
, tsiz
, eof
, attrflag
;
1478 int v3
= NFS_ISV3(vp
);
1484 nmp
= VFSTONFS(vp
->v_mount
);
1485 tsiz
= uiop
->uio_resid
;
1486 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) &&
1490 nfsstats
.rpccnt
[NFSPROC_READ
]++;
1491 len
= (tsiz
> nmp
->nm_rsize
) ? nmp
->nm_rsize
: tsiz
;
1492 nfsm_reqhead(vp
, NFSPROC_READ
, NFSX_FH(v3
) + NFSX_UNSIGNED
* 3);
1494 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
* 3);
1496 txdr_hyper(&uiop
->uio_offset
, tl
);
1497 *(tl
+ 2) = txdr_unsigned(len
);
1499 *tl
++ = txdr_unsigned(uiop
->uio_offset
);
1500 *tl
++ = txdr_unsigned(len
);
1503 nfsm_request(vp
, NFSPROC_READ
, uiop
->uio_procp
, cred
, &xid
);
1505 nfsm_postop_attr(vp
, attrflag
, &xid
);
1510 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1511 eof
= fxdr_unsigned(int, *(tl
+ 1));
1513 nfsm_loadattr(vp
, (struct vattr
*)0, &xid
);
1514 nfsm_strsiz(retlen
, nmp
->nm_rsize
);
1515 nfsm_mtouio(uiop
, retlen
);
1519 if (eof
|| retlen
== 0)
1521 } else if (retlen
< len
)
1532 nfs_writerpc(vp
, uiop
, cred
, iomode
, must_commit
)
1533 register struct vnode
*vp
;
1534 register struct uio
*uiop
;
1536 int *iomode
, *must_commit
;
1538 register u_long
*tl
;
1539 register caddr_t cp
;
1540 register int t1
, t2
, backup
;
1541 caddr_t bpos
, dpos
, cp2
;
1542 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1543 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
1544 int error
= 0, len
, tsiz
, wccflag
= NFSV3_WCCRATTR
, rlen
, commit
;
1545 int v3
= NFS_ISV3(vp
), committed
= NFSV3WRITE_FILESYNC
;
1549 if (uiop
->uio_iovcnt
!= 1)
1550 panic("nfs_writerpc: iovcnt > 1");
1553 tsiz
= uiop
->uio_resid
;
1554 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) && !v3
)
1557 nfsstats
.rpccnt
[NFSPROC_WRITE
]++;
1558 len
= (tsiz
> nmp
->nm_wsize
) ? nmp
->nm_wsize
: tsiz
;
1559 nfsm_reqhead(vp
, NFSPROC_WRITE
,
1560 NFSX_FH(v3
) + 5 * NFSX_UNSIGNED
+ nfsm_rndup(len
));
1563 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
1564 txdr_hyper(&uiop
->uio_offset
, tl
);
1566 *tl
++ = txdr_unsigned(len
);
1567 *tl
++ = txdr_unsigned(*iomode
);
1569 nfsm_build(tl
, u_long
*, 4 * NFSX_UNSIGNED
);
1570 *++tl
= txdr_unsigned(uiop
->uio_offset
);
1573 *tl
= txdr_unsigned(len
);
1574 nfsm_uiotom(uiop
, len
);
1575 nfsm_request(vp
, NFSPROC_WRITE
, uiop
->uio_procp
, cred
, &xid
);
1577 wccflag
= NFSV3_WCCCHK
;
1578 nfsm_wcc_data(vp
, wccflag
, &xid
);
1580 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
+
1582 rlen
= fxdr_unsigned(int, *tl
++);
1586 } else if (rlen
< len
) {
1587 backup
= len
- rlen
;
1588 uiop
->uio_iov
->iov_base
-= backup
;
1589 uiop
->uio_iov
->iov_len
+= backup
;
1590 uiop
->uio_offset
-= backup
;
1591 uiop
->uio_resid
+= backup
;
1594 commit
= fxdr_unsigned(int, *tl
++);
1597 * Return the lowest committment level
1598 * obtained by any of the RPCs.
1600 if (committed
== NFSV3WRITE_FILESYNC
)
1602 else if (committed
== NFSV3WRITE_DATASYNC
&&
1603 commit
== NFSV3WRITE_UNSTABLE
)
1605 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0) {
1606 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1608 nmp
->nm_flag
|= NFSMNT_HASWRITEVERF
;
1609 } else if (bcmp((caddr_t
)tl
,
1610 (caddr_t
)nmp
->nm_verf
, NFSX_V3WRITEVERF
)) {
1612 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1617 nfsm_loadattr(vp
, (struct vattr
*)0, &xid
);
1619 if (wccflag
&& vp
->v_type
!= VBAD
) /* EINVAL set on VBAD node */
1620 VTONFS(vp
)->n_mtime
= VTONFS(vp
)->n_vattr
.va_mtime
.tv_sec
;
1623 * we seem to have a case where we end up looping on shutdown
1624 * and taking down nfs servers. For V3, error cases, there is
1625 * no way to terminate loop, if the len was 0, meaning,
1626 * nmp->nm_wsize was trashed. FreeBSD has this fix in it.
1635 * does it make sense to even say it was committed if we had an error?
1636 * okay well just don't on bad vnodes then. EINVAL will be
1637 * returned on bad vnodes
1639 if (vp
->v_type
!= VBAD
&& (vp
->v_mount
->mnt_flag
& MNT_ASYNC
))
1640 committed
= NFSV3WRITE_FILESYNC
;
1641 *iomode
= committed
;
1643 uiop
->uio_resid
= tsiz
;
1649 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1650 * mode set to specify the file type and the size field for rdev.
1653 nfs_mknodrpc(dvp
, vpp
, cnp
, vap
)
1654 register struct vnode
*dvp
;
1655 register struct vnode
**vpp
;
1656 register struct componentname
*cnp
;
1657 register struct vattr
*vap
;
1659 register struct nfsv2_sattr
*sp
;
1660 register struct nfsv3_sattr
*sp3
;
1661 register u_long
*tl
;
1662 register caddr_t cp
;
1663 register long t1
, t2
;
1664 struct vnode
*newvp
= (struct vnode
*)0;
1665 struct nfsnode
*np
= (struct nfsnode
*)0;
1669 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0;
1670 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1673 int v3
= NFS_ISV3(dvp
);
1675 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
)
1676 rdev
= txdr_unsigned(vap
->va_rdev
);
1677 else if (vap
->va_type
== VFIFO
|| vap
->va_type
== VSOCK
)
1680 VOP_ABORTOP(dvp
, cnp
);
1682 return (EOPNOTSUPP
);
1684 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1685 VOP_ABORTOP(dvp
, cnp
);
1689 nfsstats
.rpccnt
[NFSPROC_MKNOD
]++;
1690 nfsm_reqhead(dvp
, NFSPROC_MKNOD
, NFSX_FH(v3
) + 4 * NFSX_UNSIGNED
+
1691 + nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1692 nfsm_fhtom(dvp
, v3
);
1693 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1695 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
+ NFSX_V3SRVSATTR
);
1696 *tl
++ = vtonfsv3_type(vap
->va_type
);
1697 sp3
= (struct nfsv3_sattr
*)tl
;
1698 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1699 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
) {
1700 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1701 *tl
++ = txdr_unsigned(major(vap
->va_rdev
));
1702 *tl
= txdr_unsigned(minor(vap
->va_rdev
));
1705 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1706 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1707 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1708 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1710 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1711 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1713 nfsm_request(dvp
, NFSPROC_MKNOD
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
1715 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
1719 newvp
= (struct vnode
*)0;
1721 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1722 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1728 nfsm_wcc_data(dvp
, wccflag
, &xid
);
1734 if (cnp
->cn_flags
& MAKEENTRY
)
1735 cache_enter(dvp
, newvp
, cnp
);
1738 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1739 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1740 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1742 VTONFS(dvp
)->n_attrstamp
= 0;
1750 * just call nfs_mknodrpc() to do the work.
1755 struct vop_mknod_args
/* {
1756 struct vnode *a_dvp;
1757 struct vnode **a_vpp;
1758 struct componentname *a_cnp;
1759 struct vattr *a_vap;
1762 struct vnode
*newvp
;
1765 error
= nfs_mknodrpc(ap
->a_dvp
, &newvp
, ap
->a_cnp
, ap
->a_vap
);
1766 if (!error
&& newvp
)
1772 static u_long create_verf
;
1774 * nfs file create call
1778 struct vop_create_args
/* {
1779 struct vnode *a_dvp;
1780 struct vnode **a_vpp;
1781 struct componentname *a_cnp;
1782 struct vattr *a_vap;
1785 register struct vnode
*dvp
= ap
->a_dvp
;
1786 register struct vattr
*vap
= ap
->a_vap
;
1787 register struct componentname
*cnp
= ap
->a_cnp
;
1788 register struct nfsv2_sattr
*sp
;
1789 register struct nfsv3_sattr
*sp3
;
1790 register u_long
*tl
;
1791 register caddr_t cp
;
1792 register long t1
, t2
;
1793 struct nfsnode
*np
= (struct nfsnode
*)0;
1794 struct vnode
*newvp
= (struct vnode
*)0;
1795 caddr_t bpos
, dpos
, cp2
;
1796 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0, fmode
= 0;
1797 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1799 int v3
= NFS_ISV3(dvp
);
1803 * Oops, not for me..
1805 if (vap
->va_type
== VSOCK
)
1806 return (nfs_mknodrpc(dvp
, ap
->a_vpp
, cnp
, vap
));
1808 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1809 VOP_ABORTOP(dvp
, cnp
);
1813 if (vap
->va_vaflags
& VA_EXCLUSIVE
)
1816 nfsstats
.rpccnt
[NFSPROC_CREATE
]++;
1817 nfsm_reqhead(dvp
, NFSPROC_CREATE
, NFSX_FH(v3
) + 2 * NFSX_UNSIGNED
+
1818 nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1819 nfsm_fhtom(dvp
, v3
);
1820 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1822 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1823 if (fmode
& O_EXCL
) {
1824 *tl
= txdr_unsigned(NFSV3CREATE_EXCLUSIVE
);
1825 nfsm_build(tl
, u_long
*, NFSX_V3CREATEVERF
);
1826 if (!TAILQ_EMPTY(&in_ifaddrhead
))
1827 *tl
++ = IA_SIN(in_ifaddrhead
.tqh_first
)->sin_addr
.s_addr
;
1829 *tl
++ = create_verf
;
1830 *tl
= ++create_verf
;
1832 *tl
= txdr_unsigned(NFSV3CREATE_UNCHECKED
);
1833 nfsm_build(tl
, u_long
*, NFSX_V3SRVSATTR
);
1834 sp3
= (struct nfsv3_sattr
*)tl
;
1835 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1838 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1839 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1840 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1841 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1843 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1844 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1846 nfsm_request(dvp
, NFSPROC_CREATE
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
1848 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
1852 newvp
= (struct vnode
*)0;
1854 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1855 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1861 nfsm_wcc_data(dvp
, wccflag
, &xid
);
1864 if (v3
&& (fmode
& O_EXCL
) && error
== NFSERR_NOTSUPP
) {
1870 } else if (v3
&& (fmode
& O_EXCL
))
1871 error
= nfs_setattrrpc(newvp
, vap
, cnp
->cn_cred
, cnp
->cn_proc
);
1873 if (cnp
->cn_flags
& MAKEENTRY
)
1874 cache_enter(dvp
, newvp
, cnp
);
1877 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1878 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1879 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1881 VTONFS(dvp
)->n_attrstamp
= 0;
1888 * nfs file remove call
1889 * To try and make nfs semantics closer to ufs semantics, a file that has
1890 * other processes using the vnode is renamed instead of removed and then
1891 * removed later on the last close.
1892 * - If v_usecount > 1
1893 * If a rename is not already in the works
1894 * call nfs_sillyrename() to set it up
1900 struct vop_remove_args
/* {
1901 struct vnodeop_desc *a_desc;
1902 struct vnode * a_dvp;
1903 struct vnode * a_vp;
1904 struct componentname * a_cnp;
1907 register struct vnode
*vp
= ap
->a_vp
;
1908 register struct vnode
*dvp
= ap
->a_dvp
;
1909 register struct componentname
*cnp
= ap
->a_cnp
;
1910 register struct nfsnode
*np
= VTONFS(vp
);
1911 int error
= 0, gofree
= 0;
1915 if ((cnp
->cn_flags
& HASBUF
) == 0)
1916 panic("nfs_remove: no name");
1917 if (vp
->v_usecount
< 1)
1918 panic("nfs_remove: bad v_usecount");
1921 if (UBCISVALID(vp
)) {
1923 if (UBCINFOEXISTS(vp
))
1924 gofree
= (ubc_isinuse(vp
, 1)) ? 0 : 1;
1926 /* dead or dying vnode.With vnode locking panic instead of error */
1927 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1933 /* UBC not in play */
1934 if (vp
->v_usecount
== 1)
1937 if (gofree
|| (np
->n_sillyrename
&&
1938 VOP_GETATTR(vp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
) == 0 &&
1939 vattr
.va_nlink
> 1)) {
1941 * Purge the name cache so that the chance of a lookup for
1942 * the name succeeding while the remove is in progress is
1943 * minimized. Without node locking it can still happen, such
1944 * that an I/O op returns ESTALE, but since you get this if
1945 * another host removes the file..
1949 * throw away biocache buffers, mainly to avoid
1950 * unnecessary delayed writes later.
1952 error
= nfs_vinvalbuf(vp
, 0, cnp
->cn_cred
, cnp
->cn_proc
, 1);
1954 ubc_setsize(vp
, (off_t
)0); /* XXX check error */
1957 error
= nfs_removerpc(dvp
, cnp
->cn_nameptr
,
1958 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
);
1960 * Kludge City: If the first reply to the remove rpc is lost..
1961 * the reply to the retransmitted request will be ENOENT
1962 * since the file was in fact removed
1963 * Therefore, we cheat and return success.
1965 if (error
== ENOENT
)
1967 } else if (!np
->n_sillyrename
) {
1968 error
= nfs_sillyrename(dvp
, vp
, cnp
);
1971 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1972 np
->n_attrstamp
= 0;
1975 VOP_UNLOCK(vp
, 0, cnp
->cn_proc
);
1983 * nfs file remove rpc called from nfs_inactive
1987 register struct sillyrename
*sp
;
1990 return (nfs_removerpc(sp
->s_dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
1995 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1998 nfs_removerpc(dvp
, name
, namelen
, cred
, proc
)
1999 register struct vnode
*dvp
;
2005 register u_long
*tl
;
2006 register caddr_t cp
;
2007 register long t1
, t2
;
2008 caddr_t bpos
, dpos
, cp2
;
2009 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2010 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2011 int v3
= NFS_ISV3(dvp
);
2014 nfsstats
.rpccnt
[NFSPROC_REMOVE
]++;
2015 nfsm_reqhead(dvp
, NFSPROC_REMOVE
,
2016 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(namelen
));
2017 nfsm_fhtom(dvp
, v3
);
2018 nfsm_strtom(name
, namelen
, NFS_MAXNAMLEN
);
2019 nfsm_request(dvp
, NFSPROC_REMOVE
, proc
, cred
, &xid
);
2021 nfsm_wcc_data(dvp
, wccflag
, &xid
);
2023 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2024 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2026 VTONFS(dvp
)->n_attrstamp
= 0;
2032 * nfs file rename call
2036 struct vop_rename_args
/* {
2037 struct vnode *a_fdvp;
2038 struct vnode *a_fvp;
2039 struct componentname *a_fcnp;
2040 struct vnode *a_tdvp;
2041 struct vnode *a_tvp;
2042 struct componentname *a_tcnp;
2045 register struct vnode
*fvp
= ap
->a_fvp
;
2046 register struct vnode
*tvp
= ap
->a_tvp
;
2047 register struct vnode
*fdvp
= ap
->a_fdvp
;
2048 register struct vnode
*tdvp
= ap
->a_tdvp
;
2049 register struct componentname
*tcnp
= ap
->a_tcnp
;
2050 register struct componentname
*fcnp
= ap
->a_fcnp
;
2051 int error
, purged
=0, inuse
=0;
2054 if ((tcnp
->cn_flags
& HASBUF
) == 0 ||
2055 (fcnp
->cn_flags
& HASBUF
) == 0)
2056 panic("nfs_rename: no name");
2058 /* Check for cross-device rename */
2059 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
2060 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
2063 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2068 * If the tvp exists and is in use, sillyrename it before doing the
2069 * rename of the new file over it.
2070 * XXX Can't sillyrename a directory.
2071 * Don't sillyrename if source and target are same vnode (hard
2072 * links or case-variants)
2074 if (tvp
&& tvp
!= fvp
) {
2075 if (UBCISVALID(tvp
)) {
2077 if (UBCINFOEXISTS(tvp
))
2078 inuse
= (ubc_isinuse(tvp
, 1)) ? 1 : 0;
2080 /* dead or dying vnode.With vnode locking panic instead of error */
2082 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2086 /* UBC not in play */
2087 if (tvp
->v_usecount
> 1)
2091 if (inuse
&& !VTONFS(tvp
)->n_sillyrename
&& tvp
->v_type
!= VDIR
) {
2092 if (error
= nfs_sillyrename(tdvp
, tvp
, tcnp
)) {
2093 /* sillyrename failed. Instead of pressing on, return error */
2094 goto out
; /* should not be ENOENT. */
2096 /* sillyrename succeeded.*/
2097 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2098 ubc_uncache(tvp
); /* get the nfs turd file to disappear */
2104 error
= nfs_renamerpc(fdvp
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
,
2105 tdvp
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
, tcnp
->cn_cred
,
2108 if (fvp
->v_type
== VDIR
) {
2109 if (tvp
!= NULL
&& tvp
->v_type
== VDIR
) {
2121 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2122 ubc_uncache(tvp
); /* get the nfs turd file to disappear */
2131 vrele(tvp
); /* already unlocked */
2135 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
2137 if (error
== ENOENT
)
2143 * nfs file rename rpc called from nfs_remove() above
2146 nfs_renameit(sdvp
, scnp
, sp
)
2148 struct componentname
*scnp
;
2149 register struct sillyrename
*sp
;
2151 return (nfs_renamerpc(sdvp
, scnp
->cn_nameptr
, scnp
->cn_namelen
,
2152 sdvp
, sp
->s_name
, sp
->s_namlen
, scnp
->cn_cred
, scnp
->cn_proc
));
2156 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
2159 nfs_renamerpc(fdvp
, fnameptr
, fnamelen
, tdvp
, tnameptr
, tnamelen
, cred
, proc
)
2160 register struct vnode
*fdvp
;
2163 register struct vnode
*tdvp
;
2169 register u_long
*tl
;
2170 register caddr_t cp
;
2171 register long t1
, t2
;
2172 caddr_t bpos
, dpos
, cp2
;
2173 int error
= 0, fwccflag
= NFSV3_WCCRATTR
, twccflag
= NFSV3_WCCRATTR
;
2174 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2175 int v3
= NFS_ISV3(fdvp
);
2178 nfsstats
.rpccnt
[NFSPROC_RENAME
]++;
2179 nfsm_reqhead(fdvp
, NFSPROC_RENAME
,
2180 (NFSX_FH(v3
) + NFSX_UNSIGNED
)*2 + nfsm_rndup(fnamelen
) +
2181 nfsm_rndup(tnamelen
));
2182 nfsm_fhtom(fdvp
, v3
);
2183 nfsm_strtom(fnameptr
, fnamelen
, NFS_MAXNAMLEN
);
2184 nfsm_fhtom(tdvp
, v3
);
2185 nfsm_strtom(tnameptr
, tnamelen
, NFS_MAXNAMLEN
);
2186 nfsm_request(fdvp
, NFSPROC_RENAME
, proc
, cred
, &xid
);
2188 u_int64_t txid
= xid
;
2190 nfsm_wcc_data(fdvp
, fwccflag
, &xid
);
2191 nfsm_wcc_data(tdvp
, twccflag
, &txid
);
2194 if (fdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2195 VTONFS(fdvp
)->n_flag
|= NMODIFIED
;
2197 VTONFS(fdvp
)->n_attrstamp
= 0;
2199 if (tdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2200 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
2202 VTONFS(tdvp
)->n_attrstamp
= 0;
2208 * nfs hard link create call
2212 struct vop_link_args
/* {
2214 struct vnode *a_tdvp;
2215 struct componentname *a_cnp;
2218 register struct vnode
*vp
= ap
->a_vp
;
2219 register struct vnode
*tdvp
= ap
->a_tdvp
;
2220 register struct componentname
*cnp
= ap
->a_cnp
;
2221 register u_long
*tl
;
2222 register caddr_t cp
;
2223 register long t1
, t2
;
2224 caddr_t bpos
, dpos
, cp2
;
2225 int error
= 0, wccflag
= NFSV3_WCCRATTR
, attrflag
= 0;
2226 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2227 int v3
= NFS_ISV3(vp
);
2230 if (vp
->v_mount
!= tdvp
->v_mount
) {
2231 VOP_ABORTOP(vp
, cnp
);
2240 * Push all writes to the server, so that the attribute cache
2241 * doesn't get "out of sync" with the server.
2242 * XXX There should be a better way!
2244 VOP_FSYNC(vp
, cnp
->cn_cred
, MNT_WAIT
, cnp
->cn_proc
);
2246 nfsstats
.rpccnt
[NFSPROC_LINK
]++;
2247 nfsm_reqhead(vp
, NFSPROC_LINK
,
2248 NFSX_FH(v3
)*2 + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2250 nfsm_fhtom(tdvp
, v3
);
2251 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2252 nfsm_request(vp
, NFSPROC_LINK
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2254 u_int64_t txid
= xid
;
2256 nfsm_postop_attr(vp
, attrflag
, &xid
);
2257 nfsm_wcc_data(tdvp
, wccflag
, &txid
);
2260 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2262 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
2263 if (!attrflag
&& vp
->v_type
!= VBAD
) /* EINVAL set on VBAD vnode */
2264 VTONFS(vp
)->n_attrstamp
= 0;
2265 if (!wccflag
&& tdvp
->v_type
!= VBAD
) /* EINVAL set on VBAD vnode */
2266 VTONFS(tdvp
)->n_attrstamp
= 0;
2269 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2271 if (error
== EEXIST
)
2277 * nfs symbolic link create call
2281 struct vop_symlink_args
/* {
2282 struct vnode *a_dvp;
2283 struct vnode **a_vpp;
2284 struct componentname *a_cnp;
2285 struct vattr *a_vap;
2289 register struct vnode
*dvp
= ap
->a_dvp
;
2290 register struct vattr
*vap
= ap
->a_vap
;
2291 register struct componentname
*cnp
= ap
->a_cnp
;
2292 register struct nfsv2_sattr
*sp
;
2293 register struct nfsv3_sattr
*sp3
;
2294 register u_long
*tl
;
2295 register caddr_t cp
;
2296 register long t1
, t2
;
2297 caddr_t bpos
, dpos
, cp2
;
2298 int slen
, error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
;
2299 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2300 struct vnode
*newvp
= (struct vnode
*)0;
2301 int v3
= NFS_ISV3(dvp
);
2304 nfsstats
.rpccnt
[NFSPROC_SYMLINK
]++;
2305 slen
= strlen(ap
->a_target
);
2306 nfsm_reqhead(dvp
, NFSPROC_SYMLINK
, NFSX_FH(v3
) + 2*NFSX_UNSIGNED
+
2307 nfsm_rndup(cnp
->cn_namelen
) + nfsm_rndup(slen
) + NFSX_SATTR(v3
));
2308 nfsm_fhtom(dvp
, v3
);
2309 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2311 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2312 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
,
2313 cnp
->cn_cred
->cr_gid
);
2315 nfsm_strtom(ap
->a_target
, slen
, NFS_MAXPATHLEN
);
2317 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2318 sp
->sa_mode
= vtonfsv2_mode(VLNK
, vap
->va_mode
);
2319 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2320 sp
->sa_gid
= txdr_unsigned(cnp
->cn_cred
->cr_gid
);
2322 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2323 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2325 nfsm_request(dvp
, NFSPROC_SYMLINK
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2327 u_int64_t dxid
= xid
;
2330 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
2331 nfsm_wcc_data(dvp
, wccflag
, &dxid
);
2336 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2337 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2338 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2340 VTONFS(dvp
)->n_attrstamp
= 0;
2344 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2346 if (error
== EEXIST
)
2356 struct vop_mkdir_args
/* {
2357 struct vnode *a_dvp;
2358 struct vnode **a_vpp;
2359 struct componentname *a_cnp;
2360 struct vattr *a_vap;
2363 register struct vnode
*dvp
= ap
->a_dvp
;
2364 register struct vattr
*vap
= ap
->a_vap
;
2365 register struct componentname
*cnp
= ap
->a_cnp
;
2366 register struct nfsv2_sattr
*sp
;
2367 register struct nfsv3_sattr
*sp3
;
2368 register u_long
*tl
;
2369 register caddr_t cp
;
2370 register long t1
, t2
;
2372 struct nfsnode
*np
= (struct nfsnode
*)0;
2373 struct vnode
*newvp
= (struct vnode
*)0;
2374 caddr_t bpos
, dpos
, cp2
;
2375 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2377 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2379 int v3
= NFS_ISV3(dvp
);
2380 u_int64_t xid
, dxid
;
2382 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
2383 VOP_ABORTOP(dvp
, cnp
);
2387 len
= cnp
->cn_namelen
;
2388 nfsstats
.rpccnt
[NFSPROC_MKDIR
]++;
2389 nfsm_reqhead(dvp
, NFSPROC_MKDIR
,
2390 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
) + NFSX_SATTR(v3
));
2391 nfsm_fhtom(dvp
, v3
);
2392 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
2394 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2395 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
2397 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2398 sp
->sa_mode
= vtonfsv2_mode(VDIR
, vap
->va_mode
);
2399 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2400 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
2402 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2403 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2405 nfsm_request(dvp
, NFSPROC_MKDIR
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2408 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
2410 nfsm_wcc_data(dvp
, wccflag
, &dxid
);
2412 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2413 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2415 VTONFS(dvp
)->n_attrstamp
= 0;
2418 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
2419 * if we can succeed in looking up the directory.
2421 if (error
== EEXIST
|| (!error
&& !gotvp
)) {
2424 newvp
= (struct vnode
*)0;
2426 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
, len
, cnp
->cn_cred
,
2430 if (newvp
->v_type
!= VDIR
)
2439 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2445 * nfs remove directory call
2449 struct vop_rmdir_args
/* {
2450 struct vnode *a_dvp;
2452 struct componentname *a_cnp;
2455 register struct vnode
*vp
= ap
->a_vp
;
2456 register struct vnode
*dvp
= ap
->a_dvp
;
2457 register struct componentname
*cnp
= ap
->a_cnp
;
2458 register u_long
*tl
;
2459 register caddr_t cp
;
2460 register long t1
, t2
;
2461 caddr_t bpos
, dpos
, cp2
;
2462 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2463 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2464 int v3
= NFS_ISV3(dvp
);
2467 nfsstats
.rpccnt
[NFSPROC_RMDIR
]++;
2468 nfsm_reqhead(dvp
, NFSPROC_RMDIR
,
2469 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2470 nfsm_fhtom(dvp
, v3
);
2471 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2472 nfsm_request(dvp
, NFSPROC_RMDIR
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2474 nfsm_wcc_data(dvp
, wccflag
, &xid
);
2476 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2477 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2478 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2480 VTONFS(dvp
)->n_attrstamp
= 0;
2487 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2489 if (error
== ENOENT
)
2499 struct vop_readdir_args
/* {
2502 struct ucred *a_cred;
2505 register struct vnode
*vp
= ap
->a_vp
;
2506 register struct nfsnode
*np
= VTONFS(vp
);
2507 register struct uio
*uio
= ap
->a_uio
;
2511 if (vp
->v_type
!= VDIR
)
2514 * First, check for hit on the EOF offset cache
2516 if (np
->n_direofoffset
> 0 && uio
->uio_offset
>= np
->n_direofoffset
&&
2517 (np
->n_flag
& NMODIFIED
) == 0) {
2518 if (VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) {
2519 if (NQNFS_CKCACHABLE(vp
, ND_READ
)) {
2520 nfsstats
.direofcache_hits
++;
2523 } else if (VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, uio
->uio_procp
) == 0 &&
2524 np
->n_mtime
== vattr
.va_mtime
.tv_sec
) {
2525 nfsstats
.direofcache_hits
++;
2531 * Call nfs_bioread() to do the real work.
2533 tresid
= uio
->uio_resid
;
2534 error
= nfs_bioread(vp
, uio
, 0, ap
->a_cred
, 0);
2536 if (!error
&& uio
->uio_resid
== tresid
)
2537 nfsstats
.direofcache_misses
++;
2543 * Called from below the buffer cache by nfs_doio().
2546 nfs_readdirrpc(vp
, uiop
, cred
)
2548 register struct uio
*uiop
;
2552 register int len
, left
;
2553 register struct dirent
*dp
;
2554 register u_long
*tl
;
2555 register caddr_t cp
;
2556 register long t1
, t2
;
2557 register nfsuint64
*cookiep
;
2558 caddr_t bpos
, dpos
, cp2
;
2559 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2561 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2562 struct nfsnode
*dnp
= VTONFS(vp
);
2564 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, bigenough
= 1;
2566 int v3
= NFS_ISV3(vp
);
2570 dp
= (struct dirent
*)0;
2573 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (NFS_DIRBLKSIZ
- 1)) ||
2574 (uiop
->uio_resid
& (NFS_DIRBLKSIZ
- 1)))
2575 panic("nfs_readdirrpc: bad uio");
2579 * If there is no cookie, assume directory was stale.
2581 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2585 return (NFSERR_BAD_COOKIE
);
2587 * Loop around doing readdir rpc's of size nm_readdirsize
2588 * truncated to a multiple of DIRBLKSIZ.
2589 * The stopping criteria is EOF or buffer full.
2591 while (more_dirs
&& bigenough
) {
2592 nfsstats
.rpccnt
[NFSPROC_READDIR
]++;
2593 nfsm_reqhead(vp
, NFSPROC_READDIR
, NFSX_FH(v3
) +
2597 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
2598 *tl
++ = cookie
.nfsuquad
[0];
2599 *tl
++ = cookie
.nfsuquad
[1];
2600 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2601 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2603 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2604 *tl
++ = cookie
.nfsuquad
[0];
2606 *tl
= txdr_unsigned(nmp
->nm_readdirsize
);
2607 nfsm_request(vp
, NFSPROC_READDIR
, uiop
->uio_procp
, cred
, &xid
);
2609 nfsm_postop_attr(vp
, attrflag
, &xid
);
2611 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2612 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2613 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
;
2619 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2620 more_dirs
= fxdr_unsigned(int, *tl
);
2622 /* loop thru the dir entries, doctoring them to 4bsd form */
2623 while (more_dirs
&& bigenough
) {
2625 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2626 fxdr_hyper(tl
, &fileno
);
2627 len
= fxdr_unsigned(int, *(tl
+ 2));
2629 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2630 fileno
= fxdr_unsigned(u_quad_t
, *tl
++);
2631 len
= fxdr_unsigned(int, *tl
);
2633 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2638 tlen
= nfsm_rndup(len
);
2640 tlen
+= 4; /* To ensure null termination */
2641 left
= DIRBLKSIZ
- blksiz
;
2642 if ((tlen
+ DIRHDSIZ
) > left
) {
2643 dp
->d_reclen
+= left
;
2644 uiop
->uio_iov
->iov_base
+= left
;
2645 uiop
->uio_iov
->iov_len
-= left
;
2646 uiop
->uio_offset
+= left
;
2647 uiop
->uio_resid
-= left
;
2650 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2653 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2654 dp
->d_fileno
= (int)fileno
;
2656 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2657 dp
->d_type
= DT_UNKNOWN
;
2658 blksiz
+= dp
->d_reclen
;
2659 if (blksiz
== DIRBLKSIZ
)
2661 uiop
->uio_offset
+= DIRHDSIZ
;
2662 uiop
->uio_resid
-= DIRHDSIZ
;
2663 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2664 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2665 nfsm_mtouio(uiop
, len
);
2666 cp
= uiop
->uio_iov
->iov_base
;
2668 *cp
= '\0'; /* null terminate */
2669 uiop
->uio_iov
->iov_base
+= tlen
;
2670 uiop
->uio_iov
->iov_len
-= tlen
;
2671 uiop
->uio_offset
+= tlen
;
2672 uiop
->uio_resid
-= tlen
;
2674 nfsm_adv(nfsm_rndup(len
));
2676 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2678 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2681 cookie
.nfsuquad
[0] = *tl
++;
2683 cookie
.nfsuquad
[1] = *tl
++;
2688 more_dirs
= fxdr_unsigned(int, *tl
);
2691 * If at end of rpc data, get the eof boolean
2694 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2695 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2700 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2701 * by increasing d_reclen for the last record.
2704 left
= DIRBLKSIZ
- blksiz
;
2705 dp
->d_reclen
+= left
;
2706 uiop
->uio_iov
->iov_base
+= left
;
2707 uiop
->uio_iov
->iov_len
-= left
;
2708 uiop
->uio_offset
+= left
;
2709 uiop
->uio_resid
-= left
;
2713 * We are now either at the end of the directory or have filled the
2717 dnp
->n_direofoffset
= uiop
->uio_offset
;
2719 if (uiop
->uio_resid
> 0)
2720 printf("EEK! readdirrpc resid > 0\n");
2721 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2729 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2732 nfs_readdirplusrpc(vp
, uiop
, cred
)
2734 register struct uio
*uiop
;
2737 register int len
, left
;
2738 register struct dirent
*dp
;
2739 register u_long
*tl
;
2740 register caddr_t cp
;
2741 register long t1
, t2
;
2742 register struct vnode
*newvp
;
2743 register nfsuint64
*cookiep
;
2744 caddr_t bpos
, dpos
, cp2
, dpossav1
, dpossav2
;
2745 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
, *mdsav1
, *mdsav2
;
2746 struct nameidata nami
, *ndp
= &nami
;
2747 struct componentname
*cnp
= &ndp
->ni_cnd
;
2749 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2750 struct nfsnode
*dnp
= VTONFS(vp
), *np
;
2753 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, doit
, bigenough
= 1, i
;
2754 int attrflag
, fhsize
;
2755 u_int64_t xid
, savexid
;
2758 dp
= (struct dirent
*)0;
2761 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (DIRBLKSIZ
- 1)) ||
2762 (uiop
->uio_resid
& (DIRBLKSIZ
- 1)))
2763 panic("nfs_readdirplusrpc: bad uio");
2769 * If there is no cookie, assume directory was stale.
2771 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2775 return (NFSERR_BAD_COOKIE
);
2777 * Loop around doing readdir rpc's of size nm_readdirsize
2778 * truncated to a multiple of DIRBLKSIZ.
2779 * The stopping criteria is EOF or buffer full.
2781 while (more_dirs
&& bigenough
) {
2782 nfsstats
.rpccnt
[NFSPROC_READDIRPLUS
]++;
2783 nfsm_reqhead(vp
, NFSPROC_READDIRPLUS
,
2784 NFSX_FH(1) + 6 * NFSX_UNSIGNED
);
2786 nfsm_build(tl
, u_long
*, 6 * NFSX_UNSIGNED
);
2787 *tl
++ = cookie
.nfsuquad
[0];
2788 *tl
++ = cookie
.nfsuquad
[1];
2789 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2790 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2791 *tl
++ = txdr_unsigned(nmp
->nm_readdirsize
);
2792 *tl
= txdr_unsigned(nmp
->nm_rsize
);
2793 nfsm_request(vp
, NFSPROC_READDIRPLUS
, uiop
->uio_procp
, cred
,
2796 nfsm_postop_attr(vp
, attrflag
, &xid
);
2801 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2802 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2803 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
++;
2804 more_dirs
= fxdr_unsigned(int, *tl
);
2806 /* loop thru the dir entries, doctoring them to 4bsd form */
2807 while (more_dirs
&& bigenough
) {
2808 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2809 fxdr_hyper(tl
, &fileno
);
2810 len
= fxdr_unsigned(int, *(tl
+ 2));
2811 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2816 tlen
= nfsm_rndup(len
);
2818 tlen
+= 4; /* To ensure null termination*/
2819 left
= DIRBLKSIZ
- blksiz
;
2820 if ((tlen
+ DIRHDSIZ
) > left
) {
2821 dp
->d_reclen
+= left
;
2822 uiop
->uio_iov
->iov_base
+= left
;
2823 uiop
->uio_iov
->iov_len
-= left
;
2824 uiop
->uio_offset
+= left
;
2825 uiop
->uio_resid
-= left
;
2828 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2831 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2832 dp
->d_fileno
= (int)fileno
;
2834 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2835 dp
->d_type
= DT_UNKNOWN
;
2836 blksiz
+= dp
->d_reclen
;
2837 if (blksiz
== DIRBLKSIZ
)
2839 uiop
->uio_offset
+= DIRHDSIZ
;
2840 uiop
->uio_resid
-= DIRHDSIZ
;
2841 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2842 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2843 cnp
->cn_nameptr
= uiop
->uio_iov
->iov_base
;
2844 cnp
->cn_namelen
= len
;
2845 nfsm_mtouio(uiop
, len
);
2846 cp
= uiop
->uio_iov
->iov_base
;
2849 uiop
->uio_iov
->iov_base
+= tlen
;
2850 uiop
->uio_iov
->iov_len
-= tlen
;
2851 uiop
->uio_offset
+= tlen
;
2852 uiop
->uio_resid
-= tlen
;
2854 nfsm_adv(nfsm_rndup(len
));
2855 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2857 cookie
.nfsuquad
[0] = *tl
++;
2858 cookie
.nfsuquad
[1] = *tl
++;
2863 * Since the attributes are before the file handle
2864 * (sigh), we must skip over the attributes and then
2865 * come back and get them.
2867 attrflag
= fxdr_unsigned(int, *tl
);
2871 nfsm_adv(NFSX_V3FATTR
);
2872 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2873 doit
= fxdr_unsigned(int, *tl
);
2875 nfsm_getfh(fhp
, fhsize
, 1);
2876 if (NFS_CMPFH(dnp
, fhp
, fhsize
)) {
2881 if ((error
= nfs_nget(vp
->v_mount
, fhp
,
2894 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
2898 IFTODT(VTTOIF(np
->n_vattr
.va_type
));
2901 for (cp
= cnp
->cn_nameptr
, i
= 1; i
<= len
;
2903 cnp
->cn_hash
+= (unsigned char)*cp
* i
;
2904 if (cnp
->cn_namelen
<= NCHNAMLEN
)
2905 cache_enter(ndp
->ni_dvp
, ndp
->ni_vp
, cnp
);
2908 /* Just skip over the file handle */
2909 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2910 i
= fxdr_unsigned(int, *tl
);
2911 nfsm_adv(nfsm_rndup(i
));
2913 if (newvp
!= NULLVP
) {
2917 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2918 more_dirs
= fxdr_unsigned(int, *tl
);
2921 * If at end of rpc data, get the eof boolean
2924 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2925 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2930 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
2931 * by increasing d_reclen for the last record.
2934 left
= DIRBLKSIZ
- blksiz
;
2935 dp
->d_reclen
+= left
;
2936 uiop
->uio_iov
->iov_base
+= left
;
2937 uiop
->uio_iov
->iov_len
-= left
;
2938 uiop
->uio_offset
+= left
;
2939 uiop
->uio_resid
-= left
;
2943 * We are now either at the end of the directory or have filled the
2947 dnp
->n_direofoffset
= uiop
->uio_offset
;
2949 if (uiop
->uio_resid
> 0)
2950 printf("EEK! readdirplusrpc resid > 0\n");
2951 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2955 if (newvp
!= NULLVP
) {
2966 * Silly rename. To make the NFS filesystem that is stateless look a little
2967 * more like the "ufs" a remove of an active vnode is translated to a rename
2968 * to a funny looking filename that is removed by nfs_inactive on the
2969 * nfsnode. There is the potential for another process on a different client
2970 * to create the same funny name between the nfs_lookitup() fails and the
2971 * nfs_rename() completes, but...
2974 nfs_sillyrename(dvp
, vp
, cnp
)
2975 struct vnode
*dvp
, *vp
;
2976 struct componentname
*cnp
;
2978 register struct sillyrename
*sp
;
2987 if (vp
->v_type
== VDIR
)
2988 panic("nfs_sillyrename: dir");
2990 MALLOC_ZONE(sp
, struct sillyrename
*,
2991 sizeof (struct sillyrename
), M_NFSREQ
, M_WAITOK
);
2992 sp
->s_cred
= crdup(cnp
->cn_cred
);
2996 /* Fudge together a funny name */
2997 pid
= cnp
->cn_proc
->p_pid
;
2998 sp
->s_namlen
= sprintf(sp
->s_name
, ".nfsA%04x4.4", pid
);
3000 /* Try lookitups until we get one that isn't there */
3001 while (nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
3002 cnp
->cn_proc
, (struct nfsnode
**)0) == 0) {
3004 if (sp
->s_name
[4] > 'z') {
3009 if ((error
= nfs_renameit(dvp
, cnp
, sp
)))
3011 error
= nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
3014 kprintf("sillyrename: %s, vp=%x, np=%x, dvp=%x\n",
3015 &sp
->s_name
[0], (unsigned)vp
, (unsigned)np
, (unsigned)dvp
);
3017 np
->n_sillyrename
= sp
;
3022 sp
->s_cred
= NOCRED
;
3024 _FREE_ZONE((caddr_t
)sp
, sizeof (struct sillyrename
), M_NFSREQ
);
3029 * Look up a file name and optionally either update the file handle or
3030 * allocate an nfsnode, depending on the value of npp.
3031 * npp == NULL --> just do the lookup
3032 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
3034 * *npp != NULL --> update the file handle in the vnode
3037 nfs_lookitup(dvp
, name
, len
, cred
, procp
, npp
)
3038 register struct vnode
*dvp
;
3043 struct nfsnode
**npp
;
3045 register u_long
*tl
;
3046 register caddr_t cp
;
3047 register long t1
, t2
;
3048 struct vnode
*newvp
= (struct vnode
*)0;
3049 struct nfsnode
*np
, *dnp
= VTONFS(dvp
);
3050 caddr_t bpos
, dpos
, cp2
;
3051 int error
= 0, fhlen
, attrflag
;
3052 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
3054 int v3
= NFS_ISV3(dvp
);
3057 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
3058 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
3059 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
3060 nfsm_fhtom(dvp
, v3
);
3061 nfsm_strtom(name
, len
, NFS_MAXNAMLEN
);
3062 nfsm_request(dvp
, NFSPROC_LOOKUP
, procp
, cred
, &xid
);
3063 if (npp
&& !error
) {
3064 nfsm_getfh(nfhp
, fhlen
, v3
);
3067 if (np
->n_fhsize
> NFS_SMALLFH
&& fhlen
<= NFS_SMALLFH
) {
3068 _FREE_ZONE((caddr_t
)np
->n_fhp
,
3069 np
->n_fhsize
, M_NFSBIGFH
);
3070 np
->n_fhp
= &np
->n_fh
;
3071 } else if (np
->n_fhsize
<= NFS_SMALLFH
&& fhlen
>NFS_SMALLFH
)
3072 MALLOC_ZONE(np
->n_fhp
, nfsfh_t
*,
3073 fhlen
, M_NFSBIGFH
, M_WAITOK
);
3074 bcopy((caddr_t
)nfhp
, (caddr_t
)np
->n_fhp
, fhlen
);
3075 np
->n_fhsize
= fhlen
;
3077 } else if (NFS_CMPFH(dnp
, nfhp
, fhlen
)) {
3081 error
= nfs_nget(dvp
->v_mount
, nfhp
, fhlen
, &np
);
3089 nfsm_postop_attr(newvp
, attrflag
, &xid
);
3090 if (!attrflag
&& *npp
== NULL
) {
3099 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
3102 if (npp
&& *npp
== NULL
) {
3116 * Nfs Version 3 commit rpc
3119 nfs_commit(vp
, offset
, cnt
, cred
, procp
)
3120 register struct vnode
*vp
;
3126 register caddr_t cp
;
3127 register u_long
*tl
;
3128 register int t1
, t2
;
3129 register struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
3130 caddr_t bpos
, dpos
, cp2
;
3131 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
3132 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
3135 FSDBG(521, vp
, offset
, cnt
, nmp
->nm_flag
);
3136 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0)
3138 nfsstats
.rpccnt
[NFSPROC_COMMIT
]++;
3139 nfsm_reqhead(vp
, NFSPROC_COMMIT
, NFSX_FH(1));
3141 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
3142 txdr_hyper(&offset
, tl
);
3144 *tl
= txdr_unsigned(cnt
);
3145 nfsm_request(vp
, NFSPROC_COMMIT
, procp
, cred
, &xid
);
3146 nfsm_wcc_data(vp
, wccflag
, &xid
);
3148 nfsm_dissect(tl
, u_long
*, NFSX_V3WRITEVERF
);
3149 if (bcmp((caddr_t
)nmp
->nm_verf
, (caddr_t
)tl
,
3150 NFSX_V3WRITEVERF
)) {
3151 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
3153 error
= NFSERR_STALEWRITEVERF
;
3162 * - make nfs_bmap() essentially a no-op that does no translation
3163 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
3164 * (Maybe I could use the process's page mapping, but I was concerned that
3165 * Kernel Write might not be enabled and also figured copyout() would do
3166 * a lot more work than bcopy() and also it currently happens in the
3167 * context of the swapper process (2).
3171 struct vop_bmap_args
/* {
3174 struct vnode **a_vpp;
3180 register struct vnode
*vp
= ap
->a_vp
;
3181 int devBlockSize
= DEV_BSIZE
;
3183 if (ap
->a_vpp
!= NULL
)
3185 if (ap
->a_bnp
!= NULL
)
3186 *ap
->a_bnp
= ap
->a_bn
* btodb(vp
->v_mount
->mnt_stat
.f_iosize
,
3188 if (ap
->a_runp
!= NULL
)
3191 if (ap
->a_runb
!= NULL
)
3199 * For async requests when nfsiod(s) are running, queue the request by
3200 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
3205 struct vop_strategy_args
*ap
;
3207 register struct buf
*bp
= ap
->a_bp
;
3212 if (ISSET(bp
->b_flags
, B_PHYS
))
3213 panic("nfs_strategy: physio");
3214 if (ISSET(bp
->b_flags
, B_ASYNC
))
3215 p
= (struct proc
*)0;
3217 p
= current_proc(); /* XXX */
3218 if (ISSET(bp
->b_flags
, B_READ
))
3223 * If the op is asynchronous and an i/o daemon is waiting
3224 * queue the request, wake it up and wait for completion
3225 * otherwise just do it ourselves.
3227 if (!ISSET(bp
->b_flags
, B_ASYNC
) || nfs_asyncio(bp
, NOCRED
))
3228 error
= nfs_doio(bp
, cr
, p
);
3235 * NB Currently unsupported.
3240 struct vop_mmap_args
/* {
3243 struct ucred *a_cred;
3252 * fsync vnode op. Just call nfs_flush() with commit == 1.
3257 struct vop_fsync_args
/* {
3258 struct vnodeop_desc *a_desc;
3259 struct vnode * a_vp;
3260 struct ucred * a_cred;
3265 return (nfs_flush(ap
->a_vp
, ap
->a_cred
, ap
->a_waitfor
, ap
->a_p
, 1));
3269 * Flush all the blocks associated with a vnode.
3270 * Walk through the buffer pool and push any dirty pages
3271 * associated with the vnode.
3274 nfs_flush(vp
, cred
, waitfor
, p
, commit
)
3275 register struct vnode
*vp
;
3281 register struct nfsnode
*np
= VTONFS(vp
);
3282 register struct buf
*bp
;
3285 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
3286 int s
, error
= 0, slptimeo
= 0, slpflag
= 0, retv
, bvecpos
, err
;
3288 u_quad_t off
, endoff
, toff
;
3289 struct ucred
* wcred
= NULL
;
3290 struct buf
**bvec
= NULL
;
3291 #ifndef NFS_COMMITBVECSIZ
3292 #define NFS_COMMITBVECSIZ 20
3294 struct buf
*bvec_on_stack
[NFS_COMMITBVECSIZ
];
3295 int bvecsize
= 0, bveccount
;
3299 FSDBG_TOP(517, vp
, np
, waitfor
, commit
);
3301 if (nmp
->nm_flag
& NFSMNT_INT
)
3307 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
3308 * server, but nas not been committed to stable storage on the server
3309 * yet. On the first pass, the byte range is worked out and the commit
3310 * rpc is done. On the second pass, nfs_writebp() is called to do the
3314 FSDBG(518, vp
->v_dirtyblkhd
.lh_first
, np
->n_flag
, 0, 0);
3315 if (vp
->v_dirtyblkhd
.lh_first
)
3316 np
->n_flag
|= NMODIFIED
;
3320 if (NFS_ISV3(vp
) && commit
) {
3323 * Count up how many buffers waiting for a commit.
3324 * This is an upper bound - any with dirty pages must be
3325 * written not commited.
3328 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3329 nbp
= bp
->b_vnbufs
.le_next
;
3330 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3331 == (B_DELWRI
| B_NEEDCOMMIT
))
3333 FSDBG(519, bp
, bp
->b_flags
, bveccount
, 0);
3336 * Allocate space to remember the list of bufs to commit. It is
3337 * important to use M_NOWAIT here to avoid a race with nfs_write
3338 * If we can't get memory (for whatever reason), we will end up
3339 * committing the buffers one-by-one in the loop below.
3341 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3342 _FREE(bvec
, M_TEMP
);
3343 if (bveccount
> NFS_COMMITBVECSIZ
) {
3344 MALLOC(bvec
, struct buf
**,
3345 bveccount
* sizeof(struct buf
*), M_TEMP
,
3348 bvec
= bvec_on_stack
;
3349 bvecsize
= NFS_COMMITBVECSIZ
;
3351 bvecsize
= bveccount
;
3353 bvec
= bvec_on_stack
;
3354 bvecsize
= NFS_COMMITBVECSIZ
;
3356 FSDBG(519, 0, bvecsize
, bveccount
, 0);
3358 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3359 nbp
= bp
->b_vnbufs
.le_next
;
3361 FSDBG(520, bp
, bp
->b_flags
, bvecpos
, bp
->b_bufsize
);
3362 FSDBG(520, bp
->b_validoff
, bp
->b_validend
,
3363 bp
->b_dirtyoff
, bp
->b_dirtyend
);
3364 if (bvecpos
>= bvecsize
)
3366 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3367 != (B_DELWRI
| B_NEEDCOMMIT
))
3371 SET(bp
->b_flags
, B_BUSY
);
3373 * we need a upl to see if the page has been
3374 * dirtied (think mmap) since the unstable write, and
3375 * so to prevent vm from paging during our commit rpc
3377 if (ISSET(bp
->b_flags
, B_PAGELIST
)) {
3378 upl
= bp
->b_pagelist
;
3380 kret
= ubc_create_upl(vp
, ubc_blktooff(vp
, bp
->b_lblkno
),
3381 bp
->b_bufsize
, &upl
,
3382 NULL
, UPL_PRECIOUS
);
3383 if (kret
!= KERN_SUCCESS
)
3384 panic("nfs_flush: create upl %d", kret
);
3386 upl_ubc_alias_set(upl
, current_act(), 1);
3387 #endif /* UBC_DEBUG */
3389 if (upl_dirty_page(ubc_upl_pageinfo(upl
), 0)) {
3390 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3391 err
= ubc_upl_abort(upl
, NULL
);
3393 printf("nfs_flush: upl abort %d\n", err
);
3396 * Any/all of it may be modified...
3398 bp
->b_dirtyoff
= bp
->b_validoff
;
3399 bp
->b_dirtyend
= bp
->b_validend
;
3400 CLR(bp
->b_flags
, B_NEEDCOMMIT
);
3401 /* blocking calls were made, re-evaluate nbp */
3402 nbp
= bp
->b_vnbufs
.le_next
;
3403 brelse(bp
); /* XXX may block. Is using nbp ok??? */
3406 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3407 bp
->b_pagelist
= upl
;
3408 SET(bp
->b_flags
, B_PAGELIST
);
3409 ubc_upl_map(upl
, (vm_address_t
*)&bp
->b_data
);
3412 /* blocking calls were made, re-evaluate nbp */
3413 nbp
= bp
->b_vnbufs
.le_next
;
3416 * Work out if all buffers are using the same cred
3417 * so we can deal with them all with one commit.
3420 wcred
= bp
->b_wcred
;
3421 else if (wcred
!= bp
->b_wcred
)
3423 SET(bp
->b_flags
, B_WRITEINPROG
);
3426 * A list of these buffers is kept so that the
3427 * second loop knows which buffers have actually
3428 * been committed. This is necessary, since there
3429 * may be a race between the commit rpc and new
3430 * uncommitted writes on the file.
3432 bvec
[bvecpos
++] = bp
;
3433 toff
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3437 toff
+= (u_quad_t
)(bp
->b_dirtyend
- bp
->b_dirtyoff
);
3445 * Commit data on the server, as required.
3446 * If all bufs are using the same wcred, then use that with
3447 * one call for all of them, otherwise commit each one
3450 if (wcred
!= NOCRED
)
3451 retv
= nfs_commit(vp
, off
, (int)(endoff
- off
),
3455 for (i
= 0; i
< bvecpos
; i
++) {
3458 FSDBG(522, bp
, bp
->b_blkno
* DEV_BSIZE
,
3459 bp
->b_dirtyoff
, bp
->b_dirtyend
);
3460 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3462 size
= (u_quad_t
)(bp
->b_dirtyend
3464 retv
= nfs_commit(vp
, off
, (int)size
,
3470 if (retv
== NFSERR_STALEWRITEVERF
)
3471 nfs_clearcommit(vp
->v_mount
);
3474 * Now, either mark the blocks I/O done or mark the
3475 * blocks dirty, depending on whether the commit
3478 for (i
= 0; i
< bvecpos
; i
++) {
3480 FSDBG(523, bp
, retv
, bp
->b_flags
, 0);
3481 CLR(bp
->b_flags
, (B_NEEDCOMMIT
| B_WRITEINPROG
));
3485 int oldflags
= bp
->b_flags
;
3489 SET(bp
->b_flags
, B_ASYNC
);
3491 (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3492 if (ISSET(oldflags
, B_DELWRI
)) {
3493 extern int nbdwrite
;
3495 wakeup((caddr_t
)&nbdwrite
);
3497 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3498 reassignbuf(bp
, vp
);
3506 * Start/do any write(s) that are required. There is a window here
3507 * where B_BUSY protects the buffer. The vm pages have been freed up,
3508 * yet B_BUSY is set. Don't think you will hit any busy/incore problems
3509 * while we sleep, but not absolutely sure. Keep an eye on it. Otherwise
3510 * we will have to hold vm page across this locked. - EKN
3513 if (current_thread_aborted()) {
3518 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3519 nbp
= bp
->b_vnbufs
.le_next
;
3520 if (ISSET(bp
->b_flags
, B_BUSY
)) {
3521 FSDBG(524, bp
, waitfor
, passone
, bp
->b_flags
);
3522 if (waitfor
!= MNT_WAIT
|| passone
)
3524 SET(bp
->b_flags
, B_WANTED
);
3525 error
= tsleep((caddr_t
)bp
, slpflag
| (PRIBIO
+ 1),
3526 "nfsfsync", slptimeo
);
3529 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3533 if (slpflag
== PCATCH
) {
3540 if (!ISSET(bp
->b_flags
, B_DELWRI
))
3541 panic("nfs_fsync: not dirty");
3542 FSDBG(525, bp
, passone
, commit
, bp
->b_flags
);
3543 if ((passone
|| !commit
) && ISSET(bp
->b_flags
, B_NEEDCOMMIT
))
3546 if (passone
|| !commit
)
3547 SET(bp
->b_flags
, B_BUSY
|B_ASYNC
);
3550 B_BUSY
|B_ASYNC
|B_WRITEINPROG
|B_NEEDCOMMIT
);
3560 if (waitfor
== MNT_WAIT
) {
3561 while (vp
->v_numoutput
) {
3562 vp
->v_flag
|= VBWAIT
;
3563 error
= tsleep((caddr_t
)&vp
->v_numoutput
,
3564 slpflag
| (PRIBIO
+ 1), "nfsfsync", slptimeo
);
3566 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3570 if (slpflag
== PCATCH
) {
3576 if (vp
->v_dirtyblkhd
.lh_first
&& commit
) {
3580 FSDBG(526, np
->n_flag
, np
->n_error
, 0, 0);
3581 if (np
->n_flag
& NWRITEERR
) {
3582 error
= np
->n_error
;
3583 np
->n_flag
&= ~NWRITEERR
;
3586 FSDBG_BOT(517, vp
, np
, error
, 0);
3587 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3588 _FREE(bvec
, M_TEMP
);
3593 * Return POSIX pathconf information applicable to nfs.
3595 * The NFS V2 protocol doesn't support this, so just return EINVAL
3601 struct vop_pathconf_args
/* {
3612 * NFS advisory byte-level locks.
3613 * Currently unsupported.
3617 struct vop_advlock_args
/* {
3626 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3629 * The following kludge is to allow diskless support to work
3630 * until a real NFS lockd is implemented. Basically, just pretend
3631 * that this is a local lock.
3633 return (lf_advlock(ap
, &(np
->n_lockf
), np
->n_size
));
3636 printf("nfs_advlock: pid %d comm %s\n", current_proc()->p_pid
, current_proc()->p_comm
);
3638 return (EOPNOTSUPP
);
3643 * Print out the contents of an nfsnode.
3647 struct vop_print_args
/* {
3651 register struct vnode
*vp
= ap
->a_vp
;
3652 register struct nfsnode
*np
= VTONFS(vp
);
3654 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
3655 np
->n_vattr
.va_fileid
, np
->n_vattr
.va_fsid
);
3656 if (vp
->v_type
== VFIFO
)
3663 * NFS directory offset lookup.
3664 * Currently unsupported.
3668 struct vop_blkatoff_args
/* {
3677 printf("nfs_blkatoff: unimplemented!!");
3679 return (EOPNOTSUPP
);
3683 * NFS flat namespace allocation.
3684 * Currently unsupported.
3688 struct vop_valloc_args
/* {
3689 struct vnode *a_pvp;
3691 struct ucred *a_cred;
3692 struct vnode **a_vpp;
3696 return (EOPNOTSUPP
);
3700 * NFS flat namespace free.
3701 * Currently unsupported.
3705 struct vop_vfree_args
/* {
3706 struct vnode *a_pvp;
3713 printf("nfs_vfree: unimplemented!!");
3715 return (EOPNOTSUPP
);
3719 * NFS file truncation.
3723 struct vop_truncate_args
/* {
3727 struct ucred *a_cred;
3732 /* Use nfs_setattr */
3734 printf("nfs_truncate: unimplemented!!");
3736 return (EOPNOTSUPP
);
3744 struct vop_update_args
/* {
3746 struct timeval *a_ta;
3747 struct timeval *a_tm;
3752 /* Use nfs_setattr */
3754 printf("nfs_update: unimplemented!!");
3756 return (EOPNOTSUPP
);
3759 int nfs_aio_threads
= 0; /* 1 per nfd (arbitrary) */
3760 struct slock nfs_aio_slock
;
3761 TAILQ_HEAD(bqueues
, buf
) nfs_aio_bufq
;
3762 int nfs_aio_bufq_len
= 0; /* diagnostic only */
3766 { /* see comment below in nfs_bwrite() for some rationale */
3768 boolean_t funnel_state
;
3770 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
3772 simple_lock(&nfs_aio_slock
);
3773 if ((bp
= nfs_aio_bufq
.tqh_first
)) {
3774 TAILQ_REMOVE(&nfs_aio_bufq
, bp
, b_freelist
);
3776 simple_unlock(&nfs_aio_slock
);
3778 } else { /* nothing to do - goodnight */
3779 assert_wait(&nfs_aio_bufq
, THREAD_UNINT
);
3780 simple_unlock(&nfs_aio_slock
);
3781 (void)tsleep((caddr_t
)0, PRIBIO
+1, "nfs_aio_bufq", 0);
3784 (void) thread_funnel_set(kernel_flock
, FALSE
);
3789 nfs_aio_thread_init()
3791 if (nfs_aio_threads
++ == 0) {
3792 simple_lock_init(&nfs_aio_slock
);
3793 TAILQ_INIT(&nfs_aio_bufq
);
3795 kernel_thread(kernel_task
, nfs_aio_thread
);
3800 * Just call nfs_writebp() with the force argument set to 1.
3804 struct vop_bwrite_args
/* {
3808 extern void wakeup_one(caddr_t chan
);
3811 * nfs_writebp will issue a synchronous rpc to if B_ASYNC then
3812 * to avoid distributed deadlocks we handoff the write to the
3813 * nfs_aio threads. Doing so allows us to complete the
3814 * current request, rather than blocking on a server which may
3815 * be ourself (or blocked on ourself).
3817 * Note the loopback deadlocks happened when the thread
3818 * invoking us was nfsd, and also when it was the pagedaemon.
3820 * This solution has one known problem. If *ALL* buffers get
3821 * on the nfs_aio queue then no forward progress can be made
3822 * until one of those writes complete. And if the current
3823 * nfs_aio writes-in-progress block due to a non-responsive server we
3824 * are in a deadlock circle. Probably the cure is to limit the
3825 * async write concurrency in getnewbuf as in FreeBSD 3.2.
3827 if (nfs_aio_threads
&& ISSET(ap
->a_bp
->b_flags
, B_ASYNC
)) {
3828 simple_lock(&nfs_aio_slock
);
3830 TAILQ_INSERT_TAIL(&nfs_aio_bufq
, ap
->a_bp
, b_freelist
);
3831 simple_unlock(&nfs_aio_slock
);
3832 wakeup_one((caddr_t
)&nfs_aio_bufq
);
3835 return (nfs_writebp(ap
->a_bp
, 1));
3839 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless
3840 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
3843 nfs_writebp(bp
, force
)
3844 register struct buf
*bp
;
3848 register int oldflags
= bp
->b_flags
, retv
= 1;
3852 struct vnode
*vp
= bp
->b_vp
;
3853 upl_page_info_t
*pl
;
3855 if(!ISSET(bp
->b_flags
, B_BUSY
))
3856 panic("nfs_writebp: buffer is not busy???");
3859 CLR(bp
->b_flags
, (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3860 if (ISSET(oldflags
, B_DELWRI
)) {
3861 extern int nbdwrite
;
3863 wakeup((caddr_t
)&nbdwrite
);
3866 if (ISSET(oldflags
, (B_ASYNC
|B_DELWRI
))) {
3867 reassignbuf(bp
, vp
);
3871 current_proc()->p_stats
->p_ru
.ru_oublock
++;
3875 * Since the B_BUSY flag is set, we need to lock the page before doing
3876 * nfs_commit. Otherwise we may block and get a busy incore pages
3877 * during a vm pageout. Move the existing code up before the commit.
3879 if (!ISSET(bp
->b_flags
, B_META
) && UBCISVALID(vp
) &&
3880 !ISSET(bp
->b_flags
, B_PAGELIST
)) {
3881 kret
= ubc_create_upl(vp
, ubc_blktooff(vp
, bp
->b_lblkno
),
3882 bp
->b_bufsize
, &upl
, &pl
, UPL_PRECIOUS
);
3883 if (kret
!= KERN_SUCCESS
)
3884 panic("nfs_writebp: ubc_create_upl %d", kret
);
3886 upl_ubc_alias_set(upl
, current_act(), 2);
3887 #endif /* UBC_DEBUG */
3889 bp
->b_pagelist
= upl
;
3890 SET(bp
->b_flags
, B_PAGELIST
);
3893 kret
= ubc_upl_map(upl
, (vm_address_t
*)&(bp
->b_data
));
3894 if (kret
!= KERN_SUCCESS
)
3895 panic("nfs_writebp: ubc_upl_map %d", kret
);
3897 panic("nfs_writebp: ubc_upl_map mapped 0");
3898 if (!upl_page_present(pl
, 0)) /* even more paranoia */
3899 panic("nfs_writebp: nopage");
3903 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3904 * an actual write will have to be scheduled via. VOP_STRATEGY().
3905 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3907 if ((oldflags
& (B_NEEDCOMMIT
| B_WRITEINPROG
)) == B_NEEDCOMMIT
) {
3908 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+ bp
->b_dirtyoff
;
3909 SET(bp
->b_flags
, B_WRITEINPROG
);
3910 retv
= nfs_commit(vp
, off
, bp
->b_dirtyend
-bp
->b_dirtyoff
,
3911 bp
->b_wcred
, bp
->b_proc
);
3912 CLR(bp
->b_flags
, B_WRITEINPROG
);
3914 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3915 CLR(bp
->b_flags
, B_NEEDCOMMIT
);
3916 biodone(bp
); /* on B_ASYNC will brelse the buffer */
3918 } else if (retv
== NFSERR_STALEWRITEVERF
)
3919 nfs_clearcommit(vp
->v_mount
);
3923 SET(bp
->b_flags
, B_WRITEINPROG
);
3927 if( (oldflags
& B_ASYNC
) == 0) {
3928 int rtval
= biowait(bp
);
3930 if (oldflags
& B_DELWRI
) {
3932 reassignbuf(bp
, vp
);
3943 * nfs special file access vnode op.
3944 * Essentially just get vattr and then imitate iaccess() since the device is
3945 * local to the client.
3949 struct vop_access_args
/* {
3952 struct ucred *a_cred;
3956 register struct vattr
*vap
;
3958 register struct ucred
*cred
= ap
->a_cred
;
3959 struct vnode
*vp
= ap
->a_vp
;
3960 mode_t mode
= ap
->a_mode
;
3966 * Disallow write attempts on filesystems mounted read-only;
3967 * unless the file is a socket, fifo, or a block or character
3968 * device resident on the filesystem.
3970 if ((mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
3971 switch (vp
->v_type
) {
3972 case VREG
: case VDIR
: case VLNK
:
3977 * If you're the super-user,
3978 * you always get access.
3980 if (cred
->cr_uid
== 0)
3983 error
= VOP_GETATTR(vp
, vap
, cred
, ap
->a_p
);
3987 * Access check is based on only one of owner, group, public.
3988 * If not owner, then check group. If not a member of the
3989 * group, then check public access.
3991 if (cred
->cr_uid
!= vap
->va_uid
) {
3993 gp
= cred
->cr_groups
;
3994 for (i
= 0; i
< cred
->cr_ngroups
; i
++, gp
++)
3995 if (vap
->va_gid
== *gp
)
4001 error
= (vap
->va_mode
& mode
) == mode
? 0 : EACCES
;
4006 * Read wrapper for special devices.
4010 struct vop_read_args
/* {
4014 struct ucred *a_cred;
4017 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4023 np
->n_atim
.tv_sec
= time
.tv_sec
;
4024 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
4025 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_read
), ap
));
4029 * Write wrapper for special devices.
4033 struct vop_write_args
/* {
4037 struct ucred *a_cred;
4040 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4046 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4047 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4048 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_write
), ap
));
4052 * Close wrapper for special devices.
4054 * Update the times on the nfsnode then do device close.
4058 struct vop_close_args
/* {
4061 struct ucred *a_cred;
4065 register struct vnode
*vp
= ap
->a_vp
;
4066 register struct nfsnode
*np
= VTONFS(vp
);
4069 if (np
->n_flag
& (NACC
| NUPD
)) {
4071 if (vp
->v_usecount
== 1 &&
4072 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
4074 if (np
->n_flag
& NACC
)
4075 vattr
.va_atime
= np
->n_atim
;
4076 if (np
->n_flag
& NUPD
)
4077 vattr
.va_mtime
= np
->n_mtim
;
4078 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
4081 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_close
), ap
));
4085 * Read wrapper for fifos.
4089 struct vop_read_args
/* {
4093 struct ucred *a_cred;
4096 extern vop_t
**fifo_vnodeop_p
;
4097 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4103 np
->n_atim
.tv_sec
= time
.tv_sec
;
4104 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
4105 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_read
), ap
));
4109 * Write wrapper for fifos.
4113 struct vop_write_args
/* {
4117 struct ucred *a_cred;
4120 extern vop_t
**fifo_vnodeop_p
;
4121 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4127 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4128 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4129 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_write
), ap
));
4133 * Close wrapper for fifos.
4135 * Update the times on the nfsnode then do fifo close.
4139 struct vop_close_args
/* {
4142 struct ucred *a_cred;
4146 register struct vnode
*vp
= ap
->a_vp
;
4147 register struct nfsnode
*np
= VTONFS(vp
);
4149 extern vop_t
**fifo_vnodeop_p
;
4151 if (np
->n_flag
& (NACC
| NUPD
)) {
4152 if (np
->n_flag
& NACC
) {
4153 np
->n_atim
.tv_sec
= time
.tv_sec
;
4154 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
4156 if (np
->n_flag
& NUPD
) {
4157 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4158 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4161 if (vp
->v_usecount
== 1 &&
4162 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
4164 if (np
->n_flag
& NACC
)
4165 vattr
.va_atime
= np
->n_atim
;
4166 if (np
->n_flag
& NUPD
)
4167 vattr
.va_mtime
= np
->n_mtim
;
4168 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
4171 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_close
), ap
));
4176 struct vop_ioctl_args
*ap
;
4180 * XXX we were once bogusly enoictl() which returned this (ENOTTY).
4181 * Probably we should return ENODEV.
4188 struct vop_select_args
*ap
;
4192 * We were once bogusly seltrue() which returns 1. Is this right?
4197 /* XXX Eliminate use of struct bp here */
4199 * Vnode op for pagein using getblk_pages
4200 * derived from nfs_bioread()
4201 * No read aheads are started from pagein operation
4205 struct vop_pagein_args
/* {
4208 vm_offset_t a_pl_offset,
4211 struct ucred *a_cred,
4215 register struct vnode
*vp
= ap
->a_vp
;
4216 upl_t pl
= ap
->a_pl
;
4217 size_t size
= ap
->a_size
;
4218 off_t f_offset
= ap
->a_f_offset
;
4219 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4220 int flags
= ap
->a_flags
;
4222 register struct nfsnode
*np
= VTONFS(vp
);
4223 register int biosize
;
4224 register int iosize
;
4227 struct proc
*p
= current_proc();
4228 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4233 struct uio
* uio
= &auio
;
4234 int nofreeupl
= flags
& UPL_NOCOMMIT
;
4236 FSDBG(322, f_offset
, size
, pl
, pl_offset
);
4237 if (pl
== (upl_t
)NULL
)
4238 panic("nfs_pagein: no upl");
4240 if (UBCINVALID(vp
)) {
4241 printf("nfs_pagein: invalid vnode 0x%x", (int)vp
);
4243 (void) ubc_upl_abort(pl
, NULL
);
4246 UBCINFOCHECK("nfs_pagein", vp
);
4249 printf("nfs_pagein: invalid size %d", size
);
4251 (void) ubc_upl_abort(pl
, NULL
);
4254 if (f_offset
< 0 || f_offset
>= np
->n_size
||
4255 (f_offset
& PAGE_MASK_64
)) {
4257 ubc_upl_abort_range(pl
, pl_offset
, size
,
4258 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4261 cred
= ubc_getcred(vp
);
4265 auio
.uio_offset
= f_offset
;
4266 auio
.uio_segflg
= UIO_SYSSPACE
;
4267 auio
.uio_rw
= UIO_READ
;
4268 auio
.uio_procp
= NULL
;
4270 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4271 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4272 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4274 if (biosize
& PAGE_MASK
)
4275 panic("nfs_pagein(%x): biosize not page aligned", biosize
);
4277 ubc_upl_map(pl
, &ioaddr
);
4278 ioaddr
+= pl_offset
;
4282 iosize
= min(biosize
, xsize
);
4283 uio
->uio_resid
= iosize
;
4284 auio
.uio_iov
= &aiov
;
4285 auio
.uio_iovcnt
= 1;
4286 aiov
.iov_len
= iosize
;
4287 aiov
.iov_base
= (caddr_t
)ioaddr
;
4289 FSDBG(322, uio
->uio_offset
, uio
->uio_resid
, ioaddr
, xsize
);
4290 #warning our nfs_pagein does not support NQNFS
4292 * With UBC we get here only when the file data is not in the VM
4293 * page cache, so go ahead and read in.
4296 upl_ubc_alias_set(pl
, current_act(), 2);
4297 #endif /* UBC_DEBUG */
4300 error
= nfs_readrpc(vp
, uio
, cred
);
4303 if (uio
->uio_resid
) {
4305 * If uio_resid > 0, there is a hole in the file
4306 * and no writes after the hole have been pushed
4307 * to the server yet... or we're at the EOF
4308 * Just zero fill the rest of the valid area.
4310 int zcnt
= uio
->uio_resid
;
4311 int zoff
= iosize
- zcnt
;
4312 bzero((char *)ioaddr
+ zoff
, zcnt
);
4314 FSDBG(324, uio
->uio_offset
, zoff
, zcnt
, ioaddr
);
4315 uio
->uio_offset
+= zcnt
;
4320 FSDBG(322, uio
->uio_offset
, uio
->uio_resid
, error
, -1);
4322 if (p
&& (vp
->v_flag
& VTEXT
) &&
4323 ((nmp
->nm_flag
& NFSMNT_NQNFS
&&
4324 NQNFS_CKINVALID(vp
, np
, ND_READ
) &&
4325 np
->n_lrev
!= np
->n_brev
) ||
4326 (!(nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4327 np
->n_mtime
!= np
->n_vattr
.va_mtime
.tv_sec
))) {
4328 uprintf("Process killed due to text file modification\n");
4329 psignal(p
, SIGKILL
);
4330 p
->p_flag
|= P_NOSWAP
;
4333 } while (error
== 0 && xsize
> 0);
4339 ubc_upl_abort_range(pl
, pl_offset
, size
,
4341 UPL_ABORT_FREE_ON_EMPTY
);
4343 ubc_upl_commit_range(pl
, pl_offset
, size
,
4344 UPL_COMMIT_CLEAR_DIRTY
|
4345 UPL_COMMIT_FREE_ON_EMPTY
);
4352 * Vnode op for pageout using UPL
4353 * Derived from nfs_write()
4354 * File size changes are not permitted in pageout.
4358 struct vop_pageout_args
/* {
4361 vm_offset_t a_pl_offset,
4364 struct ucred *a_cred,
4368 register struct vnode
*vp
= ap
->a_vp
;
4369 upl_t pl
= ap
->a_pl
;
4370 size_t size
= ap
->a_size
;
4371 off_t f_offset
= ap
->a_f_offset
;
4372 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4373 int flags
= ap
->a_flags
;
4374 int ioflag
= ap
->a_flags
;
4375 register int biosize
;
4376 struct proc
*p
= current_proc();
4377 struct nfsnode
*np
= VTONFS(vp
);
4378 register struct ucred
*cred
;
4380 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4382 int n
= 0, on
, error
= 0, iomode
, must_commit
, s
;
4387 struct uio
* uio
= &auio
;
4388 int nofreeupl
= flags
& UPL_NOCOMMIT
;
4392 FSDBG(323, f_offset
, size
, pl
, pl_offset
);
4394 if (pl
== (upl_t
)NULL
)
4395 panic("nfs_pageout: no upl");
4397 if (UBCINVALID(vp
)) {
4398 printf("nfs_pageout: invalid vnode 0x%x", (int)vp
);
4400 (void) ubc_upl_abort(pl
, NULL
);
4403 UBCINFOCHECK("nfs_pageout", vp
);
4406 printf("nfs_pageout: invalid size %d", size
);
4408 (void) ubc_upl_abort(pl
, NULL
);
4413 * I use nm_rsize, not nm_wsize so that all buffer cache blocks
4414 * will be the same size within a filesystem. nfs_writerpc will
4415 * still use nm_wsize when sizing the rpc's.
4417 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4419 if (biosize
& PAGE_MASK
)
4420 panic("nfs_pageout(%x): biosize not page aligned", biosize
);
4423 * Check to see whether the buffer is incore
4424 * If incore and not busy invalidate it from the cache
4425 * we should not find it BUSY, since we always do a
4426 * vm_fault_list_request in 'getblk' before returning
4427 * which would block on the page busy status
4429 lbn
= f_offset
/ PAGE_SIZE
; /* to match the size getblk uses */
4431 for (iosize
= size
; iosize
> 0; iosize
-= PAGE_SIZE
, lbn
++) {
4433 if (bp
= incore(vp
, lbn
)) {
4434 FSDBG(323, lbn
*PAGE_SIZE
, 1, bp
, bp
->b_flags
);
4435 if (ISSET(bp
->b_flags
, B_BUSY
)) {
4436 /* no panic. just tell vm we are busy */
4438 (void) ubc_upl_abort(pl
, NULL
);
4442 SET(bp
->b_flags
, (B_BUSY
| B_INVAL
));
4448 cred
= ubc_getcred(vp
);
4452 if (np
->n_flag
& NWRITEERR
) {
4453 np
->n_flag
&= ~NWRITEERR
;
4455 ubc_upl_abort_range(pl
, pl_offset
, size
,
4456 UPL_ABORT_FREE_ON_EMPTY
);
4457 return (np
->n_error
);
4459 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4460 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4462 if (f_offset
< 0 || f_offset
>= np
->n_size
||
4463 f_offset
& PAGE_MASK_64
|| size
& PAGE_MASK
) {
4465 ubc_upl_abort_range(pl
, pl_offset
, size
,
4466 UPL_ABORT_FREE_ON_EMPTY
);
4470 ubc_upl_map(pl
, &ioaddr
);
4472 if (f_offset
+ size
> np
->n_size
)
4473 iosize
= np
->n_size
- f_offset
;
4477 pgsize
= (iosize
+ (PAGE_SIZE
- 1)) & ~PAGE_MASK
;
4479 if (size
> pgsize
) {
4481 ubc_upl_abort_range(pl
, pl_offset
+ pgsize
,
4483 UPL_ABORT_FREE_ON_EMPTY
);
4485 auio
.uio_iov
= &aiov
;
4486 auio
.uio_iovcnt
= 1;
4487 auio
.uio_offset
= f_offset
;
4488 auio
.uio_segflg
= UIO_SYSSPACE
;
4489 auio
.uio_rw
= UIO_READ
;
4490 auio
.uio_resid
= iosize
;
4491 auio
.uio_procp
= NULL
;
4493 aiov
.iov_len
= iosize
;
4494 aiov
.iov_base
= (caddr_t
)ioaddr
+ pl_offset
;
4496 * check for partial page and clear the
4497 * contents past end of the file before
4498 * releasing it in the VM page cache
4500 if (f_offset
< np
->n_size
&& f_offset
+ size
> np
->n_size
) {
4501 size_t io
= np
->n_size
- f_offset
;
4503 bzero((caddr_t
)(ioaddr
+ pl_offset
+ io
), size
- io
);
4505 FSDBG(321, np
->n_size
, f_offset
, f_offset
+ io
, size
- io
);
4509 #warning our nfs_pageout does not support NQNFS
4510 nfsstats
.pageouts
++;
4511 lbn
= uio
->uio_offset
/ biosize
;
4512 on
= uio
->uio_offset
& (biosize
-1);
4513 n
= min((unsigned)(biosize
- on
), uio
->uio_resid
);
4516 /* (removed for UBC) */
4518 if ((off_t
)(lbn
+ 1) * biosize
> np
->n_size
) {
4519 bufsize
= np
->n_size
- (off_t
)lbn
* biosize
;
4520 bufsize
= (bufsize
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
4524 /* NMODIFIED would be set here if doing unstable writes */
4525 iomode
= NFSV3WRITE_FILESYNC
;
4526 error
= nfs_writerpc(vp
, uio
, cred
, &iomode
, &must_commit
);
4528 nfs_clearcommit(vp
->v_mount
);
4535 uio
->uio_resid
-= n
;
4536 uio
->uio_offset
+= n
;
4537 uio
->uio_iov
->iov_base
+= n
;
4538 uio
->uio_iov
->iov_len
-= n
;
4540 } while (uio
->uio_resid
> 0 && n
> 0);
4545 * We've had several different solutions on what to do when the pageout
4546 * gets an error. If we don't handle it, and return an error to the
4547 * caller, vm, it will retry . This can end in endless looping
4548 * between vm and here doing retries of the same page. Doing a dump
4549 * back to vm, will get it out of vm's knowledge and we lose whatever
4550 * data existed. This is risky, but in some cases necessary. For
4551 * example, the initial fix here was to do that for ESTALE. In that case
4552 * the server is telling us that the file is no longer the same. We
4553 * would not want to keep paging out to that. We also saw some 151
4554 * errors from Auspex server and NFSv3 can return errors higher than
4555 * ELAST. Those along with NFS known server errors we will "dump" from
4556 * vm. Errors we don't expect to occur, we dump and log for further
4557 * analysis. Errors that could be transient, networking ones,
4558 * we let vm "retry". Lastly, errors that we retry, but may have potential
4559 * to storm the network, we "retrywithsleep". "sever" will be used in
4560 * in the future to dump all pages of object for cases like ESTALE.
4561 * All this is the basis for the states returned and first guesses on
4562 * error handling. Tweaking expected as more statistics are gathered.
4563 * Note, in the long run we may need another more robust solution to
4564 * have some kind of persistant store when the vm cannot dump nor keep
4565 * retrying as a solution, but this would be a file architectural change
4568 if (!nofreeupl
) { /* otherwise stacked file system has to handle this */
4571 short action
= nfs_pageouterrorhandler(error
);
4575 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4578 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4579 if (error
<= ELAST
&&
4580 (errorcount
[error
] % 100 == 0))
4581 printf("nfs_pageout: unexpected error %d. dumping vm page\n", error
);
4582 errorcount
[error
]++;
4585 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4587 case RETRYWITHSLEEP
:
4588 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4589 /* pri unused. PSOCK for placeholder. */
4590 (void) tsleep(&lbolt
, PSOCK
,
4593 case SEVER
: /* not implemented */
4595 printf("nfs_pageout: action %d not expected\n", action
);
4599 ubc_upl_abort_range(pl
, pl_offset
, size
, abortflags
);
4600 /* return error in all cases above */
4603 ubc_upl_commit_range(pl
, pl_offset
, pgsize
,
4604 UPL_COMMIT_CLEAR_DIRTY
|
4605 UPL_COMMIT_FREE_ON_EMPTY
);
4610 /* Blktooff derives file offset given a logical block number */
4613 struct vop_blktooff_args
/* {
4620 register struct vnode
*vp
= ap
->a_vp
;
4622 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4624 *ap
->a_offset
= (off_t
)ap
->a_lblkno
* biosize
;
4631 struct vop_offtoblk_args
/* {
4638 register struct vnode
*vp
= ap
->a_vp
;
4640 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4642 *ap
->a_lblkno
= (daddr_t
)(ap
->a_offset
/ biosize
);
4648 struct vop_cmap_args
/* {
4657 return (EOPNOTSUPP
);