Add an argument to vfs_add_vnodeops() to specify VVF_* flags for the vop_ops
[dragonfly.git] / sys / vfs / umapfs / umap_vfsops.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1992, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software donated to Berkeley by
6 * 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 * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
37 *
38 * $FreeBSD: src/sys/miscfs/umapfs/umap_vfsops.c,v 1.31.2.2 2001/09/11 09:49:53 kris Exp $
dc1be39c 39 * $DragonFly: src/sys/vfs/umapfs/Attic/umap_vfsops.c,v 1.18 2005/09/17 07:43:12 dillon Exp $
984263bc
MD
40 */
41
42/*
43 * Umap Layer
44 * (See mount_umap(8) for a description of this layer.)
45 */
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/kernel.h>
50#include <sys/proc.h>
51#include <sys/vnode.h>
52#include <sys/mount.h>
fad57d0e 53#include <sys/nlookup.h>
984263bc 54#include <sys/malloc.h>
1f2de5d4 55#include "umap.h"
984263bc
MD
56#include <vm/vm_zone.h>
57
0961aa92
MD
58extern struct vnodeopv_entry_desc umap_vnodeop_entries[];
59
984263bc
MD
60static MALLOC_DEFINE(M_UMAPFSMNT, "UMAP mount", "UMAP mount structure");
61
a6ee311a
RG
62static int umapfs_fhtovp (struct mount *mp, struct fid *fidp,
63 struct vnode **vpp);
64static int umapfs_checkexp (struct mount *mp, struct sockaddr *nam,
65 int *extflagsp, struct ucred **credanonp);
66static int umapfs_mount (struct mount *mp, char *path, caddr_t data,
21739618 67 struct thread *td);
a6ee311a
RG
68static int umapfs_quotactl (struct mount *mp, int cmd, uid_t uid,
69 caddr_t arg, struct thread *td);
70static int umapfs_root (struct mount *mp, struct vnode **vpp);
a6ee311a
RG
71static int umapfs_statfs (struct mount *mp, struct statfs *sbp,
72 struct thread *td);
a6ee311a
RG
73static int umapfs_unmount (struct mount *mp, int mntflags,
74 struct thread *td);
75static int umapfs_vget (struct mount *mp, ino_t ino,
76 struct vnode **vpp);
77static int umapfs_vptofh (struct vnode *vp, struct fid *fhp);
78static int umapfs_extattrctl (struct mount *mp, int cmd,
984263bc 79 const char *attrname, caddr_t arg,
a6ee311a 80 struct thread *td);
984263bc
MD
81
82/*
83 * Mount umap layer
84 */
85static int
21739618 86umapfs_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
984263bc
MD
87{
88 struct umap_args args;
89 struct vnode *lowerrootvp, *vp;
90 struct vnode *umapm_rootvp;
91 struct umap_mount *amp;
fad57d0e 92 struct nlookupdata nd;
984263bc
MD
93 u_int size;
94 int error;
95#ifdef DEBUG
96 int i;
97#endif
98
99 /*
100 * Only for root
101 */
dadab5e9 102 if ((error = suser(td)) != 0)
984263bc
MD
103 return (error);
104
105#ifdef DEBUG
106 printf("umapfs_mount(mp = %p)\n", (void *)mp);
107#endif
108
109 /*
110 * Update is a no-op
111 */
112 if (mp->mnt_flag & MNT_UPDATE) {
113 return (EOPNOTSUPP);
984263bc
MD
114 }
115
116 /*
117 * Get argument
118 */
119 error = copyin(data, (caddr_t)&args, sizeof(struct umap_args));
120 if (error)
121 return (error);
122
123 /*
124 * Find lower node
125 */
fad57d0e
MD
126 lowerrootvp = NULL;
127 error = nlookup_init(&nd, args.target, UIO_USERSPACE, NLC_FOLLOW);
128 if (error == 0)
129 error = nlookup(&nd);
130 if (error == 0) {
131 error = cache_vget(nd.nl_ncp, nd.nl_cred, LK_EXCLUSIVE,
132 &lowerrootvp);
133 }
134 nlookup_done(&nd);
984263bc
MD
135 if (error)
136 return (error);
984263bc
MD
137
138 /*
139 * Sanity check on lower vnode
140 */
984263bc
MD
141#ifdef DEBUG
142 printf("vp = %p, check for VDIR...\n", (void *)lowerrootvp);
143#endif
984263bc
MD
144 if (lowerrootvp->v_type != VDIR) {
145 vput(lowerrootvp);
146 return (EINVAL);
147 }
148
149#ifdef DEBUG
150 printf("mp = %p\n", (void *)mp);
151#endif
152
153 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
154 M_UMAPFSMNT, M_WAITOK); /* XXX */
155
156 /*
157 * Save reference to underlying FS
158 */
159 amp->umapm_vfs = lowerrootvp->v_mount;
160
161 /*
162 * Now copy in the number of entries and maps for umap mapping.
163 */
164 if (args.nentries > MAPFILEENTRIES || args.gnentries >
165 GMAPFILEENTRIES) {
166 vput(lowerrootvp);
167 return (error);
168 }
169
170 amp->info_nentries = args.nentries;
171 amp->info_gnentries = args.gnentries;
172 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
173 2*sizeof(u_long)*args.nentries);
174 if (error)
175 return (error);
176
177#ifdef DEBUG
178 printf("umap_mount:nentries %d\n",args.nentries);
179 for (i = 0; i < args.nentries; i++)
180 printf(" %lu maps to %lu\n", amp->info_mapdata[i][0],
181 amp->info_mapdata[i][1]);
182#endif
183
184 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
185 2*sizeof(u_long)*args.gnentries);
186 if (error)
187 return (error);
188
189#ifdef DEBUG
190 printf("umap_mount:gnentries %d\n",args.gnentries);
191 for (i = 0; i < args.gnentries; i++)
192 printf(" group %lu maps to %lu\n",
193 amp->info_gmapdata[i][0],
194 amp->info_gmapdata[i][1]);
195#endif
196
dc1be39c
MD
197 vfs_add_vnodeops(mp, &mp->mnt_vn_norm_ops,
198 umap_vnodeop_entries, 0);
984263bc
MD
199
200 /*
201 * Save reference. Each mount also holds
202 * a reference on the root vnode.
203 */
204 error = umap_node_create(mp, lowerrootvp, &vp);
205 /*
206 * Unlock the node (either the lower or the alias)
207 */
5fd012e0 208 VOP_UNLOCK(vp, 0, td);
984263bc
MD
209 /*
210 * Make sure the node alias worked
211 */
212 if (error) {
213 vrele(lowerrootvp);
214 free(amp, M_UMAPFSMNT); /* XXX */
215 return (error);
216 }
217
218 /*
219 * Keep a held reference to the root vnode.
220 * It is vrele'd in umapfs_unmount.
221 */
222 umapm_rootvp = vp;
223 umapm_rootvp->v_flag |= VROOT;
224 amp->umapm_rootvp = umapm_rootvp;
225 if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
226 mp->mnt_flag |= MNT_LOCAL;
227 mp->mnt_data = (qaddr_t) amp;
228 vfs_getnewfsid(mp);
229
984263bc
MD
230 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
231 &size);
232 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
dadab5e9 233 (void)umapfs_statfs(mp, &mp->mnt_stat, td);
984263bc
MD
234 return (0);
235}
236
984263bc
MD
237/*
238 * Free reference to umap layer
239 */
240static int
dadab5e9 241umapfs_unmount(struct mount *mp, int mntflags, struct thread *td)
984263bc
MD
242{
243 int error;
244 int flags = 0;
245
246#ifdef DEBUG
247 printf("umapfs_unmount(mp = %p)\n", (void *)mp);
248#endif
249
250 if (mntflags & MNT_FORCE)
251 flags |= FORCECLOSE;
252
253 /*
254 * Clear out buffer cache. I don't think we
255 * ever get anything cached at this level at the
256 * moment, but who knows...
257 */
258#ifdef notyet
259 mntflushbuf(mp, 0);
260 if (mntinvalbuf(mp, 1))
261 return (EBUSY);
262#endif
263 /* There is 1 extra root vnode reference (umapm_rootvp). */
264 error = vflush(mp, 1, flags);
265 if (error)
266 return (error);
267
268 /*
269 * Finally, throw away the umap_mount structure
270 */
271 free(mp->mnt_data, M_UMAPFSMNT); /* XXX */
272 mp->mnt_data = 0;
273 return (0);
274}
275
276static int
dadab5e9 277umapfs_root(struct mount *mp, struct vnode **vpp)
984263bc 278{
dadab5e9 279 struct thread *td = curthread; /* XXX */
984263bc
MD
280 struct vnode *vp;
281
282#ifdef DEBUG
283 printf("umapfs_root(mp = %p, vp = %p->%p)\n",
284 (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
285 (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
286#endif
287
288 /*
289 * Return locked reference to root.
290 */
291 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
597aea93 292 vref(vp);
5fd012e0 293 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
984263bc
MD
294 *vpp = vp;
295 return (0);
296}
297
298static int
dadab5e9
MD
299umapfs_quotactl(struct mount *mp, int cmd, uid_t uid,
300 caddr_t arg, struct thread *td)
984263bc 301{
dadab5e9 302 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, td));
984263bc
MD
303}
304
305static int
dadab5e9 306umapfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
984263bc
MD
307{
308 int error;
309 struct statfs mstat;
310
311#ifdef DEBUG
312 printf("umapfs_statfs(mp = %p, vp = %p->%p)\n",
313 (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
314 (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
315#endif
316
317 bzero(&mstat, sizeof(mstat));
318
dadab5e9 319 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, td);
984263bc
MD
320 if (error)
321 return (error);
322
323 /* now copy across the "interesting" information and fake the rest */
324 sbp->f_type = mstat.f_type;
325 sbp->f_flags = mstat.f_flags;
326 sbp->f_bsize = mstat.f_bsize;
327 sbp->f_iosize = mstat.f_iosize;
328 sbp->f_blocks = mstat.f_blocks;
329 sbp->f_bfree = mstat.f_bfree;
330 sbp->f_bavail = mstat.f_bavail;
331 sbp->f_files = mstat.f_files;
332 sbp->f_ffree = mstat.f_ffree;
333 if (sbp != &mp->mnt_stat) {
334 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
984263bc
MD
335 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
336 }
337 return (0);
338}
339
984263bc 340static int
dadab5e9 341umapfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
984263bc
MD
342{
343
344 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
345}
346
347static int
dadab5e9 348umapfs_fhtovp(struct mount *mp, struct fid *fidp, struct vnode **vpp)
984263bc
MD
349{
350
351 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, vpp));
352}
353
354static int
dadab5e9
MD
355umapfs_checkexp(struct mount *mp, struct sockaddr *nam, int *exflagsp,
356 struct ucred **credanonp)
984263bc
MD
357{
358
359 return (VFS_CHECKEXP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, nam,
360 exflagsp, credanonp));
361}
362
363static int
dadab5e9 364umapfs_vptofh(struct vnode *vp, struct fid *fhp)
984263bc
MD
365{
366 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
367}
368
369static int
dadab5e9
MD
370umapfs_extattrctl(struct mount *mp, int cmd, const char *attrname,
371 caddr_t arg, struct thread *td)
984263bc
MD
372{
373 return (VFS_EXTATTRCTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, attrname,
dadab5e9 374 arg, td));
984263bc
MD
375}
376
377
378static struct vfsops umap_vfsops = {
43c45e8f
HP
379 .vfs_mount = umapfs_mount,
380 .vfs_unmount = umapfs_unmount,
381 .vfs_root = umapfs_root,
382 .vfs_quotactl = umapfs_quotactl,
383 .vfs_statfs = umapfs_statfs,
384 .vfs_sync = vfs_stdsync,
385 .vfs_vget = umapfs_vget,
386 .vfs_fhtovp = umapfs_fhtovp,
387 .vfs_checkexp = umapfs_checkexp,
388 .vfs_vptofh = umapfs_vptofh,
389 .vfs_init = umapfs_init,
390 .vfs_extattrctl = umapfs_extattrctl
984263bc
MD
391};
392
393VFS_SET(umap_vfsops, umap, VFCF_LOOPBACK);