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 * %sccs.include.redist.c% 9 * 10 * @(#)fdesc_vfsops.c 8.7 (Berkeley) 04/03/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 extern int doforce; 93 struct vnode *rootvp = VFSTOFDESC(mp)->f_root; 94 95 if (mntflags & MNT_FORCE) { 96 /* fdesc can never be rootfs so don't check for it */ 97 if (!doforce) 98 return (EINVAL); 99 flags |= FORCECLOSE; 100 } 101 102 /* 103 * Clear out buffer cache. I don't think we 104 * ever get anything cached at this level at the 105 * moment, but who knows... 106 */ 107 if (rootvp->v_usecount > 1) 108 return (EBUSY); 109 if (error = vflush(mp, rootvp, flags)) 110 return (error); 111 112 /* 113 * Release reference on underlying root vnode 114 */ 115 vrele(rootvp); 116 /* 117 * And blow it away for future re-use 118 */ 119 VOP_REVOKE(rootvp, 0); 120 /* 121 * Finally, throw away the fdescmount structure 122 */ 123 free(mp->mnt_data, M_UFSMNT); /* XXX */ 124 mp->mnt_data = 0; 125 126 return (0); 127 } 128 129 int 130 fdesc_root(mp, vpp) 131 struct mount *mp; 132 struct vnode **vpp; 133 { 134 struct vnode *vp; 135 136 /* 137 * Return locked reference to root. 138 */ 139 vp = VFSTOFDESC(mp)->f_root; 140 VREF(vp); 141 VOP_LOCK(vp); 142 *vpp = vp; 143 return (0); 144 } 145 146 int 147 fdesc_statfs(mp, sbp, p) 148 struct mount *mp; 149 struct statfs *sbp; 150 struct proc *p; 151 { 152 struct filedesc *fdp; 153 int lim; 154 int i; 155 int last; 156 int freefd; 157 158 /* 159 * Compute number of free file descriptors. 160 * [ Strange results will ensue if the open file 161 * limit is ever reduced below the current number 162 * of open files... ] 163 */ 164 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 165 fdp = p->p_fd; 166 last = min(fdp->fd_nfiles, lim); 167 freefd = 0; 168 for (i = fdp->fd_freefile; i < last; i++) 169 if (fdp->fd_ofiles[i] == NULL) 170 freefd++; 171 172 /* 173 * Adjust for the fact that the fdesc array may not 174 * have been fully allocated yet. 175 */ 176 if (fdp->fd_nfiles < lim) 177 freefd += (lim - fdp->fd_nfiles); 178 179 sbp->f_flags = 0; 180 sbp->f_bsize = DEV_BSIZE; 181 sbp->f_iosize = DEV_BSIZE; 182 sbp->f_blocks = 2; /* 1K to keep df happy */ 183 sbp->f_bfree = 0; 184 sbp->f_bavail = 0; 185 sbp->f_files = lim + 1; /* Allow for "." */ 186 sbp->f_ffree = freefd; /* See comments above */ 187 if (sbp != &mp->mnt_stat) { 188 sbp->f_type = mp->mnt_vfc->vfc_typenum; 189 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 190 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 191 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 192 } 193 return (0); 194 } 195 196 int 197 fdesc_sync(mp, waitfor) 198 struct mount *mp; 199 int waitfor; 200 { 201 202 return (0); 203 } 204 205 #define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \ 206 struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp) 207 #define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \ 208 struct proc *)))eopnotsupp) 209 #define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ 210 size_t, struct proc *)))eopnotsupp) 211 #define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \ 212 eopnotsupp) 213 #define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp) 214 215 struct vfsops fdesc_vfsops = { 216 fdesc_mount, 217 fdesc_start, 218 fdesc_unmount, 219 fdesc_root, 220 fdesc_quotactl, 221 fdesc_statfs, 222 fdesc_sync, 223 fdesc_vget, 224 fdesc_fhtovp, 225 fdesc_vptofh, 226 fdesc_init, 227 fdesc_sysctl, 228 }; 229