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
67 #include <sys/param.h>
68 #include <sys/kernel.h>
69 #include <sys/systm.h>
70 #include <sys/resourcevar.h>
72 #include <sys/mount.h>
74 #include <sys/malloc.h>
77 #include <sys/namei.h>
78 #include <sys/vnode.h>
79 #include <sys/dirent.h>
80 #include <sys/fcntl.h>
81 #include <sys/lockf.h>
84 #include <ufs/ufs/dir.h>
85 #include <vfs/vfs_support.h>
88 #include <machine/spl.h>
89 #include <vm/vm_pageout.h>
92 #include <kern/clock.h>
94 #include <miscfs/fifofs/fifo.h>
95 #include <miscfs/specfs/specdev.h>
97 #include <nfs/rpcv2.h>
98 #include <nfs/nfsproto.h>
100 #include <nfs/nfsnode.h>
101 #include <nfs/nfsmount.h>
102 #include <nfs/xdr_subs.h>
103 #include <nfs/nfsm_subs.h>
104 #include <nfs/nqnfs.h>
107 #include <netinet/in.h>
108 #include <netinet/in_var.h>
109 #include <kern/task.h>
110 #include <vm/vm_kern.h>
112 #include <sys/kdebug.h>
117 static int nfsspec_read
__P((struct vop_read_args
*));
118 static int nfsspec_write
__P((struct vop_write_args
*));
119 static int nfsfifo_read
__P((struct vop_read_args
*));
120 static int nfsfifo_write
__P((struct vop_write_args
*));
121 static int nfsspec_close
__P((struct vop_close_args
*));
122 static int nfsfifo_close
__P((struct vop_close_args
*));
123 #define nfs_poll vop_nopoll
124 static int nfs_ioctl
__P((struct vop_ioctl_args
*));
125 static int nfs_select
__P((struct vop_select_args
*));
126 static int nfs_flush
__P((struct vnode
*,struct ucred
*,int,struct proc
*,int));
127 static int nfs_setattrrpc
__P((struct vnode
*,struct vattr
*,struct ucred
*,struct proc
*));
128 static int nfs_lookup
__P((struct vop_lookup_args
*));
129 static int nfs_create
__P((struct vop_create_args
*));
130 static int nfs_mknod
__P((struct vop_mknod_args
*));
131 static int nfs_open
__P((struct vop_open_args
*));
132 static int nfs_close
__P((struct vop_close_args
*));
133 static int nfs_access
__P((struct vop_access_args
*));
134 static int nfs_getattr
__P((struct vop_getattr_args
*));
135 static int nfs_setattr
__P((struct vop_setattr_args
*));
136 static int nfs_read
__P((struct vop_read_args
*));
137 static int nfs_mmap
__P((struct vop_mmap_args
*));
138 static int nfs_fsync
__P((struct vop_fsync_args
*));
139 static int nfs_remove
__P((struct vop_remove_args
*));
140 static int nfs_link
__P((struct vop_link_args
*));
141 static int nfs_rename
__P((struct vop_rename_args
*));
142 static int nfs_mkdir
__P((struct vop_mkdir_args
*));
143 static int nfs_rmdir
__P((struct vop_rmdir_args
*));
144 static int nfs_symlink
__P((struct vop_symlink_args
*));
145 static int nfs_readdir
__P((struct vop_readdir_args
*));
146 static int nfs_bmap
__P((struct vop_bmap_args
*));
147 static int nfs_strategy
__P((struct vop_strategy_args
*));
148 static int nfs_lookitup
__P((struct vnode
*,char *,int,struct ucred
*,struct proc
*,struct nfsnode
**));
149 static int nfs_sillyrename
__P((struct vnode
*,struct vnode
*,struct componentname
*));
150 static int nfsspec_access
__P((struct vop_access_args
*));
151 static int nfs_readlink
__P((struct vop_readlink_args
*));
152 static int nfs_print
__P((struct vop_print_args
*));
153 static int nfs_pathconf
__P((struct vop_pathconf_args
*));
154 static int nfs_advlock
__P((struct vop_advlock_args
*));
155 static int nfs_blkatoff
__P((struct vop_blkatoff_args
*));
156 static int nfs_bwrite
__P((struct vop_bwrite_args
*));
157 static int nfs_valloc
__P((struct vop_valloc_args
*));
158 static int nfs_vfree
__P((struct vop_vfree_args
*));
159 static int nfs_truncate
__P((struct vop_truncate_args
*));
160 static int nfs_update
__P((struct vop_update_args
*));
161 static int nfs_pagein
__P((struct vop_pagein_args
*));
162 static int nfs_pageout
__P((struct vop_pageout_args
*));
163 static int nfs_blktooff
__P((struct vop_blktooff_args
*));
164 static int nfs_offtoblk
__P((struct vop_offtoblk_args
*));
165 static int nfs_cmap
__P((struct vop_cmap_args
*));
168 * Global vfs data structures for nfs
170 vop_t
**nfsv2_vnodeop_p
;
171 static struct vnodeopv_entry_desc nfsv2_vnodeop_entries
[] = {
172 { &vop_default_desc
, (vop_t
*)vn_default_error
},
173 { &vop_lookup_desc
, (vop_t
*)nfs_lookup
}, /* lookup */
174 { &vop_create_desc
, (vop_t
*)nfs_create
}, /* create */
175 { &vop_mknod_desc
, (vop_t
*)nfs_mknod
}, /* mknod */
176 { &vop_open_desc
, (vop_t
*)nfs_open
}, /* open */
177 { &vop_close_desc
, (vop_t
*)nfs_close
}, /* close */
178 { &vop_access_desc
, (vop_t
*)nfs_access
}, /* access */
179 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
180 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
181 { &vop_read_desc
, (vop_t
*)nfs_read
}, /* read */
182 { &vop_write_desc
, (vop_t
*)nfs_write
}, /* write */
183 { &vop_lease_desc
, (vop_t
*)nfs_lease_check
}, /* lease */
184 { &vop_ioctl_desc
, (vop_t
*)nfs_ioctl
}, /* ioctl */
185 { &vop_select_desc
, (vop_t
*)nfs_select
}, /* select */
186 { &vop_revoke_desc
, (vop_t
*)nfs_revoke
}, /* revoke */
187 { &vop_mmap_desc
, (vop_t
*)nfs_mmap
}, /* mmap */
188 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
189 { &vop_seek_desc
, (vop_t
*)nfs_seek
}, /* seek */
190 { &vop_remove_desc
, (vop_t
*)nfs_remove
}, /* remove */
191 { &vop_link_desc
, (vop_t
*)nfs_link
}, /* link */
192 { &vop_rename_desc
, (vop_t
*)nfs_rename
}, /* rename */
193 { &vop_mkdir_desc
, (vop_t
*)nfs_mkdir
}, /* mkdir */
194 { &vop_rmdir_desc
, (vop_t
*)nfs_rmdir
}, /* rmdir */
195 { &vop_symlink_desc
, (vop_t
*)nfs_symlink
}, /* symlink */
196 { &vop_readdir_desc
, (vop_t
*)nfs_readdir
}, /* readdir */
197 { &vop_readlink_desc
, (vop_t
*)nfs_readlink
}, /* readlink */
198 { &vop_abortop_desc
, (vop_t
*)nfs_abortop
}, /* abortop */
199 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
200 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
201 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
202 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
203 { &vop_bmap_desc
, (vop_t
*)nfs_bmap
}, /* bmap */
204 { &vop_strategy_desc
, (vop_t
*)nfs_strategy
}, /* strategy */
205 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
206 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
207 { &vop_pathconf_desc
, (vop_t
*)nfs_pathconf
}, /* pathconf */
208 { &vop_advlock_desc
, (vop_t
*)nfs_advlock
}, /* advlock */
209 { &vop_blkatoff_desc
, (vop_t
*)nfs_blkatoff
}, /* blkatoff */
210 { &vop_valloc_desc
, (vop_t
*)nfs_valloc
}, /* valloc */
211 { &vop_reallocblks_desc
, (vop_t
*)nfs_reallocblks
}, /* reallocblks */
212 { &vop_vfree_desc
, (vop_t
*)nfs_vfree
}, /* vfree */
213 { &vop_truncate_desc
, (vop_t
*)nfs_truncate
}, /* truncate */
214 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
215 { &vop_bwrite_desc
, (vop_t
*)nfs_bwrite
}, /* bwrite */
216 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
217 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
218 { &vop_copyfile_desc
, (vop_t
*)err_copyfile
}, /* Copyfile */
219 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
220 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
221 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
224 struct vnodeopv_desc nfsv2_vnodeop_opv_desc
=
225 { &nfsv2_vnodeop_p
, nfsv2_vnodeop_entries
};
227 VNODEOP_SET(nfsv2_vnodeop_opv_desc
);
231 * Special device vnode ops
233 vop_t
**spec_nfsv2nodeop_p
;
234 static struct vnodeopv_entry_desc spec_nfsv2nodeop_entries
[] = {
235 { &vop_default_desc
, (vop_t
*)vn_default_error
},
236 { &vop_lookup_desc
, (vop_t
*)spec_lookup
}, /* lookup */
237 { &vop_create_desc
, (vop_t
*)spec_create
}, /* create */
238 { &vop_mknod_desc
, (vop_t
*)spec_mknod
}, /* mknod */
239 { &vop_open_desc
, (vop_t
*)spec_open
}, /* open */
240 { &vop_close_desc
, (vop_t
*)nfsspec_close
}, /* close */
241 { &vop_access_desc
, (vop_t
*)nfsspec_access
}, /* access */
242 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
243 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
244 { &vop_read_desc
, (vop_t
*)nfsspec_read
}, /* read */
245 { &vop_write_desc
, (vop_t
*)nfsspec_write
}, /* write */
246 { &vop_lease_desc
, (vop_t
*)spec_lease_check
}, /* lease */
247 { &vop_ioctl_desc
, (vop_t
*)spec_ioctl
}, /* ioctl */
248 { &vop_select_desc
, (vop_t
*)spec_select
}, /* select */
249 { &vop_revoke_desc
, (vop_t
*)spec_revoke
}, /* revoke */
250 { &vop_mmap_desc
, (vop_t
*)spec_mmap
}, /* mmap */
251 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
252 { &vop_seek_desc
, (vop_t
*)spec_seek
}, /* seek */
253 { &vop_remove_desc
, (vop_t
*)spec_remove
}, /* remove */
254 { &vop_link_desc
, (vop_t
*)spec_link
}, /* link */
255 { &vop_rename_desc
, (vop_t
*)spec_rename
}, /* rename */
256 { &vop_mkdir_desc
, (vop_t
*)spec_mkdir
}, /* mkdir */
257 { &vop_rmdir_desc
, (vop_t
*)spec_rmdir
}, /* rmdir */
258 { &vop_symlink_desc
, (vop_t
*)spec_symlink
}, /* symlink */
259 { &vop_readdir_desc
, (vop_t
*)spec_readdir
}, /* readdir */
260 { &vop_readlink_desc
, (vop_t
*)spec_readlink
}, /* readlink */
261 { &vop_abortop_desc
, (vop_t
*)spec_abortop
}, /* abortop */
262 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
263 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
264 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
265 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
266 { &vop_bmap_desc
, (vop_t
*)spec_bmap
}, /* bmap */
267 { &vop_strategy_desc
, (vop_t
*)spec_strategy
}, /* strategy */
268 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
269 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
270 { &vop_pathconf_desc
, (vop_t
*)spec_pathconf
}, /* pathconf */
271 { &vop_advlock_desc
, (vop_t
*)spec_advlock
}, /* advlock */
272 { &vop_blkatoff_desc
, (vop_t
*)spec_blkatoff
}, /* blkatoff */
273 { &vop_valloc_desc
, (vop_t
*)spec_valloc
}, /* valloc */
274 { &vop_reallocblks_desc
, (vop_t
*)spec_reallocblks
}, /* reallocblks */
275 { &vop_vfree_desc
, (vop_t
*)spec_vfree
}, /* vfree */
276 { &vop_truncate_desc
, (vop_t
*)spec_truncate
}, /* truncate */
277 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
278 { &vop_bwrite_desc
, (vop_t
*)vn_bwrite
}, /* bwrite */
279 { &vop_devblocksize_desc
, (vop_t
*)spec_devblocksize
}, /* devblocksize */
280 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
281 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
282 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
283 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
284 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
287 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc
=
288 { &spec_nfsv2nodeop_p
, spec_nfsv2nodeop_entries
};
290 VNODEOP_SET(spec_nfsv2nodeop_opv_desc
);
293 vop_t
**fifo_nfsv2nodeop_p
;
294 static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries
[] = {
295 { &vop_default_desc
, (vop_t
*)vn_default_error
},
296 { &vop_lookup_desc
, (vop_t
*)fifo_lookup
}, /* lookup */
297 { &vop_create_desc
, (vop_t
*)fifo_create
}, /* create */
298 { &vop_mknod_desc
, (vop_t
*)fifo_mknod
}, /* mknod */
299 { &vop_open_desc
, (vop_t
*)fifo_open
}, /* open */
300 { &vop_close_desc
, (vop_t
*)nfsfifo_close
}, /* close */
301 { &vop_access_desc
, (vop_t
*)nfsspec_access
}, /* access */
302 { &vop_getattr_desc
, (vop_t
*)nfs_getattr
}, /* getattr */
303 { &vop_setattr_desc
, (vop_t
*)nfs_setattr
}, /* setattr */
304 { &vop_read_desc
, (vop_t
*)nfsfifo_read
}, /* read */
305 { &vop_write_desc
, (vop_t
*)nfsfifo_write
}, /* write */
306 { &vop_lease_desc
, (vop_t
*)fifo_lease_check
}, /* lease */
307 { &vop_ioctl_desc
, (vop_t
*)fifo_ioctl
}, /* ioctl */
308 { &vop_select_desc
, (vop_t
*)fifo_select
}, /* select */
309 { &vop_revoke_desc
, (vop_t
*)fifo_revoke
}, /* revoke */
310 { &vop_mmap_desc
, (vop_t
*)fifo_mmap
}, /* mmap */
311 { &vop_fsync_desc
, (vop_t
*)nfs_fsync
}, /* fsync */
312 { &vop_seek_desc
, (vop_t
*)fifo_seek
}, /* seek */
313 { &vop_remove_desc
, (vop_t
*)fifo_remove
}, /* remove */
314 { &vop_link_desc
, (vop_t
*)fifo_link
}, /* link */
315 { &vop_rename_desc
, (vop_t
*)fifo_rename
}, /* rename */
316 { &vop_mkdir_desc
, (vop_t
*)fifo_mkdir
}, /* mkdir */
317 { &vop_rmdir_desc
, (vop_t
*)fifo_rmdir
}, /* rmdir */
318 { &vop_symlink_desc
, (vop_t
*)fifo_symlink
}, /* symlink */
319 { &vop_readdir_desc
, (vop_t
*)fifo_readdir
}, /* readdir */
320 { &vop_readlink_desc
, (vop_t
*)fifo_readlink
}, /* readlink */
321 { &vop_abortop_desc
, (vop_t
*)fifo_abortop
}, /* abortop */
322 { &vop_inactive_desc
, (vop_t
*)nfs_inactive
}, /* inactive */
323 { &vop_reclaim_desc
, (vop_t
*)nfs_reclaim
}, /* reclaim */
324 { &vop_lock_desc
, (vop_t
*)nfs_lock
}, /* lock */
325 { &vop_unlock_desc
, (vop_t
*)nfs_unlock
}, /* unlock */
326 { &vop_bmap_desc
, (vop_t
*)fifo_bmap
}, /* bmap */
327 { &vop_strategy_desc
, (vop_t
*)fifo_strategy
}, /* strategy */
328 { &vop_print_desc
, (vop_t
*)nfs_print
}, /* print */
329 { &vop_islocked_desc
, (vop_t
*)nfs_islocked
}, /* islocked */
330 { &vop_pathconf_desc
, (vop_t
*)fifo_pathconf
}, /* pathconf */
331 { &vop_advlock_desc
, (vop_t
*)fifo_advlock
}, /* advlock */
332 { &vop_blkatoff_desc
, (vop_t
*)fifo_blkatoff
}, /* blkatoff */
333 { &vop_valloc_desc
, (vop_t
*)fifo_valloc
}, /* valloc */
334 { &vop_reallocblks_desc
, (vop_t
*)fifo_reallocblks
}, /* reallocblks */
335 { &vop_vfree_desc
, (vop_t
*)fifo_vfree
}, /* vfree */
336 { &vop_truncate_desc
, (vop_t
*)fifo_truncate
}, /* truncate */
337 { &vop_update_desc
, (vop_t
*)nfs_update
}, /* update */
338 { &vop_bwrite_desc
, (vop_t
*)vn_bwrite
}, /* bwrite */
339 { &vop_pagein_desc
, (vop_t
*)nfs_pagein
}, /* Pagein */
340 { &vop_pageout_desc
, (vop_t
*)nfs_pageout
}, /* Pageout */
341 { &vop_blktooff_desc
, (vop_t
*)nfs_blktooff
}, /* blktooff */
342 { &vop_offtoblk_desc
, (vop_t
*)nfs_offtoblk
}, /* offtoblk */
343 { &vop_cmap_desc
, (vop_t
*)nfs_cmap
}, /* cmap */
346 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc
=
347 { &fifo_nfsv2nodeop_p
, fifo_nfsv2nodeop_entries
};
349 VNODEOP_SET(fifo_nfsv2nodeop_opv_desc
);
352 static int nfs_commit
__P((struct vnode
*vp
, u_quad_t offset
, int cnt
,
353 struct ucred
*cred
, struct proc
*procp
));
354 static int nfs_mknodrpc
__P((struct vnode
*dvp
, struct vnode
**vpp
,
355 struct componentname
*cnp
,
357 static int nfs_removerpc
__P((struct vnode
*dvp
, char *name
, int namelen
,
358 struct ucred
*cred
, struct proc
*proc
));
359 static int nfs_renamerpc
__P((struct vnode
*fdvp
, char *fnameptr
,
360 int fnamelen
, struct vnode
*tdvp
,
361 char *tnameptr
, int tnamelen
,
362 struct ucred
*cred
, struct proc
*proc
));
363 static int nfs_renameit
__P((struct vnode
*sdvp
,
364 struct componentname
*scnp
,
365 struct sillyrename
*sp
));
370 extern u_long nfs_true
, nfs_false
;
371 extern struct nfsstats nfsstats
;
372 extern nfstype nfsv3_type
[9];
373 struct proc
*nfs_iodwant
[NFS_MAXASYNCDAEMON
];
374 struct nfsmount
*nfs_iodmount
[NFS_MAXASYNCDAEMON
];
375 int nfs_numasync
= 0;
376 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
378 static int nfsaccess_cache_timeout
= NFS_MAXATTRTIMO
;
379 /* SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
380 &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
382 #define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY \
383 | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \
384 | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
388 * the following are needed only by nfs_pageout to know how to handle errors
389 * see nfs_pageout comments on explanation of actions.
390 * the errors here are copied from errno.h and errors returned by servers
391 * are expected to match the same numbers here. If not, our actions maybe
394 enum actiontype
{NOACTION
, DUMP
, DUMPANDLOG
, RETRY
, RETRYWITHSLEEP
, SEVER
};
396 static int errorcount
[ELAST
+1]; /* better be zeros when initialized */
398 static const short errortooutcome
[ELAST
+1] = {
400 DUMP
, /* EPERM 1 Operation not permitted */
401 DUMP
, /* ENOENT 2 No such file or directory */
402 DUMPANDLOG
, /* ESRCH 3 No such process */
403 RETRY
, /* EINTR 4 Interrupted system call */
404 DUMP
, /* EIO 5 Input/output error */
405 DUMP
, /* ENXIO 6 Device not configured */
406 DUMPANDLOG
, /* E2BIG 7 Argument list too long */
407 DUMPANDLOG
, /* ENOEXEC 8 Exec format error */
408 DUMPANDLOG
, /* EBADF 9 Bad file descriptor */
409 DUMPANDLOG
, /* ECHILD 10 No child processes */
410 DUMPANDLOG
, /* EDEADLK 11 Resource deadlock avoided - was EAGAIN */
411 RETRY
, /* ENOMEM 12 Cannot allocate memory */
412 DUMP
, /* EACCES 13 Permission denied */
413 DUMPANDLOG
, /* EFAULT 14 Bad address */
414 DUMPANDLOG
, /* ENOTBLK 15 POSIX - Block device required */
415 RETRY
, /* EBUSY 16 Device busy */
416 DUMP
, /* EEXIST 17 File exists */
417 DUMP
, /* EXDEV 18 Cross-device link */
418 DUMP
, /* ENODEV 19 Operation not supported by device */
419 DUMP
, /* ENOTDIR 20 Not a directory */
420 DUMP
, /* EISDIR 21 Is a directory */
421 DUMP
, /* EINVAL 22 Invalid argument */
422 DUMPANDLOG
, /* ENFILE 23 Too many open files in system */
423 DUMPANDLOG
, /* EMFILE 24 Too many open files */
424 DUMPANDLOG
, /* ENOTTY 25 Inappropriate ioctl for device */
425 DUMPANDLOG
, /* ETXTBSY 26 Text file busy - POSIX */
426 DUMP
, /* EFBIG 27 File too large */
427 DUMP
, /* ENOSPC 28 No space left on device */
428 DUMPANDLOG
, /* ESPIPE 29 Illegal seek */
429 DUMP
, /* EROFS 30 Read-only file system */
430 DUMP
, /* EMLINK 31 Too many links */
431 RETRY
, /* EPIPE 32 Broken pipe */
433 DUMPANDLOG
, /* EDOM 33 Numerical argument out of domain */
434 DUMPANDLOG
, /* ERANGE 34 Result too large */
435 RETRY
, /* EAGAIN/EWOULDBLOCK 35 Resource temporarily unavailable */
436 DUMPANDLOG
, /* EINPROGRESS 36 Operation now in progress */
437 DUMPANDLOG
, /* EALREADY 37 Operation already in progress */
438 /* ipc/network software -- argument errors */
439 DUMPANDLOG
, /* ENOTSOC 38 Socket operation on non-socket */
440 DUMPANDLOG
, /* EDESTADDRREQ 39 Destination address required */
441 DUMPANDLOG
, /* EMSGSIZE 40 Message too long */
442 DUMPANDLOG
, /* EPROTOTYPE 41 Protocol wrong type for socket */
443 DUMPANDLOG
, /* ENOPROTOOPT 42 Protocol not available */
444 DUMPANDLOG
, /* EPROTONOSUPPORT 43 Protocol not supported */
445 DUMPANDLOG
, /* ESOCKTNOSUPPORT 44 Socket type not supported */
446 DUMPANDLOG
, /* ENOTSUP 45 Operation not supported */
447 DUMPANDLOG
, /* EPFNOSUPPORT 46 Protocol family not supported */
448 DUMPANDLOG
, /* EAFNOSUPPORT 47 Address family not supported by protocol family */
449 DUMPANDLOG
, /* EADDRINUSE 48 Address already in use */
450 DUMPANDLOG
, /* EADDRNOTAVAIL 49 Can't assign requested address */
451 /* ipc/network software -- operational errors */
452 RETRY
, /* ENETDOWN 50 Network is down */
453 RETRY
, /* ENETUNREACH 51 Network is unreachable */
454 RETRY
, /* ENETRESET 52 Network dropped connection on reset */
455 RETRY
, /* ECONNABORTED 53 Software caused connection abort */
456 RETRY
, /* ECONNRESET 54 Connection reset by peer */
457 RETRY
, /* ENOBUFS 55 No buffer space available */
458 RETRY
, /* EISCONN 56 Socket is already connected */
459 RETRY
, /* ENOTCONN 57 Socket is not connected */
460 RETRY
, /* ESHUTDOWN 58 Can't send after socket shutdown */
461 RETRY
, /* ETOOMANYREFS 59 Too many references: can't splice */
462 RETRY
, /* ETIMEDOUT 60 Operation timed out */
463 RETRY
, /* ECONNREFUSED 61 Connection refused */
465 DUMPANDLOG
, /* ELOOP 62 Too many levels of symbolic links */
466 DUMP
, /* ENAMETOOLONG 63 File name too long */
467 RETRY
, /* EHOSTDOWN 64 Host is down */
468 RETRY
, /* EHOSTUNREACH 65 No route to host */
469 DUMP
, /* ENOTEMPTY 66 Directory not empty */
471 DUMPANDLOG
, /* PROCLIM 67 Too many processes */
472 DUMPANDLOG
, /* EUSERS 68 Too many users */
473 DUMPANDLOG
, /* EDQUOT 69 Disc quota exceeded */
474 /* Network File System */
475 DUMP
, /* ESTALE 70 Stale NFS file handle */
476 DUMP
, /* EREMOTE 71 Too many levels of remote in path */
477 DUMPANDLOG
, /* EBADRPC 72 RPC struct is bad */
478 DUMPANDLOG
, /* ERPCMISMATCH 73 RPC version wrong */
479 DUMPANDLOG
, /* EPROGUNAVAIL 74 RPC prog. not avail */
480 DUMPANDLOG
, /* EPROGMISMATCH 75 Program version wrong */
481 DUMPANDLOG
, /* EPROCUNAVAIL 76 Bad procedure for program */
483 DUMPANDLOG
, /* ENOLCK 77 No locks available */
484 DUMPANDLOG
, /* ENOSYS 78 Function not implemented */
485 DUMPANDLOG
, /* EFTYPE 79 Inappropriate file type or format */
486 DUMPANDLOG
, /* EAUTH 80 Authentication error */
487 DUMPANDLOG
, /* ENEEDAUTH 81 Need authenticator */
488 /* Intelligent device errors */
489 DUMPANDLOG
, /* EPWROFF 82 Device power is off */
490 DUMPANDLOG
, /* EDEVERR 83 Device error, e.g. paper out */
491 DUMPANDLOG
, /* EOVERFLOW 84 Value too large to be stored in data type */
492 /* Program loading errors */
493 DUMPANDLOG
, /* EBADEXEC 85 Bad executable */
494 DUMPANDLOG
, /* EBADARCH 86 Bad CPU type in executable */
495 DUMPANDLOG
, /* ESHLIBVERS 87 Shared library version mismatch */
496 DUMPANDLOG
, /* EBADMACHO 88 Malformed Macho file */
501 nfs_pageouterrorhandler(error
)
507 return(errortooutcome
[error
]);
511 nfs3_access_otw(struct vnode
*vp
,
518 int error
= 0, attrflag
;
520 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
521 caddr_t bpos
, dpos
, cp2
;
522 register int32_t t1
, t2
;
525 struct nfsnode
*np
= VTONFS(vp
);
527 nfsstats
.rpccnt
[NFSPROC_ACCESS
]++;
528 nfsm_reqhead(vp
, NFSPROC_ACCESS
, NFSX_FH(v3
) + NFSX_UNSIGNED
);
530 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
531 *tl
= txdr_unsigned(wmode
);
532 nfsm_request(vp
, NFSPROC_ACCESS
, p
, cred
);
533 nfsm_postop_attr(vp
, attrflag
);
535 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
536 rmode
= fxdr_unsigned(u_int32_t
, *tl
);
538 np
->n_modeuid
= cred
->cr_uid
;
539 np
->n_modestamp
= time_second
;
546 * nfs access vnode op.
547 * For nfs version 2, just return ok. File accesses may fail later.
548 * For nfs version 3, use the access rpc to check accessibility. If file modes
549 * are changed on the server, accesses might still fail later.
553 struct vop_access_args
/* {
556 struct ucred *a_cred;
560 register struct vnode
*vp
= ap
->a_vp
;
563 int v3
= NFS_ISV3(vp
);
564 struct nfsnode
*np
= VTONFS(vp
);
567 * For nfs v3, do an access rpc, otherwise you are stuck emulating
568 * ufs_access() locally using the vattr. This may not be correct,
569 * since the server may apply other access criteria such as
570 * client uid-->server uid mapping that we do not know about, but
571 * this is better than just returning anything that is lying about
575 if (ap
->a_mode
& VREAD
)
576 mode
= NFSV3ACCESS_READ
;
579 if (vp
->v_type
== VDIR
) {
580 if (ap
->a_mode
& VWRITE
)
581 mode
|= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
|
583 if (ap
->a_mode
& VEXEC
)
584 mode
|= NFSV3ACCESS_LOOKUP
;
586 if (ap
->a_mode
& VWRITE
)
587 mode
|= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
);
588 if (ap
->a_mode
& VEXEC
)
589 mode
|= NFSV3ACCESS_EXECUTE
;
591 /* XXX safety belt, only make blanket request if caching */
592 if (nfsaccess_cache_timeout
> 0) {
593 wmode
= NFSV3ACCESS_READ
| NFSV3ACCESS_MODIFY
|
594 NFSV3ACCESS_EXTEND
| NFSV3ACCESS_EXECUTE
|
595 NFSV3ACCESS_DELETE
| NFSV3ACCESS_LOOKUP
;
600 * Does our cached result allow us to give a definite yes to
603 if ((time_second
< (np
->n_modestamp
+ nfsaccess_cache_timeout
)) &&
604 (ap
->a_cred
->cr_uid
== np
->n_modeuid
) &&
605 ((np
->n_mode
& mode
) == mode
)) {
606 /* nfsstats.accesscache_hits++; */
609 * Either a no, or a don't know. Go to the wire.
611 /* nfsstats.accesscache_misses++; */
612 error
= nfs3_access_otw(vp
, wmode
, ap
->a_p
,ap
->a_cred
);
614 if ((np
->n_mode
& mode
) != mode
)
619 return (nfsspec_access(ap
)); /* NFSv2 case checks for EROFS here */
621 * Disallow write attempts on filesystems mounted read-only;
622 * unless the file is a socket, fifo, or a block or character
623 * device resident on the filesystem.
624 * CSM - moved EROFS check down per NetBSD rev 1.71. So you
625 * get the correct error value with layered filesystems.
626 * EKN - moved the return(error) below this so it does get called.
628 if (!error
&& (ap
->a_mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
629 switch (vp
->v_type
) {
630 case VREG
: case VDIR
: case VLNK
:
641 * Check to see if the type is ok
642 * and that deletion is not in progress.
643 * For paged in text files, you will need to flush the page cache
644 * if consistency is lost.
649 struct vop_open_args
/* {
652 struct ucred *a_cred;
656 register struct vnode
*vp
= ap
->a_vp
;
657 struct nfsnode
*np
= VTONFS(vp
);
658 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
662 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
&& vp
->v_type
!= VLNK
)
663 { printf("open eacces vtyp=%d\n",vp
->v_type
);
667 * Get a valid lease. If cached data is stale, flush it.
669 if (nmp
->nm_flag
& NFSMNT_NQNFS
) {
670 if (NQNFS_CKINVALID(vp
, np
, ND_READ
)) {
672 error
= nqnfs_getlease(vp
, ND_READ
, ap
->a_cred
,
674 } while (error
== NQNFS_EXPIRED
);
677 if (np
->n_lrev
!= np
->n_brev
||
678 (np
->n_flag
& NQNFSNONCACHE
)) {
679 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
680 ap
->a_p
, 1)) == EINTR
)
682 np
->n_brev
= np
->n_lrev
;
686 if (np
->n_flag
& NMODIFIED
) {
687 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
688 ap
->a_p
, 1)) == EINTR
)
691 if (vp
->v_type
== VDIR
)
692 np
->n_direofoffset
= 0;
693 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
696 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
698 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
701 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
702 if (vp
->v_type
== VDIR
)
703 np
->n_direofoffset
= 0;
704 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
,
705 ap
->a_cred
, ap
->a_p
, 1)) == EINTR
)
707 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
711 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) == 0)
712 np
->n_attrstamp
= 0; /* For Open/Close consistency */
718 * What an NFS client should do upon close after writing is a debatable issue.
719 * Most NFS clients push delayed writes to the server upon close, basically for
721 * 1 - So that any write errors may be reported back to the client process
722 * doing the close system call. By far the two most likely errors are
723 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
724 * 2 - To put a worst case upper bound on cache inconsistency between
725 * multiple clients for the file.
726 * There is also a consistency problem for Version 2 of the protocol w.r.t.
727 * not being able to tell if other clients are writing a file concurrently,
728 * since there is no way of knowing if the changed modify time in the reply
729 * is only due to the write for this client.
730 * (NFS Version 3 provides weak cache consistency data in the reply that
731 * should be sufficient to detect and handle this case.)
733 * The current code does the following:
734 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
735 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
736 * or commit them (this satisfies 1 and 2 except for the
737 * case where the server crashes after this close but
738 * before the commit RPC, which is felt to be "good
739 * enough". Changing the last argument to nfs_flush() to
740 * a 1 would force a commit operation, if it is felt a
741 * commit is necessary now.
742 * for NQNFS - do nothing now, since 2 is dealt with via leases and
743 * 1 should be dealt with via an fsync() system call for
744 * cases where write errors are important.
749 struct vop_close_args
/* {
750 struct vnodeop_desc *a_desc;
753 struct ucred *a_cred;
757 register struct vnode
*vp
= ap
->a_vp
;
758 register struct nfsnode
*np
= VTONFS(vp
);
761 if (vp
->v_type
== VREG
) {
763 register struct sillyrename
*sp
= np
->n_sillyrename
;
765 kprintf("nfs_close: %s, dvp=%x, vp=%x, ap=%x, np=%x, sp=%x\n",
766 &sp
->s_name
[0], (unsigned)(sp
->s_dvp
), (unsigned)vp
,
767 (unsigned)ap
, (unsigned)np
, (unsigned)sp
);
769 if ((VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) == 0 &&
770 (np
->n_flag
& NMODIFIED
)) {
772 error
= nfs_flush(vp
, ap
->a_cred
, MNT_WAIT
, ap
->a_p
, 0);
773 np
->n_flag
&= ~NMODIFIED
;
775 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
, ap
->a_p
, 1);
778 if (np
->n_flag
& NWRITEERR
) {
779 np
->n_flag
&= ~NWRITEERR
;
787 * nfs getattr call from vfs.
791 struct vop_getattr_args
/* {
794 struct ucred *a_cred;
798 register struct vnode
*vp
= ap
->a_vp
;
799 register struct nfsnode
*np
= VTONFS(vp
);
805 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
806 int v3
= NFS_ISV3(vp
);
809 * Update local times for special files.
811 if (np
->n_flag
& (NACC
| NUPD
))
814 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 513)) | DBG_FUNC_START
,
815 (int)np
->n_size
, 0, (int)np
->n_vattr
.va_size
, np
->n_flag
, 0);
818 * First look in the cache.
820 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0) {
821 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 513)) | DBG_FUNC_END
,
822 (int)np
->n_size
, 0, (int)np
->n_vattr
.va_size
, np
->n_flag
, 0);
830 if (v3
&& nfsaccess_cache_timeout
> 0) {
831 /* nfsstats.accesscache_misses++; */
832 if (error
= nfs3_access_otw(vp
, NFSV3ACCESS_ALL
, ap
->a_p
, ap
->a_cred
))
834 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0)
841 nfsstats
.rpccnt
[NFSPROC_GETATTR
]++;
842 nfsm_reqhead(vp
, NFSPROC_GETATTR
, NFSX_FH(v3
));
844 nfsm_request(vp
, NFSPROC_GETATTR
, ap
->a_p
, ap
->a_cred
);
846 nfsm_loadattr(vp
, ap
->a_vap
);
847 if (np
->n_mtime
!= ap
->a_vap
->va_mtime
.tv_sec
) {
848 NFSTRACE(NFSTRC_GA_INV
, vp
);
849 if (vp
->v_type
== VDIR
)
851 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
854 NFSTRACE(NFSTRC_GA_INV1
, vp
);
855 np
->n_mtime
= ap
->a_vap
->va_mtime
.tv_sec
;
857 NFSTRACE(NFSTRC_GA_INV2
, error
);
863 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 513)) | DBG_FUNC_END
,
864 (int)np
->n_size
, -1, (int)np
->n_vattr
.va_size
, error
, 0);
874 struct vop_setattr_args
/* {
875 struct vnodeop_desc *a_desc;
878 struct ucred *a_cred;
882 register struct vnode
*vp
= ap
->a_vp
;
883 register struct nfsnode
*np
= VTONFS(vp
);
884 register struct vattr
*vap
= ap
->a_vap
;
892 * Disallow write attempts if the filesystem is mounted read-only.
894 if ((vap
->va_flags
!= VNOVAL
|| vap
->va_uid
!= (uid_t
)VNOVAL
||
895 vap
->va_gid
!= (gid_t
)VNOVAL
|| vap
->va_atime
.tv_sec
!= VNOVAL
||
896 vap
->va_mtime
.tv_sec
!= VNOVAL
|| vap
->va_mode
!= (mode_t
)VNOVAL
) &&
897 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
899 if (vap
->va_size
!= VNOVAL
) {
900 switch (vp
->v_type
) {
907 if (vap
->va_mtime
.tv_sec
== VNOVAL
&&
908 vap
->va_atime
.tv_sec
== VNOVAL
&&
909 vap
->va_mode
== (u_short
)VNOVAL
&&
910 vap
->va_uid
== (uid_t
)VNOVAL
&&
911 vap
->va_gid
== (gid_t
)VNOVAL
)
913 vap
->va_size
= VNOVAL
;
917 * Disallow write attempts if the filesystem is
920 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
922 np
->n_flag
|= NMODIFIED
;
925 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 512)) | DBG_FUNC_START
,
926 (int)np
->n_size
, (int)vap
->va_size
, (int)np
->n_vattr
.va_size
, np
->n_flag
, 0);
928 if (vap
->va_size
== 0)
929 error
= nfs_vinvalbuf(vp
, 0,
930 ap
->a_cred
, ap
->a_p
, 1);
932 error
= nfs_vinvalbuf(vp
, V_SAVE
,
933 ap
->a_cred
, ap
->a_p
, 1);
936 ubc_setsize(vp
, (off_t
)vap
->va_size
); /* XXX check error */
939 printf("nfs_setattr: nfs_vinvalbuf %d\n", error
);
942 kprintf("nfs_setattr: nfs_vinvalbuf %d\n",
944 #endif /* DIAGNOSTIC */
946 ubc_setsize(vp
, (off_t
)tsize
); /* XXX check error */
948 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 512)) | DBG_FUNC_END
,
949 (int)np
->n_size
, (int)vap
->va_size
, (int)np
->n_vattr
.va_size
, -1, 0);
953 np
->n_size
= np
->n_vattr
.va_size
= vap
->va_size
;
956 } else if ((vap
->va_mtime
.tv_sec
!= VNOVAL
||
957 vap
->va_atime
.tv_sec
!= VNOVAL
) && (np
->n_flag
& NMODIFIED
) &&
958 vp
->v_type
== VREG
&&
959 (error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
960 ap
->a_p
, 1)) == EINTR
)
963 error
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
965 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 512)) | DBG_FUNC_END
,
966 (int)np
->n_size
, (int)vap
->va_size
, (int)np
->n_vattr
.va_size
, error
, 0);
968 if (error
&& vap
->va_size
!= VNOVAL
) {
969 /* make every effort to resync file size w/ server... */
970 int err
= 0; /* preserve "error" for return */
972 printf("nfs_setattr: nfs_setattrrpc %d\n", error
);
974 kprintf("nfs_setattr: nfs_setattrrpc %d\n", error
);
975 #endif /* DIAGNOSTIC */
976 np
->n_size
= np
->n_vattr
.va_size
= tsize
;
978 ubc_setsize(vp
, (off_t
)np
->n_size
); /* XXX check error */
979 vap
->va_size
= tsize
;
980 err
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
983 printf("nfs_setattr1: nfs_setattrrpc %d\n", err
);
986 kprintf("nfs_setattr nfs_setattrrpc %d\n", err
);
987 #endif /* DIAGNOSTIC */
993 * Do an nfs setattr rpc.
996 nfs_setattrrpc(vp
, vap
, cred
, procp
)
997 register struct vnode
*vp
;
998 register struct vattr
*vap
;
1002 register struct nfsv2_sattr
*sp
;
1003 register caddr_t cp
;
1004 register long t1
, t2
;
1005 caddr_t bpos
, dpos
, cp2
;
1007 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
1008 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1009 int v3
= NFS_ISV3(vp
);
1011 nfsstats
.rpccnt
[NFSPROC_SETATTR
]++;
1012 nfsm_reqhead(vp
, NFSPROC_SETATTR
, NFSX_FH(v3
) + NFSX_SATTR(v3
));
1015 if (vap
->va_mode
!= (u_short
)VNOVAL
) {
1016 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1018 *tl
= txdr_unsigned(vap
->va_mode
);
1020 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1023 if (vap
->va_uid
!= (uid_t
)VNOVAL
) {
1024 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1026 *tl
= txdr_unsigned(vap
->va_uid
);
1028 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1031 if (vap
->va_gid
!= (gid_t
)VNOVAL
) {
1032 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1034 *tl
= txdr_unsigned(vap
->va_gid
);
1036 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1039 if (vap
->va_size
!= VNOVAL
) {
1040 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1042 txdr_hyper(&vap
->va_size
, tl
);
1044 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1047 if (vap
->va_atime
.tv_sec
!= VNOVAL
) {
1048 if (vap
->va_atime
.tv_sec
!= time
.tv_sec
) {
1049 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1050 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
1051 txdr_nfsv3time(&vap
->va_atime
, tl
);
1053 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1054 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
1057 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1058 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
1060 if (vap
->va_mtime
.tv_sec
!= VNOVAL
) {
1061 if (vap
->va_mtime
.tv_sec
!= time
.tv_sec
) {
1062 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
1063 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
1064 txdr_nfsv3time(&vap
->va_mtime
, tl
);
1066 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1067 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
1070 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1071 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
1073 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1076 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1077 if (vap
->va_mode
== (u_short
)VNOVAL
)
1078 sp
->sa_mode
= VNOVAL
;
1080 sp
->sa_mode
= vtonfsv2_mode(vp
->v_type
, vap
->va_mode
);
1081 if (vap
->va_uid
== (uid_t
)VNOVAL
)
1082 sp
->sa_uid
= VNOVAL
;
1084 sp
->sa_uid
= txdr_unsigned(vap
->va_uid
);
1085 if (vap
->va_gid
== (gid_t
)VNOVAL
)
1086 sp
->sa_gid
= VNOVAL
;
1088 sp
->sa_gid
= txdr_unsigned(vap
->va_gid
);
1089 sp
->sa_size
= txdr_unsigned(vap
->va_size
);
1090 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1091 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1093 nfsm_request(vp
, NFSPROC_SETATTR
, procp
, cred
);
1095 nfsm_wcc_data(vp
, wccflag
);
1096 if ((!wccflag
) && (vp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
1097 VTONFS(vp
)->n_attrstamp
= 0;
1099 nfsm_loadattr(vp
, (struct vattr
*)0);
1105 * nfs lookup call, one step at a time...
1106 * First look in cache
1107 * If not found, unlock the directory nfsnode and do the rpc
1111 struct vop_lookup_args
/* {
1112 struct vnodeop_desc *a_desc;
1113 struct vnode *a_dvp;
1114 struct vnode **a_vpp;
1115 struct componentname *a_cnp;
1118 register struct componentname
*cnp
= ap
->a_cnp
;
1119 register struct vnode
*dvp
= ap
->a_dvp
;
1120 register struct vnode
**vpp
= ap
->a_vpp
;
1121 register int flags
= cnp
->cn_flags
;
1122 register struct vnode
*newvp
;
1123 register u_long
*tl
;
1124 register caddr_t cp
;
1125 register long t1
, t2
;
1126 struct nfsmount
*nmp
;
1127 caddr_t bpos
, dpos
, cp2
;
1128 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1132 int lockparent
, wantparent
, error
= 0, attrflag
, fhsize
;
1133 int v3
= NFS_ISV3(dvp
);
1134 struct proc
*p
= cnp
->cn_proc
;
1135 int worldbuildworkaround
= 1;
1137 if ((flags
& ISLASTCN
) && (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
) &&
1138 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
))
1141 if (dvp
->v_type
!= VDIR
)
1143 lockparent
= flags
& LOCKPARENT
;
1144 wantparent
= flags
& (LOCKPARENT
|WANTPARENT
);
1145 nmp
= VFSTONFS(dvp
->v_mount
);
1148 if (worldbuildworkaround
) {
1150 * Temporary workaround for world builds to not have dvp go
1151 * VBAD on during server calls in this routine. When
1152 * the real ref counting problem is found take this out.
1153 * Note if this was later and before the nfsm_request
1154 * set up, the workaround did not work (NOTE other difference
1155 * was I only put one VREF in that time. Thus it needs
1156 * to be above the cache_lookup branch or with 2 VREFS. Not
1157 * sure which. Can't play with world builds right now to see
1158 * which. VOP_ACCESS could also make it go to server. - EKN
1160 VREF(dvp
); /* hang on to this dvp - EKN */
1161 VREF(dvp
); /* hang on tight - EKN */
1164 if ((error
= cache_lookup(dvp
, vpp
, cnp
)) && error
!= ENOENT
) {
1168 if ((error
= VOP_ACCESS(dvp
, VEXEC
, cnp
->cn_cred
, p
))) {
1173 /* got to check to make sure the vnode didn't go away if access went to server */
1174 if ((*vpp
)->v_type
== VBAD
) {
1182 * See the comment starting `Step through' in ufs/ufs_lookup.c
1183 * for an explanation of the locking protocol
1188 } else if (flags
& ISDOTDOT
) {
1189 VOP_UNLOCK(dvp
, 0, p
);
1190 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1191 if (!error
&& lockparent
&& (flags
& ISLASTCN
))
1192 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1194 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1195 if (!lockparent
|| error
|| !(flags
& ISLASTCN
))
1196 VOP_UNLOCK(dvp
, 0, p
);
1199 if (vpid
== newvp
->v_id
) {
1200 if (!VOP_GETATTR(newvp
, &vattr
, cnp
->cn_cred
, p
)
1201 && vattr
.va_ctime
.tv_sec
== VTONFS(newvp
)->n_ctime
) {
1202 nfsstats
.lookupcache_hits
++;
1203 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1204 cnp
->cn_flags
|= SAVENAME
;
1205 error
= 0; /* ignore any from VOP_GETATTR */
1211 if (lockparent
&& dvp
!= newvp
&& (flags
& ISLASTCN
))
1212 VOP_UNLOCK(dvp
, 0, p
);
1214 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1221 * Got to check to make sure the vnode didn't go away if VOP_GETATTR went to server
1222 * or callers prior to this blocked and had it go VBAD.
1224 if (dvp
->v_type
== VBAD
) {
1231 nfsstats
.lookupcache_misses
++;
1232 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
1233 len
= cnp
->cn_namelen
;
1234 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
1235 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
1236 nfsm_fhtom(dvp
, v3
);
1237 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
1238 /* nfsm_request for NFSv2 causes you to goto to nfsmout upon errors */
1239 nfsm_request(dvp
, NFSPROC_LOOKUP
, cnp
->cn_proc
, cnp
->cn_cred
);
1242 nfsm_postop_attr(dvp
, attrflag
);
1246 nfsm_getfh(fhp
, fhsize
, v3
);
1249 * Handle RENAME case...
1251 if (cnp
->cn_nameiop
== RENAME
&& wantparent
&& (flags
& ISLASTCN
)) {
1252 if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1257 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1263 nfsm_postop_attr(newvp
, attrflag
);
1264 nfsm_postop_attr(dvp
, attrflag
);
1266 nfsm_loadattr(newvp
, (struct vattr
*)0);
1269 cnp
->cn_flags
|= SAVENAME
;
1271 VOP_UNLOCK(dvp
, 0, p
);
1276 if (flags
& ISDOTDOT
) {
1277 VOP_UNLOCK(dvp
, 0, p
);
1278 error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
);
1280 vn_lock(dvp
, LK_EXCLUSIVE
+ LK_RETRY
, p
);
1284 if (lockparent
&& (flags
& ISLASTCN
) &&
1285 (error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
))) {
1289 } else if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1293 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1297 if (!lockparent
|| !(flags
& ISLASTCN
))
1298 VOP_UNLOCK(dvp
, 0, p
);
1302 nfsm_postop_attr(newvp
, attrflag
);
1303 nfsm_postop_attr(dvp
, attrflag
);
1305 nfsm_loadattr(newvp
, (struct vattr
*)0);
1306 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1307 cnp
->cn_flags
|= SAVENAME
;
1308 if ((cnp
->cn_flags
& MAKEENTRY
) &&
1309 (cnp
->cn_nameiop
!= DELETE
|| !(flags
& ISLASTCN
))) {
1310 np
->n_ctime
= np
->n_vattr
.va_ctime
.tv_sec
;
1311 cache_enter(dvp
, newvp
, cnp
);
1316 if (newvp
!= NULLVP
) {
1320 if ((cnp
->cn_nameiop
== CREATE
|| cnp
->cn_nameiop
== RENAME
) &&
1321 (flags
& ISLASTCN
) && error
== ENOENT
) {
1323 VOP_UNLOCK(dvp
, 0, p
);
1324 if (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
)
1327 error
= EJUSTRETURN
;
1329 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1330 cnp
->cn_flags
|= SAVENAME
;
1334 * These "vreles" set dvp refcounts back to where they were
1335 * before we took extra 2 VREFS to avoid VBAD vnode on dvp
1336 * during server calls for world builds. Remove when real
1337 * fix is found. - EKN
1339 if (worldbuildworkaround
) {
1340 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1341 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1349 * Just call nfs_bioread() to do the work.
1353 struct vop_read_args
/* {
1357 struct ucred *a_cred;
1360 register struct vnode
*vp
= ap
->a_vp
;
1362 if (vp
->v_type
!= VREG
)
1364 return (nfs_bioread(vp
, ap
->a_uio
, ap
->a_ioflag
, ap
->a_cred
, 0));
1372 struct vop_readlink_args
/* {
1375 struct ucred *a_cred;
1378 register struct vnode
*vp
= ap
->a_vp
;
1380 if (vp
->v_type
!= VLNK
)
1382 return (nfs_bioread(vp
, ap
->a_uio
, 0, ap
->a_cred
, 0));
1386 * Do a readlink rpc.
1387 * Called by nfs_doio() from below the buffer cache.
1390 nfs_readlinkrpc(vp
, uiop
, cred
)
1391 register struct vnode
*vp
;
1395 register u_long
*tl
;
1396 register caddr_t cp
;
1397 register long t1
, t2
;
1398 caddr_t bpos
, dpos
, cp2
;
1399 int error
= 0, len
, attrflag
;
1400 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1401 int v3
= NFS_ISV3(vp
);
1403 nfsstats
.rpccnt
[NFSPROC_READLINK
]++;
1404 nfsm_reqhead(vp
, NFSPROC_READLINK
, NFSX_FH(v3
));
1406 nfsm_request(vp
, NFSPROC_READLINK
, uiop
->uio_procp
, cred
);
1408 nfsm_postop_attr(vp
, attrflag
);
1410 nfsm_strsiz(len
, NFS_MAXPATHLEN
);
1411 if (len
== NFS_MAXPATHLEN
) {
1412 struct nfsnode
*np
= VTONFS(vp
);
1415 panic("nfs_readlinkrpc: null np");
1417 if (np
->n_size
&& np
->n_size
< NFS_MAXPATHLEN
)
1420 nfsm_mtouio(uiop
, len
);
1431 nfs_readrpc(vp
, uiop
, cred
)
1432 register struct vnode
*vp
;
1436 register u_long
*tl
;
1437 register caddr_t cp
;
1438 register long t1
, t2
;
1439 caddr_t bpos
, dpos
, cp2
;
1440 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1441 struct nfsmount
*nmp
;
1442 int error
= 0, len
, retlen
, tsiz
, eof
, attrflag
;
1443 int v3
= NFS_ISV3(vp
);
1448 nmp
= VFSTONFS(vp
->v_mount
);
1449 tsiz
= uiop
->uio_resid
;
1450 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) && !v3
)
1453 nfsstats
.rpccnt
[NFSPROC_READ
]++;
1454 len
= (tsiz
> nmp
->nm_rsize
) ? nmp
->nm_rsize
: tsiz
;
1455 nfsm_reqhead(vp
, NFSPROC_READ
, NFSX_FH(v3
) + NFSX_UNSIGNED
* 3);
1457 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
* 3);
1459 txdr_hyper(&uiop
->uio_offset
, tl
);
1460 *(tl
+ 2) = txdr_unsigned(len
);
1462 *tl
++ = txdr_unsigned(uiop
->uio_offset
);
1463 *tl
++ = txdr_unsigned(len
);
1466 nfsm_request(vp
, NFSPROC_READ
, uiop
->uio_procp
, cred
);
1468 nfsm_postop_attr(vp
, attrflag
);
1473 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1474 eof
= fxdr_unsigned(int, *(tl
+ 1));
1476 nfsm_loadattr(vp
, (struct vattr
*)0);
1477 nfsm_strsiz(retlen
, nmp
->nm_rsize
);
1478 nfsm_mtouio(uiop
, retlen
);
1482 if (eof
|| retlen
== 0)
1484 } else if (retlen
< len
)
1495 nfs_writerpc(vp
, uiop
, cred
, iomode
, must_commit
)
1496 register struct vnode
*vp
;
1497 register struct uio
*uiop
;
1499 int *iomode
, *must_commit
;
1501 register u_long
*tl
;
1502 register caddr_t cp
;
1503 register int t1
, t2
, backup
;
1504 caddr_t bpos
, dpos
, cp2
;
1505 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1506 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
1507 int error
= 0, len
, tsiz
, wccflag
= NFSV3_WCCRATTR
, rlen
, commit
;
1508 int v3
= NFS_ISV3(vp
), committed
= NFSV3WRITE_FILESYNC
;
1511 if (uiop
->uio_iovcnt
!= 1)
1512 panic("nfs_writerpc: iovcnt > 1");
1515 tsiz
= uiop
->uio_resid
;
1516 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) && !v3
)
1519 nfsstats
.rpccnt
[NFSPROC_WRITE
]++;
1520 len
= (tsiz
> nmp
->nm_wsize
) ? nmp
->nm_wsize
: tsiz
;
1521 nfsm_reqhead(vp
, NFSPROC_WRITE
,
1522 NFSX_FH(v3
) + 5 * NFSX_UNSIGNED
+ nfsm_rndup(len
));
1525 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
1526 txdr_hyper(&uiop
->uio_offset
, tl
);
1528 *tl
++ = txdr_unsigned(len
);
1529 *tl
++ = txdr_unsigned(*iomode
);
1531 nfsm_build(tl
, u_long
*, 4 * NFSX_UNSIGNED
);
1532 *++tl
= txdr_unsigned(uiop
->uio_offset
);
1535 *tl
= txdr_unsigned(len
);
1536 nfsm_uiotom(uiop
, len
);
1537 nfsm_request(vp
, NFSPROC_WRITE
, uiop
->uio_procp
, cred
);
1539 wccflag
= NFSV3_WCCCHK
;
1540 nfsm_wcc_data(vp
, wccflag
);
1542 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
+
1544 rlen
= fxdr_unsigned(int, *tl
++);
1548 } else if (rlen
< len
) {
1549 backup
= len
- rlen
;
1550 uiop
->uio_iov
->iov_base
-= backup
;
1551 uiop
->uio_iov
->iov_len
+= backup
;
1552 uiop
->uio_offset
-= backup
;
1553 uiop
->uio_resid
+= backup
;
1556 commit
= fxdr_unsigned(int, *tl
++);
1559 * Return the lowest committment level
1560 * obtained by any of the RPCs.
1562 if (committed
== NFSV3WRITE_FILESYNC
)
1564 else if (committed
== NFSV3WRITE_DATASYNC
&&
1565 commit
== NFSV3WRITE_UNSTABLE
)
1567 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0) {
1568 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1570 nmp
->nm_flag
|= NFSMNT_HASWRITEVERF
;
1571 } else if (bcmp((caddr_t
)tl
,
1572 (caddr_t
)nmp
->nm_verf
, NFSX_V3WRITEVERF
)) {
1574 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1579 nfsm_loadattr(vp
, (struct vattr
*)0);
1580 if ((wccflag
) && (vp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
1581 VTONFS(vp
)->n_mtime
= VTONFS(vp
)->n_vattr
.va_mtime
.tv_sec
;
1584 * we seem to have a case where we end up looping on shutdown and taking down nfs servers.
1585 * For V3, error cases, there is no way to terminate loop, if the len was 0, meaning,
1586 * nmp->nm_wsize was trashed. FreeBSD has this fix in it. Let's try it.
1593 /* does it make sense to even say it was committed if we had an error? EKN */
1594 /* okay well just don't on bad vnodes then. EINVAL will be returned on bad vnodes */
1595 if ((vp
->v_type
!= VBAD
) && (vp
->v_mount
->mnt_flag
& MNT_ASYNC
))
1596 committed
= NFSV3WRITE_FILESYNC
;
1597 *iomode
= committed
;
1599 uiop
->uio_resid
= tsiz
;
1605 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1606 * mode set to specify the file type and the size field for rdev.
1609 nfs_mknodrpc(dvp
, vpp
, cnp
, vap
)
1610 register struct vnode
*dvp
;
1611 register struct vnode
**vpp
;
1612 register struct componentname
*cnp
;
1613 register struct vattr
*vap
;
1615 register struct nfsv2_sattr
*sp
;
1616 register struct nfsv3_sattr
*sp3
;
1617 register u_long
*tl
;
1618 register caddr_t cp
;
1619 register long t1
, t2
;
1620 struct vnode
*newvp
= (struct vnode
*)0;
1621 struct nfsnode
*np
= (struct nfsnode
*)0;
1625 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0;
1626 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1628 int v3
= NFS_ISV3(dvp
);
1630 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
)
1631 rdev
= txdr_unsigned(vap
->va_rdev
);
1632 else if (vap
->va_type
== VFIFO
|| vap
->va_type
== VSOCK
)
1635 VOP_ABORTOP(dvp
, cnp
);
1637 return (EOPNOTSUPP
);
1639 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1640 VOP_ABORTOP(dvp
, cnp
);
1644 nfsstats
.rpccnt
[NFSPROC_MKNOD
]++;
1645 nfsm_reqhead(dvp
, NFSPROC_MKNOD
, NFSX_FH(v3
) + 4 * NFSX_UNSIGNED
+
1646 + nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1647 nfsm_fhtom(dvp
, v3
);
1648 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1650 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
+ NFSX_V3SRVSATTR
);
1651 *tl
++ = vtonfsv3_type(vap
->va_type
);
1652 sp3
= (struct nfsv3_sattr
*)tl
;
1653 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1654 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
) {
1655 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1656 *tl
++ = txdr_unsigned(major(vap
->va_rdev
));
1657 *tl
= txdr_unsigned(minor(vap
->va_rdev
));
1660 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1661 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1662 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1663 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1665 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1666 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1668 nfsm_request(dvp
, NFSPROC_MKNOD
, cnp
->cn_proc
, cnp
->cn_cred
);
1670 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
1674 newvp
= (struct vnode
*)0;
1676 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1677 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1683 nfsm_wcc_data(dvp
, wccflag
);
1689 if (cnp
->cn_flags
& MAKEENTRY
)
1690 cache_enter(dvp
, newvp
, cnp
);
1693 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1694 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1695 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1697 VTONFS(dvp
)->n_attrstamp
= 0;
1705 * just call nfs_mknodrpc() to do the work.
1710 struct vop_mknod_args
/* {
1711 struct vnode *a_dvp;
1712 struct vnode **a_vpp;
1713 struct componentname *a_cnp;
1714 struct vattr *a_vap;
1717 struct vnode
*newvp
;
1720 error
= nfs_mknodrpc(ap
->a_dvp
, &newvp
, ap
->a_cnp
, ap
->a_vap
);
1726 static u_long create_verf
;
1728 * nfs file create call
1732 struct vop_create_args
/* {
1733 struct vnode *a_dvp;
1734 struct vnode **a_vpp;
1735 struct componentname *a_cnp;
1736 struct vattr *a_vap;
1739 register struct vnode
*dvp
= ap
->a_dvp
;
1740 register struct vattr
*vap
= ap
->a_vap
;
1741 register struct componentname
*cnp
= ap
->a_cnp
;
1742 register struct nfsv2_sattr
*sp
;
1743 register struct nfsv3_sattr
*sp3
;
1744 register u_long
*tl
;
1745 register caddr_t cp
;
1746 register long t1
, t2
;
1747 struct nfsnode
*np
= (struct nfsnode
*)0;
1748 struct vnode
*newvp
= (struct vnode
*)0;
1749 caddr_t bpos
, dpos
, cp2
;
1750 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0, fmode
= 0;
1751 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1753 int v3
= NFS_ISV3(dvp
);
1756 * Oops, not for me..
1758 if (vap
->va_type
== VSOCK
)
1759 return (nfs_mknodrpc(dvp
, ap
->a_vpp
, cnp
, vap
));
1761 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1762 VOP_ABORTOP(dvp
, cnp
);
1766 if (vap
->va_vaflags
& VA_EXCLUSIVE
)
1769 nfsstats
.rpccnt
[NFSPROC_CREATE
]++;
1770 nfsm_reqhead(dvp
, NFSPROC_CREATE
, NFSX_FH(v3
) + 2 * NFSX_UNSIGNED
+
1771 nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1772 nfsm_fhtom(dvp
, v3
);
1773 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1775 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1776 if (fmode
& O_EXCL
) {
1777 *tl
= txdr_unsigned(NFSV3CREATE_EXCLUSIVE
);
1778 nfsm_build(tl
, u_long
*, NFSX_V3CREATEVERF
);
1779 if (!TAILQ_EMPTY(&in_ifaddrhead
))
1780 *tl
++ = IA_SIN(in_ifaddrhead
.tqh_first
)->sin_addr
.s_addr
;
1782 *tl
++ = create_verf
;
1783 *tl
= ++create_verf
;
1785 *tl
= txdr_unsigned(NFSV3CREATE_UNCHECKED
);
1786 nfsm_build(tl
, u_long
*, NFSX_V3SRVSATTR
);
1787 sp3
= (struct nfsv3_sattr
*)tl
;
1788 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1791 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1792 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1793 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1794 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1796 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1797 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1799 nfsm_request(dvp
, NFSPROC_CREATE
, cnp
->cn_proc
, cnp
->cn_cred
);
1801 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
1805 newvp
= (struct vnode
*)0;
1807 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1808 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1814 nfsm_wcc_data(dvp
, wccflag
);
1817 if (v3
&& (fmode
& O_EXCL
) && error
== NFSERR_NOTSUPP
) {
1823 } else if (v3
&& (fmode
& O_EXCL
))
1824 error
= nfs_setattrrpc(newvp
, vap
, cnp
->cn_cred
, cnp
->cn_proc
);
1826 if (cnp
->cn_flags
& MAKEENTRY
)
1827 cache_enter(dvp
, newvp
, cnp
);
1830 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1831 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1832 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1834 VTONFS(dvp
)->n_attrstamp
= 0;
1841 * nfs file remove call
1842 * To try and make nfs semantics closer to ufs semantics, a file that has
1843 * other processes using the vnode is renamed instead of removed and then
1844 * removed later on the last close.
1845 * - If v_usecount > 1
1846 * If a rename is not already in the works
1847 * call nfs_sillyrename() to set it up
1853 struct vop_remove_args
/* {
1854 struct vnodeop_desc *a_desc;
1855 struct vnode * a_dvp;
1856 struct vnode * a_vp;
1857 struct componentname * a_cnp;
1860 register struct vnode
*vp
= ap
->a_vp
;
1861 register struct vnode
*dvp
= ap
->a_dvp
;
1862 register struct componentname
*cnp
= ap
->a_cnp
;
1863 register struct nfsnode
*np
= VTONFS(vp
);
1866 int file_deleted
= 0;
1869 if ((cnp
->cn_flags
& HASBUF
) == 0)
1870 panic("nfs_remove: no name");
1871 if (vp
->v_usecount
< 1)
1872 panic("nfs_remove: bad v_usecount");
1874 if (vp
->v_usecount
== 1 ||
1875 (UBCISVALID(vp
)&&(vp
->v_usecount
==2)) ||
1876 (np
->n_sillyrename
&&
1877 VOP_GETATTR(vp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
) == 0 &&
1878 vattr
.va_nlink
> 1)) {
1880 * Purge the name cache so that the chance of a lookup for
1881 * the name succeeding while the remove is in progress is
1882 * minimized. Without node locking it can still happen, such
1883 * that an I/O op returns ESTALE, but since you get this if
1884 * another host removes the file..
1888 * throw away biocache buffers, mainly to avoid
1889 * unnecessary delayed writes later.
1891 error
= nfs_vinvalbuf(vp
, 0, cnp
->cn_cred
, cnp
->cn_proc
, 1);
1892 ubc_setsize(vp
, (off_t
)0);
1895 error
= nfs_removerpc(dvp
, cnp
->cn_nameptr
,
1896 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
);
1898 * Kludge City: If the first reply to the remove rpc is lost..
1899 * the reply to the retransmitted request will be ENOENT
1900 * since the file was in fact removed
1901 * Therefore, we cheat and return success.
1903 if (error
== ENOENT
)
1906 } else if (!np
->n_sillyrename
) {
1907 error
= nfs_sillyrename(dvp
, vp
, cnp
);
1910 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1911 np
->n_attrstamp
= 0;
1914 VOP_UNLOCK(vp
, 0, cnp
->cn_proc
);
1925 * nfs file remove rpc called from nfs_inactive
1929 register struct sillyrename
*sp
;
1932 return (nfs_removerpc(sp
->s_dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
1937 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1940 nfs_removerpc(dvp
, name
, namelen
, cred
, proc
)
1941 register struct vnode
*dvp
;
1947 register u_long
*tl
;
1948 register caddr_t cp
;
1949 register long t1
, t2
;
1950 caddr_t bpos
, dpos
, cp2
;
1951 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
1952 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1953 int v3
= NFS_ISV3(dvp
);
1955 nfsstats
.rpccnt
[NFSPROC_REMOVE
]++;
1956 nfsm_reqhead(dvp
, NFSPROC_REMOVE
,
1957 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(namelen
));
1958 nfsm_fhtom(dvp
, v3
);
1959 nfsm_strtom(name
, namelen
, NFS_MAXNAMLEN
);
1960 nfsm_request(dvp
, NFSPROC_REMOVE
, proc
, cred
);
1962 nfsm_wcc_data(dvp
, wccflag
);
1964 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1965 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1967 VTONFS(dvp
)->n_attrstamp
= 0;
1973 * nfs file rename call
1977 struct vop_rename_args
/* {
1978 struct vnode *a_fdvp;
1979 struct vnode *a_fvp;
1980 struct componentname *a_fcnp;
1981 struct vnode *a_tdvp;
1982 struct vnode *a_tvp;
1983 struct componentname *a_tcnp;
1986 register struct vnode
*fvp
= ap
->a_fvp
;
1987 register struct vnode
*tvp
= ap
->a_tvp
;
1988 register struct vnode
*fdvp
= ap
->a_fdvp
;
1989 register struct vnode
*tdvp
= ap
->a_tdvp
;
1990 register struct componentname
*tcnp
= ap
->a_tcnp
;
1991 register struct componentname
*fcnp
= ap
->a_fcnp
;
1995 if ((tcnp
->cn_flags
& HASBUF
) == 0 ||
1996 (fcnp
->cn_flags
& HASBUF
) == 0)
1997 panic("nfs_rename: no name");
1999 /* Check for cross-device rename */
2000 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
2001 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
2007 * If the tvp exists and is in use, sillyrename it before doing the
2008 * rename of the new file over it.
2009 * XXX Can't sillyrename a directory.
2011 if (tvp
&& (tvp
->v_usecount
>(UBCISVALID(tvp
) ? 2 : 1)) &&
2012 !VTONFS(tvp
)->n_sillyrename
&&
2013 tvp
->v_type
!= VDIR
&& !nfs_sillyrename(tdvp
, tvp
, tcnp
)) {
2018 error
= nfs_renamerpc(fdvp
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
,
2019 tdvp
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
, tcnp
->cn_cred
,
2022 if (fvp
->v_type
== VDIR
) {
2023 if (tvp
!= NULL
&& tvp
->v_type
== VDIR
)
2037 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
2039 if (error
== ENOENT
)
2045 * nfs file rename rpc called from nfs_remove() above
2048 nfs_renameit(sdvp
, scnp
, sp
)
2050 struct componentname
*scnp
;
2051 register struct sillyrename
*sp
;
2053 return (nfs_renamerpc(sdvp
, scnp
->cn_nameptr
, scnp
->cn_namelen
,
2054 sdvp
, sp
->s_name
, sp
->s_namlen
, scnp
->cn_cred
, scnp
->cn_proc
));
2058 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
2061 nfs_renamerpc(fdvp
, fnameptr
, fnamelen
, tdvp
, tnameptr
, tnamelen
, cred
, proc
)
2062 register struct vnode
*fdvp
;
2065 register struct vnode
*tdvp
;
2071 register u_long
*tl
;
2072 register caddr_t cp
;
2073 register long t1
, t2
;
2074 caddr_t bpos
, dpos
, cp2
;
2075 int error
= 0, fwccflag
= NFSV3_WCCRATTR
, twccflag
= NFSV3_WCCRATTR
;
2076 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2077 int v3
= NFS_ISV3(fdvp
);
2079 nfsstats
.rpccnt
[NFSPROC_RENAME
]++;
2080 nfsm_reqhead(fdvp
, NFSPROC_RENAME
,
2081 (NFSX_FH(v3
) + NFSX_UNSIGNED
)*2 + nfsm_rndup(fnamelen
) +
2082 nfsm_rndup(tnamelen
));
2083 nfsm_fhtom(fdvp
, v3
);
2084 nfsm_strtom(fnameptr
, fnamelen
, NFS_MAXNAMLEN
);
2085 nfsm_fhtom(tdvp
, v3
);
2086 nfsm_strtom(tnameptr
, tnamelen
, NFS_MAXNAMLEN
);
2087 nfsm_request(fdvp
, NFSPROC_RENAME
, proc
, cred
);
2089 nfsm_wcc_data(fdvp
, fwccflag
);
2090 nfsm_wcc_data(tdvp
, twccflag
);
2093 if (fdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2094 VTONFS(fdvp
)->n_flag
|= NMODIFIED
;
2096 VTONFS(fdvp
)->n_attrstamp
= 0;
2098 if (tdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2099 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
2101 VTONFS(tdvp
)->n_attrstamp
= 0;
2107 * nfs hard link create call
2111 struct vop_link_args
/* {
2113 struct vnode *a_tdvp;
2114 struct componentname *a_cnp;
2117 register struct vnode
*vp
= ap
->a_vp
;
2118 register struct vnode
*tdvp
= ap
->a_tdvp
;
2119 register struct componentname
*cnp
= ap
->a_cnp
;
2120 register u_long
*tl
;
2121 register caddr_t cp
;
2122 register long t1
, t2
;
2123 caddr_t bpos
, dpos
, cp2
;
2124 int error
= 0, wccflag
= NFSV3_WCCRATTR
, attrflag
= 0;
2125 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2126 int v3
= NFS_ISV3(vp
);
2128 if (vp
->v_mount
!= tdvp
->v_mount
) {
2129 VOP_ABORTOP(vp
, cnp
);
2138 * Push all writes to the server, so that the attribute cache
2139 * doesn't get "out of sync" with the server.
2140 * XXX There should be a better way!
2142 VOP_FSYNC(vp
, cnp
->cn_cred
, MNT_WAIT
, cnp
->cn_proc
);
2144 nfsstats
.rpccnt
[NFSPROC_LINK
]++;
2145 nfsm_reqhead(vp
, NFSPROC_LINK
,
2146 NFSX_FH(v3
)*2 + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2148 nfsm_fhtom(tdvp
, v3
);
2149 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2150 nfsm_request(vp
, NFSPROC_LINK
, cnp
->cn_proc
, cnp
->cn_cred
);
2152 nfsm_postop_attr(vp
, attrflag
);
2153 nfsm_wcc_data(tdvp
, wccflag
);
2156 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2158 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
2159 if ((!attrflag
) && (vp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
2160 VTONFS(vp
)->n_attrstamp
= 0;
2161 if ((!wccflag
) && (tdvp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
2162 VTONFS(tdvp
)->n_attrstamp
= 0;
2165 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2167 if (error
== EEXIST
)
2173 * nfs symbolic link create call
2177 struct vop_symlink_args
/* {
2178 struct vnode *a_dvp;
2179 struct vnode **a_vpp;
2180 struct componentname *a_cnp;
2181 struct vattr *a_vap;
2185 register struct vnode
*dvp
= ap
->a_dvp
;
2186 register struct vattr
*vap
= ap
->a_vap
;
2187 register struct componentname
*cnp
= ap
->a_cnp
;
2188 register struct nfsv2_sattr
*sp
;
2189 register struct nfsv3_sattr
*sp3
;
2190 register u_long
*tl
;
2191 register caddr_t cp
;
2192 register long t1
, t2
;
2193 caddr_t bpos
, dpos
, cp2
;
2194 int slen
, error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
;
2195 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2196 struct vnode
*newvp
= (struct vnode
*)0;
2197 int v3
= NFS_ISV3(dvp
);
2199 nfsstats
.rpccnt
[NFSPROC_SYMLINK
]++;
2200 slen
= strlen(ap
->a_target
);
2201 nfsm_reqhead(dvp
, NFSPROC_SYMLINK
, NFSX_FH(v3
) + 2*NFSX_UNSIGNED
+
2202 nfsm_rndup(cnp
->cn_namelen
) + nfsm_rndup(slen
) + NFSX_SATTR(v3
));
2203 nfsm_fhtom(dvp
, v3
);
2204 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2206 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2207 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
,
2208 cnp
->cn_cred
->cr_gid
);
2210 nfsm_strtom(ap
->a_target
, slen
, NFS_MAXPATHLEN
);
2212 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2213 sp
->sa_mode
= vtonfsv2_mode(VLNK
, vap
->va_mode
);
2214 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2215 sp
->sa_gid
= txdr_unsigned(cnp
->cn_cred
->cr_gid
);
2217 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2218 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2220 nfsm_request(dvp
, NFSPROC_SYMLINK
, cnp
->cn_proc
, cnp
->cn_cred
);
2223 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
2224 nfsm_wcc_data(dvp
, wccflag
);
2229 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2230 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2231 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2233 VTONFS(dvp
)->n_attrstamp
= 0;
2237 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2239 if (error
== EEXIST
)
2249 struct vop_mkdir_args
/* {
2250 struct vnode *a_dvp;
2251 struct vnode **a_vpp;
2252 struct componentname *a_cnp;
2253 struct vattr *a_vap;
2256 register struct vnode
*dvp
= ap
->a_dvp
;
2257 register struct vattr
*vap
= ap
->a_vap
;
2258 register struct componentname
*cnp
= ap
->a_cnp
;
2259 register struct nfsv2_sattr
*sp
;
2260 register struct nfsv3_sattr
*sp3
;
2261 register u_long
*tl
;
2262 register caddr_t cp
;
2263 register long t1
, t2
;
2265 struct nfsnode
*np
= (struct nfsnode
*)0;
2266 struct vnode
*newvp
= (struct vnode
*)0;
2267 caddr_t bpos
, dpos
, cp2
;
2268 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2270 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2272 int v3
= NFS_ISV3(dvp
);
2274 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
2275 VOP_ABORTOP(dvp
, cnp
);
2279 len
= cnp
->cn_namelen
;
2280 nfsstats
.rpccnt
[NFSPROC_MKDIR
]++;
2281 nfsm_reqhead(dvp
, NFSPROC_MKDIR
,
2282 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
) + NFSX_SATTR(v3
));
2283 nfsm_fhtom(dvp
, v3
);
2284 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
2286 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2287 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
2289 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2290 sp
->sa_mode
= vtonfsv2_mode(VDIR
, vap
->va_mode
);
2291 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2292 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
2294 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2295 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2297 nfsm_request(dvp
, NFSPROC_MKDIR
, cnp
->cn_proc
, cnp
->cn_cred
);
2299 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
2301 nfsm_wcc_data(dvp
, wccflag
);
2303 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2304 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2306 VTONFS(dvp
)->n_attrstamp
= 0;
2309 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
2310 * if we can succeed in looking up the directory.
2312 if (error
== EEXIST
|| (!error
&& !gotvp
)) {
2315 newvp
= (struct vnode
*)0;
2317 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
, len
, cnp
->cn_cred
,
2321 if (newvp
->v_type
!= VDIR
)
2330 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2336 * nfs remove directory call
2340 struct vop_rmdir_args
/* {
2341 struct vnode *a_dvp;
2343 struct componentname *a_cnp;
2346 register struct vnode
*vp
= ap
->a_vp
;
2347 register struct vnode
*dvp
= ap
->a_dvp
;
2348 register struct componentname
*cnp
= ap
->a_cnp
;
2349 register u_long
*tl
;
2350 register caddr_t cp
;
2351 register long t1
, t2
;
2352 caddr_t bpos
, dpos
, cp2
;
2353 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2354 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2355 int v3
= NFS_ISV3(dvp
);
2357 nfsstats
.rpccnt
[NFSPROC_RMDIR
]++;
2358 nfsm_reqhead(dvp
, NFSPROC_RMDIR
,
2359 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2360 nfsm_fhtom(dvp
, v3
);
2361 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2362 nfsm_request(dvp
, NFSPROC_RMDIR
, cnp
->cn_proc
, cnp
->cn_cred
);
2364 nfsm_wcc_data(dvp
, wccflag
);
2366 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2367 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2368 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2370 VTONFS(dvp
)->n_attrstamp
= 0;
2377 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2379 if (error
== ENOENT
)
2389 struct vop_readdir_args
/* {
2392 struct ucred *a_cred;
2395 register struct vnode
*vp
= ap
->a_vp
;
2396 register struct nfsnode
*np
= VTONFS(vp
);
2397 register struct uio
*uio
= ap
->a_uio
;
2401 if (vp
->v_type
!= VDIR
)
2404 * First, check for hit on the EOF offset cache
2406 if (np
->n_direofoffset
> 0 && uio
->uio_offset
>= np
->n_direofoffset
&&
2407 (np
->n_flag
& NMODIFIED
) == 0) {
2408 if (VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) {
2409 if (NQNFS_CKCACHABLE(vp
, ND_READ
)) {
2410 nfsstats
.direofcache_hits
++;
2413 } else if (VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, uio
->uio_procp
) == 0 &&
2414 np
->n_mtime
== vattr
.va_mtime
.tv_sec
) {
2415 nfsstats
.direofcache_hits
++;
2421 * Call nfs_bioread() to do the real work.
2423 tresid
= uio
->uio_resid
;
2424 error
= nfs_bioread(vp
, uio
, 0, ap
->a_cred
, 0);
2426 if (!error
&& uio
->uio_resid
== tresid
)
2427 nfsstats
.direofcache_misses
++;
2433 * Called from below the buffer cache by nfs_doio().
2436 nfs_readdirrpc(vp
, uiop
, cred
)
2438 register struct uio
*uiop
;
2442 register int len
, left
;
2443 register struct dirent
*dp
;
2444 register u_long
*tl
;
2445 register caddr_t cp
;
2446 register long t1
, t2
;
2447 register nfsuint64
*cookiep
;
2448 caddr_t bpos
, dpos
, cp2
;
2449 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2451 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2452 struct nfsnode
*dnp
= VTONFS(vp
);
2454 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, bigenough
= 1;
2456 int v3
= NFS_ISV3(vp
);
2459 dp
= (struct dirent
*)0;
2462 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (NFS_DIRBLKSIZ
- 1)) ||
2463 (uiop
->uio_resid
& (NFS_DIRBLKSIZ
- 1)))
2464 panic("nfs_readdirrpc: bad uio");
2468 * If there is no cookie, assume directory was stale.
2470 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2474 return (NFSERR_BAD_COOKIE
);
2476 * Loop around doing readdir rpc's of size nm_readdirsize
2477 * truncated to a multiple of DIRBLKSIZ.
2478 * The stopping criteria is EOF or buffer full.
2480 while (more_dirs
&& bigenough
) {
2481 nfsstats
.rpccnt
[NFSPROC_READDIR
]++;
2482 nfsm_reqhead(vp
, NFSPROC_READDIR
, NFSX_FH(v3
) +
2486 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
2487 *tl
++ = cookie
.nfsuquad
[0];
2488 *tl
++ = cookie
.nfsuquad
[1];
2489 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2490 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2492 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2493 *tl
++ = cookie
.nfsuquad
[0];
2495 *tl
= txdr_unsigned(nmp
->nm_readdirsize
);
2496 nfsm_request(vp
, NFSPROC_READDIR
, uiop
->uio_procp
, cred
);
2498 nfsm_postop_attr(vp
, attrflag
);
2500 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2501 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2502 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
;
2508 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2509 more_dirs
= fxdr_unsigned(int, *tl
);
2511 /* loop thru the dir entries, doctoring them to 4bsd form */
2512 while (more_dirs
&& bigenough
) {
2514 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2515 fxdr_hyper(tl
, &fileno
);
2516 len
= fxdr_unsigned(int, *(tl
+ 2));
2518 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2519 fileno
= fxdr_unsigned(u_quad_t
, *tl
++);
2520 len
= fxdr_unsigned(int, *tl
);
2522 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2527 tlen
= nfsm_rndup(len
);
2529 tlen
+= 4; /* To ensure null termination */
2530 left
= DIRBLKSIZ
- blksiz
;
2531 if ((tlen
+ DIRHDSIZ
) > left
) {
2532 dp
->d_reclen
+= left
;
2533 uiop
->uio_iov
->iov_base
+= left
;
2534 uiop
->uio_iov
->iov_len
-= left
;
2535 uiop
->uio_offset
+= left
;
2536 uiop
->uio_resid
-= left
;
2539 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2542 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2543 dp
->d_fileno
= (int)fileno
;
2545 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2546 dp
->d_type
= DT_UNKNOWN
;
2547 blksiz
+= dp
->d_reclen
;
2548 if (blksiz
== DIRBLKSIZ
)
2550 uiop
->uio_offset
+= DIRHDSIZ
;
2551 uiop
->uio_resid
-= DIRHDSIZ
;
2552 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2553 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2554 nfsm_mtouio(uiop
, len
);
2555 cp
= uiop
->uio_iov
->iov_base
;
2557 *cp
= '\0'; /* null terminate */
2558 uiop
->uio_iov
->iov_base
+= tlen
;
2559 uiop
->uio_iov
->iov_len
-= tlen
;
2560 uiop
->uio_offset
+= tlen
;
2561 uiop
->uio_resid
-= tlen
;
2563 nfsm_adv(nfsm_rndup(len
));
2565 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2567 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2570 cookie
.nfsuquad
[0] = *tl
++;
2572 cookie
.nfsuquad
[1] = *tl
++;
2577 more_dirs
= fxdr_unsigned(int, *tl
);
2580 * If at end of rpc data, get the eof boolean
2583 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2584 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2589 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2590 * by increasing d_reclen for the last record.
2593 left
= DIRBLKSIZ
- blksiz
;
2594 dp
->d_reclen
+= left
;
2595 uiop
->uio_iov
->iov_base
+= left
;
2596 uiop
->uio_iov
->iov_len
-= left
;
2597 uiop
->uio_offset
+= left
;
2598 uiop
->uio_resid
-= left
;
2602 * We are now either at the end of the directory or have filled the
2606 dnp
->n_direofoffset
= uiop
->uio_offset
;
2608 if (uiop
->uio_resid
> 0)
2609 printf("EEK! readdirrpc resid > 0\n");
2610 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2618 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2621 nfs_readdirplusrpc(vp
, uiop
, cred
)
2623 register struct uio
*uiop
;
2626 register int len
, left
;
2627 register struct dirent
*dp
;
2628 register u_long
*tl
;
2629 register caddr_t cp
;
2630 register long t1
, t2
;
2631 register struct vnode
*newvp
;
2632 register nfsuint64
*cookiep
;
2633 caddr_t bpos
, dpos
, cp2
, dpossav1
, dpossav2
;
2634 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
, *mdsav1
, *mdsav2
;
2635 struct nameidata nami
, *ndp
= &nami
;
2636 struct componentname
*cnp
= &ndp
->ni_cnd
;
2638 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2639 struct nfsnode
*dnp
= VTONFS(vp
), *np
;
2642 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, doit
, bigenough
= 1, i
;
2643 int attrflag
, fhsize
;
2646 dp
= (struct dirent
*)0;
2649 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (DIRBLKSIZ
- 1)) ||
2650 (uiop
->uio_resid
& (DIRBLKSIZ
- 1)))
2651 panic("nfs_readdirplusrpc: bad uio");
2657 * If there is no cookie, assume directory was stale.
2659 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2663 return (NFSERR_BAD_COOKIE
);
2665 * Loop around doing readdir rpc's of size nm_readdirsize
2666 * truncated to a multiple of DIRBLKSIZ.
2667 * The stopping criteria is EOF or buffer full.
2669 while (more_dirs
&& bigenough
) {
2670 nfsstats
.rpccnt
[NFSPROC_READDIRPLUS
]++;
2671 nfsm_reqhead(vp
, NFSPROC_READDIRPLUS
,
2672 NFSX_FH(1) + 6 * NFSX_UNSIGNED
);
2674 nfsm_build(tl
, u_long
*, 6 * NFSX_UNSIGNED
);
2675 *tl
++ = cookie
.nfsuquad
[0];
2676 *tl
++ = cookie
.nfsuquad
[1];
2677 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2678 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2679 *tl
++ = txdr_unsigned(nmp
->nm_readdirsize
);
2680 *tl
= txdr_unsigned(nmp
->nm_rsize
);
2681 nfsm_request(vp
, NFSPROC_READDIRPLUS
, uiop
->uio_procp
, cred
);
2682 nfsm_postop_attr(vp
, attrflag
);
2687 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2688 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2689 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
++;
2690 more_dirs
= fxdr_unsigned(int, *tl
);
2692 /* loop thru the dir entries, doctoring them to 4bsd form */
2693 while (more_dirs
&& bigenough
) {
2694 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2695 fxdr_hyper(tl
, &fileno
);
2696 len
= fxdr_unsigned(int, *(tl
+ 2));
2697 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2702 tlen
= nfsm_rndup(len
);
2704 tlen
+= 4; /* To ensure null termination*/
2705 left
= DIRBLKSIZ
- blksiz
;
2706 if ((tlen
+ DIRHDSIZ
) > left
) {
2707 dp
->d_reclen
+= left
;
2708 uiop
->uio_iov
->iov_base
+= left
;
2709 uiop
->uio_iov
->iov_len
-= left
;
2710 uiop
->uio_offset
+= left
;
2711 uiop
->uio_resid
-= left
;
2714 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2717 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2718 dp
->d_fileno
= (int)fileno
;
2720 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2721 dp
->d_type
= DT_UNKNOWN
;
2722 blksiz
+= dp
->d_reclen
;
2723 if (blksiz
== DIRBLKSIZ
)
2725 uiop
->uio_offset
+= DIRHDSIZ
;
2726 uiop
->uio_resid
-= DIRHDSIZ
;
2727 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2728 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2729 cnp
->cn_nameptr
= uiop
->uio_iov
->iov_base
;
2730 cnp
->cn_namelen
= len
;
2731 nfsm_mtouio(uiop
, len
);
2732 cp
= uiop
->uio_iov
->iov_base
;
2735 uiop
->uio_iov
->iov_base
+= tlen
;
2736 uiop
->uio_iov
->iov_len
-= tlen
;
2737 uiop
->uio_offset
+= tlen
;
2738 uiop
->uio_resid
-= tlen
;
2740 nfsm_adv(nfsm_rndup(len
));
2741 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2743 cookie
.nfsuquad
[0] = *tl
++;
2744 cookie
.nfsuquad
[1] = *tl
++;
2749 * Since the attributes are before the file handle
2750 * (sigh), we must skip over the attributes and then
2751 * come back and get them.
2753 attrflag
= fxdr_unsigned(int, *tl
);
2757 nfsm_adv(NFSX_V3FATTR
);
2758 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2759 doit
= fxdr_unsigned(int, *tl
);
2761 nfsm_getfh(fhp
, fhsize
, 1);
2762 if (NFS_CMPFH(dnp
, fhp
, fhsize
)) {
2767 if ((error
= nfs_nget(vp
->v_mount
, fhp
,
2779 nfsm_loadattr(newvp
, (struct vattr
*)0);
2783 IFTODT(VTTOIF(np
->n_vattr
.va_type
));
2786 for (cp
= cnp
->cn_nameptr
, i
= 1; i
<= len
;
2788 cnp
->cn_hash
+= (unsigned char)*cp
* i
;
2789 if (cnp
->cn_namelen
<= NCHNAMLEN
)
2790 cache_enter(ndp
->ni_dvp
, ndp
->ni_vp
, cnp
);
2793 /* Just skip over the file handle */
2794 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2795 i
= fxdr_unsigned(int, *tl
);
2796 nfsm_adv(nfsm_rndup(i
));
2798 if (newvp
!= NULLVP
) {
2802 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2803 more_dirs
= fxdr_unsigned(int, *tl
);
2806 * If at end of rpc data, get the eof boolean
2809 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2810 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2815 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
2816 * by increasing d_reclen for the last record.
2819 left
= DIRBLKSIZ
- blksiz
;
2820 dp
->d_reclen
+= left
;
2821 uiop
->uio_iov
->iov_base
+= left
;
2822 uiop
->uio_iov
->iov_len
-= left
;
2823 uiop
->uio_offset
+= left
;
2824 uiop
->uio_resid
-= left
;
2828 * We are now either at the end of the directory or have filled the
2832 dnp
->n_direofoffset
= uiop
->uio_offset
;
2834 if (uiop
->uio_resid
> 0)
2835 printf("EEK! readdirplusrpc resid > 0\n");
2836 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2840 if (newvp
!= NULLVP
) {
2851 * Silly rename. To make the NFS filesystem that is stateless look a little
2852 * more like the "ufs" a remove of an active vnode is translated to a rename
2853 * to a funny looking filename that is removed by nfs_inactive on the
2854 * nfsnode. There is the potential for another process on a different client
2855 * to create the same funny name between the nfs_lookitup() fails and the
2856 * nfs_rename() completes, but...
2859 nfs_sillyrename(dvp
, vp
, cnp
)
2860 struct vnode
*dvp
, *vp
;
2861 struct componentname
*cnp
;
2863 register struct sillyrename
*sp
;
2872 if (vp
->v_type
== VDIR
)
2873 panic("nfs_sillyrename: dir");
2875 MALLOC_ZONE(sp
, struct sillyrename
*,
2876 sizeof (struct sillyrename
), M_NFSREQ
, M_WAITOK
);
2877 sp
->s_cred
= crdup(cnp
->cn_cred
);
2881 /* Fudge together a funny name */
2882 pid
= cnp
->cn_proc
->p_pid
;
2883 sp
->s_namlen
= sprintf(sp
->s_name
, ".nfsA%04x4.4", pid
);
2885 /* Try lookitups until we get one that isn't there */
2886 while (nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
2887 cnp
->cn_proc
, (struct nfsnode
**)0) == 0) {
2889 if (sp
->s_name
[4] > 'z') {
2894 if ((error
= nfs_renameit(dvp
, cnp
, sp
)))
2896 error
= nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
2899 kprintf("sillyrename: %s, vp=%x, np=%x, dvp=%x\n",
2900 &sp
->s_name
[0], (unsigned)vp
, (unsigned)np
, (unsigned)dvp
);
2902 np
->n_sillyrename
= sp
;
2907 sp
->s_cred
= NOCRED
;
2909 _FREE_ZONE((caddr_t
)sp
, sizeof (struct sillyrename
), M_NFSREQ
);
2914 * Look up a file name and optionally either update the file handle or
2915 * allocate an nfsnode, depending on the value of npp.
2916 * npp == NULL --> just do the lookup
2917 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2919 * *npp != NULL --> update the file handle in the vnode
2922 nfs_lookitup(dvp
, name
, len
, cred
, procp
, npp
)
2923 register struct vnode
*dvp
;
2928 struct nfsnode
**npp
;
2930 register u_long
*tl
;
2931 register caddr_t cp
;
2932 register long t1
, t2
;
2933 struct vnode
*newvp
= (struct vnode
*)0;
2934 struct nfsnode
*np
, *dnp
= VTONFS(dvp
);
2935 caddr_t bpos
, dpos
, cp2
;
2936 int error
= 0, fhlen
, attrflag
;
2937 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2939 int v3
= NFS_ISV3(dvp
);
2941 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
2942 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
2943 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
2944 nfsm_fhtom(dvp
, v3
);
2945 nfsm_strtom(name
, len
, NFS_MAXNAMLEN
);
2946 nfsm_request(dvp
, NFSPROC_LOOKUP
, procp
, cred
);
2947 if (npp
&& !error
) {
2948 nfsm_getfh(nfhp
, fhlen
, v3
);
2951 if (np
->n_fhsize
> NFS_SMALLFH
&& fhlen
<= NFS_SMALLFH
) {
2952 _FREE_ZONE((caddr_t
)np
->n_fhp
,
2953 np
->n_fhsize
, M_NFSBIGFH
);
2954 np
->n_fhp
= &np
->n_fh
;
2955 } else if (np
->n_fhsize
<= NFS_SMALLFH
&& fhlen
>NFS_SMALLFH
)
2956 MALLOC_ZONE(np
->n_fhp
, nfsfh_t
*,
2957 fhlen
, M_NFSBIGFH
, M_WAITOK
);
2958 bcopy((caddr_t
)nfhp
, (caddr_t
)np
->n_fhp
, fhlen
);
2959 np
->n_fhsize
= fhlen
;
2961 } else if (NFS_CMPFH(dnp
, nfhp
, fhlen
)) {
2965 error
= nfs_nget(dvp
->v_mount
, nfhp
, fhlen
, &np
);
2973 nfsm_postop_attr(newvp
, attrflag
);
2974 if (!attrflag
&& *npp
== NULL
) {
2983 nfsm_loadattr(newvp
, (struct vattr
*)0);
2986 if (npp
&& *npp
== NULL
) {
3000 * Nfs Version 3 commit rpc
3003 nfs_commit(vp
, offset
, cnt
, cred
, procp
)
3004 register struct vnode
*vp
;
3010 register caddr_t cp
;
3011 register u_long
*tl
;
3012 register int t1
, t2
;
3013 register struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
3014 caddr_t bpos
, dpos
, cp2
;
3015 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
3016 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
3018 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0)
3020 nfsstats
.rpccnt
[NFSPROC_COMMIT
]++;
3021 nfsm_reqhead(vp
, NFSPROC_COMMIT
, NFSX_FH(1));
3023 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
3024 txdr_hyper(&offset
, tl
);
3026 *tl
= txdr_unsigned(cnt
);
3027 nfsm_request(vp
, NFSPROC_COMMIT
, procp
, cred
);
3028 nfsm_wcc_data(vp
, wccflag
);
3030 nfsm_dissect(tl
, u_long
*, NFSX_V3WRITEVERF
);
3031 if (bcmp((caddr_t
)nmp
->nm_verf
, (caddr_t
)tl
,
3032 NFSX_V3WRITEVERF
)) {
3033 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
3035 error
= NFSERR_STALEWRITEVERF
;
3044 * - make nfs_bmap() essentially a no-op that does no translation
3045 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
3046 * (Maybe I could use the process's page mapping, but I was concerned that
3047 * Kernel Write might not be enabled and also figured copyout() would do
3048 * a lot more work than bcopy() and also it currently happens in the
3049 * context of the swapper process (2).
3053 struct vop_bmap_args
/* {
3056 struct vnode **a_vpp;
3062 register struct vnode
*vp
= ap
->a_vp
;
3063 int devBlockSize
= DEV_BSIZE
;
3065 if (ap
->a_vpp
!= NULL
)
3067 if (ap
->a_bnp
!= NULL
)
3068 *ap
->a_bnp
= ap
->a_bn
* btodb(vp
->v_mount
->mnt_stat
.f_iosize
,
3070 if (ap
->a_runp
!= NULL
)
3073 if (ap
->a_runb
!= NULL
)
3081 * For async requests when nfsiod(s) are running, queue the request by
3082 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
3087 struct vop_strategy_args
*ap
;
3089 register struct buf
*bp
= ap
->a_bp
;
3094 if (ISSET(bp
->b_flags
, B_PHYS
))
3095 panic("nfs_strategy: physio");
3096 if (ISSET(bp
->b_flags
, B_ASYNC
))
3097 p
= (struct proc
*)0;
3099 p
= current_proc(); /* XXX */
3100 if (ISSET(bp
->b_flags
, B_READ
))
3105 * If the op is asynchronous and an i/o daemon is waiting
3106 * queue the request, wake it up and wait for completion
3107 * otherwise just do it ourselves.
3109 if (!ISSET(bp
->b_flags
, B_ASYNC
) || nfs_asyncio(bp
, NOCRED
))
3110 error
= nfs_doio(bp
, cr
, p
);
3117 * NB Currently unsupported.
3122 struct vop_mmap_args
/* {
3125 struct ucred *a_cred;
3134 * fsync vnode op. Just call nfs_flush() with commit == 1.
3139 struct vop_fsync_args
/* {
3140 struct vnodeop_desc *a_desc;
3141 struct vnode * a_vp;
3142 struct ucred * a_cred;
3148 return (nfs_flush(ap
->a_vp
, ap
->a_cred
, ap
->a_waitfor
, ap
->a_p
, 1));
3152 * Flush all the blocks associated with a vnode.
3153 * Walk through the buffer pool and push any dirty pages
3154 * associated with the vnode.
3157 nfs_flush(vp
, cred
, waitfor
, p
, commit
)
3158 register struct vnode
*vp
;
3164 register struct nfsnode
*np
= VTONFS(vp
);
3165 register struct buf
*bp
;
3168 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
3169 int s
, error
= 0, slptimeo
= 0, slpflag
= 0, retv
, bvecpos
, err
;
3171 u_quad_t off
, endoff
, toff
;
3172 struct ucred
* wcred
= NULL
;
3173 struct buf
**bvec
= NULL
;
3178 #ifndef NFS_COMMITBVECSIZ
3179 #define NFS_COMMITBVECSIZ 20
3181 struct buf
*bvec_on_stack
[NFS_COMMITBVECSIZ
];
3182 struct upl_t
*upls_on_stack
[NFS_COMMITBVECSIZ
];
3183 int bvecsize
= 0, bveccount
, buplpos
;
3185 if (nmp
->nm_flag
& NFSMNT_INT
)
3191 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
3192 * server, but nas not been committed to stable storage on the server
3193 * yet. On the first pass, the byte range is worked out and the commit
3194 * rpc is done. On the second pass, nfs_writebp() is called to do the
3198 if (vp
->v_dirtyblkhd
.lh_first
)
3199 np
->n_flag
|= NMODIFIED
;
3204 if (NFS_ISV3(vp
) && commit
) {
3207 * Count up how many buffers waiting for a commit.
3210 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3211 nbp
= bp
->b_vnbufs
.le_next
;
3212 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3213 == (B_DELWRI
| B_NEEDCOMMIT
))
3217 * Allocate space to remember the list of bufs to commit. It is
3218 * important to use M_NOWAIT here to avoid a race with nfs_write.
3219 * If we can't get memory (for whatever reason), we will end up
3220 * committing the buffers one-by-one in the loop below.
3222 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3223 _FREE(bvec
, M_TEMP
);
3224 if (upls
!= NULL
&& upls
!= (upl_t
*) upls_on_stack
)
3225 _FREE(upls
, M_TEMP
);
3227 bvecsize
= NFS_COMMITBVECSIZ
;
3228 if (bveccount
> NFS_COMMITBVECSIZ
) {
3229 MALLOC(bvec
, struct buf
**,
3230 bveccount
* sizeof(struct buf
*), M_TEMP
, M_NOWAIT
);
3231 MALLOC(upls
, upl_t
*,
3232 bveccount
* sizeof(upl_t
), M_TEMP
, M_NOWAIT
);
3233 if ((bvec
== NULL
) || (upls
== NULL
)) {
3235 _FREE(bvec
, M_TEMP
);
3237 _FREE(upls
, M_TEMP
);
3238 bvec
= bvec_on_stack
;
3239 upls
= (upl_t
*) upls_on_stack
;
3241 bvecsize
= bveccount
;
3243 bvec
= bvec_on_stack
;
3244 upls
= (upl_t
*) upls_on_stack
;
3247 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3248 nbp
= bp
->b_vnbufs
.le_next
;
3249 if (bvecpos
>= bvecsize
)
3251 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3252 != (B_DELWRI
| B_NEEDCOMMIT
))
3256 * Work out if all buffers are using the same cred
3257 * so we can deal with them all with one commit.
3260 wcred
= bp
->b_wcred
;
3261 else if (wcred
!= bp
->b_wcred
)
3263 SET(bp
->b_flags
, (B_BUSY
| B_WRITEINPROG
));
3266 * we need ubc_create_upl so if vm decides to
3267 * do paging while we are waiting on commit rpc,
3268 * that it doesn't pick these pages.
3270 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3271 kret
= ubc_create_upl(vp
,
3272 ubc_blktooff(vp
, bp
->b_lblkno
),
3277 if (kret
!= KERN_SUCCESS
)
3278 panic("nfs_getcacheblk: get pagelists failed with (%d)", kret
);
3281 upl_ubc_alias_set(upls
[buplpos
], ioaddr
, 1);
3282 #endif /* UBC_DEBUG */
3283 buplpos
++; /* not same as bvecpos if upl existed already */
3287 * A list of these buffers is kept so that the
3288 * second loop knows which buffers have actually
3289 * been committed. This is necessary, since there
3290 * may be a race between the commit rpc and new
3291 * uncommitted writes on the file.
3293 bvec
[bvecpos
++] = bp
;
3294 toff
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3298 toff
+= (u_quad_t
)(bp
->b_dirtyend
- bp
->b_dirtyoff
);
3306 * Commit data on the server, as required.
3307 * If all bufs are using the same wcred, then use that with
3308 * one call for all of them, otherwise commit each one
3311 if (wcred
!= NOCRED
)
3312 retv
= nfs_commit(vp
, off
, (int)(endoff
- off
),
3316 for (i
= 0; i
< bvecpos
; i
++) {
3319 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3321 size
= (u_quad_t
)(bp
->b_dirtyend
3323 retv
= nfs_commit(vp
, off
, (int)size
,
3329 if (retv
== NFSERR_STALEWRITEVERF
)
3330 nfs_clearcommit(vp
->v_mount
);
3332 for (i
= 0; i
< buplpos
; i
++) {
3334 * Before the VOP_BWRITE and biodone(ASYNC)/brelse, we have to undo
3335 * holding the vm page or we we will deadlock on another vm_fault_list_request.
3336 * Here's a convenient place to put it.
3337 * Better if we could hold it by setting the PAGELIST flag and kernel_upl_map
3338 * as does nfs_writebp. Then normal biodones and brelse will clean it up and
3339 * we can avoid this abort. For now make minimal changes.
3341 err
= ubc_upl_abort(upls
[i
], NULL
);
3343 printf("nfs_flush: kernel_upl_abort %d\n", err
);
3348 * Now, either mark the blocks I/O done or mark the
3349 * blocks dirty, depending on whether the commit
3352 for (i
= 0; i
< bvecpos
; i
++) {
3355 CLR(bp
->b_flags
, (B_NEEDCOMMIT
| B_WRITEINPROG
));
3360 SET(bp
->b_flags
, B_ASYNC
);
3362 CLR(bp
->b_flags
, (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3363 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3364 reassignbuf(bp
, vp
);
3373 * Start/do any write(s) that are required.
3374 * There is a window here where B_BUSY protects the buffer. The vm pages have been
3375 * freed up, yet B_BUSY is set. Don't think you will hit any busy/incore problems while
3376 * we sleep, but not absolutely sure. Keep an eye on it. Otherwise we will have to hold
3377 * vm page across this locked. - EKN
3380 if (current_thread_aborted()) {
3385 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3386 nbp
= bp
->b_vnbufs
.le_next
;
3387 if (ISSET(bp
->b_flags
, B_BUSY
)) {
3388 if (waitfor
!= MNT_WAIT
|| passone
)
3390 SET(bp
->b_flags
, B_WANTED
);
3391 error
= tsleep((caddr_t
)bp
, slpflag
| (PRIBIO
+ 1),
3392 "nfsfsync", slptimeo
);
3395 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3399 if (slpflag
== PCATCH
) {
3406 if (!ISSET(bp
->b_flags
, B_DELWRI
))
3407 panic("nfs_fsync: not dirty");
3408 if ((passone
|| !commit
) && ISSET(bp
->b_flags
, B_NEEDCOMMIT
))
3411 if (passone
|| !commit
)
3412 SET(bp
->b_flags
, (B_BUSY
|B_ASYNC
));
3414 SET(bp
->b_flags
, (B_BUSY
|B_ASYNC
|B_WRITEINPROG
|B_NEEDCOMMIT
));
3425 if (waitfor
== MNT_WAIT
) {
3426 while (vp
->v_numoutput
) {
3427 vp
->v_flag
|= VBWAIT
;
3428 error
= tsleep((caddr_t
)&vp
->v_numoutput
,
3429 slpflag
| (PRIBIO
+ 1), "nfsfsync", slptimeo
);
3431 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3435 if (slpflag
== PCATCH
) {
3441 if (vp
->v_dirtyblkhd
.lh_first
&& commit
) {
3445 if (np
->n_flag
& NWRITEERR
) {
3446 error
= np
->n_error
;
3447 np
->n_flag
&= ~NWRITEERR
;
3450 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3451 _FREE(bvec
, M_TEMP
);
3452 if (upls
!= NULL
&& upls
!= (upl_t
*) upls_on_stack
)
3453 _FREE(upls
, M_TEMP
);
3458 * Return POSIX pathconf information applicable to nfs.
3460 * The NFS V2 protocol doesn't support this, so just return EINVAL
3466 struct vop_pathconf_args
/* {
3477 * NFS advisory byte-level locks.
3478 * Currently unsupported.
3482 struct vop_advlock_args
/* {
3491 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3494 * The following kludge is to allow diskless support to work
3495 * until a real NFS lockd is implemented. Basically, just pretend
3496 * that this is a local lock.
3498 return (lf_advlock(ap
, &(np
->n_lockf
), np
->n_size
));
3501 printf("nfs_advlock: pid %d comm %s\n", current_proc()->p_pid
, current_proc()->p_comm
);
3503 return (EOPNOTSUPP
);
3508 * Print out the contents of an nfsnode.
3512 struct vop_print_args
/* {
3516 register struct vnode
*vp
= ap
->a_vp
;
3517 register struct nfsnode
*np
= VTONFS(vp
);
3519 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
3520 np
->n_vattr
.va_fileid
, np
->n_vattr
.va_fsid
);
3521 if (vp
->v_type
== VFIFO
)
3528 * NFS directory offset lookup.
3529 * Currently unsupported.
3533 struct vop_blkatoff_args
/* {
3542 printf("nfs_blkatoff: unimplemented!!");
3544 return (EOPNOTSUPP
);
3548 * NFS flat namespace allocation.
3549 * Currently unsupported.
3553 struct vop_valloc_args
/* {
3554 struct vnode *a_pvp;
3556 struct ucred *a_cred;
3557 struct vnode **a_vpp;
3561 return (EOPNOTSUPP
);
3565 * NFS flat namespace free.
3566 * Currently unsupported.
3570 struct vop_vfree_args
/* {
3571 struct vnode *a_pvp;
3578 printf("nfs_vfree: unimplemented!!");
3580 return (EOPNOTSUPP
);
3584 * NFS file truncation.
3588 struct vop_truncate_args
/* {
3592 struct ucred *a_cred;
3597 /* Use nfs_setattr */
3599 printf("nfs_truncate: unimplemented!!");
3601 return (EOPNOTSUPP
);
3609 struct vop_update_args
/* {
3611 struct timeval *a_ta;
3612 struct timeval *a_tm;
3617 /* Use nfs_setattr */
3619 printf("nfs_update: unimplemented!!");
3621 return (EOPNOTSUPP
);
3624 int nfs_aio_threads
= 0; /* 1 per nfd (arbitrary) */
3625 struct slock nfs_aio_slock
;
3626 TAILQ_HEAD(bqueues
, buf
) nfs_aio_bufq
;
3627 int nfs_aio_bufq_len
= 0; /* diagnostic only */
3631 { /* see comment below in nfs_bwrite() for some rationale */
3633 boolean_t funnel_state
;
3635 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
3637 simple_lock(&nfs_aio_slock
);
3638 if ((bp
= nfs_aio_bufq
.tqh_first
)) {
3639 TAILQ_REMOVE(&nfs_aio_bufq
, bp
, b_freelist
);
3641 simple_unlock(&nfs_aio_slock
);
3643 } else { /* nothing to do - goodnight */
3644 assert_wait(&nfs_aio_bufq
, THREAD_UNINT
);
3645 simple_unlock(&nfs_aio_slock
);
3646 (void)tsleep((caddr_t
)0, PRIBIO
+1, "nfs_aio_bufq", 0);
3649 (void) thread_funnel_set(kernel_flock
, FALSE
);
3654 nfs_aio_thread_init()
3656 if (nfs_aio_threads
++ == 0) {
3657 simple_lock_init(&nfs_aio_slock
);
3658 TAILQ_INIT(&nfs_aio_bufq
);
3660 kernel_thread(kernel_task
, nfs_aio_thread
);
3665 * Just call nfs_writebp() with the force argument set to 1.
3669 struct vop_bwrite_args
/* {
3673 extern void wakeup_one(caddr_t chan
);
3676 * nfs_writebp will issue a synchronous rpc to if B_ASYNC then
3677 * to avoid distributed deadlocks we handoff the write to the
3678 * nfs_aio threads. Doing so allows us to complete the
3679 * current request, rather than blocking on a server which may
3680 * be ourself (or blocked on ourself).
3682 * Note the loopback deadlocks happened when the thread
3683 * invoking us was nfsd, and also when it was the pagedaemon.
3685 * This solution has one known problem. If *ALL* buffers get
3686 * on the nfs_aio queue then no forward progress can be made
3687 * until one of those writes complete. And if the current
3688 * nfs_aio writes-in-progress block due to a non-responsive server we
3689 * are in a deadlock circle. Probably the cure is to limit the
3690 * async write concurrency in getnewbuf as in FreeBSD 3.2.
3692 if (nfs_aio_threads
&& ISSET(ap
->a_bp
->b_flags
, B_ASYNC
)) {
3693 simple_lock(&nfs_aio_slock
);
3695 TAILQ_INSERT_TAIL(&nfs_aio_bufq
, ap
->a_bp
, b_freelist
);
3696 simple_unlock(&nfs_aio_slock
);
3697 wakeup_one((caddr_t
)&nfs_aio_bufq
);
3700 return (nfs_writebp(ap
->a_bp
, 1));
3704 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless
3705 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
3708 nfs_writebp(bp
, force
)
3709 register struct buf
*bp
;
3713 register int oldflags
= bp
->b_flags
, retv
= 1;
3717 struct vnode
*vp
= bp
->b_vp
;
3718 upl_page_info_t
*pl
;
3720 if(!ISSET(bp
->b_flags
, B_BUSY
))
3721 panic("nfs_writebp: buffer is not busy???");
3724 CLR(bp
->b_flags
, (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3726 if (ISSET(oldflags
, (B_ASYNC
|B_DELWRI
))) {
3727 reassignbuf(bp
, vp
);
3731 current_proc()->p_stats
->p_ru
.ru_oublock
++;
3735 * Since the B_BUSY flag is set, we need to lock the page before doing nfs_commit.
3736 * Otherwise we may block and get a busy incore pages during a vm pageout.
3737 * Move the existing code up before the commit.
3740 if (!ISSET(bp
->b_flags
, B_META
) && UBCISVALID(vp
)) {
3742 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3743 kret
= ubc_create_upl(vp
,
3744 ubc_blktooff(vp
, bp
->b_lblkno
),
3749 if (kret
!= KERN_SUCCESS
) {
3750 panic("nfs_writebp: get pagelists failed with (%d)", kret
);
3754 upl_ubc_alias_set(upl
, ioaddr
, 2);
3755 #endif /* UBC_DEBUG */
3759 bp
->b_pagelist
= upl
;
3760 SET(bp
->b_flags
, B_PAGELIST
);
3763 kret
= ubc_upl_map(upl
, (vm_address_t
*)&(bp
->b_data
));
3764 if (kret
!= KERN_SUCCESS
) {
3765 panic("nfs_writebp: ubc_upl_map() failed with (%d)", kret
);
3768 panic("nfs_writebp: upl_map mapped 0");
3770 if (!upl_page_present(pl
, 0)) {
3772 * may be the page got paged out.
3773 * let's just read it in. It is marked
3774 * busy so we should not have any one
3775 * yanking this page underneath the fileIO
3777 panic("nfs_writebp: nopage");
3783 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3784 * an actual write will have to be scheduled via. VOP_STRATEGY().
3785 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3787 if ((oldflags
& (B_NEEDCOMMIT
| B_WRITEINPROG
)) == B_NEEDCOMMIT
) {
3788 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+ bp
->b_dirtyoff
;
3789 SET(bp
->b_flags
, B_WRITEINPROG
);
3790 retv
= nfs_commit(vp
, off
, bp
->b_dirtyend
-bp
->b_dirtyoff
,
3791 bp
->b_wcred
, bp
->b_proc
);
3792 CLR(bp
->b_flags
, B_WRITEINPROG
);
3794 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3795 CLR(bp
->b_flags
, B_NEEDCOMMIT
);
3796 biodone(bp
); /* on B_ASYNC will brelse the buffer */
3798 } else if (retv
== NFSERR_STALEWRITEVERF
)
3799 nfs_clearcommit(vp
->v_mount
);
3803 SET(bp
->b_flags
, B_WRITEINPROG
);
3807 if( (oldflags
& B_ASYNC
) == 0) {
3808 int rtval
= biowait(bp
);
3810 if (oldflags
& B_DELWRI
) {
3812 reassignbuf(bp
, vp
);
3823 * nfs special file access vnode op.
3824 * Essentially just get vattr and then imitate iaccess() since the device is
3825 * local to the client.
3829 struct vop_access_args
/* {
3832 struct ucred *a_cred;
3836 register struct vattr
*vap
;
3838 register struct ucred
*cred
= ap
->a_cred
;
3839 struct vnode
*vp
= ap
->a_vp
;
3840 mode_t mode
= ap
->a_mode
;
3846 * Disallow write attempts on filesystems mounted read-only;
3847 * unless the file is a socket, fifo, or a block or character
3848 * device resident on the filesystem.
3850 if ((mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
3851 switch (vp
->v_type
) {
3852 case VREG
: case VDIR
: case VLNK
:
3857 * If you're the super-user,
3858 * you always get access.
3860 if (cred
->cr_uid
== 0)
3863 error
= VOP_GETATTR(vp
, vap
, cred
, ap
->a_p
);
3867 * Access check is based on only one of owner, group, public.
3868 * If not owner, then check group. If not a member of the
3869 * group, then check public access.
3871 if (cred
->cr_uid
!= vap
->va_uid
) {
3873 gp
= cred
->cr_groups
;
3874 for (i
= 0; i
< cred
->cr_ngroups
; i
++, gp
++)
3875 if (vap
->va_gid
== *gp
)
3881 error
= (vap
->va_mode
& mode
) == mode
? 0 : EACCES
;
3886 * Read wrapper for special devices.
3890 struct vop_read_args
/* {
3894 struct ucred *a_cred;
3897 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3903 np
->n_atim
.tv_sec
= time
.tv_sec
;
3904 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
3905 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_read
), ap
));
3909 * Write wrapper for special devices.
3913 struct vop_write_args
/* {
3917 struct ucred *a_cred;
3920 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3926 np
->n_mtim
.tv_sec
= time
.tv_sec
;
3927 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
3928 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_write
), ap
));
3932 * Close wrapper for special devices.
3934 * Update the times on the nfsnode then do device close.
3938 struct vop_close_args
/* {
3941 struct ucred *a_cred;
3945 register struct vnode
*vp
= ap
->a_vp
;
3946 register struct nfsnode
*np
= VTONFS(vp
);
3949 if (np
->n_flag
& (NACC
| NUPD
)) {
3951 if (vp
->v_usecount
== 1 &&
3952 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
3954 if (np
->n_flag
& NACC
)
3955 vattr
.va_atime
= np
->n_atim
;
3956 if (np
->n_flag
& NUPD
)
3957 vattr
.va_mtime
= np
->n_mtim
;
3958 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
3961 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_close
), ap
));
3965 * Read wrapper for fifos.
3969 struct vop_read_args
/* {
3973 struct ucred *a_cred;
3976 extern vop_t
**fifo_vnodeop_p
;
3977 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3983 np
->n_atim
.tv_sec
= time
.tv_sec
;
3984 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
3985 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_read
), ap
));
3989 * Write wrapper for fifos.
3993 struct vop_write_args
/* {
3997 struct ucred *a_cred;
4000 extern vop_t
**fifo_vnodeop_p
;
4001 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
4007 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4008 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4009 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_write
), ap
));
4013 * Close wrapper for fifos.
4015 * Update the times on the nfsnode then do fifo close.
4019 struct vop_close_args
/* {
4022 struct ucred *a_cred;
4026 register struct vnode
*vp
= ap
->a_vp
;
4027 register struct nfsnode
*np
= VTONFS(vp
);
4029 extern vop_t
**fifo_vnodeop_p
;
4031 if (np
->n_flag
& (NACC
| NUPD
)) {
4032 if (np
->n_flag
& NACC
) {
4033 np
->n_atim
.tv_sec
= time
.tv_sec
;
4034 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
4036 if (np
->n_flag
& NUPD
) {
4037 np
->n_mtim
.tv_sec
= time
.tv_sec
;
4038 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
4041 if (vp
->v_usecount
== 1 &&
4042 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
4044 if (np
->n_flag
& NACC
)
4045 vattr
.va_atime
= np
->n_atim
;
4046 if (np
->n_flag
& NUPD
)
4047 vattr
.va_mtime
= np
->n_mtim
;
4048 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
4051 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_close
), ap
));
4056 struct vop_ioctl_args
*ap
;
4060 * XXX we were once bogusly enoictl() which returned this (ENOTTY).
4061 * Probably we should return ENODEV.
4068 struct vop_select_args
*ap
;
4072 * We were once bogusly seltrue() which returns 1. Is this right?
4077 /* XXX Eliminate use of struct bp here */
4079 * Vnode op for pagein using getblk_pages
4080 * derived from nfs_bioread()
4081 * No read aheads are started from pagein operation
4085 struct vop_pagein_args
/* {
4088 vm_offset_t a_pl_offset,
4091 struct ucred *a_cred,
4095 register struct vnode
*vp
= ap
->a_vp
;
4096 upl_t pl
= ap
->a_pl
;
4097 size_t size
= ap
->a_size
;
4098 off_t f_offset
= ap
->a_f_offset
;
4099 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4100 int flags
= ap
->a_flags
;
4102 register struct nfsnode
*np
= VTONFS(vp
);
4103 register int biosize
;
4106 struct proc
*p
= current_proc();
4107 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4112 struct uio
* uio
= &auio
;
4113 int nocommit
= flags
& UPL_NOCOMMIT
;
4115 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 322)) | DBG_FUNC_NONE
,
4116 (int)f_offset
, size
, pl
, pl_offset
, 0);
4118 if (UBCINVALID(vp
)) {
4120 panic("nfs_pagein: invalid vp");
4121 #endif /* DIAGNOSTIC */
4125 UBCINFOCHECK("nfs_pagein", vp
);
4126 if(pl
== (upl_t
)NULL
) {
4127 panic("nfs_pagein: no upl");
4130 cred
= ubc_getcred(vp
);
4137 if (f_offset
< 0 || f_offset
>= np
->n_size
4138 || (f_offset
& PAGE_MASK_64
)) {
4140 ubc_upl_abort_range(pl
, pl_offset
, size
,
4141 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4145 auio
.uio_iov
= &aiov
;
4146 auio
.uio_iovcnt
= 1;
4147 auio
.uio_offset
= f_offset
;
4148 auio
.uio_segflg
= UIO_SYSSPACE
;
4149 auio
.uio_rw
= UIO_READ
;
4150 auio
.uio_procp
= NULL
;
4153 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4154 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4155 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4157 if (biosize
& PAGE_MASK
)
4158 panic("nfs_pagein(%x): biosize not page aligned", biosize
);
4160 #if 0 /* Why bother? */
4161 /* DO NOT BOTHER WITH "approximately maintained cache consistency" */
4162 /* Does not make sense in paging paths -- Umesh*/
4164 * For nfs, cache consistency can only be maintained approximately.
4165 * Although RFC1094 does not specify the criteria, the following is
4166 * believed to be compatible with the reference port.
4167 * For nqnfs, full cache consistency is maintained within the loop.
4169 * If the file's modify time on the server has changed since the
4170 * last read rpc or you have written to the file,
4171 * you may have lost data cache consistency with the
4172 * server, so flush all of the file's data out of the cache.
4173 * Then force a getattr rpc to ensure that you have up to date
4175 * NB: This implies that cache data can be read when up to
4176 * NFS_ATTRTIMEO seconds out of date. If you find that you need current
4177 * attributes this could be forced by setting n_attrstamp to 0 before
4178 * the VOP_GETATTR() call.
4180 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) == 0) {
4181 if (np
->n_flag
& NMODIFIED
) {
4182 np
->n_attrstamp
= 0;
4183 error
= VOP_GETATTR(vp
, &vattr
, cred
, p
);
4186 ubc_upl_abort_range(pl
, pl_offset
, size
,
4187 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4190 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
4192 error
= VOP_GETATTR(vp
, &vattr
, cred
, p
);
4195 ubc_upl_abort_range(pl
, pl_offset
, size
,
4196 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4199 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
4200 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4203 ubc_upl_abort_range(pl
, pl_offset
, size
,
4204 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4207 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
4211 #endif 0 /* Why bother? */
4213 ubc_upl_map(pl
, &ioaddr
);
4214 ioaddr
+= pl_offset
;
4218 uio
->uio_resid
= min(biosize
, xsize
);
4219 aiov
.iov_len
= uio
->uio_resid
;
4220 aiov
.iov_base
= (caddr_t
)ioaddr
;
4222 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 322)) | DBG_FUNC_NONE
,
4223 (int)uio
->uio_offset
, uio
->uio_resid
, ioaddr
, xsize
, 0);
4225 #warning nfs_pagein does not support NQNFS yet.
4226 #if 0 /* why bother? */
4227 /* NO RESOURCES TO FIX NQNFS CASE */
4228 /* We need to deal with this later -- Umesh */
4230 * Get a valid lease. If cached data is stale, flush it.
4232 if (nmp
->nm_flag
& NFSMNT_NQNFS
) {
4233 if (NQNFS_CKINVALID(vp
, np
, ND_READ
)) {
4235 error
= nqnfs_getlease(vp
, ND_READ
, cred
, p
);
4236 } while (error
== NQNFS_EXPIRED
);
4240 ubc_upl_abort_range(pl
, pl_offset
, size
,
4241 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4245 if (np
->n_lrev
!= np
->n_brev
||
4246 (np
->n_flag
& NQNFSNONCACHE
)) {
4247 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4251 ubc_upl_abort_range(pl
, pl_offset
, size
,
4252 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4255 np
->n_brev
= np
->n_lrev
;
4259 #endif 0 /* why bother? */
4261 if (np
->n_flag
& NQNFSNONCACHE
) {
4262 error
= nfs_readrpc(vp
, uio
, cred
);
4267 ubc_upl_abort_range(pl
, pl_offset
, size
,
4268 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4270 ubc_upl_commit_range(pl
, pl_offset
, size
,
4271 UPL_COMMIT_CLEAR_DIRTY
| UPL_COMMIT_FREE_ON_EMPTY
);
4277 * With UBC we get here only when the file data is not in the VM
4278 * page cache, so go ahead and read in.
4281 upl_ubc_alias_set(pl
, ioaddr
, 2);
4282 #endif /* UBC_DEBUG */
4284 error
= nfs_readrpc(vp
, uio
, cred
);
4290 if (uio
->uio_resid
) {
4292 * If uio_resid > 0, there is a hole in the file and
4293 * no writes after the hole have been pushed to
4294 * the server yet... or we're at the EOF
4295 * Just zero fill the rest of the valid area.
4297 zcnt
= uio
->uio_resid
;
4298 zoff
= biosize
- zcnt
;
4299 bzero((char *)ioaddr
+ zoff
, zcnt
);
4301 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 324)) | DBG_FUNC_NONE
,
4302 (int)uio
->uio_offset
, zoff
, zcnt
, ioaddr
, 0);
4304 uio
->uio_offset
+= zcnt
;
4309 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 322)) | DBG_FUNC_NONE
,
4310 (int)uio
->uio_offset
, uio
->uio_resid
, error
, -1, 0);
4312 if (p
&& (vp
->v_flag
& VTEXT
) &&
4313 (((nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4314 NQNFS_CKINVALID(vp
, np
, ND_READ
) &&
4315 np
->n_lrev
!= np
->n_brev
) ||
4316 (!(nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4317 np
->n_mtime
!= np
->n_vattr
.va_mtime
.tv_sec
))) {
4318 uprintf("Process killed due to text file modification\n");
4319 psignal(p
, SIGKILL
);
4320 p
->p_flag
|= P_NOSWAP
;
4323 } while (error
== 0 && xsize
> 0);
4329 ubc_upl_abort_range(pl
, pl_offset
, size
,
4330 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4332 ubc_upl_commit_range(pl
, pl_offset
, size
,
4333 UPL_COMMIT_CLEAR_DIRTY
| UPL_COMMIT_FREE_ON_EMPTY
);
4342 * Vnode op for pageout using UPL
4343 * Derived from nfs_write()
4344 * File size changes are not permitted in pageout.
4348 struct vop_pageout_args
/* {
4351 vm_offset_t a_pl_offset,
4354 struct ucred *a_cred,
4358 register struct vnode
*vp
= ap
->a_vp
;
4359 upl_t pl
= ap
->a_pl
;
4360 size_t size
= ap
->a_size
;
4361 off_t f_offset
= ap
->a_f_offset
;
4362 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4363 int flags
= ap
->a_flags
;
4364 int ioflag
= ap
->a_flags
;
4365 register int biosize
;
4366 struct proc
*p
= current_proc();
4367 struct nfsnode
*np
= VTONFS(vp
);
4368 register struct ucred
*cred
;
4370 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4373 int n
= 0, on
, error
= 0, iomode
, must_commit
, s
;
4378 struct uio
* uio
= &auio
;
4379 int nocommit
= flags
& UPL_NOCOMMIT
;
4383 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 323)) | DBG_FUNC_NONE
,
4384 (int)f_offset
, size
, pl
, pl_offset
, 0);
4386 if (UBCINVALID(vp
)) {
4388 panic("nfs_pageout: invalid vnode");
4392 UBCINFOCHECK("nfs_pageout", vp
);
4397 if (pl
== (upl_t
)NULL
) {
4398 panic("nfs_pageout: no upl");
4402 * I use nm_rsize, not nm_wsize so that all buffer cache blocks
4403 * will be the same size within a filesystem. nfs_writerpc will
4404 * still use nm_wsize when sizing the rpc's.
4406 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4408 if (biosize
& PAGE_MASK
)
4409 panic("nfs_pageout(%x): biosize not page aligned", biosize
);
4413 * Check to see whether the buffer is incore
4414 * If incore and not busy invalidate it from the cache
4415 * we should not find it BUSY, since we always do a
4416 * vm_fault_list_request in 'getblk' before returning
4417 * which would block on the page busy status
4419 lbn
= f_offset
/ PAGE_SIZE
; /* to match the size getblk uses */
4421 for (iosize
= size
; iosize
> 0; iosize
-= PAGE_SIZE
, lbn
++) {
4424 if (bp
= incore(vp
, lbn
)) {
4425 if (ISSET(bp
->b_flags
, B_BUSY
)) {
4426 /* don't panic incore. just tell vm we are busy */
4427 (void) ubc_upl_abort(pl
, NULL
);
4432 SET(bp
->b_flags
, (B_BUSY
| B_INVAL
));
4438 cred
= ubc_getcred(vp
);
4442 if (np
->n_flag
& NWRITEERR
) {
4443 np
->n_flag
&= ~NWRITEERR
;
4445 ubc_upl_abort_range(pl
, pl_offset
, size
, UPL_ABORT_FREE_ON_EMPTY
);
4446 return (np
->n_error
);
4448 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4449 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4451 if (f_offset
< 0 || f_offset
>= np
->n_size
||
4452 (f_offset
& PAGE_MASK_64
) || (size
& PAGE_MASK
)) {
4454 ubc_upl_abort_range(pl
, pl_offset
, size
, UPL_ABORT_FREE_ON_EMPTY
);
4458 ubc_upl_map(pl
, &ioaddr
);
4460 if ((f_offset
+ size
) > np
->n_size
)
4461 iosize
= np
->n_size
- f_offset
;
4465 pgsize
= (iosize
+ (PAGE_SIZE
- 1)) & ~PAGE_MASK
;
4467 if (size
> pgsize
) {
4469 ubc_upl_abort_range(pl
, pl_offset
+ pgsize
, size
- pgsize
,
4470 UPL_ABORT_FREE_ON_EMPTY
);
4472 auio
.uio_iov
= &aiov
;
4473 auio
.uio_iovcnt
= 1;
4474 auio
.uio_offset
= f_offset
;
4475 auio
.uio_segflg
= UIO_SYSSPACE
;
4476 auio
.uio_rw
= UIO_READ
;
4477 auio
.uio_resid
= iosize
;
4478 auio
.uio_procp
= NULL
;
4480 aiov
.iov_len
= iosize
;
4481 aiov
.iov_base
= (caddr_t
)ioaddr
+ pl_offset
;
4484 * check for partial page and clear the
4485 * contents past end of the file before
4486 * releasing it in the VM page cache
4488 if ((f_offset
< np
->n_size
) && (f_offset
+ size
) > np
->n_size
) {
4489 size_t io
= np
->n_size
- f_offset
;
4491 bzero((caddr_t
)(ioaddr
+ pl_offset
+ io
), size
- io
);
4493 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 321)) | DBG_FUNC_NONE
,
4494 (int)np
->n_size
, (int)f_offset
, (int)f_offset
+ io
, size
- io
, 0);
4499 #warning nfs_pageout does not support NQNFS yet.
4500 #if 0 /* why bother? */
4501 /* NO RESOURCES TO FIX NQNFS CASE */
4502 /* We need to deal with this later -- Umesh */
4505 * Check for a valid write lease.
4507 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4508 NQNFS_CKINVALID(vp
, np
, ND_WRITE
)) {
4510 error
= nqnfs_getlease(vp
, ND_WRITE
, cred
, p
);
4511 } while (error
== NQNFS_EXPIRED
);
4515 ubc_upl_abort_range(pl
, pl_offset
, size
,
4516 UPL_ABORT_FREE_ON_EMPTY
);
4519 if (np
->n_lrev
!= np
->n_brev
||
4520 (np
->n_flag
& NQNFSNONCACHE
)) {
4521 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4525 ubc_upl_abort_range(pl
, pl_offset
, size
,
4526 UPL_ABORT_FREE_ON_EMPTY
);
4529 np
->n_brev
= np
->n_lrev
;
4532 #endif 0 /* why bother? */
4534 if ((np
->n_flag
& NQNFSNONCACHE
) && uio
->uio_iovcnt
== 1) {
4535 iomode
= NFSV3WRITE_FILESYNC
;
4536 error
= nfs_writerpc(vp
, uio
, cred
, &iomode
, &must_commit
);
4538 nfs_clearcommit(vp
->v_mount
);
4541 /* copied from non-nqnfs case below. see there for comments */
4545 short action
= nfs_pageouterrorhandler(error
);
4549 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4552 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4553 if ((error
<= ELAST
) && (errorcount
[error
] % 100 == 0))
4554 printf("nfs_pageout: unexpected error %d. dumping vm page\n", error
);
4555 errorcount
[error
]++;
4558 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4560 case RETRYWITHSLEEP
:
4561 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4562 (void) tsleep(&lbolt
, PSOCK
, "nfspageout", 0); /* pri unused. PSOCK for placeholder. */
4564 case SEVER
: /* not implemented */
4566 printf("nfs_pageout: action %d not expected\n", action
);
4570 ubc_upl_abort_range(pl
, pl_offset
, size
, abortflags
);
4571 /* return error in all cases above */
4574 ubc_upl_commit_range(pl
,
4576 UPL_COMMIT_CLEAR_DIRTY
| UPL_COMMIT_FREE_ON_EMPTY
);
4578 return (error
); /* note this early return */
4581 nfsstats
.pageouts
++;
4582 lbn
= uio
->uio_offset
/ biosize
;
4583 on
= uio
->uio_offset
& (biosize
-1);
4584 n
= min((unsigned)(biosize
- on
), uio
->uio_resid
);
4588 if ((lbn
+ 1) * biosize
> np
->n_size
) {
4589 bufsize
= np
->n_size
- lbn
* biosize
;
4590 bufsize
= (bufsize
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
4595 np
->n_flag
|= NMODIFIED
;
4597 #if 0 /* why bother? */
4598 /* NO RESOURCES TO FIX NQNFS CASE */
4599 /* We need to deal with this later -- Umesh */
4601 * Check for valid write lease and get one as required.
4602 * In case getblk() and/or bwrite() delayed us.
4604 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4605 NQNFS_CKINVALID(vp
, np
, ND_WRITE
)) {
4607 error
= nqnfs_getlease(vp
, ND_WRITE
, cred
, p
);
4608 } while (error
== NQNFS_EXPIRED
);
4612 if (np
->n_lrev
!= np
->n_brev
||
4613 (np
->n_flag
& NQNFSNONCACHE
)) {
4614 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4618 ubc_upl_abort_range(pl
, pl_offset
, size
,
4619 UPL_ABORT_FREE_ON_EMPTY
);
4623 np
->n_brev
= np
->n_lrev
;
4627 #endif 0 /* why bother? */
4629 iomode
= NFSV3WRITE_FILESYNC
;
4630 error
= nfs_writerpc(vp
, uio
, cred
, &iomode
, &must_commit
);
4632 nfs_clearcommit(vp
->v_mount
);
4639 uio
->uio_resid
-= n
;
4640 uio
->uio_offset
+= n
;
4641 uio
->uio_iov
->iov_base
+= n
;
4642 uio
->uio_iov
->iov_len
-= n
;
4644 } while (uio
->uio_resid
> 0 && n
> 0);
4649 * We've had several different solutions on what to do when the pageout
4650 * gets an error. If we don't handle it, and return an error to the
4651 * caller, vm, it will retry . This can end in endless looping
4652 * between vm and here doing retries of the same page. Doing a dump
4653 * back to vm, will get it out of vm's knowledge and we lose whatever
4654 * data existed. This is risky, but in some cases necessary. For
4655 * example, the initial fix here was to do that for ESTALE. In that case
4656 * the server is telling us that the file is no longer the same. We
4657 * would not want to keep paging out to that. We also saw some 151
4658 * errors from Auspex server and NFSv3 can return errors higher than
4659 * ELAST. Those along with NFS known server errors we will "dump" from vm.
4660 * Errors we don't expect to occur, we dump and log for further
4661 * analysis. Errors that could be transient, networking ones,
4662 * we let vm "retry". Lastly, errors that we retry, but may have potential
4663 * to storm the network, we "retrywithsleep". "sever" will be used in
4664 * in the future to dump all pages of object for cases like ESTALE.
4665 * All this is the basis for the states returned and first guesses on
4666 * error handling. Tweaking expected as more statistics are gathered.
4667 * Note, in the long run we may need another more robust solution to
4668 * have some kind of persistant store when the vm cannot dump nor keep
4669 * retrying as a solution, but this would be a file architectural change.
4672 if (!nocommit
) { /* otherwise stacked file system has to handle this */
4675 short action
= nfs_pageouterrorhandler(error
);
4679 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4682 abortflags
= UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
;
4683 if ((error
<= ELAST
) && (errorcount
[error
] % 100 == 0))
4684 printf("nfs_pageout: unexpected error %d. dumping vm page\n", error
);
4685 errorcount
[error
]++;
4688 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4690 case RETRYWITHSLEEP
:
4691 abortflags
= UPL_ABORT_FREE_ON_EMPTY
;
4692 (void) tsleep(&lbolt
, PSOCK
, "nfspageout", 0); /* pri unused. PSOCK for placeholder. */
4694 case SEVER
: /* not implemented */
4696 printf("nfs_pageout: action %d not expected\n", action
);
4700 ubc_upl_abort_range(pl
, pl_offset
, size
, abortflags
);
4701 /* return error in all cases above */
4704 ubc_upl_commit_range(pl
, pl_offset
, pgsize
,
4705 UPL_COMMIT_CLEAR_DIRTY
| UPL_COMMIT_FREE_ON_EMPTY
);
4710 /* Blktooff derives file offset given a logical block number */
4713 struct vop_blktooff_args
/* {
4720 register struct vnode
*vp
= ap
->a_vp
;
4722 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4724 *ap
->a_offset
= (off_t
)(ap
->a_lblkno
* biosize
);
4729 /* Blktooff derives file offset given a logical block number */
4732 struct vop_offtoblk_args
/* {
4739 register struct vnode
*vp
= ap
->a_vp
;
4741 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4743 *ap
->a_lblkno
= (daddr_t
)(ap
->a_offset
/ biosize
);
4749 struct vop_cmap_args
/* {
4758 return (EOPNOTSUPP
);