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.4 (Berkeley) 01/21/94 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 getnewfsid(mp, MOUNT_FDESC); 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 vgone(rootvp); 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_quotactl(mp, cmd, uid, arg, p) 148 struct mount *mp; 149 int cmd; 150 uid_t uid; 151 caddr_t arg; 152 struct proc *p; 153 { 154 155 return (EOPNOTSUPP); 156 } 157 158 int 159 fdesc_statfs(mp, sbp, p) 160 struct mount *mp; 161 struct statfs *sbp; 162 struct proc *p; 163 { 164 struct filedesc *fdp; 165 int lim; 166 int i; 167 int last; 168 int freefd; 169 170 /* 171 * Compute number of free file descriptors. 172 * [ Strange results will ensue if the open file 173 * limit is ever reduced below the current number 174 * of open files... ] 175 */ 176 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 177 fdp = p->p_fd; 178 last = min(fdp->fd_nfiles, lim); 179 freefd = 0; 180 for (i = fdp->fd_freefile; i < last; i++) 181 if (fdp->fd_ofiles[i] == NULL) 182 freefd++; 183 184 /* 185 * Adjust for the fact that the fdesc array may not 186 * have been fully allocated yet. 187 */ 188 if (fdp->fd_nfiles < lim) 189 freefd += (lim - fdp->fd_nfiles); 190 191 sbp->f_type = MOUNT_FDESC; 192 sbp->f_flags = 0; 193 sbp->f_bsize = DEV_BSIZE; 194 sbp->f_iosize = DEV_BSIZE; 195 sbp->f_blocks = 2; /* 1K to keep df happy */ 196 sbp->f_bfree = 0; 197 sbp->f_bavail = 0; 198 sbp->f_files = lim + 1; /* Allow for "." */ 199 sbp->f_ffree = freefd; /* See comments above */ 200 if (sbp != &mp->mnt_stat) { 201 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 202 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 203 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 204 } 205 return (0); 206 } 207 208 int 209 fdesc_sync(mp, waitfor) 210 struct mount *mp; 211 int waitfor; 212 { 213 214 return (0); 215 } 216 217 /* 218 * Fdesc flat namespace lookup. 219 * Currently unsupported. 220 */ 221 int 222 fdesc_vget(mp, ino, vpp) 223 struct mount *mp; 224 ino_t ino; 225 struct vnode **vpp; 226 { 227 228 return (EOPNOTSUPP); 229 } 230 231 int 232 fdesc_fhtovp(mp, fhp, setgen, vpp) 233 struct mount *mp; 234 struct fid *fhp; 235 int setgen; 236 struct vnode **vpp; 237 { 238 return (EOPNOTSUPP); 239 } 240 241 int 242 fdesc_vptofh(vp, fhp) 243 struct vnode *vp; 244 struct fid *fhp; 245 { 246 247 return (EOPNOTSUPP); 248 } 249 250 struct vfsops fdesc_vfsops = { 251 fdesc_mount, 252 fdesc_start, 253 fdesc_unmount, 254 fdesc_root, 255 fdesc_quotactl, 256 fdesc_statfs, 257 fdesc_sync, 258 fdesc_vget, 259 fdesc_fhtovp, 260 fdesc_vptofh, 261 fdesc_init, 262 }; 263