VFS accounting: implement an initialization framework
[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 *
d9fad06e
MD
8 * The statvfs->statfs conversion code was contributed to the DragonFly
9 * Project by Joerg Sonnenberger <joerg@bec.de>.
984263bc
MD
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
d9fad06e 39 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
984263bc 40 * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
27469235 41 * $DragonFly: src/sys/kern/vfs_default.c,v 1.55 2008/09/28 04:31:50 dillon Exp $
984263bc
MD
42 */
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/buf.h>
47#include <sys/conf.h>
8ddc6004
MD
48#include <sys/fcntl.h>
49#include <sys/file.h>
984263bc
MD
50#include <sys/kernel.h>
51#include <sys/lock.h>
52#include <sys/malloc.h>
53#include <sys/mount.h>
54#include <sys/unistd.h>
55#include <sys/vnode.h>
690a3127 56#include <sys/namei.h>
fad57d0e 57#include <sys/nlookup.h>
949ecb9b 58#include <sys/mountctl.h>
e788edda 59#include <sys/vfs_quota.h>
984263bc
MD
60
61#include <machine/limits.h>
62
63#include <vm/vm.h>
64#include <vm/vm_object.h>
65#include <vm/vm_page.h>
66#include <vm/vm_pager.h>
67#include <vm/vnode_pager.h>
68
e62afb5f 69static int vop_nolookup (struct vop_old_lookup_args *);
402ed7e1 70static int vop_nostrategy (struct vop_strategy_args *);
984263bc
MD
71
72/*
73 * This vnode table stores what we want to do if the filesystem doesn't
74 * implement a particular VOP.
75 *
76 * If there is no specific entry here, we will return EOPNOTSUPP.
984263bc 77 */
66a1ddf5
MD
78struct vop_ops default_vnode_vops = {
79 .vop_default = vop_eopnotsupp,
80 .vop_advlock = (void *)vop_einval,
81 .vop_fsync = (void *)vop_null,
82 .vop_ioctl = (void *)vop_enotty,
66a1ddf5
MD
83 .vop_mmap = (void *)vop_einval,
84 .vop_old_lookup = vop_nolookup,
85 .vop_open = vop_stdopen,
86 .vop_close = vop_stdclose,
27469235 87 .vop_pathconf = vop_stdpathconf,
66a1ddf5
MD
88 .vop_readlink = (void *)vop_einval,
89 .vop_reallocblks = (void *)vop_eopnotsupp,
66a1ddf5 90 .vop_strategy = vop_nostrategy,
66a1ddf5
MD
91 .vop_getacl = (void *)vop_eopnotsupp,
92 .vop_setacl = (void *)vop_eopnotsupp,
93 .vop_aclcheck = (void *)vop_eopnotsupp,
94 .vop_getextattr = (void *)vop_eopnotsupp,
95 .vop_setextattr = (void *)vop_eopnotsupp,
349433c9 96 .vop_markatime = vop_stdmarkatime,
66a1ddf5
MD
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,
177403a9 108 .vop_mountctl = vop_stdmountctl
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
349433c9
MD
138vop_stdmarkatime(struct vop_markatime_args *ap)
139{
140 return (EOPNOTSUPP);
141}
142
143int
984263bc
MD
144vop_null(struct vop_generic_args *ap)
145{
984263bc
MD
146 return (0);
147}
148
149int
150vop_defaultop(struct vop_generic_args *ap)
151{
66a1ddf5 152 return (VOCALL(&default_vnode_vops, ap));
984263bc
MD
153}
154
155int
156vop_panic(struct vop_generic_args *ap)
157{
31bd717a 158 panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name);
984263bc
MD
159}
160
690a3127 161/*
dff430ab
MD
162 * vop_compat_resolve { struct nchandle *a_nch, struct vnode *dvp }
163 * XXX STOPGAP FUNCTION
690a3127 164 *
21739618
MD
165 * XXX OLD API ROUTINE! WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
166 * WILL BE REMOVED. This procedure exists for all VFSs which have not
fad57d0e 167 * yet implemented VOP_NRESOLVE(). It converts VOP_NRESOLVE() into a
e62afb5f 168 * vop_old_lookup() and does appropriate translations.
21739618 169 *
690a3127
MD
170 * Resolve a ncp for VFSs which do not support the VOP. Eventually all
171 * VFSs will support this VOP and this routine can be removed, since
fad57d0e 172 * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
690a3127
MD
173 * API.
174 *
21739618
MD
175 * A locked ncp is passed in to be resolved. The NCP is resolved by
176 * figuring out the vnode (if any) and calling cache_setvp() to attach the
177 * vnode to the entry. If the entry represents a non-existant node then
178 * cache_setvp() is called with a NULL vnode to resolve the entry into a
179 * negative cache entry. No vnode locks are retained and the
690a3127 180 * ncp is left locked on return.
8e005a45 181 *
fad57d0e
MD
182 * The ncp will NEVER represent "", "." or "..", or contain any slashes.
183 *
8e005a45
MD
184 * There is a potential directory and vnode interlock. The lock order
185 * requirement is: namecache, governing directory, resolved vnode.
690a3127 186 */
417215fe 187int
fad57d0e 188vop_compat_nresolve(struct vop_nresolve_args *ap)
690a3127
MD
189{
190 int error;
191 struct vnode *dvp;
192 struct vnode *vp;
28623bf9 193 struct nchandle *nch;
690a3127
MD
194 struct namecache *ncp;
195 struct componentname cnp;
196
28623bf9
MD
197 nch = ap->a_nch; /* locked namecache node */
198 ncp = nch->ncp;
dff430ab 199 dvp = ap->a_dvp;
8c361dda 200
fad57d0e
MD
201 /*
202 * UFS currently stores all sorts of side effects, including a loop
203 * variable, in the directory inode. That needs to be fixed and the
204 * other VFS's audited before we can switch to LK_SHARED.
205 */
87de5057 206 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 207 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e 208 ncp, ncp->nc_name);
67773eb3
MD
209 return(EAGAIN);
210 }
690a3127
MD
211
212 bzero(&cnp, sizeof(cnp));
213 cnp.cn_nameiop = NAMEI_LOOKUP;
fad57d0e 214 cnp.cn_flags = 0;
690a3127
MD
215 cnp.cn_nameptr = ncp->nc_name;
216 cnp.cn_namelen = ncp->nc_nlen;
21739618
MD
217 cnp.cn_cred = ap->a_cred;
218 cnp.cn_td = curthread; /* XXX */
219
220 /*
e62afb5f 221 * vop_old_lookup() always returns vp locked. dvp may or may not be
21739618
MD
222 * left locked depending on CNP_PDIRUNLOCK.
223 */
e62afb5f 224 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
8c361dda 225 if (error == 0)
a11aaa81 226 vn_unlock(vp);
8c361dda 227 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 228 vn_unlock(dvp);
8c361dda
MD
229 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
230 /* was resolved by another process while we were unlocked */
231 if (error == 0)
232 vrele(vp);
233 } else if (error == 0) {
690a3127 234 KKASSERT(vp != NULL);
28623bf9 235 cache_setvp(nch, vp);
8c361dda 236 vrele(vp);
690a3127
MD
237 } else if (error == ENOENT) {
238 KKASSERT(vp == NULL);
239 if (cnp.cn_flags & CNP_ISWHITEOUT)
240 ncp->nc_flag |= NCF_WHITEOUT;
28623bf9 241 cache_setvp(nch, NULL);
690a3127 242 }
8c361dda 243 vrele(dvp);
21739618 244 return (error);
690a3127
MD
245}
246
fad57d0e
MD
247/*
248 * vop_compat_nlookupdotdot { struct vnode *a_dvp,
249 * struct vnode **a_vpp,
250 * struct ucred *a_cred }
251 *
252 * Lookup the vnode representing the parent directory of the specified
253 * directory vnode. a_dvp should not be locked. If no error occurs *a_vpp
254 * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
255 *
256 * This function is designed to aid NFS server-side operations and is
257 * used by cache_fromdvp() to create a consistent, connected namecache
258 * topology.
259 *
260 * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
261 * code out from their *_lookup() and create *_nlookupdotdot(). Then as time
262 * permits VFSs will implement the remaining *_n*() calls and finally get
263 * rid of their *_lookup() call.
264 */
265int
266vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
267{
268 struct componentname cnp;
269 int error;
270
271 /*
272 * UFS currently stores all sorts of side effects, including a loop
273 * variable, in the directory inode. That needs to be fixed and the
274 * other VFS's audited before we can switch to LK_SHARED.
275 */
276 *ap->a_vpp = NULL;
87de5057 277 if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0)
fad57d0e
MD
278 return (error);
279 if (ap->a_dvp->v_type != VDIR) {
280 vput(ap->a_dvp);
281 return (ENOTDIR);
282 }
283
284 bzero(&cnp, sizeof(cnp));
285 cnp.cn_nameiop = NAMEI_LOOKUP;
286 cnp.cn_flags = CNP_ISDOTDOT;
287 cnp.cn_nameptr = "..";
288 cnp.cn_namelen = 2;
289 cnp.cn_cred = ap->a_cred;
290 cnp.cn_td = curthread; /* XXX */
291
292 /*
e62afb5f 293 * vop_old_lookup() always returns vp locked. dvp may or may not be
fad57d0e
MD
294 * left locked depending on CNP_PDIRUNLOCK.
295 */
e62afb5f 296 error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
fad57d0e 297 if (error == 0)
a11aaa81 298 vn_unlock(*ap->a_vpp);
fad57d0e
MD
299 if (cnp.cn_flags & CNP_PDIRUNLOCK)
300 vrele(ap->a_dvp);
301 else
302 vput(ap->a_dvp);
303 return (error);
304}
21739618
MD
305
306/*
28623bf9 307 * vop_compat_ncreate { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab
MD
308 * struct vnode *a_dvp,
309 * struct vnode **a_vpp,
fad57d0e
MD
310 * struct ucred *a_cred,
311 * struct vattr *a_vap }
21739618 312 *
fad57d0e
MD
313 * Create a file as specified by a_vap. Compatibility requires us to issue
314 * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
315 * to setup the directory inode's i_offset and i_count (e.g. in UFS).
316 */
317int
318vop_compat_ncreate(struct vop_ncreate_args *ap)
319{
320 struct thread *td = curthread;
321 struct componentname cnp;
28623bf9 322 struct nchandle *nch;
fad57d0e
MD
323 struct namecache *ncp;
324 struct vnode *dvp;
325 int error;
326
327 /*
328 * Sanity checks, get a locked directory vnode.
329 */
28623bf9 330 nch = ap->a_nch; /* locked namecache node */
dff430ab 331 dvp = ap->a_dvp;
28623bf9 332 ncp = nch->ncp;
fad57d0e 333
87de5057 334 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 335 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
336 ncp, ncp->nc_name);
337 return(EAGAIN);
338 }
339
340 /*
e62afb5f 341 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
342 * caches all information required to create the entry in the
343 * directory inode. We expect a return code of EJUSTRETURN for
344 * the CREATE case. The cnp must simulated a saved-name situation.
345 */
346 bzero(&cnp, sizeof(cnp));
347 cnp.cn_nameiop = NAMEI_CREATE;
348 cnp.cn_flags = CNP_LOCKPARENT;
349 cnp.cn_nameptr = ncp->nc_name;
350 cnp.cn_namelen = ncp->nc_nlen;
351 cnp.cn_cred = ap->a_cred;
352 cnp.cn_td = td;
353 *ap->a_vpp = NULL;
354
e62afb5f 355 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
fad57d0e
MD
356
357 /*
358 * EJUSTRETURN should be returned for this case, which means that
359 * the VFS has setup the directory inode for the create. The dvp we
360 * passed in is expected to remain in a locked state.
361 *
362 * If the VOP_OLD_CREATE is successful we are responsible for updating
363 * the cache state of the locked ncp that was passed to us.
364 */
365 if (error == EJUSTRETURN) {
366 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
367 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
368 if (error == 0) {
28623bf9
MD
369 cache_setunresolved(nch);
370 cache_setvp(nch, *ap->a_vpp);
fad57d0e
MD
371 }
372 } else {
373 if (error == 0) {
374 vput(*ap->a_vpp);
375 *ap->a_vpp = NULL;
376 error = EEXIST;
377 }
378 KKASSERT(*ap->a_vpp == NULL);
379 }
380 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 381 vn_unlock(dvp);
fad57d0e
MD
382 vrele(dvp);
383 return (error);
384}
385
386/*
28623bf9 387 * vop_compat_nmkdir { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab
MD
388 * struct vnode *a_dvp,
389 * struct vnode **a_vpp,
fad57d0e
MD
390 * struct ucred *a_cred,
391 * struct vattr *a_vap }
21739618 392 *
fad57d0e
MD
393 * Create a directory as specified by a_vap. Compatibility requires us to
394 * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
395 * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
21739618 396 */
fad57d0e
MD
397int
398vop_compat_nmkdir(struct vop_nmkdir_args *ap)
399{
400 struct thread *td = curthread;
401 struct componentname cnp;
28623bf9 402 struct nchandle *nch;
fad57d0e
MD
403 struct namecache *ncp;
404 struct vnode *dvp;
405 int error;
406
407 /*
408 * Sanity checks, get a locked directory vnode.
409 */
28623bf9
MD
410 nch = ap->a_nch; /* locked namecache node */
411 ncp = nch->ncp;
dff430ab 412 dvp = ap->a_dvp;
87de5057 413 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 414 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
415 ncp, ncp->nc_name);
416 return(EAGAIN);
417 }
418
419 /*
e62afb5f 420 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
421 * caches all information required to create the entry in the
422 * directory inode. We expect a return code of EJUSTRETURN for
423 * the CREATE case. The cnp must simulated a saved-name situation.
424 */
425 bzero(&cnp, sizeof(cnp));
426 cnp.cn_nameiop = NAMEI_CREATE;
427 cnp.cn_flags = CNP_LOCKPARENT;
428 cnp.cn_nameptr = ncp->nc_name;
429 cnp.cn_namelen = ncp->nc_nlen;
430 cnp.cn_cred = ap->a_cred;
431 cnp.cn_td = td;
432 *ap->a_vpp = NULL;
433
e62afb5f 434 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
fad57d0e
MD
435
436 /*
437 * EJUSTRETURN should be returned for this case, which means that
438 * the VFS has setup the directory inode for the create. The dvp we
439 * passed in is expected to remain in a locked state.
440 *
441 * If the VOP_OLD_MKDIR is successful we are responsible for updating
442 * the cache state of the locked ncp that was passed to us.
443 */
444 if (error == EJUSTRETURN) {
445 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
446 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
447 if (error == 0) {
28623bf9
MD
448 cache_setunresolved(nch);
449 cache_setvp(nch, *ap->a_vpp);
fad57d0e
MD
450 }
451 } else {
452 if (error == 0) {
453 vput(*ap->a_vpp);
454 *ap->a_vpp = NULL;
455 error = EEXIST;
456 }
457 KKASSERT(*ap->a_vpp == NULL);
458 }
459 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 460 vn_unlock(dvp);
fad57d0e
MD
461 vrele(dvp);
462 return (error);
463}
464
465/*
28623bf9 466 * vop_compat_nmknod { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab
MD
467 * struct vnode *a_dvp,
468 * struct vnode **a_vpp,
fad57d0e
MD
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;
dff430ab 491 dvp = ap->a_dvp;
fad57d0e 492
87de5057 493 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 494 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
495 ncp, ncp->nc_name);
496 return(EAGAIN);
497 }
498
499 /*
e62afb5f 500 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
501 * caches all information required to create the entry in the
502 * directory inode. We expect a return code of EJUSTRETURN for
503 * the CREATE case. The cnp must simulated a saved-name situation.
504 */
505 bzero(&cnp, sizeof(cnp));
506 cnp.cn_nameiop = NAMEI_CREATE;
507 cnp.cn_flags = CNP_LOCKPARENT;
508 cnp.cn_nameptr = ncp->nc_name;
509 cnp.cn_namelen = ncp->nc_nlen;
510 cnp.cn_cred = ap->a_cred;
511 cnp.cn_td = td;
512 *ap->a_vpp = NULL;
513
e62afb5f 514 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
fad57d0e
MD
515
516 /*
517 * EJUSTRETURN should be returned for this case, which means that
518 * the VFS has setup the directory inode for the create. The dvp we
519 * passed in is expected to remain in a locked state.
520 *
521 * If the VOP_OLD_MKNOD is successful we are responsible for updating
522 * the cache state of the locked ncp that was passed to us.
523 */
524 if (error == EJUSTRETURN) {
525 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
526 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
527 if (error == 0) {
28623bf9
MD
528 cache_setunresolved(nch);
529 cache_setvp(nch, *ap->a_vpp);
fad57d0e
MD
530 }
531 } else {
532 if (error == 0) {
533 vput(*ap->a_vpp);
534 *ap->a_vpp = NULL;
535 error = EEXIST;
536 }
537 KKASSERT(*ap->a_vpp == NULL);
538 }
539 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 540 vn_unlock(dvp);
fad57d0e
MD
541 vrele(dvp);
542 return (error);
543}
544
545/*
28623bf9 546 * vop_compat_nlink { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab 547 * struct vnode *a_dvp,
fad57d0e
MD
548 * struct vnode *a_vp,
549 * struct ucred *a_cred }
550 *
551 * The passed vp is locked and represents the source. The passed ncp is
552 * locked and represents the target to create.
553 */
554int
555vop_compat_nlink(struct vop_nlink_args *ap)
556{
557 struct thread *td = curthread;
558 struct componentname cnp;
28623bf9 559 struct nchandle *nch;
fad57d0e
MD
560 struct namecache *ncp;
561 struct vnode *dvp;
562 struct vnode *tvp;
563 int error;
564
565 /*
566 * Sanity checks, get a locked directory vnode.
567 */
28623bf9
MD
568 nch = ap->a_nch; /* locked namecache node */
569 ncp = nch->ncp;
dff430ab 570 dvp = ap->a_dvp;
fad57d0e 571
87de5057 572 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 573 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
574 ncp, ncp->nc_name);
575 return(EAGAIN);
576 }
577
578 /*
e62afb5f 579 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
580 * caches all information required to create the entry in the
581 * directory inode. We expect a return code of EJUSTRETURN for
582 * the CREATE case. The cnp must simulated a saved-name situation.
583 */
584 bzero(&cnp, sizeof(cnp));
585 cnp.cn_nameiop = NAMEI_CREATE;
586 cnp.cn_flags = CNP_LOCKPARENT;
587 cnp.cn_nameptr = ncp->nc_name;
588 cnp.cn_namelen = ncp->nc_nlen;
589 cnp.cn_cred = ap->a_cred;
590 cnp.cn_td = td;
591
592 tvp = NULL;
e62afb5f 593 error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
fad57d0e
MD
594
595 /*
596 * EJUSTRETURN should be returned for this case, which means that
597 * the VFS has setup the directory inode for the create. The dvp we
598 * passed in is expected to remain in a locked state.
599 *
600 * If the VOP_OLD_LINK is successful we are responsible for updating
601 * the cache state of the locked ncp that was passed to us.
602 */
603 if (error == EJUSTRETURN) {
604 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
605 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
606 if (error == 0) {
28623bf9
MD
607 cache_setunresolved(nch);
608 cache_setvp(nch, ap->a_vp);
fad57d0e
MD
609 }
610 } else {
611 if (error == 0) {
612 vput(tvp);
613 error = EEXIST;
614 }
615 }
616 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 617 vn_unlock(dvp);
fad57d0e
MD
618 vrele(dvp);
619 return (error);
620}
621
622int
623vop_compat_nsymlink(struct vop_nsymlink_args *ap)
624{
625 struct thread *td = curthread;
626 struct componentname cnp;
28623bf9 627 struct nchandle *nch;
fad57d0e
MD
628 struct namecache *ncp;
629 struct vnode *dvp;
630 struct vnode *vp;
631 int error;
632
633 /*
634 * Sanity checks, get a locked directory vnode.
635 */
636 *ap->a_vpp = NULL;
28623bf9
MD
637 nch = ap->a_nch; /* locked namecache node */
638 ncp = nch->ncp;
dff430ab 639 dvp = ap->a_dvp;
fad57d0e 640
87de5057 641 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 642 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
643 ncp, ncp->nc_name);
644 return(EAGAIN);
645 }
646
647 /*
e62afb5f 648 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
649 * caches all information required to create the entry in the
650 * directory inode. We expect a return code of EJUSTRETURN for
651 * the CREATE case. The cnp must simulated a saved-name situation.
652 */
653 bzero(&cnp, sizeof(cnp));
654 cnp.cn_nameiop = NAMEI_CREATE;
655 cnp.cn_flags = CNP_LOCKPARENT;
656 cnp.cn_nameptr = ncp->nc_name;
657 cnp.cn_namelen = ncp->nc_nlen;
658 cnp.cn_cred = ap->a_cred;
659 cnp.cn_td = td;
660
661 vp = NULL;
e62afb5f 662 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
663
664 /*
665 * EJUSTRETURN should be returned for this case, which means that
666 * the VFS has setup the directory inode for the create. The dvp we
667 * passed in is expected to remain in a locked state.
668 *
669 * If the VOP_OLD_SYMLINK is successful we are responsible for updating
670 * the cache state of the locked ncp that was passed to us.
671 */
672 if (error == EJUSTRETURN) {
673 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
674 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
675 if (error == 0) {
28623bf9
MD
676 cache_setunresolved(nch);
677 cache_setvp(nch, vp);
fad57d0e
MD
678 *ap->a_vpp = vp;
679 }
680 } else {
681 if (error == 0) {
682 vput(vp);
683 vp = NULL;
684 error = EEXIST;
685 }
686 KKASSERT(vp == NULL);
687 }
688 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 689 vn_unlock(dvp);
fad57d0e
MD
690 vrele(dvp);
691 return (error);
692}
693
694/*
28623bf9 695 * vop_compat_nwhiteout { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab 696 * struct vnode *a_dvp,
fad57d0e
MD
697 * struct ucred *a_cred,
698 * int a_flags }
699 *
700 * Issie a whiteout operation (create, lookup, or delete). Compatibility
701 * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue
702 * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
703 * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops. For NAMEI_LOOKUP
704 * no lookup is necessary.
705 */
706int
707vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
21739618 708{
fad57d0e
MD
709 struct thread *td = curthread;
710 struct componentname cnp;
28623bf9 711 struct nchandle *nch;
fad57d0e
MD
712 struct namecache *ncp;
713 struct vnode *dvp;
21739618 714 struct vnode *vp;
21739618
MD
715 int error;
716
fad57d0e
MD
717 /*
718 * Sanity checks, get a locked directory vnode.
719 */
28623bf9
MD
720 nch = ap->a_nch; /* locked namecache node */
721 ncp = nch->ncp;
dff430ab 722 dvp = ap->a_dvp;
21739618 723
87de5057 724 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 725 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
726 ncp, ncp->nc_name);
727 return(EAGAIN);
21739618 728 }
21739618
MD
729
730 /*
e62afb5f 731 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
732 * caches all information required to create the entry in the
733 * directory inode. We expect a return code of EJUSTRETURN for
734 * the CREATE case. The cnp must simulated a saved-name situation.
735 */
736 bzero(&cnp, sizeof(cnp));
737 cnp.cn_nameiop = ap->a_flags;
738 cnp.cn_flags = CNP_LOCKPARENT;
739 cnp.cn_nameptr = ncp->nc_name;
740 cnp.cn_namelen = ncp->nc_nlen;
741 cnp.cn_cred = ap->a_cred;
742 cnp.cn_td = td;
743
744 vp = NULL;
745
746 /*
747 * EJUSTRETURN should be returned for the CREATE or DELETE cases.
748 * The VFS has setup the directory inode for the create. The dvp we
749 * passed in is expected to remain in a locked state.
750 *
751 * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
752 * the cache state of the locked ncp that was passed to us.
753 */
754 switch(ap->a_flags) {
755 case NAMEI_DELETE:
756 cnp.cn_flags |= CNP_DOWHITEOUT;
757 /* fall through */
758 case NAMEI_CREATE:
e62afb5f 759 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
760 if (error == EJUSTRETURN) {
761 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
762 error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
763 if (error == 0)
28623bf9 764 cache_setunresolved(nch);
fad57d0e
MD
765 } else {
766 if (error == 0) {
767 vput(vp);
768 vp = NULL;
769 error = EEXIST;
770 }
771 KKASSERT(vp == NULL);
772 }
773 break;
774 case NAMEI_LOOKUP:
775 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
776 break;
777 default:
778 error = EINVAL;
779 break;
780 }
781 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 782 vn_unlock(dvp);
fad57d0e
MD
783 vrele(dvp);
784 return (error);
785}
786
787
788/*
28623bf9 789 * vop_compat_nremove { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab
MD
790 * struct vnode *a_dvp,
791 * struct ucred *a_cred }
fad57d0e
MD
792 */
793int
794vop_compat_nremove(struct vop_nremove_args *ap)
795{
796 struct thread *td = curthread;
797 struct componentname cnp;
28623bf9 798 struct nchandle *nch;
fad57d0e
MD
799 struct namecache *ncp;
800 struct vnode *dvp;
801 struct vnode *vp;
802 int error;
803
804 /*
805 * Sanity checks, get a locked directory vnode.
806 */
28623bf9
MD
807 nch = ap->a_nch; /* locked namecache node */
808 ncp = nch->ncp;
dff430ab 809 dvp = ap->a_dvp;
fad57d0e 810
87de5057 811 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 812 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
813 ncp, ncp->nc_name);
814 return(EAGAIN);
815 }
816
817 /*
e62afb5f 818 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
819 * caches all information required to delete the entry in the
820 * directory inode. We expect a return code of 0 for the DELETE
821 * case (meaning that a vp has been found). The cnp must simulated
822 * a saved-name situation.
823 */
824 bzero(&cnp, sizeof(cnp));
825 cnp.cn_nameiop = NAMEI_DELETE;
826 cnp.cn_flags = CNP_LOCKPARENT;
827 cnp.cn_nameptr = ncp->nc_name;
828 cnp.cn_namelen = ncp->nc_nlen;
829 cnp.cn_cred = ap->a_cred;
830 cnp.cn_td = td;
831
832 /*
833 * The vnode must be a directory and must not represent the
834 * current directory.
21739618 835 */
fad57d0e 836 vp = NULL;
e62afb5f 837 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
838 if (error == 0 && vp->v_type == VDIR)
839 error = EPERM;
b8997912 840 if (error == 0) {
fad57d0e 841 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
842 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
843 if (error == 0) {
28623bf9
MD
844 cache_setunresolved(nch);
845 cache_setvp(nch, NULL);
bf40a153 846 cache_inval_vp(vp, CINV_DESTROY);
fad57d0e 847 }
b8997912 848 }
fad57d0e
MD
849 if (vp) {
850 if (dvp == vp)
851 vrele(vp);
852 else
853 vput(vp);
854 }
855 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 856 vn_unlock(dvp);
fad57d0e
MD
857 vrele(dvp);
858 return (error);
21739618
MD
859}
860
fad57d0e 861/*
28623bf9 862 * vop_compat_nrmdir { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab
MD
863 * struct vnode *dvp,
864 * struct ucred *a_cred }
fad57d0e
MD
865 */
866int
867vop_compat_nrmdir(struct vop_nrmdir_args *ap)
868{
869 struct thread *td = curthread;
870 struct componentname cnp;
28623bf9 871 struct nchandle *nch;
fad57d0e
MD
872 struct namecache *ncp;
873 struct vnode *dvp;
874 struct vnode *vp;
875 int error;
21739618 876
fad57d0e
MD
877 /*
878 * Sanity checks, get a locked directory vnode.
879 */
28623bf9
MD
880 nch = ap->a_nch; /* locked namecache node */
881 ncp = nch->ncp;
dff430ab 882 dvp = ap->a_dvp;
fad57d0e 883
87de5057 884 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 885 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
886 ncp, ncp->nc_name);
887 return(EAGAIN);
888 }
889
890 /*
e62afb5f 891 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
892 * caches all information required to delete the entry in the
893 * directory inode. We expect a return code of 0 for the DELETE
894 * case (meaning that a vp has been found). The cnp must simulated
895 * a saved-name situation.
896 */
897 bzero(&cnp, sizeof(cnp));
898 cnp.cn_nameiop = NAMEI_DELETE;
899 cnp.cn_flags = CNP_LOCKPARENT;
900 cnp.cn_nameptr = ncp->nc_name;
901 cnp.cn_namelen = ncp->nc_nlen;
902 cnp.cn_cred = ap->a_cred;
903 cnp.cn_td = td;
904
905 /*
906 * The vnode must be a directory and must not represent the
907 * current directory.
908 */
909 vp = NULL;
e62afb5f 910 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
911 if (error == 0 && vp->v_type != VDIR)
912 error = ENOTDIR;
913 if (error == 0 && vp == dvp)
914 error = EINVAL;
915 if (error == 0 && (vp->v_flag & VROOT))
916 error = EBUSY;
917 if (error == 0) {
918 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
919 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
920
921 /*
922 * Note that this invalidation will cause any process
923 * currently CD'd into the directory being removed to be
924 * disconnected from the topology and not be able to ".."
925 * back out.
926 */
bf40a153 927 if (error == 0) {
28623bf9 928 cache_inval(nch, CINV_DESTROY);
bf40a153
MD
929 cache_inval_vp(vp, CINV_DESTROY);
930 }
fad57d0e
MD
931 }
932 if (vp) {
933 if (dvp == vp)
934 vrele(vp);
935 else
936 vput(vp);
937 }
938 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 939 vn_unlock(dvp);
fad57d0e
MD
940 vrele(dvp);
941 return (error);
942}
943
944/*
28623bf9
MD
945 * vop_compat_nrename { struct nchandle *a_fnch, XXX STOPGAP FUNCTION
946 * struct nchandle *a_tnch,
fad57d0e
MD
947 * struct ucred *a_cred }
948 *
949 * This is a fairly difficult procedure. The old VOP_OLD_RENAME requires that
950 * the source directory and vnode be unlocked and the target directory and
951 * vnode (if it exists) be locked. All arguments will be vrele'd and
952 * the targets will also be unlocked regardless of the return code.
953 */
954int
955vop_compat_nrename(struct vop_nrename_args *ap)
956{
957 struct thread *td = curthread;
958 struct componentname fcnp;
959 struct componentname tcnp;
28623bf9
MD
960 struct nchandle *fnch;
961 struct nchandle *tnch;
fad57d0e
MD
962 struct namecache *fncp;
963 struct namecache *tncp;
964 struct vnode *fdvp, *fvp;
965 struct vnode *tdvp, *tvp;
966 int error;
967
968 /*
969 * Sanity checks, get referenced vnodes representing the source.
970 */
28623bf9
MD
971 fnch = ap->a_fnch; /* locked namecache node */
972 fncp = fnch->ncp;
dff430ab 973 fdvp = ap->a_fdvp;
fad57d0e
MD
974
975 /*
976 * Temporarily lock the source directory and lookup in DELETE mode to
977 * check permissions. XXX delete permissions should have been
978 * checked by nlookup(), we need to add NLC_DELETE for delete
979 * checking. It is unclear whether VFS's require the directory setup
980 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
981 * since it isn't locked and since UFS always does a relookup of
982 * the source, it is believed that the only side effect that matters
983 * is the permissions check.
984 */
87de5057 985 if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 986 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
987 fncp, fncp->nc_name);
988 return(EAGAIN);
989 }
990
991 bzero(&fcnp, sizeof(fcnp));
992 fcnp.cn_nameiop = NAMEI_DELETE;
993 fcnp.cn_flags = CNP_LOCKPARENT;
994 fcnp.cn_nameptr = fncp->nc_name;
995 fcnp.cn_namelen = fncp->nc_nlen;
996 fcnp.cn_cred = ap->a_cred;
997 fcnp.cn_td = td;
998
999 /*
e62afb5f 1000 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
fad57d0e
MD
1001 * fvp.
1002 */
1003 fvp = NULL;
e62afb5f 1004 error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
fad57d0e 1005 if (error == 0 && (fvp->v_flag & VROOT)) {
e62afb5f 1006 vput(fvp); /* as if vop_old_lookup had failed */
fad57d0e
MD
1007 error = EBUSY;
1008 }
1009 if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1010 fcnp.cn_flags |= CNP_PDIRUNLOCK;
a11aaa81 1011 vn_unlock(fdvp);
fad57d0e
MD
1012 }
1013 if (error) {
1014 vrele(fdvp);
1015 return (error);
1016 }
a11aaa81 1017 vn_unlock(fvp);
fad57d0e
MD
1018
1019 /*
1020 * fdvp and fvp are now referenced and unlocked.
1021 *
1022 * Get a locked directory vnode for the target and lookup the target
1023 * in CREATE mode so it places the required information in the
1024 * directory inode.
1025 */
28623bf9
MD
1026 tnch = ap->a_tnch; /* locked namecache node */
1027 tncp = tnch->ncp;
dff430ab 1028 tdvp = ap->a_tdvp;
fad57d0e
MD
1029 if (error) {
1030 vrele(fdvp);
1031 vrele(fvp);
1032 return (error);
1033 }
87de5057 1034 if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 1035 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
1036 tncp, tncp->nc_name);
1037 vrele(fdvp);
1038 vrele(fvp);
1039 return(EAGAIN);
1040 }
1041
1042 /*
e62afb5f 1043 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
1044 * caches all information required to create the entry in the
1045 * target directory inode.
1046 */
1047 bzero(&tcnp, sizeof(tcnp));
1048 tcnp.cn_nameiop = NAMEI_RENAME;
1049 tcnp.cn_flags = CNP_LOCKPARENT;
1050 tcnp.cn_nameptr = tncp->nc_name;
1051 tcnp.cn_namelen = tncp->nc_nlen;
1052 tcnp.cn_cred = ap->a_cred;
1053 tcnp.cn_td = td;
1054
1055 tvp = NULL;
e62afb5f 1056 error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
fad57d0e
MD
1057
1058 if (error == EJUSTRETURN) {
1059 /*
1060 * Target does not exist. tvp should be NULL.
1061 */
1062 KKASSERT(tvp == NULL);
1063 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1064 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
227cf16d 1065 if (error == 0)
28623bf9 1066 cache_rename(fnch, tnch);
fad57d0e
MD
1067 } else if (error == 0) {
1068 /*
1069 * Target exists. VOP_OLD_RENAME should correctly delete the
1070 * target.
1071 */
1072 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1073 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
227cf16d 1074 if (error == 0)
28623bf9 1075 cache_rename(fnch, tnch);
fad57d0e
MD
1076 } else {
1077 vrele(fdvp);
1078 vrele(fvp);
1079 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1080 vrele(tdvp);
1081 else
1082 vput(tdvp);
1083 }
1084 return (error);
1085}
21739618 1086
984263bc 1087static int
c972a82f 1088vop_nolookup(struct vop_old_lookup_args *ap)
984263bc
MD
1089{
1090
1091 *ap->a_vpp = NULL;
1092 return (ENOTDIR);
1093}
1094
1095/*
1096 * vop_nostrategy:
1097 *
1098 * Strategy routine for VFS devices that have none.
1099 *
1100 * B_ERROR and B_INVAL must be cleared prior to calling any strategy
10f3fee5
MD
1101 * routine. Typically this is done for a BUF_CMD_READ strategy call.
1102 * Typically B_INVAL is assumed to already be clear prior to a write
1103 * and should not be cleared manually unless you just made the buffer
1104 * invalid. B_ERROR should be cleared either way.
984263bc
MD
1105 */
1106
1107static int
1108vop_nostrategy (struct vop_strategy_args *ap)
1109{
6ea70f76 1110 kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
984263bc 1111 vprint("", ap->a_vp);
81b5c339
MD
1112 ap->a_bio->bio_buf->b_flags |= B_ERROR;
1113 ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1114 biodone(ap->a_bio);
984263bc
MD
1115 return (EOPNOTSUPP);
1116}
1117
1118int
c972a82f 1119vop_stdpathconf(struct vop_pathconf_args *ap)
984263bc 1120{
27469235 1121 int error = 0;
984263bc
MD
1122
1123 switch (ap->a_name) {
27469235
MD
1124 case _PC_LINK_MAX:
1125 *ap->a_retval = LINK_MAX;
1126 break;
1127 case _PC_NAME_MAX:
1128 *ap->a_retval = NAME_MAX;
1129 break;
1130 case _PC_PATH_MAX:
1131 *ap->a_retval = PATH_MAX;
1132 break;
1133 case _PC_MAX_CANON:
1134 *ap->a_retval = MAX_CANON;
1135 break;
1136 case _PC_MAX_INPUT:
1137 *ap->a_retval = MAX_INPUT;
1138 break;
1139 case _PC_PIPE_BUF:
1140 *ap->a_retval = PIPE_BUF;
1141 break;
1142 case _PC_CHOWN_RESTRICTED:
1143 *ap->a_retval = 1;
1144 break;
1145 case _PC_NO_TRUNC:
1146 *ap->a_retval = 1;
1147 break;
1148 case _PC_VDISABLE:
1149 *ap->a_retval = _POSIX_VDISABLE;
1150 break;
1151 default:
1152 error = EINVAL;
1153 break;
984263bc 1154 }
27469235 1155 return (error);
984263bc
MD
1156}
1157
1158/*
8ddc6004
MD
1159 * Standard open.
1160 *
b478fdce 1161 * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp)
8ddc6004
MD
1162 *
1163 * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1164 */
1165int
1166vop_stdopen(struct vop_open_args *ap)
1167{
1168 struct vnode *vp = ap->a_vp;
1169 struct file *fp;
1170
1171 if ((fp = ap->a_fp) != NULL) {
1172 switch(vp->v_type) {
1173 case VFIFO:
1174 fp->f_type = DTYPE_FIFO;
1175 break;
1176 default:
1177 fp->f_type = DTYPE_VNODE;
1178 break;
1179 }
1180 fp->f_flag = ap->a_mode & FMASK;
1181 fp->f_ops = &vnode_fileops;
1182 fp->f_data = vp;
1183 vref(vp);
1184 }
1185 if (ap->a_mode & FWRITE)
1186 ++vp->v_writecount;
1187 KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1188 ++vp->v_opencount;
1189 return (0);
1190}
1191
1192/*
1193 * Standard close.
1194 *
b478fdce 1195 * (struct vnode *a_vp, int a_fflag)
8ddc6004
MD
1196 *
1197 * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE. same as a_mode in stdopen?
1198 */
1199int
1200vop_stdclose(struct vop_close_args *ap)
1201{
1202 struct vnode *vp = ap->a_vp;
1203
1204 KASSERT(vp->v_opencount > 0,
a2a3460a
MD
1205 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d type=%d ops=%p flgs=%08x\n",
1206 vp, vp->v_opencount, vp->v_type, *vp->v_ops, vp->v_flag));
8ddc6004
MD
1207 if (ap->a_fflag & FWRITE) {
1208 KASSERT(vp->v_writecount > 0,
1209 ("VOP_STDCLOSE: BAD WRITECOUNT %p %d\n",
1210 vp, vp->v_writecount));
1211 --vp->v_writecount;
1212 }
1213 --vp->v_opencount;
1214 return (0);
1215}
1216
1217/*
1787385d
MD
1218 * Implement standard getpages and putpages. All filesystems must use
1219 * the buffer cache to back regular files.
1220 */
1221int
1222vop_stdgetpages(struct vop_getpages_args *ap)
1223{
1224 struct mount *mp;
1225 int error;
1226
1227 if ((mp = ap->a_vp->v_mount) != NULL) {
1228 error = vnode_pager_generic_getpages(
1229 ap->a_vp, ap->a_m, ap->a_count,
1c48c952 1230 ap->a_reqpage, ap->a_seqaccess);
1787385d
MD
1231 } else {
1232 error = VM_PAGER_BAD;
1233 }
1234 return (error);
1235}
1236
1237int
1238vop_stdputpages(struct vop_putpages_args *ap)
1239{
1240 struct mount *mp;
1241 int error;
1242
1243 if ((mp = ap->a_vp->v_mount) != NULL) {
1244 error = vnode_pager_generic_putpages(
1245 ap->a_vp, ap->a_m, ap->a_count,
1246 ap->a_sync, ap->a_rtvals);
1247 } else {
1248 error = VM_PAGER_BAD;
1249 }
1250 return (error);
1251}
1252
aec8eea4
MD
1253int
1254vop_stdnoread(struct vop_read_args *ap)
1255{
1256 return (EINVAL);
1257}
1258
1259int
1260vop_stdnowrite(struct vop_write_args *ap)
1261{
1262 return (EINVAL);
1263}
1264
984263bc
MD
1265/*
1266 * vfs default ops
1267 * used to fill the vfs fucntion table to get reasonable default return values.
1268 */
1269int
acde96db 1270vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
984263bc
MD
1271{
1272 return (0);
1273}
1274
1275int
acde96db 1276vfs_stdunmount(struct mount *mp, int mntflags)
984263bc
MD
1277{
1278 return (0);
1279}
1280
177403a9
MD
1281int
1282vop_stdmountctl(struct vop_mountctl_args *ap)
1283{
1284
1285 struct mount *mp;
1286 int error = 0;
1287
1288 mp = ap->a_head.a_ops->head.vv_mount;
1289
1290 switch(ap->a_op) {
1291 case MOUNTCTL_MOUNTFLAGS:
1292 /*
1293 * Get a string buffer with all the mount flags
1294 * names comman separated.
1295 * mount(2) will use this information.
1296 */
dad088a5
MD
1297 *ap->a_res = vfs_flagstostr(mp->mnt_flag & MNT_VISFLAGMASK, NULL,
1298 ap->a_buf, ap->a_buflen, &error);
177403a9
MD
1299 break;
1300 case MOUNTCTL_INSTALL_VFS_JOURNAL:
1301 case MOUNTCTL_RESTART_VFS_JOURNAL:
1302 case MOUNTCTL_REMOVE_VFS_JOURNAL:
1303 case MOUNTCTL_RESYNC_VFS_JOURNAL:
1304 case MOUNTCTL_STATUS_VFS_JOURNAL:
1305 error = journal_mountctl(ap);
1306 break;
1307 default:
1308 error = EOPNOTSUPP;
1309 break;
1310 }
1311 return (error);
1312}
1313
984263bc 1314int
dadab5e9 1315vfs_stdroot(struct mount *mp, struct vnode **vpp)
984263bc
MD
1316{
1317 return (EOPNOTSUPP);
1318}
1319
1320int
acde96db 1321vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
984263bc
MD
1322{
1323 return (EOPNOTSUPP);
1324}
1325
d9fad06e
MD
1326/*
1327 * If the VFS does not implement statvfs, then call statfs and convert
1328 * the values. This code was taken from libc's __cvtstatvfs() function,
1329 * contributed by Joerg Sonnenberger.
1330 */
1331int
1332vfs_stdstatvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
1333{
1334 struct statfs *in;
1335 int error;
1336
1337 in = &mp->mnt_stat;
1338 error = VFS_STATFS(mp, in, cred);
1339 if (error == 0) {
1340 bzero(sbp, sizeof(*sbp));
1341
1342 sbp->f_bsize = in->f_bsize;
1343 sbp->f_frsize = in->f_bsize;
1344 sbp->f_blocks = in->f_blocks;
1345 sbp->f_bfree = in->f_bfree;
1346 sbp->f_bavail = in->f_bavail;
1347 sbp->f_files = in->f_files;
1348 sbp->f_ffree = in->f_ffree;
1349
1350 /*
1351 * XXX
1352 * This field counts the number of available inodes to non-root
1353 * users, but this information is not available via statfs.
1354 * Just ignore this issue by returning the total number
1355 * instead.
1356 */
1357 sbp->f_favail = in->f_ffree;
1358
1359 /*
1360 * XXX
1361 * This field has a different meaning for statfs and statvfs.
1362 * For the former it is the cookie exported for NFS and not
1363 * intended for normal userland use.
1364 */
1365 sbp->f_fsid = 0;
1366
1367 sbp->f_flag = 0;
1368 if (in->f_flags & MNT_RDONLY)
1369 sbp->f_flag |= ST_RDONLY;
1370 if (in->f_flags & MNT_NOSUID)
1371 sbp->f_flag |= ST_NOSUID;
1372 sbp->f_namemax = 0;
1373 sbp->f_owner = in->f_owner;
1374 /*
1375 * XXX
1376 * statfs contains the type as string, statvfs expects it as
1377 * enumeration.
1378 */
1379 sbp->f_type = 0;
1380
1381 sbp->f_syncreads = in->f_syncreads;
1382 sbp->f_syncwrites = in->f_syncwrites;
1383 sbp->f_asyncreads = in->f_asyncreads;
1384 sbp->f_asyncwrites = in->f_asyncwrites;
1385 }
1386 return (error);
1387}
1388
984263bc 1389int
dadab5e9 1390vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
984263bc
MD
1391{
1392 return (EOPNOTSUPP);
1393}
1394
1395int
acde96db 1396vfs_stdstart(struct mount *mp, int flags)
984263bc
MD
1397{
1398 return (0);
1399}
1400
1401int
dadab5e9 1402vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
acde96db 1403 caddr_t arg, struct ucred *cred)
984263bc
MD
1404{
1405 return (EOPNOTSUPP);
1406}
1407
1408int
87de5057 1409vfs_stdsync(struct mount *mp, int waitfor)
984263bc
MD
1410{
1411 return (0);
1412}
1413
43c45e8f 1414int
87de5057 1415vfs_stdnosync(struct mount *mp, int waitfor)
43c45e8f
HP
1416{
1417 return (EOPNOTSUPP);
1418}
1419
984263bc 1420int
b9b0a6d0 1421vfs_stdvget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
984263bc
MD
1422{
1423 return (EOPNOTSUPP);
1424}
1425
1426int
67863d04
MD
1427vfs_stdfhtovp(struct mount *mp, struct vnode *rootvp,
1428 struct fid *fhp, struct vnode **vpp)
984263bc
MD
1429{
1430 return (EOPNOTSUPP);
1431}
1432
1433int
dadab5e9
MD
1434vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1435 struct ucred **credanonp)
984263bc
MD
1436{
1437 return (EOPNOTSUPP);
1438}
1439
1440int
dadab5e9 1441vfs_stdinit(struct vfsconf *vfsp)
984263bc
MD
1442{
1443 return (0);
1444}
1445
1446int
dadab5e9 1447vfs_stduninit(struct vfsconf *vfsp)
984263bc
MD
1448{
1449 return(0);
1450}
1451
1452int
0f6997f9
MD
1453vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp,
1454 int attrnamespace, const char *attrname,
1455 struct ucred *cred)
984263bc
MD
1456{
1457 return(EOPNOTSUPP);
1458}
1459
e788edda
FT
1460#define ACCOUNTING_NB_FSTYPES 8
1461
1462static const char *accounting_fstypes[ACCOUNTING_NB_FSTYPES] = {
1463 "ext2fs", "hammer", "hpfs", "mfs", "ntfs", "null", "tmpfs", "ufs" };
1464
1465int
1466vfs_stdac_init(struct mount *mp)
1467{
1468 const char* fs_type;
1469 int i, fstype_ok = 0;
1470
1471 /* if mounted fs is read-only, do not do anything */
1472 if (mp->mnt_flag & MNT_RDONLY)
1473 return (0);
1474
1475 /* is mounted fs type one we want to do some accounting for ? */
1476 for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
1477 fs_type = accounting_fstypes[i];
1478 if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
1479 sizeof(mp->mnt_stat)) == 0) {
1480 fstype_ok = 1;
1481 break;
1482 }
1483 }
1484 if (fstype_ok == 0)
1485 return (0);
1486
1487 kprintf("vfs_quota: enabling accounting for %s\n",
1488 mp->mnt_stat.f_mntonname);
1489 vq_init(mp);
1490 return (0);
1491}
1492
1493int
1494vfs_stdac_done(struct mount *mp)
1495{
1496 const char* fs_type;
1497 int i, fstype_ok = 0;
1498
1499 /* if mounted fs is read-only, do not do anything */
1500 if (mp->mnt_flag & MNT_RDONLY)
1501 return (0);
1502
1503 /* is mounted fs type one we want to do some accounting for ? */
1504 for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
1505 fs_type = accounting_fstypes[i];
1506 if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
1507 sizeof(mp->mnt_stat)) == 0) {
1508 fstype_ok = 1;
1509 break;
1510 }
1511 }
1512 if (fstype_ok == 0)
1513 return (0);
1514
1515 vq_done(mp);
1516 return (0);
1517}
1518
1c18cfd0
FT
1519int
1520vfs_stdaccount(struct mount *mp, uid_t uid, gid_t gid, int64_t delta)
1521{
1522 return(0);
1523}
1524
e788edda
FT
1525int
1526vfs_noaccount(struct mount *mp, uid_t uid, gid_t gid, int64_t delta)
1527{
1528 return(0);
1529}
1530
984263bc 1531/* end of vfs default ops */