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