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. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)null_vnops.c 8.6 (Berkeley) 5/27/95 33 * 34 * Ancestors: 35 * @(#)lofs_vnops.c 1.2 (Berkeley) 6/18/92 36 * $FreeBSD: src/sys/miscfs/nullfs/null_vnops.c,v 1.38.2.6 2002/07/31 00:32:28 semenu Exp $ 37 * $DragonFly: src/sys/vfs/nullfs/null_vnops.c,v 1.30 2008/09/17 21:44:25 dillon Exp $ 38 * ...and... 39 * @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project 40 * 41 * $FreeBSD: src/sys/miscfs/nullfs/null_vnops.c,v 1.38.2.6 2002/07/31 00:32:28 semenu Exp $ 42 */ 43 44 /* 45 * Null Layer 46 * 47 * (See mount_null(8) for more information.) 48 * 49 * The null layer duplicates a portion of the file system 50 * name space under a new name. In this respect, it is 51 * similar to the loopback file system. It differs from 52 * the loopback fs in two respects: it is implemented using 53 * a stackable layers techniques, and its "null-node"s stack above 54 * all lower-layer vnodes, not just over directory vnodes. 55 * 56 * The null layer has two purposes. First, it serves as a demonstration 57 * of layering by proving a layer which does nothing. (It actually 58 * does everything the loopback file system does, which is slightly 59 * more than nothing.) Second, the null layer can serve as a prototype 60 * layer. Since it provides all necessary layer framework, 61 * new file system layers can be created very easily be starting 62 * with a null layer. 63 * 64 * The remainder of this man page examines the null layer as a basis 65 * for constructing new layers. 66 * 67 * 68 * INSTANTIATING NEW NULL LAYERS 69 * 70 * New null layers are created with mount_null(8). 71 * Mount_null(8) takes two arguments, the pathname 72 * of the lower vfs (target-pn) and the pathname where the null 73 * layer will appear in the namespace (alias-pn). After 74 * the null layer is put into place, the contents 75 * of target-pn subtree will be aliased under alias-pn. 76 * 77 * 78 * OPERATION OF A NULL LAYER 79 * 80 * The null layer is the minimum file system layer, 81 * simply bypassing all possible operations to the lower layer 82 * for processing there. The majority of its activity used to center 83 * on a so-called bypass routine, through which nullfs vnodes 84 * passed on operation to their underlying peer. 85 * 86 * However, with the current implementation nullfs doesn't have any private 87 * vnodes, rather it relies on DragonFly's namecache API. That gives a much 88 * more lightweight null layer, as namecache structures are pure data, with 89 * no private operations, so there is no need of subtle dispatching routines. 90 * 91 * Unlike the old code, this implementation is not a general skeleton overlay 92 * filesystem: to get more comprehensive overlaying, we will need vnode 93 * operation dispatch. Other overlay filesystems might be 94 * able to get on with a hybrid solution: overlay some vnodes, and rely 95 * on namecache API for the rest. 96 */ 97 98 #include <sys/param.h> 99 #include <sys/systm.h> 100 #include <sys/kernel.h> 101 #include <sys/sysctl.h> 102 #include <sys/vnode.h> 103 #include <sys/mount.h> 104 #include <sys/mountctl.h> 105 #include <sys/proc.h> 106 #include <sys/namei.h> 107 #include <sys/malloc.h> 108 #include <sys/buf.h> 109 #include "null.h" 110 111 static int null_nresolve(struct vop_nresolve_args *ap); 112 static int null_ncreate(struct vop_ncreate_args *ap); 113 static int null_nmkdir(struct vop_nmkdir_args *ap); 114 static int null_nmknod(struct vop_nmknod_args *ap); 115 static int null_nlink(struct vop_nlink_args *ap); 116 static int null_nsymlink(struct vop_nsymlink_args *ap); 117 static int null_nwhiteout(struct vop_nwhiteout_args *ap); 118 static int null_nremove(struct vop_nremove_args *ap); 119 static int null_nrmdir(struct vop_nrmdir_args *ap); 120 static int null_nrename(struct vop_nrename_args *ap); 121 static int null_mountctl(struct vop_mountctl_args *ap); 122 123 static int 124 null_nresolve(struct vop_nresolve_args *ap) 125 { 126 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 127 128 return vop_nresolve_ap(ap); 129 } 130 131 static int 132 null_ncreate(struct vop_ncreate_args *ap) 133 { 134 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 135 136 return vop_ncreate_ap(ap); 137 } 138 139 static int 140 null_nmkdir(struct vop_nmkdir_args *ap) 141 { 142 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 143 144 return vop_nmkdir_ap(ap); 145 } 146 147 static int 148 null_nmknod(struct vop_nmknod_args *ap) 149 { 150 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 151 152 return vop_nmknod_ap(ap); 153 } 154 155 static int 156 null_nlink(struct vop_nlink_args *ap) 157 { 158 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 159 160 return vop_nlink_ap(ap); 161 } 162 163 static int 164 null_nsymlink(struct vop_nsymlink_args *ap) 165 { 166 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 167 168 return vop_nsymlink_ap(ap); 169 } 170 171 static int 172 null_nwhiteout(struct vop_nwhiteout_args *ap) 173 { 174 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 175 176 return vop_nwhiteout_ap(ap); 177 } 178 179 static int 180 null_nremove(struct vop_nremove_args *ap) 181 { 182 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 183 184 return vop_nremove_ap(ap); 185 } 186 187 static int 188 null_nrmdir(struct vop_nrmdir_args *ap) 189 { 190 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 191 192 return vop_nrmdir_ap(ap); 193 } 194 195 static int 196 null_nrename(struct vop_nrename_args *ap) 197 { 198 struct mount *lmp; 199 200 lmp = MOUNTTONULLMOUNT(ap->a_fnch->mount)->nullm_vfs; 201 if (lmp != MOUNTTONULLMOUNT(ap->a_tnch->mount)->nullm_vfs) 202 return (EINVAL); 203 204 ap->a_head.a_ops = lmp->mnt_vn_norm_ops; 205 206 return vop_nrename_ap(ap); 207 } 208 209 static int 210 null_mountctl(struct vop_mountctl_args *ap) 211 { 212 struct mount *mp; 213 int error; 214 215 mp = ap->a_head.a_ops->head.vv_mount; 216 217 switch(ap->a_op) { 218 case MOUNTCTL_SET_EXPORT: 219 if (ap->a_ctllen != sizeof(struct export_args)) 220 error = EINVAL; 221 else 222 error = nullfs_export(mp, ap->a_op, (const void *)ap->a_ctl); 223 break; 224 case MOUNTCTL_MOUNTFLAGS: 225 error = vop_stdmountctl(ap); 226 break; 227 default: 228 error = EOPNOTSUPP; 229 break; 230 } 231 return (error); 232 #if 0 233 ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; 234 235 return vop_mountctl_ap(ap); 236 #endif 237 } 238 239 /* 240 * Global vfs data structures 241 */ 242 struct vop_ops null_vnode_vops = { 243 .vop_nresolve = null_nresolve, 244 .vop_ncreate = null_ncreate, 245 .vop_nmkdir = null_nmkdir, 246 .vop_nmknod = null_nmknod, 247 .vop_nlink = null_nlink, 248 .vop_nsymlink = null_nsymlink, 249 .vop_nwhiteout = null_nwhiteout, 250 .vop_nremove = null_nremove, 251 .vop_nrmdir = null_nrmdir, 252 .vop_nrename = null_nrename, 253 .vop_mountctl = null_mountctl 254 }; 255 256