1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * John Heidemann of the UCLA Ficus project. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. 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 * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95 37 * 38 * Ancestors: 39 * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92 40 * $FreeBSD: src/sys/miscfs/nullfs/null_vnops.c,v 1.38.2.6 2002/07/31 00:32:28 semenu Exp $ 41 * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.24 2006/01/04 03:09:53 dillon Exp $ 42 * ...and... 43 * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project 44 * 45 * $FreeBSD: src/sys/miscfs/nullfs/null_vnops.c,v 1.38.2.6 2002/07/31 00:32:28 semenu Exp $ 46 */ 47 48 /* 49 * Null Layer 50 * 51 * (See mount_null(8) for more information.) 52 * 53 * The null layer duplicates a portion of the file system 54 * name space under a new name. In this respect, it is 55 * similar to the loopback file system. It differs from 56 * the loopback fs in two respects: it is implemented using 57 * a stackable layers techniques, and its "null-node"s stack above 58 * all lower-layer vnodes, not just over directory vnodes. 59 * 60 * The null layer has two purposes. First, it serves as a demonstration 61 * of layering by proving a layer which does nothing. (It actually 62 * does everything the loopback file system does, which is slightly 63 * more than nothing.) Second, the null layer can serve as a prototype 64 * layer. Since it provides all necessary layer framework, 65 * new file system layers can be created very easily be starting 66 * with a null layer. 67 * 68 * The remainder of this man page examines the null layer as a basis 69 * for constructing new layers. 70 * 71 * 72 * INSTANTIATING NEW NULL LAYERS 73 * 74 * New null layers are created with mount_null(8). 75 * Mount_null(8) takes two arguments, the pathname 76 * of the lower vfs (target-pn) and the pathname where the null 77 * layer will appear in the namespace (alias-pn). After 78 * the null layer is put into place, the contents 79 * of target-pn subtree will be aliased under alias-pn. 80 * 81 * 82 * OPERATION OF A NULL LAYER 83 * 84 * The null layer is the minimum file system layer, 85 * simply bypassing all possible operations to the lower layer 86 * for processing there. The majority of its activity used to center 87 * on a so-called bypass routine, through which nullfs vnodes 88 * passed on operation to their underlying peer. 89 * 90 * However, with the current implementation nullfs doesn't have any private 91 * vnodes, it rather relies on DragonFly's namecache API. That gives a much 92 * more lightweight null layer, as namecache structures are pure data, with 93 * no private operations, so there is no need of subtle dispatching routines. 94 * 95 * Unlike the old code, this implementation is not a general skeleton overlay 96 * filesystem: to get more comprehensive overlaying, like that of umapfs, we 97 * will need vnode operation dispatch. Other overlay filesystems, like unionfs 98 * might be able to get on with a hybrid solution: overlay some vnodes, and rely 99 * on namecache API for the rest. 100 */ 101 102 #include <sys/param.h> 103 #include <sys/systm.h> 104 #include <sys/kernel.h> 105 #include <sys/sysctl.h> 106 #include <sys/vnode.h> 107 #include <sys/mount.h> 108 #include <sys/proc.h> 109 #include <sys/namei.h> 110 #include <sys/malloc.h> 111 #include <sys/buf.h> 112 #include "null.h" 113 114 static int null_nresolve(struct vop_nresolve_args *ap); 115 static int null_ncreate(struct vop_ncreate_args *ap); 116 static int null_nmkdir(struct vop_nmkdir_args *ap); 117 static int null_nmknod(struct vop_nmknod_args *ap); 118 static int null_nlink(struct vop_nlink_args *ap); 119 static int null_nsymlink(struct vop_nsymlink_args *ap); 120 static int null_nwhiteout(struct vop_nwhiteout_args *ap); 121 static int null_nremove(struct vop_nremove_args *ap); 122 static int null_nrmdir(struct vop_nrmdir_args *ap); 123 static int null_nrename(struct vop_nrename_args *ap); 124 125 static int 126 null_nresolve(struct vop_nresolve_args *ap) 127 { 128 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 129 130 return vop_nresolve_ap(ap); 131 } 132 133 static int 134 null_ncreate(struct vop_ncreate_args *ap) 135 { 136 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 137 138 return vop_ncreate_ap(ap); 139 } 140 141 static int 142 null_nmkdir(struct vop_nmkdir_args *ap) 143 { 144 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 145 146 return vop_nmkdir_ap(ap); 147 } 148 149 static int 150 null_nmknod(struct vop_nmknod_args *ap) 151 { 152 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 153 154 return vop_nmknod_ap(ap); 155 } 156 157 static int 158 null_nlink(struct vop_nlink_args *ap) 159 { 160 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 161 162 return vop_nlink_ap(ap); 163 } 164 165 static int 166 null_nsymlink(struct vop_nsymlink_args *ap) 167 { 168 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 169 170 return vop_nsymlink_ap(ap); 171 } 172 173 static int 174 null_nwhiteout(struct vop_nwhiteout_args *ap) 175 { 176 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 177 178 return vop_nwhiteout_ap(ap); 179 } 180 181 static int 182 null_nremove(struct vop_nremove_args *ap) 183 { 184 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 185 186 return vop_nremove_ap(ap); 187 } 188 189 static int 190 null_nrmdir(struct vop_nrmdir_args *ap) 191 { 192 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_ncp->nc_mount)->nullm_vfs->mnt_vn_norm_ops; 193 194 return vop_nrmdir_ap(ap); 195 } 196 197 static int 198 null_nrename(struct vop_nrename_args *ap) 199 { 200 struct mount *lmp; 201 202 lmp = MOUNTTONULLMOUNT(ap->a_fncp->nc_mount)->nullm_vfs; 203 if (lmp != MOUNTTONULLMOUNT(ap->a_tncp->nc_mount)->nullm_vfs) 204 return (EINVAL); 205 206 ap->a_head.a_ops = lmp->mnt_vn_norm_ops; 207 208 return vop_nrename_ap(ap); 209 } 210 211 /* 212 * Global vfs data structures 213 */ 214 struct vnodeopv_entry_desc null_vnodeop_entries[] = { 215 { &vop_nresolve_desc, (vnodeopv_entry_t) null_nresolve }, 216 { &vop_ncreate_desc, (vnodeopv_entry_t) null_ncreate }, 217 { &vop_nmkdir_desc, (vnodeopv_entry_t) null_nmkdir }, 218 { &vop_nmknod_desc, (vnodeopv_entry_t) null_nmknod }, 219 { &vop_nlink_desc, (vnodeopv_entry_t) null_nlink }, 220 { &vop_nsymlink_desc, (vnodeopv_entry_t) null_nsymlink }, 221 { &vop_nwhiteout_desc, (vnodeopv_entry_t) null_nwhiteout }, 222 { &vop_nremove_desc, (vnodeopv_entry_t) null_nremove }, 223 { &vop_nrmdir_desc, (vnodeopv_entry_t) null_nrmdir }, 224 { &vop_nrename_desc, (vnodeopv_entry_t) null_nrename }, 225 { NULL, NULL } 226 }; 227 228