1 | /* $NetBSD: layer_vfsops.c,v 1.46 2015/04/20 19:36:55 riastradh Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 1999 National Aeronautics & Space Administration |
5 | * All rights reserved. |
6 | * |
7 | * This software was written by William Studenmund of the |
8 | * Numerical Aerospace Simulation Facility, NASA Ames Research Center. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. Neither the name of the National Aeronautics & Space Administration |
19 | * nor the names of its contributors may be used to endorse or promote |
20 | * products derived from this software without specific prior written |
21 | * permission. |
22 | * |
23 | * THIS SOFTWARE IS PROVIDED BY THE NATIONAL AERONAUTICS & SPACE ADMINISTRATION |
24 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
25 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
26 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ADMINISTRATION OR CONTRIB- |
27 | * UTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
28 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
33 | * POSSIBILITY OF SUCH DAMAGE. |
34 | */ |
35 | |
36 | /* |
37 | * Copyright (c) 1992, 1993, 1995 |
38 | * The Regents of the University of California. All rights reserved. |
39 | * |
40 | * This code is derived from software donated to Berkeley by |
41 | * Jan-Simon Pendry. |
42 | * |
43 | * Redistribution and use in source and binary forms, with or without |
44 | * modification, are permitted provided that the following conditions |
45 | * are met: |
46 | * 1. Redistributions of source code must retain the above copyright |
47 | * notice, this list of conditions and the following disclaimer. |
48 | * 2. Redistributions in binary form must reproduce the above copyright |
49 | * notice, this list of conditions and the following disclaimer in the |
50 | * documentation and/or other materials provided with the distribution. |
51 | * 3. Neither the name of the University nor the names of its contributors |
52 | * may be used to endorse or promote products derived from this software |
53 | * without specific prior written permission. |
54 | * |
55 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
56 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
57 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
58 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
59 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
60 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
61 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
62 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
63 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
64 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
65 | * SUCH DAMAGE. |
66 | * |
67 | * from: Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp |
68 | * from: @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92 |
69 | * @(#)null_vfsops.c 8.7 (Berkeley) 5/14/95 |
70 | */ |
71 | |
72 | /* |
73 | * Generic layer VFS operations. |
74 | */ |
75 | |
76 | #include <sys/cdefs.h> |
77 | __KERNEL_RCSID(0, "$NetBSD: layer_vfsops.c,v 1.46 2015/04/20 19:36:55 riastradh Exp $" ); |
78 | |
79 | #include <sys/param.h> |
80 | #include <sys/sysctl.h> |
81 | #include <sys/systm.h> |
82 | #include <sys/vnode.h> |
83 | #include <sys/mount.h> |
84 | #include <sys/namei.h> |
85 | #include <sys/kauth.h> |
86 | #include <sys/module.h> |
87 | |
88 | #include <miscfs/specfs/specdev.h> |
89 | #include <miscfs/genfs/layer.h> |
90 | #include <miscfs/genfs/layer_extern.h> |
91 | |
92 | SYSCTL_SETUP_PROTO(sysctl_vfs_layerfs_setup); |
93 | |
94 | MODULE(MODULE_CLASS_MISC, layerfs, NULL); |
95 | |
96 | static int |
97 | layerfs_modcmd(modcmd_t cmd, void *arg) |
98 | { |
99 | #ifdef _MODULE |
100 | static struct sysctllog *layerfs_clog = NULL; |
101 | #endif |
102 | |
103 | switch (cmd) { |
104 | case MODULE_CMD_INIT: |
105 | #ifdef _MODULE |
106 | sysctl_vfs_layerfs_setup(&layerfs_clog); |
107 | #endif |
108 | return 0; |
109 | case MODULE_CMD_FINI: |
110 | #ifdef _MODULE |
111 | sysctl_teardown(&layerfs_clog); |
112 | #endif |
113 | return 0; |
114 | default: |
115 | return ENOTTY; |
116 | } |
117 | return 0; |
118 | } |
119 | |
120 | /* |
121 | * VFS start. Nothing needed here - the start routine on the underlying |
122 | * filesystem will have been called when that filesystem was mounted. |
123 | */ |
124 | int |
125 | layerfs_start(struct mount *mp, int flags) |
126 | { |
127 | |
128 | #ifdef notyet |
129 | return VFS_START(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, flags); |
130 | #else |
131 | return 0; |
132 | #endif |
133 | } |
134 | |
135 | int |
136 | layerfs_root(struct mount *mp, struct vnode **vpp) |
137 | { |
138 | struct vnode *vp; |
139 | |
140 | vp = MOUNTTOLAYERMOUNT(mp)->layerm_rootvp; |
141 | if (vp == NULL) { |
142 | *vpp = NULL; |
143 | return EINVAL; |
144 | } |
145 | /* |
146 | * Return root vnode with locked and with a reference held. |
147 | */ |
148 | vref(vp); |
149 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
150 | *vpp = vp; |
151 | return 0; |
152 | } |
153 | |
154 | int |
155 | layerfs_quotactl(struct mount *mp, struct quotactl_args *args) |
156 | { |
157 | |
158 | return VFS_QUOTACTL(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, args); |
159 | } |
160 | |
161 | int |
162 | layerfs_statvfs(struct mount *mp, struct statvfs *sbp) |
163 | { |
164 | struct statvfs *sbuf; |
165 | int error; |
166 | |
167 | sbuf = kmem_zalloc(sizeof(*sbuf), KM_SLEEP); |
168 | if (sbuf == NULL) { |
169 | return ENOMEM; |
170 | } |
171 | error = VFS_STATVFS(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, sbuf); |
172 | if (error) { |
173 | goto done; |
174 | } |
175 | /* Copy across the relevant data and fake the rest. */ |
176 | sbp->f_flag = sbuf->f_flag; |
177 | sbp->f_bsize = sbuf->f_bsize; |
178 | sbp->f_frsize = sbuf->f_frsize; |
179 | sbp->f_iosize = sbuf->f_iosize; |
180 | sbp->f_blocks = sbuf->f_blocks; |
181 | sbp->f_bfree = sbuf->f_bfree; |
182 | sbp->f_bavail = sbuf->f_bavail; |
183 | sbp->f_bresvd = sbuf->f_bresvd; |
184 | sbp->f_files = sbuf->f_files; |
185 | sbp->f_ffree = sbuf->f_ffree; |
186 | sbp->f_favail = sbuf->f_favail; |
187 | sbp->f_fresvd = sbuf->f_fresvd; |
188 | sbp->f_namemax = sbuf->f_namemax; |
189 | copy_statvfs_info(sbp, mp); |
190 | done: |
191 | kmem_free(sbuf, sizeof(*sbuf)); |
192 | return error; |
193 | } |
194 | |
195 | int |
196 | layerfs_sync(struct mount *mp, int waitfor, |
197 | kauth_cred_t cred) |
198 | { |
199 | |
200 | /* |
201 | * XXX - Assumes no data cached at layer. |
202 | */ |
203 | return 0; |
204 | } |
205 | |
206 | int |
207 | layerfs_loadvnode(struct mount *mp, struct vnode *vp, |
208 | const void *key, size_t key_len, const void **new_key) |
209 | { |
210 | struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp); |
211 | struct vnode *lowervp; |
212 | struct layer_node *xp; |
213 | |
214 | KASSERT(key_len == sizeof(struct vnode *)); |
215 | memcpy(&lowervp, key, key_len); |
216 | |
217 | xp = kmem_alloc(lmp->layerm_size, KM_SLEEP); |
218 | if (xp == NULL) |
219 | return ENOMEM; |
220 | |
221 | /* Share the interlock with the lower node. */ |
222 | mutex_obj_hold(lowervp->v_interlock); |
223 | uvm_obj_setlock(&vp->v_uobj, lowervp->v_interlock); |
224 | |
225 | vp->v_tag = lmp->layerm_tag; |
226 | vp->v_type = lowervp->v_type; |
227 | vp->v_op = lmp->layerm_vnodeop_p; |
228 | if (vp->v_type == VBLK || vp->v_type == VCHR) |
229 | spec_node_init(vp, lowervp->v_rdev); |
230 | vp->v_data = xp; |
231 | xp->layer_vnode = vp; |
232 | xp->layer_lowervp = lowervp; |
233 | xp->layer_flags = 0; |
234 | uvm_vnp_setsize(vp, 0); |
235 | |
236 | /* Add a reference to the lower node. */ |
237 | vref(lowervp); |
238 | *new_key = &xp->layer_lowervp; |
239 | return 0; |
240 | } |
241 | |
242 | int |
243 | layerfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) |
244 | { |
245 | struct vnode *vp; |
246 | int error; |
247 | |
248 | error = VFS_VGET(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, ino, &vp); |
249 | if (error) { |
250 | *vpp = NULL; |
251 | return error; |
252 | } |
253 | VOP_UNLOCK(vp); |
254 | error = layer_node_create(mp, vp, vpp); |
255 | if (error) { |
256 | vrele(vp); |
257 | *vpp = NULL; |
258 | return error; |
259 | } |
260 | error = vn_lock(*vpp, LK_EXCLUSIVE); |
261 | if (error) { |
262 | vrele(*vpp); |
263 | *vpp = NULL; |
264 | return error; |
265 | } |
266 | return 0; |
267 | } |
268 | |
269 | int |
270 | layerfs_fhtovp(struct mount *mp, struct fid *fidp, struct vnode **vpp) |
271 | { |
272 | struct vnode *vp; |
273 | int error; |
274 | |
275 | error = VFS_FHTOVP(MOUNTTOLAYERMOUNT(mp)->layerm_vfs, fidp, &vp); |
276 | if (error) { |
277 | *vpp = NULL; |
278 | return error; |
279 | } |
280 | VOP_UNLOCK(vp); |
281 | error = layer_node_create(mp, vp, vpp); |
282 | if (error) { |
283 | vput(vp); |
284 | *vpp = NULL; |
285 | return (error); |
286 | } |
287 | error = vn_lock(*vpp, LK_EXCLUSIVE); |
288 | if (error) { |
289 | vrele(*vpp); |
290 | *vpp = NULL; |
291 | return error; |
292 | } |
293 | return 0; |
294 | } |
295 | |
296 | int |
297 | layerfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) |
298 | { |
299 | |
300 | return VFS_VPTOFH(LAYERVPTOLOWERVP(vp), fhp, fh_size); |
301 | } |
302 | |
303 | /* |
304 | * layerfs_snapshot - handle a snapshot through a layered file system |
305 | * |
306 | * At present, we do NOT support snapshotting through a layered file |
307 | * system as the ffs implementation changes v_vnlock of the snapshot |
308 | * vnodes to point to one common lock. As there is no way for us to |
309 | * absolutely pass this change up the stack, a layered file system |
310 | * would end up referencing the wrong lock. |
311 | * |
312 | * This routine serves as a central resource for this behavior; all |
313 | * layered file systems don't need to worry about the above. Also, if |
314 | * things get fixed, all layers get the benefit. |
315 | */ |
316 | int |
317 | layerfs_snapshot(struct mount *mp, struct vnode *vp, |
318 | struct timespec *ts) |
319 | { |
320 | |
321 | return EOPNOTSUPP; |
322 | } |
323 | |
324 | SYSCTL_SETUP(sysctl_vfs_layerfs_setup, "sysctl vfs.layerfs subtree setup" ) |
325 | { |
326 | const struct sysctlnode *layerfs_node = NULL; |
327 | |
328 | sysctl_createv(clog, 0, NULL, &layerfs_node, |
329 | #ifdef _MODULE |
330 | 0, |
331 | #else |
332 | CTLFLAG_PERMANENT, |
333 | #endif |
334 | CTLTYPE_NODE, "layerfs" , |
335 | SYSCTL_DESCR("Generic layered file system" ), |
336 | NULL, 0, NULL, 0, |
337 | CTL_VFS, CTL_CREATE, CTL_EOL); |
338 | |
339 | #ifdef LAYERFS_DIAGNOSTIC |
340 | sysctl_createv(clog, 0, &layerfs_node, NULL, |
341 | #ifndef _MODULE |
342 | CTLFLAG_PERMANENT | |
343 | #endif |
344 | CTLFLAG_READWRITE, |
345 | CTLTYPE_INT, |
346 | "debug" , |
347 | SYSCTL_DESCR("Verbose debugging messages" ), |
348 | NULL, 0, &layerfs_debug, 0, |
349 | CTL_CREATE, CTL_EOL); |
350 | #endif |
351 | |
352 | /* |
353 | * other subtrees should really be aliases to this, but since |
354 | * they can't tell if layerfs has been instantiated yet, they |
355 | * can't do that...not easily. not yet. :-) |
356 | */ |
357 | } |
358 | |
359 | int |
360 | layerfs_renamelock_enter(struct mount *mp) |
361 | { |
362 | |
363 | return VFS_RENAMELOCK_ENTER(MOUNTTOLAYERMOUNT(mp)->layerm_vfs); |
364 | } |
365 | |
366 | void |
367 | layerfs_renamelock_exit(struct mount *mp) |
368 | { |
369 | |
370 | VFS_RENAMELOCK_EXIT(MOUNTTOLAYERMOUNT(mp)->layerm_vfs); |
371 | } |
372 | |