1*53838Spendry /*
2*53838Spendry  * Copyright (c) 1992 The Regents of the University of California
3*53838Spendry  * Copyright (c) 1990, 1992 Jan-Simon Pendry
4*53838Spendry  * All rights reserved.
5*53838Spendry  *
6*53838Spendry  * This code is derived from software donated to Berkeley by
7*53838Spendry  * Jan-Simon Pendry.
8*53838Spendry  *
9*53838Spendry  * %sccs.include.redist.c%
10*53838Spendry  *
11*53838Spendry  *	@(#)fdesc_vfsops.c	1.1 (Berkeley) 06/03/92
12*53838Spendry  *
13*53838Spendry  * $Id: fdesc_vfsops.c,v 1.6 1992/05/30 10:25:59 jsp Exp jsp $
14*53838Spendry  */
15*53838Spendry 
16*53838Spendry /*
17*53838Spendry  * /dev/fd Filesystem
18*53838Spendry  */
19*53838Spendry 
20*53838Spendry #include <sys/param.h>
21*53838Spendry #include <sys/systm.h>
22*53838Spendry #include <sys/time.h>
23*53838Spendry #include <sys/types.h>
24*53838Spendry #include <sys/proc.h>
25*53838Spendry #include <sys/resourcevar.h>
26*53838Spendry #include <sys/filedesc.h>
27*53838Spendry #include <sys/vnode.h>
28*53838Spendry #include <sys/mount.h>
29*53838Spendry #include <sys/namei.h>
30*53838Spendry #include <sys/malloc.h>
31*53838Spendry #include <fdesc/fdesc.h>
32*53838Spendry 
33*53838Spendry static u_short fdesc_mntid;
34*53838Spendry 
35*53838Spendry fdesc_init()
36*53838Spendry {
37*53838Spendry #ifdef FDESC_DIAGNOSTIC
38*53838Spendry 	printf("fdesc_init\n");		/* printed during system boot */
39*53838Spendry #endif
40*53838Spendry }
41*53838Spendry 
42*53838Spendry /*
43*53838Spendry  * Mount the per-process file descriptors (/dev/fd)
44*53838Spendry  */
45*53838Spendry fdesc_mount(mp, path, data, ndp, p)
46*53838Spendry 	struct mount *mp;
47*53838Spendry 	char *path;
48*53838Spendry 	caddr_t data;
49*53838Spendry 	struct nameidata *ndp;
50*53838Spendry 	struct proc *p;
51*53838Spendry {
52*53838Spendry 	int error = 0;
53*53838Spendry 	u_int size;
54*53838Spendry 	struct fdescmount *fmp;
55*53838Spendry 	struct vnode *rvp;
56*53838Spendry 
57*53838Spendry #ifdef FDESC_DIAGNOSTIC
58*53838Spendry 	printf("fdesc_mount(mp = %x)\n", mp);
59*53838Spendry #endif
60*53838Spendry 
61*53838Spendry 	/*
62*53838Spendry 	 * Update is a no-op
63*53838Spendry 	 */
64*53838Spendry 	if (mp->mnt_flag & MNT_UPDATE)
65*53838Spendry 		return (EOPNOTSUPP);
66*53838Spendry 
67*53838Spendry 	error = getnewvnode(VT_UFS, mp, fdesc_vnodeop_p, &rvp);	/* XXX */
68*53838Spendry 	if (error)
69*53838Spendry 		return (error);
70*53838Spendry 
71*53838Spendry 	MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount),
72*53838Spendry 				M_UFSMNT, M_WAITOK);	/* XXX */
73*53838Spendry 	rvp->v_type = VDIR;
74*53838Spendry 	rvp->v_flag |= VROOT;
75*53838Spendry #ifdef FDESC_DIAGNOSTIC
76*53838Spendry 	printf("fdesc_mount: root vp = %x\n", rvp);
77*53838Spendry #endif
78*53838Spendry 	fmp->f_root = rvp;
79*53838Spendry 	mp->mnt_flag |= MNT_LOCAL;
80*53838Spendry 	mp->mnt_data = (qaddr_t) fmp;
81*53838Spendry 	getnewfsid(mp, MOUNT_FDESC);
82*53838Spendry 
83*53838Spendry 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
84*53838Spendry 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
85*53838Spendry 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
86*53838Spendry 	bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc"));
87*53838Spendry #ifdef FDESC_DIAGNOSTIC
88*53838Spendry 	printf("fdesc_mount: at %s\n", mp->mnt_stat.f_mntonname);
89*53838Spendry #endif
90*53838Spendry 	return (0);
91*53838Spendry }
92*53838Spendry 
93*53838Spendry fdesc_start(mp, flags, p)
94*53838Spendry 	struct mount *mp;
95*53838Spendry 	int flags;
96*53838Spendry 	struct proc *p;
97*53838Spendry {
98*53838Spendry 	return (0);
99*53838Spendry }
100*53838Spendry 
101*53838Spendry fdesc_unmount(mp, mntflags, p)
102*53838Spendry 	struct mount *mp;
103*53838Spendry 	int mntflags;
104*53838Spendry 	struct proc *p;
105*53838Spendry {
106*53838Spendry 	int error;
107*53838Spendry 	int flags = 0;
108*53838Spendry 	extern int doforce;
109*53838Spendry 	struct vnode *rootvp = VFSTOFDESC(mp)->f_root;
110*53838Spendry 
111*53838Spendry #ifdef FDESC_DIAGNOSTIC
112*53838Spendry 	printf("fdesc_unmount(mp = %x)\n", mp);
113*53838Spendry #endif
114*53838Spendry 
115*53838Spendry 	if (mntflags & MNT_FORCE) {
116*53838Spendry 		/* fdesc can never be rootfs so don't check for it */
117*53838Spendry 		if (!doforce)
118*53838Spendry 			return (EINVAL);
119*53838Spendry 		flags |= FORCECLOSE;
120*53838Spendry 	}
121*53838Spendry 
122*53838Spendry 	/*
123*53838Spendry 	 * Clear out buffer cache.  I don't think we
124*53838Spendry 	 * ever get anything cached at this level at the
125*53838Spendry 	 * moment, but who knows...
126*53838Spendry 	 */
127*53838Spendry #ifdef FDESC_DIAGNOSTIC
128*53838Spendry 	printf("fdesc_unmount: calling mntflushbuf\n");
129*53838Spendry #endif
130*53838Spendry 	mntflushbuf(mp, 0);
131*53838Spendry #ifdef FDESC_DIAGNOSTIC
132*53838Spendry 	printf("fdesc_unmount: calling mntinvalbuf\n");
133*53838Spendry #endif
134*53838Spendry 	if (mntinvalbuf(mp, 1))
135*53838Spendry 		return (EBUSY);
136*53838Spendry 	if (rootvp->v_usecount > 1)
137*53838Spendry 		return (EBUSY);
138*53838Spendry #ifdef FDESC_DIAGNOSTIC
139*53838Spendry 	printf("fdesc_unmount: calling vflush\n");
140*53838Spendry #endif
141*53838Spendry 	if (error = vflush(mp, rootvp, flags))
142*53838Spendry 		return (error);
143*53838Spendry 
144*53838Spendry #ifdef FDESC_DIAGNOSTIC
145*53838Spendry 	vprint("fdesc root", rootvp);
146*53838Spendry #endif
147*53838Spendry 	/*
148*53838Spendry 	 * Release reference on underlying root vnode
149*53838Spendry 	 */
150*53838Spendry 	vrele(rootvp);
151*53838Spendry 	/*
152*53838Spendry 	 * And blow it away for future re-use
153*53838Spendry 	 */
154*53838Spendry 	vgone(rootvp);
155*53838Spendry 	/*
156*53838Spendry 	 * Finally, throw away the fdescmount structure
157*53838Spendry 	 */
158*53838Spendry 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
159*53838Spendry 	mp->mnt_data = 0;
160*53838Spendry 	return 0;
161*53838Spendry }
162*53838Spendry 
163*53838Spendry fdesc_root(mp, vpp)
164*53838Spendry 	struct mount *mp;
165*53838Spendry 	struct vnode **vpp;
166*53838Spendry {
167*53838Spendry 	USES_VOP_LOCK;
168*53838Spendry 	struct vnode *vp;
169*53838Spendry 	int error;
170*53838Spendry 
171*53838Spendry #ifdef FDESC_DIAGNOSTIC
172*53838Spendry 	printf("fdesc_root(mp = %x)\n", mp);
173*53838Spendry #endif
174*53838Spendry 
175*53838Spendry 	/*
176*53838Spendry 	 * Return locked reference to root.
177*53838Spendry 	 */
178*53838Spendry #ifdef FDESC_DIAGNOSTIC
179*53838Spendry 	printf("fdesc_root: fdesc = %x\n", VFSTOFDESC(mp));
180*53838Spendry #endif
181*53838Spendry 	vp = VFSTOFDESC(mp)->f_root;
182*53838Spendry #ifdef FDESC_DIAGNOSTIC
183*53838Spendry 	printf("fdesc_root: root = %x\n", vp);
184*53838Spendry #endif
185*53838Spendry 	VREF(vp);
186*53838Spendry #ifdef FDESC_DIAGNOSTIC
187*53838Spendry 	printf("fdesc_root: calling VOP_LOCK\n");
188*53838Spendry #endif
189*53838Spendry 	VOP_LOCK(vp);
190*53838Spendry #ifdef FDESC_DIAGNOSTIC
191*53838Spendry 	printf("fdesc_root: back from VOP_LOCK\n");
192*53838Spendry #endif
193*53838Spendry 	*vpp = vp;
194*53838Spendry #ifdef FDESC_DIAGNOSTIC
195*53838Spendry 	printf("fdesc_root(mp = %x) = %x\n", mp, vp);
196*53838Spendry #endif
197*53838Spendry 	return (0);
198*53838Spendry }
199*53838Spendry 
200*53838Spendry fdesc_quotactl(mp, cmd, uid, arg, p)
201*53838Spendry 	struct mount *mp;
202*53838Spendry 	int cmd;
203*53838Spendry 	uid_t uid;
204*53838Spendry 	caddr_t arg;
205*53838Spendry 	struct proc *p;
206*53838Spendry {
207*53838Spendry 	return (EOPNOTSUPP);
208*53838Spendry }
209*53838Spendry 
210*53838Spendry fdesc_statfs(mp, sbp, p)
211*53838Spendry 	struct mount *mp;
212*53838Spendry 	struct statfs *sbp;
213*53838Spendry 	struct proc *p;
214*53838Spendry {
215*53838Spendry 	struct filedesc *fdp;
216*53838Spendry 	int lim;
217*53838Spendry 	int i;
218*53838Spendry 	int last;
219*53838Spendry 	int freefd;
220*53838Spendry 
221*53838Spendry #ifdef FDESC_DIAGNOSTIC
222*53838Spendry 	printf("fdesc_statfs(mp = %x)\n", mp);
223*53838Spendry #endif
224*53838Spendry 
225*53838Spendry 	/*
226*53838Spendry 	 * Compute number of free file descriptors.
227*53838Spendry 	 * [ Strange results will ensue if the open file
228*53838Spendry 	 * limit is ever reduced below the current number
229*53838Spendry 	 * of open files... ]
230*53838Spendry 	 */
231*53838Spendry 	lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
232*53838Spendry 	fdp = p->p_fd;
233*53838Spendry 	last = min(fdp->fd_nfiles, lim);
234*53838Spendry 	freefd = 0;
235*53838Spendry 	for (i = fdp->fd_freefile; i < last; i++)
236*53838Spendry 		if (fdp->fd_ofiles[i] == NULL)
237*53838Spendry 			freefd++;
238*53838Spendry 
239*53838Spendry 	/*
240*53838Spendry 	 * Adjust for the fact that the fdesc array may not
241*53838Spendry 	 * have been fully allocated yet.
242*53838Spendry 	 */
243*53838Spendry 	if (fdp->fd_nfiles < lim)
244*53838Spendry 		freefd += (lim - fdp->fd_nfiles);
245*53838Spendry 
246*53838Spendry 	sbp->f_type = MOUNT_FDESC;
247*53838Spendry 	sbp->f_flags = 0;
248*53838Spendry 	sbp->f_bsize = DEV_BSIZE;
249*53838Spendry 	sbp->f_iosize = DEV_BSIZE;
250*53838Spendry 	sbp->f_blocks = 2;		/* 1K to keep df happy */
251*53838Spendry 	sbp->f_bfree = 0;
252*53838Spendry 	sbp->f_bavail = 0;
253*53838Spendry 	sbp->f_files = lim + 1;		/* Allow for "." */
254*53838Spendry 	sbp->f_ffree = freefd;		/* See comments above */
255*53838Spendry 	if (sbp != &mp->mnt_stat) {
256*53838Spendry 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
257*53838Spendry 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
258*53838Spendry 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
259*53838Spendry 	}
260*53838Spendry 	return (0);
261*53838Spendry }
262*53838Spendry 
263*53838Spendry fdesc_sync(mp, waitfor)
264*53838Spendry 	struct mount *mp;
265*53838Spendry 	int waitfor;
266*53838Spendry {
267*53838Spendry 	return (0);
268*53838Spendry }
269*53838Spendry 
270*53838Spendry fdesc_fhtovp(mp, fhp, setgen, vpp)
271*53838Spendry 	struct mount *mp;
272*53838Spendry 	struct fid *fhp;
273*53838Spendry 	int setgen;
274*53838Spendry 	struct vnode **vpp;
275*53838Spendry {
276*53838Spendry 	return (EOPNOTSUPP);
277*53838Spendry }
278*53838Spendry 
279*53838Spendry fdesc_vptofh(vp, fhp)
280*53838Spendry 	struct vnode *vp;
281*53838Spendry 	struct fid *fhp;
282*53838Spendry {
283*53838Spendry 	return (EOPNOTSUPP);
284*53838Spendry }
285*53838Spendry 
286*53838Spendry struct vfsops fdesc_vfsops = {
287*53838Spendry 	fdesc_mount,
288*53838Spendry 	fdesc_start,
289*53838Spendry 	fdesc_unmount,
290*53838Spendry 	fdesc_root,
291*53838Spendry 	fdesc_quotactl,
292*53838Spendry 	fdesc_statfs,
293*53838Spendry 	fdesc_sync,
294*53838Spendry 	fdesc_fhtovp,
295*53838Spendry 	fdesc_vptofh,
296*53838Spendry 	fdesc_init,
297*53838Spendry };
298