Remove VOP_GETVOBJECT, VOP_DESTROYVOBJECT, and VOP_CREATEVOBJECT. Rearrange
[dragonfly.git] / sys / kern / vfs_default.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed
6 * to Berkeley by John Heidemann of the UCLA Ficus project.
7 *
8 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *
39 * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
7540ab49 40 * $DragonFly: src/sys/kern/vfs_default.c,v 1.31 2006/03/29 18:44:50 dillon Exp $
984263bc
MD
41 */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/buf.h>
46#include <sys/conf.h>
47#include <sys/kernel.h>
48#include <sys/lock.h>
49#include <sys/malloc.h>
50#include <sys/mount.h>
51#include <sys/unistd.h>
52#include <sys/vnode.h>
690a3127 53#include <sys/namei.h>
fad57d0e 54#include <sys/nlookup.h>
984263bc 55#include <sys/poll.h>
949ecb9b 56#include <sys/mountctl.h>
984263bc
MD
57
58#include <machine/limits.h>
59
60#include <vm/vm.h>
61#include <vm/vm_object.h>
62#include <vm/vm_page.h>
63#include <vm/vm_pager.h>
64#include <vm/vnode_pager.h>
65
e62afb5f 66static int vop_nolookup (struct vop_old_lookup_args *);
402ed7e1 67static int vop_nostrategy (struct vop_strategy_args *);
984263bc
MD
68
69/*
70 * This vnode table stores what we want to do if the filesystem doesn't
71 * implement a particular VOP.
72 *
73 * If there is no specific entry here, we will return EOPNOTSUPP.
984263bc 74 */
2d3e977e 75struct vop_ops *default_vnode_vops;
984263bc 76static struct vnodeopv_entry_desc default_vnodeop_entries[] = {
2d3e977e
MD
77 { &vop_default_desc, vop_eopnotsupp },
78 { &vop_advlock_desc, vop_einval },
79 { &vop_bwrite_desc, (void *) vop_stdbwrite },
80 { &vop_close_desc, vop_null },
2d3e977e 81 { &vop_fsync_desc, vop_null },
2d3e977e 82 { &vop_ioctl_desc, vop_enotty },
3446c007 83 { &vop_islocked_desc, (void *) vop_stdislocked },
3446c007 84 { &vop_lock_desc, (void *) vop_stdlock },
2d3e977e 85 { &vop_mmap_desc, vop_einval },
e62afb5f 86 { &vop_old_lookup_desc, (void *) vop_nolookup },
2d3e977e
MD
87 { &vop_open_desc, vop_null },
88 { &vop_pathconf_desc, vop_einval },
89 { &vop_poll_desc, (void *) vop_nopoll },
90 { &vop_readlink_desc, vop_einval },
91 { &vop_reallocblks_desc, vop_eopnotsupp },
92 { &vop_revoke_desc, (void *) vop_stdrevoke },
93 { &vop_strategy_desc, (void *) vop_nostrategy },
3446c007 94 { &vop_unlock_desc, (void *) vop_stdunlock },
2d3e977e
MD
95 { &vop_getacl_desc, vop_eopnotsupp },
96 { &vop_setacl_desc, vop_eopnotsupp },
97 { &vop_aclcheck_desc, vop_eopnotsupp },
98 { &vop_getextattr_desc, vop_eopnotsupp },
99 { &vop_setextattr_desc, vop_eopnotsupp },
fad57d0e
MD
100 { &vop_nresolve_desc, (void *) vop_compat_nresolve },
101 { &vop_nlookupdotdot_desc, (void *) vop_compat_nlookupdotdot },
102 { &vop_ncreate_desc, (void *) vop_compat_ncreate },
103 { &vop_nmkdir_desc, (void *) vop_compat_nmkdir },
104 { &vop_nmknod_desc, (void *) vop_compat_nmknod },
105 { &vop_nlink_desc, (void *) vop_compat_nlink },
106 { &vop_nsymlink_desc, (void *) vop_compat_nsymlink },
107 { &vop_nwhiteout_desc, (void *) vop_compat_nwhiteout },
108 { &vop_nremove_desc, (void *) vop_compat_nremove },
109 { &vop_nrmdir_desc, (void *) vop_compat_nrmdir },
110 { &vop_nrename_desc, (void *) vop_compat_nrename },
2281065e 111 { &vop_mountctl_desc, (void *) journal_mountctl },
984263bc
MD
112 { NULL, NULL }
113};
114
115static struct vnodeopv_desc default_vnodeop_opv_desc =
dc1be39c 116 { &default_vnode_vops, default_vnodeop_entries, 0 };
984263bc
MD
117
118VNODEOP_SET(default_vnodeop_opv_desc);
119
120int
121vop_eopnotsupp(struct vop_generic_args *ap)
122{
984263bc
MD
123 return (EOPNOTSUPP);
124}
125
126int
127vop_ebadf(struct vop_generic_args *ap)
128{
984263bc
MD
129 return (EBADF);
130}
131
132int
133vop_enotty(struct vop_generic_args *ap)
134{
984263bc
MD
135 return (ENOTTY);
136}
137
138int
139vop_einval(struct vop_generic_args *ap)
140{
984263bc
MD
141 return (EINVAL);
142}
143
144int
145vop_null(struct vop_generic_args *ap)
146{
984263bc
MD
147 return (0);
148}
149
150int
151vop_defaultop(struct vop_generic_args *ap)
152{
0961aa92 153 return (VOCALL(default_vnode_vops, ap));
984263bc
MD
154}
155
156int
157vop_panic(struct vop_generic_args *ap)
158{
159
160 panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name);
161}
162
690a3127 163/*
fad57d0e 164 * vop_compat_resolve { struct namecache *a_ncp } XXX STOPGAP FUNCTION
690a3127 165 *
21739618
MD
166 * XXX OLD API ROUTINE! WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
167 * WILL BE REMOVED. This procedure exists for all VFSs which have not
fad57d0e 168 * yet implemented VOP_NRESOLVE(). It converts VOP_NRESOLVE() into a
e62afb5f 169 * vop_old_lookup() and does appropriate translations.
21739618 170 *
690a3127
MD
171 * Resolve a ncp for VFSs which do not support the VOP. Eventually all
172 * VFSs will support this VOP and this routine can be removed, since
fad57d0e 173 * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
690a3127
MD
174 * API.
175 *
21739618
MD
176 * A locked ncp is passed in to be resolved. The NCP is resolved by
177 * figuring out the vnode (if any) and calling cache_setvp() to attach the
178 * vnode to the entry. If the entry represents a non-existant node then
179 * cache_setvp() is called with a NULL vnode to resolve the entry into a
180 * negative cache entry. No vnode locks are retained and the
690a3127 181 * ncp is left locked on return.
8e005a45 182 *
fad57d0e
MD
183 * The ncp will NEVER represent "", "." or "..", or contain any slashes.
184 *
8e005a45
MD
185 * There is a potential directory and vnode interlock. The lock order
186 * requirement is: namecache, governing directory, resolved vnode.
690a3127 187 */
417215fe 188int
fad57d0e 189vop_compat_nresolve(struct vop_nresolve_args *ap)
690a3127
MD
190{
191 int error;
192 struct vnode *dvp;
193 struct vnode *vp;
194 struct namecache *ncp;
195 struct componentname cnp;
196
197 ncp = ap->a_ncp; /* locked namecache node */
21739618
MD
198 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
199 return(EPERM);
690a3127
MD
200 if (ncp->nc_parent == NULL)
201 return(EPERM);
202 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
203 return(EPERM);
8c361dda 204
fad57d0e
MD
205 /*
206 * UFS currently stores all sorts of side effects, including a loop
207 * variable, in the directory inode. That needs to be fixed and the
208 * other VFS's audited before we can switch to LK_SHARED.
209 */
5fd012e0 210 if ((error = vget(dvp, LK_EXCLUSIVE, curthread)) != 0) {
fad57d0e
MD
211 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
212 ncp, ncp->nc_name);
67773eb3
MD
213 return(EAGAIN);
214 }
690a3127
MD
215
216 bzero(&cnp, sizeof(cnp));
217 cnp.cn_nameiop = NAMEI_LOOKUP;
fad57d0e 218 cnp.cn_flags = 0;
690a3127
MD
219 cnp.cn_nameptr = ncp->nc_name;
220 cnp.cn_namelen = ncp->nc_nlen;
21739618
MD
221 cnp.cn_cred = ap->a_cred;
222 cnp.cn_td = curthread; /* XXX */
223
224 /*
e62afb5f 225 * vop_old_lookup() always returns vp locked. dvp may or may not be
21739618
MD
226 * left locked depending on CNP_PDIRUNLOCK.
227 */
e62afb5f 228 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
8c361dda 229 if (error == 0)
5fd012e0 230 VOP_UNLOCK(vp, 0, curthread);
8c361dda 231 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
5fd012e0 232 VOP_UNLOCK(dvp, 0, curthread);
8c361dda
MD
233 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
234 /* was resolved by another process while we were unlocked */
235 if (error == 0)
236 vrele(vp);
237 } else if (error == 0) {
690a3127
MD
238 KKASSERT(vp != NULL);
239 cache_setvp(ncp, vp);
8c361dda 240 vrele(vp);
690a3127
MD
241 } else if (error == ENOENT) {
242 KKASSERT(vp == NULL);
243 if (cnp.cn_flags & CNP_ISWHITEOUT)
244 ncp->nc_flag |= NCF_WHITEOUT;
245 cache_setvp(ncp, NULL);
246 }
8c361dda 247 vrele(dvp);
21739618 248 return (error);
690a3127
MD
249}
250
fad57d0e
MD
251/*
252 * vop_compat_nlookupdotdot { struct vnode *a_dvp,
253 * struct vnode **a_vpp,
254 * struct ucred *a_cred }
255 *
256 * Lookup the vnode representing the parent directory of the specified
257 * directory vnode. a_dvp should not be locked. If no error occurs *a_vpp
258 * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
259 *
260 * This function is designed to aid NFS server-side operations and is
261 * used by cache_fromdvp() to create a consistent, connected namecache
262 * topology.
263 *
264 * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
265 * code out from their *_lookup() and create *_nlookupdotdot(). Then as time
266 * permits VFSs will implement the remaining *_n*() calls and finally get
267 * rid of their *_lookup() call.
268 */
269int
270vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
271{
272 struct componentname cnp;
273 int error;
274
275 /*
276 * UFS currently stores all sorts of side effects, including a loop
277 * variable, in the directory inode. That needs to be fixed and the
278 * other VFS's audited before we can switch to LK_SHARED.
279 */
280 *ap->a_vpp = NULL;
281 if ((error = vget(ap->a_dvp, LK_EXCLUSIVE, curthread)) != 0)
282 return (error);
283 if (ap->a_dvp->v_type != VDIR) {
284 vput(ap->a_dvp);
285 return (ENOTDIR);
286 }
287
288 bzero(&cnp, sizeof(cnp));
289 cnp.cn_nameiop = NAMEI_LOOKUP;
290 cnp.cn_flags = CNP_ISDOTDOT;
291 cnp.cn_nameptr = "..";
292 cnp.cn_namelen = 2;
293 cnp.cn_cred = ap->a_cred;
294 cnp.cn_td = curthread; /* XXX */
295
296 /*
e62afb5f 297 * vop_old_lookup() always returns vp locked. dvp may or may not be
fad57d0e
MD
298 * left locked depending on CNP_PDIRUNLOCK.
299 */
e62afb5f 300 error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
fad57d0e
MD
301 if (error == 0)
302 VOP_UNLOCK(*ap->a_vpp, 0, curthread);
303 if (cnp.cn_flags & CNP_PDIRUNLOCK)
304 vrele(ap->a_dvp);
305 else
306 vput(ap->a_dvp);
307 return (error);
308}
21739618
MD
309
310/*
fad57d0e
MD
311 * vop_compat_ncreate { struct namecache *a_ncp, XXX STOPGAP FUNCTION
312 * struct vnode *a_vpp,
313 * struct ucred *a_cred,
314 * struct vattr *a_vap }
21739618 315 *
fad57d0e
MD
316 * Create a file as specified by a_vap. Compatibility requires us to issue
317 * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
318 * to setup the directory inode's i_offset and i_count (e.g. in UFS).
319 */
320int
321vop_compat_ncreate(struct vop_ncreate_args *ap)
322{
323 struct thread *td = curthread;
324 struct componentname cnp;
325 struct namecache *ncp;
326 struct vnode *dvp;
327 int error;
328
329 /*
330 * Sanity checks, get a locked directory vnode.
331 */
332 ncp = ap->a_ncp; /* locked namecache node */
333 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
334 return(EPERM);
335 if (ncp->nc_parent == NULL)
336 return(EPERM);
337 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
338 return(EPERM);
339
340 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
341 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
342 ncp, ncp->nc_name);
343 return(EAGAIN);
344 }
345
346 /*
e62afb5f 347 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
348 * caches all information required to create the entry in the
349 * directory inode. We expect a return code of EJUSTRETURN for
350 * the CREATE case. The cnp must simulated a saved-name situation.
351 */
352 bzero(&cnp, sizeof(cnp));
353 cnp.cn_nameiop = NAMEI_CREATE;
354 cnp.cn_flags = CNP_LOCKPARENT;
355 cnp.cn_nameptr = ncp->nc_name;
356 cnp.cn_namelen = ncp->nc_nlen;
357 cnp.cn_cred = ap->a_cred;
358 cnp.cn_td = td;
359 *ap->a_vpp = NULL;
360
e62afb5f 361 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
fad57d0e
MD
362
363 /*
364 * EJUSTRETURN should be returned for this case, which means that
365 * the VFS has setup the directory inode for the create. The dvp we
366 * passed in is expected to remain in a locked state.
367 *
368 * If the VOP_OLD_CREATE is successful we are responsible for updating
369 * the cache state of the locked ncp that was passed to us.
370 */
371 if (error == EJUSTRETURN) {
372 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
373 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
374 if (error == 0) {
375 cache_setunresolved(ncp);
376 cache_setvp(ncp, *ap->a_vpp);
377 }
378 } else {
379 if (error == 0) {
380 vput(*ap->a_vpp);
381 *ap->a_vpp = NULL;
382 error = EEXIST;
383 }
384 KKASSERT(*ap->a_vpp == NULL);
385 }
386 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
387 VOP_UNLOCK(dvp, 0, td);
388 vrele(dvp);
389 return (error);
390}
391
392/*
393 * vop_compat_nmkdir { struct namecache *a_ncp, XXX STOPGAP FUNCTION
394 * struct vnode *a_vpp,
395 * struct ucred *a_cred,
396 * struct vattr *a_vap }
21739618 397 *
fad57d0e
MD
398 * Create a directory as specified by a_vap. Compatibility requires us to
399 * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
400 * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
21739618 401 */
fad57d0e
MD
402int
403vop_compat_nmkdir(struct vop_nmkdir_args *ap)
404{
405 struct thread *td = curthread;
406 struct componentname cnp;
407 struct namecache *ncp;
408 struct vnode *dvp;
409 int error;
410
411 /*
412 * Sanity checks, get a locked directory vnode.
413 */
414 ncp = ap->a_ncp; /* locked namecache node */
415 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
416 return(EPERM);
417 if (ncp->nc_parent == NULL)
418 return(EPERM);
419 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
420 return(EPERM);
421
422 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
423 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
424 ncp, ncp->nc_name);
425 return(EAGAIN);
426 }
427
428 /*
e62afb5f 429 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
430 * caches all information required to create the entry in the
431 * directory inode. We expect a return code of EJUSTRETURN for
432 * the CREATE case. The cnp must simulated a saved-name situation.
433 */
434 bzero(&cnp, sizeof(cnp));
435 cnp.cn_nameiop = NAMEI_CREATE;
436 cnp.cn_flags = CNP_LOCKPARENT;
437 cnp.cn_nameptr = ncp->nc_name;
438 cnp.cn_namelen = ncp->nc_nlen;
439 cnp.cn_cred = ap->a_cred;
440 cnp.cn_td = td;
441 *ap->a_vpp = NULL;
442
e62afb5f 443 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
fad57d0e
MD
444
445 /*
446 * EJUSTRETURN should be returned for this case, which means that
447 * the VFS has setup the directory inode for the create. The dvp we
448 * passed in is expected to remain in a locked state.
449 *
450 * If the VOP_OLD_MKDIR is successful we are responsible for updating
451 * the cache state of the locked ncp that was passed to us.
452 */
453 if (error == EJUSTRETURN) {
454 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
455 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
456 if (error == 0) {
457 cache_setunresolved(ncp);
458 cache_setvp(ncp, *ap->a_vpp);
459 }
460 } else {
461 if (error == 0) {
462 vput(*ap->a_vpp);
463 *ap->a_vpp = NULL;
464 error = EEXIST;
465 }
466 KKASSERT(*ap->a_vpp == NULL);
467 }
468 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
469 VOP_UNLOCK(dvp, 0, td);
470 vrele(dvp);
471 return (error);
472}
473
474/*
475 * vop_compat_nmknod { struct namecache *a_ncp, XXX STOPGAP FUNCTION
476 * struct vnode *a_vpp,
477 * struct ucred *a_cred,
478 * struct vattr *a_vap }
479 *
480 * Create a device or fifo node as specified by a_vap. Compatibility requires
481 * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD
482 * in order to setup the directory inode's i_offset and i_count (e.g. in UFS).
483 */
484int
485vop_compat_nmknod(struct vop_nmknod_args *ap)
486{
487 struct thread *td = curthread;
488 struct componentname cnp;
489 struct namecache *ncp;
490 struct vnode *dvp;
491 int error;
492
493 /*
494 * Sanity checks, get a locked directory vnode.
495 */
496 ncp = ap->a_ncp; /* locked namecache node */
497 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
498 return(EPERM);
499 if (ncp->nc_parent == NULL)
500 return(EPERM);
501 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
502 return(EPERM);
503
504 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
505 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
506 ncp, ncp->nc_name);
507 return(EAGAIN);
508 }
509
510 /*
e62afb5f 511 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
512 * caches all information required to create the entry in the
513 * directory inode. We expect a return code of EJUSTRETURN for
514 * the CREATE case. The cnp must simulated a saved-name situation.
515 */
516 bzero(&cnp, sizeof(cnp));
517 cnp.cn_nameiop = NAMEI_CREATE;
518 cnp.cn_flags = CNP_LOCKPARENT;
519 cnp.cn_nameptr = ncp->nc_name;
520 cnp.cn_namelen = ncp->nc_nlen;
521 cnp.cn_cred = ap->a_cred;
522 cnp.cn_td = td;
523 *ap->a_vpp = NULL;
524
e62afb5f 525 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
fad57d0e
MD
526
527 /*
528 * EJUSTRETURN should be returned for this case, which means that
529 * the VFS has setup the directory inode for the create. The dvp we
530 * passed in is expected to remain in a locked state.
531 *
532 * If the VOP_OLD_MKNOD is successful we are responsible for updating
533 * the cache state of the locked ncp that was passed to us.
534 */
535 if (error == EJUSTRETURN) {
536 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
537 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
538 if (error == 0) {
539 cache_setunresolved(ncp);
540 cache_setvp(ncp, *ap->a_vpp);
541 }
542 } else {
543 if (error == 0) {
544 vput(*ap->a_vpp);
545 *ap->a_vpp = NULL;
546 error = EEXIST;
547 }
548 KKASSERT(*ap->a_vpp == NULL);
549 }
550 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
551 VOP_UNLOCK(dvp, 0, td);
552 vrele(dvp);
553 return (error);
554}
555
556/*
557 * vop_compat_nlink { struct namecache *a_ncp, XXX STOPGAP FUNCTION
558 * struct vnode *a_vp,
559 * struct ucred *a_cred }
560 *
561 * The passed vp is locked and represents the source. The passed ncp is
562 * locked and represents the target to create.
563 */
564int
565vop_compat_nlink(struct vop_nlink_args *ap)
566{
567 struct thread *td = curthread;
568 struct componentname cnp;
569 struct namecache *ncp;
570 struct vnode *dvp;
571 struct vnode *tvp;
572 int error;
573
574 /*
575 * Sanity checks, get a locked directory vnode.
576 */
577 ncp = ap->a_ncp; /* locked namecache node */
578 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
579 return(EPERM);
580 if (ncp->nc_parent == NULL)
581 return(EPERM);
582 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
583 return(EPERM);
584
585 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
586 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
587 ncp, ncp->nc_name);
588 return(EAGAIN);
589 }
590
591 /*
e62afb5f 592 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
593 * caches all information required to create the entry in the
594 * directory inode. We expect a return code of EJUSTRETURN for
595 * the CREATE case. The cnp must simulated a saved-name situation.
596 */
597 bzero(&cnp, sizeof(cnp));
598 cnp.cn_nameiop = NAMEI_CREATE;
599 cnp.cn_flags = CNP_LOCKPARENT;
600 cnp.cn_nameptr = ncp->nc_name;
601 cnp.cn_namelen = ncp->nc_nlen;
602 cnp.cn_cred = ap->a_cred;
603 cnp.cn_td = td;
604
605 tvp = NULL;
e62afb5f 606 error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
fad57d0e
MD
607
608 /*
609 * EJUSTRETURN should be returned for this case, which means that
610 * the VFS has setup the directory inode for the create. The dvp we
611 * passed in is expected to remain in a locked state.
612 *
613 * If the VOP_OLD_LINK is successful we are responsible for updating
614 * the cache state of the locked ncp that was passed to us.
615 */
616 if (error == EJUSTRETURN) {
617 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
618 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
619 if (error == 0) {
620 cache_setunresolved(ncp);
621 cache_setvp(ncp, ap->a_vp);
622 }
623 } else {
624 if (error == 0) {
625 vput(tvp);
626 error = EEXIST;
627 }
628 }
629 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
630 VOP_UNLOCK(dvp, 0, td);
631 vrele(dvp);
632 return (error);
633}
634
635int
636vop_compat_nsymlink(struct vop_nsymlink_args *ap)
637{
638 struct thread *td = curthread;
639 struct componentname cnp;
640 struct namecache *ncp;
641 struct vnode *dvp;
642 struct vnode *vp;
643 int error;
644
645 /*
646 * Sanity checks, get a locked directory vnode.
647 */
648 *ap->a_vpp = NULL;
649 ncp = ap->a_ncp; /* locked namecache node */
650 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
651 return(EPERM);
652 if (ncp->nc_parent == NULL)
653 return(EPERM);
654 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
655 return(EPERM);
656
657 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
658 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
659 ncp, ncp->nc_name);
660 return(EAGAIN);
661 }
662
663 /*
e62afb5f 664 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
665 * caches all information required to create the entry in the
666 * directory inode. We expect a return code of EJUSTRETURN for
667 * the CREATE case. The cnp must simulated a saved-name situation.
668 */
669 bzero(&cnp, sizeof(cnp));
670 cnp.cn_nameiop = NAMEI_CREATE;
671 cnp.cn_flags = CNP_LOCKPARENT;
672 cnp.cn_nameptr = ncp->nc_name;
673 cnp.cn_namelen = ncp->nc_nlen;
674 cnp.cn_cred = ap->a_cred;
675 cnp.cn_td = td;
676
677 vp = NULL;
e62afb5f 678 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
679
680 /*
681 * EJUSTRETURN should be returned for this case, which means that
682 * the VFS has setup the directory inode for the create. The dvp we
683 * passed in is expected to remain in a locked state.
684 *
685 * If the VOP_OLD_SYMLINK is successful we are responsible for updating
686 * the cache state of the locked ncp that was passed to us.
687 */
688 if (error == EJUSTRETURN) {
689 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
690 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
691 if (error == 0) {
692 cache_setunresolved(ncp);
693 cache_setvp(ncp, vp);
694 *ap->a_vpp = vp;
695 }
696 } else {
697 if (error == 0) {
698 vput(vp);
699 vp = NULL;
700 error = EEXIST;
701 }
702 KKASSERT(vp == NULL);
703 }
704 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
705 VOP_UNLOCK(dvp, 0, td);
706 vrele(dvp);
707 return (error);
708}
709
710/*
711 * vop_compat_nwhiteout { struct namecache *a_ncp, XXX STOPGAP FUNCTION
712 * struct ucred *a_cred,
713 * int a_flags }
714 *
715 * Issie a whiteout operation (create, lookup, or delete). Compatibility
716 * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue
717 * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
718 * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops. For NAMEI_LOOKUP
719 * no lookup is necessary.
720 */
721int
722vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
21739618 723{
fad57d0e
MD
724 struct thread *td = curthread;
725 struct componentname cnp;
726 struct namecache *ncp;
727 struct vnode *dvp;
21739618 728 struct vnode *vp;
21739618
MD
729 int error;
730
fad57d0e
MD
731 /*
732 * Sanity checks, get a locked directory vnode.
733 */
734 ncp = ap->a_ncp; /* locked namecache node */
735 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
736 return(EPERM);
737 if (ncp->nc_parent == NULL)
738 return(EPERM);
739 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
740 return(EPERM);
21739618 741
fad57d0e
MD
742 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
743 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
744 ncp, ncp->nc_name);
745 return(EAGAIN);
21739618 746 }
21739618
MD
747
748 /*
e62afb5f 749 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
750 * caches all information required to create the entry in the
751 * directory inode. We expect a return code of EJUSTRETURN for
752 * the CREATE case. The cnp must simulated a saved-name situation.
753 */
754 bzero(&cnp, sizeof(cnp));
755 cnp.cn_nameiop = ap->a_flags;
756 cnp.cn_flags = CNP_LOCKPARENT;
757 cnp.cn_nameptr = ncp->nc_name;
758 cnp.cn_namelen = ncp->nc_nlen;
759 cnp.cn_cred = ap->a_cred;
760 cnp.cn_td = td;
761
762 vp = NULL;
763
764 /*
765 * EJUSTRETURN should be returned for the CREATE or DELETE cases.
766 * The VFS has setup the directory inode for the create. The dvp we
767 * passed in is expected to remain in a locked state.
768 *
769 * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
770 * the cache state of the locked ncp that was passed to us.
771 */
772 switch(ap->a_flags) {
773 case NAMEI_DELETE:
774 cnp.cn_flags |= CNP_DOWHITEOUT;
775 /* fall through */
776 case NAMEI_CREATE:
e62afb5f 777 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
778 if (error == EJUSTRETURN) {
779 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
780 error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
781 if (error == 0)
782 cache_setunresolved(ncp);
783 } else {
784 if (error == 0) {
785 vput(vp);
786 vp = NULL;
787 error = EEXIST;
788 }
789 KKASSERT(vp == NULL);
790 }
791 break;
792 case NAMEI_LOOKUP:
793 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
794 break;
795 default:
796 error = EINVAL;
797 break;
798 }
799 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
800 VOP_UNLOCK(dvp, 0, td);
801 vrele(dvp);
802 return (error);
803}
804
805
806/*
807 * vop_compat_nremove { struct namecache *a_ncp, XXX STOPGAP FUNCTION
808 * struct ucred *a_cred }
809 */
810int
811vop_compat_nremove(struct vop_nremove_args *ap)
812{
813 struct thread *td = curthread;
814 struct componentname cnp;
815 struct namecache *ncp;
816 struct vnode *dvp;
817 struct vnode *vp;
818 int error;
819
820 /*
821 * Sanity checks, get a locked directory vnode.
822 */
823 ncp = ap->a_ncp; /* locked namecache node */
824 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
825 return(EPERM);
826 if (ncp->nc_parent == NULL)
827 return(EPERM);
828 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
829 return(EPERM);
830
831 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
832 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
833 ncp, ncp->nc_name);
834 return(EAGAIN);
835 }
836
837 /*
e62afb5f 838 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
839 * caches all information required to delete the entry in the
840 * directory inode. We expect a return code of 0 for the DELETE
841 * case (meaning that a vp has been found). The cnp must simulated
842 * a saved-name situation.
843 */
844 bzero(&cnp, sizeof(cnp));
845 cnp.cn_nameiop = NAMEI_DELETE;
846 cnp.cn_flags = CNP_LOCKPARENT;
847 cnp.cn_nameptr = ncp->nc_name;
848 cnp.cn_namelen = ncp->nc_nlen;
849 cnp.cn_cred = ap->a_cred;
850 cnp.cn_td = td;
851
852 /*
853 * The vnode must be a directory and must not represent the
854 * current directory.
21739618 855 */
fad57d0e 856 vp = NULL;
e62afb5f 857 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
858 if (error == 0 && vp->v_type == VDIR)
859 error = EPERM;
b8997912 860 if (error == 0) {
fad57d0e 861 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
862 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
863 if (error == 0) {
864 cache_setunresolved(ncp);
865 cache_setvp(ncp, NULL);
866 }
b8997912 867 }
fad57d0e
MD
868 if (vp) {
869 if (dvp == vp)
870 vrele(vp);
871 else
872 vput(vp);
873 }
874 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
875 VOP_UNLOCK(dvp, 0, td);
876 vrele(dvp);
877 return (error);
21739618
MD
878}
879
fad57d0e
MD
880/*
881 * vop_compat_nrmdir { struct namecache *a_ncp, XXX STOPGAP FUNCTION
882 * struct ucred *a_cred }
883 */
884int
885vop_compat_nrmdir(struct vop_nrmdir_args *ap)
886{
887 struct thread *td = curthread;
888 struct componentname cnp;
889 struct namecache *ncp;
890 struct vnode *dvp;
891 struct vnode *vp;
892 int error;
21739618 893
fad57d0e
MD
894 /*
895 * Sanity checks, get a locked directory vnode.
896 */
897 ncp = ap->a_ncp; /* locked namecache node */
898 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
899 return(EPERM);
900 if (ncp->nc_parent == NULL)
901 return(EPERM);
902 if ((dvp = ncp->nc_parent->nc_vp) == NULL)
903 return(EPERM);
904
905 if ((error = vget(dvp, LK_EXCLUSIVE, td)) != 0) {
906 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
907 ncp, ncp->nc_name);
908 return(EAGAIN);
909 }
910
911 /*
e62afb5f 912 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
913 * caches all information required to delete the entry in the
914 * directory inode. We expect a return code of 0 for the DELETE
915 * case (meaning that a vp has been found). The cnp must simulated
916 * a saved-name situation.
917 */
918 bzero(&cnp, sizeof(cnp));
919 cnp.cn_nameiop = NAMEI_DELETE;
920 cnp.cn_flags = CNP_LOCKPARENT;
921 cnp.cn_nameptr = ncp->nc_name;
922 cnp.cn_namelen = ncp->nc_nlen;
923 cnp.cn_cred = ap->a_cred;
924 cnp.cn_td = td;
925
926 /*
927 * The vnode must be a directory and must not represent the
928 * current directory.
929 */
930 vp = NULL;
e62afb5f 931 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
932 if (error == 0 && vp->v_type != VDIR)
933 error = ENOTDIR;
934 if (error == 0 && vp == dvp)
935 error = EINVAL;
936 if (error == 0 && (vp->v_flag & VROOT))
937 error = EBUSY;
938 if (error == 0) {
939 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
940 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
941
942 /*
943 * Note that this invalidation will cause any process
944 * currently CD'd into the directory being removed to be
945 * disconnected from the topology and not be able to ".."
946 * back out.
947 */
948 if (error == 0)
e09206ba 949 cache_inval(ncp, CINV_DESTROY);
fad57d0e
MD
950 }
951 if (vp) {
952 if (dvp == vp)
953 vrele(vp);
954 else
955 vput(vp);
956 }
957 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
958 VOP_UNLOCK(dvp, 0, td);
959 vrele(dvp);
960 return (error);
961}
962
963/*
964 * vop_compat_nrename { struct namecache *a_fncp, XXX STOPGAP FUNCTION
965 * struct namecache *a_tncp,
966 * struct ucred *a_cred }
967 *
968 * This is a fairly difficult procedure. The old VOP_OLD_RENAME requires that
969 * the source directory and vnode be unlocked and the target directory and
970 * vnode (if it exists) be locked. All arguments will be vrele'd and
971 * the targets will also be unlocked regardless of the return code.
972 */
973int
974vop_compat_nrename(struct vop_nrename_args *ap)
975{
976 struct thread *td = curthread;
977 struct componentname fcnp;
978 struct componentname tcnp;
979 struct namecache *fncp;
980 struct namecache *tncp;
981 struct vnode *fdvp, *fvp;
982 struct vnode *tdvp, *tvp;
983 int error;
984
985 /*
986 * Sanity checks, get referenced vnodes representing the source.
987 */
988 fncp = ap->a_fncp; /* locked namecache node */
989 if (fncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
990 return(EPERM);
991 if (fncp->nc_parent == NULL)
992 return(EPERM);
993 if ((fdvp = fncp->nc_parent->nc_vp) == NULL)
994 return(EPERM);
995
996 /*
997 * Temporarily lock the source directory and lookup in DELETE mode to
998 * check permissions. XXX delete permissions should have been
999 * checked by nlookup(), we need to add NLC_DELETE for delete
1000 * checking. It is unclear whether VFS's require the directory setup
1001 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
1002 * since it isn't locked and since UFS always does a relookup of
1003 * the source, it is believed that the only side effect that matters
1004 * is the permissions check.
1005 */
1006 if ((error = vget(fdvp, LK_EXCLUSIVE, td)) != 0) {
1007 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1008 fncp, fncp->nc_name);
1009 return(EAGAIN);
1010 }
1011
1012 bzero(&fcnp, sizeof(fcnp));
1013 fcnp.cn_nameiop = NAMEI_DELETE;
1014 fcnp.cn_flags = CNP_LOCKPARENT;
1015 fcnp.cn_nameptr = fncp->nc_name;
1016 fcnp.cn_namelen = fncp->nc_nlen;
1017 fcnp.cn_cred = ap->a_cred;
1018 fcnp.cn_td = td;
1019
1020 /*
e62afb5f 1021 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
fad57d0e
MD
1022 * fvp.
1023 */
1024 fvp = NULL;
e62afb5f 1025 error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
fad57d0e 1026 if (error == 0 && (fvp->v_flag & VROOT)) {
e62afb5f 1027 vput(fvp); /* as if vop_old_lookup had failed */
fad57d0e
MD
1028 error = EBUSY;
1029 }
1030 if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1031 fcnp.cn_flags |= CNP_PDIRUNLOCK;
1032 VOP_UNLOCK(fdvp, 0, td);
1033 }
1034 if (error) {
1035 vrele(fdvp);
1036 return (error);
1037 }
1038 VOP_UNLOCK(fvp, 0, td);
1039
1040 /*
1041 * fdvp and fvp are now referenced and unlocked.
1042 *
1043 * Get a locked directory vnode for the target and lookup the target
1044 * in CREATE mode so it places the required information in the
1045 * directory inode.
1046 */
1047 tncp = ap->a_tncp; /* locked namecache node */
1048 if (tncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */
1049 error = EPERM;
1050 if (tncp->nc_parent == NULL)
1051 error = EPERM;
1052 if ((tdvp = tncp->nc_parent->nc_vp) == NULL)
1053 error = EPERM;
1054 if (error) {
1055 vrele(fdvp);
1056 vrele(fvp);
1057 return (error);
1058 }
1059 if ((error = vget(tdvp, LK_EXCLUSIVE, td)) != 0) {
1060 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
1061 tncp, tncp->nc_name);
1062 vrele(fdvp);
1063 vrele(fvp);
1064 return(EAGAIN);
1065 }
1066
1067 /*
e62afb5f 1068 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
1069 * caches all information required to create the entry in the
1070 * target directory inode.
1071 */
1072 bzero(&tcnp, sizeof(tcnp));
1073 tcnp.cn_nameiop = NAMEI_RENAME;
1074 tcnp.cn_flags = CNP_LOCKPARENT;
1075 tcnp.cn_nameptr = tncp->nc_name;
1076 tcnp.cn_namelen = tncp->nc_nlen;
1077 tcnp.cn_cred = ap->a_cred;
1078 tcnp.cn_td = td;
1079
1080 tvp = NULL;
e62afb5f 1081 error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
fad57d0e
MD
1082
1083 if (error == EJUSTRETURN) {
1084 /*
1085 * Target does not exist. tvp should be NULL.
1086 */
1087 KKASSERT(tvp == NULL);
1088 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1089 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1090 if (error == 0) {
1091 cache_rename(fncp, tncp);
1092 cache_setvp(tncp, fvp);
1093 }
1094 } else if (error == 0) {
1095 /*
1096 * Target exists. VOP_OLD_RENAME should correctly delete the
1097 * target.
1098 */
1099 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1100 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
1101 if (error == 0) {
1102 cache_rename(fncp, tncp);
1103 cache_setvp(tncp, fvp);
1104 }
1105 } else {
1106 vrele(fdvp);
1107 vrele(fvp);
1108 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1109 vrele(tdvp);
1110 else
1111 vput(tdvp);
1112 }
1113 return (error);
1114}
21739618 1115
984263bc
MD
1116static int
1117vop_nolookup(ap)
e62afb5f 1118 struct vop_old_lookup_args /* {
984263bc
MD
1119 struct vnode *a_dvp;
1120 struct vnode **a_vpp;
1121 struct componentname *a_cnp;
1122 } */ *ap;
1123{
1124
1125 *ap->a_vpp = NULL;
1126 return (ENOTDIR);
1127}
1128
1129/*
1130 * vop_nostrategy:
1131 *
1132 * Strategy routine for VFS devices that have none.
1133 *
1134 * B_ERROR and B_INVAL must be cleared prior to calling any strategy
1135 * routine. Typically this is done for a B_READ strategy call. Typically
1136 * B_INVAL is assumed to already be clear prior to a write and should not
1137 * be cleared manually unless you just made the buffer invalid. B_ERROR
1138 * should be cleared either way.
1139 */
1140
1141static int
1142vop_nostrategy (struct vop_strategy_args *ap)
1143{
81b5c339 1144 printf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
984263bc 1145 vprint("", ap->a_vp);
81b5c339
MD
1146 vprint("", ap->a_bio->bio_buf->b_vp);
1147 ap->a_bio->bio_buf->b_flags |= B_ERROR;
1148 ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1149 biodone(ap->a_bio);
984263bc
MD
1150 return (EOPNOTSUPP);
1151}
1152
1153int
1154vop_stdpathconf(ap)
1155 struct vop_pathconf_args /* {
1156 struct vnode *a_vp;
1157 int a_name;
1158 int *a_retval;
1159 } */ *ap;
1160{
1161
1162 switch (ap->a_name) {
1163 case _PC_LINK_MAX:
1164 *ap->a_retval = LINK_MAX;
1165 return (0);
1166 case _PC_MAX_CANON:
1167 *ap->a_retval = MAX_CANON;
1168 return (0);
1169 case _PC_MAX_INPUT:
1170 *ap->a_retval = MAX_INPUT;
1171 return (0);
1172 case _PC_PIPE_BUF:
1173 *ap->a_retval = PIPE_BUF;
1174 return (0);
1175 case _PC_CHOWN_RESTRICTED:
1176 *ap->a_retval = 1;
1177 return (0);
1178 case _PC_VDISABLE:
1179 *ap->a_retval = _POSIX_VDISABLE;
1180 return (0);
1181 default:
1182 return (EINVAL);
1183 }
1184 /* NOTREACHED */
1185}
1186
1187/*
3446c007
MD
1188 * Standard lock. The lock is recursive-capable only if the lock was
1189 * initialized with LK_CANRECURSE or that flag is passed in a_flags.
984263bc
MD
1190 */
1191int
1192vop_stdlock(ap)
1193 struct vop_lock_args /* {
1194 struct vnode *a_vp;
1195 int a_flags;
1196 struct proc *a_p;
1197 } */ *ap;
1198{
3446c007 1199 int error;
984263bc
MD
1200
1201#ifndef DEBUG_LOCKS
5fd012e0 1202 error = lockmgr(&ap->a_vp->v_lock, ap->a_flags, NULL, ap->a_td);
984263bc 1203#else
3446c007 1204 error = debuglockmgr(&ap->a_vp->v_lock, ap->a_flags,
5fd012e0 1205 NULL, ap->a_td,
3446c007 1206 "vop_stdlock", ap->a_vp->filename, ap->a_vp->line);
984263bc 1207#endif
3446c007 1208 return(error);
984263bc
MD
1209}
1210
1211int
1212vop_stdunlock(ap)
1213 struct vop_unlock_args /* {
1214 struct vnode *a_vp;
1215 int a_flags;
dadab5e9 1216 struct thread *a_td;
984263bc
MD
1217 } */ *ap;
1218{
3446c007 1219 int error;
984263bc 1220
3446c007 1221 error = lockmgr(&ap->a_vp->v_lock, ap->a_flags | LK_RELEASE,
5fd012e0 1222 NULL, ap->a_td);
3446c007 1223 return(error);
984263bc
MD
1224}
1225
1226int
1227vop_stdislocked(ap)
1228 struct vop_islocked_args /* {
1229 struct vnode *a_vp;
dadab5e9 1230 struct thread *a_td;
984263bc
MD
1231 } */ *ap;
1232{
3446c007 1233 return (lockstatus(&ap->a_vp->v_lock, ap->a_td));
984263bc
MD
1234}
1235
1236/*
1237 * Return true for select/poll.
1238 */
1239int
1240vop_nopoll(ap)
1241 struct vop_poll_args /* {
1242 struct vnode *a_vp;
1243 int a_events;
1244 struct ucred *a_cred;
1245 struct proc *a_p;
1246 } */ *ap;
1247{
1248 /*
1249 * Return true for read/write. If the user asked for something
1250 * special, return POLLNVAL, so that clients have a way of
1251 * determining reliably whether or not the extended
1252 * functionality is present without hard-coding knowledge
1253 * of specific filesystem implementations.
1254 */
1255 if (ap->a_events & ~POLLSTANDARD)
1256 return (POLLNVAL);
1257
1258 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1259}
1260
1261/*
1262 * Implement poll for local filesystems that support it.
1263 */
1264int
1265vop_stdpoll(ap)
1266 struct vop_poll_args /* {
1267 struct vnode *a_vp;
1268 int a_events;
1269 struct ucred *a_cred;
dadab5e9 1270 struct thread *a_td;
984263bc
MD
1271 } */ *ap;
1272{
1273 if (ap->a_events & ~POLLSTANDARD)
dadab5e9 1274 return (vn_pollrecord(ap->a_vp, ap->a_td, ap->a_events));
984263bc
MD
1275 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1276}
1277
1278int
1279vop_stdbwrite(ap)
1280 struct vop_bwrite_args *ap;
1281{
1282 return (bwrite(ap->a_bp));
1283}
1284
984263bc
MD
1285/*
1286 * vfs default ops
1287 * used to fill the vfs fucntion table to get reasonable default return values.
1288 */
1289int
43c45e8f 1290vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct thread *td)
984263bc
MD
1291{
1292 return (0);
1293}
1294
1295int
dadab5e9 1296vfs_stdunmount(struct mount *mp, int mntflags, struct thread *td)
984263bc
MD
1297{
1298 return (0);
1299}
1300
1301int
dadab5e9 1302vfs_stdroot(struct mount *mp, struct vnode **vpp)
984263bc
MD
1303{
1304 return (EOPNOTSUPP);
1305}
1306
1307int
dadab5e9 1308vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct thread *td)
984263bc
MD
1309{
1310 return (EOPNOTSUPP);
1311}
1312
1313int
dadab5e9 1314vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
984263bc
MD
1315{
1316 return (EOPNOTSUPP);
1317}
1318
1319int
dadab5e9 1320vfs_stdstart(struct mount *mp, int flags, struct thread *td)
984263bc
MD
1321{
1322 return (0);
1323}
1324
1325int
dadab5e9
MD
1326vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
1327 caddr_t arg, struct thread *td)
984263bc
MD
1328{
1329 return (EOPNOTSUPP);
1330}
1331
1332int
3b568787 1333vfs_stdsync(struct mount *mp, int waitfor, struct thread *td)
984263bc
MD
1334{
1335 return (0);
1336}
1337
43c45e8f
HP
1338int
1339vfs_stdnosync(struct mount *mp, int waitfor, struct thread *td)
1340{
1341 return (EOPNOTSUPP);
1342}
1343
984263bc 1344int
dadab5e9 1345vfs_stdvget(struct mount *mp, ino_t ino, struct vnode **vpp)
984263bc
MD
1346{
1347 return (EOPNOTSUPP);
1348}
1349
1350int
dadab5e9 1351vfs_stdfhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
984263bc
MD
1352{
1353 return (EOPNOTSUPP);
1354}
1355
1356int
dadab5e9
MD
1357vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1358 struct ucred **credanonp)
984263bc
MD
1359{
1360 return (EOPNOTSUPP);
1361}
1362
1363int
dadab5e9 1364vfs_stdinit(struct vfsconf *vfsp)
984263bc
MD
1365{
1366 return (0);
1367}
1368
1369int
dadab5e9 1370vfs_stduninit(struct vfsconf *vfsp)
984263bc
MD
1371{
1372 return(0);
1373}
1374
1375int
dadab5e9
MD
1376vfs_stdextattrctl(struct mount *mp, int cmd, const char *attrname,
1377 caddr_t arg, struct thread *td)
984263bc
MD
1378{
1379 return(EOPNOTSUPP);
1380}
1381
1382/* end of vfs default ops */