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