kernel - add cache_unlink(), fix a rename issue.
[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
MD
40 * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
41 */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/buf.h>
46#include <sys/conf.h>
8ddc6004
MD
47#include <sys/fcntl.h>
48#include <sys/file.h>
984263bc
MD
49#include <sys/kernel.h>
50#include <sys/lock.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/unistd.h>
54#include <sys/vnode.h>
690a3127 55#include <sys/namei.h>
fad57d0e 56#include <sys/nlookup.h>
949ecb9b 57#include <sys/mountctl.h>
e788edda 58#include <sys/vfs_quota.h>
984263bc
MD
59
60#include <machine/limits.h>
61
62#include <vm/vm.h>
63#include <vm/vm_object.h>
64#include <vm/vm_page.h>
65#include <vm/vm_pager.h>
66#include <vm/vnode_pager.h>
67
e62afb5f 68static int vop_nolookup (struct vop_old_lookup_args *);
402ed7e1 69static int vop_nostrategy (struct vop_strategy_args *);
984263bc
MD
70
71/*
72 * This vnode table stores what we want to do if the filesystem doesn't
73 * implement a particular VOP.
74 *
75 * If there is no specific entry here, we will return EOPNOTSUPP.
984263bc 76 */
66a1ddf5
MD
77struct vop_ops default_vnode_vops = {
78 .vop_default = vop_eopnotsupp,
79 .vop_advlock = (void *)vop_einval,
80 .vop_fsync = (void *)vop_null,
81 .vop_ioctl = (void *)vop_enotty,
66a1ddf5
MD
82 .vop_mmap = (void *)vop_einval,
83 .vop_old_lookup = vop_nolookup,
84 .vop_open = vop_stdopen,
85 .vop_close = vop_stdclose,
27469235 86 .vop_pathconf = vop_stdpathconf,
66a1ddf5
MD
87 .vop_readlink = (void *)vop_einval,
88 .vop_reallocblks = (void *)vop_eopnotsupp,
66a1ddf5 89 .vop_strategy = vop_nostrategy,
66a1ddf5
MD
90 .vop_getacl = (void *)vop_eopnotsupp,
91 .vop_setacl = (void *)vop_eopnotsupp,
92 .vop_aclcheck = (void *)vop_eopnotsupp,
93 .vop_getextattr = (void *)vop_eopnotsupp,
94 .vop_setextattr = (void *)vop_eopnotsupp,
349433c9 95 .vop_markatime = vop_stdmarkatime,
66a1ddf5
MD
96 .vop_nresolve = vop_compat_nresolve,
97 .vop_nlookupdotdot = vop_compat_nlookupdotdot,
98 .vop_ncreate = vop_compat_ncreate,
99 .vop_nmkdir = vop_compat_nmkdir,
100 .vop_nmknod = vop_compat_nmknod,
101 .vop_nlink = vop_compat_nlink,
102 .vop_nsymlink = vop_compat_nsymlink,
103 .vop_nwhiteout = vop_compat_nwhiteout,
104 .vop_nremove = vop_compat_nremove,
105 .vop_nrmdir = vop_compat_nrmdir,
106 .vop_nrename = vop_compat_nrename,
177403a9 107 .vop_mountctl = vop_stdmountctl
984263bc
MD
108};
109
66a1ddf5 110VNODEOP_SET(default_vnode_vops);
984263bc
MD
111
112int
113vop_eopnotsupp(struct vop_generic_args *ap)
114{
984263bc
MD
115 return (EOPNOTSUPP);
116}
117
118int
119vop_ebadf(struct vop_generic_args *ap)
120{
984263bc
MD
121 return (EBADF);
122}
123
124int
125vop_enotty(struct vop_generic_args *ap)
126{
984263bc
MD
127 return (ENOTTY);
128}
129
130int
131vop_einval(struct vop_generic_args *ap)
132{
984263bc
MD
133 return (EINVAL);
134}
135
136int
349433c9
MD
137vop_stdmarkatime(struct vop_markatime_args *ap)
138{
139 return (EOPNOTSUPP);
140}
141
142int
984263bc
MD
143vop_null(struct vop_generic_args *ap)
144{
984263bc
MD
145 return (0);
146}
147
148int
149vop_defaultop(struct vop_generic_args *ap)
150{
66a1ddf5 151 return (VOCALL(&default_vnode_vops, ap));
984263bc
MD
152}
153
154int
155vop_panic(struct vop_generic_args *ap)
156{
31bd717a 157 panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name);
984263bc
MD
158}
159
690a3127 160/*
dff430ab
MD
161 * vop_compat_resolve { struct nchandle *a_nch, struct vnode *dvp }
162 * XXX STOPGAP FUNCTION
690a3127 163 *
21739618
MD
164 * XXX OLD API ROUTINE! WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
165 * WILL BE REMOVED. This procedure exists for all VFSs which have not
fad57d0e 166 * yet implemented VOP_NRESOLVE(). It converts VOP_NRESOLVE() into a
e62afb5f 167 * vop_old_lookup() and does appropriate translations.
21739618 168 *
690a3127
MD
169 * Resolve a ncp for VFSs which do not support the VOP. Eventually all
170 * VFSs will support this VOP and this routine can be removed, since
fad57d0e 171 * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
690a3127
MD
172 * API.
173 *
21739618
MD
174 * A locked ncp is passed in to be resolved. The NCP is resolved by
175 * figuring out the vnode (if any) and calling cache_setvp() to attach the
176 * vnode to the entry. If the entry represents a non-existant node then
177 * cache_setvp() is called with a NULL vnode to resolve the entry into a
178 * negative cache entry. No vnode locks are retained and the
690a3127 179 * ncp is left locked on return.
8e005a45 180 *
fad57d0e
MD
181 * The ncp will NEVER represent "", "." or "..", or contain any slashes.
182 *
8e005a45
MD
183 * There is a potential directory and vnode interlock. The lock order
184 * requirement is: namecache, governing directory, resolved vnode.
690a3127 185 */
417215fe 186int
fad57d0e 187vop_compat_nresolve(struct vop_nresolve_args *ap)
690a3127
MD
188{
189 int error;
190 struct vnode *dvp;
191 struct vnode *vp;
28623bf9 192 struct nchandle *nch;
690a3127
MD
193 struct namecache *ncp;
194 struct componentname cnp;
195
28623bf9
MD
196 nch = ap->a_nch; /* locked namecache node */
197 ncp = nch->ncp;
dff430ab 198 dvp = ap->a_dvp;
8c361dda 199
fad57d0e
MD
200 /*
201 * UFS currently stores all sorts of side effects, including a loop
202 * variable, in the directory inode. That needs to be fixed and the
203 * other VFS's audited before we can switch to LK_SHARED.
204 */
87de5057 205 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 206 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e 207 ncp, ncp->nc_name);
67773eb3
MD
208 return(EAGAIN);
209 }
690a3127
MD
210
211 bzero(&cnp, sizeof(cnp));
212 cnp.cn_nameiop = NAMEI_LOOKUP;
fad57d0e 213 cnp.cn_flags = 0;
690a3127
MD
214 cnp.cn_nameptr = ncp->nc_name;
215 cnp.cn_namelen = ncp->nc_nlen;
21739618
MD
216 cnp.cn_cred = ap->a_cred;
217 cnp.cn_td = curthread; /* XXX */
218
219 /*
e62afb5f 220 * vop_old_lookup() always returns vp locked. dvp may or may not be
21739618
MD
221 * left locked depending on CNP_PDIRUNLOCK.
222 */
e62afb5f 223 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
8c361dda 224 if (error == 0)
a11aaa81 225 vn_unlock(vp);
8c361dda 226 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 227 vn_unlock(dvp);
8c361dda
MD
228 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
229 /* was resolved by another process while we were unlocked */
230 if (error == 0)
231 vrele(vp);
232 } else if (error == 0) {
690a3127 233 KKASSERT(vp != NULL);
28623bf9 234 cache_setvp(nch, vp);
8c361dda 235 vrele(vp);
690a3127
MD
236 } else if (error == ENOENT) {
237 KKASSERT(vp == NULL);
238 if (cnp.cn_flags & CNP_ISWHITEOUT)
239 ncp->nc_flag |= NCF_WHITEOUT;
28623bf9 240 cache_setvp(nch, NULL);
690a3127 241 }
8c361dda 242 vrele(dvp);
21739618 243 return (error);
690a3127
MD
244}
245
fad57d0e
MD
246/*
247 * vop_compat_nlookupdotdot { struct vnode *a_dvp,
248 * struct vnode **a_vpp,
249 * struct ucred *a_cred }
250 *
251 * Lookup the vnode representing the parent directory of the specified
252 * directory vnode. a_dvp should not be locked. If no error occurs *a_vpp
253 * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
254 *
255 * This function is designed to aid NFS server-side operations and is
256 * used by cache_fromdvp() to create a consistent, connected namecache
257 * topology.
258 *
259 * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
260 * code out from their *_lookup() and create *_nlookupdotdot(). Then as time
261 * permits VFSs will implement the remaining *_n*() calls and finally get
262 * rid of their *_lookup() call.
263 */
264int
265vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
266{
267 struct componentname cnp;
268 int error;
269
270 /*
271 * UFS currently stores all sorts of side effects, including a loop
272 * variable, in the directory inode. That needs to be fixed and the
273 * other VFS's audited before we can switch to LK_SHARED.
274 */
275 *ap->a_vpp = NULL;
87de5057 276 if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0)
fad57d0e
MD
277 return (error);
278 if (ap->a_dvp->v_type != VDIR) {
279 vput(ap->a_dvp);
280 return (ENOTDIR);
281 }
282
283 bzero(&cnp, sizeof(cnp));
284 cnp.cn_nameiop = NAMEI_LOOKUP;
285 cnp.cn_flags = CNP_ISDOTDOT;
286 cnp.cn_nameptr = "..";
287 cnp.cn_namelen = 2;
288 cnp.cn_cred = ap->a_cred;
289 cnp.cn_td = curthread; /* XXX */
290
291 /*
e62afb5f 292 * vop_old_lookup() always returns vp locked. dvp may or may not be
fad57d0e 293 * left locked depending on CNP_PDIRUNLOCK.
7f23b320
MD
294 *
295 * (*vpp) will be returned locked if no error occured, which is the
296 * state we want.
fad57d0e 297 */
e62afb5f 298 error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
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 842 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
8d09ad3d
MD
843 if (error == 0)
844 cache_unlink(nch);
b8997912 845 }
fad57d0e
MD
846 if (vp) {
847 if (dvp == vp)
848 vrele(vp);
849 else
850 vput(vp);
851 }
852 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 853 vn_unlock(dvp);
fad57d0e
MD
854 vrele(dvp);
855 return (error);
21739618
MD
856}
857
fad57d0e 858/*
28623bf9 859 * vop_compat_nrmdir { struct nchandle *a_nch, XXX STOPGAP FUNCTION
dff430ab
MD
860 * struct vnode *dvp,
861 * struct ucred *a_cred }
fad57d0e
MD
862 */
863int
864vop_compat_nrmdir(struct vop_nrmdir_args *ap)
865{
866 struct thread *td = curthread;
867 struct componentname cnp;
28623bf9 868 struct nchandle *nch;
fad57d0e
MD
869 struct namecache *ncp;
870 struct vnode *dvp;
871 struct vnode *vp;
872 int error;
21739618 873
fad57d0e
MD
874 /*
875 * Sanity checks, get a locked directory vnode.
876 */
28623bf9
MD
877 nch = ap->a_nch; /* locked namecache node */
878 ncp = nch->ncp;
dff430ab 879 dvp = ap->a_dvp;
fad57d0e 880
87de5057 881 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 882 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
883 ncp, ncp->nc_name);
884 return(EAGAIN);
885 }
886
887 /*
e62afb5f 888 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
889 * caches all information required to delete the entry in the
890 * directory inode. We expect a return code of 0 for the DELETE
891 * case (meaning that a vp has been found). The cnp must simulated
892 * a saved-name situation.
893 */
894 bzero(&cnp, sizeof(cnp));
895 cnp.cn_nameiop = NAMEI_DELETE;
896 cnp.cn_flags = CNP_LOCKPARENT;
897 cnp.cn_nameptr = ncp->nc_name;
898 cnp.cn_namelen = ncp->nc_nlen;
899 cnp.cn_cred = ap->a_cred;
900 cnp.cn_td = td;
901
902 /*
903 * The vnode must be a directory and must not represent the
904 * current directory.
905 */
906 vp = NULL;
e62afb5f 907 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
fad57d0e
MD
908 if (error == 0 && vp->v_type != VDIR)
909 error = ENOTDIR;
910 if (error == 0 && vp == dvp)
911 error = EINVAL;
912 if (error == 0 && (vp->v_flag & VROOT))
913 error = EBUSY;
914 if (error == 0) {
915 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
fad57d0e
MD
916 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
917
918 /*
919 * Note that this invalidation will cause any process
920 * currently CD'd into the directory being removed to be
921 * disconnected from the topology and not be able to ".."
922 * back out.
923 */
bf40a153 924 if (error == 0) {
28623bf9 925 cache_inval(nch, CINV_DESTROY);
bf40a153
MD
926 cache_inval_vp(vp, CINV_DESTROY);
927 }
fad57d0e
MD
928 }
929 if (vp) {
930 if (dvp == vp)
931 vrele(vp);
932 else
933 vput(vp);
934 }
935 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
a11aaa81 936 vn_unlock(dvp);
fad57d0e
MD
937 vrele(dvp);
938 return (error);
939}
940
941/*
28623bf9
MD
942 * vop_compat_nrename { struct nchandle *a_fnch, XXX STOPGAP FUNCTION
943 * struct nchandle *a_tnch,
fad57d0e
MD
944 * struct ucred *a_cred }
945 *
946 * This is a fairly difficult procedure. The old VOP_OLD_RENAME requires that
947 * the source directory and vnode be unlocked and the target directory and
948 * vnode (if it exists) be locked. All arguments will be vrele'd and
949 * the targets will also be unlocked regardless of the return code.
950 */
951int
952vop_compat_nrename(struct vop_nrename_args *ap)
953{
954 struct thread *td = curthread;
955 struct componentname fcnp;
956 struct componentname tcnp;
28623bf9
MD
957 struct nchandle *fnch;
958 struct nchandle *tnch;
fad57d0e
MD
959 struct namecache *fncp;
960 struct namecache *tncp;
961 struct vnode *fdvp, *fvp;
962 struct vnode *tdvp, *tvp;
963 int error;
964
965 /*
966 * Sanity checks, get referenced vnodes representing the source.
967 */
28623bf9
MD
968 fnch = ap->a_fnch; /* locked namecache node */
969 fncp = fnch->ncp;
dff430ab 970 fdvp = ap->a_fdvp;
fad57d0e
MD
971
972 /*
973 * Temporarily lock the source directory and lookup in DELETE mode to
974 * check permissions. XXX delete permissions should have been
975 * checked by nlookup(), we need to add NLC_DELETE for delete
976 * checking. It is unclear whether VFS's require the directory setup
977 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
978 * since it isn't locked and since UFS always does a relookup of
979 * the source, it is believed that the only side effect that matters
980 * is the permissions check.
981 */
87de5057 982 if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 983 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
984 fncp, fncp->nc_name);
985 return(EAGAIN);
986 }
987
988 bzero(&fcnp, sizeof(fcnp));
989 fcnp.cn_nameiop = NAMEI_DELETE;
990 fcnp.cn_flags = CNP_LOCKPARENT;
991 fcnp.cn_nameptr = fncp->nc_name;
992 fcnp.cn_namelen = fncp->nc_nlen;
993 fcnp.cn_cred = ap->a_cred;
994 fcnp.cn_td = td;
995
996 /*
e62afb5f 997 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
fad57d0e
MD
998 * fvp.
999 */
1000 fvp = NULL;
e62afb5f 1001 error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
fad57d0e 1002 if (error == 0 && (fvp->v_flag & VROOT)) {
e62afb5f 1003 vput(fvp); /* as if vop_old_lookup had failed */
fad57d0e
MD
1004 error = EBUSY;
1005 }
1006 if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
1007 fcnp.cn_flags |= CNP_PDIRUNLOCK;
a11aaa81 1008 vn_unlock(fdvp);
fad57d0e
MD
1009 }
1010 if (error) {
1011 vrele(fdvp);
1012 return (error);
1013 }
a11aaa81 1014 vn_unlock(fvp);
fad57d0e
MD
1015
1016 /*
1017 * fdvp and fvp are now referenced and unlocked.
1018 *
1019 * Get a locked directory vnode for the target and lookup the target
1020 * in CREATE mode so it places the required information in the
1021 * directory inode.
1022 */
28623bf9
MD
1023 tnch = ap->a_tnch; /* locked namecache node */
1024 tncp = tnch->ncp;
dff430ab 1025 tdvp = ap->a_tdvp;
fad57d0e
MD
1026 if (error) {
1027 vrele(fdvp);
1028 vrele(fvp);
1029 return (error);
1030 }
87de5057 1031 if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) {
6ea70f76 1032 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
fad57d0e
MD
1033 tncp, tncp->nc_name);
1034 vrele(fdvp);
1035 vrele(fvp);
1036 return(EAGAIN);
1037 }
1038
1039 /*
e62afb5f 1040 * Setup the cnp for a traditional vop_old_lookup() call. The lookup
fad57d0e
MD
1041 * caches all information required to create the entry in the
1042 * target directory inode.
1043 */
1044 bzero(&tcnp, sizeof(tcnp));
1045 tcnp.cn_nameiop = NAMEI_RENAME;
1046 tcnp.cn_flags = CNP_LOCKPARENT;
1047 tcnp.cn_nameptr = tncp->nc_name;
1048 tcnp.cn_namelen = tncp->nc_nlen;
1049 tcnp.cn_cred = ap->a_cred;
1050 tcnp.cn_td = td;
1051
1052 tvp = NULL;
e62afb5f 1053 error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
fad57d0e
MD
1054
1055 if (error == EJUSTRETURN) {
1056 /*
1057 * Target does not exist. tvp should be NULL.
1058 */
1059 KKASSERT(tvp == NULL);
1060 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1061 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
227cf16d 1062 if (error == 0)
28623bf9 1063 cache_rename(fnch, tnch);
fad57d0e
MD
1064 } else if (error == 0) {
1065 /*
1066 * Target exists. VOP_OLD_RENAME should correctly delete the
1067 * target.
1068 */
1069 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
1070 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
227cf16d 1071 if (error == 0)
28623bf9 1072 cache_rename(fnch, tnch);
fad57d0e
MD
1073 } else {
1074 vrele(fdvp);
1075 vrele(fvp);
1076 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
1077 vrele(tdvp);
1078 else
1079 vput(tdvp);
1080 }
1081 return (error);
1082}
21739618 1083
984263bc 1084static int
c972a82f 1085vop_nolookup(struct vop_old_lookup_args *ap)
984263bc
MD
1086{
1087
1088 *ap->a_vpp = NULL;
1089 return (ENOTDIR);
1090}
1091
1092/*
1093 * vop_nostrategy:
1094 *
1095 * Strategy routine for VFS devices that have none.
1096 *
1097 * B_ERROR and B_INVAL must be cleared prior to calling any strategy
10f3fee5
MD
1098 * routine. Typically this is done for a BUF_CMD_READ strategy call.
1099 * Typically B_INVAL is assumed to already be clear prior to a write
1100 * and should not be cleared manually unless you just made the buffer
1101 * invalid. B_ERROR should be cleared either way.
984263bc
MD
1102 */
1103
1104static int
1105vop_nostrategy (struct vop_strategy_args *ap)
1106{
6ea70f76 1107 kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
984263bc 1108 vprint("", ap->a_vp);
81b5c339
MD
1109 ap->a_bio->bio_buf->b_flags |= B_ERROR;
1110 ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
1111 biodone(ap->a_bio);
984263bc
MD
1112 return (EOPNOTSUPP);
1113}
1114
1115int
c972a82f 1116vop_stdpathconf(struct vop_pathconf_args *ap)
984263bc 1117{
27469235 1118 int error = 0;
984263bc
MD
1119
1120 switch (ap->a_name) {
27469235
MD
1121 case _PC_LINK_MAX:
1122 *ap->a_retval = LINK_MAX;
1123 break;
1124 case _PC_NAME_MAX:
1125 *ap->a_retval = NAME_MAX;
1126 break;
1127 case _PC_PATH_MAX:
1128 *ap->a_retval = PATH_MAX;
1129 break;
1130 case _PC_MAX_CANON:
1131 *ap->a_retval = MAX_CANON;
1132 break;
1133 case _PC_MAX_INPUT:
1134 *ap->a_retval = MAX_INPUT;
1135 break;
1136 case _PC_PIPE_BUF:
1137 *ap->a_retval = PIPE_BUF;
1138 break;
1139 case _PC_CHOWN_RESTRICTED:
1140 *ap->a_retval = 1;
1141 break;
1142 case _PC_NO_TRUNC:
1143 *ap->a_retval = 1;
1144 break;
1145 case _PC_VDISABLE:
1146 *ap->a_retval = _POSIX_VDISABLE;
1147 break;
1148 default:
1149 error = EINVAL;
1150 break;
984263bc 1151 }
27469235 1152 return (error);
984263bc
MD
1153}
1154
1155/*
8ddc6004
MD
1156 * Standard open.
1157 *
b478fdce 1158 * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp)
8ddc6004
MD
1159 *
1160 * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
1161 */
1162int
1163vop_stdopen(struct vop_open_args *ap)
1164{
1165 struct vnode *vp = ap->a_vp;
1166 struct file *fp;
1167
1168 if ((fp = ap->a_fp) != NULL) {
1169 switch(vp->v_type) {
1170 case VFIFO:
1171 fp->f_type = DTYPE_FIFO;
1172 break;
1173 default:
1174 fp->f_type = DTYPE_VNODE;
1175 break;
1176 }
1177 fp->f_flag = ap->a_mode & FMASK;
1178 fp->f_ops = &vnode_fileops;
1179 fp->f_data = vp;
1180 vref(vp);
1181 }
1182 if (ap->a_mode & FWRITE)
1183 ++vp->v_writecount;
1184 KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
1185 ++vp->v_opencount;
1186 return (0);
1187}
1188
1189/*
1190 * Standard close.
1191 *
b478fdce 1192 * (struct vnode *a_vp, int a_fflag)
8ddc6004
MD
1193 *
1194 * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE. same as a_mode in stdopen?
1195 */
1196int
1197vop_stdclose(struct vop_close_args *ap)
1198{
1199 struct vnode *vp = ap->a_vp;
1200
1201 KASSERT(vp->v_opencount > 0,
ed20d0e3 1202 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d type=%d ops=%p flgs=%08x",
a2a3460a 1203 vp, vp->v_opencount, vp->v_type, *vp->v_ops, vp->v_flag));
8ddc6004
MD
1204 if (ap->a_fflag & FWRITE) {
1205 KASSERT(vp->v_writecount > 0,
ed20d0e3 1206 ("VOP_STDCLOSE: BAD WRITECOUNT %p %d",
8ddc6004
MD
1207 vp, vp->v_writecount));
1208 --vp->v_writecount;
1209 }
1210 --vp->v_opencount;
1211 return (0);
1212}
1213
1214/*
1787385d
MD
1215 * Implement standard getpages and putpages. All filesystems must use
1216 * the buffer cache to back regular files.
1217 */
1218int
1219vop_stdgetpages(struct vop_getpages_args *ap)
1220{
1221 struct mount *mp;
1222 int error;
1223
1224 if ((mp = ap->a_vp->v_mount) != NULL) {
1225 error = vnode_pager_generic_getpages(
1226 ap->a_vp, ap->a_m, ap->a_count,
1c48c952 1227 ap->a_reqpage, ap->a_seqaccess);
1787385d
MD
1228 } else {
1229 error = VM_PAGER_BAD;
1230 }
1231 return (error);
1232}
1233
1234int
1235vop_stdputpages(struct vop_putpages_args *ap)
1236{
1237 struct mount *mp;
1238 int error;
1239
1240 if ((mp = ap->a_vp->v_mount) != NULL) {
1241 error = vnode_pager_generic_putpages(
1242 ap->a_vp, ap->a_m, ap->a_count,
1243 ap->a_sync, ap->a_rtvals);
1244 } else {
1245 error = VM_PAGER_BAD;
1246 }
1247 return (error);
1248}
1249
aec8eea4
MD
1250int
1251vop_stdnoread(struct vop_read_args *ap)
1252{
1253 return (EINVAL);
1254}
1255
1256int
1257vop_stdnowrite(struct vop_write_args *ap)
1258{
1259 return (EINVAL);
1260}
1261
984263bc
MD
1262/*
1263 * vfs default ops
1264 * used to fill the vfs fucntion table to get reasonable default return values.
1265 */
1266int
acde96db 1267vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
984263bc
MD
1268{
1269 return (0);
1270}
1271
1272int
acde96db 1273vfs_stdunmount(struct mount *mp, int mntflags)
984263bc
MD
1274{
1275 return (0);
1276}
1277
177403a9
MD
1278int
1279vop_stdmountctl(struct vop_mountctl_args *ap)
1280{
1281
1282 struct mount *mp;
1283 int error = 0;
1284
1285 mp = ap->a_head.a_ops->head.vv_mount;
1286
1287 switch(ap->a_op) {
1288 case MOUNTCTL_MOUNTFLAGS:
1289 /*
1290 * Get a string buffer with all the mount flags
1291 * names comman separated.
1292 * mount(2) will use this information.
1293 */
dad088a5
MD
1294 *ap->a_res = vfs_flagstostr(mp->mnt_flag & MNT_VISFLAGMASK, NULL,
1295 ap->a_buf, ap->a_buflen, &error);
177403a9
MD
1296 break;
1297 case MOUNTCTL_INSTALL_VFS_JOURNAL:
1298 case MOUNTCTL_RESTART_VFS_JOURNAL:
1299 case MOUNTCTL_REMOVE_VFS_JOURNAL:
1300 case MOUNTCTL_RESYNC_VFS_JOURNAL:
1301 case MOUNTCTL_STATUS_VFS_JOURNAL:
1302 error = journal_mountctl(ap);
1303 break;
1304 default:
1305 error = EOPNOTSUPP;
1306 break;
1307 }
1308 return (error);
1309}
1310
984263bc 1311int
dadab5e9 1312vfs_stdroot(struct mount *mp, struct vnode **vpp)
984263bc
MD
1313{
1314 return (EOPNOTSUPP);
1315}
1316
1317int
acde96db 1318vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
984263bc
MD
1319{
1320 return (EOPNOTSUPP);
1321}
1322
d9fad06e
MD
1323/*
1324 * If the VFS does not implement statvfs, then call statfs and convert
1325 * the values. This code was taken from libc's __cvtstatvfs() function,
1326 * contributed by Joerg Sonnenberger.
1327 */
1328int
1329vfs_stdstatvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
1330{
1331 struct statfs *in;
1332 int error;
1333
1334 in = &mp->mnt_stat;
1335 error = VFS_STATFS(mp, in, cred);
1336 if (error == 0) {
1337 bzero(sbp, sizeof(*sbp));
1338
1339 sbp->f_bsize = in->f_bsize;
1340 sbp->f_frsize = in->f_bsize;
1341 sbp->f_blocks = in->f_blocks;
1342 sbp->f_bfree = in->f_bfree;
1343 sbp->f_bavail = in->f_bavail;
1344 sbp->f_files = in->f_files;
1345 sbp->f_ffree = in->f_ffree;
1346
1347 /*
1348 * XXX
1349 * This field counts the number of available inodes to non-root
1350 * users, but this information is not available via statfs.
1351 * Just ignore this issue by returning the total number
1352 * instead.
1353 */
1354 sbp->f_favail = in->f_ffree;
1355
1356 /*
1357 * XXX
1358 * This field has a different meaning for statfs and statvfs.
1359 * For the former it is the cookie exported for NFS and not
1360 * intended for normal userland use.
1361 */
1362 sbp->f_fsid = 0;
1363
1364 sbp->f_flag = 0;
1365 if (in->f_flags & MNT_RDONLY)
1366 sbp->f_flag |= ST_RDONLY;
1367 if (in->f_flags & MNT_NOSUID)
1368 sbp->f_flag |= ST_NOSUID;
1369 sbp->f_namemax = 0;
1370 sbp->f_owner = in->f_owner;
1371 /*
1372 * XXX
1373 * statfs contains the type as string, statvfs expects it as
1374 * enumeration.
1375 */
1376 sbp->f_type = 0;
1377
1378 sbp->f_syncreads = in->f_syncreads;
1379 sbp->f_syncwrites = in->f_syncwrites;
1380 sbp->f_asyncreads = in->f_asyncreads;
1381 sbp->f_asyncwrites = in->f_asyncwrites;
1382 }
1383 return (error);
1384}
1385
984263bc 1386int
dadab5e9 1387vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
984263bc
MD
1388{
1389 return (EOPNOTSUPP);
1390}
1391
1392int
acde96db 1393vfs_stdstart(struct mount *mp, int flags)
984263bc
MD
1394{
1395 return (0);
1396}
1397
1398int
dadab5e9 1399vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
acde96db 1400 caddr_t arg, struct ucred *cred)
984263bc
MD
1401{
1402 return (EOPNOTSUPP);
1403}
1404
1405int
87de5057 1406vfs_stdsync(struct mount *mp, int waitfor)
984263bc
MD
1407{
1408 return (0);
1409}
1410
43c45e8f 1411int
87de5057 1412vfs_stdnosync(struct mount *mp, int waitfor)
43c45e8f
HP
1413{
1414 return (EOPNOTSUPP);
1415}
1416
984263bc 1417int
b9b0a6d0 1418vfs_stdvget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
984263bc
MD
1419{
1420 return (EOPNOTSUPP);
1421}
1422
1423int
67863d04
MD
1424vfs_stdfhtovp(struct mount *mp, struct vnode *rootvp,
1425 struct fid *fhp, struct vnode **vpp)
984263bc
MD
1426{
1427 return (EOPNOTSUPP);
1428}
1429
1430int
dadab5e9
MD
1431vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
1432 struct ucred **credanonp)
984263bc
MD
1433{
1434 return (EOPNOTSUPP);
1435}
1436
1437int
dadab5e9 1438vfs_stdinit(struct vfsconf *vfsp)
984263bc
MD
1439{
1440 return (0);
1441}
1442
1443int
dadab5e9 1444vfs_stduninit(struct vfsconf *vfsp)
984263bc
MD
1445{
1446 return(0);
1447}
1448
1449int
0f6997f9
MD
1450vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp,
1451 int attrnamespace, const char *attrname,
1452 struct ucred *cred)
984263bc
MD
1453{
1454 return(EOPNOTSUPP);
1455}
1456
e788edda
FT
1457#define ACCOUNTING_NB_FSTYPES 8
1458
1459static const char *accounting_fstypes[ACCOUNTING_NB_FSTYPES] = {
1460 "ext2fs", "hammer", "hpfs", "mfs", "ntfs", "null", "tmpfs", "ufs" };
1461
1462int
1463vfs_stdac_init(struct mount *mp)
1464{
1465 const char* fs_type;
1466 int i, fstype_ok = 0;
1467
e788edda
FT
1468 /* is mounted fs type one we want to do some accounting for ? */
1469 for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
1470 fs_type = accounting_fstypes[i];
1471 if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
1472 sizeof(mp->mnt_stat)) == 0) {
1473 fstype_ok = 1;
1474 break;
1475 }
1476 }
1477 if (fstype_ok == 0)
1478 return (0);
1479
e788edda
FT
1480 vq_init(mp);
1481 return (0);
1482}
1483
75a5a592 1484void
e788edda
FT
1485vfs_stdac_done(struct mount *mp)
1486{
e788edda 1487 vq_done(mp);
e788edda
FT
1488}
1489
75779c3c
AH
1490void
1491vfs_stdncpgen_set(struct mount *mp, struct namecache *ncp)
1492{
1493}
1494
1495int
1496vfs_stdncpgen_test(struct mount *mp, struct namecache *ncp)
1497{
1498 return 0;
1499}
984263bc 1500/* end of vfs default ops */