Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / sys / vfs / nullfs / null_vnops.c
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.28 2006/10/27 04:56:34 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, we will need vnode
97  * operation dispatch. Other overlay filesystems, like unionfs might be
98  * 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_nch->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_nch->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_nch->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_nch->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_nch->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_nch->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_nch->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_nch->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_nch->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_fnch->mount)->nullm_vfs;
203         if (lmp != MOUNTTONULLMOUNT(ap->a_tnch->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 vop_ops null_vnode_vops = {
215         .vop_nresolve =         null_nresolve,
216         .vop_ncreate =          null_ncreate,
217         .vop_nmkdir =           null_nmkdir,
218         .vop_nmknod =           null_nmknod,
219         .vop_nlink =            null_nlink,
220         .vop_nsymlink =         null_nsymlink,
221         .vop_nwhiteout =        null_nwhiteout,
222         .vop_nremove =          null_nremove,
223         .vop_nrmdir =           null_nrmdir,
224         .vop_nrename =          null_nrename
225 };
226