2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1989, 1993
25 * The Regents of the University of California. All rights reserved.
27 * This code is derived from software contributed to Berkeley by
28 * Rick Macklem at The University of Guelph.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
59 * FreeBSD-Id: nfs_vnops.c,v 1.72 1997/11/07 09:20:48 phk Exp $
64 * vnode op calls for Sun NFS version 2 and 3
66 #include <sys/param.h>
67 #include <sys/kernel.h>
68 #include <sys/systm.h>
69 #include <sys/resourcevar.h>
71 #include <sys/mount.h>
73 #include <sys/malloc.h>
76 #include <sys/namei.h>
77 #include <sys/vnode.h>
78 #include <sys/dirent.h>
79 #include <sys/fcntl.h>
80 #include <sys/lockf.h>
83 #include <ufs/ufs/dir.h>
84 #include <vfs/vfs_support.h>
87 #include <machine/spl.h>
88 #include <vm/vm_pageout.h>
91 #include <kern/clock.h>
93 #include <miscfs/fifofs/fifo.h>
94 #include <miscfs/specfs/specdev.h>
96 #include <nfs/rpcv2.h>
97 #include <nfs/nfsproto.h>
99 #include <nfs/nfsnode.h>
100 #include <nfs/nfsmount.h>
101 #include <nfs/xdr_subs.h>
102 #include <nfs/nfsm_subs.h>
103 #include <nfs/nqnfs.h>
106 #include <netinet/in.h>
107 #include <netinet/in_var.h>
108 #include <vm/vm_kern.h>
110 #include <kern/task.h>
111 #include <kern/sched_prim.h>
113 #include <sys/kdebug.h>
115 #define FSDBG(A, B, C, D, E) \
116 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_NONE, \
117 (int)(B), (int)(C), (int)(D), (int)(E), 0)
118 #define FSDBG_TOP(A, B, C, D, E) \
119 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_START, \
120 (int)(B), (int)(C), (int)(D), (int)(E), 0)
121 #define FSDBG_BOT(A, B, C, D, E) \
122 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, (A))) | DBG_FUNC_END, \
123 (int)(B), (int)(C), (int)(D), (int)(E), 0)
128 static int nfsspec_read
__P((struct vop_read_args
*));
129 static int nfsspec_write
__P((struct vop_write_args
*));
130 static int nfsfifo_read
__P((struct vop_read_args
*));
131 static int nfsfifo_write
__P((struct vop_write_args
*));
132 static int nfsspec_close
__P((struct vop_close_args
*));
133 static int nfsfifo_close
__P((struct vop_close_args
*));
134 #define nfs_poll vop_nopoll
135 static int nfs_ioctl
__P((struct vop_ioctl_args
*));
136 static int nfs_select
__P((struct vop_select_args
*));
137 static int nfs_flush
__P((struct vnode
*,struct ucred
*,int,struct proc
*,int));
138 static int nfs_setattrrpc
__P((struct vnode
*,struct vattr
*,struct ucred
*,struct proc
*));
139 static int nfs_lookup
__P((struct vop_lookup_args
*));
140 static int nfs_create
__P((struct vop_create_args
*));
141 static int nfs_mknod
__P((struct vop_mknod_args
*));
142 static int nfs_open
__P((struct vop_open_args
*));
143 static int nfs_close
__P((struct vop_close_args
*));
144 static int nfs_access
__P((struct vop_access_args
*));
145 static int nfs_getattr
__P((struct vop_getattr_args
*));
146 static int nfs_setattr
__P((struct vop_setattr_args
*));
147 static int nfs_read
__P((struct vop_read_args
*));
148 static int nfs_mmap
__P((struct vop_mmap_args
*));
149 static int nfs_fsync
__P((struct vop_fsync_args
*));
150 static int nfs_remove
__P((struct vop_remove_args
*));
151 static int nfs_link
__P((struct vop_link_args
*));
152 static int nfs_rename
__P((struct vop_rename_args
*));
153 static int nfs_mkdir
__P((struct vop_mkdir_args
*));
154 static int nfs_rmdir
__P((struct vop_rmdir_args
*));
155 static int nfs_symlink
__P((struct vop_symlink_args
*));
156 static int nfs_readdir
__P((struct vop_readdir_args
*));
157 static int nfs_bmap
__P((struct vop_bmap_args
*));
158 static int nfs_strategy
__P((struct vop_strategy_args
*));
159 static int nfs_lookitup
__P((struct vnode
*,char *,int,struct ucred
*,struct proc
*,struct nfsnode
**));
160 static int nfs_sillyrename
__P((struct vnode
*,struct vnode
*,struct componentname
*));
161 static int nfsspec_access
__P((struct vop_access_args
*));
162 static int nfs_readlink
__P((struct vop_readlink_args
*));
163 static int nfs_print
__P((struct vop_print_args
*));
164 static int nfs_pathconf
__P((struct vop_pathconf_args
*));
165 static int nfs_advlock
__P((struct vop_advlock_args
*));
166 static int nfs_blkatoff
__P((struct vop_blkatoff_args
*));
167 static int nfs_bwrite
__P((struct vop_bwrite_args
*));
168 static int nfs_valloc
__P((struct vop_valloc_args
*));
169 static int nfs_vfree
__P((struct vop_vfree_args
*));
170 static int nfs_truncate
__P((struct vop_truncate_args
*));
171 static int nfs_update
__P((struct vop_update_args
*));
172 static int nfs_pagein
__P((struct vop_pagein_args
*));
173 static int nfs_pageout
__P((struct vop_pageout_args
*));
174 static int nfs_blktooff
__P((struct vop_blktooff_args
*));
175 static int nfs_offtoblk
__P((struct vop_offtoblk_args
*));
176 static int nfs_cmap
__P((struct vop_cmap_args
*));
179 * Global vfs data structures for nfs
181 vop_t
**nfsv2_vnodeop_p
;
182 static struct vnodeopv_entry_desc nfsv2_vnodeop_entries
[] = {
183 { &vop_default_desc
, (vop_t
*)vn_default_error
},
184 { &vop_lookup_desc
, (vop_t
*)nfs_lookup
}, /* lookup */
185 { &vop_create_desc
, (vop_t
*)nfs_create
}, /* create */
186 { &vop_mknod_desc
, (vop_t
*)nfs_mknod
}, /* mknod */
187 { &vop_open_desc
, (vop_t
*)nfs_open
}, /* open */
188 { &vop_close_desc
, (vop_t
*)nfs_close
}, /* close */
189 { &vop_access_desc
, (vop_t
*)nfs_access
}, /* access */
190 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
191 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
192 { &vop_read_desc
, (vop_t
*)nfs_read
}, /* read */
193 { &vop_write_desc
, (vop_t
*)nfs_write
}, /* write */
194 { &vop_lease_desc
, (vop_t
*)nfs_lease_check
}, /* lease */
195 { &vop_ioctl_desc
, (vop_t
*)nfs_ioctl
}, /* ioctl */
196 { &vop_select_desc
, (vop_t
*)nfs_select
}, /* select */
197 { &vop_revoke_desc
, (vop_t
*)nfs_revoke
}, /* revoke */
198 { &vop_mmap_desc
, (vop_t
*)nfs_mmap
}, /* mmap */
199 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
200 { &vop_seek_desc
, (vop_t
*)nfs_seek
}, /* seek */
201 { &vop_remove_desc
, (vop_t
*)nfs_remove
}, /* remove */
202 { &vop_link_desc
, (vop_t
*)nfs_link
}, /* link */
203 { &vop_rename_desc
, (vop_t
*)nfs_rename
}, /* rename */
204 { &vop_mkdir_desc
, (vop_t
*)nfs_mkdir
}, /* mkdir */
205 { &vop_rmdir_desc
, (vop_t
*)nfs_rmdir
}, /* rmdir */
206 { &vop_symlink_desc
, (vop_t
*)nfs_symlink
}, /* symlink */
207 { &vop_readdir_desc
, (vop_t
*)nfs_readdir
}, /* readdir */
208 { &vop_readlink_desc
, (vop_t
*)nfs_readlink
}, /* readlink */
209 { &vop_abortop_desc
, (vop_t
*)nfs_abortop
}, /* abortop */
210 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
211 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
212 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
213 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
214 { &vop_bmap_desc
, (vop_t
*)nfs_bmap
}, /* bmap */
215 { &vop_strategy_desc
, (vop_t
*)nfs_strategy
}, /* strategy */
216 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
217 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
218 { &vop_pathconf_desc
, (vop_t
*)nfs_pathconf
}, /* pathconf */
219 { &vop_advlock_desc
, (vop_t
*)nfs_advlock
}, /* advlock */
220 { &vop_blkatoff_desc
, (vop_t
*)nfs_blkatoff
}, /* blkatoff */
221 { &vop_valloc_desc
, (vop_t
*)nfs_valloc
}, /* valloc */
222 { &vop_reallocblks_desc
, (vop_t
*)nfs_reallocblks
}, /* reallocblks */
223 { &vop_vfree_desc
, (vop_t
*)nfs_vfree
}, /* vfree */
224 { &vop_truncate_desc
, (vop_t
*)nfs_truncate
}, /* truncate */
225 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
226 { &vop_bwrite_desc
, (vop_t
*)nfs_bwrite
}, /* bwrite */
227 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
228 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
229 { &vop_copyfile_desc
, (vop_t
*)err_copyfile
}, /* Copyfile */
230 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
231 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
232 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
235 struct vnodeopv_desc nfsv2_vnodeop_opv_desc
=
236 { &nfsv2_vnodeop_p
, nfsv2_vnodeop_entries
};
238 VNODEOP_SET(nfsv2_vnodeop_opv_desc
);
242 * Special device vnode ops
244 vop_t
**spec_nfsv2nodeop_p
;
245 static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries
[] = {
246 { &vop_default_desc
, (vop_t
*)vn_default_error
},
247 { &vop_lookup_desc
, (vop_t
*)spec_lookup
}, /* lookup */
248 { &vop_create_desc
, (vop_t
*)spec_create
}, /* create */
249 { &vop_mknod_desc
, (vop_t
*)spec_mknod
}, /* mknod */
250 { &vop_open_desc
, (vop_t
*)spec_open
}, /* open */
251 { &vop_close_desc
, (vop_t
*)nfsspec_close
}, /* close */
252 { &vop_access_desc
, (vop_t
*)nfsspec_access
}, /* access */
253 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
254 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
255 { &vop_read_desc
, (vop_t
*)nfsspec_read
}, /* read */
256 { &vop_write_desc
, (vop_t
*)nfsspec_write
}, /* write */
257 { &vop_lease_desc
, (vop_t
*)spec_lease_check
}, /* lease */
258 { &vop_ioctl_desc
, (vop_t
*)spec_ioctl
}, /* ioctl */
259 { &vop_select_desc
, (vop_t
*)spec_select
}, /* select */
260 { &vop_revoke_desc
, (vop_t
*)spec_revoke
}, /* revoke */
261 { &vop_mmap_desc
, (vop_t
*)spec_mmap
}, /* mmap */
262 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
263 { &vop_seek_desc
, (vop_t
*)spec_seek
}, /* seek */
264 { &vop_remove_desc
, (vop_t
*)spec_remove
}, /* remove */
265 { &vop_link_desc
, (vop_t
*)spec_link
}, /* link */
266 { &vop_rename_desc
, (vop_t
*)spec_rename
}, /* rename */
267 { &vop_mkdir_desc
, (vop_t
*)spec_mkdir
}, /* mkdir */
268 { &vop_rmdir_desc
, (vop_t
*)spec_rmdir
}, /* rmdir */
269 { &vop_symlink_desc
, (vop_t
*)spec_symlink
}, /* symlink */
270 { &vop_readdir_desc
, (vop_t
*)spec_readdir
}, /* readdir */
271 { &vop_readlink_desc
, (vop_t
*)spec_readlink
}, /* readlink */
272 { &vop_abortop_desc
, (vop_t
*)spec_abortop
}, /* abortop */
273 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
274 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
275 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
276 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
277 { &vop_bmap_desc
, (vop_t
*)spec_bmap
}, /* bmap */
278 { &vop_strategy_desc
, (vop_t
*)spec_strategy
}, /* strategy */
279 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
280 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
281 { &vop_pathconf_desc
, (vop_t
*)spec_pathconf
}, /* pathconf */
282 { &vop_advlock_desc
, (vop_t
*)spec_advlock
}, /* advlock */
283 { &vop_blkatoff_desc
, (vop_t
*)spec_blkatoff
}, /* blkatoff */
284 { &vop_valloc_desc
, (vop_t
*)spec_valloc
}, /* valloc */
285 { &vop_reallocblks_desc
, (vop_t
*)spec_reallocblks
}, /* reallocblks */
286 { &vop_vfree_desc
, (vop_t
*)spec_vfree
}, /* vfree */
287 { &vop_truncate_desc
, (vop_t
*)spec_truncate
}, /* truncate */
288 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
289 { &vop_bwrite_desc
, (vop_t
*)vn_bwrite
}, /* bwrite */
290 { &vop_devblocksize_desc
, (vop_t
*)spec_devblocksize
}, /* devblocksize */
291 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
292 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
293 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
294 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
295 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
298 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc
=
299 { &spec_nfsv2nodeop_p
, spec_nfsv2nodeop_entries
};
301 VNODEOP_SET(spec_nfsv2nodeop_opv_desc
);
304 vop_t
**fifo_nfsv2nodeop_p
;
305 static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries
[] = {
306 { &vop_default_desc
, (vop_t
*)vn_default_error
},
307 { &vop_lookup_desc
, (vop_t
*)fifo_lookup
}, /* lookup */
308 { &vop_create_desc
, (vop_t
*)fifo_create
}, /* create */
309 { &vop_mknod_desc
, (vop_t
*)fifo_mknod
}, /* mknod */
310 { &vop_open_desc
, (vop_t
*)fifo_open
}, /* open */
311 { &vop_close_desc
, (vop_t
*)nfsfifo_close
}, /* close */
312 { &vop_access_desc
, (vop_t
*)nfsspec_access
}, /* access */
313 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
314 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
315 { &vop_read_desc
, (vop_t
*)nfsfifo_read
}, /* read */
316 { &vop_write_desc
, (vop_t
*)nfsfifo_write
}, /* write */
317 { &vop_lease_desc
, (vop_t
*)fifo_lease_check
}, /* lease */
318 { &vop_ioctl_desc
, (vop_t
*)fifo_ioctl
}, /* ioctl */
319 { &vop_select_desc
, (vop_t
*)fifo_select
}, /* select */
320 { &vop_revoke_desc
, (vop_t
*)fifo_revoke
}, /* revoke */
321 { &vop_mmap_desc
, (vop_t
*)fifo_mmap
}, /* mmap */
322 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
323 { &vop_seek_desc
, (vop_t
*)fifo_seek
}, /* seek */
324 { &vop_remove_desc
, (vop_t
*)fifo_remove
}, /* remove */
325 { &vop_link_desc
, (vop_t
*)fifo_link
}, /* link */
326 { &vop_rename_desc
, (vop_t
*)fifo_rename
}, /* rename */
327 { &vop_mkdir_desc
, (vop_t
*)fifo_mkdir
}, /* mkdir */
328 { &vop_rmdir_desc
, (vop_t
*)fifo_rmdir
}, /* rmdir */
329 { &vop_symlink_desc
, (vop_t
*)fifo_symlink
}, /* symlink */
330 { &vop_readdir_desc
, (vop_t
*)fifo_readdir
}, /* readdir */
331 { &vop_readlink_desc
, (vop_t
*)fifo_readlink
}, /* readlink */
332 { &vop_abortop_desc
, (vop_t
*)fifo_abortop
}, /* abortop */
333 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
334 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
335 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
336 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
337 { &vop_bmap_desc
, (vop_t
*)fifo_bmap
}, /* bmap */
338 { &vop_strategy_desc
, (vop_t
*)fifo_strategy
}, /* strategy */
339 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
340 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
341 { &vop_pathconf_desc
, (vop_t
*)fifo_pathconf
}, /* pathconf */
342 { &vop_advlock_desc
, (vop_t
*)fifo_advlock
}, /* advlock */
343 { &vop_blkatoff_desc
, (vop_t
*)fifo_blkatoff
}, /* blkatoff */
344 { &vop_valloc_desc
, (vop_t
*)fifo_valloc
}, /* valloc */
345 { &vop_reallocblks_desc
, (vop_t
*)fifo_reallocblks
}, /* reallocblks */
346 { &vop_vfree_desc
, (vop_t
*)fifo_vfree
}, /* vfree */
347 { &vop_truncate_desc
, (vop_t
*)fifo_truncate
}, /* truncate */
348 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
349 { &vop_bwrite_desc
, (vop_t
*)vn_bwrite
}, /* bwrite */
350 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
351 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
352 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
353 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
354 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
357 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc
=
358 { &fifo_nfsv2nodeop_p
, fifo_nfsv2nodeop_entries
};
360 VNODEOP_SET(fifo_nfsv2nodeop_opv_desc
);
363 static int nfs_commit
__P((struct vnode
*vp
, u_quad_t offset
, int cnt
,
364 struct ucred
*cred
, struct proc
*procp
));
365 static int nfs_mknodrpc
__P((struct vnode
*dvp
, struct vnode
**vpp
,
366 struct componentname
*cnp
,
368 static int nfs_removerpc
__P((struct vnode
*dvp
, char *name
, int namelen
,
369 struct ucred
*cred
, struct proc
*proc
));
370 static int nfs_renamerpc
__P((struct vnode
*fdvp
, char *fnameptr
,
371 int fnamelen
, struct vnode
*tdvp
,
372 char *tnameptr
, int tnamelen
,
373 struct ucred
*cred
, struct proc
*proc
));
374 static int nfs_renameit
__P((struct vnode
*sdvp
,
375 struct componentname
*scnp
,
376 struct sillyrename
*sp
));
381 extern u_long nfs_true
, nfs_false
;
382 extern struct nfsstats nfsstats
;
383 extern nfstype nfsv3_type
[9];
384 struct proc
*nfs_iodwant
[NFS_MAXASYNCDAEMON
];
385 struct nfsmount
*nfs_iodmount
[NFS_MAXASYNCDAEMON
];
386 int nfs_numasync
= 0;
387 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
389 static int nfsaccess_cache_timeout
= NFS_MAXATTRTIMO
;
390 /* SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
391 &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
393 #define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY \
394 | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \
395 | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
399 * the following are needed only by nfs_pageout to know how to handle errors
400 * see nfs_pageout comments on explanation of actions.
401 * the errors here are copied from errno.h and errors returned by servers
402 * are expected to match the same numbers here. If not, our actions maybe
405 enum actiontype
{NOACTION
, DUMP
, DUMPANDLOG
, RETRY
, RETRYWITHSLEEP
, SEVER
};
407 static int errorcount
[ELAST
+1]; /* better be zeros when initialized */
409 static const short errortooutcome
[ELAST
+1] = {
411 DUMP
, /* EPERM 1 Operation not permitted */
412 DUMP
, /* ENOENT 2 No such file or directory */
413 DUMPANDLOG
, /* ESRCH 3 No such process */
414 RETRY
, /* EINTR 4 Interrupted system call */
415 DUMP
, /* EIO 5 Input/output error */
416 DUMP
, /* ENXIO 6 Device not configured */
417 DUMPANDLOG
, /* E2BIG 7 Argument list too long */
418 DUMPANDLOG
, /* ENOEXEC 8 Exec format error */
419 DUMPANDLOG
, /* EBADF 9 Bad file descriptor */
420 DUMPANDLOG
, /* ECHILD 10 No child processes */
421 DUMPANDLOG
, /* EDEADLK 11 Resource deadlock avoided - was EAGAIN */
422 RETRY
, /* ENOMEM 12 Cannot allocate memory */
423 DUMP
, /* EACCES 13 Permission denied */
424 DUMPANDLOG
, /* EFAULT 14 Bad address */
425 DUMPANDLOG
, /* ENOTBLK 15 POSIX - Block device required */
426 RETRY
, /* EBUSY 16 Device busy */
427 DUMP
, /* EEXIST 17 File exists */
428 DUMP
, /* EXDEV 18 Cross-device link */
429 DUMP
, /* ENODEV 19 Operation not supported by device */
430 DUMP
, /* ENOTDIR 20 Not a directory */
431 DUMP
, /* EISDIR 21 Is a directory */
432 DUMP
, /* EINVAL 22 Invalid argument */
433 DUMPANDLOG
, /* ENFILE 23 Too many open files in system */
434 DUMPANDLOG
, /* EMFILE 24 Too many open files */
435 DUMPANDLOG
, /* ENOTTY 25 Inappropriate ioctl for device */
436 DUMPANDLOG
, /* ETXTBSY 26 Text file busy - POSIX */
437 DUMP
, /* EFBIG 27 File too large */
438 DUMP
, /* ENOSPC 28 No space left on device */
439 DUMPANDLOG
, /* ESPIPE 29 Illegal seek */
440 DUMP
, /* EROFS 30 Read-only file system */
441 DUMP
, /* EMLINK 31 Too many links */
442 RETRY
, /* EPIPE 32 Broken pipe */
444 DUMPANDLOG
, /* EDOM 33 Numerical argument out of domain */
445 DUMPANDLOG
, /* ERANGE 34 Result too large */
446 RETRY
, /* EAGAIN/EWOULDBLOCK 35 Resource temporarily unavailable */
447 DUMPANDLOG
, /* EINPROGRESS 36 Operation now in progress */
448 DUMPANDLOG
, /* EALREADY 37 Operation already in progress */
449 /* ipc/network software -- argument errors */
450 DUMPANDLOG
, /* ENOTSOC 38 Socket operation on non-socket */
451 DUMPANDLOG
, /* EDESTADDRREQ 39 Destination address required */
452 DUMPANDLOG
, /* EMSGSIZE 40 Message too long */
453 DUMPANDLOG
, /* EPROTOTYPE 41 Protocol wrong type for socket */
454 DUMPANDLOG
, /* ENOPROTOOPT 42 Protocol not available */
455 DUMPANDLOG
, /* EPROTONOSUPPORT 43 Protocol not supported */
456 DUMPANDLOG
, /* ESOCKTNOSUPPORT 44 Socket type not supported */
457 DUMPANDLOG
, /* ENOTSUP 45 Operation not supported */
458 DUMPANDLOG
, /* EPFNOSUPPORT 46 Protocol family not supported */
459 DUMPANDLOG
, /* EAFNOSUPPORT 47 Address family not supported by protocol family */
460 DUMPANDLOG
, /* EADDRINUSE 48 Address already in use */
461 DUMPANDLOG
, /* EADDRNOTAVAIL 49 Can't assign requested address */
462 /* ipc/network software -- operational errors */
463 RETRY
, /* ENETDOWN 50 Network is down */
464 RETRY
, /* ENETUNREACH 51 Network is unreachable */
465 RETRY
, /* ENETRESET 52 Network dropped connection on reset */
466 RETRY
, /* ECONNABORTED 53 Software caused connection abort */
467 RETRY
, /* ECONNRESET 54 Connection reset by peer */
468 RETRY
, /* ENOBUFS 55 No buffer space available */
469 RETRY
, /* EISCONN 56 Socket is already connected */
470 RETRY
, /* ENOTCONN 57 Socket is not connected */
471 RETRY
, /* ESHUTDOWN 58 Can't send after socket shutdown */
472 RETRY
, /* ETOOMANYREFS 59 Too many references: can't splice */
473 RETRY
, /* ETIMEDOUT 60 Operation timed out */
474 RETRY
, /* ECONNREFUSED 61 Connection refused */
476 DUMPANDLOG
, /* ELOOP 62 Too many levels of symbolic links */
477 DUMP
, /* ENAMETOOLONG 63 File name too long */
478 RETRY
, /* EHOSTDOWN 64 Host is down */
479 RETRY
, /* EHOSTUNREACH 65 No route to host */
480 DUMP
, /* ENOTEMPTY 66 Directory not empty */
482 DUMPANDLOG
, /* PROCLIM 67 Too many processes */
483 DUMPANDLOG
, /* EUSERS 68 Too many users */
484 DUMPANDLOG
, /* EDQUOT 69 Disc quota exceeded */
485 /* Network File System */
486 DUMP
, /* ESTALE 70 Stale NFS file handle */
487 DUMP
, /* EREMOTE 71 Too many levels of remote in path */
488 DUMPANDLOG
, /* EBADRPC 72 RPC struct is bad */
489 DUMPANDLOG
, /* ERPCMISMATCH 73 RPC version wrong */
490 DUMPANDLOG
, /* EPROGUNAVAIL 74 RPC prog. not avail */
491 DUMPANDLOG
, /* EPROGMISMATCH 75 Program version wrong */
492 DUMPANDLOG
, /* EPROCUNAVAIL 76 Bad procedure for program */
494 DUMPANDLOG
, /* ENOLCK 77 No locks available */
495 DUMPANDLOG
, /* ENOSYS 78 Function not implemented */
496 DUMPANDLOG
, /* EFTYPE 79 Inappropriate file type or format */
497 DUMPANDLOG
, /* EAUTH 80 Authentication error */
498 DUMPANDLOG
, /* ENEEDAUTH 81 Need authenticator */
499 /* Intelligent device errors */
500 DUMPANDLOG
, /* EPWROFF 82 Device power is off */
501 DUMPANDLOG
, /* EDEVERR 83 Device error, e.g. paper out */
502 DUMPANDLOG
, /* EOVERFLOW 84 Value too large to be stored in data type */
503 /* Program loading errors */
504 DUMPANDLOG
, /* EBADEXEC 85 Bad executable */
505 DUMPANDLOG
, /* EBADARCH 86 Bad CPU type in executable */
506 DUMPANDLOG
, /* ESHLIBVERS 87 Shared library version mismatch */
507 DUMPANDLOG
, /* EBADMACHO 88 Malformed Macho file */
512 nfs_pageouterrorhandler(error
)
518 return(errortooutcome
[error
]);
522 nfs3_access_otw(struct vnode
*vp
,
529 int error
= 0, attrflag
;
531 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
532 caddr_t bpos
, dpos
, cp2
;
533 register int32_t t1
, t2
;
536 struct nfsnode
*np
= VTONFS(vp
);
539 nfsstats
.rpccnt
[NFSPROC_ACCESS
]++;
540 nfsm_reqhead(vp
, NFSPROC_ACCESS
, NFSX_FH(v3
) + NFSX_UNSIGNED
);
542 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
543 *tl
= txdr_unsigned(wmode
);
544 nfsm_request(vp
, NFSPROC_ACCESS
, p
, cred
, &xid
);
545 nfsm_postop_attr(vp
, attrflag
, &xid
);
547 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
548 rmode
= fxdr_unsigned(u_int32_t
, *tl
);
550 np
->n_modeuid
= cred
->cr_uid
;
551 np
->n_modestamp
= time_second
;
558 * nfs access vnode op.
559 * For nfs version 2, just return ok. File accesses may fail later.
560 * For nfs version 3, use the access rpc to check accessibility. If file modes
561 * are changed on the server, accesses might still fail later.
565 struct vop_access_args
/* {
568 struct ucred *a_cred;
572 register struct vnode
*vp
= ap
->a_vp
;
575 int v3
= NFS_ISV3(vp
);
576 struct nfsnode
*np
= VTONFS(vp
);
579 * For nfs v3, do an access rpc, otherwise you are stuck emulating
580 * ufs_access() locally using the vattr. This may not be correct,
581 * since the server may apply other access criteria such as
582 * client uid-->server uid mapping that we do not know about, but
583 * this is better than just returning anything that is lying about
587 if (ap
->a_mode
& VREAD
)
588 mode
= NFSV3ACCESS_READ
;
591 if (vp
->v_type
== VDIR
) {
592 if (ap
->a_mode
& VWRITE
)
593 mode
|= NFSV3ACCESS_MODIFY
|
594 NFSV3ACCESS_EXTEND
| NFSV3ACCESS_DELETE
;
595 if (ap
->a_mode
& VEXEC
)
596 mode
|= NFSV3ACCESS_LOOKUP
;
598 if (ap
->a_mode
& VWRITE
)
599 mode
|= NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
;
600 if (ap
->a_mode
& VEXEC
)
601 mode
|= NFSV3ACCESS_EXECUTE
;
603 /* XXX safety belt, only make blanket request if caching */
604 if (nfsaccess_cache_timeout
> 0) {
605 wmode
= NFSV3ACCESS_READ
| NFSV3ACCESS_MODIFY
|
606 NFSV3ACCESS_EXTEND
| NFSV3ACCESS_EXECUTE
|
607 NFSV3ACCESS_DELETE
| NFSV3ACCESS_LOOKUP
;
612 * Does our cached result allow us to give a definite yes to
615 if (time_second
< np
->n_modestamp
+ nfsaccess_cache_timeout
&&
616 ap
->a_cred
->cr_uid
== np
->n_modeuid
&&
617 (np
->n_mode
& mode
) == mode
) {
618 /* nfsstats.accesscache_hits++; */
621 * Either a no, or a don't know. Go to the wire.
623 /* nfsstats.accesscache_misses++; */
624 error
= nfs3_access_otw(vp
, wmode
, ap
->a_p
,ap
->a_cred
);
626 if ((np
->n_mode
& mode
) != mode
)
631 return (nfsspec_access(ap
)); /* NFSv2 case checks for EROFS here */
633 * Disallow write attempts on filesystems mounted read-only;
634 * unless the file is a socket, fifo, or a block or character
635 * device resident on the filesystem.
636 * CSM - moved EROFS check down per NetBSD rev 1.71. So you
637 * get the correct error value with layered filesystems.
638 * EKN - moved the return(error) below this so it does get called.
640 if (!error
&& (ap
->a_mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
641 switch (vp
->v_type
) {
642 case VREG
: case VDIR
: case VLNK
:
653 * Check to see if the type is ok
654 * and that deletion is not in progress.
655 * For paged in text files, you will need to flush the page cache
656 * if consistency is lost.
662 struct vop_open_args
/* {
665 struct ucred *a_cred;
669 register struct vnode
*vp
= ap
->a_vp
;
670 struct nfsnode
*np
= VTONFS(vp
);
671 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
675 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
&& vp
->v_type
!= VLNK
) {
679 * Get a valid lease. If cached data is stale, flush it.
681 if (nmp
->nm_flag
& NFSMNT_NQNFS
) {
682 if (NQNFS_CKINVALID(vp
, np
, ND_READ
)) {
684 error
= nqnfs_getlease(vp
, ND_READ
, ap
->a_cred
,
686 } while (error
== NQNFS_EXPIRED
);
689 if (np
->n_lrev
!= np
->n_brev
||
690 (np
->n_flag
& NQNFSNONCACHE
)) {
691 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
692 ap
->a_p
, 1)) == EINTR
)
694 np
->n_brev
= np
->n_lrev
;
698 if (np
->n_flag
& NMODIFIED
) {
699 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
700 ap
->a_p
, 1)) == EINTR
)
703 if (vp
->v_type
== VDIR
)
704 np
->n_direofoffset
= 0;
705 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
708 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
710 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
713 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
714 if (vp
->v_type
== VDIR
)
715 np
->n_direofoffset
= 0;
716 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
,
717 ap
->a_cred
, ap
->a_p
, 1)) == EINTR
)
719 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
723 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) == 0)
724 np
->n_attrstamp
= 0; /* For Open/Close consistency */
730 * What an NFS client should do upon close after writing is a debatable issue.
731 * Most NFS clients push delayed writes to the server upon close, basically for
733 * 1 - So that any write errors may be reported back to the client process
734 * doing the close system call. By far the two most likely errors are
735 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
736 * 2 - To put a worst case upper bound on cache inconsistency between
737 * multiple clients for the file.
738 * There is also a consistency problem for Version 2 of the protocol w.r.t.
739 * not being able to tell if other clients are writing a file concurrently,
740 * since there is no way of knowing if the changed modify time in the reply
741 * is only due to the write for this client.
742 * (NFS Version 3 provides weak cache consistency data in the reply that
743 * should be sufficient to detect and handle this case.)
745 * The current code does the following:
746 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
747 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
748 * or commit them (this satisfies 1 and 2 except for the
749 * case where the server crashes after this close but
750 * before the commit RPC, which is felt to be "good
751 * enough". Changing the last argument to nfs_flush() to
752 * a 1 would force a commit operation, if it is felt a
753 * commit is necessary now.
754 * for NQNFS - do nothing now, since 2 is dealt with via leases and
755 * 1 should be dealt with via an fsync() system call for
756 * cases where write errors are important.
761 struct vop_close_args
/* {
762 struct vnodeop_desc *a_desc;
765 struct ucred *a_cred;
769 register struct vnode
*vp
= ap
->a_vp
;
770 register struct nfsnode
*np
= VTONFS(vp
);
773 if (vp
->v_type
== VREG
) {
775 register struct sillyrename
*sp
= np
->n_sillyrename
;
777 kprintf("nfs_close: %s, dvp=%x, vp=%x, ap=%x, np=%x, sp=%x\n",
778 &sp
->s_name
[0], (unsigned)(sp
->s_dvp
), (unsigned)vp
,
779 (unsigned)ap
, (unsigned)np
, (unsigned)sp
);
781 if ((VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) == 0 &&
782 (np
->n_flag
& NMODIFIED
)) {
784 error
= nfs_flush(vp
, ap
->a_cred
, MNT_WAIT
, ap
->a_p
, 1);
786 * We cannot clear the NMODIFIED bit in np->n_flag due to
787 * potential races with other processes
788 * NMODIFIED is a hint
790 /* np->n_flag &= ~NMODIFIED; */
792 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
, ap
->a_p
, 1);
795 if (np
->n_flag
& NWRITEERR
) {
796 np
->n_flag
&= ~NWRITEERR
;
804 * nfs getattr call from vfs.
808 struct vop_getattr_args
/* {
811 struct ucred *a_cred;
815 register struct vnode
*vp
= ap
->a_vp
;
816 register struct nfsnode
*np
= VTONFS(vp
);
822 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
823 int v3
= NFS_ISV3(vp
);
827 FSDBG_TOP(513, np
->n_size
, np
, np
->n_vattr
.va_size
, np
->n_flag
);
829 * Update local times for special files.
831 if (np
->n_flag
& (NACC
| NUPD
))
834 * First look in the cache.
836 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0) {
837 FSDBG_BOT(513, np
->n_size
, 0, np
->n_vattr
.va_size
, np
->n_flag
);
840 if (error
!= ENOENT
) {
841 FSDBG_BOT(513, np
->n_size
, error
, np
->n_vattr
.va_size
,
847 if (v3
&& nfsaccess_cache_timeout
> 0) {
848 /* nfsstats.accesscache_misses++; */
849 if (error
= nfs3_access_otw(vp
, NFSV3ACCESS_ALL
, ap
->a_p
,
852 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0)
860 nfsstats
.rpccnt
[NFSPROC_GETATTR
]++;
861 nfsm_reqhead(vp
, NFSPROC_GETATTR
, NFSX_FH(v3
));
863 nfsm_request(vp
, NFSPROC_GETATTR
, ap
->a_p
, ap
->a_cred
, &xid
);
865 nfsm_loadattr(vp
, ap
->a_vap
, &xid
);
866 if (!xid
) { /* out-of-order rpc - attributes were dropped */
868 FSDBG(513, -1, np
, np
->n_xid
<< 32, np
->n_xid
);
869 if (avoidfloods
++ < 100)
872 * avoidfloods>1 is bizarre. at 100 pull the plug
874 panic("nfs_getattr: getattr flood\n");
876 if (np
->n_mtime
!= ap
->a_vap
->va_mtime
.tv_sec
) {
877 FSDBG(513, -1, np
, -1, vp
);
878 if (vp
->v_type
== VDIR
)
880 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
882 FSDBG(513, -1, np
, -2, error
);
884 np
->n_mtime
= ap
->a_vap
->va_mtime
.tv_sec
;
889 FSDBG_BOT(513, np
->n_size
, -1, np
->n_vattr
.va_size
, error
);
898 struct vop_setattr_args
/* {
899 struct vnodeop_desc *a_desc;
902 struct ucred *a_cred;
906 register struct vnode
*vp
= ap
->a_vp
;
907 register struct nfsnode
*np
= VTONFS(vp
);
908 register struct vattr
*vap
= ap
->a_vap
;
916 #ifdef XXX /* enable this code soon! (but test it first) */
918 * Setting of flags is not supported.
920 if (vap
->va_flags
!= VNOVAL
)
925 * Disallow write attempts if the filesystem is mounted read-only.
927 if ((vap
->va_flags
!= VNOVAL
|| vap
->va_uid
!= (uid_t
)VNOVAL
||
928 vap
->va_gid
!= (gid_t
)VNOVAL
|| vap
->va_atime
.tv_sec
!= VNOVAL
||
929 vap
->va_mtime
.tv_sec
!= VNOVAL
|| vap
->va_mode
!= (mode_t
)VNOVAL
) &&
930 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
932 if (vap
->va_size
!= VNOVAL
) {
933 switch (vp
->v_type
) {
940 if (vap
->va_mtime
.tv_sec
== VNOVAL
&&
941 vap
->va_atime
.tv_sec
== VNOVAL
&&
942 vap
->va_mode
== (u_short
)VNOVAL
&&
943 vap
->va_uid
== (uid_t
)VNOVAL
&&
944 vap
->va_gid
== (gid_t
)VNOVAL
)
946 vap
->va_size
= VNOVAL
;
950 * Disallow write attempts if the filesystem is
953 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
955 FSDBG_TOP(512, np
->n_size
, vap
->va_size
,
956 np
->n_vattr
.va_size
, np
->n_flag
);
957 if (np
->n_flag
& NMODIFIED
) {
958 if (vap
->va_size
== 0)
959 error
= nfs_vinvalbuf(vp
, 0,
960 ap
->a_cred
, ap
->a_p
, 1);
962 error
= nfs_vinvalbuf(vp
, V_SAVE
,
963 ap
->a_cred
, ap
->a_p
, 1);
965 printf("nfs_setattr: nfs_vinvalbuf %d\n", error
);
966 FSDBG_BOT(512, np
->n_size
, vap
->va_size
,
967 np
->n_vattr
.va_size
, -1);
970 } else if (np
->n_size
> vap
->va_size
) { /* shrinking? */
975 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
,
977 obn
= (np
->n_size
- 1) / biosize
;
978 bn
= vap
->va_size
/ biosize
;
979 for ( ; obn
>= bn
; obn
--)
980 if (incore(vp
, obn
)) {
981 bp
= getblk(vp
, obn
, biosize
, 0,
983 FSDBG(512, bp
, bp
->b_flags
,
985 SET(bp
->b_flags
, B_INVAL
);
990 np
->n_size
= np
->n_vattr
.va_size
= vap
->va_size
;
991 ubc_setsize(vp
, (off_t
)vap
->va_size
); /* XXX */
993 } else if ((vap
->va_mtime
.tv_sec
!= VNOVAL
||
994 vap
->va_atime
.tv_sec
!= VNOVAL
) &&
995 (np
->n_flag
& NMODIFIED
) && vp
->v_type
== VREG
&&
996 (error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
997 ap
->a_p
, 1)) == EINTR
)
999 error
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
1000 FSDBG_BOT(512, np
->n_size
, vap
->va_size
, np
->n_vattr
.va_size
, error
);
1001 if (error
&& vap
->va_size
!= VNOVAL
) {
1002 /* make every effort to resync file size w/ server... */
1003 int err
= 0; /* preserve "error" for return */
1005 printf("nfs_setattr: nfs_setattrrpc %d\n", error
);
1006 np
->n_size
= np
->n_vattr
.va_size
= tsize
;
1007 ubc_setsize(vp
, (off_t
)np
->n_size
); /* XXX check error */
1008 vap
->va_size
= tsize
;
1009 err
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
1011 printf("nfs_setattr1: nfs_setattrrpc %d\n", err
);
1017 * Do an nfs setattr rpc.
1020 nfs_setattrrpc(vp
, vap
, cred
, procp
)
1021 register struct vnode
*vp
;
1022 register struct vattr
*vap
;
1026 register struct nfsv2_sattr
*sp
;
1027 register caddr_t cp
;
1028 register long t1
, t2
;
1029 caddr_t bpos
, dpos
, cp2
;
1031 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
1032 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1033 int v3
= NFS_ISV3(vp
);
1036 nfsstats
.rpccnt
[NFSPROC_SETATTR
]++;
1037 nfsm_reqhead(vp
, NFSPROC_SETATTR
, NFSX_FH(v3
) + NFSX_SATTR(v3
));
1040 if (vap
->va_mode
!= (u_short
)VNOVAL
) {
1041 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1043 *tl
= txdr_unsigned(vap
->va_mode
);
1045 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1048 if (vap
->va_uid
!= (uid_t
)VNOVAL
) {
1049 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1051 *tl
= txdr_unsigned(vap
->va_uid
);
1053 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1056 if (vap
->va_gid
!= (gid_t
)VNOVAL
) {
1057 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1059 *tl
= txdr_unsigned(vap
->va_gid
);
1061 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1064 if (vap
->va_size
!= VNOVAL
) {
1065 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1067 txdr_hyper(&vap
->va_size
, tl
);
1069 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1072 if (vap
->va_atime
.tv_sec
!= VNOVAL
) {
1073 if (vap
->va_atime
.tv_sec
!= time
.tv_sec
) {
1074 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1075 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
1076 txdr_nfsv3time(&vap
->va_atime
, tl
);
1078 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1079 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
1082 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1083 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
1085 if (vap
->va_mtime
.tv_sec
!= VNOVAL
) {
1086 if (vap
->va_mtime
.tv_sec
!= time
.tv_sec
) {
1087 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1088 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
1089 txdr_nfsv3time(&vap
->va_mtime
, tl
);
1091 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1092 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
1095 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1096 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
1098 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1101 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1102 if (vap
->va_mode
== (u_short
)VNOVAL
)
1103 sp
->sa_mode
= VNOVAL
;
1105 sp
->sa_mode
= vtonfsv2_mode(vp
->v_type
, vap
->va_mode
);
1106 if (vap
->va_uid
== (uid_t
)VNOVAL
)
1107 sp
->sa_uid
= VNOVAL
;
1109 sp
->sa_uid
= txdr_unsigned(vap
->va_uid
);
1110 if (vap
->va_gid
== (gid_t
)VNOVAL
)
1111 sp
->sa_gid
= VNOVAL
;
1113 sp
->sa_gid
= txdr_unsigned(vap
->va_gid
);
1114 sp
->sa_size
= txdr_unsigned(vap
->va_size
);
1115 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1116 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1118 nfsm_request(vp
, NFSPROC_SETATTR
, procp
, cred
, &xid
);
1120 nfsm_wcc_data(vp
, wccflag
, &xid
);
1121 if (!wccflag
&& vp
->v_type
!= VBAD
) /* EINVAL on VBAD node */
1122 VTONFS(vp
)->n_attrstamp
= 0;
1124 nfsm_loadattr(vp
, (struct vattr
*)0, &xid
);
1130 * nfs lookup call, one step at a time...
1131 * First look in cache
1132 * If not found, unlock the directory nfsnode and do the rpc
1136 struct vop_lookup_args
/* {
1137 struct vnodeop_desc *a_desc;
1138 struct vnode *a_dvp;
1139 struct vnode **a_vpp;
1140 struct componentname *a_cnp;
1143 register struct componentname
*cnp
= ap
->a_cnp
;
1144 register struct vnode
*dvp
= ap
->a_dvp
;
1145 register struct vnode
**vpp
= ap
->a_vpp
;
1146 register int flags
= cnp
->cn_flags
;
1147 register struct vnode
*newvp
;
1148 register u_long
*tl
;
1149 register caddr_t cp
;
1150 register long t1
, t2
;
1151 struct nfsmount
*nmp
;
1152 caddr_t bpos
, dpos
, cp2
;
1153 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1157 int lockparent
, wantparent
, error
= 0, attrflag
, fhsize
;
1158 int v3
= NFS_ISV3(dvp
);
1159 struct proc
*p
= cnp
->cn_proc
;
1160 int worldbuildworkaround
= 1;
1163 if ((flags
& ISLASTCN
) && (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
) &&
1164 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
))
1167 if (dvp
->v_type
!= VDIR
)
1169 lockparent
= flags
& LOCKPARENT
;
1170 wantparent
= flags
& (LOCKPARENT
|WANTPARENT
);
1171 nmp
= VFSTONFS(dvp
->v_mount
);
1174 if (worldbuildworkaround
) {
1176 * Temporary workaround for world builds to not have dvp go
1177 * VBAD on during server calls in this routine. When
1178 * the real ref counting problem is found take this out.
1179 * Note if this was later and before the nfsm_request
1180 * set up, the workaround did not work (NOTE other difference
1181 * was I only put one VREF in that time. Thus it needs
1182 * to be above the cache_lookup branch or with 2 VREFS. Not
1183 * sure which. Can't play with world builds right now to see
1184 * which. VOP_ACCESS could also make it go to server. - EKN
1186 VREF(dvp
); /* hang on to this dvp - EKN */
1187 VREF(dvp
); /* hang on tight - EKN */
1190 if ((error
= cache_lookup(dvp
, vpp
, cnp
)) && error
!= ENOENT
) {
1194 if ((error
= VOP_ACCESS(dvp
, VEXEC
, cnp
->cn_cred
, p
))) {
1199 /* got to check to make sure the vnode didn't go away if access went to server */
1200 if ((*vpp
)->v_type
== VBAD
) {
1208 * See the comment starting `Step through' in ufs/ufs_lookup.c
1209 * for an explanation of the locking protocol
1214 } else if (flags
& ISDOTDOT
) {
1215 VOP_UNLOCK(dvp
, 0, p
);
1216 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1217 if (!error
&& lockparent
&& (flags
& ISLASTCN
))
1218 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1220 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1221 if (!lockparent
|| error
|| !(flags
& ISLASTCN
))
1222 VOP_UNLOCK(dvp
, 0, p
);
1225 if (vpid
== newvp
->v_id
) {
1226 if (!VOP_GETATTR(newvp
, &vattr
, cnp
->cn_cred
, p
)
1227 && vattr
.va_ctime
.tv_sec
== VTONFS(newvp
)->n_ctime
) {
1228 nfsstats
.lookupcache_hits
++;
1229 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1230 cnp
->cn_flags
|= SAVENAME
;
1231 error
= 0; /* ignore any from VOP_GETATTR */
1237 if (lockparent
&& dvp
!= newvp
&& (flags
& ISLASTCN
))
1238 VOP_UNLOCK(dvp
, 0, p
);
1240 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1247 * Got to check to make sure the vnode didn't go away if VOP_GETATTR went to server
1248 * or callers prior to this blocked and had it go VBAD.
1250 if (dvp
->v_type
== VBAD
) {
1257 nfsstats
.lookupcache_misses
++;
1258 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
1259 len
= cnp
->cn_namelen
;
1260 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
1261 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
1262 nfsm_fhtom(dvp
, v3
);
1263 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
1264 /* nfsm_request for NFSv2 causes you to goto to nfsmout upon errors */
1265 nfsm_request(dvp
, NFSPROC_LOOKUP
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
1268 nfsm_postop_attr(dvp
, attrflag
, &xid
);
1272 nfsm_getfh(fhp
, fhsize
, v3
);
1275 * Handle RENAME case...
1277 if (cnp
->cn_nameiop
== RENAME
&& wantparent
&& (flags
& ISLASTCN
)) {
1278 if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1283 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1289 u_int64_t dxid
= xid
;
1291 nfsm_postop_attr(newvp
, attrflag
, &xid
);
1292 nfsm_postop_attr(dvp
, attrflag
, &dxid
);
1294 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
1297 cnp
->cn_flags
|= SAVENAME
;
1299 VOP_UNLOCK(dvp
, 0, p
);
1304 if (flags
& ISDOTDOT
) {
1305 VOP_UNLOCK(dvp
, 0, p
);
1306 error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
);
1308 vn_lock(dvp
, LK_EXCLUSIVE
+ LK_RETRY
, p
);
1312 if (lockparent
&& (flags
& ISLASTCN
) &&
1313 (error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
))) {
1317 } else if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1321 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1325 if (!lockparent
|| !(flags
& ISLASTCN
))
1326 VOP_UNLOCK(dvp
, 0, p
);
1330 u_int64_t dxid
= xid
;
1332 nfsm_postop_attr(newvp
, attrflag
, &xid
);
1333 nfsm_postop_attr(dvp
, attrflag
, &dxid
);
1335 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
1336 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1337 cnp
->cn_flags
|= SAVENAME
;
1338 if ((cnp
->cn_flags
& MAKEENTRY
) &&
1339 (cnp
->cn_nameiop
!= DELETE
|| !(flags
& ISLASTCN
))) {
1340 np
->n_ctime
= np
->n_vattr
.va_ctime
.tv_sec
;
1341 cache_enter(dvp
, newvp
, cnp
);
1346 if (newvp
!= NULLVP
) {
1350 if ((cnp
->cn_nameiop
== CREATE
|| cnp
->cn_nameiop
== RENAME
) &&
1351 (flags
& ISLASTCN
) && error
== ENOENT
) {
1353 VOP_UNLOCK(dvp
, 0, p
);
1354 if (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
)
1357 error
= EJUSTRETURN
;
1359 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1360 cnp
->cn_flags
|= SAVENAME
;
1364 * These "vreles" set dvp refcounts back to where they were
1365 * before we took extra 2 VREFS to avoid VBAD vnode on dvp
1366 * during server calls for world builds. Remove when real
1367 * fix is found. - EKN
1369 if (worldbuildworkaround
) {
1370 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1371 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1379 * Just call nfs_bioread() to do the work.
1383 struct vop_read_args
/* {
1387 struct ucred *a_cred;
1390 register struct vnode
*vp
= ap
->a_vp
;
1392 if (vp
->v_type
!= VREG
)
1394 return (nfs_bioread(vp
, ap
->a_uio
, ap
->a_ioflag
, ap
->a_cred
, 0));
1403 struct vop_readlink_args
/* {
1406 struct ucred *a_cred;
1409 register struct vnode
*vp
= ap
->a_vp
;
1411 if (vp
->v_type
!= VLNK
)
1413 return (nfs_bioread(vp
, ap
->a_uio
, 0, ap
->a_cred
, 0));
1417 * Do a readlink rpc.
1418 * Called by nfs_doio() from below the buffer cache.
1421 nfs_readlinkrpc(vp
, uiop
, cred
)
1422 register struct vnode
*vp
;
1426 register u_long
*tl
;
1427 register caddr_t cp
;
1428 register long t1
, t2
;
1429 caddr_t bpos
, dpos
, cp2
;
1430 int error
= 0, len
, attrflag
;
1431 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1432 int v3
= NFS_ISV3(vp
);
1435 nfsstats
.rpccnt
[NFSPROC_READLINK
]++;
1436 nfsm_reqhead(vp
, NFSPROC_READLINK
, NFSX_FH(v3
));
1438 nfsm_request(vp
, NFSPROC_READLINK
, uiop
->uio_procp
, cred
, &xid
);
1440 nfsm_postop_attr(vp
, attrflag
, &xid
);
1442 nfsm_strsiz(len
, NFS_MAXPATHLEN
);
1443 if (len
== NFS_MAXPATHLEN
) {
1444 struct nfsnode
*np
= VTONFS(vp
);
1447 panic("nfs_readlinkrpc: null np");
1449 if (np
->n_size
&& np
->n_size
< NFS_MAXPATHLEN
)
1452 nfsm_mtouio(uiop
, len
);
1463 nfs_readrpc(vp
, uiop
, cred
)
1464 register struct vnode
*vp
;
1468 register u_long
*tl
;
1469 register caddr_t cp
;
1470 register long t1
, t2
;
1471 caddr_t bpos
, dpos
, cp2
;
1472 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1473 struct nfsmount
*nmp
;
1474 int error
= 0, len
, retlen
, tsiz
, eof
, attrflag
;
1475 int v3
= NFS_ISV3(vp
);
1481 nmp
= VFSTONFS(vp
->v_mount
);
1482 tsiz
= uiop
->uio_resid
;
1483 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) &&
1487 nfsstats
.rpccnt
[NFSPROC_READ
]++;
1488 len
= (tsiz
> nmp
->nm_rsize
) ? nmp
->nm_rsize
: tsiz
;
1489 nfsm_reqhead(vp
, NFSPROC_READ
, NFSX_FH(v3
) + NFSX_UNSIGNED
* 3);
1491 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
* 3);
1493 txdr_hyper(&uiop
->uio_offset
, tl
);
1494 *(tl
+ 2) = txdr_unsigned(len
);
1496 *tl
++ = txdr_unsigned(uiop
->uio_offset
);
1497 *tl
++ = txdr_unsigned(len
);
1500 nfsm_request(vp
, NFSPROC_READ
, uiop
->uio_procp
, cred
, &xid
);
1502 nfsm_postop_attr(vp
, attrflag
, &xid
);
1507 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1508 eof
= fxdr_unsigned(int, *(tl
+ 1));
1510 nfsm_loadattr(vp
, (struct vattr
*)0, &xid
);
1511 nfsm_strsiz(retlen
, nmp
->nm_rsize
);
1512 nfsm_mtouio(uiop
, retlen
);
1516 if (eof
|| retlen
== 0)
1518 } else if (retlen
< len
)
1529 nfs_writerpc(vp
, uiop
, cred
, iomode
, must_commit
)
1530 register struct vnode
*vp
;
1531 register struct uio
*uiop
;
1533 int *iomode
, *must_commit
;
1535 register u_long
*tl
;
1536 register caddr_t cp
;
1537 register int t1
, t2
, backup
;
1538 caddr_t bpos
, dpos
, cp2
;
1539 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1540 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
1541 int error
= 0, len
, tsiz
, wccflag
= NFSV3_WCCRATTR
, rlen
, commit
;
1542 int v3
= NFS_ISV3(vp
), committed
= NFSV3WRITE_FILESYNC
;
1546 if (uiop
->uio_iovcnt
!= 1)
1547 panic("nfs_writerpc: iovcnt > 1");
1550 tsiz
= uiop
->uio_resid
;
1551 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) && !v3
)
1554 nfsstats
.rpccnt
[NFSPROC_WRITE
]++;
1555 len
= (tsiz
> nmp
->nm_wsize
) ? nmp
->nm_wsize
: tsiz
;
1556 nfsm_reqhead(vp
, NFSPROC_WRITE
,
1557 NFSX_FH(v3
) + 5 * NFSX_UNSIGNED
+ nfsm_rndup(len
));
1560 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
1561 txdr_hyper(&uiop
->uio_offset
, tl
);
1563 *tl
++ = txdr_unsigned(len
);
1564 *tl
++ = txdr_unsigned(*iomode
);
1566 nfsm_build(tl
, u_long
*, 4 * NFSX_UNSIGNED
);
1567 *++tl
= txdr_unsigned(uiop
->uio_offset
);
1570 *tl
= txdr_unsigned(len
);
1571 nfsm_uiotom(uiop
, len
);
1572 nfsm_request(vp
, NFSPROC_WRITE
, uiop
->uio_procp
, cred
, &xid
);
1574 wccflag
= NFSV3_WCCCHK
;
1575 nfsm_wcc_data(vp
, wccflag
, &xid
);
1577 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
+
1579 rlen
= fxdr_unsigned(int, *tl
++);
1583 } else if (rlen
< len
) {
1584 backup
= len
- rlen
;
1585 uiop
->uio_iov
->iov_base
-= backup
;
1586 uiop
->uio_iov
->iov_len
+= backup
;
1587 uiop
->uio_offset
-= backup
;
1588 uiop
->uio_resid
+= backup
;
1591 commit
= fxdr_unsigned(int, *tl
++);
1594 * Return the lowest committment level
1595 * obtained by any of the RPCs.
1597 if (committed
== NFSV3WRITE_FILESYNC
)
1599 else if (committed
== NFSV3WRITE_DATASYNC
&&
1600 commit
== NFSV3WRITE_UNSTABLE
)
1602 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0) {
1603 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1605 nmp
->nm_flag
|= NFSMNT_HASWRITEVERF
;
1606 } else if (bcmp((caddr_t
)tl
,
1607 (caddr_t
)nmp
->nm_verf
, NFSX_V3WRITEVERF
)) {
1609 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1614 nfsm_loadattr(vp
, (struct vattr
*)0, &xid
);
1616 if (wccflag
&& vp
->v_type
!= VBAD
) /* EINVAL set on VBAD node */
1617 VTONFS(vp
)->n_mtime
= VTONFS(vp
)->n_vattr
.va_mtime
.tv_sec
;
1620 * we seem to have a case where we end up looping on shutdown
1621 * and taking down nfs servers. For V3, error cases, there is
1622 * no way to terminate loop, if the len was 0, meaning,
1623 * nmp->nm_wsize was trashed. FreeBSD has this fix in it.
1632 * does it make sense to even say it was committed if we had an error?
1633 * okay well just don't on bad vnodes then. EINVAL will be
1634 * returned on bad vnodes
1636 if (vp
->v_type
!= VBAD
&& (vp
->v_mount
->mnt_flag
& MNT_ASYNC
))
1637 committed
= NFSV3WRITE_FILESYNC
;
1638 *iomode
= committed
;
1640 uiop
->uio_resid
= tsiz
;
1646 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1647 * mode set to specify the file type and the size field for rdev.
1650 nfs_mknodrpc(dvp
, vpp
, cnp
, vap
)
1651 register struct vnode
*dvp
;
1652 register struct vnode
**vpp
;
1653 register struct componentname
*cnp
;
1654 register struct vattr
*vap
;
1656 register struct nfsv2_sattr
*sp
;
1657 register struct nfsv3_sattr
*sp3
;
1658 register u_long
*tl
;
1659 register caddr_t cp
;
1660 register long t1
, t2
;
1661 struct vnode
*newvp
= (struct vnode
*)0;
1662 struct nfsnode
*np
= (struct nfsnode
*)0;
1666 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0;
1667 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1670 int v3
= NFS_ISV3(dvp
);
1672 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
)
1673 rdev
= txdr_unsigned(vap
->va_rdev
);
1674 else if (vap
->va_type
== VFIFO
|| vap
->va_type
== VSOCK
)
1677 VOP_ABORTOP(dvp
, cnp
);
1679 return (EOPNOTSUPP
);
1681 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1682 VOP_ABORTOP(dvp
, cnp
);
1686 nfsstats
.rpccnt
[NFSPROC_MKNOD
]++;
1687 nfsm_reqhead(dvp
, NFSPROC_MKNOD
, NFSX_FH(v3
) + 4 * NFSX_UNSIGNED
+
1688 + nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1689 nfsm_fhtom(dvp
, v3
);
1690 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1692 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
+ NFSX_V3SRVSATTR
);
1693 *tl
++ = vtonfsv3_type(vap
->va_type
);
1694 sp3
= (struct nfsv3_sattr
*)tl
;
1695 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1696 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
) {
1697 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1698 *tl
++ = txdr_unsigned(major(vap
->va_rdev
));
1699 *tl
= txdr_unsigned(minor(vap
->va_rdev
));
1702 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1703 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1704 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1705 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1707 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1708 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1710 nfsm_request(dvp
, NFSPROC_MKNOD
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
1712 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
1716 newvp
= (struct vnode
*)0;
1718 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1719 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1725 nfsm_wcc_data(dvp
, wccflag
, &xid
);
1731 if (cnp
->cn_flags
& MAKEENTRY
)
1732 cache_enter(dvp
, newvp
, cnp
);
1735 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1736 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1737 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1739 VTONFS(dvp
)->n_attrstamp
= 0;
1747 * just call nfs_mknodrpc() to do the work.
1752 struct vop_mknod_args
/* {
1753 struct vnode *a_dvp;
1754 struct vnode **a_vpp;
1755 struct componentname *a_cnp;
1756 struct vattr *a_vap;
1759 struct vnode
*newvp
;
1762 error
= nfs_mknodrpc(ap
->a_dvp
, &newvp
, ap
->a_cnp
, ap
->a_vap
);
1763 if (!error
&& newvp
)
1769 static u_long create_verf
;
1771 * nfs file create call
1775 struct vop_create_args
/* {
1776 struct vnode *a_dvp;
1777 struct vnode **a_vpp;
1778 struct componentname *a_cnp;
1779 struct vattr *a_vap;
1782 register struct vnode
*dvp
= ap
->a_dvp
;
1783 register struct vattr
*vap
= ap
->a_vap
;
1784 register struct componentname
*cnp
= ap
->a_cnp
;
1785 register struct nfsv2_sattr
*sp
;
1786 register struct nfsv3_sattr
*sp3
;
1787 register u_long
*tl
;
1788 register caddr_t cp
;
1789 register long t1
, t2
;
1790 struct nfsnode
*np
= (struct nfsnode
*)0;
1791 struct vnode
*newvp
= (struct vnode
*)0;
1792 caddr_t bpos
, dpos
, cp2
;
1793 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0, fmode
= 0;
1794 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1796 int v3
= NFS_ISV3(dvp
);
1800 * Oops, not for me..
1802 if (vap
->va_type
== VSOCK
)
1803 return (nfs_mknodrpc(dvp
, ap
->a_vpp
, cnp
, vap
));
1805 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1806 VOP_ABORTOP(dvp
, cnp
);
1810 if (vap
->va_vaflags
& VA_EXCLUSIVE
)
1813 nfsstats
.rpccnt
[NFSPROC_CREATE
]++;
1814 nfsm_reqhead(dvp
, NFSPROC_CREATE
, NFSX_FH(v3
) + 2 * NFSX_UNSIGNED
+
1815 nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1816 nfsm_fhtom(dvp
, v3
);
1817 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1819 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1820 if (fmode
& O_EXCL
) {
1821 *tl
= txdr_unsigned(NFSV3CREATE_EXCLUSIVE
);
1822 nfsm_build(tl
, u_long
*, NFSX_V3CREATEVERF
);
1823 if (!TAILQ_EMPTY(&in_ifaddrhead
))
1824 *tl
++ = IA_SIN(in_ifaddrhead
.tqh_first
)->sin_addr
.s_addr
;
1826 *tl
++ = create_verf
;
1827 *tl
= ++create_verf
;
1829 *tl
= txdr_unsigned(NFSV3CREATE_UNCHECKED
);
1830 nfsm_build(tl
, u_long
*, NFSX_V3SRVSATTR
);
1831 sp3
= (struct nfsv3_sattr
*)tl
;
1832 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1835 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1836 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1837 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1838 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1840 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1841 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1843 nfsm_request(dvp
, NFSPROC_CREATE
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
1845 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
1849 newvp
= (struct vnode
*)0;
1851 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1852 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1858 nfsm_wcc_data(dvp
, wccflag
, &xid
);
1861 if (v3
&& (fmode
& O_EXCL
) && error
== NFSERR_NOTSUPP
) {
1867 } else if (v3
&& (fmode
& O_EXCL
))
1868 error
= nfs_setattrrpc(newvp
, vap
, cnp
->cn_cred
, cnp
->cn_proc
);
1870 if (cnp
->cn_flags
& MAKEENTRY
)
1871 cache_enter(dvp
, newvp
, cnp
);
1874 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1875 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1876 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1878 VTONFS(dvp
)->n_attrstamp
= 0;
1885 * nfs file remove call
1886 * To try and make nfs semantics closer to ufs semantics, a file that has
1887 * other processes using the vnode is renamed instead of removed and then
1888 * removed later on the last close.
1889 * - If v_usecount > 1
1890 * If a rename is not already in the works
1891 * call nfs_sillyrename() to set it up
1897 struct vop_remove_args
/* {
1898 struct vnodeop_desc *a_desc;
1899 struct vnode * a_dvp;
1900 struct vnode * a_vp;
1901 struct componentname * a_cnp;
1904 register struct vnode
*vp
= ap
->a_vp
;
1905 register struct vnode
*dvp
= ap
->a_dvp
;
1906 register struct componentname
*cnp
= ap
->a_cnp
;
1907 register struct nfsnode
*np
= VTONFS(vp
);
1908 int error
= 0, gofree
= 0;
1912 if ((cnp
->cn_flags
& HASBUF
) == 0)
1913 panic("nfs_remove: no name");
1914 if (vp
->v_usecount
< 1)
1915 panic("nfs_remove: bad v_usecount");
1918 if (UBCISVALID(vp
)) {
1920 if (UBCINFOEXISTS(vp
))
1921 gofree
= (ubc_isinuse(vp
, 1)) ? 0 : 1;
1923 /* dead or dying vnode.With vnode locking panic instead of error */
1924 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1930 /* UBC not in play */
1931 if (vp
->v_usecount
== 1)
1934 if (gofree
|| (np
->n_sillyrename
&&
1935 VOP_GETATTR(vp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
) == 0 &&
1936 vattr
.va_nlink
> 1)) {
1938 * Purge the name cache so that the chance of a lookup for
1939 * the name succeeding while the remove is in progress is
1940 * minimized. Without node locking it can still happen, such
1941 * that an I/O op returns ESTALE, but since you get this if
1942 * another host removes the file..
1946 * throw away biocache buffers, mainly to avoid
1947 * unnecessary delayed writes later.
1949 error
= nfs_vinvalbuf(vp
, 0, cnp
->cn_cred
, cnp
->cn_proc
, 1);
1951 ubc_setsize(vp
, (off_t
)0); /* XXX check error */
1954 error
= nfs_removerpc(dvp
, cnp
->cn_nameptr
,
1955 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
);
1957 * Kludge City: If the first reply to the remove rpc is lost..
1958 * the reply to the retransmitted request will be ENOENT
1959 * since the file was in fact removed
1960 * Therefore, we cheat and return success.
1962 if (error
== ENOENT
)
1964 } else if (!np
->n_sillyrename
) {
1965 error
= nfs_sillyrename(dvp
, vp
, cnp
);
1968 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1969 np
->n_attrstamp
= 0;
1972 VOP_UNLOCK(vp
, 0, cnp
->cn_proc
);
1980 * nfs file remove rpc called from nfs_inactive
1984 register struct sillyrename
*sp
;
1987 return (nfs_removerpc(sp
->s_dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
1992 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1995 nfs_removerpc(dvp
, name
, namelen
, cred
, proc
)
1996 register struct vnode
*dvp
;
2002 register u_long
*tl
;
2003 register caddr_t cp
;
2004 register long t1
, t2
;
2005 caddr_t bpos
, dpos
, cp2
;
2006 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2007 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2008 int v3
= NFS_ISV3(dvp
);
2011 nfsstats
.rpccnt
[NFSPROC_REMOVE
]++;
2012 nfsm_reqhead(dvp
, NFSPROC_REMOVE
,
2013 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(namelen
));
2014 nfsm_fhtom(dvp
, v3
);
2015 nfsm_strtom(name
, namelen
, NFS_MAXNAMLEN
);
2016 nfsm_request(dvp
, NFSPROC_REMOVE
, proc
, cred
, &xid
);
2018 nfsm_wcc_data(dvp
, wccflag
, &xid
);
2020 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2021 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2023 VTONFS(dvp
)->n_attrstamp
= 0;
2029 * nfs file rename call
2033 struct vop_rename_args
/* {
2034 struct vnode *a_fdvp;
2035 struct vnode *a_fvp;
2036 struct componentname *a_fcnp;
2037 struct vnode *a_tdvp;
2038 struct vnode *a_tvp;
2039 struct componentname *a_tcnp;
2042 register struct vnode
*fvp
= ap
->a_fvp
;
2043 register struct vnode
*tvp
= ap
->a_tvp
;
2044 register struct vnode
*fdvp
= ap
->a_fdvp
;
2045 register struct vnode
*tdvp
= ap
->a_tdvp
;
2046 register struct componentname
*tcnp
= ap
->a_tcnp
;
2047 register struct componentname
*fcnp
= ap
->a_fcnp
;
2048 int error
, purged
=0, inuse
=0;
2051 if ((tcnp
->cn_flags
& HASBUF
) == 0 ||
2052 (fcnp
->cn_flags
& HASBUF
) == 0)
2053 panic("nfs_rename: no name");
2055 /* Check for cross-device rename */
2056 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
2057 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
2060 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2065 * If the tvp exists and is in use, sillyrename it before doing the
2066 * rename of the new file over it.
2067 * XXX Can't sillyrename a directory.
2068 * Don't sillyrename if source and target are same vnode (hard
2069 * links or case-variants)
2071 if (tvp
&& tvp
!= fvp
) {
2072 if (UBCISVALID(tvp
)) {
2074 if (UBCINFOEXISTS(tvp
))
2075 inuse
= (ubc_isinuse(tvp
, 1)) ? 1 : 0;
2077 /* dead or dying vnode.With vnode locking panic instead of error */
2079 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2083 /* UBC not in play */
2084 if (tvp
->v_usecount
> 1)
2088 if (inuse
&& !VTONFS(tvp
)->n_sillyrename
&& tvp
->v_type
!= VDIR
) {
2089 if (error
= nfs_sillyrename(tdvp
, tvp
, tcnp
)) {
2090 /* sillyrename failed. Instead of pressing on, return error */
2091 goto out
; /* should not be ENOENT. */
2093 /* sillyrename succeeded.*/
2094 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2095 ubc_uncache(tvp
); /* get the nfs turd file to disappear */
2101 error
= nfs_renamerpc(fdvp
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
,
2102 tdvp
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
, tcnp
->cn_cred
,
2105 if (fvp
->v_type
== VDIR
) {
2106 if (tvp
!= NULL
&& tvp
->v_type
== VDIR
) {
2118 VOP_UNLOCK(tvp
, 0, tcnp
->cn_proc
);
2119 ubc_uncache(tvp
); /* get the nfs turd file to disappear */
2128 vrele(tvp
); /* already unlocked */
2132 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
2134 if (error
== ENOENT
)
2140 * nfs file rename rpc called from nfs_remove() above
2143 nfs_renameit(sdvp
, scnp
, sp
)
2145 struct componentname
*scnp
;
2146 register struct sillyrename
*sp
;
2148 return (nfs_renamerpc(sdvp
, scnp
->cn_nameptr
, scnp
->cn_namelen
,
2149 sdvp
, sp
->s_name
, sp
->s_namlen
, scnp
->cn_cred
, scnp
->cn_proc
));
2153 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
2156 nfs_renamerpc(fdvp
, fnameptr
, fnamelen
, tdvp
, tnameptr
, tnamelen
, cred
, proc
)
2157 register struct vnode
*fdvp
;
2160 register struct vnode
*tdvp
;
2166 register u_long
*tl
;
2167 register caddr_t cp
;
2168 register long t1
, t2
;
2169 caddr_t bpos
, dpos
, cp2
;
2170 int error
= 0, fwccflag
= NFSV3_WCCRATTR
, twccflag
= NFSV3_WCCRATTR
;
2171 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2172 int v3
= NFS_ISV3(fdvp
);
2175 nfsstats
.rpccnt
[NFSPROC_RENAME
]++;
2176 nfsm_reqhead(fdvp
, NFSPROC_RENAME
,
2177 (NFSX_FH(v3
) + NFSX_UNSIGNED
)*2 + nfsm_rndup(fnamelen
) +
2178 nfsm_rndup(tnamelen
));
2179 nfsm_fhtom(fdvp
, v3
);
2180 nfsm_strtom(fnameptr
, fnamelen
, NFS_MAXNAMLEN
);
2181 nfsm_fhtom(tdvp
, v3
);
2182 nfsm_strtom(tnameptr
, tnamelen
, NFS_MAXNAMLEN
);
2183 nfsm_request(fdvp
, NFSPROC_RENAME
, proc
, cred
, &xid
);
2185 u_int64_t txid
= xid
;
2187 nfsm_wcc_data(fdvp
, fwccflag
, &xid
);
2188 nfsm_wcc_data(tdvp
, twccflag
, &txid
);
2191 if (fdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2192 VTONFS(fdvp
)->n_flag
|= NMODIFIED
;
2194 VTONFS(fdvp
)->n_attrstamp
= 0;
2196 if (tdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2197 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
2199 VTONFS(tdvp
)->n_attrstamp
= 0;
2205 * nfs hard link create call
2209 struct vop_link_args
/* {
2211 struct vnode *a_tdvp;
2212 struct componentname *a_cnp;
2215 register struct vnode
*vp
= ap
->a_vp
;
2216 register struct vnode
*tdvp
= ap
->a_tdvp
;
2217 register struct componentname
*cnp
= ap
->a_cnp
;
2218 register u_long
*tl
;
2219 register caddr_t cp
;
2220 register long t1
, t2
;
2221 caddr_t bpos
, dpos
, cp2
;
2222 int error
= 0, wccflag
= NFSV3_WCCRATTR
, attrflag
= 0;
2223 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2224 int v3
= NFS_ISV3(vp
);
2227 if (vp
->v_mount
!= tdvp
->v_mount
) {
2228 VOP_ABORTOP(vp
, cnp
);
2237 * Push all writes to the server, so that the attribute cache
2238 * doesn't get "out of sync" with the server.
2239 * XXX There should be a better way!
2241 VOP_FSYNC(vp
, cnp
->cn_cred
, MNT_WAIT
, cnp
->cn_proc
);
2243 nfsstats
.rpccnt
[NFSPROC_LINK
]++;
2244 nfsm_reqhead(vp
, NFSPROC_LINK
,
2245 NFSX_FH(v3
)*2 + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2247 nfsm_fhtom(tdvp
, v3
);
2248 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2249 nfsm_request(vp
, NFSPROC_LINK
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2251 u_int64_t txid
= xid
;
2253 nfsm_postop_attr(vp
, attrflag
, &xid
);
2254 nfsm_wcc_data(tdvp
, wccflag
, &txid
);
2257 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2259 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
2260 if (!attrflag
&& vp
->v_type
!= VBAD
) /* EINVAL set on VBAD vnode */
2261 VTONFS(vp
)->n_attrstamp
= 0;
2262 if (!wccflag
&& tdvp
->v_type
!= VBAD
) /* EINVAL set on VBAD vnode */
2263 VTONFS(tdvp
)->n_attrstamp
= 0;
2266 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2268 if (error
== EEXIST
)
2274 * nfs symbolic link create call
2278 struct vop_symlink_args
/* {
2279 struct vnode *a_dvp;
2280 struct vnode **a_vpp;
2281 struct componentname *a_cnp;
2282 struct vattr *a_vap;
2286 register struct vnode
*dvp
= ap
->a_dvp
;
2287 register struct vattr
*vap
= ap
->a_vap
;
2288 register struct componentname
*cnp
= ap
->a_cnp
;
2289 register struct nfsv2_sattr
*sp
;
2290 register struct nfsv3_sattr
*sp3
;
2291 register u_long
*tl
;
2292 register caddr_t cp
;
2293 register long t1
, t2
;
2294 caddr_t bpos
, dpos
, cp2
;
2295 int slen
, error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
;
2296 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2297 struct vnode
*newvp
= (struct vnode
*)0;
2298 int v3
= NFS_ISV3(dvp
);
2301 nfsstats
.rpccnt
[NFSPROC_SYMLINK
]++;
2302 slen
= strlen(ap
->a_target
);
2303 nfsm_reqhead(dvp
, NFSPROC_SYMLINK
, NFSX_FH(v3
) + 2*NFSX_UNSIGNED
+
2304 nfsm_rndup(cnp
->cn_namelen
) + nfsm_rndup(slen
) + NFSX_SATTR(v3
));
2305 nfsm_fhtom(dvp
, v3
);
2306 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2308 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2309 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
,
2310 cnp
->cn_cred
->cr_gid
);
2312 nfsm_strtom(ap
->a_target
, slen
, NFS_MAXPATHLEN
);
2314 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2315 sp
->sa_mode
= vtonfsv2_mode(VLNK
, vap
->va_mode
);
2316 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2317 sp
->sa_gid
= txdr_unsigned(cnp
->cn_cred
->cr_gid
);
2319 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2320 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2322 nfsm_request(dvp
, NFSPROC_SYMLINK
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2324 u_int64_t dxid
= xid
;
2327 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
2328 nfsm_wcc_data(dvp
, wccflag
, &dxid
);
2333 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2334 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2335 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2337 VTONFS(dvp
)->n_attrstamp
= 0;
2341 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2343 if (error
== EEXIST
)
2353 struct vop_mkdir_args
/* {
2354 struct vnode *a_dvp;
2355 struct vnode **a_vpp;
2356 struct componentname *a_cnp;
2357 struct vattr *a_vap;
2360 register struct vnode
*dvp
= ap
->a_dvp
;
2361 register struct vattr
*vap
= ap
->a_vap
;
2362 register struct componentname
*cnp
= ap
->a_cnp
;
2363 register struct nfsv2_sattr
*sp
;
2364 register struct nfsv3_sattr
*sp3
;
2365 register u_long
*tl
;
2366 register caddr_t cp
;
2367 register long t1
, t2
;
2369 struct nfsnode
*np
= (struct nfsnode
*)0;
2370 struct vnode
*newvp
= (struct vnode
*)0;
2371 caddr_t bpos
, dpos
, cp2
;
2372 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2374 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2376 int v3
= NFS_ISV3(dvp
);
2377 u_int64_t xid
, dxid
;
2379 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
2380 VOP_ABORTOP(dvp
, cnp
);
2384 len
= cnp
->cn_namelen
;
2385 nfsstats
.rpccnt
[NFSPROC_MKDIR
]++;
2386 nfsm_reqhead(dvp
, NFSPROC_MKDIR
,
2387 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
) + NFSX_SATTR(v3
));
2388 nfsm_fhtom(dvp
, v3
);
2389 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
2391 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2392 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
2394 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2395 sp
->sa_mode
= vtonfsv2_mode(VDIR
, vap
->va_mode
);
2396 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2397 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
2399 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2400 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2402 nfsm_request(dvp
, NFSPROC_MKDIR
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2405 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
, &xid
);
2407 nfsm_wcc_data(dvp
, wccflag
, &dxid
);
2409 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2410 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2412 VTONFS(dvp
)->n_attrstamp
= 0;
2415 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
2416 * if we can succeed in looking up the directory.
2418 if (error
== EEXIST
|| (!error
&& !gotvp
)) {
2421 newvp
= (struct vnode
*)0;
2423 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
, len
, cnp
->cn_cred
,
2427 if (newvp
->v_type
!= VDIR
)
2436 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2442 * nfs remove directory call
2446 struct vop_rmdir_args
/* {
2447 struct vnode *a_dvp;
2449 struct componentname *a_cnp;
2452 register struct vnode
*vp
= ap
->a_vp
;
2453 register struct vnode
*dvp
= ap
->a_dvp
;
2454 register struct componentname
*cnp
= ap
->a_cnp
;
2455 register u_long
*tl
;
2456 register caddr_t cp
;
2457 register long t1
, t2
;
2458 caddr_t bpos
, dpos
, cp2
;
2459 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2460 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2461 int v3
= NFS_ISV3(dvp
);
2464 nfsstats
.rpccnt
[NFSPROC_RMDIR
]++;
2465 nfsm_reqhead(dvp
, NFSPROC_RMDIR
,
2466 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2467 nfsm_fhtom(dvp
, v3
);
2468 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2469 nfsm_request(dvp
, NFSPROC_RMDIR
, cnp
->cn_proc
, cnp
->cn_cred
, &xid
);
2471 nfsm_wcc_data(dvp
, wccflag
, &xid
);
2473 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2474 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2475 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2477 VTONFS(dvp
)->n_attrstamp
= 0;
2484 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2486 if (error
== ENOENT
)
2496 struct vop_readdir_args
/* {
2499 struct ucred *a_cred;
2502 register struct vnode
*vp
= ap
->a_vp
;
2503 register struct nfsnode
*np
= VTONFS(vp
);
2504 register struct uio
*uio
= ap
->a_uio
;
2508 if (vp
->v_type
!= VDIR
)
2511 * First, check for hit on the EOF offset cache
2513 if (np
->n_direofoffset
> 0 && uio
->uio_offset
>= np
->n_direofoffset
&&
2514 (np
->n_flag
& NMODIFIED
) == 0) {
2515 if (VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) {
2516 if (NQNFS_CKCACHABLE(vp
, ND_READ
)) {
2517 nfsstats
.direofcache_hits
++;
2520 } else if (VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, uio
->uio_procp
) == 0 &&
2521 np
->n_mtime
== vattr
.va_mtime
.tv_sec
) {
2522 nfsstats
.direofcache_hits
++;
2528 * Call nfs_bioread() to do the real work.
2530 tresid
= uio
->uio_resid
;
2531 error
= nfs_bioread(vp
, uio
, 0, ap
->a_cred
, 0);
2533 if (!error
&& uio
->uio_resid
== tresid
)
2534 nfsstats
.direofcache_misses
++;
2540 * Called from below the buffer cache by nfs_doio().
2543 nfs_readdirrpc(vp
, uiop
, cred
)
2545 register struct uio
*uiop
;
2549 register int len
, left
;
2550 register struct dirent
*dp
;
2551 register u_long
*tl
;
2552 register caddr_t cp
;
2553 register long t1
, t2
;
2554 register nfsuint64
*cookiep
;
2555 caddr_t bpos
, dpos
, cp2
;
2556 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2558 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2559 struct nfsnode
*dnp
= VTONFS(vp
);
2561 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, bigenough
= 1;
2563 int v3
= NFS_ISV3(vp
);
2567 dp
= (struct dirent
*)0;
2570 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (NFS_DIRBLKSIZ
- 1)) ||
2571 (uiop
->uio_resid
& (NFS_DIRBLKSIZ
- 1)))
2572 panic("nfs_readdirrpc: bad uio");
2576 * If there is no cookie, assume directory was stale.
2578 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2582 return (NFSERR_BAD_COOKIE
);
2584 * Loop around doing readdir rpc's of size nm_readdirsize
2585 * truncated to a multiple of DIRBLKSIZ.
2586 * The stopping criteria is EOF or buffer full.
2588 while (more_dirs
&& bigenough
) {
2589 nfsstats
.rpccnt
[NFSPROC_READDIR
]++;
2590 nfsm_reqhead(vp
, NFSPROC_READDIR
, NFSX_FH(v3
) +
2594 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
2595 *tl
++ = cookie
.nfsuquad
[0];
2596 *tl
++ = cookie
.nfsuquad
[1];
2597 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2598 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2600 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2601 *tl
++ = cookie
.nfsuquad
[0];
2603 *tl
= txdr_unsigned(nmp
->nm_readdirsize
);
2604 nfsm_request(vp
, NFSPROC_READDIR
, uiop
->uio_procp
, cred
, &xid
);
2606 nfsm_postop_attr(vp
, attrflag
, &xid
);
2608 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2609 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2610 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
;
2616 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2617 more_dirs
= fxdr_unsigned(int, *tl
);
2619 /* loop thru the dir entries, doctoring them to 4bsd form */
2620 while (more_dirs
&& bigenough
) {
2622 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2623 fxdr_hyper(tl
, &fileno
);
2624 len
= fxdr_unsigned(int, *(tl
+ 2));
2626 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2627 fileno
= fxdr_unsigned(u_quad_t
, *tl
++);
2628 len
= fxdr_unsigned(int, *tl
);
2630 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2635 tlen
= nfsm_rndup(len
);
2637 tlen
+= 4; /* To ensure null termination */
2638 left
= DIRBLKSIZ
- blksiz
;
2639 if ((tlen
+ DIRHDSIZ
) > left
) {
2640 dp
->d_reclen
+= left
;
2641 uiop
->uio_iov
->iov_base
+= left
;
2642 uiop
->uio_iov
->iov_len
-= left
;
2643 uiop
->uio_offset
+= left
;
2644 uiop
->uio_resid
-= left
;
2647 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2650 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2651 dp
->d_fileno
= (int)fileno
;
2653 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2654 dp
->d_type
= DT_UNKNOWN
;
2655 blksiz
+= dp
->d_reclen
;
2656 if (blksiz
== DIRBLKSIZ
)
2658 uiop
->uio_offset
+= DIRHDSIZ
;
2659 uiop
->uio_resid
-= DIRHDSIZ
;
2660 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2661 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2662 nfsm_mtouio(uiop
, len
);
2663 cp
= uiop
->uio_iov
->iov_base
;
2665 *cp
= '\0'; /* null terminate */
2666 uiop
->uio_iov
->iov_base
+= tlen
;
2667 uiop
->uio_iov
->iov_len
-= tlen
;
2668 uiop
->uio_offset
+= tlen
;
2669 uiop
->uio_resid
-= tlen
;
2671 nfsm_adv(nfsm_rndup(len
));
2673 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2675 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2678 cookie
.nfsuquad
[0] = *tl
++;
2680 cookie
.nfsuquad
[1] = *tl
++;
2685 more_dirs
= fxdr_unsigned(int, *tl
);
2688 * If at end of rpc data, get the eof boolean
2691 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2692 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2697 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2698 * by increasing d_reclen for the last record.
2701 left
= DIRBLKSIZ
- blksiz
;
2702 dp
->d_reclen
+= left
;
2703 uiop
->uio_iov
->iov_base
+= left
;
2704 uiop
->uio_iov
->iov_len
-= left
;
2705 uiop
->uio_offset
+= left
;
2706 uiop
->uio_resid
-= left
;
2710 * We are now either at the end of the directory or have filled the
2714 dnp
->n_direofoffset
= uiop
->uio_offset
;
2716 if (uiop
->uio_resid
> 0)
2717 printf("EEK! readdirrpc resid > 0\n");
2718 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2726 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2729 nfs_readdirplusrpc(vp
, uiop
, cred
)
2731 register struct uio
*uiop
;
2734 register int len
, left
;
2735 register struct dirent
*dp
;
2736 register u_long
*tl
;
2737 register caddr_t cp
;
2738 register long t1
, t2
;
2739 register struct vnode
*newvp
;
2740 register nfsuint64
*cookiep
;
2741 caddr_t bpos
, dpos
, cp2
, dpossav1
, dpossav2
;
2742 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
, *mdsav1
, *mdsav2
;
2743 struct nameidata nami
, *ndp
= &nami
;
2744 struct componentname
*cnp
= &ndp
->ni_cnd
;
2746 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2747 struct nfsnode
*dnp
= VTONFS(vp
), *np
;
2750 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, doit
, bigenough
= 1, i
;
2751 int attrflag
, fhsize
;
2752 u_int64_t xid
, savexid
;
2755 dp
= (struct dirent
*)0;
2758 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (DIRBLKSIZ
- 1)) ||
2759 (uiop
->uio_resid
& (DIRBLKSIZ
- 1)))
2760 panic("nfs_readdirplusrpc: bad uio");
2766 * If there is no cookie, assume directory was stale.
2768 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2772 return (NFSERR_BAD_COOKIE
);
2774 * Loop around doing readdir rpc's of size nm_readdirsize
2775 * truncated to a multiple of DIRBLKSIZ.
2776 * The stopping criteria is EOF or buffer full.
2778 while (more_dirs
&& bigenough
) {
2779 nfsstats
.rpccnt
[NFSPROC_READDIRPLUS
]++;
2780 nfsm_reqhead(vp
, NFSPROC_READDIRPLUS
,
2781 NFSX_FH(1) + 6 * NFSX_UNSIGNED
);
2783 nfsm_build(tl
, u_long
*, 6 * NFSX_UNSIGNED
);
2784 *tl
++ = cookie
.nfsuquad
[0];
2785 *tl
++ = cookie
.nfsuquad
[1];
2786 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2787 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2788 *tl
++ = txdr_unsigned(nmp
->nm_readdirsize
);
2789 *tl
= txdr_unsigned(nmp
->nm_rsize
);
2790 nfsm_request(vp
, NFSPROC_READDIRPLUS
, uiop
->uio_procp
, cred
,
2793 nfsm_postop_attr(vp
, attrflag
, &xid
);
2798 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2799 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2800 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
++;
2801 more_dirs
= fxdr_unsigned(int, *tl
);
2803 /* loop thru the dir entries, doctoring them to 4bsd form */
2804 while (more_dirs
&& bigenough
) {
2805 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2806 fxdr_hyper(tl
, &fileno
);
2807 len
= fxdr_unsigned(int, *(tl
+ 2));
2808 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2813 tlen
= nfsm_rndup(len
);
2815 tlen
+= 4; /* To ensure null termination*/
2816 left
= DIRBLKSIZ
- blksiz
;
2817 if ((tlen
+ DIRHDSIZ
) > left
) {
2818 dp
->d_reclen
+= left
;
2819 uiop
->uio_iov
->iov_base
+= left
;
2820 uiop
->uio_iov
->iov_len
-= left
;
2821 uiop
->uio_offset
+= left
;
2822 uiop
->uio_resid
-= left
;
2825 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2828 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2829 dp
->d_fileno
= (int)fileno
;
2831 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2832 dp
->d_type
= DT_UNKNOWN
;
2833 blksiz
+= dp
->d_reclen
;
2834 if (blksiz
== DIRBLKSIZ
)
2836 uiop
->uio_offset
+= DIRHDSIZ
;
2837 uiop
->uio_resid
-= DIRHDSIZ
;
2838 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2839 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2840 cnp
->cn_nameptr
= uiop
->uio_iov
->iov_base
;
2841 cnp
->cn_namelen
= len
;
2842 nfsm_mtouio(uiop
, len
);
2843 cp
= uiop
->uio_iov
->iov_base
;
2846 uiop
->uio_iov
->iov_base
+= tlen
;
2847 uiop
->uio_iov
->iov_len
-= tlen
;
2848 uiop
->uio_offset
+= tlen
;
2849 uiop
->uio_resid
-= tlen
;
2851 nfsm_adv(nfsm_rndup(len
));
2852 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2854 cookie
.nfsuquad
[0] = *tl
++;
2855 cookie
.nfsuquad
[1] = *tl
++;
2860 * Since the attributes are before the file handle
2861 * (sigh), we must skip over the attributes and then
2862 * come back and get them.
2864 attrflag
= fxdr_unsigned(int, *tl
);
2868 nfsm_adv(NFSX_V3FATTR
);
2869 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2870 doit
= fxdr_unsigned(int, *tl
);
2872 nfsm_getfh(fhp
, fhsize
, 1);
2873 if (NFS_CMPFH(dnp
, fhp
, fhsize
)) {
2878 if ((error
= nfs_nget(vp
->v_mount
, fhp
,
2891 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
2895 IFTODT(VTTOIF(np
->n_vattr
.va_type
));
2898 for (cp
= cnp
->cn_nameptr
, i
= 1; i
<= len
;
2900 cnp
->cn_hash
+= (unsigned char)*cp
* i
;
2901 if (cnp
->cn_namelen
<= NCHNAMLEN
)
2902 cache_enter(ndp
->ni_dvp
, ndp
->ni_vp
, cnp
);
2905 /* Just skip over the file handle */
2906 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2907 i
= fxdr_unsigned(int, *tl
);
2908 nfsm_adv(nfsm_rndup(i
));
2910 if (newvp
!= NULLVP
) {
2914 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2915 more_dirs
= fxdr_unsigned(int, *tl
);
2918 * If at end of rpc data, get the eof boolean
2921 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2922 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2927 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
2928 * by increasing d_reclen for the last record.
2931 left
= DIRBLKSIZ
- blksiz
;
2932 dp
->d_reclen
+= left
;
2933 uiop
->uio_iov
->iov_base
+= left
;
2934 uiop
->uio_iov
->iov_len
-= left
;
2935 uiop
->uio_offset
+= left
;
2936 uiop
->uio_resid
-= left
;
2940 * We are now either at the end of the directory or have filled the
2944 dnp
->n_direofoffset
= uiop
->uio_offset
;
2946 if (uiop
->uio_resid
> 0)
2947 printf("EEK! readdirplusrpc resid > 0\n");
2948 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2952 if (newvp
!= NULLVP
) {
2963 * Silly rename. To make the NFS filesystem that is stateless look a little
2964 * more like the "ufs" a remove of an active vnode is translated to a rename
2965 * to a funny looking filename that is removed by nfs_inactive on the
2966 * nfsnode. There is the potential for another process on a different client
2967 * to create the same funny name between the nfs_lookitup() fails and the
2968 * nfs_rename() completes, but...
2971 nfs_sillyrename(dvp
, vp
, cnp
)
2972 struct vnode
*dvp
, *vp
;
2973 struct componentname
*cnp
;
2975 register struct sillyrename
*sp
;
2984 if (vp
->v_type
== VDIR
)
2985 panic("nfs_sillyrename: dir");
2987 MALLOC_ZONE(sp
, struct sillyrename
*,
2988 sizeof (struct sillyrename
), M_NFSREQ
, M_WAITOK
);
2989 sp
->s_cred
= crdup(cnp
->cn_cred
);
2993 /* Fudge together a funny name */
2994 pid
= cnp
->cn_proc
->p_pid
;
2995 sp
->s_namlen
= sprintf(sp
->s_name
, ".nfsA%04x4.4", pid
);
2997 /* Try lookitups until we get one that isn't there */
2998 while (nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
2999 cnp
->cn_proc
, (struct nfsnode
**)0) == 0) {
3001 if (sp
->s_name
[4] > 'z') {
3006 if ((error
= nfs_renameit(dvp
, cnp
, sp
)))
3008 error
= nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
3011 kprintf("sillyrename: %s, vp=%x, np=%x, dvp=%x\n",
3012 &sp
->s_name
[0], (unsigned)vp
, (unsigned)np
, (unsigned)dvp
);
3014 np
->n_sillyrename
= sp
;
3019 sp
->s_cred
= NOCRED
;
3021 _FREE_ZONE((caddr_t
)sp
, sizeof (struct sillyrename
), M_NFSREQ
);
3026 * Look up a file name and optionally either update the file handle or
3027 * allocate an nfsnode, depending on the value of npp.
3028 * npp == NULL --> just do the lookup
3029 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
3031 * *npp != NULL --> update the file handle in the vnode
3034 nfs_lookitup(dvp
, name
, len
, cred
, procp
, npp
)
3035 register struct vnode
*dvp
;
3040 struct nfsnode
**npp
;
3042 register u_long
*tl
;
3043 register caddr_t cp
;
3044 register long t1
, t2
;
3045 struct vnode
*newvp
= (struct vnode
*)0;
3046 struct nfsnode
*np
, *dnp
= VTONFS(dvp
);
3047 caddr_t bpos
, dpos
, cp2
;
3048 int error
= 0, fhlen
, attrflag
;
3049 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
3051 int v3
= NFS_ISV3(dvp
);
3054 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
3055 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
3056 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
3057 nfsm_fhtom(dvp
, v3
);
3058 nfsm_strtom(name
, len
, NFS_MAXNAMLEN
);
3059 nfsm_request(dvp
, NFSPROC_LOOKUP
, procp
, cred
, &xid
);
3060 if (npp
&& !error
) {
3061 nfsm_getfh(nfhp
, fhlen
, v3
);
3064 if (np
->n_fhsize
> NFS_SMALLFH
&& fhlen
<= NFS_SMALLFH
) {
3065 _FREE_ZONE((caddr_t
)np
->n_fhp
,
3066 np
->n_fhsize
, M_NFSBIGFH
);
3067 np
->n_fhp
= &np
->n_fh
;
3068 } else if (np
->n_fhsize
<= NFS_SMALLFH
&& fhlen
>NFS_SMALLFH
)
3069 MALLOC_ZONE(np
->n_fhp
, nfsfh_t
*,
3070 fhlen
, M_NFSBIGFH
, M_WAITOK
);
3071 bcopy((caddr_t
)nfhp
, (caddr_t
)np
->n_fhp
, fhlen
);
3072 np
->n_fhsize
= fhlen
;
3074 } else if (NFS_CMPFH(dnp
, nfhp
, fhlen
)) {
3078 error
= nfs_nget(dvp
->v_mount
, nfhp
, fhlen
, &np
);
3086 nfsm_postop_attr(newvp
, attrflag
, &xid
);
3087 if (!attrflag
&& *npp
== NULL
) {
3096 nfsm_loadattr(newvp
, (struct vattr
*)0, &xid
);
3099 if (npp
&& *npp
== NULL
) {
3113 * Nfs Version 3 commit rpc
3116 nfs_commit(vp
, offset
, cnt
, cred
, procp
)
3117 register struct vnode
*vp
;
3123 register caddr_t cp
;
3124 register u_long
*tl
;
3125 register int t1
, t2
;
3126 register struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
3127 caddr_t bpos
, dpos
, cp2
;
3128 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
3129 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
3132 FSDBG(521, vp
, offset
, cnt
, nmp
->nm_flag
);
3133 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0)
3135 nfsstats
.rpccnt
[NFSPROC_COMMIT
]++;
3136 nfsm_reqhead(vp
, NFSPROC_COMMIT
, NFSX_FH(1));
3138 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
3139 txdr_hyper(&offset
, tl
);
3141 *tl
= txdr_unsigned(cnt
);
3142 nfsm_request(vp
, NFSPROC_COMMIT
, procp
, cred
, &xid
);
3143 nfsm_wcc_data(vp
, wccflag
, &xid
);
3145 nfsm_dissect(tl
, u_long
*, NFSX_V3WRITEVERF
);
3146 if (bcmp((caddr_t
)nmp
->nm_verf
, (caddr_t
)tl
,
3147 NFSX_V3WRITEVERF
)) {
3148 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
3150 error
= NFSERR_STALEWRITEVERF
;
3159 * - make nfs_bmap() essentially a no-op that does no translation
3160 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
3161 * (Maybe I could use the process's page mapping, but I was concerned that
3162 * Kernel Write might not be enabled and also figured copyout() would do
3163 * a lot more work than bcopy() and also it currently happens in the
3164 * context of the swapper process (2).
3168 struct vop_bmap_args
/* {
3171 struct vnode **a_vpp;
3177 register struct vnode
*vp
= ap
->a_vp
;
3178 int devBlockSize
= DEV_BSIZE
;
3180 if (ap
->a_vpp
!= NULL
)
3182 if (ap
->a_bnp
!= NULL
)
3183 *ap
->a_bnp
= ap
->a_bn
* btodb(vp
->v_mount
->mnt_stat
.f_iosize
,
3185 if (ap
->a_runp
!= NULL
)
3188 if (ap
->a_runb
!= NULL
)
3196 * For async requests when nfsiod(s) are running, queue the request by
3197 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
3202 struct vop_strategy_args
*ap
;
3204 register struct buf
*bp
= ap
->a_bp
;
3209 if (ISSET(bp
->b_flags
, B_PHYS
))
3210 panic("nfs_strategy: physio");
3211 if (ISSET(bp
->b_flags
, B_ASYNC
))
3212 p
= (struct proc
*)0;
3214 p
= current_proc(); /* XXX */
3215 if (ISSET(bp
->b_flags
, B_READ
))
3220 * If the op is asynchronous and an i/o daemon is waiting
3221 * queue the request, wake it up and wait for completion
3222 * otherwise just do it ourselves.
3224 if (!ISSET(bp
->b_flags
, B_ASYNC
) || nfs_asyncio(bp
, NOCRED
))
3225 error
= nfs_doio(bp
, cr
, p
);
3232 * NB Currently unsupported.
3237 struct vop_mmap_args
/* {
3240 struct ucred *a_cred;
3249 * fsync vnode op. Just call nfs_flush() with commit == 1.
3254 struct vop_fsync_args
/* {
3255 struct vnodeop_desc *a_desc;
3256 struct vnode * a_vp;
3257 struct ucred * a_cred;
3262 return (nfs_flush(ap
->a_vp
, ap
->a_cred
, ap
->a_waitfor
, ap
->a_p
, 1));
3266 * Flush all the blocks associated with a vnode.
3267 * Walk through the buffer pool and push any dirty pages
3268 * associated with the vnode.
3271 nfs_flush(vp
, cred
, waitfor
, p
, commit
)
3272 register struct vnode
*vp
;
3278 register struct nfsnode
*np
= VTONFS(vp
);
3279 register struct buf
*bp
;
3282 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
3283 int s
, error
= 0, slptimeo
= 0, slpflag
= 0, retv
, bvecpos
, err
;
3285 u_quad_t off
, endoff
, toff
;
3286 struct ucred
* wcred
= NULL
;
3287 struct buf
**bvec
= NULL
;
3288 #ifndef NFS_COMMITBVECSIZ
3289 #define NFS_COMMITBVECSIZ 20
3291 struct buf
*bvec_on_stack
[NFS_COMMITBVECSIZ
];
3292 int bvecsize
= 0, bveccount
;
3296 FSDBG_TOP(517, vp
, np
, waitfor
, commit
);
3298 if (nmp
->nm_flag
& NFSMNT_INT
)
3304 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
3305 * server, but nas not been committed to stable storage on the server
3306 * yet. On the first pass, the byte range is worked out and the commit
3307 * rpc is done. On the second pass, nfs_writebp() is called to do the
3311 FSDBG(518, vp
->v_dirtyblkhd
.lh_first
, np
->n_flag
, 0, 0);
3312 if (vp
->v_dirtyblkhd
.lh_first
)
3313 np
->n_flag
|= NMODIFIED
;
3317 if (NFS_ISV3(vp
) && commit
) {
3320 * Count up how many buffers waiting for a commit.
3321 * This is an upper bound - any with dirty pages must be
3322 * written not commited.
3325 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3326 nbp
= bp
->b_vnbufs
.le_next
;
3327 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3328 == (B_DELWRI
| B_NEEDCOMMIT
))
3330 FSDBG(519, bp
, bp
->b_flags
, bveccount
, 0);
3333 * Allocate space to remember the list of bufs to commit. It is
3334 * important to use M_NOWAIT here to avoid a race with nfs_write
3335 * If we can't get memory (for whatever reason), we will end up
3336 * committing the buffers one-by-one in the loop below.
3338 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3339 _FREE(bvec
, M_TEMP
);
3340 if (bveccount
> NFS_COMMITBVECSIZ
) {
3341 MALLOC(bvec
, struct buf
**,
3342 bveccount
* sizeof(struct buf
*), M_TEMP
,
3345 bvec
= bvec_on_stack
;
3346 bvecsize
= NFS_COMMITBVECSIZ
;
3348 bvecsize
= bveccount
;
3350 bvec
= bvec_on_stack
;
3351 bvecsize
= NFS_COMMITBVECSIZ
;
3353 FSDBG(519, 0, bvecsize
, bveccount
, 0);
3355 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3356 nbp
= bp
->b_vnbufs
.le_next
;
3358 FSDBG(520, bp
, bp
->b_flags
, bvecpos
, bp
->b_bufsize
);
3359 FSDBG(520, bp
->b_validoff
, bp
->b_validend
,
3360 bp
->b_dirtyoff
, bp
->b_dirtyend
);
3361 if (bvecpos
>= bvecsize
)
3363 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3364 != (B_DELWRI
| B_NEEDCOMMIT
))
3368 SET(bp
->b_flags
, B_BUSY
);
3370 * we need a upl to see if the page has been
3371 * dirtied (think mmap) since the unstable write, and
3372 * so to prevent vm from paging during our commit rpc
3374 if (ISSET(bp
->b_flags
, B_PAGELIST
)) {
3375 upl
= bp
->b_pagelist
;
3377 kret
= ubc_create_upl(vp
, ubc_blktooff(vp
, bp
->b_lblkno
),
3378 bp
->b_bufsize
, &upl
,
3379 NULL
, UPL_PRECIOUS
);
3380 if (kret
!= KERN_SUCCESS
)
3381 panic("nfs_flush: create upl %d", kret
);
3383 upl_ubc_alias_set(upl
, current_act(), 1);
3384 #endif /* UBC_DEBUG */
3386 if (upl_dirty_page(ubc_upl_pageinfo(upl
), 0)) {
3387 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3388 err
= ubc_upl_abort(upl
, NULL
);
3390 printf("nfs_flush: upl abort %d\n", err
);
3393 * Any/all of it may be modified...
3395 bp
->b_dirtyoff
= bp
->b_validoff
;
3396 bp
->b_dirtyend
= bp
->b_validend
;
3397 CLR(bp
->b_flags
, B_NEEDCOMMIT
);
3398 /* blocking calls were made, re-evaluate nbp */
3399 nbp
= bp
->b_vnbufs
.le_next
;
3400 brelse(bp
); /* XXX may block. Is using nbp ok??? */
3403 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3404 bp
->b_pagelist
= upl
;
3405 SET(bp
->b_flags
, B_PAGELIST
);
3406 ubc_upl_map(upl
, (vm_address_t
*)&bp
->b_data
);
3409 /* blocking calls were made, re-evaluate nbp */
3410 nbp
= bp
->b_vnbufs
.le_next
;
3413 * Work out if all buffers are using the same cred
3414 * so we can deal with them all with one commit.
3417 wcred
= bp
->b_wcred
;
3418 else if (wcred
!= bp
->b_wcred
)
3420 SET(bp
->b_flags
, B_WRITEINPROG
);
3423 * A list of these buffers is kept so that the
3424 * second loop knows which buffers have actually
3425 * been committed. This is necessary, since there
3426 * may be a race between the commit rpc and new
3427 * uncommitted writes on the file.
3429 bvec
[bvecpos
++] = bp
;
3430 toff
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3434 toff
+= (u_quad_t
)(bp
->b_dirtyend
- bp
->b_dirtyoff
);
3442 * Commit data on the server, as required.
3443 * If all bufs are using the same wcred, then use that with
3444 * one call for all of them, otherwise commit each one
3447 if (wcred
!= NOCRED
)
3448 retv
= nfs_commit(vp
, off
, (int)(endoff
- off
),
3452 for (i
= 0; i
< bvecpos
; i
++) {
3455 FSDBG(522, bp
, bp
->b_blkno
* DEV_BSIZE
,
3456 bp
->b_dirtyoff
, bp
->b_dirtyend
);
3457 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3459 size
= (u_quad_t
)(bp
->b_dirtyend
3461 retv
= nfs_commit(vp
, off
, (int)size
,
3467 if (retv
== NFSERR_STALEWRITEVERF
)
3468 nfs_clearcommit(vp
->v_mount
);
3471 * Now, either mark the blocks I/O done or mark the
3472 * blocks dirty, depending on whether the commit
3475 for (i
= 0; i
< bvecpos
; i
++) {
3477 FSDBG(523, bp
, retv
, bp
->b_flags
, 0);
3478 CLR(bp
->b_flags
, (B_NEEDCOMMIT
| B_WRITEINPROG
));
3482 int oldflags
= bp
->b_flags
;
3486 SET(bp
->b_flags
, B_ASYNC
);
3488 (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3489 if (ISSET(oldflags
, B_DELWRI
)) {
3490 extern int nbdwrite
;
3492 wakeup((caddr_t
)&nbdwrite
);
3494 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3495 reassignbuf(bp
, vp
);
3503 * Start/do any write(s) that are required. There is a window here
3504 * where B_BUSY protects the buffer. The vm pages have been freed up,
3505 * yet B_BUSY is set. Don't think you will hit any busy/incore problems
3506 * while we sleep, but not absolutely sure. Keep an eye on it. Otherwise
3507 * we will have to hold vm page across this locked. - EKN
3510 if (current_thread_aborted()) {
3515 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3516 nbp
= bp
->b_vnbufs
.le_next
;
3517 if (ISSET(bp
->b_flags
, B_BUSY
)) {
3518 FSDBG(524, bp
, waitfor
, passone
, bp
->b_flags
);
3519 if (waitfor
!= MNT_WAIT
|| passone
)
3521 SET(bp
->b_flags
, B_WANTED
);
3522 error
= tsleep((caddr_t
)bp
, slpflag
| (PRIBIO
+ 1),
3523 "nfsfsync", slptimeo
);
3526 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3530 if (slpflag
== PCATCH
) {
3537 if (!ISSET(bp
->b_flags
, B_DELWRI
))
3538 panic("nfs_fsync: not dirty");
3539 FSDBG(525, bp
, passone
, commit
, bp
->b_flags
);
3540 if ((passone
|| !commit
) && ISSET(bp
->b_flags
, B_NEEDCOMMIT
))
3543 if (passone
|| !commit
)
3544 SET(bp
->b_flags
, B_BUSY
|B_ASYNC
);
3547 B_BUSY
|B_ASYNC
|B_WRITEINPROG
|B_NEEDCOMMIT
);
3557 if (waitfor
== MNT_WAIT
) {
3558 while (vp
->v_numoutput
) {
3559 vp
->v_flag
|= VBWAIT
;
3560 error
= tsleep((caddr_t
)&vp
->v_numoutput
,
3561 slpflag
| (PRIBIO
+ 1), "nfsfsync", slptimeo
);
3563 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3567 if (slpflag
== PCATCH
) {
3573 if (vp
->v_dirtyblkhd
.lh_first
&& commit
) {
3577 FSDBG(526, np
->n_flag
, np
->n_error
, 0, 0);
3578 if (np
->n_flag
& NWRITEERR
) {
3579 error
= np
->n_error
;
3580 np
->n_flag
&= ~NWRITEERR
;
3583 FSDBG_BOT(517, vp
, np
, error
, 0);
3584 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3585 _FREE(bvec
, M_TEMP
);
3590 * Return POSIX pathconf information applicable to nfs.
3592 * The NFS V2 protocol doesn't support this, so just return EINVAL
3598 struct vop_pathconf_args
/* {
3609 * NFS advisory byte-level locks.
3610 * Currently unsupported.
3614 struct vop_advlock_args
/* {
3623 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3626 * The following kludge is to allow diskless support to work
3627 * until a real NFS lockd is implemented. Basically, just pretend
3628 * that this is a local lock.
3630 return (lf_advlock(ap
, &(np
->n_lockf
), np
->n_size
));
3633 printf("nfs_advlock: pid %d comm %s\n", current_proc()->p_pid
, current_proc()->p_comm
);
3635 return (EOPNOTSUPP
);
3640 * Print out the contents of an nfsnode.
3644 struct vop_print_args
/* {
3648 register struct vnode
*vp
= ap
->a_vp
;
3649 register struct nfsnode
*np
= VTONFS(vp
);
3651 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
3652 np
->n_vattr
.va_fileid
, np
->n_vattr
.va_fsid
);
3653 if (vp
->v_type
== VFIFO
)
3660 * NFS directory offset lookup.
3661 * Currently unsupported.
3665 struct vop_blkatoff_args
/* {
3674 printf("nfs_blkatoff: unimplemented!!");
3676 return (EOPNOTSUPP
);
3680 * NFS flat namespace allocation.
3681 * Currently unsupported.
3685 struct vop_valloc_args
/* {
3686 struct vnode *a_pvp;
3688 struct ucred *a_cred;
3689 struct vnode **a_vpp;
3693 return (EOPNOTSUPP
);
3697 * NFS flat namespace free.
3698 * Currently unsupported.
3702 struct vop_vfree_args
/* {
3703 struct vnode *a_pvp;
3710 printf("nfs_vfree: unimplemented!!");
3712 return (EOPNOTSUPP
);
3716 * NFS file truncation.
3720 struct vop_truncate_args
/* {
3724 struct ucred *a_cred;
3729 /* Use nfs_setattr */
3731 printf("nfs_truncate: unimplemented!!");
3733 return (EOPNOTSUPP
);
3741 struct vop_update_args
/* {
3743 struct timeval *a_ta;
3744 struct timeval *a_tm;
3749 /* Use nfs_setattr */
3751 printf("nfs_update: unimplemented!!");
3753 return (EOPNOTSUPP
);
3756 int nfs_aio_threads
= 0; /* 1 per nfd (arbitrary) */
3757 struct slock nfs_aio_slock
;
3758 TAILQ_HEAD(bqueues
, buf
) nfs_aio_bufq
;
3759 int nfs_aio_bufq_len
= 0; /* diagnostic only */
3763 { /* see comment below in nfs_bwrite() for some rationale */
3765 boolean_t funnel_state
;
3767 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
3769 simple_lock(&nfs_aio_slock
);
3770 if ((bp
= nfs_aio_bufq
.tqh_first
)) {
3771 TAILQ_REMOVE(&nfs_aio_bufq
, bp
, b_freelist
);
3773 simple_unlock(&nfs_aio_slock
);
3775 } else { /* nothing to do - goodnight */
3776 assert_wait(&nfs_aio_bufq
, THREAD_UNINT
);
3777 simple_unlock(&nfs_aio_slock
);
3778 (void)tsleep((caddr_t
)0, PRIBIO
+1, "nfs_aio_bufq", 0);
3781 (void) thread_funnel_set(kernel_flock
, FALSE
);
3786 nfs_aio_thread_init()
3788 if (nfs_aio_threads
++ == 0) {
3789 simple_lock_init(&nfs_aio_slock
);
3790 TAILQ_INIT(&nfs_aio_bufq
);
3792 kernel_thread(kernel_task
, nfs_aio_thread
);
3797 * Just call nfs_writebp() with the force argument set to 1.
3801 struct vop_bwrite_args
/* {
3805 extern void wakeup_one(caddr_t chan
);
3808 * nfs_writebp will issue a synchronous rpc to if B_ASYNC then
3809 * to avoid distributed deadlocks we handoff the write to the
3810 * nfs_aio threads. Doing so allows us to complete the
3811 * current request, rather than blocking on a server which may
3812 * be ourself (or blocked on ourself).
3814 * Note the loopback deadlocks happened when the thread
3815 * invoking us was nfsd, and also when it was the pagedaemon.
3817 * This solution has one known problem. If *ALL* buffers get
3818 * on the nfs_aio queue then no forward progress can be made
3819 * until one of those writes complete. And if the current
3820 * nfs_aio writes-in-progress block due to a non-responsive server we
3821 * are in a deadlock circle. Probably the cure is to limit the
3822 * async write concurrency in getnewbuf as in FreeBSD 3.2.
3824 if (nfs_aio_threads
&& ISSET(ap
->a_bp
->b_flags
, B_ASYNC
)) {
3825 simple_lock(&nfs_aio_slock
);
3827 TAILQ_INSERT_TAIL(&nfs_aio_bufq
, ap
->a_bp
, b_freelist
);
3828 simple_unlock(&nfs_aio_slock
);
3829 wakeup_one((caddr_t
)&nfs_aio_bufq
);
3832 return (nfs_writebp(ap
->a_bp
, 1));
3836 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless
3837 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
3840 nfs_writebp(bp
, force
)
3841 register struct buf
*bp
;
3845 register int oldflags
= bp
->b_flags
, retv
= 1;
3849 struct vnode
*vp
= bp
->b_vp
;
3850 upl_page_info_t
*pl
;
3852 if(!ISSET(bp
->b_flags
, B_BUSY
))
3853 panic("nfs_writebp: buffer is not busy???");
3856 CLR(bp
->b_flags
, (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3857 if (ISSET(oldflags
, B_DELWRI
)) {
3858 extern int nbdwrite
;
3860 wakeup((caddr_t
)&nbdwrite
);
3863 if (ISSET(oldflags
, (B_ASYNC
|B_DELWRI
))) {
3864 reassignbuf(bp
, vp
);
3868 current_proc()->p_stats
->p_ru
.ru_oublock
++;
3872 * Since the B_BUSY flag is set, we need to lock the page before doing
3873 * nfs_commit. Otherwise we may block and get a busy incore pages
3874 * during a vm pageout. Move the existing code up before the commit.
3876 if (!ISSET(bp
->b_flags
, B_META
) && UBCISVALID(vp
) &&
3877 !ISSET(bp
->b_flags
, B_PAGELIST
)) {
3878 kret
= ubc_create_upl(vp
, ubc_blktooff(vp
, bp
->b_lblkno
),
3879 bp
->b_bufsize
, &upl
, &pl
, UPL_PRECIOUS
);
3880 if (kret
!= KERN_SUCCESS
)
3881 panic("nfs_writebp: ubc_create_upl %d", kret
);
3883 upl_ubc_alias_set(upl
, current_act(), 2);
3884 #endif /* UBC_DEBUG */
3886 bp
->b_pagelist
= upl
;
3887 SET(bp
->b_flags
, B_PAGELIST
);
3890 kret
= ubc_upl_map(upl
, (vm_address_t
*)&(bp
->b_data
));
3891 if (kret
!= KERN_SUCCESS
)
3892 panic("nfs_writebp: ubc_upl_map %d", kret
);
3894 panic("nfs_writebp: ubc_upl_map mapped 0");
3895 if (!upl_page_present(pl
, 0)) /* even more paranoia */
3896 panic("nfs_writebp: nopage");
3900 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3901 * an actual write will have to be scheduled via. VOP_STRATEGY().
3902 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3904 if ((oldflags
& (B_NEEDCOMMIT
| B_WRITEINPROG
)) == B_NEEDCOMMIT
) {
3905 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+ bp
->b_dirtyoff
;
3906 SET(bp
->b_flags
, B_WRITEINPROG
);
3907 retv
= nfs_commit(vp
, off
, bp
->b_dirtyend
-bp
->b_dirtyoff
,
3908 bp
->b_wcred
, bp
->b_proc
);
3909 CLR(bp
->b_flags
, B_WRITEINPROG
);
3911 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3912 CLR(bp
->b_flags
, B_NEEDCOMMIT
);
3913 biodone(bp
); /* on B_ASYNC will brelse the buffer */
3915 } else if (retv
== NFSERR_STALEWRITEVERF
)
3916 nfs_clearcommit(vp
->v_mount
);
3920 SET(bp
->b_flags
, B_WRITEINPROG
);
3924 if( (oldflags
& B_ASYNC
) == 0) {
3925 int rtval
= biowait(bp
);
3927 if (oldflags
& B_DELWRI
) {
3929 reassignbuf(bp
, vp
);
3940 * nfs special file access vnode op.
3941 * Essentially just get vattr and then imitate iaccess() since the device is
3942 * local to the client.
3946 struct vop_access_args
/* {
3949 struct ucred *a_cred;
3953 register struct vattr
*vap
;
3955 register struct ucred
*cred
= ap
->a_cred
;
3956 struct vnode
*vp
= ap
->a_vp
;
3957 mode_t mode
= ap
->a_mode
;
3963 * Disallow write attempts on filesystems mounted read-only;
3964 * unless the file is a socket, fifo, or a block or character
3965 * device resident on the filesystem.
3967 if ((mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
3968 switch (vp
->v_type
) {
3969 case VREG
: case VDIR
: case VLNK
:
3974 * If you're the super-user,
3975 * you always get access.
3977 if (cred
->cr_uid
== 0)
3980 error
= VOP_GETATTR(vp
, vap
, cred
, ap
->a_p
);
3984 * Access check is based on only one of owner, group, public.
3985 * If not owner, then check group. If not a member of the
3986 * group, then check public access.
3988 if (cred
->cr_uid
!= vap
->va_uid
) {
3990 gp
= cred
->cr_groups
;
3991 for (i
= 0; i
< cred
->cr_ngroups
; i
++, gp
++)
3992 if (vap
->va_gid
== *gp
)
3998 error
= (vap
->va_mode
& mode
) == mode
? 0 : EACCES
;
4003 * Read wrapper for special devices.
4007 struct vop_read_args
/* {
4011 struct ucred *a_cred;
4014 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4020 np
->n_atim
.tv_sec
= time
.tv_sec
;
4021 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
4022 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_read
), ap
));
4026 * Write wrapper for special devices.
4030 struct vop_write_args
/* {
4034 struct ucred *a_cred;
4037 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4043 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4044 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4045 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_write
), ap
));
4049 * Close wrapper for special devices.
4051 * Update the times on the nfsnode then do device close.
4055 struct vop_close_args
/* {
4058 struct ucred *a_cred;
4062 register struct vnode
*vp
= ap
->a_vp
;
4063 register struct nfsnode
*np
= VTONFS(vp
);
4066 if (np
->n_flag
& (NACC
| NUPD
)) {
4068 if (vp
->v_usecount
== 1 &&
4069 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
4071 if (np
->n_flag
& NACC
)
4072 vattr
.va_atime
= np
->n_atim
;
4073 if (np
->n_flag
& NUPD
)
4074 vattr
.va_mtime
= np
->n_mtim
;
4075 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
4078 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_close
), ap
));
4082 * Read wrapper for fifos.
4086 struct vop_read_args
/* {
4090 struct ucred *a_cred;
4093 extern vop_t
**fifo_vnodeop_p
;
4094 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4100 np
->n_atim
.tv_sec
= time
.tv_sec
;
4101 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
4102 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_read
), ap
));
4106 * Write wrapper for fifos.
4110 struct vop_write_args
/* {
4114 struct ucred *a_cred;
4117 extern vop_t
**fifo_vnodeop_p
;
4118 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4124 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4125 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4126 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_write
), ap
));
4130 * Close wrapper for fifos.
4132 * Update the times on the nfsnode then do fifo close.
4136 struct vop_close_args
/* {
4139 struct ucred *a_cred;
4143 register struct vnode
*vp
= ap
->a_vp
;
4144 register struct nfsnode
*np
= VTONFS(vp
);
4146 extern vop_t
**fifo_vnodeop_p
;
4148 if (np
->n_flag
& (NACC
| NUPD
)) {
4149 if (np
->n_flag
& NACC
) {
4150 np
->n_atim
.tv_sec
= time
.tv_sec
;
4151 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
4153 if (np
->n_flag
& NUPD
) {
4154 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4155 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4158 if (vp
->v_usecount
== 1 &&
4159 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
4161 if (np
->n_flag
& NACC
)
4162 vattr
.va_atime
= np
->n_atim
;
4163 if (np
->n_flag
& NUPD
)
4164 vattr
.va_mtime
= np
->n_mtim
;
4165 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
4168 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_close
), ap
));
4173 struct vop_ioctl_args
*ap
;
4177 * XXX we were once bogusly enoictl() which returned this (ENOTTY).
4178 * Probably we should return ENODEV.
4185 struct vop_select_args
*ap
;
4189 * We were once bogusly seltrue() which returns 1. Is this right?
4194 /* XXX Eliminate use of struct bp here */
4196 * Vnode op for pagein using getblk_pages
4197 * derived from nfs_bioread()
4198 * No read aheads are started from pagein operation
4202 struct vop_pagein_args
/* {
4205 vm_offset_t a_pl_offset,
4208 struct ucred *a_cred,
4212 register struct vnode
*vp
= ap
->a_vp
;
4213 upl_t pl
= ap
->a_pl
;
4214 size_t size
= ap
->a_size
;
4215 off_t f_offset
= ap
->a_f_offset
;
4216 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4217 int flags
= ap
->a_flags
;
4219 register struct nfsnode
*np
= VTONFS(vp
);
4220 register int biosize
;
4221 register int iosize
;
4224 struct proc
*p
= current_proc();
4225 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4230 struct uio
* uio
= &auio
;
4231 int nofreeupl
= flags
& UPL_NOCOMMIT
;
4233 FSDBG(322, f_offset
, size
, pl
, pl_offset
);
4234 if (pl
== (upl_t
)NULL
)
4235 panic("nfs_pagein: no upl");
4237 if (UBCINVALID(vp
)) {
4238 printf("nfs_pagein: invalid vnode 0x%x", (int)vp
);
4240 (void) ubc_upl_abort(pl
, NULL
);
4243 UBCINFOCHECK("nfs_pagein", vp
);
4246 printf("nfs_pagein: invalid size %d", size
);
4248 (void) ubc_upl_abort(pl
, NULL
);
4251 if (f_offset
< 0 || f_offset
>= np
->n_size
||
4252 (f_offset
& PAGE_MASK_64
)) {
4254 ubc_upl_abort_range(pl
, pl_offset
, size
,
4255 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4258 cred
= ubc_getcred(vp
);
4262 auio
.uio_offset
= f_offset
;
4263 auio
.uio_segflg
= UIO_SYSSPACE
;
4264 auio
.uio_rw
= UIO_READ
;
4265 auio
.uio_procp
= NULL
;
4267 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4268 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4269 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4271 if (biosize
& PAGE_MASK
)
4272 panic("nfs_pagein(%x): biosize not page aligned", biosize
);
4274 ubc_upl_map(pl
, &ioaddr
);
4275 ioaddr
+= pl_offset
;
4279 iosize
= min(biosize
, xsize
);
4280 uio
->uio_resid
= iosize
;
4281 auio
.uio_iov
= &aiov
;
4282 auio
.uio_iovcnt
= 1;
4283 aiov
.iov_len
= iosize
;
4284 aiov
.iov_base
= (caddr_t
)ioaddr
;
4286 FSDBG(322, uio
->uio_offset
, uio
->uio_resid
, ioaddr
, xsize
);
4287 #warning our nfs_pagein does not support NQNFS
4289 * With UBC we get here only when the file data is not in the VM
4290 * page cache, so go ahead and read in.
4293 upl_ubc_alias_set(pl
, current_act(), 2);
4294 #endif /* UBC_DEBUG */
4297 error
= nfs_readrpc(vp
, uio
, cred
);
4300 if (uio
->uio_resid
) {
4302 * If uio_resid > 0, there is a hole in the file
4303 * and no writes after the hole have been pushed
4304 * to the server yet... or we're at the EOF
4305 * Just zero fill the rest of the valid area.
4307 int zcnt
= uio
->uio_resid
;
4308 int zoff
= iosize
- zcnt
;
4309 bzero((char *)ioaddr
+ zoff
, zcnt
);
4311 FSDBG(324, uio
->uio_offset
, zoff
, zcnt
, ioaddr
);
4312 uio
->uio_offset
+= zcnt
;
4317 FSDBG(322, uio
->uio_offset
, uio
->uio_resid
, error
, -1);
4319 if (p
&& (vp
->v_flag
& VTEXT
) &&
4320 ((nmp
->nm_flag
& NFSMNT_NQNFS
&&
4321 NQNFS_CKINVALID(vp
, np
, ND_READ
) &&
4322 np
->n_lrev
!= np
->n_brev
) ||
4323 (!(nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4324 np
->n_mtime
!= np
->n_vattr
.va_mtime
.tv_sec
))) {
4325 uprintf("Process killed due to text file modification\n");
4326 psignal(p
, SIGKILL
);
4327 p
->p_flag
|= P_NOSWAP
;
4330 } while (error
== 0 && xsize
> 0);
4336 ubc_upl_abort_range(pl
, pl_offset
, size
,
4338 UPL_ABORT_FREE_ON_EMPTY
);
4340 ubc_upl_commit_range(pl
, pl_offset
, size
,
4341 UPL_COMMIT_CLEAR_DIRTY
|
4342 UPL_COMMIT_FREE_ON_EMPTY
);
4349 * Vnode op for pageout using UPL
4350 * Derived from nfs_write()
4351 * File size changes are not permitted in pageout.
4355 struct vop_pageout_args
/* {
4358 vm_offset_t a_pl_offset,
4361 struct ucred *a_cred,
4365 register struct vnode
*vp
= ap
->a_vp
;
4366 upl_t pl
= ap
->a_pl
;
4367 size_t size
= ap
->a_size
;
4368 off_t f_offset
= ap
->a_f_offset
;
4369 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4370 int flags
= ap
->a_flags
;
4371 int ioflag
= ap
->a_flags
;
4372 register int biosize
;
4373 struct proc
*p
= current_proc();
4374 struct nfsnode
*np
= VTONFS(vp
);
4375 register struct ucred
*cred
;
4377 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4379 int n
= 0, on
, error
= 0, iomode
, must_commit
, s
;
4384 struct uio
* uio
= &auio
;
4385 int nofreeupl
= flags
& UPL_NOCOMMIT
;
4389 FSDBG(323, f_offset
, size
, pl
, pl_offset
);
4391 if (pl
== (upl_t
)NULL
)
4392 panic("nfs_pageout: no upl");
4394 if (UBCINVALID(vp
)) {
4395 printf("nfs_pageout: invalid vnode 0x%x", (int)vp
);
4397 (void) ubc_upl_abort(pl
, NULL
);
4400 UBCINFOCHECK("nfs_pageout", vp
);
4403 printf("nfs_pageout: invalid size %d", size
);
4405 (void) ubc_upl_abort(pl
, NULL
);
4410 * I use nm_rsize, not nm_wsize so that all buffer cache blocks
4411 * will be the same size within a filesystem. nfs_writerpc will
4412 * still use nm_wsize when sizing the rpc's.
4414 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4416 if (biosize
& PAGE_MASK
)
4417 panic("nfs_pageout(%x): biosize not page aligned", biosize
);
4420 * Check to see whether the buffer is incore
4421 * If incore and not busy invalidate it from the cache
4422 * we should not find it BUSY, since we always do a
4423 * vm_fault_list_request in 'getblk' before returning
4424 * which would block on the page busy status
4426 lbn
= f_offset
/ PAGE_SIZE
; /* to match the size getblk uses */
4428 for (iosize
= size
; iosize
> 0; iosize
-= PAGE_SIZE
, lbn
++) {
4430 if (bp
= incore(vp
, lbn
)) {
4431 FSDBG(323, lbn
*PAGE_SIZE
, 1, bp
, bp
->b_flags
);
4432 if (ISSET(bp
->b_flags
, B_BUSY
)) {
4433 /* no panic. just tell vm we are busy */
4435 (void) ubc_upl_abort(pl
, NULL
);
4439 SET(bp
->b_flags
, (B_BUSY
| B_INVAL
));
4445 cred
= ubc_getcred(vp
);
4449 if (np
->n_flag
& NWRITEERR
) {
4450 np
->n_flag
&= ~NWRITEERR
;
4452 ubc_upl_abort_range(pl
, pl_offset
, size
,
4453 UPL_ABORT_FREE_ON_EMPTY
);
4454 return (np
->n_error
);
4456 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4457 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4459 if (f_offset
< 0 || f_offset
>= np
->n_size
||
4460 f_offset
& PAGE_MASK_64
|| size
& PAGE_MASK
) {
4462 ubc_upl_abort_range(pl
, pl_offset
, size
,
4463 UPL_ABORT_FREE_ON_EMPTY
);
4467 ubc_upl_map(pl
, &ioaddr
);
4469 if (f_offset
+ size
> np
->n_size
)
4470 iosize
= np
->n_size
- f_offset
;
4474 pgsize
= (iosize
+ (PAGE_SIZE
- 1)) & ~PAGE_MASK
;
4476 if (size
> pgsize
) {
4478 ubc_upl_abort_range(pl
, pl_offset
+ pgsize
,
4480 UPL_ABORT_FREE_ON_EMPTY
);
4482 auio
.uio_iov
= &aiov
;
4483 auio
.uio_iovcnt
= 1;
4484 auio
.uio_offset
= f_offset
;
4485 auio
.uio_segflg
= UIO_SYSSPACE
;
4486 auio
.uio_rw
= UIO_READ
;
4487 auio
.uio_resid
= iosize
;
4488 auio
.uio_procp
= NULL
;
4490 aiov
.iov_len
= iosize
;
4491 aiov
.iov_base
= (caddr_t
)ioaddr
+ pl_offset
;
4493 * check for partial page and clear the
4494 * contents past end of the file before
4495 * releasing it in the VM page cache
4497 if (f_offset
< np
->n_size
&& f_offset
+ size
> np
->n_size
) {
4498 size_t io
= np
->n_size
- f_offset
;
4500 bzero((caddr_t
)(ioaddr
+ pl_offset
+ io
), size
- io
);
4502 FSDBG(321, np
->n_size
, f_offset
, f_offset
+ io
, size
- io
);
4506 #warning our nfs_pageout does not support NQNFS
4507 nfsstats
.pageouts
++;
4508 lbn
= uio
->uio_offset
/ biosize
;
4509 on
= uio
->uio_offset
& (biosize
-1);
4510 n
= min((unsigned)(biosize
- on
), uio
->uio_resid
);
4513 /* (removed for UBC) */
4515 if ((off_t
)(lbn
+ 1) * biosize
> np
->n_size
) {
4516 bufsize
= np
->n_size
- (off_t
)lbn
* biosize
;
4517 bufsize
= (bufsize
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
4521 /* NMODIFIED would be set here if doing unstable writes */
4522 iomode
= NFSV3WRITE_FILESYNC
;
4523 error
= nfs_writerpc(vp
, uio
, cred
, &iomode
, &must_commit
);
4525 nfs_clearcommit(vp
->v_mount
);
4532 uio
->uio_resid
-= n
;
4533 uio
->uio_offset
+= n
;
4534 uio
->uio_iov
->iov_base
+= n
;
4535 uio
->uio_iov
->iov_len
-= n
;
4537 } while (uio
->uio_resid
> 0 && n
> 0);
4542 * We've had several different solutions on what to do when the pageout
4543 * gets an error. If we don't handle it, and return an error to the
4544 * caller, vm, it will retry . This can end in endless looping
4545 * between vm and here doing retries of the same page. Doing a dump
4546 * back to vm, will get it out of vm's knowledge and we lose whatever
4547 * data existed. This is risky, but in some cases necessary. For
4548 * example, the initial fix here was to do that for ESTALE. In that case
4549 * the server is telling us that the file is no longer the same. We
4550 * would not want to keep paging out to that. We also saw some 151
4551 * errors from Auspex server and NFSv3 can return errors higher than
4552 * ELAST. Those along with NFS known server errors we will "dump" from
4553 * vm. Errors we don't expect to occur, we dump and log for further
4554 * analysis. Errors that could be transient, networking ones,
4555 * we let vm "retry". Lastly, errors that we retry, but may have potential
4556 * to storm the network, we "retrywithsleep". "sever" will be used in
4557 * in the future to dump all pages of object for cases like ESTALE.
4558 * All this is the basis for the states returned and first guesses on
4559 * error handling. Tweaking expected as more statistics are gathered.
4560 * Note, in the long run we may need another more robust solution to
4561 * have some kind of persistant store when the vm cannot dump nor keep
4562 * retrying as a solution, but this would be a file architectural change
4565 if (!nofreeupl
) { /* otherwise stacked file system has to handle this */
4568 short action
= nfs_pageouterrorhandler(error
);
4572 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4575 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4576 if (error
<= ELAST
&&
4577 (errorcount
[error
] % 100 == 0))
4578 printf("nfs_pageout: unexpected error %d. dumping vm page\n", error
);
4579 errorcount
[error
]++;
4582 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4584 case RETRYWITHSLEEP
:
4585 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4586 /* pri unused. PSOCK for placeholder. */
4587 (void) tsleep(&lbolt
, PSOCK
,
4590 case SEVER
: /* not implemented */
4592 printf("nfs_pageout: action %d not expected\n", action
);
4596 ubc_upl_abort_range(pl
, pl_offset
, size
, abortflags
);
4597 /* return error in all cases above */
4600 ubc_upl_commit_range(pl
, pl_offset
, pgsize
,
4601 UPL_COMMIT_CLEAR_DIRTY
|
4602 UPL_COMMIT_FREE_ON_EMPTY
);
4607 /* Blktooff derives file offset given a logical block number */
4610 struct vop_blktooff_args
/* {
4617 register struct vnode
*vp
= ap
->a_vp
;
4619 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4621 *ap
->a_offset
= (off_t
)ap
->a_lblkno
* biosize
;
4628 struct vop_offtoblk_args
/* {
4635 register struct vnode
*vp
= ap
->a_vp
;
4637 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4639 *ap
->a_lblkno
= (daddr_t
)(ap
->a_offset
/ biosize
);
4645 struct vop_cmap_args
/* {
4654 return (EOPNOTSUPP
);