Add an argument to vfs_add_vnodeops() to specify VVF_* flags for the vop_ops
[dragonfly.git] / sys / vfs / fdesc / fdesc_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 * Jan-Simon Pendry.
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 * @(#)fdesc_vfsops.c 8.4 (Berkeley) 1/21/94
37 *
38 * $FreeBSD: src/sys/miscfs/fdesc/fdesc_vfsops.c,v 1.22.2.3 2002/08/23 17:42:39 njl Exp $
dc1be39c 39 * $DragonFly: src/sys/vfs/fdesc/fdesc_vfsops.c,v 1.16 2005/09/17 07:43:03 dillon Exp $
984263bc
MD
40 */
41
42/*
43 * /dev/fd Filesystem
44 */
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/filedesc.h>
49#include <sys/kernel.h>
50#include <sys/lock.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/proc.h>
54#include <sys/resourcevar.h>
55#include <sys/socket.h>
56#include <sys/vnode.h>
57
1f2de5d4 58#include "fdesc.h"
984263bc 59
0961aa92
MD
60extern struct vnodeopv_entry_desc fdesc_vnodeop_entries[];
61
984263bc
MD
62static MALLOC_DEFINE(M_FDESCMNT, "FDESC mount", "FDESC mount structure");
63
a6ee311a 64static int fdesc_mount (struct mount *mp, char *path, caddr_t data,
21739618 65 struct thread *td);
a6ee311a
RG
66static int fdesc_unmount (struct mount *mp, int mntflags,
67 struct thread *td);
68static int fdesc_statfs (struct mount *mp, struct statfs *sbp,
69 struct thread *td);
984263bc
MD
70
71/*
72 * Mount the per-process file descriptors (/dev/fd)
73 */
74static int
21739618 75fdesc_mount(struct mount *mp, char *path, caddr_t data, struct thread *td)
984263bc
MD
76{
77 int error = 0;
78 struct fdescmount *fmp;
79 struct vnode *rvp;
984263bc
MD
80
81 if (path == NULL)
82 panic("fdesc_mount: cannot mount as root");
83
84 /*
85 * Update is a no-op
86 */
87 if (mp->mnt_flag & MNT_UPDATE)
88 return (EOPNOTSUPP);
89
dc1be39c
MD
90 vfs_add_vnodeops(mp, &mp->mnt_vn_norm_ops,
91 fdesc_vnodeop_entries, 0);
0961aa92 92
dadab5e9 93 error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp, td);
984263bc
MD
94 if (error)
95 return (error);
96
97 MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount),
98 M_FDESCMNT, M_WAITOK); /* XXX */
99 rvp->v_type = VDIR;
100 rvp->v_flag |= VROOT;
101 fmp->f_root = rvp;
102 /* XXX -- don't mark as local to work around fts() problems */
103 /*mp->mnt_flag |= MNT_LOCAL;*/
104 mp->mnt_data = (qaddr_t) fmp;
105 vfs_getnewfsid(mp);
106
984263bc
MD
107 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
108 bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc"));
dadab5e9 109 (void)fdesc_statfs(mp, &mp->mnt_stat, td);
984263bc
MD
110 return (0);
111}
112
113static int
dadab5e9 114fdesc_unmount(struct mount *mp, int mntflags, struct thread *td)
984263bc
MD
115{
116 int error;
117 int flags = 0;
118
119 if (mntflags & MNT_FORCE)
120 flags |= FORCECLOSE;
121
122 /*
123 * Clear out buffer cache. I don't think we
124 * ever get anything cached at this level at the
125 * moment, but who knows...
126 *
127 * There is 1 extra root vnode reference corresponding
128 * to f_root.
129 */
130 if ((error = vflush(mp, 1, flags)) != 0)
131 return (error);
132
133 /*
134 * Finally, throw away the fdescmount structure
135 */
136 free(mp->mnt_data, M_FDESCMNT); /* XXX */
137 mp->mnt_data = 0;
138
139 return (0);
140}
141
142int
dadab5e9 143fdesc_root(struct mount *mp, struct vnode **vpp)
984263bc 144{
dadab5e9 145 struct thread *td = curthread; /* XXX */
984263bc
MD
146 struct vnode *vp;
147
148 /*
149 * Return locked reference to root.
150 */
151 vp = VFSTOFDESC(mp)->f_root;
597aea93 152 vref(vp);
5fd012e0 153 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
984263bc
MD
154 *vpp = vp;
155 return (0);
156}
157
158static int
dadab5e9 159fdesc_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
984263bc 160{
dadab5e9 161 struct proc *p = td->td_proc;
984263bc
MD
162 struct filedesc *fdp;
163 int lim;
164 int i;
165 int last;
166 int freefd;
167
dadab5e9
MD
168 KKASSERT(p);
169
984263bc
MD
170 /*
171 * Compute number of free file descriptors.
172 * [ Strange results will ensue if the open file
173 * limit is ever reduced below the current number
174 * of open files... ]
175 */
176 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
177 fdp = p->p_fd;
178 last = min(fdp->fd_nfiles, lim);
179 freefd = 0;
180 for (i = fdp->fd_freefile; i < last; i++)
0679adc4 181 if (fdp->fd_files[i].fp == NULL)
984263bc
MD
182 freefd++;
183
184 /*
185 * Adjust for the fact that the fdesc array may not
186 * have been fully allocated yet.
187 */
188 if (fdp->fd_nfiles < lim)
189 freefd += (lim - fdp->fd_nfiles);
190
191 sbp->f_flags = 0;
192 sbp->f_bsize = DEV_BSIZE;
193 sbp->f_iosize = DEV_BSIZE;
194 sbp->f_blocks = 2; /* 1K to keep df happy */
195 sbp->f_bfree = 0;
196 sbp->f_bavail = 0;
197 sbp->f_files = lim + 1; /* Allow for "." */
198 sbp->f_ffree = freefd; /* See comments above */
199 if (sbp != &mp->mnt_stat) {
200 sbp->f_type = mp->mnt_vfc->vfc_typenum;
201 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
984263bc
MD
202 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
203 }
204 return (0);
205}
206
207static struct vfsops fdesc_vfsops = {
43c45e8f
HP
208 .vfs_mount = fdesc_mount,
209 .vfs_unmount = fdesc_unmount,
210 .vfs_root = fdesc_root,
211 .vfs_statfs = fdesc_statfs,
212 .vfs_sync = vfs_stdsync,
213 .vfs_init = fdesc_init,
214 .vfs_uninit = fdesc_uninit
984263bc
MD
215};
216
217VFS_SET(fdesc_vfsops, fdesc, VFCF_SYNTHETIC);