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