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