xref: /minix/sys/ufs/ufs/ufs_vfsops.c (revision 0a6a1f1d)
1 /*	$NetBSD: ufs_vfsops.c,v 1.54 2015/03/17 09:39:29 hannken Exp $	*/
2 
3 /*
4  * Copyright (c) 1991, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  * (c) UNIX System Laboratories, Inc.
7  * All or some portions of this file are derived from material licensed
8  * to the University of California by American Telephone and Telegraph
9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10  * the permission of UNIX System Laboratories, Inc.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	@(#)ufs_vfsops.c	8.8 (Berkeley) 5/20/95
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c,v 1.54 2015/03/17 09:39:29 hannken Exp $");
41 
42 #if defined(_KERNEL_OPT)
43 #include "opt_ffs.h"
44 #include "opt_quota.h"
45 #endif
46 
47 #include <sys/param.h>
48 #include <sys/mbuf.h>
49 #include <sys/mount.h>
50 #include <sys/proc.h>
51 #include <sys/buf.h>
52 #include <sys/vnode.h>
53 #include <sys/kmem.h>
54 #include <sys/kauth.h>
55 
56 #include <miscfs/specfs/specdev.h>
57 
58 #include <sys/quotactl.h>
59 #include <ufs/ufs/quota.h>
60 #include <ufs/ufs/inode.h>
61 #include <ufs/ufs/ufsmount.h>
62 #include <ufs/ufs/ufs_extern.h>
63 #ifdef UFS_DIRHASH
64 #include <ufs/ufs/dirhash.h>
65 #endif
66 
67 /* how many times ufs_init() was called */
68 static int ufs_initcount = 0;
69 
70 pool_cache_t ufs_direct_cache;
71 
72 /*
73  * Make a filesystem operational.
74  * Nothing to do at the moment.
75  */
76 /* ARGSUSED */
77 int
ufs_start(struct mount * mp,int flags)78 ufs_start(struct mount *mp, int flags)
79 {
80 
81 	return (0);
82 }
83 
84 /*
85  * Return the root of a filesystem.
86  */
87 int
ufs_root(struct mount * mp,struct vnode ** vpp)88 ufs_root(struct mount *mp, struct vnode **vpp)
89 {
90 	struct vnode *nvp;
91 	int error;
92 
93 	if ((error = VFS_VGET(mp, (ino_t)UFS_ROOTINO, &nvp)) != 0)
94 		return (error);
95 	*vpp = nvp;
96 	return (0);
97 }
98 
99 /*
100  * Look up and return a vnode/inode pair by inode number.
101  */
102 int
ufs_vget(struct mount * mp,ino_t ino,struct vnode ** vpp)103 ufs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
104 {
105 	int error;
106 
107 	error = vcache_get(mp, &ino, sizeof(ino), vpp);
108 	if (error)
109 		return error;
110 	error = vn_lock(*vpp, LK_EXCLUSIVE);
111 	if (error) {
112 		vrele(*vpp);
113 		*vpp = NULL;
114 		return error;
115 	}
116 	return 0;
117 }
118 
119 /*
120  * Do operations associated with quotas
121  */
122 int
ufs_quotactl(struct mount * mp,struct quotactl_args * args)123 ufs_quotactl(struct mount *mp, struct quotactl_args *args)
124 {
125 
126 #if !defined(QUOTA) && !defined(QUOTA2)
127 	(void) mp;
128 	(void) args;
129 	return (EOPNOTSUPP);
130 #else
131 	struct lwp *l = curlwp;
132 	int error;
133 
134 	/* Mark the mount busy, as we're passing it to kauth(9). */
135 	error = vfs_busy(mp, NULL);
136 	if (error) {
137 		return (error);
138 	}
139 	mutex_enter(&mp->mnt_updating);
140 
141 	error = quota_handle_cmd(mp, l, args);
142 
143 	mutex_exit(&mp->mnt_updating);
144 	vfs_unbusy(mp, false, NULL);
145 	return (error);
146 #endif
147 }
148 
149 #if 0
150 	switch (cmd) {
151 	case Q_SYNC:
152 		break;
153 
154 	case Q_GETQUOTA:
155 		/* The user can always query about his own quota. */
156 		if (uid == kauth_cred_getuid(l->l_cred))
157 			break;
158 
159 		error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
160 		    KAUTH_REQ_SYSTEM_FS_QUOTA_GET, mp, KAUTH_ARG(uid), NULL);
161 
162 		break;
163 
164 	case Q_QUOTAON:
165 	case Q_QUOTAOFF:
166 		error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
167 		    KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF, mp, NULL, NULL);
168 
169 		break;
170 
171 	case Q_SETQUOTA:
172 	case Q_SETUSE:
173 		error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_FS_QUOTA,
174 		    KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE, mp, KAUTH_ARG(uid), NULL);
175 
176 		break;
177 
178 	default:
179 		error = EINVAL;
180 		break;
181 	}
182 
183 	type = cmds & SUBCMDMASK;
184 	if (!error) {
185 		/* Only check if there was no error above. */
186 		if ((u_int)type >= MAXQUOTAS)
187 			error = EINVAL;
188 	}
189 
190 	if (error) {
191 		vfs_unbusy(mp, false, NULL);
192 		return (error);
193 	}
194 
195 	mutex_enter(&mp->mnt_updating);
196 	switch (cmd) {
197 
198 	case Q_QUOTAON:
199 		error = quotaon(l, mp, type, arg);
200 		break;
201 
202 	case Q_QUOTAOFF:
203 		error = quotaoff(l, mp, type);
204 		break;
205 
206 	case Q_SETQUOTA:
207 		error = setquota(mp, uid, type, arg);
208 		break;
209 
210 	case Q_SETUSE:
211 		error = setuse(mp, uid, type, arg);
212 		break;
213 
214 	case Q_GETQUOTA:
215 		error = getquota(mp, uid, type, arg);
216 		break;
217 
218 	case Q_SYNC:
219 		error = qsync(mp);
220 		break;
221 
222 	default:
223 		error = EINVAL;
224 	}
225 	mutex_exit(&mp->mnt_updating);
226 	vfs_unbusy(mp, false, NULL);
227 	return (error);
228 #endif
229 
230 /*
231  * This is the generic part of fhtovp called after the underlying
232  * filesystem has validated the file handle.
233  */
234 int
ufs_fhtovp(struct mount * mp,struct ufid * ufhp,struct vnode ** vpp)235 ufs_fhtovp(struct mount *mp, struct ufid *ufhp, struct vnode **vpp)
236 {
237 	struct vnode *nvp;
238 	struct inode *ip;
239 	int error;
240 
241 	if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) {
242 		if (error == ENOENT)
243 			error = ESTALE;
244 		*vpp = NULLVP;
245 		return (error);
246 	}
247 	ip = VTOI(nvp);
248 	KASSERT(ip != NULL);
249 	if (ip->i_mode == 0 || ip->i_gen != ufhp->ufid_gen) {
250 		vput(nvp);
251 		*vpp = NULLVP;
252 		return (ESTALE);
253 	}
254 	*vpp = nvp;
255 	return (0);
256 }
257 
258 /*
259  * Initialize UFS filesystems, done only once.
260  */
261 void
ufs_init(void)262 ufs_init(void)
263 {
264 	if (ufs_initcount++ > 0)
265 		return;
266 
267 	ufs_direct_cache = pool_cache_init(sizeof(struct direct), 0, 0, 0,
268 	    "ufsdir", NULL, IPL_NONE, NULL, NULL, NULL);
269 
270 #if defined(QUOTA) || defined(QUOTA2)
271 	dqinit();
272 #endif
273 #ifdef UFS_DIRHASH
274 	ufsdirhash_init();
275 #endif
276 #ifdef UFS_EXTATTR
277 	ufs_extattr_init();
278 #endif
279 }
280 
281 void
ufs_reinit(void)282 ufs_reinit(void)
283 {
284 #if defined(QUOTA) || defined(QUOTA2)
285 	dqreinit();
286 #endif
287 }
288 
289 /*
290  * Free UFS filesystem resources, done only once.
291  */
292 void
ufs_done(void)293 ufs_done(void)
294 {
295 	if (--ufs_initcount > 0)
296 		return;
297 
298 #if defined(QUOTA) || defined(QUOTA2)
299 	dqdone();
300 #endif
301 	pool_cache_destroy(ufs_direct_cache);
302 #ifdef UFS_DIRHASH
303 	ufsdirhash_done();
304 #endif
305 #ifdef UFS_EXTATTR
306 	ufs_extattr_done();
307 #endif
308 }
309