null_vnops.c revision 1.13 1 1.13 fvdl /* $NetBSD: null_vnops.c,v 1.13 1998/03/01 02:21:43 fvdl Exp $ */
2 1.2 cgd
3 1.1 mycroft /*
4 1.1 mycroft * Copyright (c) 1992, 1993
5 1.1 mycroft * The Regents of the University of California. All rights reserved.
6 1.1 mycroft *
7 1.1 mycroft * This code is derived from software contributed to Berkeley by
8 1.1 mycroft * John Heidemann of the UCLA Ficus project.
9 1.1 mycroft *
10 1.1 mycroft * Redistribution and use in source and binary forms, with or without
11 1.1 mycroft * modification, are permitted provided that the following conditions
12 1.1 mycroft * are met:
13 1.1 mycroft * 1. Redistributions of source code must retain the above copyright
14 1.1 mycroft * notice, this list of conditions and the following disclaimer.
15 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 mycroft * notice, this list of conditions and the following disclaimer in the
17 1.1 mycroft * documentation and/or other materials provided with the distribution.
18 1.1 mycroft * 3. All advertising materials mentioning features or use of this software
19 1.1 mycroft * must display the following acknowledgement:
20 1.1 mycroft * This product includes software developed by the University of
21 1.1 mycroft * California, Berkeley and its contributors.
22 1.1 mycroft * 4. Neither the name of the University nor the names of its contributors
23 1.1 mycroft * may be used to endorse or promote products derived from this software
24 1.1 mycroft * without specific prior written permission.
25 1.1 mycroft *
26 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 1.1 mycroft * SUCH DAMAGE.
37 1.1 mycroft *
38 1.13 fvdl * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95
39 1.1 mycroft *
40 1.1 mycroft * Ancestors:
41 1.1 mycroft * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92
42 1.13 fvdl * $Id: null_vnops.c,v 1.13 1998/03/01 02:21:43 fvdl Exp $
43 1.1 mycroft * ...and...
44 1.1 mycroft * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
45 1.1 mycroft */
46 1.1 mycroft
47 1.1 mycroft /*
48 1.1 mycroft * Null Layer
49 1.1 mycroft *
50 1.1 mycroft * (See mount_null(8) for more information.)
51 1.1 mycroft *
52 1.1 mycroft * The null layer duplicates a portion of the file system
53 1.1 mycroft * name space under a new name. In this respect, it is
54 1.1 mycroft * similar to the loopback file system. It differs from
55 1.1 mycroft * the loopback fs in two respects: it is implemented using
56 1.1 mycroft * a stackable layers techniques, and it's "null-node"s stack above
57 1.1 mycroft * all lower-layer vnodes, not just over directory vnodes.
58 1.1 mycroft *
59 1.1 mycroft * The null layer has two purposes. First, it serves as a demonstration
60 1.1 mycroft * of layering by proving a layer which does nothing. (It actually
61 1.1 mycroft * does everything the loopback file system does, which is slightly
62 1.1 mycroft * more than nothing.) Second, the null layer can serve as a prototype
63 1.1 mycroft * layer. Since it provides all necessary layer framework,
64 1.1 mycroft * new file system layers can be created very easily be starting
65 1.1 mycroft * with a null layer.
66 1.1 mycroft *
67 1.1 mycroft * The remainder of this man page examines the null layer as a basis
68 1.1 mycroft * for constructing new layers.
69 1.1 mycroft *
70 1.1 mycroft *
71 1.1 mycroft * INSTANTIATING NEW NULL LAYERS
72 1.1 mycroft *
73 1.1 mycroft * New null layers are created with mount_null(8).
74 1.1 mycroft * Mount_null(8) takes two arguments, the pathname
75 1.1 mycroft * of the lower vfs (target-pn) and the pathname where the null
76 1.1 mycroft * layer will appear in the namespace (alias-pn). After
77 1.1 mycroft * the null layer is put into place, the contents
78 1.1 mycroft * of target-pn subtree will be aliased under alias-pn.
79 1.1 mycroft *
80 1.1 mycroft *
81 1.1 mycroft * OPERATION OF A NULL LAYER
82 1.1 mycroft *
83 1.1 mycroft * The null layer is the minimum file system layer,
84 1.1 mycroft * simply bypassing all possible operations to the lower layer
85 1.1 mycroft * for processing there. The majority of its activity centers
86 1.1 mycroft * on the bypass routine, though which nearly all vnode operations
87 1.1 mycroft * pass.
88 1.1 mycroft *
89 1.1 mycroft * The bypass routine accepts arbitrary vnode operations for
90 1.1 mycroft * handling by the lower layer. It begins by examing vnode
91 1.1 mycroft * operation arguments and replacing any null-nodes by their
92 1.1 mycroft * lower-layer equivlants. It then invokes the operation
93 1.1 mycroft * on the lower layer. Finally, it replaces the null-nodes
94 1.1 mycroft * in the arguments and, if a vnode is return by the operation,
95 1.1 mycroft * stacks a null-node on top of the returned vnode.
96 1.1 mycroft *
97 1.13 fvdl * Although bypass handles most operations, vop_getattr, vop_lock,
98 1.13 fvdl * vop_unlock, vop_inactive, vop_reclaim, and vop_print are not
99 1.13 fvdl * bypassed. Vop_getattr must change the fsid being returned.
100 1.13 fvdl * Vop_lock and vop_unlock must handle any locking for the
101 1.13 fvdl * current vnode as well as pass the lock request down.
102 1.1 mycroft * Vop_inactive and vop_reclaim are not bypassed so that
103 1.13 fvdl * they can handle freeing null-layer specific data. Vop_print
104 1.13 fvdl * is not bypassed to avoid excessive debugging information.
105 1.13 fvdl * Also, certain vnode operations change the locking state within
106 1.13 fvdl * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
107 1.13 fvdl * and symlink). Ideally these operations should not change the
108 1.13 fvdl * lock state, but should be changed to let the caller of the
109 1.13 fvdl * function unlock them. Otherwise all intermediate vnode layers
110 1.13 fvdl * (such as union, umapfs, etc) must catch these functions to do
111 1.13 fvdl * the necessary locking at their layer.
112 1.1 mycroft *
113 1.1 mycroft *
114 1.1 mycroft * INSTANTIATING VNODE STACKS
115 1.1 mycroft *
116 1.1 mycroft * Mounting associates the null layer with a lower layer,
117 1.1 mycroft * effect stacking two VFSes. Vnode stacks are instead
118 1.1 mycroft * created on demand as files are accessed.
119 1.1 mycroft *
120 1.1 mycroft * The initial mount creates a single vnode stack for the
121 1.1 mycroft * root of the new null layer. All other vnode stacks
122 1.1 mycroft * are created as a result of vnode operations on
123 1.1 mycroft * this or other null vnode stacks.
124 1.1 mycroft *
125 1.1 mycroft * New vnode stacks come into existance as a result of
126 1.1 mycroft * an operation which returns a vnode.
127 1.1 mycroft * The bypass routine stacks a null-node above the new
128 1.1 mycroft * vnode before returning it to the caller.
129 1.1 mycroft *
130 1.1 mycroft * For example, imagine mounting a null layer with
131 1.1 mycroft * "mount_null /usr/include /dev/layer/null".
132 1.1 mycroft * Changing directory to /dev/layer/null will assign
133 1.1 mycroft * the root null-node (which was created when the null layer was mounted).
134 1.1 mycroft * Now consider opening "sys". A vop_lookup would be
135 1.1 mycroft * done on the root null-node. This operation would bypass through
136 1.1 mycroft * to the lower layer which would return a vnode representing
137 1.1 mycroft * the UFS "sys". Null_bypass then builds a null-node
138 1.1 mycroft * aliasing the UFS "sys" and returns this to the caller.
139 1.1 mycroft * Later operations on the null-node "sys" will repeat this
140 1.1 mycroft * process when constructing other vnode stacks.
141 1.1 mycroft *
142 1.1 mycroft *
143 1.1 mycroft * CREATING OTHER FILE SYSTEM LAYERS
144 1.1 mycroft *
145 1.1 mycroft * One of the easiest ways to construct new file system layers is to make
146 1.1 mycroft * a copy of the null layer, rename all files and variables, and
147 1.1 mycroft * then begin modifing the copy. Sed can be used to easily rename
148 1.1 mycroft * all variables.
149 1.1 mycroft *
150 1.1 mycroft * The umap layer is an example of a layer descended from the
151 1.1 mycroft * null layer.
152 1.1 mycroft *
153 1.1 mycroft *
154 1.1 mycroft * INVOKING OPERATIONS ON LOWER LAYERS
155 1.1 mycroft *
156 1.1 mycroft * There are two techniques to invoke operations on a lower layer
157 1.1 mycroft * when the operation cannot be completely bypassed. Each method
158 1.1 mycroft * is appropriate in different situations. In both cases,
159 1.1 mycroft * it is the responsibility of the aliasing layer to make
160 1.1 mycroft * the operation arguments "correct" for the lower layer
161 1.1 mycroft * by mapping an vnode arguments to the lower layer.
162 1.1 mycroft *
163 1.1 mycroft * The first approach is to call the aliasing layer's bypass routine.
164 1.1 mycroft * This method is most suitable when you wish to invoke the operation
165 1.1 mycroft * currently being hanldled on the lower layer. It has the advantage
166 1.1 mycroft * that the bypass routine already must do argument mapping.
167 1.1 mycroft * An example of this is null_getattrs in the null layer.
168 1.1 mycroft *
169 1.1 mycroft * A second approach is to directly invoked vnode operations on
170 1.1 mycroft * the lower layer with the VOP_OPERATIONNAME interface.
171 1.1 mycroft * The advantage of this method is that it is easy to invoke
172 1.1 mycroft * arbitrary operations on the lower layer. The disadvantage
173 1.1 mycroft * is that vnodes arguments must be manualy mapped.
174 1.1 mycroft *
175 1.1 mycroft */
176 1.1 mycroft
177 1.1 mycroft #include <sys/param.h>
178 1.1 mycroft #include <sys/systm.h>
179 1.1 mycroft #include <sys/proc.h>
180 1.1 mycroft #include <sys/time.h>
181 1.1 mycroft #include <sys/types.h>
182 1.1 mycroft #include <sys/vnode.h>
183 1.1 mycroft #include <sys/mount.h>
184 1.1 mycroft #include <sys/namei.h>
185 1.1 mycroft #include <sys/malloc.h>
186 1.1 mycroft #include <sys/buf.h>
187 1.1 mycroft #include <miscfs/nullfs/null.h>
188 1.13 fvdl #include <miscfs/genfs/genfs.h>
189 1.1 mycroft
190 1.1 mycroft
191 1.1 mycroft int null_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
192 1.1 mycroft
193 1.5 christos int null_bypass __P((void *));
194 1.5 christos int null_getattr __P((void *));
195 1.5 christos int null_inactive __P((void *));
196 1.5 christos int null_reclaim __P((void *));
197 1.5 christos int null_print __P((void *));
198 1.5 christos int null_strategy __P((void *));
199 1.5 christos int null_bwrite __P((void *));
200 1.7 jtk int null_lock __P((void *));
201 1.7 jtk int null_unlock __P((void *));
202 1.7 jtk int null_islocked __P((void *));
203 1.7 jtk int null_lookup __P((void *));
204 1.13 fvdl int null_setattr __P((void *));
205 1.13 fvdl int null_access __P((void *));
206 1.13 fvdl
207 1.7 jtk
208 1.1 mycroft /*
209 1.1 mycroft * This is the 10-Apr-92 bypass routine.
210 1.1 mycroft * This version has been optimized for speed, throwing away some
211 1.1 mycroft * safety checks. It should still always work, but it's not as
212 1.1 mycroft * robust to programmer errors.
213 1.1 mycroft * Define SAFETY to include some error checking code.
214 1.1 mycroft *
215 1.1 mycroft * In general, we map all vnodes going down and unmap them on the way back.
216 1.1 mycroft * As an exception to this, vnodes can be marked "unmapped" by setting
217 1.1 mycroft * the Nth bit in operation's vdesc_flags.
218 1.1 mycroft *
219 1.1 mycroft * Also, some BSD vnode operations have the side effect of vrele'ing
220 1.1 mycroft * their arguments. With stacking, the reference counts are held
221 1.1 mycroft * by the upper node, not the lower one, so we must handle these
222 1.1 mycroft * side-effects here. This is not of concern in Sun-derived systems
223 1.1 mycroft * since there are no such side-effects.
224 1.1 mycroft *
225 1.1 mycroft * This makes the following assumptions:
226 1.1 mycroft * - only one returned vpp
227 1.1 mycroft * - no INOUT vpp's (Sun's vop_open has one of these)
228 1.1 mycroft * - the vnode operation vector of the first vnode should be used
229 1.1 mycroft * to determine what implementation of the op should be invoked
230 1.1 mycroft * - all mapped vnodes are of our vnode-type (NEEDSWORK:
231 1.1 mycroft * problems on rmdir'ing mount points and renaming?)
232 1.1 mycroft */
233 1.1 mycroft int
234 1.5 christos null_bypass(v)
235 1.5 christos void *v;
236 1.5 christos {
237 1.1 mycroft struct vop_generic_args /* {
238 1.1 mycroft struct vnodeop_desc *a_desc;
239 1.1 mycroft <other random data follows, presumably>
240 1.5 christos } */ *ap = v;
241 1.13 fvdl extern int (**null_vnodeop_p) __P((void *));
242 1.1 mycroft register struct vnode **this_vp_p;
243 1.1 mycroft int error;
244 1.1 mycroft struct vnode *old_vps[VDESC_MAX_VPS];
245 1.1 mycroft struct vnode **vps_p[VDESC_MAX_VPS];
246 1.1 mycroft struct vnode ***vppp;
247 1.1 mycroft struct vnodeop_desc *descp = ap->a_desc;
248 1.1 mycroft int reles, i;
249 1.1 mycroft
250 1.1 mycroft if (null_bug_bypass)
251 1.9 christos printf ("null_bypass: %s\n", descp->vdesc_name);
252 1.1 mycroft
253 1.1 mycroft #ifdef SAFETY
254 1.1 mycroft /*
255 1.1 mycroft * We require at least one vp.
256 1.1 mycroft */
257 1.1 mycroft if (descp->vdesc_vp_offsets == NULL ||
258 1.1 mycroft descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
259 1.1 mycroft panic ("null_bypass: no vp's in map.\n");
260 1.1 mycroft #endif
261 1.1 mycroft
262 1.1 mycroft /*
263 1.1 mycroft * Map the vnodes going in.
264 1.1 mycroft * Later, we'll invoke the operation based on
265 1.1 mycroft * the first mapped vnode's operation vector.
266 1.1 mycroft */
267 1.1 mycroft reles = descp->vdesc_flags;
268 1.1 mycroft for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
269 1.1 mycroft if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
270 1.1 mycroft break; /* bail out at end of list */
271 1.1 mycroft vps_p[i] = this_vp_p =
272 1.1 mycroft VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[i],ap);
273 1.1 mycroft /*
274 1.1 mycroft * We're not guaranteed that any but the first vnode
275 1.1 mycroft * are of our type. Check for and don't map any
276 1.1 mycroft * that aren't. (We must always map first vp or vclean fails.)
277 1.1 mycroft */
278 1.13 fvdl if (i && (*this_vp_p == NULL ||
279 1.3 mycroft (*this_vp_p)->v_op != null_vnodeop_p)) {
280 1.13 fvdl old_vps[i] = NULL;
281 1.1 mycroft } else {
282 1.1 mycroft old_vps[i] = *this_vp_p;
283 1.1 mycroft *(vps_p[i]) = NULLVPTOLOWERVP(*this_vp_p);
284 1.1 mycroft /*
285 1.1 mycroft * XXX - Several operations have the side effect
286 1.1 mycroft * of vrele'ing their vp's. We must account for
287 1.1 mycroft * that. (This should go away in the future.)
288 1.1 mycroft */
289 1.1 mycroft if (reles & 1)
290 1.1 mycroft VREF(*this_vp_p);
291 1.1 mycroft }
292 1.1 mycroft
293 1.1 mycroft }
294 1.1 mycroft
295 1.1 mycroft /*
296 1.1 mycroft * Call the operation on the lower layer
297 1.1 mycroft * with the modified argument structure.
298 1.1 mycroft */
299 1.1 mycroft error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
300 1.1 mycroft
301 1.1 mycroft /*
302 1.1 mycroft * Maintain the illusion of call-by-value
303 1.1 mycroft * by restoring vnodes in the argument structure
304 1.1 mycroft * to their original value.
305 1.1 mycroft */
306 1.1 mycroft reles = descp->vdesc_flags;
307 1.1 mycroft for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
308 1.1 mycroft if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
309 1.1 mycroft break; /* bail out at end of list */
310 1.13 fvdl if (old_vps[i]) {
311 1.1 mycroft *(vps_p[i]) = old_vps[i];
312 1.13 fvdl if (reles & 1)
313 1.13 fvdl vrele(*(vps_p[i]));
314 1.1 mycroft }
315 1.1 mycroft }
316 1.1 mycroft
317 1.1 mycroft /*
318 1.1 mycroft * Map the possible out-going vpp
319 1.1 mycroft * (Assumes that the lower layer always returns
320 1.1 mycroft * a VREF'ed vpp unless it gets an error.)
321 1.1 mycroft */
322 1.1 mycroft if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
323 1.1 mycroft !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
324 1.1 mycroft !error) {
325 1.1 mycroft /*
326 1.1 mycroft * XXX - even though some ops have vpp returned vp's,
327 1.1 mycroft * several ops actually vrele this before returning.
328 1.1 mycroft * We must avoid these ops.
329 1.1 mycroft * (This should go away when these ops are regularized.)
330 1.1 mycroft */
331 1.1 mycroft if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
332 1.1 mycroft goto out;
333 1.1 mycroft vppp = VOPARG_OFFSETTO(struct vnode***,
334 1.1 mycroft descp->vdesc_vpp_offset,ap);
335 1.7 jtk error = null_node_create(old_vps[0]->v_mount, **vppp, *vppp,
336 1.7 jtk descp == &vop_lookup_desc ? 0 : 1);
337 1.1 mycroft }
338 1.1 mycroft
339 1.1 mycroft out:
340 1.1 mycroft return (error);
341 1.1 mycroft }
342 1.1 mycroft
343 1.13 fvdl /*
344 1.13 fvdl * We have to carry on the locking protocol on the null layer vnodes
345 1.13 fvdl * as we progress through the tree. We also have to enforce read-only
346 1.13 fvdl * if this layer is mounted read-only.
347 1.13 fvdl */
348 1.13 fvdl int
349 1.13 fvdl null_lookup(v)
350 1.13 fvdl void *v;
351 1.13 fvdl {
352 1.13 fvdl struct vop_lookup_args /* {
353 1.13 fvdl struct vnode * a_dvp;
354 1.13 fvdl struct vnode ** a_vpp;
355 1.13 fvdl struct componentname * a_cnp;
356 1.13 fvdl } */ *ap = v;
357 1.13 fvdl struct componentname *cnp = ap->a_cnp;
358 1.13 fvdl int flags = cnp->cn_flags;
359 1.13 fvdl struct vop_lock_args lockargs;
360 1.13 fvdl struct vop_unlock_args unlockargs;
361 1.13 fvdl struct vnode *dvp, *vp;
362 1.13 fvdl int error;
363 1.13 fvdl
364 1.13 fvdl if ((flags & ISLASTCN) && (ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
365 1.13 fvdl (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
366 1.13 fvdl return (EROFS);
367 1.13 fvdl error = null_bypass(ap);
368 1.13 fvdl if (error == EJUSTRETURN && (flags & ISLASTCN) &&
369 1.13 fvdl (ap->a_dvp->v_mount->mnt_flag & MNT_RDONLY) &&
370 1.13 fvdl (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
371 1.13 fvdl error = EROFS;
372 1.13 fvdl /*
373 1.13 fvdl * We must do the same locking and unlocking at this layer as
374 1.13 fvdl * is done in the layers below us. We could figure this out
375 1.13 fvdl * based on the error return and the LASTCN, LOCKPARENT, and
376 1.13 fvdl * LOCKLEAF flags. However, it is more expidient to just find
377 1.13 fvdl * out the state of the lower level vnodes and set ours to the
378 1.13 fvdl * same state.
379 1.13 fvdl */
380 1.13 fvdl dvp = ap->a_dvp;
381 1.13 fvdl vp = *ap->a_vpp;
382 1.13 fvdl if (dvp == vp)
383 1.13 fvdl return (error);
384 1.13 fvdl if (!VOP_ISLOCKED(dvp)) {
385 1.13 fvdl unlockargs.a_vp = dvp;
386 1.13 fvdl unlockargs.a_flags = 0;
387 1.13 fvdl genfs_nounlock(&unlockargs);
388 1.13 fvdl }
389 1.13 fvdl if (vp != NULL && VOP_ISLOCKED(vp)) {
390 1.13 fvdl lockargs.a_vp = vp;
391 1.13 fvdl lockargs.a_flags = LK_SHARED;
392 1.13 fvdl genfs_nolock(&lockargs);
393 1.13 fvdl }
394 1.13 fvdl return (error);
395 1.13 fvdl }
396 1.13 fvdl
397 1.13 fvdl /*
398 1.13 fvdl * Setattr call. Disallow write attempts if the layer is mounted read-only.
399 1.13 fvdl */
400 1.13 fvdl int
401 1.13 fvdl null_setattr(v)
402 1.13 fvdl void *v;
403 1.13 fvdl {
404 1.13 fvdl struct vop_setattr_args /* {
405 1.13 fvdl struct vnodeop_desc *a_desc;
406 1.13 fvdl struct vnode *a_vp;
407 1.13 fvdl struct vattr *a_vap;
408 1.13 fvdl struct ucred *a_cred;
409 1.13 fvdl struct proc *a_p;
410 1.13 fvdl } */ *ap = v;
411 1.13 fvdl struct vnode *vp = ap->a_vp;
412 1.13 fvdl struct vattr *vap = ap->a_vap;
413 1.13 fvdl
414 1.13 fvdl if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
415 1.13 fvdl vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
416 1.13 fvdl vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
417 1.13 fvdl (vp->v_mount->mnt_flag & MNT_RDONLY))
418 1.13 fvdl return (EROFS);
419 1.13 fvdl if (vap->va_size != VNOVAL) {
420 1.13 fvdl switch (vp->v_type) {
421 1.13 fvdl case VDIR:
422 1.13 fvdl return (EISDIR);
423 1.13 fvdl case VCHR:
424 1.13 fvdl case VBLK:
425 1.13 fvdl case VSOCK:
426 1.13 fvdl case VFIFO:
427 1.13 fvdl return (0);
428 1.13 fvdl case VREG:
429 1.13 fvdl case VLNK:
430 1.13 fvdl default:
431 1.13 fvdl /*
432 1.13 fvdl * Disallow write attempts if the filesystem is
433 1.13 fvdl * mounted read-only.
434 1.13 fvdl */
435 1.13 fvdl if (vp->v_mount->mnt_flag & MNT_RDONLY)
436 1.13 fvdl return (EROFS);
437 1.13 fvdl }
438 1.13 fvdl }
439 1.13 fvdl return (null_bypass(ap));
440 1.13 fvdl }
441 1.1 mycroft
442 1.1 mycroft /*
443 1.1 mycroft * We handle getattr only to change the fsid.
444 1.1 mycroft */
445 1.1 mycroft int
446 1.5 christos null_getattr(v)
447 1.5 christos void *v;
448 1.5 christos {
449 1.1 mycroft struct vop_getattr_args /* {
450 1.1 mycroft struct vnode *a_vp;
451 1.1 mycroft struct vattr *a_vap;
452 1.1 mycroft struct ucred *a_cred;
453 1.1 mycroft struct proc *a_p;
454 1.5 christos } */ *ap = v;
455 1.1 mycroft int error;
456 1.13 fvdl
457 1.10 pk if ((error = null_bypass(ap)) != 0)
458 1.1 mycroft return (error);
459 1.1 mycroft /* Requires that arguments be restored. */
460 1.1 mycroft ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
461 1.1 mycroft return (0);
462 1.1 mycroft }
463 1.1 mycroft
464 1.13 fvdl int
465 1.13 fvdl null_access(v)
466 1.13 fvdl void *v;
467 1.13 fvdl {
468 1.13 fvdl struct vop_access_args /* {
469 1.13 fvdl struct vnode *a_vp;
470 1.13 fvdl int a_mode;
471 1.13 fvdl struct ucred *a_cred;
472 1.13 fvdl struct proc *a_p;
473 1.13 fvdl } */ *ap = v;
474 1.13 fvdl struct vnode *vp = ap->a_vp;
475 1.13 fvdl mode_t mode = ap->a_mode;
476 1.13 fvdl
477 1.13 fvdl /*
478 1.13 fvdl * Disallow write attempts on read-only layers;
479 1.13 fvdl * unless the file is a socket, fifo, or a block or
480 1.13 fvdl * character device resident on the file system.
481 1.13 fvdl */
482 1.13 fvdl if (mode & VWRITE) {
483 1.13 fvdl switch (vp->v_type) {
484 1.13 fvdl case VDIR:
485 1.13 fvdl case VLNK:
486 1.13 fvdl case VREG:
487 1.13 fvdl if (vp->v_mount->mnt_flag & MNT_RDONLY)
488 1.13 fvdl return (EROFS);
489 1.13 fvdl break;
490 1.13 fvdl default:
491 1.13 fvdl break;
492 1.13 fvdl }
493 1.13 fvdl }
494 1.13 fvdl return (null_bypass(ap));
495 1.13 fvdl }
496 1.13 fvdl
497 1.13 fvdl /*
498 1.13 fvdl * We need to process our own vnode lock and then clear the
499 1.13 fvdl * interlock flag as it applies only to our vnode, not the
500 1.13 fvdl * vnodes below us on the stack.
501 1.13 fvdl */
502 1.13 fvdl int
503 1.13 fvdl null_lock(v)
504 1.13 fvdl void *v;
505 1.13 fvdl {
506 1.13 fvdl struct vop_lock_args /* {
507 1.13 fvdl struct vnode *a_vp;
508 1.13 fvdl int a_flags;
509 1.13 fvdl struct proc *a_p;
510 1.13 fvdl } */ *ap = v;
511 1.13 fvdl
512 1.13 fvdl genfs_nolock(ap);
513 1.13 fvdl if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
514 1.13 fvdl return (0);
515 1.13 fvdl ap->a_flags &= ~LK_INTERLOCK;
516 1.13 fvdl return (null_bypass(ap));
517 1.13 fvdl }
518 1.13 fvdl
519 1.13 fvdl /*
520 1.13 fvdl * We need to process our own vnode unlock and then clear the
521 1.13 fvdl * interlock flag as it applies only to our vnode, not the
522 1.13 fvdl * vnodes below us on the stack.
523 1.13 fvdl */
524 1.13 fvdl int
525 1.13 fvdl null_unlock(v)
526 1.13 fvdl void *v;
527 1.13 fvdl {
528 1.13 fvdl struct vop_unlock_args /* {
529 1.13 fvdl struct vnode *a_vp;
530 1.13 fvdl int a_flags;
531 1.13 fvdl struct proc *a_p;
532 1.13 fvdl } */ *ap = v;
533 1.13 fvdl
534 1.13 fvdl genfs_nounlock(ap);
535 1.13 fvdl ap->a_flags &= ~LK_INTERLOCK;
536 1.13 fvdl return (null_bypass(ap));
537 1.13 fvdl }
538 1.1 mycroft
539 1.1 mycroft int
540 1.5 christos null_inactive(v)
541 1.5 christos void *v;
542 1.1 mycroft {
543 1.13 fvdl struct vop_inactive_args /* {
544 1.13 fvdl struct vnode *a_vp;
545 1.13 fvdl struct proc *a_p;
546 1.13 fvdl } */ *ap = v;
547 1.13 fvdl
548 1.1 mycroft /*
549 1.1 mycroft * Do nothing (and _don't_ bypass).
550 1.1 mycroft * Wait to vrele lowervp until reclaim,
551 1.1 mycroft * so that until then our null_node is in the
552 1.1 mycroft * cache and reusable.
553 1.1 mycroft *
554 1.1 mycroft * NEEDSWORK: Someday, consider inactive'ing
555 1.1 mycroft * the lowervp and then trying to reactivate it
556 1.1 mycroft * with capabilities (v_id)
557 1.1 mycroft * like they do in the name lookup cache code.
558 1.1 mycroft * That's too much work for now.
559 1.1 mycroft */
560 1.13 fvdl VOP_UNLOCK(ap->a_vp, 0);
561 1.1 mycroft return (0);
562 1.1 mycroft }
563 1.1 mycroft
564 1.1 mycroft int
565 1.5 christos null_reclaim(v)
566 1.5 christos void *v;
567 1.5 christos {
568 1.1 mycroft struct vop_reclaim_args /* {
569 1.1 mycroft struct vnode *a_vp;
570 1.13 fvdl struct proc *a_p;
571 1.5 christos } */ *ap = v;
572 1.1 mycroft struct vnode *vp = ap->a_vp;
573 1.1 mycroft struct null_node *xp = VTONULL(vp);
574 1.1 mycroft struct vnode *lowervp = xp->null_lowervp;
575 1.1 mycroft
576 1.1 mycroft /*
577 1.1 mycroft * Note: in vop_reclaim, vp->v_op == dead_vnodeop_p,
578 1.1 mycroft * so we can't call VOPs on ourself.
579 1.1 mycroft */
580 1.1 mycroft /* After this assignment, this node will not be re-used. */
581 1.1 mycroft xp->null_lowervp = NULL;
582 1.4 mycroft LIST_REMOVE(xp, null_hash);
583 1.1 mycroft FREE(vp->v_data, M_TEMP);
584 1.1 mycroft vp->v_data = NULL;
585 1.1 mycroft vrele (lowervp);
586 1.1 mycroft return (0);
587 1.1 mycroft }
588 1.1 mycroft
589 1.1 mycroft int
590 1.5 christos null_print(v)
591 1.5 christos void *v;
592 1.5 christos {
593 1.1 mycroft struct vop_print_args /* {
594 1.1 mycroft struct vnode *a_vp;
595 1.5 christos } */ *ap = v;
596 1.1 mycroft register struct vnode *vp = ap->a_vp;
597 1.9 christos printf ("\ttag VT_NULLFS, vp=%p, lowervp=%p\n", vp, NULLVPTOLOWERVP(vp));
598 1.1 mycroft return (0);
599 1.1 mycroft }
600 1.1 mycroft
601 1.1 mycroft /*
602 1.1 mycroft * XXX - vop_strategy must be hand coded because it has no
603 1.1 mycroft * vnode in its arguments.
604 1.1 mycroft * This goes away with a merged VM/buffer cache.
605 1.1 mycroft */
606 1.1 mycroft int
607 1.5 christos null_strategy(v)
608 1.5 christos void *v;
609 1.5 christos {
610 1.1 mycroft struct vop_strategy_args /* {
611 1.1 mycroft struct buf *a_bp;
612 1.5 christos } */ *ap = v;
613 1.1 mycroft struct buf *bp = ap->a_bp;
614 1.1 mycroft int error;
615 1.1 mycroft struct vnode *savedvp;
616 1.1 mycroft
617 1.1 mycroft savedvp = bp->b_vp;
618 1.1 mycroft bp->b_vp = NULLVPTOLOWERVP(bp->b_vp);
619 1.1 mycroft
620 1.1 mycroft error = VOP_STRATEGY(bp);
621 1.1 mycroft
622 1.1 mycroft bp->b_vp = savedvp;
623 1.1 mycroft
624 1.1 mycroft return (error);
625 1.1 mycroft }
626 1.1 mycroft
627 1.1 mycroft /*
628 1.1 mycroft * XXX - like vop_strategy, vop_bwrite must be hand coded because it has no
629 1.1 mycroft * vnode in its arguments.
630 1.1 mycroft * This goes away with a merged VM/buffer cache.
631 1.1 mycroft */
632 1.1 mycroft int
633 1.5 christos null_bwrite(v)
634 1.5 christos void *v;
635 1.5 christos {
636 1.1 mycroft struct vop_bwrite_args /* {
637 1.1 mycroft struct buf *a_bp;
638 1.5 christos } */ *ap = v;
639 1.1 mycroft struct buf *bp = ap->a_bp;
640 1.1 mycroft int error;
641 1.1 mycroft struct vnode *savedvp;
642 1.1 mycroft
643 1.1 mycroft savedvp = bp->b_vp;
644 1.1 mycroft bp->b_vp = NULLVPTOLOWERVP(bp->b_vp);
645 1.1 mycroft
646 1.1 mycroft error = VOP_BWRITE(bp);
647 1.1 mycroft
648 1.1 mycroft bp->b_vp = savedvp;
649 1.1 mycroft
650 1.1 mycroft return (error);
651 1.1 mycroft }
652 1.1 mycroft
653 1.1 mycroft /*
654 1.1 mycroft * Global vfs data structures
655 1.1 mycroft */
656 1.5 christos int (**null_vnodeop_p) __P((void *));
657 1.1 mycroft struct vnodeopv_entry_desc null_vnodeop_entries[] = {
658 1.13 fvdl { &vop_default_desc, null_bypass },
659 1.1 mycroft
660 1.13 fvdl { &vop_lookup_desc, null_lookup },
661 1.13 fvdl { &vop_setattr_desc, null_setattr },
662 1.13 fvdl { &vop_getattr_desc, null_getattr },
663 1.13 fvdl { &vop_access_desc, null_access },
664 1.13 fvdl { &vop_lock_desc, null_lock },
665 1.13 fvdl { &vop_unlock_desc, null_unlock },
666 1.13 fvdl { &vop_inactive_desc, null_inactive },
667 1.13 fvdl { &vop_reclaim_desc, null_reclaim },
668 1.13 fvdl { &vop_print_desc, null_print },
669 1.1 mycroft
670 1.13 fvdl { &vop_strategy_desc, null_strategy },
671 1.13 fvdl { &vop_bwrite_desc, null_bwrite },
672 1.1 mycroft
673 1.13 fvdl { (struct vnodeop_desc*)NULL, (int(*)__P((void *)))NULL }
674 1.1 mycroft };
675 1.13 fvdl struct vnodeopv_desc null_vnodeop_opv_desc =
676 1.1 mycroft { &null_vnodeop_p, null_vnodeop_entries };
677