/* $NetBSD$ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Taylor R Campbell. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * XXX NOTE NOTE NOTE XXX * * This code does not actually work. It is a draft of an idea. It * probably won't even compile, even if you make it include the right * header files. */ int layer_node_create(struct mount *mp, struct vnode *lowervp, struct vnode *vpp) { struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp); struct vnode *vp = NULL; int error; /* * Try to get an existing vnode for the lower vnode. */ error = vinotab_get(lmp->lm_vinotab, &lowervp, sizeof(lowervp), VGET_INTR, &vp); KASSERT((error == 0) == (vp != NULL)); if (error != ENOENT) goto out; /* * Nothing there. Try to allocate one. */ error = (*lmp->layerm_alloc)(mp, lowervp, &vp); KASSERT((error == 0) == (vp != NULL)); if (error) goto out; /* * vp has a reference to lowervp, and we shall use vp * henceforth, so drop our reference to lowervp. * * XXX Caller should do this, not us... */ vrele(lowervp); KASSERT(0 < lowervp->v_usecount); error = 0; out: *vpp = vp; return error; } int layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode *vpp) { struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp); struct vnode *vp = NULL, *vp0 = NULL; struct layer_node *xp; int error; /* * Create a new vnode for this lower vnode. */ error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p, lowervp->v_interlock, &vp); KASSERT((error == 0) == (vp != NULL)); if (error) goto out; /* * Create a layer node for it and fill it in just enough for a * lookup. */ xp = kmem_zalloc(lmp->layerm_size, KM_SLEEP); KASSERT(xp != NULL); xp->layer_lowervp = lowervp; /* * Try to put this vnode in the table for the lower vnode. If * someone else beat us to it, release ours and use theirs * instead. */ error = vinotab_intern(lmp->lm_vinotab, &xp->layer_vinoent, &xp->layer_lowervp, sizeof(xp->layer_lowervp), vp, &vp0); KASSERT((error == 0) == (vp0 != NULL)); if (vp0 != vp) { kmem_free(xp, lmp->layerm_size); ungetnewvnode(vp); vp = vp0; goto out; } /* * Set up the layer node. */ vref(lowervp); xp->layer_flags = 0; /* * Set up the vnode. */ vp->v_data = xp; vp->v_vflag &= ~VV_MPSAFE; vp->v_vflag |= (lowervp->v_vflag && VV_MPSAFE); vp->v_type = lowervp->v_type; if ((vp->v_type == VBLK) || (vp->v_type == VCHR)) spec_node_init(vp, lowervp->v_rdev); mutex_enter(vp->v_interlock); vp->v_iflag |= VI_LAYER; mutex_exit(vp->v_interlock); /* * Set the inode size. (XXX Why shouldn't we leave this * VSIZENOTSET as it is initialized to be? Are users * guaranteed to reinitialize it?) */ uvm_vnp_setsize(vp, 0); /* * All set. Mark it ready to go and wake anyone waiting. */ vready(vp); error = 0; out: *vpp = vp; return error; } int layer_reclaim(void *v) { struct vop_reclaim_args /* { struct vnode *a_vp; } */ *ap = v; struct vnode *vp = ap->a_vp; struct layer_mount *lmp = MOUNTTOLAYERMOUNT(vp->v_mount); struct layer_node *xp = VTOLAYER(vp); struct vonde *lowervp = xp->layer_lowervp; /* XXX Nobody else does this. Why should layerfs? */ if (vp == lmp->layerm_rootvp) lmp->layerm_rootvp = NULL; vinotab_remove(lmp->lm_vinotab, &xp->layer_vinoent); xp->layer_lowervp = NULL; kmem_free(xp, lmp->layerm_size); vp->v_data = NULL; vrele(lowervp); return 0; }