Commit | Line | Data |
---|---|---|
984263bc MD |
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. | |
dc71b7ab | 16 | * 3. Neither the name of the University nor the names of its contributors |
984263bc MD |
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 | |
984263bc MD |
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 | |
8cb8b61a MD |
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 | |
3ea4f8fe | 84 | * vnodes, rather it relies on DragonFly's namecache API. That gives a much |
8cb8b61a MD |
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 | |
ccb16a17 | 89 | * filesystem: to get more comprehensive overlaying, we will need vnode |
1319714e | 90 | * operation dispatch. Other overlay filesystems might be |
ccb16a17 | 91 | * able to get on with a hybrid solution: overlay some vnodes, and rely |
8cb8b61a MD |
92 | * on namecache API for the rest. |
93 | */ | |
94 | ||
984263bc MD |
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> | |
67863d04 | 101 | #include <sys/mountctl.h> |
dadab5e9 | 102 | #include <sys/proc.h> |
984263bc MD |
103 | #include <sys/malloc.h> |
104 | #include <sys/buf.h> | |
1f2de5d4 | 105 | #include "null.h" |
984263bc | 106 | |
fad57d0e MD |
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); | |
8cb8b61a MD |
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); | |
fad57d0e MD |
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); | |
67863d04 | 117 | static int null_mountctl(struct vop_mountctl_args *ap); |
fad57d0e | 118 | |
417215fe | 119 | static int |
fad57d0e | 120 | null_nresolve(struct vop_nresolve_args *ap) |
417215fe | 121 | { |
28623bf9 | 122 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
5fd012e0 | 123 | |
8cb8b61a | 124 | return vop_nresolve_ap(ap); |
5fd012e0 MD |
125 | } |
126 | ||
984263bc | 127 | static int |
8cb8b61a | 128 | null_ncreate(struct vop_ncreate_args *ap) |
984263bc | 129 | { |
28623bf9 | 130 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
984263bc | 131 | |
8cb8b61a | 132 | return vop_ncreate_ap(ap); |
984263bc MD |
133 | } |
134 | ||
984263bc | 135 | static int |
8cb8b61a | 136 | null_nmkdir(struct vop_nmkdir_args *ap) |
984263bc | 137 | { |
28623bf9 | 138 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
984263bc | 139 | |
8cb8b61a | 140 | return vop_nmkdir_ap(ap); |
984263bc MD |
141 | } |
142 | ||
984263bc | 143 | static int |
8cb8b61a | 144 | null_nmknod(struct vop_nmknod_args *ap) |
984263bc | 145 | { |
28623bf9 | 146 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
3446c007 | 147 | |
8cb8b61a | 148 | return vop_nmknod_ap(ap); |
984263bc MD |
149 | } |
150 | ||
151 | static int | |
8cb8b61a | 152 | null_nlink(struct vop_nlink_args *ap) |
984263bc | 153 | { |
28623bf9 | 154 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
984263bc | 155 | |
8cb8b61a | 156 | return vop_nlink_ap(ap); |
984263bc MD |
157 | } |
158 | ||
984263bc | 159 | static int |
8cb8b61a | 160 | null_nsymlink(struct vop_nsymlink_args *ap) |
984263bc | 161 | { |
28623bf9 | 162 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
984263bc | 163 | |
8cb8b61a | 164 | return vop_nsymlink_ap(ap); |
984263bc MD |
165 | } |
166 | ||
984263bc | 167 | static int |
8cb8b61a | 168 | null_nwhiteout(struct vop_nwhiteout_args *ap) |
984263bc | 169 | { |
28623bf9 | 170 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
984263bc | 171 | |
8cb8b61a | 172 | return vop_nwhiteout_ap(ap); |
984263bc MD |
173 | } |
174 | ||
175 | static int | |
8cb8b61a | 176 | null_nremove(struct vop_nremove_args *ap) |
984263bc | 177 | { |
28623bf9 | 178 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
984263bc | 179 | |
8cb8b61a | 180 | return vop_nremove_ap(ap); |
984263bc MD |
181 | } |
182 | ||
984263bc | 183 | static int |
8cb8b61a | 184 | null_nrmdir(struct vop_nrmdir_args *ap) |
984263bc | 185 | { |
28623bf9 | 186 | ap->a_head.a_ops = MOUNTTONULLMOUNT(ap->a_nch->mount)->nullm_vfs->mnt_vn_norm_ops; |
984263bc | 187 | |
8cb8b61a | 188 | return vop_nrmdir_ap(ap); |
984263bc MD |
189 | } |
190 | ||
984263bc | 191 | static int |
8cb8b61a | 192 | null_nrename(struct vop_nrename_args *ap) |
984263bc | 193 | { |
8cb8b61a | 194 | struct mount *lmp; |
984263bc | 195 | |
28623bf9 MD |
196 | lmp = MOUNTTONULLMOUNT(ap->a_fnch->mount)->nullm_vfs; |
197 | if (lmp != MOUNTTONULLMOUNT(ap->a_tnch->mount)->nullm_vfs) | |
8cb8b61a | 198 | return (EINVAL); |
71ed54ce | 199 | |
8cb8b61a | 200 | ap->a_head.a_ops = lmp->mnt_vn_norm_ops; |
984263bc | 201 | |
8cb8b61a | 202 | return vop_nrename_ap(ap); |
984263bc MD |
203 | } |
204 | ||
67863d04 MD |
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; | |
726e0641 MD |
220 | case MOUNTCTL_MOUNTFLAGS: |
221 | error = vop_stdmountctl(ap); | |
222 | break; | |
67863d04 MD |
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 | ||
984263bc MD |
235 | /* |
236 | * Global vfs data structures | |
237 | */ | |
66a1ddf5 MD |
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, | |
67863d04 MD |
248 | .vop_nrename = null_nrename, |
249 | .vop_mountctl = null_mountctl | |
984263bc | 250 | }; |
984263bc | 251 |