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