fdesc_vfsops.c revision 22521
11541Srgrimes/*
222521Sdyson * Copyright (c) 1992, 1993, 1995
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software donated to Berkeley by
61541Srgrimes * Jan-Simon Pendry.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms, with or without
91541Srgrimes * modification, are permitted provided that the following conditions
101541Srgrimes * are met:
111541Srgrimes * 1. Redistributions of source code must retain the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer.
131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer in the
151541Srgrimes *    documentation and/or other materials provided with the distribution.
161541Srgrimes * 3. All advertising materials mentioning features or use of this software
171541Srgrimes *    must display the following acknowledgement:
181541Srgrimes *	This product includes software developed by the University of
191541Srgrimes *	California, Berkeley and its contributors.
201541Srgrimes * 4. Neither the name of the University nor the names of its contributors
211541Srgrimes *    may be used to endorse or promote products derived from this software
221541Srgrimes *    without specific prior written permission.
231541Srgrimes *
241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341541Srgrimes * SUCH DAMAGE.
351541Srgrimes *
361541Srgrimes *	@(#)fdesc_vfsops.c	8.4 (Berkeley) 1/21/94
371541Srgrimes *
3821673Sjkh * $FreeBSD: head/sys/fs/fdescfs/fdesc_vfsops.c 22521 1997-02-10 02:22:35Z dyson $
391541Srgrimes */
401541Srgrimes
411541Srgrimes/*
421541Srgrimes * /dev/fd Filesystem
431541Srgrimes */
441541Srgrimes
451541Srgrimes#include <sys/param.h>
461541Srgrimes#include <sys/systm.h>
472946Swollman#include <sys/kernel.h>
481541Srgrimes#include <sys/time.h>
491541Srgrimes#include <sys/types.h>
501541Srgrimes#include <sys/proc.h>
511541Srgrimes#include <sys/resourcevar.h>
521541Srgrimes#include <sys/filedesc.h>
531541Srgrimes#include <sys/vnode.h>
541541Srgrimes#include <sys/mount.h>
551541Srgrimes#include <sys/namei.h>
561541Srgrimes#include <sys/malloc.h>
571541Srgrimes#include <miscfs/fdesc/fdesc.h>
581541Srgrimes
5912333Sbdestatic int	fdesc_fhtovp __P((struct mount *mp, struct fid *fhp,
6012333Sbde				  struct mbuf *nam, struct vnode **vpp,
6112333Sbde				  int *exflagsp, struct ucred **credanonp));
6212333Sbdestatic int	fdesc_mount __P((struct mount *mp, char *path, caddr_t data,
6312333Sbde				 struct nameidata *ndp, struct proc *p));
6412333Sbdestatic int	fdesc_quotactl __P((struct mount *mp, int cmd, uid_t uid,
6512333Sbde				    caddr_t arg, struct proc *p));
6612333Sbdestatic int	fdesc_start __P((struct mount *mp, int flags, struct proc *p));
6712333Sbdestatic int	fdesc_unmount __P((struct mount *mp, int mntflags,
6812333Sbde				   struct proc *p));
6912333Sbdestatic int	fdesc_statfs __P((struct mount *mp, struct statfs *sbp,
7012333Sbde				  struct proc *p));
7112333Sbdestatic int	fdesc_sync __P((struct mount *mp, int waitfor,
7212333Sbde				struct ucred *cred, struct proc *p));
7312333Sbdestatic int	fdesc_vget __P((struct mount *mp, ino_t ino,
7412333Sbde				struct vnode **vpp));
7512333Sbdestatic int	fdesc_vptofh __P((struct vnode *vp, struct fid *fhp));
7612333Sbde
771541Srgrimes/*
781541Srgrimes * Mount the per-process file descriptors (/dev/fd)
791541Srgrimes */
8012143Sphkstatic int
811541Srgrimesfdesc_mount(mp, path, data, ndp, p)
821541Srgrimes	struct mount *mp;
831541Srgrimes	char *path;
841541Srgrimes	caddr_t data;
851541Srgrimes	struct nameidata *ndp;
861541Srgrimes	struct proc *p;
871541Srgrimes{
881541Srgrimes	int error = 0;
891541Srgrimes	u_int size;
901541Srgrimes	struct fdescmount *fmp;
911541Srgrimes	struct vnode *rvp;
921541Srgrimes
931541Srgrimes	/*
941541Srgrimes	 * Update is a no-op
951541Srgrimes	 */
961541Srgrimes	if (mp->mnt_flag & MNT_UPDATE)
971541Srgrimes		return (EOPNOTSUPP);
981541Srgrimes
991541Srgrimes	error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp);
1001541Srgrimes	if (error)
1011541Srgrimes		return (error);
1021541Srgrimes
1031541Srgrimes	MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount),
1041541Srgrimes				M_UFSMNT, M_WAITOK);	/* XXX */
1051541Srgrimes	rvp->v_type = VDIR;
1061541Srgrimes	rvp->v_flag |= VROOT;
1071541Srgrimes	fmp->f_root = rvp;
1081541Srgrimes	/* XXX -- don't mark as local to work around fts() problems */
1091541Srgrimes	/*mp->mnt_flag |= MNT_LOCAL;*/
1101541Srgrimes	mp->mnt_data = (qaddr_t) fmp;
11122521Sdyson	vfs_getnewfsid(mp);
1121541Srgrimes
1131541Srgrimes	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
1141541Srgrimes	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
1151541Srgrimes	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
1161541Srgrimes	bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc"));
11710533Smpp	(void)fdesc_statfs(mp, &mp->mnt_stat, p);
1181541Srgrimes	return (0);
1191541Srgrimes}
1201541Srgrimes
12112143Sphkstatic int
1221541Srgrimesfdesc_start(mp, flags, p)
1231541Srgrimes	struct mount *mp;
1241541Srgrimes	int flags;
1251541Srgrimes	struct proc *p;
1261541Srgrimes{
1271541Srgrimes	return (0);
1281541Srgrimes}
1291541Srgrimes
13012143Sphkstatic int
1311541Srgrimesfdesc_unmount(mp, mntflags, p)
1321541Srgrimes	struct mount *mp;
1331541Srgrimes	int mntflags;
1341541Srgrimes	struct proc *p;
1351541Srgrimes{
1361541Srgrimes	int error;
1371541Srgrimes	int flags = 0;
1381541Srgrimes	struct vnode *rootvp = VFSTOFDESC(mp)->f_root;
1391541Srgrimes
14022521Sdyson	if (mntflags & MNT_FORCE)
1411541Srgrimes		flags |= FORCECLOSE;
1421541Srgrimes
1431541Srgrimes	/*
1441541Srgrimes	 * Clear out buffer cache.  I don't think we
1451541Srgrimes	 * ever get anything cached at this level at the
1461541Srgrimes	 * moment, but who knows...
1471541Srgrimes	 */
1481541Srgrimes	if (rootvp->v_usecount > 1)
1491541Srgrimes		return (EBUSY);
1501541Srgrimes	if (error = vflush(mp, rootvp, flags))
1511541Srgrimes		return (error);
1521541Srgrimes
1531541Srgrimes	/*
1541541Srgrimes	 * Release reference on underlying root vnode
1551541Srgrimes	 */
1561541Srgrimes	vrele(rootvp);
1571541Srgrimes	/*
1581541Srgrimes	 * And blow it away for future re-use
1591541Srgrimes	 */
1601541Srgrimes	vgone(rootvp);
1611541Srgrimes	/*
1621541Srgrimes	 * Finally, throw away the fdescmount structure
1631541Srgrimes	 */
1641541Srgrimes	free(mp->mnt_data, M_UFSMNT);	/* XXX */
1651541Srgrimes	mp->mnt_data = 0;
1661541Srgrimes
1671541Srgrimes	return (0);
1681541Srgrimes}
1691541Srgrimes
1701541Srgrimesint
1711541Srgrimesfdesc_root(mp, vpp)
1721541Srgrimes	struct mount *mp;
1731541Srgrimes	struct vnode **vpp;
1741541Srgrimes{
17522521Sdyson	struct proc *p = curproc;	/* XXX */
1761541Srgrimes	struct vnode *vp;
1771541Srgrimes
1781541Srgrimes	/*
1791541Srgrimes	 * Return locked reference to root.
1801541Srgrimes	 */
1811541Srgrimes	vp = VFSTOFDESC(mp)->f_root;
1821541Srgrimes	VREF(vp);
18322521Sdyson	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1841541Srgrimes	*vpp = vp;
1851541Srgrimes	return (0);
1861541Srgrimes}
1871541Srgrimes
18812143Sphkstatic int
1891541Srgrimesfdesc_statfs(mp, sbp, p)
1901541Srgrimes	struct mount *mp;
1911541Srgrimes	struct statfs *sbp;
1921541Srgrimes	struct proc *p;
1931541Srgrimes{
1941541Srgrimes	struct filedesc *fdp;
1951541Srgrimes	int lim;
1961541Srgrimes	int i;
1971541Srgrimes	int last;
1981541Srgrimes	int freefd;
1991541Srgrimes
2001541Srgrimes	/*
2011541Srgrimes	 * Compute number of free file descriptors.
2021541Srgrimes	 * [ Strange results will ensue if the open file
2031541Srgrimes	 * limit is ever reduced below the current number
2041541Srgrimes	 * of open files... ]
2051541Srgrimes	 */
2061541Srgrimes	lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
2071541Srgrimes	fdp = p->p_fd;
2081541Srgrimes	last = min(fdp->fd_nfiles, lim);
2091541Srgrimes	freefd = 0;
2101541Srgrimes	for (i = fdp->fd_freefile; i < last; i++)
2111541Srgrimes		if (fdp->fd_ofiles[i] == NULL)
2121541Srgrimes			freefd++;
2131541Srgrimes
2141541Srgrimes	/*
2151541Srgrimes	 * Adjust for the fact that the fdesc array may not
2161541Srgrimes	 * have been fully allocated yet.
2171541Srgrimes	 */
2181541Srgrimes	if (fdp->fd_nfiles < lim)
2191541Srgrimes		freefd += (lim - fdp->fd_nfiles);
2201541Srgrimes
2211541Srgrimes	sbp->f_flags = 0;
2221541Srgrimes	sbp->f_bsize = DEV_BSIZE;
2231541Srgrimes	sbp->f_iosize = DEV_BSIZE;
2241541Srgrimes	sbp->f_blocks = 2;		/* 1K to keep df happy */
2251541Srgrimes	sbp->f_bfree = 0;
2261541Srgrimes	sbp->f_bavail = 0;
2271541Srgrimes	sbp->f_files = lim + 1;		/* Allow for "." */
2281541Srgrimes	sbp->f_ffree = freefd;		/* See comments above */
2291541Srgrimes	if (sbp != &mp->mnt_stat) {
23022521Sdyson		sbp->f_type = mp->mnt_vfc->vfc_typenum;
2311541Srgrimes		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
2321541Srgrimes		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
2331541Srgrimes		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
2341541Srgrimes	}
2351541Srgrimes	return (0);
2361541Srgrimes}
2371541Srgrimes
23812143Sphkstatic int
23912333Sbdefdesc_sync(mp, waitfor, cred, p)
2401541Srgrimes	struct mount *mp;
2411541Srgrimes	int waitfor;
24212333Sbde	struct ucred *cred;
24312333Sbde	struct proc *p;
2441541Srgrimes{
2451541Srgrimes
2461541Srgrimes	return (0);
2471541Srgrimes}
2481541Srgrimes
24922521Sdyson#define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \
25022521Sdyson	    struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp)
25122521Sdyson#define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \
25222521Sdyson	    struct proc *)))eopnotsupp)
25322521Sdyson#define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
25422521Sdyson	    size_t, struct proc *)))eopnotsupp)
25522521Sdyson#define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \
25622521Sdyson	    eopnotsupp)
25722521Sdyson#define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp)
2581541Srgrimes
25912143Sphkstatic struct vfsops fdesc_vfsops = {
2601541Srgrimes	fdesc_mount,
2611541Srgrimes	fdesc_start,
2621541Srgrimes	fdesc_unmount,
2631541Srgrimes	fdesc_root,
2641541Srgrimes	fdesc_quotactl,
2651541Srgrimes	fdesc_statfs,
2661541Srgrimes	fdesc_sync,
2671541Srgrimes	fdesc_vget,
2681541Srgrimes	fdesc_fhtovp,
2691541Srgrimes	fdesc_vptofh,
2701541Srgrimes	fdesc_init,
2711541Srgrimes};
2722946Swollman
2737095SwollmanVFS_SET(fdesc_vfsops, fdesc, MOUNT_FDESC, VFCF_SYNTHETIC);
274