1*0a6a1f1dSLionel Sambuc /* $NetBSD: ulfs_vfsops.c,v 1.11 2015/09/15 15:01:03 dholland Exp $ */
284d9c625SLionel Sambuc /* from NetBSD: ufs_vfsops.c,v 1.52 2013/01/22 09:39:18 dholland Exp */
384d9c625SLionel Sambuc
484d9c625SLionel Sambuc /*
584d9c625SLionel Sambuc * Copyright (c) 1991, 1993, 1994
684d9c625SLionel Sambuc * The Regents of the University of California. All rights reserved.
784d9c625SLionel Sambuc * (c) UNIX System Laboratories, Inc.
884d9c625SLionel Sambuc * All or some portions of this file are derived from material licensed
984d9c625SLionel Sambuc * to the University of California by American Telephone and Telegraph
1084d9c625SLionel Sambuc * Co. or Unix System Laboratories, Inc. and are reproduced herein with
1184d9c625SLionel Sambuc * the permission of UNIX System Laboratories, Inc.
1284d9c625SLionel Sambuc *
1384d9c625SLionel Sambuc * Redistribution and use in source and binary forms, with or without
1484d9c625SLionel Sambuc * modification, are permitted provided that the following conditions
1584d9c625SLionel Sambuc * are met:
1684d9c625SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
1784d9c625SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1884d9c625SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
1984d9c625SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
2084d9c625SLionel Sambuc * documentation and/or other materials provided with the distribution.
2184d9c625SLionel Sambuc * 3. Neither the name of the University nor the names of its contributors
2284d9c625SLionel Sambuc * may be used to endorse or promote products derived from this software
2384d9c625SLionel Sambuc * without specific prior written permission.
2484d9c625SLionel Sambuc *
2584d9c625SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2684d9c625SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2784d9c625SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2884d9c625SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2984d9c625SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3084d9c625SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3184d9c625SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3284d9c625SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3384d9c625SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3484d9c625SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3584d9c625SLionel Sambuc * SUCH DAMAGE.
3684d9c625SLionel Sambuc *
3784d9c625SLionel Sambuc * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95
3884d9c625SLionel Sambuc */
3984d9c625SLionel Sambuc
4084d9c625SLionel Sambuc #include <sys/cdefs.h>
41*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: ulfs_vfsops.c,v 1.11 2015/09/15 15:01:03 dholland Exp $");
4284d9c625SLionel Sambuc
4384d9c625SLionel Sambuc #if defined(_KERNEL_OPT)
4484d9c625SLionel Sambuc #include "opt_lfs.h"
4584d9c625SLionel Sambuc #include "opt_quota.h"
4684d9c625SLionel Sambuc #endif
4784d9c625SLionel Sambuc
4884d9c625SLionel Sambuc #include <sys/param.h>
4984d9c625SLionel Sambuc #include <sys/mbuf.h>
5084d9c625SLionel Sambuc #include <sys/mount.h>
5184d9c625SLionel Sambuc #include <sys/proc.h>
5284d9c625SLionel Sambuc #include <sys/buf.h>
5384d9c625SLionel Sambuc #include <sys/vnode.h>
5484d9c625SLionel Sambuc #include <sys/kmem.h>
5584d9c625SLionel Sambuc #include <sys/kauth.h>
5684d9c625SLionel Sambuc #include <sys/quotactl.h>
5784d9c625SLionel Sambuc
5884d9c625SLionel Sambuc #include <miscfs/specfs/specdev.h>
5984d9c625SLionel Sambuc
6084d9c625SLionel Sambuc #include <ufs/lfs/lfs.h>
61*0a6a1f1dSLionel Sambuc #include <ufs/lfs/lfs_accessors.h>
6284d9c625SLionel Sambuc #include <ufs/lfs/ulfs_quotacommon.h>
6384d9c625SLionel Sambuc #include <ufs/lfs/ulfs_inode.h>
6484d9c625SLionel Sambuc #include <ufs/lfs/ulfsmount.h>
6584d9c625SLionel Sambuc #include <ufs/lfs/ulfs_extern.h>
6684d9c625SLionel Sambuc #ifdef LFS_DIRHASH
6784d9c625SLionel Sambuc #include <ufs/lfs/ulfs_dirhash.h>
6884d9c625SLionel Sambuc #endif
6984d9c625SLionel Sambuc
7084d9c625SLionel Sambuc /* how many times ulfs_init() was called */
7184d9c625SLionel Sambuc static int ulfs_initcount = 0;
7284d9c625SLionel Sambuc
7384d9c625SLionel Sambuc /*
7484d9c625SLionel Sambuc * Make a filesystem operational.
7584d9c625SLionel Sambuc * Nothing to do at the moment.
7684d9c625SLionel Sambuc */
7784d9c625SLionel Sambuc /* ARGSUSED */
7884d9c625SLionel Sambuc int
ulfs_start(struct mount * mp,int flags)7984d9c625SLionel Sambuc ulfs_start(struct mount *mp, int flags)
8084d9c625SLionel Sambuc {
8184d9c625SLionel Sambuc
8284d9c625SLionel Sambuc return (0);
8384d9c625SLionel Sambuc }
8484d9c625SLionel Sambuc
8584d9c625SLionel Sambuc /*
8684d9c625SLionel Sambuc * Return the root of a filesystem.
8784d9c625SLionel Sambuc */
8884d9c625SLionel Sambuc int
ulfs_root(struct mount * mp,struct vnode ** vpp)8984d9c625SLionel Sambuc ulfs_root(struct mount *mp, struct vnode **vpp)
9084d9c625SLionel Sambuc {
9184d9c625SLionel Sambuc struct vnode *nvp;
9284d9c625SLionel Sambuc int error;
9384d9c625SLionel Sambuc
9484d9c625SLionel Sambuc if ((error = VFS_VGET(mp, (ino_t)ULFS_ROOTINO, &nvp)) != 0)
9584d9c625SLionel Sambuc return (error);
9684d9c625SLionel Sambuc *vpp = nvp;
9784d9c625SLionel Sambuc return (0);
9884d9c625SLionel Sambuc }
9984d9c625SLionel Sambuc
10084d9c625SLionel Sambuc /*
10184d9c625SLionel Sambuc * Do operations associated with quotas
10284d9c625SLionel Sambuc */
10384d9c625SLionel Sambuc int
ulfs_quotactl(struct mount * mp,struct quotactl_args * args)10484d9c625SLionel Sambuc ulfs_quotactl(struct mount *mp, struct quotactl_args *args)
10584d9c625SLionel Sambuc {
10684d9c625SLionel Sambuc
10784d9c625SLionel Sambuc #if !defined(LFS_QUOTA) && !defined(LFS_QUOTA2)
10884d9c625SLionel Sambuc (void) mp;
10984d9c625SLionel Sambuc (void) args;
11084d9c625SLionel Sambuc return (EOPNOTSUPP);
11184d9c625SLionel Sambuc #else
11284d9c625SLionel Sambuc struct lwp *l = curlwp;
11384d9c625SLionel Sambuc int error;
11484d9c625SLionel Sambuc
11584d9c625SLionel Sambuc /* Mark the mount busy, as we're passing it to kauth(9). */
11684d9c625SLionel Sambuc error = vfs_busy(mp, NULL);
11784d9c625SLionel Sambuc if (error) {
11884d9c625SLionel Sambuc return (error);
11984d9c625SLionel Sambuc }
12084d9c625SLionel Sambuc mutex_enter(&mp->mnt_updating);
12184d9c625SLionel Sambuc
12284d9c625SLionel Sambuc error = lfsquota_handle_cmd(mp, l, args);
12384d9c625SLionel Sambuc
12484d9c625SLionel Sambuc mutex_exit(&mp->mnt_updating);
12584d9c625SLionel Sambuc vfs_unbusy(mp, false, NULL);
12684d9c625SLionel Sambuc return (error);
12784d9c625SLionel Sambuc #endif
12884d9c625SLionel Sambuc }
12984d9c625SLionel Sambuc
13084d9c625SLionel Sambuc #if 0
13184d9c625SLionel Sambuc switch (cmd) {
13284d9c625SLionel Sambuc case Q_SYNC:
13384d9c625SLionel Sambuc break;
13484d9c625SLionel Sambuc
13584d9c625SLionel Sambuc case Q_GETQUOTA:
13684d9c625SLionel Sambuc /* The user can always query about his own quota. */
13784d9c625SLionel Sambuc if (uid == kauth_cred_getuid(l->l_cred))
13884d9c625SLionel Sambuc break;
13984d9c625SLionel Sambuc
14084d9c625SLionel Sambuc error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
14184d9c625SLionel Sambuc KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(uid), NULL);
14284d9c625SLionel Sambuc
14384d9c625SLionel Sambuc break;
14484d9c625SLionel Sambuc
14584d9c625SLionel Sambuc case Q_QUOTAON:
14684d9c625SLionel Sambuc case Q_QUOTAOFF:
14784d9c625SLionel Sambuc error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
14884d9c625SLionel Sambuc KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
14984d9c625SLionel Sambuc
15084d9c625SLionel Sambuc break;
15184d9c625SLionel Sambuc
15284d9c625SLionel Sambuc case Q_SETQUOTA:
15384d9c625SLionel Sambuc case Q_SETUSE:
15484d9c625SLionel Sambuc error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
15584d9c625SLionel Sambuc KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(uid), NULL);
15684d9c625SLionel Sambuc
15784d9c625SLionel Sambuc break;
15884d9c625SLionel Sambuc
15984d9c625SLionel Sambuc default:
16084d9c625SLionel Sambuc error = EINVAL;
16184d9c625SLionel Sambuc break;
16284d9c625SLionel Sambuc }
16384d9c625SLionel Sambuc
16484d9c625SLionel Sambuc type = cmds & SUBCMDMASK;
16584d9c625SLionel Sambuc if (!error) {
16684d9c625SLionel Sambuc /* Only check if there was no error above. */
16784d9c625SLionel Sambuc if ((u_int)type >= MAXQUOTAS)
16884d9c625SLionel Sambuc error = EINVAL;
16984d9c625SLionel Sambuc }
17084d9c625SLionel Sambuc
17184d9c625SLionel Sambuc if (error) {
17284d9c625SLionel Sambuc vfs_unbusy(mp, false, NULL);
17384d9c625SLionel Sambuc return (error);
17484d9c625SLionel Sambuc }
17584d9c625SLionel Sambuc
17684d9c625SLionel Sambuc mutex_enter(&mp->mnt_updating);
17784d9c625SLionel Sambuc switch (cmd) {
17884d9c625SLionel Sambuc
17984d9c625SLionel Sambuc case Q_QUOTAON:
18084d9c625SLionel Sambuc error = quotaon(l, mp, type, arg);
18184d9c625SLionel Sambuc break;
18284d9c625SLionel Sambuc
18384d9c625SLionel Sambuc case Q_QUOTAOFF:
18484d9c625SLionel Sambuc error = quotaoff(l, mp, type);
18584d9c625SLionel Sambuc break;
18684d9c625SLionel Sambuc
18784d9c625SLionel Sambuc case Q_SETQUOTA:
18884d9c625SLionel Sambuc error = setquota(mp, uid, type, arg);
18984d9c625SLionel Sambuc break;
19084d9c625SLionel Sambuc
19184d9c625SLionel Sambuc case Q_SETUSE:
19284d9c625SLionel Sambuc error = setuse(mp, uid, type, arg);
19384d9c625SLionel Sambuc break;
19484d9c625SLionel Sambuc
19584d9c625SLionel Sambuc case Q_GETQUOTA:
19684d9c625SLionel Sambuc error = getquota(mp, uid, type, arg);
19784d9c625SLionel Sambuc break;
19884d9c625SLionel Sambuc
19984d9c625SLionel Sambuc case Q_SYNC:
20084d9c625SLionel Sambuc error = lfs_qsync(mp);
20184d9c625SLionel Sambuc break;
20284d9c625SLionel Sambuc
20384d9c625SLionel Sambuc default:
20484d9c625SLionel Sambuc error = EINVAL;
20584d9c625SLionel Sambuc }
20684d9c625SLionel Sambuc mutex_exit(&mp->mnt_updating);
20784d9c625SLionel Sambuc vfs_unbusy(mp, false, NULL);
20884d9c625SLionel Sambuc return (error);
20984d9c625SLionel Sambuc #endif
21084d9c625SLionel Sambuc
21184d9c625SLionel Sambuc /*
21284d9c625SLionel Sambuc * This is the generic part of fhtovp called after the underlying
21384d9c625SLionel Sambuc * filesystem has validated the file handle.
21484d9c625SLionel Sambuc */
21584d9c625SLionel Sambuc int
ulfs_fhtovp(struct mount * mp,struct ulfs_ufid * ufhp,struct vnode ** vpp)21684d9c625SLionel Sambuc ulfs_fhtovp(struct mount *mp, struct ulfs_ufid *ufhp, struct vnode **vpp)
21784d9c625SLionel Sambuc {
21884d9c625SLionel Sambuc struct vnode *nvp;
21984d9c625SLionel Sambuc struct inode *ip;
22084d9c625SLionel Sambuc int error;
22184d9c625SLionel Sambuc
22284d9c625SLionel Sambuc if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
223*0a6a1f1dSLionel Sambuc if (error == ENOENT)
224*0a6a1f1dSLionel Sambuc error = ESTALE;
22584d9c625SLionel Sambuc *vpp = NULLVP;
22684d9c625SLionel Sambuc return (error);
22784d9c625SLionel Sambuc }
22884d9c625SLionel Sambuc ip = VTOI(nvp);
22984d9c625SLionel Sambuc KASSERT(ip != NULL);
23084d9c625SLionel Sambuc if (ip->i_mode == 0 || ip->i_gen != ufhp->ufid_gen) {
23184d9c625SLionel Sambuc vput(nvp);
23284d9c625SLionel Sambuc *vpp = NULLVP;
23384d9c625SLionel Sambuc return (ESTALE);
23484d9c625SLionel Sambuc }
23584d9c625SLionel Sambuc *vpp = nvp;
23684d9c625SLionel Sambuc return (0);
23784d9c625SLionel Sambuc }
23884d9c625SLionel Sambuc
23984d9c625SLionel Sambuc /*
24084d9c625SLionel Sambuc * Initialize ULFS filesystems, done only once.
24184d9c625SLionel Sambuc */
24284d9c625SLionel Sambuc void
ulfs_init(void)24384d9c625SLionel Sambuc ulfs_init(void)
24484d9c625SLionel Sambuc {
24584d9c625SLionel Sambuc if (ulfs_initcount++ > 0)
24684d9c625SLionel Sambuc return;
24784d9c625SLionel Sambuc
24884d9c625SLionel Sambuc #if defined(LFS_QUOTA) || defined(LFS_QUOTA2)
24984d9c625SLionel Sambuc lfs_dqinit();
25084d9c625SLionel Sambuc #endif
25184d9c625SLionel Sambuc #ifdef LFS_DIRHASH
25284d9c625SLionel Sambuc ulfsdirhash_init();
25384d9c625SLionel Sambuc #endif
25484d9c625SLionel Sambuc #ifdef LFS_EXTATTR
25584d9c625SLionel Sambuc ulfs_extattr_init();
25684d9c625SLionel Sambuc #endif
25784d9c625SLionel Sambuc }
25884d9c625SLionel Sambuc
25984d9c625SLionel Sambuc void
ulfs_reinit(void)26084d9c625SLionel Sambuc ulfs_reinit(void)
26184d9c625SLionel Sambuc {
262*0a6a1f1dSLionel Sambuc
26384d9c625SLionel Sambuc #if defined(LFS_QUOTA) || defined(LFS_QUOTA2)
26484d9c625SLionel Sambuc lfs_dqreinit();
26584d9c625SLionel Sambuc #endif
26684d9c625SLionel Sambuc }
26784d9c625SLionel Sambuc
26884d9c625SLionel Sambuc /*
26984d9c625SLionel Sambuc * Free ULFS filesystem resources, done only once.
27084d9c625SLionel Sambuc */
27184d9c625SLionel Sambuc void
ulfs_done(void)27284d9c625SLionel Sambuc ulfs_done(void)
27384d9c625SLionel Sambuc {
27484d9c625SLionel Sambuc if (--ulfs_initcount > 0)
27584d9c625SLionel Sambuc return;
27684d9c625SLionel Sambuc
27784d9c625SLionel Sambuc #if defined(LFS_QUOTA) || defined(LFS_QUOTA2)
27884d9c625SLionel Sambuc lfs_dqdone();
27984d9c625SLionel Sambuc #endif
28084d9c625SLionel Sambuc #ifdef LFS_DIRHASH
28184d9c625SLionel Sambuc ulfsdirhash_done();
28284d9c625SLionel Sambuc #endif
28384d9c625SLionel Sambuc #ifdef LFS_EXTATTR
28484d9c625SLionel Sambuc ulfs_extattr_done();
28584d9c625SLionel Sambuc #endif
28684d9c625SLionel Sambuc }
287