xref: /freebsd/sys/fs/fdescfs/fdesc_vfsops.c (revision e627b39baccd1ec9129690167cf5e6d860509655)
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 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  * $Id: fdesc_vfsops.c,v 1.6 1995/11/07 13:39:18 phk Exp $
39  */
40 
41 /*
42  * /dev/fd Filesystem
43  */
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/time.h>
49 #include <sys/types.h>
50 #include <sys/proc.h>
51 #include <sys/resourcevar.h>
52 #include <sys/filedesc.h>
53 #include <sys/vnode.h>
54 #include <sys/mount.h>
55 #include <sys/namei.h>
56 #include <sys/malloc.h>
57 #include <miscfs/fdesc/fdesc.h>
58 
59 static int	fdesc_fhtovp __P((struct mount *mp, struct fid *fhp,
60 				  struct mbuf *nam, struct vnode **vpp,
61 				  int *exflagsp, struct ucred **credanonp));
62 static int	fdesc_mount __P((struct mount *mp, char *path, caddr_t data,
63 				 struct nameidata *ndp, struct proc *p));
64 static int	fdesc_quotactl __P((struct mount *mp, int cmd, uid_t uid,
65 				    caddr_t arg, struct proc *p));
66 static int	fdesc_start __P((struct mount *mp, int flags, struct proc *p));
67 static int	fdesc_unmount __P((struct mount *mp, int mntflags,
68 				   struct proc *p));
69 static int	fdesc_statfs __P((struct mount *mp, struct statfs *sbp,
70 				  struct proc *p));
71 static int	fdesc_sync __P((struct mount *mp, int waitfor,
72 				struct ucred *cred, struct proc *p));
73 static int	fdesc_vget __P((struct mount *mp, ino_t ino,
74 				struct vnode **vpp));
75 static int	fdesc_vptofh __P((struct vnode *vp, struct fid *fhp));
76 
77 /*
78  * Mount the per-process file descriptors (/dev/fd)
79  */
80 static int
81 fdesc_mount(mp, path, data, ndp, p)
82 	struct mount *mp;
83 	char *path;
84 	caddr_t data;
85 	struct nameidata *ndp;
86 	struct proc *p;
87 {
88 	int error = 0;
89 	u_int size;
90 	struct fdescmount *fmp;
91 	struct vnode *rvp;
92 
93 	/*
94 	 * Update is a no-op
95 	 */
96 	if (mp->mnt_flag & MNT_UPDATE)
97 		return (EOPNOTSUPP);
98 
99 	error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp);
100 	if (error)
101 		return (error);
102 
103 	MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount),
104 				M_UFSMNT, M_WAITOK);	/* XXX */
105 	rvp->v_type = VDIR;
106 	rvp->v_flag |= VROOT;
107 	fmp->f_root = rvp;
108 	/* XXX -- don't mark as local to work around fts() problems */
109 	/*mp->mnt_flag |= MNT_LOCAL;*/
110 	mp->mnt_data = (qaddr_t) fmp;
111 	getnewfsid(mp, MOUNT_FDESC);
112 
113 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
114 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
115 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
116 	bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc"));
117 	(void)fdesc_statfs(mp, &mp->mnt_stat, p);
118 	return (0);
119 }
120 
121 static int
122 fdesc_start(mp, flags, p)
123 	struct mount *mp;
124 	int flags;
125 	struct proc *p;
126 {
127 	return (0);
128 }
129 
130 static int
131 fdesc_unmount(mp, mntflags, p)
132 	struct mount *mp;
133 	int mntflags;
134 	struct proc *p;
135 {
136 	int error;
137 	int flags = 0;
138 	struct vnode *rootvp = VFSTOFDESC(mp)->f_root;
139 
140 	if (mntflags & MNT_FORCE) {
141 		/* fdesc can never be rootfs so don't check for it */
142 		if (!doforce)
143 			return (EINVAL);
144 		flags |= FORCECLOSE;
145 	}
146 
147 	/*
148 	 * Clear out buffer cache.  I don't think we
149 	 * ever get anything cached at this level at the
150 	 * moment, but who knows...
151 	 */
152 	if (rootvp->v_usecount > 1)
153 		return (EBUSY);
154 	if (error = vflush(mp, rootvp, flags))
155 		return (error);
156 
157 	/*
158 	 * Release reference on underlying root vnode
159 	 */
160 	vrele(rootvp);
161 	/*
162 	 * And blow it away for future re-use
163 	 */
164 	vgone(rootvp);
165 	/*
166 	 * Finally, throw away the fdescmount structure
167 	 */
168 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
169 	mp->mnt_data = 0;
170 
171 	return (0);
172 }
173 
174 int
175 fdesc_root(mp, vpp)
176 	struct mount *mp;
177 	struct vnode **vpp;
178 {
179 	struct vnode *vp;
180 
181 	/*
182 	 * Return locked reference to root.
183 	 */
184 	vp = VFSTOFDESC(mp)->f_root;
185 	VREF(vp);
186 	VOP_LOCK(vp);
187 	*vpp = vp;
188 	return (0);
189 }
190 
191 static int
192 fdesc_quotactl(mp, cmd, uid, arg, p)
193 	struct mount *mp;
194 	int cmd;
195 	uid_t uid;
196 	caddr_t arg;
197 	struct proc *p;
198 {
199 
200 	return (EOPNOTSUPP);
201 }
202 
203 static int
204 fdesc_statfs(mp, sbp, p)
205 	struct mount *mp;
206 	struct statfs *sbp;
207 	struct proc *p;
208 {
209 	struct filedesc *fdp;
210 	int lim;
211 	int i;
212 	int last;
213 	int freefd;
214 
215 	/*
216 	 * Compute number of free file descriptors.
217 	 * [ Strange results will ensue if the open file
218 	 * limit is ever reduced below the current number
219 	 * of open files... ]
220 	 */
221 	lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
222 	fdp = p->p_fd;
223 	last = min(fdp->fd_nfiles, lim);
224 	freefd = 0;
225 	for (i = fdp->fd_freefile; i < last; i++)
226 		if (fdp->fd_ofiles[i] == NULL)
227 			freefd++;
228 
229 	/*
230 	 * Adjust for the fact that the fdesc array may not
231 	 * have been fully allocated yet.
232 	 */
233 	if (fdp->fd_nfiles < lim)
234 		freefd += (lim - fdp->fd_nfiles);
235 
236 	sbp->f_type = MOUNT_FDESC;
237 	sbp->f_flags = 0;
238 	sbp->f_bsize = DEV_BSIZE;
239 	sbp->f_iosize = DEV_BSIZE;
240 	sbp->f_blocks = 2;		/* 1K to keep df happy */
241 	sbp->f_bfree = 0;
242 	sbp->f_bavail = 0;
243 	sbp->f_files = lim + 1;		/* Allow for "." */
244 	sbp->f_ffree = freefd;		/* See comments above */
245 	if (sbp != &mp->mnt_stat) {
246 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
247 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
248 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
249 	}
250 	return (0);
251 }
252 
253 static int
254 fdesc_sync(mp, waitfor, cred, p)
255 	struct mount *mp;
256 	int waitfor;
257 	struct ucred *cred;
258 	struct proc *p;
259 {
260 
261 	return (0);
262 }
263 
264 /*
265  * Fdesc flat namespace lookup.
266  * Currently unsupported.
267  */
268 static int
269 fdesc_vget(mp, ino, vpp)
270 	struct mount *mp;
271 	ino_t ino;
272 	struct vnode **vpp;
273 {
274 
275 	return (EOPNOTSUPP);
276 }
277 
278 static int
279 fdesc_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
280 	struct mount *mp;
281 	struct fid *fhp;
282 	struct mbuf *nam;
283 	struct vnode **vpp;
284 	int *exflagsp;
285 	struct ucred **credanonp;
286 {
287 
288 	return (EOPNOTSUPP);
289 }
290 
291 static int
292 fdesc_vptofh(vp, fhp)
293 	struct vnode *vp;
294 	struct fid *fhp;
295 {
296 
297 	return (EOPNOTSUPP);
298 }
299 
300 static struct vfsops fdesc_vfsops = {
301 	fdesc_mount,
302 	fdesc_start,
303 	fdesc_unmount,
304 	fdesc_root,
305 	fdesc_quotactl,
306 	fdesc_statfs,
307 	fdesc_sync,
308 	fdesc_vget,
309 	fdesc_fhtovp,
310 	fdesc_vptofh,
311 	fdesc_init,
312 };
313 
314 VFS_SET(fdesc_vfsops, fdesc, MOUNT_FDESC, VFCF_SYNTHETIC);
315