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 * %sccs.include.redist.c% 9 * 10 * @(#)fdesc_vfsops.c 8.9 (Berkeley) 05/10/95 11 * 12 * $Id: fdesc_vfsops.c,v 1.9 1993/04/06 15:28:33 jsp Exp $ 13 */ 14 15 /* 16 * /dev/fd Filesystem 17 */ 18 19 #include <sys/param.h> 20 #include <sys/systm.h> 21 #include <sys/time.h> 22 #include <sys/types.h> 23 #include <sys/proc.h> 24 #include <sys/resourcevar.h> 25 #include <sys/filedesc.h> 26 #include <sys/vnode.h> 27 #include <sys/mount.h> 28 #include <sys/namei.h> 29 #include <sys/malloc.h> 30 #include <miscfs/fdesc/fdesc.h> 31 32 /* 33 * Mount the per-process file descriptors (/dev/fd) 34 */ 35 int 36 fdesc_mount(mp, path, data, ndp, p) 37 struct mount *mp; 38 char *path; 39 caddr_t data; 40 struct nameidata *ndp; 41 struct proc *p; 42 { 43 int error = 0; 44 u_int size; 45 struct fdescmount *fmp; 46 struct vnode *rvp; 47 48 /* 49 * Update is a no-op 50 */ 51 if (mp->mnt_flag & MNT_UPDATE) 52 return (EOPNOTSUPP); 53 54 error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp); 55 if (error) 56 return (error); 57 58 MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount), 59 M_UFSMNT, M_WAITOK); /* XXX */ 60 rvp->v_type = VDIR; 61 rvp->v_flag |= VROOT; 62 fmp->f_root = rvp; 63 /* XXX -- don't mark as local to work around fts() problems */ 64 /*mp->mnt_flag |= MNT_LOCAL;*/ 65 mp->mnt_data = (qaddr_t) fmp; 66 vfs_getnewfsid(mp); 67 68 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 69 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 70 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 71 bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc")); 72 return (0); 73 } 74 75 int 76 fdesc_start(mp, flags, p) 77 struct mount *mp; 78 int flags; 79 struct proc *p; 80 { 81 return (0); 82 } 83 84 int 85 fdesc_unmount(mp, mntflags, p) 86 struct mount *mp; 87 int mntflags; 88 struct proc *p; 89 { 90 int error; 91 int flags = 0; 92 struct vnode *rootvp = VFSTOFDESC(mp)->f_root; 93 94 if (mntflags & MNT_FORCE) 95 flags |= FORCECLOSE; 96 97 /* 98 * Clear out buffer cache. I don't think we 99 * ever get anything cached at this level at the 100 * moment, but who knows... 101 */ 102 if (rootvp->v_usecount > 1) 103 return (EBUSY); 104 if (error = vflush(mp, rootvp, flags)) 105 return (error); 106 107 /* 108 * Release reference on underlying root vnode 109 */ 110 vrele(rootvp); 111 /* 112 * And blow it away for future re-use 113 */ 114 vgone(rootvp); 115 /* 116 * Finally, throw away the fdescmount structure 117 */ 118 free(mp->mnt_data, M_UFSMNT); /* XXX */ 119 mp->mnt_data = 0; 120 121 return (0); 122 } 123 124 int 125 fdesc_root(mp, vpp) 126 struct mount *mp; 127 struct vnode **vpp; 128 { 129 struct vnode *vp; 130 131 /* 132 * Return locked reference to root. 133 */ 134 vp = VFSTOFDESC(mp)->f_root; 135 VREF(vp); 136 VOP_LOCK(vp); 137 *vpp = vp; 138 return (0); 139 } 140 141 int 142 fdesc_statfs(mp, sbp, p) 143 struct mount *mp; 144 struct statfs *sbp; 145 struct proc *p; 146 { 147 struct filedesc *fdp; 148 int lim; 149 int i; 150 int last; 151 int freefd; 152 153 /* 154 * Compute number of free file descriptors. 155 * [ Strange results will ensue if the open file 156 * limit is ever reduced below the current number 157 * of open files... ] 158 */ 159 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 160 fdp = p->p_fd; 161 last = min(fdp->fd_nfiles, lim); 162 freefd = 0; 163 for (i = fdp->fd_freefile; i < last; i++) 164 if (fdp->fd_ofiles[i] == NULL) 165 freefd++; 166 167 /* 168 * Adjust for the fact that the fdesc array may not 169 * have been fully allocated yet. 170 */ 171 if (fdp->fd_nfiles < lim) 172 freefd += (lim - fdp->fd_nfiles); 173 174 sbp->f_flags = 0; 175 sbp->f_bsize = DEV_BSIZE; 176 sbp->f_iosize = DEV_BSIZE; 177 sbp->f_blocks = 2; /* 1K to keep df happy */ 178 sbp->f_bfree = 0; 179 sbp->f_bavail = 0; 180 sbp->f_files = lim + 1; /* Allow for "." */ 181 sbp->f_ffree = freefd; /* See comments above */ 182 if (sbp != &mp->mnt_stat) { 183 sbp->f_type = mp->mnt_vfc->vfc_typenum; 184 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 185 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 186 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 187 } 188 return (0); 189 } 190 191 int 192 fdesc_sync(mp, waitfor) 193 struct mount *mp; 194 int waitfor; 195 { 196 197 return (0); 198 } 199 200 #define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \ 201 struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp) 202 #define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \ 203 struct proc *)))eopnotsupp) 204 #define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ 205 size_t, struct proc *)))eopnotsupp) 206 #define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \ 207 eopnotsupp) 208 #define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp) 209 210 struct vfsops fdesc_vfsops = { 211 fdesc_mount, 212 fdesc_start, 213 fdesc_unmount, 214 fdesc_root, 215 fdesc_quotactl, 216 fdesc_statfs, 217 fdesc_sync, 218 fdesc_vget, 219 fdesc_fhtovp, 220 fdesc_vptofh, 221 fdesc_init, 222 fdesc_sysctl, 223 }; 224