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_badop
}, /* 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)
389 nfs3_access_otw(struct vnode
*vp
,
396 int error
= 0, attrflag
;
398 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
399 caddr_t bpos
, dpos
, cp2
;
400 register int32_t t1
, t2
;
403 struct nfsnode
*np
= VTONFS(vp
);
405 nfsstats
.rpccnt
[NFSPROC_ACCESS
]++;
406 nfsm_reqhead(vp
, NFSPROC_ACCESS
, NFSX_FH(v3
) + NFSX_UNSIGNED
);
408 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
409 *tl
= txdr_unsigned(wmode
);
410 nfsm_request(vp
, NFSPROC_ACCESS
, p
, cred
);
411 nfsm_postop_attr(vp
, attrflag
);
413 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
414 rmode
= fxdr_unsigned(u_int32_t
, *tl
);
416 np
->n_modeuid
= cred
->cr_uid
;
417 np
->n_modestamp
= time_second
;
424 * nfs access vnode op.
425 * For nfs version 2, just return ok. File accesses may fail later.
426 * For nfs version 3, use the access rpc to check accessibility. If file modes
427 * are changed on the server, accesses might still fail later.
431 struct vop_access_args
/* {
434 struct ucred *a_cred;
438 register struct vnode
*vp
= ap
->a_vp
;
441 int v3
= NFS_ISV3(vp
);
442 struct nfsnode
*np
= VTONFS(vp
);
445 * For nfs v3, do an access rpc, otherwise you are stuck emulating
446 * ufs_access() locally using the vattr. This may not be correct,
447 * since the server may apply other access criteria such as
448 * client uid-->server uid mapping that we do not know about, but
449 * this is better than just returning anything that is lying about
453 if (ap
->a_mode
& VREAD
)
454 mode
= NFSV3ACCESS_READ
;
457 if (vp
->v_type
== VDIR
) {
458 if (ap
->a_mode
& VWRITE
)
459 mode
|= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
|
461 if (ap
->a_mode
& VEXEC
)
462 mode
|= NFSV3ACCESS_LOOKUP
;
464 if (ap
->a_mode
& VWRITE
)
465 mode
|= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
);
466 if (ap
->a_mode
& VEXEC
)
467 mode
|= NFSV3ACCESS_EXECUTE
;
469 /* XXX safety belt, only make blanket request if caching */
470 if (nfsaccess_cache_timeout
> 0) {
471 wmode
= NFSV3ACCESS_READ
| NFSV3ACCESS_MODIFY
|
472 NFSV3ACCESS_EXTEND
| NFSV3ACCESS_EXECUTE
|
473 NFSV3ACCESS_DELETE
| NFSV3ACCESS_LOOKUP
;
479 * Does our cached result allow us to give a definite yes to
482 if ((time_second
< (np
->n_modestamp
+ nfsaccess_cache_timeout
)) &&
483 (ap
->a_cred
->cr_uid
== np
->n_modeuid
) &&
484 ((np
->n_mode
& mode
) == mode
)) {
485 /* nfsstats.accesscache_hits++; */
488 * Either a no, or a don't know. Go to the wire.
490 /* nfsstats.accesscache_misses++; */
491 error
= nfs3_access_otw(vp
, wmode
, ap
->a_p
,ap
->a_cred
);
493 if ((np
->n_mode
& mode
) != mode
)
498 return (nfsspec_access(ap
)); /* NFSv2 case checks for EROFS here*/
499 /* CSM - moved EROFS check down per NetBSD rev 1.71. So you
500 * get the correct error value with layered filesystems.
501 * EKN - moved the return(error) below this so it does get called.*/
503 * Disallow write attempts on filesystems mounted read-only;
504 * unless the file is a socket, fifo, or a block or character
505 * device resident on the filesystem.
507 if (!error
&& (ap
->a_mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
508 switch (vp
->v_type
) {
509 case VREG
: case VDIR
: case VLNK
:
520 * Check to see if the type is ok
521 * and that deletion is not in progress.
522 * For paged in text files, you will need to flush the page cache
523 * if consistency is lost.
528 struct vop_open_args
/* {
531 struct ucred *a_cred;
535 register struct vnode
*vp
= ap
->a_vp
;
536 struct nfsnode
*np
= VTONFS(vp
);
537 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
541 if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
&& vp
->v_type
!= VLNK
)
542 { printf("open eacces vtyp=%d\n",vp
->v_type
);
546 * Get a valid lease. If cached data is stale, flush it.
548 if (nmp
->nm_flag
& NFSMNT_NQNFS
) {
549 if (NQNFS_CKINVALID(vp
, np
, ND_READ
)) {
551 error
= nqnfs_getlease(vp
, ND_READ
, ap
->a_cred
,
553 } while (error
== NQNFS_EXPIRED
);
556 if (np
->n_lrev
!= np
->n_brev
||
557 (np
->n_flag
& NQNFSNONCACHE
)) {
558 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
559 ap
->a_p
, 1)) == EINTR
)
561 np
->n_brev
= np
->n_lrev
;
565 if (np
->n_flag
& NMODIFIED
) {
566 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
567 ap
->a_p
, 1)) == EINTR
)
570 if (vp
->v_type
== VDIR
)
571 np
->n_direofoffset
= 0;
572 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
575 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
577 error
= VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
580 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
581 if (vp
->v_type
== VDIR
)
582 np
->n_direofoffset
= 0;
583 if ((error
= nfs_vinvalbuf(vp
, V_SAVE
,
584 ap
->a_cred
, ap
->a_p
, 1)) == EINTR
)
586 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
590 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) == 0)
591 np
->n_attrstamp
= 0; /* For Open/Close consistency */
597 * What an NFS client should do upon close after writing is a debatable issue.
598 * Most NFS clients push delayed writes to the server upon close, basically for
600 * 1 - So that any write errors may be reported back to the client process
601 * doing the close system call. By far the two most likely errors are
602 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
603 * 2 - To put a worst case upper bound on cache inconsistency between
604 * multiple clients for the file.
605 * There is also a consistency problem for Version 2 of the protocol w.r.t.
606 * not being able to tell if other clients are writing a file concurrently,
607 * since there is no way of knowing if the changed modify time in the reply
608 * is only due to the write for this client.
609 * (NFS Version 3 provides weak cache consistency data in the reply that
610 * should be sufficient to detect and handle this case.)
612 * The current code does the following:
613 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
614 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
615 * or commit them (this satisfies 1 and 2 except for the
616 * case where the server crashes after this close but
617 * before the commit RPC, which is felt to be "good
618 * enough". Changing the last argument to nfs_flush() to
619 * a 1 would force a commit operation, if it is felt a
620 * commit is necessary now.
621 * for NQNFS - do nothing now, since 2 is dealt with via leases and
622 * 1 should be dealt with via an fsync() system call for
623 * cases where write errors are important.
628 struct vop_close_args
/* {
629 struct vnodeop_desc *a_desc;
632 struct ucred *a_cred;
636 register struct vnode
*vp
= ap
->a_vp
;
637 register struct nfsnode
*np
= VTONFS(vp
);
640 if (vp
->v_type
== VREG
) {
642 register struct sillyrename
*sp
= np
->n_sillyrename
;
644 kprintf("nfs_close: %s, dvp=%x, vp=%x, ap=%x, np=%x, sp=%x\n",
645 &sp
->s_name
[0], (unsigned)(sp
->s_dvp
), (unsigned)vp
,
646 (unsigned)ap
, (unsigned)np
, (unsigned)sp
);
648 if ((VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) == 0 &&
649 (np
->n_flag
& NMODIFIED
)) {
651 error
= nfs_flush(vp
, ap
->a_cred
, MNT_WAIT
, ap
->a_p
, 0);
652 np
->n_flag
&= ~NMODIFIED
;
654 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
, ap
->a_p
, 1);
657 if (np
->n_flag
& NWRITEERR
) {
658 np
->n_flag
&= ~NWRITEERR
;
666 * nfs getattr call from vfs.
670 struct vop_getattr_args
/* {
673 struct ucred *a_cred;
677 register struct vnode
*vp
= ap
->a_vp
;
678 register struct nfsnode
*np
= VTONFS(vp
);
684 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
685 int v3
= NFS_ISV3(vp
);
688 * Update local times for special files.
690 if (np
->n_flag
& (NACC
| NUPD
))
693 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 513)) | DBG_FUNC_START
,
694 (int)np
->n_size
, 0, (int)np
->n_vattr
.va_size
, np
->n_flag
, 0);
697 * First look in the cache.
699 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0) {
700 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 513)) | DBG_FUNC_END
,
701 (int)np
->n_size
, 0, (int)np
->n_vattr
.va_size
, np
->n_flag
, 0);
709 if (v3
&& nfsaccess_cache_timeout
> 0) {
710 /* nfsstats.accesscache_misses++; */
711 if (error
= nfs3_access_otw(vp
, NFSV3ACCESS_ALL
, ap
->a_p
, ap
->a_cred
))
713 if ((error
= nfs_getattrcache(vp
, ap
->a_vap
)) == 0)
720 nfsstats
.rpccnt
[NFSPROC_GETATTR
]++;
721 nfsm_reqhead(vp
, NFSPROC_GETATTR
, NFSX_FH(v3
));
723 nfsm_request(vp
, NFSPROC_GETATTR
, ap
->a_p
, ap
->a_cred
);
725 nfsm_loadattr(vp
, ap
->a_vap
);
726 if (np
->n_mtime
!= ap
->a_vap
->va_mtime
.tv_sec
) {
727 NFSTRACE(NFSTRC_GA_INV
, vp
);
728 if (vp
->v_type
== VDIR
)
730 error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
733 NFSTRACE(NFSTRC_GA_INV1
, vp
);
734 np
->n_mtime
= ap
->a_vap
->va_mtime
.tv_sec
;
736 NFSTRACE(NFSTRC_GA_INV2
, error
);
742 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 513)) | DBG_FUNC_END
,
743 (int)np
->n_size
, -1, (int)np
->n_vattr
.va_size
, error
, 0);
753 struct vop_setattr_args
/* {
754 struct vnodeop_desc *a_desc;
757 struct ucred *a_cred;
761 register struct vnode
*vp
= ap
->a_vp
;
762 register struct nfsnode
*np
= VTONFS(vp
);
763 register struct vattr
*vap
= ap
->a_vap
;
771 * Disallow write attempts if the filesystem is mounted read-only.
773 if ((vap
->va_flags
!= VNOVAL
|| vap
->va_uid
!= (uid_t
)VNOVAL
||
774 vap
->va_gid
!= (gid_t
)VNOVAL
|| vap
->va_atime
.tv_sec
!= VNOVAL
||
775 vap
->va_mtime
.tv_sec
!= VNOVAL
|| vap
->va_mode
!= (mode_t
)VNOVAL
) &&
776 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
778 if (vap
->va_size
!= VNOVAL
) {
779 switch (vp
->v_type
) {
786 if (vap
->va_mtime
.tv_sec
== VNOVAL
&&
787 vap
->va_atime
.tv_sec
== VNOVAL
&&
788 vap
->va_mode
== (u_short
)VNOVAL
&&
789 vap
->va_uid
== (uid_t
)VNOVAL
&&
790 vap
->va_gid
== (gid_t
)VNOVAL
)
792 vap
->va_size
= VNOVAL
;
796 * Disallow write attempts if the filesystem is
799 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
801 np
->n_flag
|= NMODIFIED
;
804 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 512)) | DBG_FUNC_START
,
805 (int)np
->n_size
, (int)vap
->va_size
, (int)np
->n_vattr
.va_size
, np
->n_flag
, 0);
807 if (vap
->va_size
== 0)
808 error
= nfs_vinvalbuf(vp
, 0,
809 ap
->a_cred
, ap
->a_p
, 1);
811 error
= nfs_vinvalbuf(vp
, V_SAVE
,
812 ap
->a_cred
, ap
->a_p
, 1);
815 ubc_setsize(vp
, (off_t
)vap
->va_size
); /* XXX check error */
818 printf("nfs_setattr: nfs_vinvalbuf %d\n", error
);
821 kprintf("nfs_setattr: nfs_vinvalbuf %d\n",
823 #endif /* DIAGNOSTIC */
825 ubc_setsize(vp
, (off_t
)tsize
); /* XXX check error */
827 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 512)) | DBG_FUNC_END
,
828 (int)np
->n_size
, (int)vap
->va_size
, (int)np
->n_vattr
.va_size
, -1, 0);
832 np
->n_size
= np
->n_vattr
.va_size
= vap
->va_size
;
835 } else if ((vap
->va_mtime
.tv_sec
!= VNOVAL
||
836 vap
->va_atime
.tv_sec
!= VNOVAL
) && (np
->n_flag
& NMODIFIED
) &&
837 vp
->v_type
== VREG
&&
838 (error
= nfs_vinvalbuf(vp
, V_SAVE
, ap
->a_cred
,
839 ap
->a_p
, 1)) == EINTR
)
842 error
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
844 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 512)) | DBG_FUNC_END
,
845 (int)np
->n_size
, (int)vap
->va_size
, (int)np
->n_vattr
.va_size
, error
, 0);
847 if (error
&& vap
->va_size
!= VNOVAL
) {
848 /* make every effort to resync file size w/ server... */
849 int err
= 0; /* preserve "error" for return */
851 printf("nfs_setattr: nfs_setattrrpc %d\n", error
);
853 kprintf("nfs_setattr: nfs_setattrrpc %d\n", error
);
854 #endif /* DIAGNOSTIC */
855 np
->n_size
= np
->n_vattr
.va_size
= tsize
;
857 ubc_setsize(vp
, (off_t
)np
->n_size
); /* XXX check error */
858 vap
->va_size
= tsize
;
859 err
= nfs_setattrrpc(vp
, vap
, ap
->a_cred
, ap
->a_p
);
862 printf("nfs_setattr1: nfs_setattrrpc %d\n", err
);
865 kprintf("nfs_setattr nfs_setattrrpc %d\n", err
);
866 #endif /* DIAGNOSTIC */
872 * Do an nfs setattr rpc.
875 nfs_setattrrpc(vp
, vap
, cred
, procp
)
876 register struct vnode
*vp
;
877 register struct vattr
*vap
;
881 register struct nfsv2_sattr
*sp
;
883 register long t1
, t2
;
884 caddr_t bpos
, dpos
, cp2
;
886 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
887 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
888 int v3
= NFS_ISV3(vp
);
890 nfsstats
.rpccnt
[NFSPROC_SETATTR
]++;
891 nfsm_reqhead(vp
, NFSPROC_SETATTR
, NFSX_FH(v3
) + NFSX_SATTR(v3
));
894 if (vap
->va_mode
!= (u_short
)VNOVAL
) {
895 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
897 *tl
= txdr_unsigned(vap
->va_mode
);
899 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
902 if (vap
->va_uid
!= (uid_t
)VNOVAL
) {
903 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
905 *tl
= txdr_unsigned(vap
->va_uid
);
907 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
910 if (vap
->va_gid
!= (gid_t
)VNOVAL
) {
911 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
913 *tl
= txdr_unsigned(vap
->va_gid
);
915 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
918 if (vap
->va_size
!= VNOVAL
) {
919 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
921 txdr_hyper(&vap
->va_size
, tl
);
923 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
926 if (vap
->va_atime
.tv_sec
!= VNOVAL
) {
927 if (vap
->va_atime
.tv_sec
!= time
.tv_sec
) {
928 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
929 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
930 txdr_nfsv3time(&vap
->va_atime
, tl
);
932 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
933 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
936 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
937 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
939 if (vap
->va_mtime
.tv_sec
!= VNOVAL
) {
940 if (vap
->va_mtime
.tv_sec
!= time
.tv_sec
) {
941 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
942 *tl
++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT
);
943 txdr_nfsv3time(&vap
->va_mtime
, tl
);
945 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
946 *tl
= txdr_unsigned(NFSV3SATTRTIME_TOSERVER
);
949 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
950 *tl
= txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE
);
952 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
955 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
956 if (vap
->va_mode
== (u_short
)VNOVAL
)
957 sp
->sa_mode
= VNOVAL
;
959 sp
->sa_mode
= vtonfsv2_mode(vp
->v_type
, vap
->va_mode
);
960 if (vap
->va_uid
== (uid_t
)VNOVAL
)
963 sp
->sa_uid
= txdr_unsigned(vap
->va_uid
);
964 if (vap
->va_gid
== (gid_t
)VNOVAL
)
967 sp
->sa_gid
= txdr_unsigned(vap
->va_gid
);
968 sp
->sa_size
= txdr_unsigned(vap
->va_size
);
969 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
970 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
972 nfsm_request(vp
, NFSPROC_SETATTR
, procp
, cred
);
974 nfsm_wcc_data(vp
, wccflag
);
975 if ((!wccflag
) && (vp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
976 VTONFS(vp
)->n_attrstamp
= 0;
978 nfsm_loadattr(vp
, (struct vattr
*)0);
984 * nfs lookup call, one step at a time...
985 * First look in cache
986 * If not found, unlock the directory nfsnode and do the rpc
990 struct vop_lookup_args
/* {
991 struct vnodeop_desc *a_desc;
993 struct vnode **a_vpp;
994 struct componentname *a_cnp;
997 register struct componentname
*cnp
= ap
->a_cnp
;
998 register struct vnode
*dvp
= ap
->a_dvp
;
999 register struct vnode
**vpp
= ap
->a_vpp
;
1000 register int flags
= cnp
->cn_flags
;
1001 register struct vnode
*newvp
;
1002 register u_long
*tl
;
1003 register caddr_t cp
;
1004 register long t1
, t2
;
1005 struct nfsmount
*nmp
;
1006 caddr_t bpos
, dpos
, cp2
;
1007 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1011 int lockparent
, wantparent
, error
= 0, attrflag
, fhsize
;
1012 int v3
= NFS_ISV3(dvp
);
1013 struct proc
*p
= cnp
->cn_proc
;
1014 int worldbuildworkaround
= 1;
1016 if ((flags
& ISLASTCN
) && (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
) &&
1017 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
))
1020 if (dvp
->v_type
!= VDIR
)
1022 lockparent
= flags
& LOCKPARENT
;
1023 wantparent
= flags
& (LOCKPARENT
|WANTPARENT
);
1024 nmp
= VFSTONFS(dvp
->v_mount
);
1027 if (worldbuildworkaround
) {
1028 /* temporary workaround for world builds to not have dvp go
1029 VBAD on during server calls in this routine. When
1030 the real ref counting problem is found take this out.
1031 Note if this was later and before the nfsm_request
1032 set up, the workaround did not work (NOTE other difference
1033 was I only put one VREF in that time. Thus it needs
1034 to be above the cache_lookup branch or with 2 VREFS. Not
1035 sure which. Can't play with world builds right now to see
1036 which. VOP_ACCESS could also make it go to server. - EKN */
1037 VREF(dvp
); /* hang on to this dvp - EKN */
1038 VREF(dvp
); /* hang on tight - EKN */
1041 if ((error
= cache_lookup(dvp
, vpp
, cnp
)) && error
!= ENOENT
) {
1045 if ((error
= VOP_ACCESS(dvp
, VEXEC
, cnp
->cn_cred
, p
))) {
1047 if (worldbuildworkaround
) {
1048 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1049 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1054 /* got to check to make sure the vnode didn't go away if access went to server */
1055 if ((*vpp
)->v_type
== VBAD
) {
1056 if (worldbuildworkaround
) {
1057 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1058 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1066 * See the comment starting `Step through' in ufs/ufs_lookup.c
1067 * for an explanation of the locking protocol
1072 } else if (flags
& ISDOTDOT
) {
1073 VOP_UNLOCK(dvp
, 0, p
);
1074 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1075 if (!error
&& lockparent
&& (flags
& ISLASTCN
))
1076 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1078 error
= vget(newvp
, LK_EXCLUSIVE
, p
);
1079 if (!lockparent
|| error
|| !(flags
& ISLASTCN
))
1080 VOP_UNLOCK(dvp
, 0, p
);
1083 if (vpid
== newvp
->v_id
) {
1084 if (!VOP_GETATTR(newvp
, &vattr
, cnp
->cn_cred
, p
)
1085 && vattr
.va_ctime
.tv_sec
== VTONFS(newvp
)->n_ctime
) {
1086 nfsstats
.lookupcache_hits
++;
1087 if (cnp
->cn_nameiop
!= LOOKUP
&&
1089 cnp
->cn_flags
|= SAVENAME
;
1091 if (worldbuildworkaround
) {
1092 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1093 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1101 if (lockparent
&& dvp
!= newvp
&& (flags
& ISLASTCN
))
1102 VOP_UNLOCK(dvp
, 0, p
);
1104 error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
);
1107 if (worldbuildworkaround
) {
1108 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1109 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1116 * Got to check to make sure the vnode didn't go away if VOP_GETATTR went to server
1117 * or callers prior to this blocked and had it go VBAD.
1119 if (dvp
->v_type
== VBAD
) {
1120 if (worldbuildworkaround
) {
1121 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1122 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1129 nfsstats
.lookupcache_misses
++;
1130 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
1131 len
= cnp
->cn_namelen
;
1132 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
1133 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
1134 nfsm_fhtom(dvp
, v3
);
1135 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
1136 nfsm_request(dvp
, NFSPROC_LOOKUP
, cnp
->cn_proc
, cnp
->cn_cred
);
1138 /* this two lines set dvp refcounts back to where they were
1139 * before we took extra 2 VREFS to avoid VBAD vnode on dvp
1140 * during server calls for world builds. Remove when real
1141 * fix is found. - EKN */
1142 if (worldbuildworkaround
) {
1143 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1144 vrele(dvp
); /* end of hanging on tight to dvp - EKN */
1148 nfsm_postop_attr(dvp
, attrflag
);
1152 nfsm_getfh(fhp
, fhsize
, v3
);
1155 * Handle RENAME case...
1157 if (cnp
->cn_nameiop
== RENAME
&& wantparent
&& (flags
& ISLASTCN
)) {
1158 if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1162 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1168 nfsm_postop_attr(newvp
, attrflag
);
1169 nfsm_postop_attr(dvp
, attrflag
);
1171 nfsm_loadattr(newvp
, (struct vattr
*)0);
1174 cnp
->cn_flags
|= SAVENAME
;
1176 VOP_UNLOCK(dvp
, 0, p
);
1180 if (flags
& ISDOTDOT
) {
1181 VOP_UNLOCK(dvp
, 0, p
);
1182 error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
);
1184 vn_lock(dvp
, LK_EXCLUSIVE
+ LK_RETRY
, p
);
1188 if (lockparent
&& (flags
& ISLASTCN
) &&
1189 (error
= vn_lock(dvp
, LK_EXCLUSIVE
, p
))) {
1193 } else if (NFS_CMPFH(np
, fhp
, fhsize
)) {
1197 if ((error
= nfs_nget(dvp
->v_mount
, fhp
, fhsize
, &np
))) {
1201 if (!lockparent
|| !(flags
& ISLASTCN
))
1202 VOP_UNLOCK(dvp
, 0, p
);
1206 nfsm_postop_attr(newvp
, attrflag
);
1207 nfsm_postop_attr(dvp
, attrflag
);
1209 nfsm_loadattr(newvp
, (struct vattr
*)0);
1210 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1211 cnp
->cn_flags
|= SAVENAME
;
1212 if ((cnp
->cn_flags
& MAKEENTRY
) &&
1213 (cnp
->cn_nameiop
!= DELETE
|| !(flags
& ISLASTCN
))) {
1214 np
->n_ctime
= np
->n_vattr
.va_ctime
.tv_sec
;
1215 cache_enter(dvp
, newvp
, cnp
);
1220 if (newvp
!= NULLVP
) {
1224 if ((cnp
->cn_nameiop
== CREATE
|| cnp
->cn_nameiop
== RENAME
) &&
1225 (flags
& ISLASTCN
) && error
== ENOENT
) {
1227 VOP_UNLOCK(dvp
, 0, p
);
1228 if (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
)
1231 error
= EJUSTRETURN
;
1233 if (cnp
->cn_nameiop
!= LOOKUP
&& (flags
& ISLASTCN
))
1234 cnp
->cn_flags
|= SAVENAME
;
1241 * Just call nfs_bioread() to do the work.
1245 struct vop_read_args
/* {
1249 struct ucred *a_cred;
1252 register struct vnode
*vp
= ap
->a_vp
;
1254 if (vp
->v_type
!= VREG
)
1256 return (nfs_bioread(vp
, ap
->a_uio
, ap
->a_ioflag
, ap
->a_cred
, 0));
1264 struct vop_readlink_args
/* {
1267 struct ucred *a_cred;
1270 register struct vnode
*vp
= ap
->a_vp
;
1272 if (vp
->v_type
!= VLNK
)
1274 return (nfs_bioread(vp
, ap
->a_uio
, 0, ap
->a_cred
, 0));
1278 * Do a readlink rpc.
1279 * Called by nfs_doio() from below the buffer cache.
1282 nfs_readlinkrpc(vp
, uiop
, cred
)
1283 register struct vnode
*vp
;
1287 register u_long
*tl
;
1288 register caddr_t cp
;
1289 register long t1
, t2
;
1290 caddr_t bpos
, dpos
, cp2
;
1291 int error
= 0, len
, attrflag
;
1292 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1293 int v3
= NFS_ISV3(vp
);
1295 nfsstats
.rpccnt
[NFSPROC_READLINK
]++;
1296 nfsm_reqhead(vp
, NFSPROC_READLINK
, NFSX_FH(v3
));
1298 nfsm_request(vp
, NFSPROC_READLINK
, uiop
->uio_procp
, cred
);
1300 nfsm_postop_attr(vp
, attrflag
);
1302 nfsm_strsiz(len
, NFS_MAXPATHLEN
);
1303 if (len
== NFS_MAXPATHLEN
) {
1304 struct nfsnode
*np
= VTONFS(vp
);
1307 panic("nfs_readlinkrpc: null np");
1309 if (np
->n_size
&& np
->n_size
< NFS_MAXPATHLEN
)
1312 nfsm_mtouio(uiop
, len
);
1323 nfs_readrpc(vp
, uiop
, cred
)
1324 register struct vnode
*vp
;
1328 register u_long
*tl
;
1329 register caddr_t cp
;
1330 register long t1
, t2
;
1331 caddr_t bpos
, dpos
, cp2
;
1332 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1333 struct nfsmount
*nmp
;
1334 int error
= 0, len
, retlen
, tsiz
, eof
, attrflag
;
1335 int v3
= NFS_ISV3(vp
);
1340 nmp
= VFSTONFS(vp
->v_mount
);
1341 tsiz
= uiop
->uio_resid
;
1342 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) && !v3
)
1345 nfsstats
.rpccnt
[NFSPROC_READ
]++;
1346 len
= (tsiz
> nmp
->nm_rsize
) ? nmp
->nm_rsize
: tsiz
;
1347 nfsm_reqhead(vp
, NFSPROC_READ
, NFSX_FH(v3
) + NFSX_UNSIGNED
* 3);
1349 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
* 3);
1351 txdr_hyper(&uiop
->uio_offset
, tl
);
1352 *(tl
+ 2) = txdr_unsigned(len
);
1354 *tl
++ = txdr_unsigned(uiop
->uio_offset
);
1355 *tl
++ = txdr_unsigned(len
);
1358 nfsm_request(vp
, NFSPROC_READ
, uiop
->uio_procp
, cred
);
1360 nfsm_postop_attr(vp
, attrflag
);
1365 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1366 eof
= fxdr_unsigned(int, *(tl
+ 1));
1368 nfsm_loadattr(vp
, (struct vattr
*)0);
1369 nfsm_strsiz(retlen
, nmp
->nm_rsize
);
1370 nfsm_mtouio(uiop
, retlen
);
1374 if (eof
|| retlen
== 0)
1376 } else if (retlen
< len
)
1387 nfs_writerpc(vp
, uiop
, cred
, iomode
, must_commit
)
1388 register struct vnode
*vp
;
1389 register struct uio
*uiop
;
1391 int *iomode
, *must_commit
;
1393 register u_long
*tl
;
1394 register caddr_t cp
;
1395 register int t1
, t2
, backup
;
1396 caddr_t bpos
, dpos
, cp2
;
1397 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1398 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
1399 int error
= 0, len
, tsiz
, wccflag
= NFSV3_WCCRATTR
, rlen
, commit
;
1400 int v3
= NFS_ISV3(vp
), committed
= NFSV3WRITE_FILESYNC
;
1403 if (uiop
->uio_iovcnt
!= 1)
1404 panic("nfs_writerpc: iovcnt > 1");
1407 tsiz
= uiop
->uio_resid
;
1408 if (((u_int64_t
)uiop
->uio_offset
+ (unsigned int)tsiz
> 0xffffffff) && !v3
)
1411 nfsstats
.rpccnt
[NFSPROC_WRITE
]++;
1412 len
= (tsiz
> nmp
->nm_wsize
) ? nmp
->nm_wsize
: tsiz
;
1413 nfsm_reqhead(vp
, NFSPROC_WRITE
,
1414 NFSX_FH(v3
) + 5 * NFSX_UNSIGNED
+ nfsm_rndup(len
));
1417 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
1418 txdr_hyper(&uiop
->uio_offset
, tl
);
1420 *tl
++ = txdr_unsigned(len
);
1421 *tl
++ = txdr_unsigned(*iomode
);
1423 nfsm_build(tl
, u_long
*, 4 * NFSX_UNSIGNED
);
1424 *++tl
= txdr_unsigned(uiop
->uio_offset
);
1427 *tl
= txdr_unsigned(len
);
1428 nfsm_uiotom(uiop
, len
);
1429 nfsm_request(vp
, NFSPROC_WRITE
, uiop
->uio_procp
, cred
);
1431 wccflag
= NFSV3_WCCCHK
;
1432 nfsm_wcc_data(vp
, wccflag
);
1434 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
+
1436 rlen
= fxdr_unsigned(int, *tl
++);
1440 } else if (rlen
< len
) {
1441 backup
= len
- rlen
;
1442 uiop
->uio_iov
->iov_base
-= backup
;
1443 uiop
->uio_iov
->iov_len
+= backup
;
1444 uiop
->uio_offset
-= backup
;
1445 uiop
->uio_resid
+= backup
;
1448 commit
= fxdr_unsigned(int, *tl
++);
1451 * Return the lowest committment level
1452 * obtained by any of the RPCs.
1454 if (committed
== NFSV3WRITE_FILESYNC
)
1456 else if (committed
== NFSV3WRITE_DATASYNC
&&
1457 commit
== NFSV3WRITE_UNSTABLE
)
1459 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0) {
1460 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1462 nmp
->nm_flag
|= NFSMNT_HASWRITEVERF
;
1463 } else if (bcmp((caddr_t
)tl
,
1464 (caddr_t
)nmp
->nm_verf
, NFSX_V3WRITEVERF
)) {
1466 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
1471 nfsm_loadattr(vp
, (struct vattr
*)0);
1472 if ((wccflag
) && (vp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
1473 VTONFS(vp
)->n_mtime
= VTONFS(vp
)->n_vattr
.va_mtime
.tv_sec
;
1476 * we seem to have a case where we end up looping on shutdown and taking down nfs servers.
1477 * For V3, error cases, there is no way to terminate loop, if the len was 0, meaning,
1478 * nmp->nm_wsize was trashed. FreeBSD has this fix in it. Let's try it.
1485 /* does it make sense to even say it was committed if we had an error? EKN */
1486 /* okay well just don't on bad vnodes then. EINVAL will be returned on bad vnodes */
1487 if ((vp
->v_type
!= VBAD
) && (vp
->v_mount
->mnt_flag
& MNT_ASYNC
))
1488 committed
= NFSV3WRITE_FILESYNC
;
1489 *iomode
= committed
;
1491 uiop
->uio_resid
= tsiz
;
1497 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1498 * mode set to specify the file type and the size field for rdev.
1501 nfs_mknodrpc(dvp
, vpp
, cnp
, vap
)
1502 register struct vnode
*dvp
;
1503 register struct vnode
**vpp
;
1504 register struct componentname
*cnp
;
1505 register struct vattr
*vap
;
1507 register struct nfsv2_sattr
*sp
;
1508 register struct nfsv3_sattr
*sp3
;
1509 register u_long
*tl
;
1510 register caddr_t cp
;
1511 register long t1
, t2
;
1512 struct vnode
*newvp
= (struct vnode
*)0;
1513 struct nfsnode
*np
= (struct nfsnode
*)0;
1517 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0;
1518 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1520 int v3
= NFS_ISV3(dvp
);
1522 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
)
1523 rdev
= txdr_unsigned(vap
->va_rdev
);
1524 else if (vap
->va_type
== VFIFO
|| vap
->va_type
== VSOCK
)
1527 VOP_ABORTOP(dvp
, cnp
);
1529 return (EOPNOTSUPP
);
1531 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1532 VOP_ABORTOP(dvp
, cnp
);
1536 nfsstats
.rpccnt
[NFSPROC_MKNOD
]++;
1537 nfsm_reqhead(dvp
, NFSPROC_MKNOD
, NFSX_FH(v3
) + 4 * NFSX_UNSIGNED
+
1538 + nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1539 nfsm_fhtom(dvp
, v3
);
1540 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1542 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
+ NFSX_V3SRVSATTR
);
1543 *tl
++ = vtonfsv3_type(vap
->va_type
);
1544 sp3
= (struct nfsv3_sattr
*)tl
;
1545 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1546 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
) {
1547 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
1548 *tl
++ = txdr_unsigned(major(vap
->va_rdev
));
1549 *tl
= txdr_unsigned(minor(vap
->va_rdev
));
1552 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1553 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1554 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1555 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1557 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1558 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1560 nfsm_request(dvp
, NFSPROC_MKNOD
, cnp
->cn_proc
, cnp
->cn_cred
);
1562 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
1566 newvp
= (struct vnode
*)0;
1568 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1569 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1575 nfsm_wcc_data(dvp
, wccflag
);
1581 if (cnp
->cn_flags
& MAKEENTRY
)
1582 cache_enter(dvp
, newvp
, cnp
);
1585 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1586 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1587 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1589 VTONFS(dvp
)->n_attrstamp
= 0;
1597 * just call nfs_mknodrpc() to do the work.
1602 struct vop_mknod_args
/* {
1603 struct vnode *a_dvp;
1604 struct vnode **a_vpp;
1605 struct componentname *a_cnp;
1606 struct vattr *a_vap;
1609 struct vnode
*newvp
;
1612 error
= nfs_mknodrpc(ap
->a_dvp
, &newvp
, ap
->a_cnp
, ap
->a_vap
);
1618 static u_long create_verf
;
1620 * nfs file create call
1624 struct vop_create_args
/* {
1625 struct vnode *a_dvp;
1626 struct vnode **a_vpp;
1627 struct componentname *a_cnp;
1628 struct vattr *a_vap;
1631 register struct vnode
*dvp
= ap
->a_dvp
;
1632 register struct vattr
*vap
= ap
->a_vap
;
1633 register struct componentname
*cnp
= ap
->a_cnp
;
1634 register struct nfsv2_sattr
*sp
;
1635 register struct nfsv3_sattr
*sp3
;
1636 register u_long
*tl
;
1637 register caddr_t cp
;
1638 register long t1
, t2
;
1639 struct nfsnode
*np
= (struct nfsnode
*)0;
1640 struct vnode
*newvp
= (struct vnode
*)0;
1641 caddr_t bpos
, dpos
, cp2
;
1642 int error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
= 0, fmode
= 0;
1643 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1645 int v3
= NFS_ISV3(dvp
);
1648 * Oops, not for me..
1650 if (vap
->va_type
== VSOCK
)
1651 return (nfs_mknodrpc(dvp
, ap
->a_vpp
, cnp
, vap
));
1653 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
1654 VOP_ABORTOP(dvp
, cnp
);
1658 if (vap
->va_vaflags
& VA_EXCLUSIVE
)
1661 nfsstats
.rpccnt
[NFSPROC_CREATE
]++;
1662 nfsm_reqhead(dvp
, NFSPROC_CREATE
, NFSX_FH(v3
) + 2 * NFSX_UNSIGNED
+
1663 nfsm_rndup(cnp
->cn_namelen
) + NFSX_SATTR(v3
));
1664 nfsm_fhtom(dvp
, v3
);
1665 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
1667 nfsm_build(tl
, u_long
*, NFSX_UNSIGNED
);
1668 if (fmode
& O_EXCL
) {
1669 *tl
= txdr_unsigned(NFSV3CREATE_EXCLUSIVE
);
1670 nfsm_build(tl
, u_long
*, NFSX_V3CREATEVERF
);
1671 if (!TAILQ_EMPTY(&in_ifaddrhead
))
1672 *tl
++ = IA_SIN(in_ifaddrhead
.tqh_first
)->sin_addr
.s_addr
;
1674 *tl
++ = create_verf
;
1675 *tl
= ++create_verf
;
1677 *tl
= txdr_unsigned(NFSV3CREATE_UNCHECKED
);
1678 nfsm_build(tl
, u_long
*, NFSX_V3SRVSATTR
);
1679 sp3
= (struct nfsv3_sattr
*)tl
;
1680 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
1683 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1684 sp
->sa_mode
= vtonfsv2_mode(vap
->va_type
, vap
->va_mode
);
1685 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
1686 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
1688 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
1689 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
1691 nfsm_request(dvp
, NFSPROC_CREATE
, cnp
->cn_proc
, cnp
->cn_cred
);
1693 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
1697 newvp
= (struct vnode
*)0;
1699 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
,
1700 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
, &np
);
1706 nfsm_wcc_data(dvp
, wccflag
);
1709 if (v3
&& (fmode
& O_EXCL
) && error
== NFSERR_NOTSUPP
) {
1715 } else if (v3
&& (fmode
& O_EXCL
))
1716 error
= nfs_setattrrpc(newvp
, vap
, cnp
->cn_cred
, cnp
->cn_proc
);
1718 if (cnp
->cn_flags
& MAKEENTRY
)
1719 cache_enter(dvp
, newvp
, cnp
);
1722 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1723 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1724 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1726 VTONFS(dvp
)->n_attrstamp
= 0;
1733 * nfs file remove call
1734 * To try and make nfs semantics closer to ufs semantics, a file that has
1735 * other processes using the vnode is renamed instead of removed and then
1736 * removed later on the last close.
1737 * - If v_usecount > 1
1738 * If a rename is not already in the works
1739 * call nfs_sillyrename() to set it up
1745 struct vop_remove_args
/* {
1746 struct vnodeop_desc *a_desc;
1747 struct vnode * a_dvp;
1748 struct vnode * a_vp;
1749 struct componentname * a_cnp;
1752 register struct vnode
*vp
= ap
->a_vp
;
1753 register struct vnode
*dvp
= ap
->a_dvp
;
1754 register struct componentname
*cnp
= ap
->a_cnp
;
1755 register struct nfsnode
*np
= VTONFS(vp
);
1758 int file_deleted
= 0;
1761 if ((cnp
->cn_flags
& HASBUF
) == 0)
1762 panic("nfs_remove: no name");
1763 if (vp
->v_usecount
< 1)
1764 panic("nfs_remove: bad v_usecount");
1766 if (vp
->v_usecount
== 1 ||
1767 (UBCISVALID(vp
)&&(vp
->v_usecount
==2)) ||
1768 (np
->n_sillyrename
&&
1769 VOP_GETATTR(vp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
) == 0 &&
1770 vattr
.va_nlink
> 1)) {
1772 * Purge the name cache so that the chance of a lookup for
1773 * the name succeeding while the remove is in progress is
1774 * minimized. Without node locking it can still happen, such
1775 * that an I/O op returns ESTALE, but since you get this if
1776 * another host removes the file..
1780 * throw away biocache buffers, mainly to avoid
1781 * unnecessary delayed writes later.
1783 error
= nfs_vinvalbuf(vp
, 0, cnp
->cn_cred
, cnp
->cn_proc
, 1);
1784 ubc_setsize(vp
, (off_t
)0);
1787 error
= nfs_removerpc(dvp
, cnp
->cn_nameptr
,
1788 cnp
->cn_namelen
, cnp
->cn_cred
, cnp
->cn_proc
);
1790 * Kludge City: If the first reply to the remove rpc is lost..
1791 * the reply to the retransmitted request will be ENOENT
1792 * since the file was in fact removed
1793 * Therefore, we cheat and return success.
1795 if (error
== ENOENT
)
1798 } else if (!np
->n_sillyrename
) {
1799 error
= nfs_sillyrename(dvp
, vp
, cnp
);
1802 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
1803 np
->n_attrstamp
= 0;
1812 if (file_deleted
&& UBCINFOEXISTS(vp
)) {
1813 (void) ubc_uncache(vp
);
1815 /* WARNING vp may not be valid after this */
1822 * nfs file remove rpc called from nfs_inactive
1826 register struct sillyrename
*sp
;
1829 return (nfs_removerpc(sp
->s_dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
1834 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1837 nfs_removerpc(dvp
, name
, namelen
, cred
, proc
)
1838 register struct vnode
*dvp
;
1844 register u_long
*tl
;
1845 register caddr_t cp
;
1846 register long t1
, t2
;
1847 caddr_t bpos
, dpos
, cp2
;
1848 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
1849 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1850 int v3
= NFS_ISV3(dvp
);
1852 nfsstats
.rpccnt
[NFSPROC_REMOVE
]++;
1853 nfsm_reqhead(dvp
, NFSPROC_REMOVE
,
1854 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(namelen
));
1855 nfsm_fhtom(dvp
, v3
);
1856 nfsm_strtom(name
, namelen
, NFS_MAXNAMLEN
);
1857 nfsm_request(dvp
, NFSPROC_REMOVE
, proc
, cred
);
1859 nfsm_wcc_data(dvp
, wccflag
);
1861 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1862 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
1864 VTONFS(dvp
)->n_attrstamp
= 0;
1870 * nfs file rename call
1874 struct vop_rename_args
/* {
1875 struct vnode *a_fdvp;
1876 struct vnode *a_fvp;
1877 struct componentname *a_fcnp;
1878 struct vnode *a_tdvp;
1879 struct vnode *a_tvp;
1880 struct componentname *a_tcnp;
1883 register struct vnode
*fvp
= ap
->a_fvp
;
1884 register struct vnode
*tvp
= ap
->a_tvp
;
1885 register struct vnode
*fdvp
= ap
->a_fdvp
;
1886 register struct vnode
*tdvp
= ap
->a_tdvp
;
1887 register struct componentname
*tcnp
= ap
->a_tcnp
;
1888 register struct componentname
*fcnp
= ap
->a_fcnp
;
1892 if ((tcnp
->cn_flags
& HASBUF
) == 0 ||
1893 (fcnp
->cn_flags
& HASBUF
) == 0)
1894 panic("nfs_rename: no name");
1896 /* Check for cross-device rename */
1897 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
1898 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
1904 * If the tvp exists and is in use, sillyrename it before doing the
1905 * rename of the new file over it.
1906 * XXX Can't sillyrename a directory.
1908 if (tvp
&& (tvp
->v_usecount
>(UBCISVALID(tvp
) ? 2 : 1)) &&
1909 !VTONFS(tvp
)->n_sillyrename
&&
1910 tvp
->v_type
!= VDIR
&& !nfs_sillyrename(tdvp
, tvp
, tcnp
)) {
1915 error
= nfs_renamerpc(fdvp
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
,
1916 tdvp
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
, tcnp
->cn_cred
,
1919 if (fvp
->v_type
== VDIR
) {
1920 if (tvp
!= NULL
&& tvp
->v_type
== VDIR
)
1934 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1936 if (error
== ENOENT
)
1942 * nfs file rename rpc called from nfs_remove() above
1945 nfs_renameit(sdvp
, scnp
, sp
)
1947 struct componentname
*scnp
;
1948 register struct sillyrename
*sp
;
1950 return (nfs_renamerpc(sdvp
, scnp
->cn_nameptr
, scnp
->cn_namelen
,
1951 sdvp
, sp
->s_name
, sp
->s_namlen
, scnp
->cn_cred
, scnp
->cn_proc
));
1955 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
1958 nfs_renamerpc(fdvp
, fnameptr
, fnamelen
, tdvp
, tnameptr
, tnamelen
, cred
, proc
)
1959 register struct vnode
*fdvp
;
1962 register struct vnode
*tdvp
;
1968 register u_long
*tl
;
1969 register caddr_t cp
;
1970 register long t1
, t2
;
1971 caddr_t bpos
, dpos
, cp2
;
1972 int error
= 0, fwccflag
= NFSV3_WCCRATTR
, twccflag
= NFSV3_WCCRATTR
;
1973 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
1974 int v3
= NFS_ISV3(fdvp
);
1976 nfsstats
.rpccnt
[NFSPROC_RENAME
]++;
1977 nfsm_reqhead(fdvp
, NFSPROC_RENAME
,
1978 (NFSX_FH(v3
) + NFSX_UNSIGNED
)*2 + nfsm_rndup(fnamelen
) +
1979 nfsm_rndup(tnamelen
));
1980 nfsm_fhtom(fdvp
, v3
);
1981 nfsm_strtom(fnameptr
, fnamelen
, NFS_MAXNAMLEN
);
1982 nfsm_fhtom(tdvp
, v3
);
1983 nfsm_strtom(tnameptr
, tnamelen
, NFS_MAXNAMLEN
);
1984 nfsm_request(fdvp
, NFSPROC_RENAME
, proc
, cred
);
1986 nfsm_wcc_data(fdvp
, fwccflag
);
1987 nfsm_wcc_data(tdvp
, twccflag
);
1990 if (fdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1991 VTONFS(fdvp
)->n_flag
|= NMODIFIED
;
1993 VTONFS(fdvp
)->n_attrstamp
= 0;
1995 if (tdvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
1996 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
1998 VTONFS(tdvp
)->n_attrstamp
= 0;
2004 * nfs hard link create call
2008 struct vop_link_args
/* {
2010 struct vnode *a_tdvp;
2011 struct componentname *a_cnp;
2014 register struct vnode
*vp
= ap
->a_vp
;
2015 register struct vnode
*tdvp
= ap
->a_tdvp
;
2016 register struct componentname
*cnp
= ap
->a_cnp
;
2017 register u_long
*tl
;
2018 register caddr_t cp
;
2019 register long t1
, t2
;
2020 caddr_t bpos
, dpos
, cp2
;
2021 int error
= 0, wccflag
= NFSV3_WCCRATTR
, attrflag
= 0;
2022 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2023 int v3
= NFS_ISV3(vp
);
2025 if (vp
->v_mount
!= tdvp
->v_mount
) {
2026 VOP_ABORTOP(vp
, cnp
);
2035 * Push all writes to the server, so that the attribute cache
2036 * doesn't get "out of sync" with the server.
2037 * XXX There should be a better way!
2039 VOP_FSYNC(vp
, cnp
->cn_cred
, MNT_WAIT
, cnp
->cn_proc
);
2041 nfsstats
.rpccnt
[NFSPROC_LINK
]++;
2042 nfsm_reqhead(vp
, NFSPROC_LINK
,
2043 NFSX_FH(v3
)*2 + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2045 nfsm_fhtom(tdvp
, v3
);
2046 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2047 nfsm_request(vp
, NFSPROC_LINK
, cnp
->cn_proc
, cnp
->cn_cred
);
2049 nfsm_postop_attr(vp
, attrflag
);
2050 nfsm_wcc_data(tdvp
, wccflag
);
2053 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2055 VTONFS(tdvp
)->n_flag
|= NMODIFIED
;
2056 if ((!attrflag
) && (vp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
2057 VTONFS(vp
)->n_attrstamp
= 0;
2058 if ((!wccflag
) && (tdvp
->v_type
!= VBAD
)) /* EINVAL set on VBAD vnode */
2059 VTONFS(tdvp
)->n_attrstamp
= 0;
2062 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2064 if (error
== EEXIST
)
2070 * nfs symbolic link create call
2074 struct vop_symlink_args
/* {
2075 struct vnode *a_dvp;
2076 struct vnode **a_vpp;
2077 struct componentname *a_cnp;
2078 struct vattr *a_vap;
2082 register struct vnode
*dvp
= ap
->a_dvp
;
2083 register struct vattr
*vap
= ap
->a_vap
;
2084 register struct componentname
*cnp
= ap
->a_cnp
;
2085 register struct nfsv2_sattr
*sp
;
2086 register struct nfsv3_sattr
*sp3
;
2087 register u_long
*tl
;
2088 register caddr_t cp
;
2089 register long t1
, t2
;
2090 caddr_t bpos
, dpos
, cp2
;
2091 int slen
, error
= 0, wccflag
= NFSV3_WCCRATTR
, gotvp
;
2092 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2093 struct vnode
*newvp
= (struct vnode
*)0;
2094 int v3
= NFS_ISV3(dvp
);
2096 nfsstats
.rpccnt
[NFSPROC_SYMLINK
]++;
2097 slen
= strlen(ap
->a_target
);
2098 nfsm_reqhead(dvp
, NFSPROC_SYMLINK
, NFSX_FH(v3
) + 2*NFSX_UNSIGNED
+
2099 nfsm_rndup(cnp
->cn_namelen
) + nfsm_rndup(slen
) + NFSX_SATTR(v3
));
2100 nfsm_fhtom(dvp
, v3
);
2101 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2103 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2104 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
,
2105 cnp
->cn_cred
->cr_gid
);
2107 nfsm_strtom(ap
->a_target
, slen
, NFS_MAXPATHLEN
);
2109 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2110 sp
->sa_mode
= vtonfsv2_mode(VLNK
, vap
->va_mode
);
2111 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2112 sp
->sa_gid
= txdr_unsigned(cnp
->cn_cred
->cr_gid
);
2114 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2115 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2117 nfsm_request(dvp
, NFSPROC_SYMLINK
, cnp
->cn_proc
, cnp
->cn_cred
);
2120 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
2121 nfsm_wcc_data(dvp
, wccflag
);
2126 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2127 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on VBAD vnode */
2128 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2130 VTONFS(dvp
)->n_attrstamp
= 0;
2134 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
2136 if (error
== EEXIST
)
2146 struct vop_mkdir_args
/* {
2147 struct vnode *a_dvp;
2148 struct vnode **a_vpp;
2149 struct componentname *a_cnp;
2150 struct vattr *a_vap;
2153 register struct vnode
*dvp
= ap
->a_dvp
;
2154 register struct vattr
*vap
= ap
->a_vap
;
2155 register struct componentname
*cnp
= ap
->a_cnp
;
2156 register struct nfsv2_sattr
*sp
;
2157 register struct nfsv3_sattr
*sp3
;
2158 register u_long
*tl
;
2159 register caddr_t cp
;
2160 register long t1
, t2
;
2162 struct nfsnode
*np
= (struct nfsnode
*)0;
2163 struct vnode
*newvp
= (struct vnode
*)0;
2164 caddr_t bpos
, dpos
, cp2
;
2165 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2167 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2169 int v3
= NFS_ISV3(dvp
);
2171 if ((error
= VOP_GETATTR(dvp
, &vattr
, cnp
->cn_cred
, cnp
->cn_proc
))) {
2172 VOP_ABORTOP(dvp
, cnp
);
2176 len
= cnp
->cn_namelen
;
2177 nfsstats
.rpccnt
[NFSPROC_MKDIR
]++;
2178 nfsm_reqhead(dvp
, NFSPROC_MKDIR
,
2179 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
) + NFSX_SATTR(v3
));
2180 nfsm_fhtom(dvp
, v3
);
2181 nfsm_strtom(cnp
->cn_nameptr
, len
, NFS_MAXNAMLEN
);
2183 nfsm_build(sp3
, struct nfsv3_sattr
*, NFSX_V3SRVSATTR
);
2184 nfsm_v3sattr(sp3
, vap
, cnp
->cn_cred
->cr_uid
, vattr
.va_gid
);
2186 nfsm_build(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2187 sp
->sa_mode
= vtonfsv2_mode(VDIR
, vap
->va_mode
);
2188 sp
->sa_uid
= txdr_unsigned(cnp
->cn_cred
->cr_uid
);
2189 sp
->sa_gid
= txdr_unsigned(vattr
.va_gid
);
2191 txdr_nfsv2time(&vap
->va_atime
, &sp
->sa_atime
);
2192 txdr_nfsv2time(&vap
->va_mtime
, &sp
->sa_mtime
);
2194 nfsm_request(dvp
, NFSPROC_MKDIR
, cnp
->cn_proc
, cnp
->cn_cred
);
2196 nfsm_mtofh(dvp
, newvp
, v3
, gotvp
);
2198 nfsm_wcc_data(dvp
, wccflag
);
2200 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2201 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2203 VTONFS(dvp
)->n_attrstamp
= 0;
2206 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
2207 * if we can succeed in looking up the directory.
2209 if (error
== EEXIST
|| (!error
&& !gotvp
)) {
2212 newvp
= (struct vnode
*)0;
2214 error
= nfs_lookitup(dvp
, cnp
->cn_nameptr
, len
, cnp
->cn_cred
,
2218 if (newvp
->v_type
!= VDIR
)
2227 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2233 * nfs remove directory call
2237 struct vop_rmdir_args
/* {
2238 struct vnode *a_dvp;
2240 struct componentname *a_cnp;
2243 register struct vnode
*vp
= ap
->a_vp
;
2244 register struct vnode
*dvp
= ap
->a_dvp
;
2245 register struct componentname
*cnp
= ap
->a_cnp
;
2246 register u_long
*tl
;
2247 register caddr_t cp
;
2248 register long t1
, t2
;
2249 caddr_t bpos
, dpos
, cp2
;
2250 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2251 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2252 int v3
= NFS_ISV3(dvp
);
2254 nfsstats
.rpccnt
[NFSPROC_RMDIR
]++;
2255 nfsm_reqhead(dvp
, NFSPROC_RMDIR
,
2256 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(cnp
->cn_namelen
));
2257 nfsm_fhtom(dvp
, v3
);
2258 nfsm_strtom(cnp
->cn_nameptr
, cnp
->cn_namelen
, NFS_MAXNAMLEN
);
2259 nfsm_request(dvp
, NFSPROC_RMDIR
, cnp
->cn_proc
, cnp
->cn_cred
);
2261 nfsm_wcc_data(dvp
, wccflag
);
2263 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
2264 if (dvp
->v_type
!= VBAD
) { /* EINVAL set on this case */
2265 VTONFS(dvp
)->n_flag
|= NMODIFIED
;
2267 VTONFS(dvp
)->n_attrstamp
= 0;
2274 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2276 if (error
== ENOENT
)
2286 struct vop_readdir_args
/* {
2289 struct ucred *a_cred;
2292 register struct vnode
*vp
= ap
->a_vp
;
2293 register struct nfsnode
*np
= VTONFS(vp
);
2294 register struct uio
*uio
= ap
->a_uio
;
2298 if (vp
->v_type
!= VDIR
)
2301 * First, check for hit on the EOF offset cache
2303 if (np
->n_direofoffset
> 0 && uio
->uio_offset
>= np
->n_direofoffset
&&
2304 (np
->n_flag
& NMODIFIED
) == 0) {
2305 if (VFSTONFS(vp
->v_mount
)->nm_flag
& NFSMNT_NQNFS
) {
2306 if (NQNFS_CKCACHABLE(vp
, ND_READ
)) {
2307 nfsstats
.direofcache_hits
++;
2310 } else if (VOP_GETATTR(vp
, &vattr
, ap
->a_cred
, uio
->uio_procp
) == 0 &&
2311 np
->n_mtime
== vattr
.va_mtime
.tv_sec
) {
2312 nfsstats
.direofcache_hits
++;
2318 * Call nfs_bioread() to do the real work.
2320 tresid
= uio
->uio_resid
;
2321 error
= nfs_bioread(vp
, uio
, 0, ap
->a_cred
, 0);
2323 if (!error
&& uio
->uio_resid
== tresid
)
2324 nfsstats
.direofcache_misses
++;
2330 * Called from below the buffer cache by nfs_doio().
2333 nfs_readdirrpc(vp
, uiop
, cred
)
2335 register struct uio
*uiop
;
2339 register int len
, left
;
2340 register struct dirent
*dp
;
2341 register u_long
*tl
;
2342 register caddr_t cp
;
2343 register long t1
, t2
;
2344 register nfsuint64
*cookiep
;
2345 caddr_t bpos
, dpos
, cp2
;
2346 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2348 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2349 struct nfsnode
*dnp
= VTONFS(vp
);
2351 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, bigenough
= 1;
2353 int v3
= NFS_ISV3(vp
);
2356 dp
= (struct dirent
*)0;
2359 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (NFS_DIRBLKSIZ
- 1)) ||
2360 (uiop
->uio_resid
& (NFS_DIRBLKSIZ
- 1)))
2361 panic("nfs_readdirrpc: bad uio");
2365 * If there is no cookie, assume directory was stale.
2367 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2371 return (NFSERR_BAD_COOKIE
);
2373 * Loop around doing readdir rpc's of size nm_readdirsize
2374 * truncated to a multiple of DIRBLKSIZ.
2375 * The stopping criteria is EOF or buffer full.
2377 while (more_dirs
&& bigenough
) {
2378 nfsstats
.rpccnt
[NFSPROC_READDIR
]++;
2379 nfsm_reqhead(vp
, NFSPROC_READDIR
, NFSX_FH(v3
) +
2383 nfsm_build(tl
, u_long
*, 5 * NFSX_UNSIGNED
);
2384 *tl
++ = cookie
.nfsuquad
[0];
2385 *tl
++ = cookie
.nfsuquad
[1];
2386 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2387 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2389 nfsm_build(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2390 *tl
++ = cookie
.nfsuquad
[0];
2392 *tl
= txdr_unsigned(nmp
->nm_readdirsize
);
2393 nfsm_request(vp
, NFSPROC_READDIR
, uiop
->uio_procp
, cred
);
2395 nfsm_postop_attr(vp
, attrflag
);
2397 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2398 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2399 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
;
2405 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2406 more_dirs
= fxdr_unsigned(int, *tl
);
2408 /* loop thru the dir entries, doctoring them to 4bsd form */
2409 while (more_dirs
&& bigenough
) {
2411 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2412 fxdr_hyper(tl
, &fileno
);
2413 len
= fxdr_unsigned(int, *(tl
+ 2));
2415 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2416 fileno
= fxdr_unsigned(u_quad_t
, *tl
++);
2417 len
= fxdr_unsigned(int, *tl
);
2419 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2424 tlen
= nfsm_rndup(len
);
2426 tlen
+= 4; /* To ensure null termination */
2427 left
= DIRBLKSIZ
- blksiz
;
2428 if ((tlen
+ DIRHDSIZ
) > left
) {
2429 dp
->d_reclen
+= left
;
2430 uiop
->uio_iov
->iov_base
+= left
;
2431 uiop
->uio_iov
->iov_len
-= left
;
2432 uiop
->uio_offset
+= left
;
2433 uiop
->uio_resid
-= left
;
2436 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2439 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2440 dp
->d_fileno
= (int)fileno
;
2442 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2443 dp
->d_type
= DT_UNKNOWN
;
2444 blksiz
+= dp
->d_reclen
;
2445 if (blksiz
== DIRBLKSIZ
)
2447 uiop
->uio_offset
+= DIRHDSIZ
;
2448 uiop
->uio_resid
-= DIRHDSIZ
;
2449 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2450 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2451 nfsm_mtouio(uiop
, len
);
2452 cp
= uiop
->uio_iov
->iov_base
;
2454 *cp
= '\0'; /* null terminate */
2455 uiop
->uio_iov
->iov_base
+= tlen
;
2456 uiop
->uio_iov
->iov_len
-= tlen
;
2457 uiop
->uio_offset
+= tlen
;
2458 uiop
->uio_resid
-= tlen
;
2460 nfsm_adv(nfsm_rndup(len
));
2462 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2464 nfsm_dissect(tl
, u_long
*, 2 * NFSX_UNSIGNED
);
2467 cookie
.nfsuquad
[0] = *tl
++;
2469 cookie
.nfsuquad
[1] = *tl
++;
2474 more_dirs
= fxdr_unsigned(int, *tl
);
2477 * If at end of rpc data, get the eof boolean
2480 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2481 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2486 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2487 * by increasing d_reclen for the last record.
2490 left
= DIRBLKSIZ
- blksiz
;
2491 dp
->d_reclen
+= left
;
2492 uiop
->uio_iov
->iov_base
+= left
;
2493 uiop
->uio_iov
->iov_len
-= left
;
2494 uiop
->uio_offset
+= left
;
2495 uiop
->uio_resid
-= left
;
2499 * We are now either at the end of the directory or have filled the
2503 dnp
->n_direofoffset
= uiop
->uio_offset
;
2505 if (uiop
->uio_resid
> 0)
2506 printf("EEK! readdirrpc resid > 0\n");
2507 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2515 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2518 nfs_readdirplusrpc(vp
, uiop
, cred
)
2520 register struct uio
*uiop
;
2523 register int len
, left
;
2524 register struct dirent
*dp
;
2525 register u_long
*tl
;
2526 register caddr_t cp
;
2527 register long t1
, t2
;
2528 register struct vnode
*newvp
;
2529 register nfsuint64
*cookiep
;
2530 caddr_t bpos
, dpos
, cp2
, dpossav1
, dpossav2
;
2531 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
, *mdsav1
, *mdsav2
;
2532 struct nameidata nami
, *ndp
= &nami
;
2533 struct componentname
*cnp
= &ndp
->ni_cnd
;
2535 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2536 struct nfsnode
*dnp
= VTONFS(vp
), *np
;
2539 int error
= 0, tlen
, more_dirs
= 1, blksiz
= 0, doit
, bigenough
= 1, i
;
2540 int attrflag
, fhsize
;
2543 dp
= (struct dirent
*)0;
2546 if (uiop
->uio_iovcnt
!= 1 || (uiop
->uio_offset
& (DIRBLKSIZ
- 1)) ||
2547 (uiop
->uio_resid
& (DIRBLKSIZ
- 1)))
2548 panic("nfs_readdirplusrpc: bad uio");
2554 * If there is no cookie, assume directory was stale.
2556 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 0);
2560 return (NFSERR_BAD_COOKIE
);
2562 * Loop around doing readdir rpc's of size nm_readdirsize
2563 * truncated to a multiple of DIRBLKSIZ.
2564 * The stopping criteria is EOF or buffer full.
2566 while (more_dirs
&& bigenough
) {
2567 nfsstats
.rpccnt
[NFSPROC_READDIRPLUS
]++;
2568 nfsm_reqhead(vp
, NFSPROC_READDIRPLUS
,
2569 NFSX_FH(1) + 6 * NFSX_UNSIGNED
);
2571 nfsm_build(tl
, u_long
*, 6 * NFSX_UNSIGNED
);
2572 *tl
++ = cookie
.nfsuquad
[0];
2573 *tl
++ = cookie
.nfsuquad
[1];
2574 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[0];
2575 *tl
++ = dnp
->n_cookieverf
.nfsuquad
[1];
2576 *tl
++ = txdr_unsigned(nmp
->nm_readdirsize
);
2577 *tl
= txdr_unsigned(nmp
->nm_rsize
);
2578 nfsm_request(vp
, NFSPROC_READDIRPLUS
, uiop
->uio_procp
, cred
);
2579 nfsm_postop_attr(vp
, attrflag
);
2584 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2585 dnp
->n_cookieverf
.nfsuquad
[0] = *tl
++;
2586 dnp
->n_cookieverf
.nfsuquad
[1] = *tl
++;
2587 more_dirs
= fxdr_unsigned(int, *tl
);
2589 /* loop thru the dir entries, doctoring them to 4bsd form */
2590 while (more_dirs
&& bigenough
) {
2591 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2592 fxdr_hyper(tl
, &fileno
);
2593 len
= fxdr_unsigned(int, *(tl
+ 2));
2594 if (len
<= 0 || len
> NFS_MAXNAMLEN
) {
2599 tlen
= nfsm_rndup(len
);
2601 tlen
+= 4; /* To ensure null termination*/
2602 left
= DIRBLKSIZ
- blksiz
;
2603 if ((tlen
+ DIRHDSIZ
) > left
) {
2604 dp
->d_reclen
+= left
;
2605 uiop
->uio_iov
->iov_base
+= left
;
2606 uiop
->uio_iov
->iov_len
-= left
;
2607 uiop
->uio_offset
+= left
;
2608 uiop
->uio_resid
-= left
;
2611 if ((tlen
+ DIRHDSIZ
) > uiop
->uio_resid
)
2614 dp
= (struct dirent
*)uiop
->uio_iov
->iov_base
;
2615 dp
->d_fileno
= (int)fileno
;
2617 dp
->d_reclen
= tlen
+ DIRHDSIZ
;
2618 dp
->d_type
= DT_UNKNOWN
;
2619 blksiz
+= dp
->d_reclen
;
2620 if (blksiz
== DIRBLKSIZ
)
2622 uiop
->uio_offset
+= DIRHDSIZ
;
2623 uiop
->uio_resid
-= DIRHDSIZ
;
2624 uiop
->uio_iov
->iov_base
+= DIRHDSIZ
;
2625 uiop
->uio_iov
->iov_len
-= DIRHDSIZ
;
2626 cnp
->cn_nameptr
= uiop
->uio_iov
->iov_base
;
2627 cnp
->cn_namelen
= len
;
2628 nfsm_mtouio(uiop
, len
);
2629 cp
= uiop
->uio_iov
->iov_base
;
2632 uiop
->uio_iov
->iov_base
+= tlen
;
2633 uiop
->uio_iov
->iov_len
-= tlen
;
2634 uiop
->uio_offset
+= tlen
;
2635 uiop
->uio_resid
-= tlen
;
2637 nfsm_adv(nfsm_rndup(len
));
2638 nfsm_dissect(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2640 cookie
.nfsuquad
[0] = *tl
++;
2641 cookie
.nfsuquad
[1] = *tl
++;
2646 * Since the attributes are before the file handle
2647 * (sigh), we must skip over the attributes and then
2648 * come back and get them.
2650 attrflag
= fxdr_unsigned(int, *tl
);
2654 nfsm_adv(NFSX_V3FATTR
);
2655 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2656 doit
= fxdr_unsigned(int, *tl
);
2658 nfsm_getfh(fhp
, fhsize
, 1);
2659 if (NFS_CMPFH(dnp
, fhp
, fhsize
)) {
2664 if ((error
= nfs_nget(vp
->v_mount
, fhp
,
2676 nfsm_loadattr(newvp
, (struct vattr
*)0);
2680 IFTODT(VTTOIF(np
->n_vattr
.va_type
));
2683 for (cp
= cnp
->cn_nameptr
, i
= 1; i
<= len
;
2685 cnp
->cn_hash
+= (unsigned char)*cp
* i
;
2686 if (cnp
->cn_namelen
<= NCHNAMLEN
)
2687 cache_enter(ndp
->ni_dvp
, ndp
->ni_vp
, cnp
);
2690 /* Just skip over the file handle */
2691 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2692 i
= fxdr_unsigned(int, *tl
);
2693 nfsm_adv(nfsm_rndup(i
));
2695 if (newvp
!= NULLVP
) {
2699 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2700 more_dirs
= fxdr_unsigned(int, *tl
);
2703 * If at end of rpc data, get the eof boolean
2706 nfsm_dissect(tl
, u_long
*, NFSX_UNSIGNED
);
2707 more_dirs
= (fxdr_unsigned(int, *tl
) == 0);
2712 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
2713 * by increasing d_reclen for the last record.
2716 left
= DIRBLKSIZ
- blksiz
;
2717 dp
->d_reclen
+= left
;
2718 uiop
->uio_iov
->iov_base
+= left
;
2719 uiop
->uio_iov
->iov_len
-= left
;
2720 uiop
->uio_offset
+= left
;
2721 uiop
->uio_resid
-= left
;
2725 * We are now either at the end of the directory or have filled the
2729 dnp
->n_direofoffset
= uiop
->uio_offset
;
2731 if (uiop
->uio_resid
> 0)
2732 printf("EEK! readdirplusrpc resid > 0\n");
2733 cookiep
= nfs_getcookie(dnp
, uiop
->uio_offset
, 1);
2737 if (newvp
!= NULLVP
) {
2748 * Silly rename. To make the NFS filesystem that is stateless look a little
2749 * more like the "ufs" a remove of an active vnode is translated to a rename
2750 * to a funny looking filename that is removed by nfs_inactive on the
2751 * nfsnode. There is the potential for another process on a different client
2752 * to create the same funny name between the nfs_lookitup() fails and the
2753 * nfs_rename() completes, but...
2756 nfs_sillyrename(dvp
, vp
, cnp
)
2757 struct vnode
*dvp
, *vp
;
2758 struct componentname
*cnp
;
2760 register struct sillyrename
*sp
;
2769 if (vp
->v_type
== VDIR
)
2770 panic("nfs_sillyrename: dir");
2772 MALLOC_ZONE(sp
, struct sillyrename
*,
2773 sizeof (struct sillyrename
), M_NFSREQ
, M_WAITOK
);
2774 sp
->s_cred
= crdup(cnp
->cn_cred
);
2778 /* Fudge together a funny name */
2779 pid
= cnp
->cn_proc
->p_pid
;
2780 sp
->s_namlen
= sprintf(sp
->s_name
, ".nfsA%04x4.4", pid
);
2782 /* Try lookitups until we get one that isn't there */
2783 while (nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
2784 cnp
->cn_proc
, (struct nfsnode
**)0) == 0) {
2786 if (sp
->s_name
[4] > 'z') {
2791 if ((error
= nfs_renameit(dvp
, cnp
, sp
)))
2793 error
= nfs_lookitup(dvp
, sp
->s_name
, sp
->s_namlen
, sp
->s_cred
,
2796 kprintf("sillyrename: %s, vp=%x, np=%x, dvp=%x\n",
2797 &sp
->s_name
[0], (unsigned)vp
, (unsigned)np
, (unsigned)dvp
);
2799 np
->n_sillyrename
= sp
;
2804 sp
->s_cred
= NOCRED
;
2806 _FREE_ZONE((caddr_t
)sp
, sizeof (struct sillyrename
), M_NFSREQ
);
2811 * Look up a file name and optionally either update the file handle or
2812 * allocate an nfsnode, depending on the value of npp.
2813 * npp == NULL --> just do the lookup
2814 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2816 * *npp != NULL --> update the file handle in the vnode
2819 nfs_lookitup(dvp
, name
, len
, cred
, procp
, npp
)
2820 register struct vnode
*dvp
;
2825 struct nfsnode
**npp
;
2827 register u_long
*tl
;
2828 register caddr_t cp
;
2829 register long t1
, t2
;
2830 struct vnode
*newvp
= (struct vnode
*)0;
2831 struct nfsnode
*np
, *dnp
= VTONFS(dvp
);
2832 caddr_t bpos
, dpos
, cp2
;
2833 int error
= 0, fhlen
, attrflag
;
2834 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2836 int v3
= NFS_ISV3(dvp
);
2838 nfsstats
.rpccnt
[NFSPROC_LOOKUP
]++;
2839 nfsm_reqhead(dvp
, NFSPROC_LOOKUP
,
2840 NFSX_FH(v3
) + NFSX_UNSIGNED
+ nfsm_rndup(len
));
2841 nfsm_fhtom(dvp
, v3
);
2842 nfsm_strtom(name
, len
, NFS_MAXNAMLEN
);
2843 nfsm_request(dvp
, NFSPROC_LOOKUP
, procp
, cred
);
2844 if (npp
&& !error
) {
2845 nfsm_getfh(nfhp
, fhlen
, v3
);
2848 if (np
->n_fhsize
> NFS_SMALLFH
&& fhlen
<= NFS_SMALLFH
) {
2849 _FREE_ZONE((caddr_t
)np
->n_fhp
,
2850 np
->n_fhsize
, M_NFSBIGFH
);
2851 np
->n_fhp
= &np
->n_fh
;
2852 } else if (np
->n_fhsize
<= NFS_SMALLFH
&& fhlen
>NFS_SMALLFH
)
2853 MALLOC_ZONE(np
->n_fhp
, nfsfh_t
*,
2854 fhlen
, M_NFSBIGFH
, M_WAITOK
);
2855 bcopy((caddr_t
)nfhp
, (caddr_t
)np
->n_fhp
, fhlen
);
2856 np
->n_fhsize
= fhlen
;
2858 } else if (NFS_CMPFH(dnp
, nfhp
, fhlen
)) {
2862 error
= nfs_nget(dvp
->v_mount
, nfhp
, fhlen
, &np
);
2870 nfsm_postop_attr(newvp
, attrflag
);
2871 if (!attrflag
&& *npp
== NULL
) {
2880 nfsm_loadattr(newvp
, (struct vattr
*)0);
2883 if (npp
&& *npp
== NULL
) {
2897 * Nfs Version 3 commit rpc
2900 nfs_commit(vp
, offset
, cnt
, cred
, procp
)
2901 register struct vnode
*vp
;
2907 register caddr_t cp
;
2908 register u_long
*tl
;
2909 register int t1
, t2
;
2910 register struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
2911 caddr_t bpos
, dpos
, cp2
;
2912 int error
= 0, wccflag
= NFSV3_WCCRATTR
;
2913 struct mbuf
*mreq
, *mrep
, *md
, *mb
, *mb2
;
2915 if ((nmp
->nm_flag
& NFSMNT_HASWRITEVERF
) == 0)
2917 nfsstats
.rpccnt
[NFSPROC_COMMIT
]++;
2918 nfsm_reqhead(vp
, NFSPROC_COMMIT
, NFSX_FH(1));
2920 nfsm_build(tl
, u_long
*, 3 * NFSX_UNSIGNED
);
2921 txdr_hyper(&offset
, tl
);
2923 *tl
= txdr_unsigned(cnt
);
2924 nfsm_request(vp
, NFSPROC_COMMIT
, procp
, cred
);
2925 nfsm_wcc_data(vp
, wccflag
);
2927 nfsm_dissect(tl
, u_long
*, NFSX_V3WRITEVERF
);
2928 if (bcmp((caddr_t
)nmp
->nm_verf
, (caddr_t
)tl
,
2929 NFSX_V3WRITEVERF
)) {
2930 bcopy((caddr_t
)tl
, (caddr_t
)nmp
->nm_verf
,
2932 error
= NFSERR_STALEWRITEVERF
;
2941 * - make nfs_bmap() essentially a no-op that does no translation
2942 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
2943 * (Maybe I could use the process's page mapping, but I was concerned that
2944 * Kernel Write might not be enabled and also figured copyout() would do
2945 * a lot more work than bcopy() and also it currently happens in the
2946 * context of the swapper process (2).
2950 struct vop_bmap_args
/* {
2953 struct vnode **a_vpp;
2959 register struct vnode
*vp
= ap
->a_vp
;
2960 int devBlockSize
= DEV_BSIZE
;
2962 if (ap
->a_vpp
!= NULL
)
2964 if (ap
->a_bnp
!= NULL
)
2965 *ap
->a_bnp
= ap
->a_bn
* btodb(vp
->v_mount
->mnt_stat
.f_iosize
,
2967 if (ap
->a_runp
!= NULL
)
2970 if (ap
->a_runb
!= NULL
)
2978 * For async requests when nfsiod(s) are running, queue the request by
2979 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2984 struct vop_strategy_args
*ap
;
2986 register struct buf
*bp
= ap
->a_bp
;
2991 if (ISSET(bp
->b_flags
, B_PHYS
))
2992 panic("nfs_strategy: physio");
2993 if (ISSET(bp
->b_flags
, B_ASYNC
))
2994 p
= (struct proc
*)0;
2996 p
= current_proc(); /* XXX */
2997 if (ISSET(bp
->b_flags
, B_READ
))
3002 * If the op is asynchronous and an i/o daemon is waiting
3003 * queue the request, wake it up and wait for completion
3004 * otherwise just do it ourselves.
3006 if (!ISSET(bp
->b_flags
, B_ASYNC
) || nfs_asyncio(bp
, NOCRED
))
3007 error
= nfs_doio(bp
, cr
, p
);
3014 * NB Currently unsupported.
3019 struct vop_mmap_args
/* {
3022 struct ucred *a_cred;
3031 * fsync vnode op. Just call nfs_flush() with commit == 1.
3036 struct vop_fsync_args
/* {
3037 struct vnodeop_desc *a_desc;
3038 struct vnode * a_vp;
3039 struct ucred * a_cred;
3045 return (nfs_flush(ap
->a_vp
, ap
->a_cred
, ap
->a_waitfor
, ap
->a_p
, 1));
3049 * Flush all the blocks associated with a vnode.
3050 * Walk through the buffer pool and push any dirty pages
3051 * associated with the vnode.
3054 nfs_flush(vp
, cred
, waitfor
, p
, commit
)
3055 register struct vnode
*vp
;
3061 register struct nfsnode
*np
= VTONFS(vp
);
3062 register struct buf
*bp
;
3065 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
3066 int s
, error
= 0, slptimeo
= 0, slpflag
= 0, retv
, bvecpos
, err
;
3068 u_quad_t off
, endoff
, toff
;
3069 struct ucred
* wcred
= NULL
;
3070 struct buf
**bvec
= NULL
;
3076 #ifndef NFS_COMMITBVECSIZ
3077 #define NFS_COMMITBVECSIZ 20
3079 struct buf
*bvec_on_stack
[NFS_COMMITBVECSIZ
];
3080 struct upl_t
*upls_on_stack
[NFS_COMMITBVECSIZ
];
3081 int bvecsize
= 0, bveccount
, buplpos
;
3083 if (nmp
->nm_flag
& NFSMNT_INT
)
3089 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
3090 * server, but nas not been committed to stable storage on the server
3091 * yet. On the first pass, the byte range is worked out and the commit
3092 * rpc is done. On the second pass, nfs_writebp() is called to do the
3096 if (vp
->v_dirtyblkhd
.lh_first
)
3097 np
->n_flag
|= NMODIFIED
;
3102 if (NFS_ISV3(vp
) && commit
) {
3105 * Count up how many buffers waiting for a commit.
3108 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3109 nbp
= bp
->b_vnbufs
.le_next
;
3110 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3111 == (B_DELWRI
| B_NEEDCOMMIT
))
3115 * Allocate space to remember the list of bufs to commit. It is
3116 * important to use M_NOWAIT here to avoid a race with nfs_write.
3117 * If we can't get memory (for whatever reason), we will end up
3118 * committing the buffers one-by-one in the loop below.
3120 if (bveccount
> NFS_COMMITBVECSIZ
) {
3121 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3122 _FREE(bvec
, M_TEMP
);
3123 MALLOC(bvec
, struct buf
**,
3124 bveccount
* sizeof(struct buf
*), M_TEMP
, M_NOWAIT
);
3126 bvec
= bvec_on_stack
;
3127 bvecsize
= NFS_COMMITBVECSIZ
;
3129 bvecsize
= bveccount
;
3130 /* allocate the upl structure before the loop based on buffers to commit */
3131 if (upls
!= NULL
&& upls
!= upls_on_stack
)
3132 _FREE(upls
, M_TEMP
);
3133 MALLOC(upls
, struct upl_t
*,
3134 bveccount
* sizeof(upl_t
), M_TEMP
, M_NOWAIT
);
3136 upls
= upls_on_stack
;
3138 if (bvec
&& bvec
!= bvec_on_stack
)
3139 _FREE(bvec
, M_TEMP
);
3140 bvec
= bvec_on_stack
;
3141 bvecsize
= NFS_COMMITBVECSIZ
;
3142 if (upls
&& upls
!= upls_on_stack
)
3143 _FREE(upls
, M_TEMP
);
3144 upls
= upls_on_stack
;
3147 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3148 nbp
= bp
->b_vnbufs
.le_next
;
3149 if (bvecpos
>= bvecsize
)
3151 if ((bp
->b_flags
& (B_BUSY
| B_DELWRI
| B_NEEDCOMMIT
))
3152 != (B_DELWRI
| B_NEEDCOMMIT
))
3156 * Work out if all buffers are using the same cred
3157 * so we can deal with them all with one commit.
3160 wcred
= bp
->b_wcred
;
3161 else if (wcred
!= bp
->b_wcred
)
3163 SET(bp
->b_flags
, (B_BUSY
| B_WRITEINPROG
));
3166 * we need vm_fault_list_request so if vm decides to
3167 * do paging while we are waiting on commit rpc,
3168 * that it doesn't pick these pages.
3170 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3171 /* if pagelist exists, assume vm pages are locked/busy already */ off_t file_offset
= ubc_blktooff(vp
, bp
->b_lblkno
);
3172 object
= ubc_getobject(vp
, (UBC_NOREACTIVATE
|UBC_HOLDOBJECT
));
3173 if (object
== (void*)NULL
)
3174 panic("nfs_getcacheblk: NULL vmobject");
3175 if(bp
->b_bufsize
& 0xfff)
3176 panic("nfs_getcacheblk: list request is less than 4k");
3177 kret
= vm_fault_list_request(
3178 object
, (vm_object_offset_t
)file_offset
,
3179 bp
->b_bufsize
, &(upls
[buplpos
]), NULL
, 0,
3180 (int)(UPL_NO_SYNC
| UPL_CLEAN_IN_PLACE
|UPL_PRECIOUS
|
3182 if (kret
!= KERN_SUCCESS
)
3183 panic("nfs_getcacheblk: get pagelists failed with (%d)", kret
);
3186 upl_ubc_alias_set(pl
, ioaddr
, 1);
3187 #endif /* UBC_DEBUG */
3188 buplpos
++; /* not same as bvecpos if upl existed already */
3192 * A list of these buffers is kept so that the
3193 * second loop knows which buffers have actually
3194 * been committed. This is necessary, since there
3195 * may be a race between the commit rpc and new
3196 * uncommitted writes on the file.
3198 bvec
[bvecpos
++] = bp
;
3199 toff
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3203 toff
+= (u_quad_t
)(bp
->b_dirtyend
- bp
->b_dirtyoff
);
3211 * Commit data on the server, as required.
3212 * If all bufs are using the same wcred, then use that with
3213 * one call for all of them, otherwise commit each one
3216 if (wcred
!= NOCRED
)
3217 retv
= nfs_commit(vp
, off
, (int)(endoff
- off
),
3221 for (i
= 0; i
< bvecpos
; i
++) {
3224 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+
3226 size
= (u_quad_t
)(bp
->b_dirtyend
3228 retv
= nfs_commit(vp
, off
, (int)size
,
3234 if (retv
== NFSERR_STALEWRITEVERF
)
3235 nfs_clearcommit(vp
->v_mount
);
3237 for (i
= 0; i
< buplpos
; i
++) {
3239 * before the VOP_BWRITE and biodone(ASYNC)/brelse, we have to undo
3240 * holding the vm page or we we will deadlock on another vm_fault_list_request.
3241 * Here's a convenient place to put it.
3242 * Better if we could hold it by setting the PAGELIST flag and kernel_upl_map
3243 * as does nfs_writebp. Then normal biodones and brelse will clean it up and
3244 * we can avoid this abort. For now make minimal changse and test this out.
3246 err
= kernel_upl_abort(upls
[i
], NULL
);
3248 printf("nfs_flush: kernel_upl_abort %d\n", err
);
3252 * Now, either mark the blocks I/O done or mark the
3253 * blocks dirty, depending on whether the commit
3256 for (i
= 0; i
< bvecpos
; i
++) {
3259 CLR(bp
->b_flags
, (B_NEEDCOMMIT
| B_WRITEINPROG
));
3264 SET(bp
->b_flags
, B_ASYNC
);
3266 CLR(bp
->b_flags
, (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3267 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3268 reassignbuf(bp
, vp
);
3277 * Start/do any write(s) that are required.
3278 * There is a window here where B_BUSY protects the buffer. The vm pages have been
3279 * freed up, yet B_BUSY is set. Don't think you will hit any busy/incore problems while
3280 * we sleep, but not absolutely sure. Keep an eye on it. Otherwise we will have to hold
3281 * vm page across this locked. - EKN
3284 if (current_thread_aborted()) {
3289 for (bp
= vp
->v_dirtyblkhd
.lh_first
; bp
; bp
= nbp
) {
3290 nbp
= bp
->b_vnbufs
.le_next
;
3291 if (ISSET(bp
->b_flags
, B_BUSY
)) {
3292 if (waitfor
!= MNT_WAIT
|| passone
)
3294 SET(bp
->b_flags
, B_WANTED
);
3295 error
= tsleep((caddr_t
)bp
, slpflag
| (PRIBIO
+ 1),
3296 "nfsfsync", slptimeo
);
3299 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3303 if (slpflag
== PCATCH
) {
3310 if (!ISSET(bp
->b_flags
, B_DELWRI
))
3311 panic("nfs_fsync: not dirty");
3312 if ((passone
|| !commit
) && ISSET(bp
->b_flags
, B_NEEDCOMMIT
))
3315 if (passone
|| !commit
)
3316 SET(bp
->b_flags
, (B_BUSY
|B_ASYNC
));
3318 SET(bp
->b_flags
, (B_BUSY
|B_ASYNC
|B_WRITEINPROG
|B_NEEDCOMMIT
));
3329 if (waitfor
== MNT_WAIT
) {
3330 while (vp
->v_numoutput
) {
3331 vp
->v_flag
|= VBWAIT
;
3332 error
= tsleep((caddr_t
)&vp
->v_numoutput
,
3333 slpflag
| (PRIBIO
+ 1), "nfsfsync", slptimeo
);
3335 if (nfs_sigintr(nmp
, (struct nfsreq
*)0, p
)) {
3339 if (slpflag
== PCATCH
) {
3345 if (vp
->v_dirtyblkhd
.lh_first
&& commit
) {
3349 if (np
->n_flag
& NWRITEERR
) {
3350 error
= np
->n_error
;
3351 np
->n_flag
&= ~NWRITEERR
;
3354 if (bvec
!= NULL
&& bvec
!= bvec_on_stack
)
3355 _FREE(bvec
, M_TEMP
);
3356 if (upls
!= NULL
&& upls
!= upls_on_stack
)
3357 _FREE(upls
, M_TEMP
);
3362 * Return POSIX pathconf information applicable to nfs.
3364 * The NFS V2 protocol doesn't support this, so just return EINVAL
3370 struct vop_pathconf_args
/* {
3381 * NFS advisory byte-level locks.
3382 * Currently unsupported.
3386 struct vop_advlock_args
/* {
3395 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3398 * The following kludge is to allow diskless support to work
3399 * until a real NFS lockd is implemented. Basically, just pretend
3400 * that this is a local lock.
3402 return (lf_advlock(ap
, &(np
->n_lockf
), np
->n_size
));
3405 printf("nfs_advlock: pid %d comm %s\n", current_proc()->p_pid
, current_proc()->p_comm
);
3407 return (EOPNOTSUPP
);
3412 * Print out the contents of an nfsnode.
3416 struct vop_print_args
/* {
3420 register struct vnode
*vp
= ap
->a_vp
;
3421 register struct nfsnode
*np
= VTONFS(vp
);
3423 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
3424 np
->n_vattr
.va_fileid
, np
->n_vattr
.va_fsid
);
3425 if (vp
->v_type
== VFIFO
)
3432 * NFS directory offset lookup.
3433 * Currently unsupported.
3437 struct vop_blkatoff_args
/* {
3446 printf("nfs_blkatoff: unimplemented!!");
3448 return (EOPNOTSUPP
);
3452 * NFS flat namespace allocation.
3453 * Currently unsupported.
3457 struct vop_valloc_args
/* {
3458 struct vnode *a_pvp;
3460 struct ucred *a_cred;
3461 struct vnode **a_vpp;
3465 return (EOPNOTSUPP
);
3469 * NFS flat namespace free.
3470 * Currently unsupported.
3474 struct vop_vfree_args
/* {
3475 struct vnode *a_pvp;
3482 printf("nfs_vfree: unimplemented!!");
3484 return (EOPNOTSUPP
);
3488 * NFS file truncation.
3492 struct vop_truncate_args
/* {
3496 struct ucred *a_cred;
3501 /* Use nfs_setattr */
3503 printf("nfs_truncate: unimplemented!!");
3505 return (EOPNOTSUPP
);
3513 struct vop_update_args
/* {
3515 struct timeval *a_ta;
3516 struct timeval *a_tm;
3521 /* Use nfs_setattr */
3523 printf("nfs_update: unimplemented!!");
3525 return (EOPNOTSUPP
);
3528 int nfs_aio_threads
= 0; /* 1 per nfd (arbitrary) */
3529 struct slock nfs_aio_slock
;
3530 TAILQ_HEAD(bqueues
, buf
) nfs_aio_bufq
;
3531 int nfs_aio_bufq_len
= 0; /* diagnostic only */
3535 { /* see comment below in nfs_bwrite() for some rationale */
3537 boolean_t funnel_state
;
3539 funnel_state
= thread_funnel_set(kernel_flock
, TRUE
);
3541 simple_lock(&nfs_aio_slock
);
3542 if ((bp
= nfs_aio_bufq
.tqh_first
)) {
3543 TAILQ_REMOVE(&nfs_aio_bufq
, bp
, b_freelist
);
3545 simple_unlock(&nfs_aio_slock
);
3547 } else { /* nothing to do - goodnight */
3548 assert_wait(&nfs_aio_bufq
, THREAD_UNINT
);
3549 simple_unlock(&nfs_aio_slock
);
3550 (void)tsleep((caddr_t
)0, PRIBIO
+1, "nfs_aio_bufq", 0);
3553 (void) thread_funnel_set(kernel_flock
, FALSE
);
3558 nfs_aio_thread_init()
3560 if (nfs_aio_threads
++ == 0) {
3561 simple_lock_init(&nfs_aio_slock
);
3562 TAILQ_INIT(&nfs_aio_bufq
);
3564 kernel_thread(kernel_task
, nfs_aio_thread
);
3569 * Just call nfs_writebp() with the force argument set to 1.
3573 struct vop_bwrite_args
/* {
3577 extern void wakeup_one(caddr_t chan
);
3580 * nfs_writebp will issue a synchronous rpc to if B_ASYNC then
3581 * to avoid distributed deadlocks we handoff the write to the
3582 * nfs_aio threads. Doing so allows us to complete the
3583 * current request, rather than blocking on a server which may
3584 * be ourself (or blocked on ourself).
3586 * Note the loopback deadlocks happened when the thread
3587 * invoking us was nfsd, and also when it was the pagedaemon.
3589 * This solution has one known problem. If *ALL* buffers get
3590 * on the nfs_aio queue then no forward progress can be made
3591 * until one of those writes complete. And if the current
3592 * nfs_aio writes-in-progress block due to a non-responsive server we
3593 * are in a deadlock circle. Probably the cure is to limit the
3594 * async write concurrency in getnewbuf as in FreeBSD 3.2.
3596 if (nfs_aio_threads
&& ISSET(ap
->a_bp
->b_flags
, B_ASYNC
)) {
3597 simple_lock(&nfs_aio_slock
);
3599 TAILQ_INSERT_TAIL(&nfs_aio_bufq
, ap
->a_bp
, b_freelist
);
3600 simple_unlock(&nfs_aio_slock
);
3601 wakeup_one((caddr_t
)&nfs_aio_bufq
);
3604 return (nfs_writebp(ap
->a_bp
, 1));
3608 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless
3609 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
3612 nfs_writebp(bp
, force
)
3613 register struct buf
*bp
;
3617 register int oldflags
= bp
->b_flags
, retv
= 1;
3622 struct vnode
*vp
= bp
->b_vp
;
3623 upl_page_info_t
*pl
;
3625 if(!ISSET(bp
->b_flags
, B_BUSY
))
3626 panic("nfs_writebp: buffer is not busy???");
3629 CLR(bp
->b_flags
, (B_READ
|B_DONE
|B_ERROR
|B_DELWRI
));
3631 if (ISSET(oldflags
, (B_ASYNC
|B_DELWRI
))) {
3632 reassignbuf(bp
, vp
);
3636 current_proc()->p_stats
->p_ru
.ru_oublock
++;
3640 * Since the B_BUSY flag is set, we need to lock the page before doing nfs_commit.
3641 * Otherwise we may block and get a busy incore pages during a vm pageout.
3642 * Move the existing code up before the commit.
3645 if (!ISSET(bp
->b_flags
, B_META
) && UBCISVALID(vp
)) {
3647 if (!ISSET(bp
->b_flags
, B_PAGELIST
)) {
3649 off_t file_offset
= ubc_blktooff(vp
, bp
->b_lblkno
);
3651 object
= ubc_getobject(vp
, (UBC_NOREACTIVATE
|UBC_HOLDOBJECT
));
3652 if (object
== (void*)NULL
)
3653 panic("nfs_writebp: NULL vmobject");
3655 if(bp
->b_bufsize
& 0xfff)
3656 panic("nfs_writebp: list request is with less than 4k");
3658 kret
= vm_fault_list_request(object
, (vm_object_offset_t
)file_offset
,
3659 bp
->b_bufsize
, &upl
, NULL
, 0,
3660 (int)(UPL_NO_SYNC
| UPL_CLEAN_IN_PLACE
| UPL_PRECIOUS
| UPL_SET_INTERNAL
));
3661 if (kret
!= KERN_SUCCESS
) {
3662 panic("nfs_writebp: get pagelists failed with (%d)", kret
);
3666 upl_ubc_alias_set(pl
, ioaddr
, 2);
3667 #endif /* UBC_DEBUG */
3671 pl
= UPL_GET_INTERNAL_PAGE_LIST(upl
);
3672 bp
->b_pagelist
= upl
;
3673 SET(bp
->b_flags
, B_PAGELIST
);
3676 kret
= kernel_upl_map(kernel_map
, upl
,
3677 (vm_address_t
*)&(bp
->b_data
));
3678 if (kret
!= KERN_SUCCESS
) {
3679 panic("nfs_writebp: kernel_upl_map() failed with (%d)", kret
);
3682 panic("nfs_writebp: upl_map mapped 0");
3683 if (!upl_page_present(pl
, 0)) {
3685 * may be the page got paged out.
3686 * let's just read it in. It is marked
3687 * busy so we should not have any one
3688 * yanking this page underneath the fileIO
3690 panic("nfs_writebp: nopage");
3696 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3697 * an actual write will have to be scheduled via. VOP_STRATEGY().
3698 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3700 if ((oldflags
& (B_NEEDCOMMIT
| B_WRITEINPROG
)) == B_NEEDCOMMIT
) {
3701 off
= ((u_quad_t
)bp
->b_blkno
) * DEV_BSIZE
+ bp
->b_dirtyoff
;
3702 SET(bp
->b_flags
, B_WRITEINPROG
);
3703 retv
= nfs_commit(vp
, off
, bp
->b_dirtyend
-bp
->b_dirtyoff
,
3704 bp
->b_wcred
, bp
->b_proc
);
3705 CLR(bp
->b_flags
, B_WRITEINPROG
);
3707 bp
->b_dirtyoff
= bp
->b_dirtyend
= 0;
3708 CLR(bp
->b_flags
, B_NEEDCOMMIT
);
3709 biodone(bp
); /* on B_ASYNC will brelse the buffer */
3711 } else if (retv
== NFSERR_STALEWRITEVERF
)
3712 nfs_clearcommit(vp
->v_mount
);
3716 SET(bp
->b_flags
, B_WRITEINPROG
);
3722 if( (oldflags
& B_ASYNC
) == 0) {
3723 int rtval
= biowait(bp
);
3725 if (oldflags
& B_DELWRI
) {
3727 reassignbuf(bp
, vp
);
3738 * nfs special file access vnode op.
3739 * Essentially just get vattr and then imitate iaccess() since the device is
3740 * local to the client.
3744 struct vop_access_args
/* {
3747 struct ucred *a_cred;
3751 register struct vattr
*vap
;
3753 register struct ucred
*cred
= ap
->a_cred
;
3754 struct vnode
*vp
= ap
->a_vp
;
3755 mode_t mode
= ap
->a_mode
;
3761 * Disallow write attempts on filesystems mounted read-only;
3762 * unless the file is a socket, fifo, or a block or character
3763 * device resident on the filesystem.
3765 if ((mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
3766 switch (vp
->v_type
) {
3767 case VREG
: case VDIR
: case VLNK
:
3772 * If you're the super-user,
3773 * you always get access.
3775 if (cred
->cr_uid
== 0)
3778 error
= VOP_GETATTR(vp
, vap
, cred
, ap
->a_p
);
3782 * Access check is based on only one of owner, group, public.
3783 * If not owner, then check group. If not a member of the
3784 * group, then check public access.
3786 if (cred
->cr_uid
!= vap
->va_uid
) {
3788 gp
= cred
->cr_groups
;
3789 for (i
= 0; i
< cred
->cr_ngroups
; i
++, gp
++)
3790 if (vap
->va_gid
== *gp
)
3796 error
= (vap
->va_mode
& mode
) == mode
? 0 : EACCES
;
3801 * Read wrapper for special devices.
3805 struct vop_read_args
/* {
3809 struct ucred *a_cred;
3812 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3818 np
->n_atim
.tv_sec
= time
.tv_sec
;
3819 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
3820 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_read
), ap
));
3824 * Write wrapper for special devices.
3828 struct vop_write_args
/* {
3832 struct ucred *a_cred;
3835 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3841 np
->n_mtim
.tv_sec
= time
.tv_sec
;
3842 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
3843 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_write
), ap
));
3847 * Close wrapper for special devices.
3849 * Update the times on the nfsnode then do device close.
3853 struct vop_close_args
/* {
3856 struct ucred *a_cred;
3860 register struct vnode
*vp
= ap
->a_vp
;
3861 register struct nfsnode
*np
= VTONFS(vp
);
3864 if (np
->n_flag
& (NACC
| NUPD
)) {
3866 if (vp
->v_usecount
== 1 &&
3867 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
3869 if (np
->n_flag
& NACC
)
3870 vattr
.va_atime
= np
->n_atim
;
3871 if (np
->n_flag
& NUPD
)
3872 vattr
.va_mtime
= np
->n_mtim
;
3873 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
3876 return (VOCALL(spec_vnodeop_p
, VOFFSET(vop_close
), ap
));
3880 * Read wrapper for fifos.
3884 struct vop_read_args
/* {
3888 struct ucred *a_cred;
3891 extern vop_t
**fifo_vnodeop_p
;
3892 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3898 np
->n_atim
.tv_sec
= time
.tv_sec
;
3899 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
3900 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_read
), ap
));
3904 * Write wrapper for fifos.
3908 struct vop_write_args
/* {
3912 struct ucred *a_cred;
3915 extern vop_t
**fifo_vnodeop_p
;
3916 register struct nfsnode
*np
= VTONFS(ap
->a_vp
);
3922 np
->n_mtim
.tv_sec
= time
.tv_sec
;
3923 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
3924 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_write
), ap
));
3928 * Close wrapper for fifos.
3930 * Update the times on the nfsnode then do fifo close.
3934 struct vop_close_args
/* {
3937 struct ucred *a_cred;
3941 register struct vnode
*vp
= ap
->a_vp
;
3942 register struct nfsnode
*np
= VTONFS(vp
);
3944 extern vop_t
**fifo_vnodeop_p
;
3946 if (np
->n_flag
& (NACC
| NUPD
)) {
3947 if (np
->n_flag
& NACC
) {
3948 np
->n_atim
.tv_sec
= time
.tv_sec
;
3949 np
->n_atim
.tv_nsec
= time
.tv_usec
* 1000;
3951 if (np
->n_flag
& NUPD
) {
3952 np
->n_mtim
.tv_sec
= time
.tv_sec
;
3953 np
->n_mtim
.tv_nsec
= time
.tv_usec
* 1000;
3956 if (vp
->v_usecount
== 1 &&
3957 (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) == 0) {
3959 if (np
->n_flag
& NACC
)
3960 vattr
.va_atime
= np
->n_atim
;
3961 if (np
->n_flag
& NUPD
)
3962 vattr
.va_mtime
= np
->n_mtim
;
3963 (void)VOP_SETATTR(vp
, &vattr
, ap
->a_cred
, ap
->a_p
);
3966 return (VOCALL(fifo_vnodeop_p
, VOFFSET(vop_close
), ap
));
3971 struct vop_ioctl_args
*ap
;
3975 * XXX we were once bogusly enoictl() which returned this (ENOTTY).
3976 * Probably we should return ENODEV.
3983 struct vop_select_args
*ap
;
3987 * We were once bogusly seltrue() which returns 1. Is this right?
3992 /* XXX Eliminate use of struct bp here */
3994 * Vnode op for pagein using getblk_pages
3995 * derived from nfs_bioread()
3996 * No read aheads are started from pagein operation
4000 struct vop_pagein_args
/* {
4003 vm_offset_t a_pl_offset,
4006 struct ucred *a_cred,
4010 register struct vnode
*vp
= ap
->a_vp
;
4011 upl_t pl
= ap
->a_pl
;
4012 size_t size
= ap
->a_size
;
4013 off_t f_offset
= ap
->a_f_offset
;
4014 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4015 int flags
= ap
->a_flags
;
4017 register struct nfsnode
*np
= VTONFS(vp
);
4018 register int biosize
;
4021 struct proc
*p
= current_proc();
4022 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4027 struct uio
* uio
= &auio
;
4028 int nocommit
= flags
& UPL_NOCOMMIT
;
4030 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 322)) | DBG_FUNC_NONE
,
4031 (int)f_offset
, size
, pl
, pl_offset
, 0);
4033 if (UBCINVALID(vp
)) {
4035 panic("nfs_pagein: invalid vp");
4036 #endif /* DIAGNOSTIC */
4040 UBCINFOCHECK("nfs_pagein", vp
);
4041 if(pl
== (upl_t
)NULL
) {
4042 panic("nfs_pagein: no upl");
4045 cred
= ubc_getcred(vp
);
4052 if (f_offset
< 0 || f_offset
>= np
->n_size
4053 || (f_offset
& PAGE_MASK_64
)) {
4055 kernel_upl_abort_range(pl
, pl_offset
, size
,
4056 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4060 auio
.uio_iov
= &aiov
;
4061 auio
.uio_iovcnt
= 1;
4062 auio
.uio_offset
= f_offset
;
4063 auio
.uio_segflg
= UIO_SYSSPACE
;
4064 auio
.uio_rw
= UIO_READ
;
4065 auio
.uio_procp
= NULL
;
4068 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4069 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4070 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4072 if (biosize
& PAGE_MASK
)
4073 panic("nfs_pagein(%x): biosize not page aligned", biosize
);
4075 #if 0 /* Why bother? */
4076 /* DO NOT BOTHER WITH "approximately maintained cache consistency" */
4077 /* Does not make sense in paging paths -- Umesh*/
4079 * For nfs, cache consistency can only be maintained approximately.
4080 * Although RFC1094 does not specify the criteria, the following is
4081 * believed to be compatible with the reference port.
4082 * For nqnfs, full cache consistency is maintained within the loop.
4084 * If the file's modify time on the server has changed since the
4085 * last read rpc or you have written to the file,
4086 * you may have lost data cache consistency with the
4087 * server, so flush all of the file's data out of the cache.
4088 * Then force a getattr rpc to ensure that you have up to date
4090 * NB: This implies that cache data can be read when up to
4091 * NFS_ATTRTIMEO seconds out of date. If you find that you need current
4092 * attributes this could be forced by setting n_attrstamp to 0 before
4093 * the VOP_GETATTR() call.
4095 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) == 0) {
4096 if (np
->n_flag
& NMODIFIED
) {
4097 np
->n_attrstamp
= 0;
4098 error
= VOP_GETATTR(vp
, &vattr
, cred
, p
);
4101 kernel_upl_abort_range(pl
, pl_offset
,
4104 UPL_ABORT_FREE_ON_EMPTY
);
4107 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
4109 error
= VOP_GETATTR(vp
, &vattr
, cred
, p
);
4112 kernel_upl_abort_range(pl
, pl_offset
, size
,
4114 UPL_ABORT_FREE_ON_EMPTY
);
4117 if (np
->n_mtime
!= vattr
.va_mtime
.tv_sec
) {
4118 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4121 kernel_upl_abort_range(pl
, pl_offset
, size
,
4123 UPL_ABORT_FREE_ON_EMPTY
);
4126 np
->n_mtime
= vattr
.va_mtime
.tv_sec
;
4130 #endif 0 /* Why bother? */
4132 kernel_upl_map(kernel_map
, pl
, &ioaddr
);
4133 ioaddr
+= pl_offset
;
4137 uio
->uio_resid
= min(biosize
, xsize
);
4138 aiov
.iov_len
= uio
->uio_resid
;
4139 aiov
.iov_base
= (caddr_t
)ioaddr
;
4141 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 322)) | DBG_FUNC_NONE
,
4142 (int)uio
->uio_offset
, uio
->uio_resid
, ioaddr
, xsize
, 0);
4144 #warning nfs_pagein does not support NQNFS yet.
4145 #if 0 /* why bother? */
4146 /* NO RESOURCES TO FIX NQNFS CASE */
4147 /* We need to deal with this later -- Umesh */
4149 * Get a valid lease. If cached data is stale, flush it.
4151 if (nmp
->nm_flag
& NFSMNT_NQNFS
) {
4152 if (NQNFS_CKINVALID(vp
, np
, ND_READ
)) {
4154 error
= nqnfs_getlease(vp
, ND_READ
, cred
, p
);
4155 } while (error
== NQNFS_EXPIRED
);
4157 kernel_upl_unmap(kernel_map
, pl
);
4159 kernel_upl_abort_range(pl
, pl_offset
,
4160 size
,UPL_ABORT_ERROR
|
4161 UPL_ABORT_FREE_ON_EMPTY
);
4165 if (np
->n_lrev
!= np
->n_brev
||
4166 (np
->n_flag
& NQNFSNONCACHE
)) {
4167 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4169 kernel_upl_unmap(kernel_map
, pl
);
4171 kernel_upl_abort_range(pl
,
4173 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4176 np
->n_brev
= np
->n_lrev
;
4180 #endif 0 /* why bother? */
4182 if (np
->n_flag
& NQNFSNONCACHE
) {
4183 error
= nfs_readrpc(vp
, uio
, cred
);
4184 kernel_upl_unmap(kernel_map
, pl
);
4188 kernel_upl_abort_range(pl
, pl_offset
, size
,
4189 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4191 kernel_upl_commit_range(pl
,
4193 UPL_COMMIT_CLEAR_DIRTY
4194 | UPL_COMMIT_FREE_ON_EMPTY
,
4195 UPL_GET_INTERNAL_PAGE_LIST(pl
),
4202 * With UBC we get here only when the file data is not in the VM
4203 * page cache, so go ahead and read in.
4206 upl_ubc_alias_set(pl
, ioaddr
, 2);
4207 #endif /* UBC_DEBUG */
4209 error
= nfs_readrpc(vp
, uio
, cred
);
4215 if (uio
->uio_resid
) {
4217 * If uio_resid > 0, there is a hole in the file and
4218 * no writes after the hole have been pushed to
4219 * the server yet... or we're at the EOF
4220 * Just zero fill the rest of the valid area.
4222 zcnt
= uio
->uio_resid
;
4223 zoff
= biosize
- zcnt
;
4224 bzero((char *)ioaddr
+ zoff
, zcnt
);
4226 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 324)) | DBG_FUNC_NONE
,
4227 (int)uio
->uio_offset
, zoff
, zcnt
, ioaddr
, 0);
4229 uio
->uio_offset
+= zcnt
;
4234 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 322)) | DBG_FUNC_NONE
,
4235 (int)uio
->uio_offset
, uio
->uio_resid
, error
, -1, 0);
4237 if (p
&& (vp
->v_flag
& VTEXT
) &&
4238 (((nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4239 NQNFS_CKINVALID(vp
, np
, ND_READ
) &&
4240 np
->n_lrev
!= np
->n_brev
) ||
4241 (!(nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4242 np
->n_mtime
!= np
->n_vattr
.va_mtime
.tv_sec
))) {
4243 uprintf("Process killed due to text file modification\n");
4244 psignal(p
, SIGKILL
);
4245 p
->p_flag
|= P_NOSWAP
;
4248 } while (error
== 0 && xsize
> 0);
4250 kernel_upl_unmap(kernel_map
, pl
);
4254 kernel_upl_abort_range(pl
, pl_offset
, size
,
4255 UPL_ABORT_ERROR
| UPL_ABORT_FREE_ON_EMPTY
);
4257 kernel_upl_commit_range(pl
, pl_offset
, size
,
4258 UPL_COMMIT_CLEAR_DIRTY
4259 | UPL_COMMIT_FREE_ON_EMPTY
,
4260 UPL_GET_INTERNAL_PAGE_LIST(pl
),
4268 * Vnode op for pageout using UPL
4269 * Derived from nfs_write()
4270 * File size changes are not permitted in pageout.
4274 struct vop_pageout_args
/* {
4277 vm_offset_t a_pl_offset,
4280 struct ucred *a_cred,
4284 register struct vnode
*vp
= ap
->a_vp
;
4285 upl_t pl
= ap
->a_pl
;
4286 size_t size
= ap
->a_size
;
4287 off_t f_offset
= ap
->a_f_offset
;
4288 vm_offset_t pl_offset
= ap
->a_pl_offset
;
4289 int flags
= ap
->a_flags
;
4290 int ioflag
= ap
->a_flags
;
4291 register int biosize
;
4292 struct proc
*p
= current_proc();
4293 struct nfsnode
*np
= VTONFS(vp
);
4294 register struct ucred
*cred
;
4296 struct nfsmount
*nmp
= VFSTONFS(vp
->v_mount
);
4299 int n
= 0, on
, error
= 0, iomode
, must_commit
, s
;
4304 struct uio
* uio
= &auio
;
4305 int nocommit
= flags
& UPL_NOCOMMIT
;
4309 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 323)) | DBG_FUNC_NONE
,
4310 (int)f_offset
, size
, pl
, pl_offset
, 0);
4312 if (UBCINVALID(vp
)) {
4314 panic("nfs_pageout: invalid vnode");
4318 UBCINFOCHECK("nfs_pageout", vp
);
4323 if (pl
== (upl_t
)NULL
) {
4324 panic("nfs_pageout: no upl");
4328 * I use nm_rsize, not nm_wsize so that all buffer cache blocks
4329 * will be the same size within a filesystem. nfs_writerpc will
4330 * still use nm_wsize when sizing the rpc's.
4332 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, size
);
4334 if (biosize
& PAGE_MASK
)
4335 panic("nfs_pageout(%x): biosize not page aligned", biosize
);
4339 * Check to see whether the buffer is incore
4340 * If incore and not busy invalidate it from the cache
4341 * we should not find it BUSY, since we always do a
4342 * vm_fault_list_request in 'getblk' before returning
4343 * which would block on the page busy status
4345 lbn
= f_offset
/ PAGE_SIZE
; /* to match the size getblk uses */
4347 for (iosize
= size
; iosize
> 0; iosize
-= PAGE_SIZE
, lbn
++) {
4350 if (bp
= incore(vp
, lbn
)) {
4351 if (ISSET(bp
->b_flags
, B_BUSY
)) {
4352 /* don't panic incore. just tell vm we are busy */
4353 (void) kernel_upl_abort(pl
, NULL
);
4358 SET(bp
->b_flags
, (B_BUSY
| B_INVAL
));
4364 cred
= ubc_getcred(vp
);
4368 if (np
->n_flag
& NWRITEERR
) {
4369 np
->n_flag
&= ~NWRITEERR
;
4371 kernel_upl_abort_range(pl
, pl_offset
, size
,
4372 UPL_ABORT_FREE_ON_EMPTY
);
4373 return (np
->n_error
);
4375 if ((nmp
->nm_flag
& (NFSMNT_NFSV3
| NFSMNT_GOTFSINFO
)) == NFSMNT_NFSV3
)
4376 (void)nfs_fsinfo(nmp
, vp
, cred
, p
);
4378 if (f_offset
< 0 || f_offset
>= np
->n_size
||
4379 (f_offset
& PAGE_MASK_64
) || (size
& PAGE_MASK
)) {
4381 kernel_upl_abort_range(pl
, pl_offset
, size
,
4382 UPL_ABORT_FREE_ON_EMPTY
);
4386 kernel_upl_map(kernel_map
, pl
, &ioaddr
);
4388 if ((f_offset
+ size
) > np
->n_size
)
4389 iosize
= np
->n_size
- f_offset
;
4393 pgsize
= (iosize
+ (PAGE_SIZE
- 1)) & ~PAGE_MASK
;
4395 if (size
> pgsize
) {
4397 kernel_upl_abort_range(pl
, pl_offset
+ pgsize
, size
- pgsize
,
4398 UPL_ABORT_FREE_ON_EMPTY
);
4400 auio
.uio_iov
= &aiov
;
4401 auio
.uio_iovcnt
= 1;
4402 auio
.uio_offset
= f_offset
;
4403 auio
.uio_segflg
= UIO_SYSSPACE
;
4404 auio
.uio_rw
= UIO_READ
;
4405 auio
.uio_resid
= iosize
;
4406 auio
.uio_procp
= NULL
;
4408 aiov
.iov_len
= iosize
;
4409 aiov
.iov_base
= (caddr_t
)ioaddr
+ pl_offset
;
4412 * check for partial page and clear the
4413 * contents past end of the file before
4414 * releasing it in the VM page cache
4416 if ((f_offset
< np
->n_size
) && (f_offset
+ size
) > np
->n_size
) {
4417 size_t io
= np
->n_size
- f_offset
;
4419 bzero((caddr_t
)(ioaddr
+ pl_offset
+ io
), size
- io
);
4421 KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW
, 321)) | DBG_FUNC_NONE
,
4422 (int)np
->n_size
, (int)f_offset
, (int)f_offset
+ io
, size
- io
, 0);
4427 #warning nfs_pageout does not support NQNFS yet.
4428 #if 0 /* why bother? */
4429 /* NO RESOURCES TO FIX NQNFS CASE */
4430 /* We need to deal with this later -- Umesh */
4433 * Check for a valid write lease.
4435 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4436 NQNFS_CKINVALID(vp
, np
, ND_WRITE
)) {
4438 error
= nqnfs_getlease(vp
, ND_WRITE
, cred
, p
);
4439 } while (error
== NQNFS_EXPIRED
);
4441 kernel_upl_unmap(kernel_map
, pl
);
4443 kernel_upl_abort_range(pl
, pl_offset
, size
,
4444 UPL_ABORT_FREE_ON_EMPTY
);
4447 if (np
->n_lrev
!= np
->n_brev
||
4448 (np
->n_flag
& NQNFSNONCACHE
)) {
4449 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4451 kernel_upl_unmap(kernel_map
, pl
);
4453 kernel_upl_abort_range(pl
,
4455 UPL_ABORT_FREE_ON_EMPTY
);
4458 np
->n_brev
= np
->n_lrev
;
4461 #endif 0 /* why bother? */
4463 if ((np
->n_flag
& NQNFSNONCACHE
) && uio
->uio_iovcnt
== 1) {
4464 iomode
= NFSV3WRITE_FILESYNC
;
4465 error
= nfs_writerpc(vp
, uio
, cred
, &iomode
, &must_commit
);
4467 nfs_clearcommit(vp
->v_mount
);
4468 kernel_upl_unmap(kernel_map
, pl
);
4470 /* see comments below after other nfs_writerpc and ESTALE */
4471 if (error
== ESTALE
) {
4472 kernel_upl_abort_range(pl
, pl_offset
, size
,
4473 UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
);
4477 kernel_upl_abort_range(pl
, pl_offset
, size
,
4478 UPL_ABORT_FREE_ON_EMPTY
);
4480 kernel_upl_commit_range(pl
,
4482 UPL_COMMIT_CLEAR_DIRTY
| UPL_COMMIT_FREE_ON_EMPTY
,
4483 UPL_GET_INTERNAL_PAGE_LIST(pl
), MAX_UPL_TRANSFER
);
4488 nfsstats
.pageouts
++;
4489 lbn
= uio
->uio_offset
/ biosize
;
4490 on
= uio
->uio_offset
& (biosize
-1);
4491 n
= min((unsigned)(biosize
- on
), uio
->uio_resid
);
4495 if ((lbn
+ 1) * biosize
> np
->n_size
) {
4496 bufsize
= np
->n_size
- lbn
* biosize
;
4497 bufsize
= (bufsize
+ DEV_BSIZE
- 1) & ~(DEV_BSIZE
- 1);
4502 np
->n_flag
|= NMODIFIED
;
4504 #if 0 /* why bother? */
4505 /* NO RESOURCES TO FIX NQNFS CASE */
4506 /* We need to deal with this later -- Umesh */
4508 * Check for valid write lease and get one as required.
4509 * In case getblk() and/or bwrite() delayed us.
4511 if ((nmp
->nm_flag
& NFSMNT_NQNFS
) &&
4512 NQNFS_CKINVALID(vp
, np
, ND_WRITE
)) {
4514 error
= nqnfs_getlease(vp
, ND_WRITE
, cred
, p
);
4515 } while (error
== NQNFS_EXPIRED
);
4519 if (np
->n_lrev
!= np
->n_brev
||
4520 (np
->n_flag
& NQNFSNONCACHE
)) {
4521 error
= nfs_vinvalbuf(vp
, V_SAVE
, cred
, p
, 1);
4523 kernel_upl_unmap(kernel_map
, pl
);
4525 kernel_upl_abort_range(pl
,
4528 UPL_ABORT_FREE_ON_EMPTY
);
4532 np
->n_brev
= np
->n_lrev
;
4536 #endif 0 /* why bother? */
4538 iomode
= NFSV3WRITE_FILESYNC
;
4539 error
= nfs_writerpc(vp
, uio
, cred
, &iomode
, &must_commit
);
4541 nfs_clearcommit(vp
->v_mount
);
4548 uio
->uio_resid
-= n
;
4549 uio
->uio_offset
+= n
;
4550 uio
->uio_iov
->iov_base
+= n
;
4551 uio
->uio_iov
->iov_len
-= n
;
4553 } while (uio
->uio_resid
> 0 && n
> 0);
4556 kernel_upl_unmap(kernel_map
, pl
);
4558 * EStale is special. In this case, we want vm to dump out
4559 * the pages. Better yet, sever the object so we don't come
4560 * back here on each page of the object to page out. For now,
4562 * XXX What about !nocommit case? Should ESTALE only be checked
4563 * in that portion? - EKN
4565 if (error
== ESTALE
) {
4566 kernel_upl_abort_range(pl
, pl_offset
, size
,
4567 UPL_ABORT_DUMP_PAGES
|UPL_ABORT_FREE_ON_EMPTY
);
4571 kernel_upl_abort_range(pl
, pl_offset
, pgsize
,
4572 UPL_ABORT_FREE_ON_EMPTY
);
4574 kernel_upl_commit_range(pl
, pl_offset
, pgsize
,
4575 UPL_COMMIT_CLEAR_DIRTY
| UPL_COMMIT_FREE_ON_EMPTY
,
4576 UPL_GET_INTERNAL_PAGE_LIST(pl
), MAX_UPL_TRANSFER
);
4583 /* Blktooff derives file offset given a logical block number */
4586 struct vop_blktooff_args
/* {
4593 register struct vnode
*vp
= ap
->a_vp
;
4595 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4597 *ap
->a_offset
= (off_t
)(ap
->a_lblkno
* biosize
);
4602 /* Blktooff derives file offset given a logical block number */
4605 struct vop_offtoblk_args
/* {
4612 register struct vnode
*vp
= ap
->a_vp
;
4614 biosize
= min(vp
->v_mount
->mnt_stat
.f_iosize
, PAGE_SIZE
); /* nfs_bio.c */
4616 *ap
->a_lblkno
= (daddr_t
)(ap
->a_offset
/ biosize
);
4622 struct vop_cmap_args
/* {
4631 return (EOPNOTSUPP
);