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