1 /* 2 * Copyright (c) 1992 The Regents of the University of California 3 * Copyright (c) 1990, 1992 Jan-Simon Pendry 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 7.3 (Berkeley) 04/22/93 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 dev_t devctty; 34 35 fdesc_init() 36 { 37 #ifdef FDESC_DIAGNOSTIC 38 printf("fdesc_init\n"); /* printed during system boot */ 39 #endif 40 devctty = makedev(nchrdev, 0); 41 } 42 43 /* 44 * Mount the per-process file descriptors (/dev/fd) 45 */ 46 fdesc_mount(mp, path, data, ndp, p) 47 struct mount *mp; 48 char *path; 49 caddr_t data; 50 struct nameidata *ndp; 51 struct proc *p; 52 { 53 int error = 0; 54 u_int size; 55 struct fdescmount *fmp; 56 struct vnode *rvp; 57 58 #ifdef FDESC_DIAGNOSTIC 59 printf("fdesc_mount(mp = %x)\n", mp); 60 #endif 61 62 /* 63 * Update is a no-op 64 */ 65 if (mp->mnt_flag & MNT_UPDATE) 66 return (EOPNOTSUPP); 67 68 error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp); 69 if (error) 70 return (error); 71 72 MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount), 73 M_UFSMNT, M_WAITOK); /* XXX */ 74 rvp->v_type = VDIR; 75 rvp->v_flag |= VROOT; 76 #ifdef FDESC_DIAGNOSTIC 77 printf("fdesc_mount: root vp = %x\n", rvp); 78 #endif 79 fmp->f_root = rvp; 80 mp->mnt_flag |= MNT_LOCAL; 81 mp->mnt_data = (qaddr_t) fmp; 82 getnewfsid(mp, MOUNT_FDESC); 83 84 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 85 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 86 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); 87 bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc")); 88 #ifdef FDESC_DIAGNOSTIC 89 printf("fdesc_mount: at %s\n", mp->mnt_stat.f_mntonname); 90 #endif 91 return (0); 92 } 93 94 fdesc_start(mp, flags, p) 95 struct mount *mp; 96 int flags; 97 struct proc *p; 98 { 99 return (0); 100 } 101 102 fdesc_unmount(mp, mntflags, p) 103 struct mount *mp; 104 int mntflags; 105 struct proc *p; 106 { 107 int error; 108 int flags = 0; 109 extern int doforce; 110 struct vnode *rootvp = VFSTOFDESC(mp)->f_root; 111 112 #ifdef FDESC_DIAGNOSTIC 113 printf("fdesc_unmount(mp = %x)\n", mp); 114 #endif 115 116 if (mntflags & MNT_FORCE) { 117 /* fdesc can never be rootfs so don't check for it */ 118 if (!doforce) 119 return (EINVAL); 120 flags |= FORCECLOSE; 121 } 122 123 /* 124 * Clear out buffer cache. I don't think we 125 * ever get anything cached at this level at the 126 * moment, but who knows... 127 */ 128 #if 0 129 #ifdef FDESC_DIAGNOSTIC 130 printf("fdesc_unmount: calling mntflushbuf\n"); 131 #endif 132 mntflushbuf(mp, 0); 133 #ifdef FDESC_DIAGNOSTIC 134 printf("fdesc_unmount: calling mntinvalbuf\n"); 135 #endif 136 if (mntinvalbuf(mp, 1)) 137 return (EBUSY); 138 #endif 139 if (rootvp->v_usecount > 1) 140 return (EBUSY); 141 #ifdef FDESC_DIAGNOSTIC 142 printf("fdesc_unmount: calling vflush\n"); 143 #endif 144 if (error = vflush(mp, rootvp, flags)) 145 return (error); 146 147 #ifdef FDESC_DIAGNOSTIC 148 vprint("fdesc root", rootvp); 149 #endif 150 /* 151 * Release reference on underlying root vnode 152 */ 153 vrele(rootvp); 154 /* 155 * And blow it away for future re-use 156 */ 157 vgone(rootvp); 158 /* 159 * Finally, throw away the fdescmount structure 160 */ 161 free(mp->mnt_data, M_UFSMNT); /* XXX */ 162 mp->mnt_data = 0; 163 return 0; 164 } 165 166 fdesc_root(mp, vpp) 167 struct mount *mp; 168 struct vnode **vpp; 169 { 170 struct vnode *vp; 171 int error; 172 173 #ifdef FDESC_DIAGNOSTIC 174 printf("fdesc_root(mp = %x)\n", mp); 175 #endif 176 177 /* 178 * Return locked reference to root. 179 */ 180 vp = VFSTOFDESC(mp)->f_root; 181 VREF(vp); 182 VOP_LOCK(vp); 183 *vpp = vp; 184 return (0); 185 } 186 187 fdesc_quotactl(mp, cmd, uid, arg, p) 188 struct mount *mp; 189 int cmd; 190 uid_t uid; 191 caddr_t arg; 192 struct proc *p; 193 { 194 return (EOPNOTSUPP); 195 } 196 197 fdesc_statfs(mp, sbp, p) 198 struct mount *mp; 199 struct statfs *sbp; 200 struct proc *p; 201 { 202 struct filedesc *fdp; 203 int lim; 204 int i; 205 int last; 206 int freefd; 207 208 #ifdef FDESC_DIAGNOSTIC 209 printf("fdesc_statfs(mp = %x)\n", mp); 210 #endif 211 212 /* 213 * Compute number of free file descriptors. 214 * [ Strange results will ensue if the open file 215 * limit is ever reduced below the current number 216 * of open files... ] 217 */ 218 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 219 fdp = p->p_fd; 220 last = min(fdp->fd_nfiles, lim); 221 freefd = 0; 222 for (i = fdp->fd_freefile; i < last; i++) 223 if (fdp->fd_ofiles[i] == NULL) 224 freefd++; 225 226 /* 227 * Adjust for the fact that the fdesc array may not 228 * have been fully allocated yet. 229 */ 230 if (fdp->fd_nfiles < lim) 231 freefd += (lim - fdp->fd_nfiles); 232 233 sbp->f_type = MOUNT_FDESC; 234 sbp->f_flags = 0; 235 sbp->f_bsize = DEV_BSIZE; 236 sbp->f_iosize = DEV_BSIZE; 237 sbp->f_blocks = 2; /* 1K to keep df happy */ 238 sbp->f_bfree = 0; 239 sbp->f_bavail = 0; 240 sbp->f_files = lim + 1; /* Allow for "." */ 241 sbp->f_ffree = freefd; /* See comments above */ 242 if (sbp != &mp->mnt_stat) { 243 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 244 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 245 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 246 } 247 return (0); 248 } 249 250 fdesc_sync(mp, waitfor) 251 struct mount *mp; 252 int waitfor; 253 { 254 return (0); 255 } 256 257 /* 258 * Fdesc flat namespace lookup. 259 * Currently unsupported. 260 */ 261 fdesc_vget(mp, ino, vpp) 262 struct mount *mp; 263 ino_t ino; 264 struct vnode **vpp; 265 { 266 267 return (EOPNOTSUPP); 268 } 269 270 271 fdesc_fhtovp(mp, fhp, setgen, vpp) 272 struct mount *mp; 273 struct fid *fhp; 274 int setgen; 275 struct vnode **vpp; 276 { 277 return (EOPNOTSUPP); 278 } 279 280 fdesc_vptofh(vp, fhp) 281 struct vnode *vp; 282 struct fid *fhp; 283 { 284 return (EOPNOTSUPP); 285 } 286 287 struct vfsops fdesc_vfsops = { 288 fdesc_mount, 289 fdesc_start, 290 fdesc_unmount, 291 fdesc_root, 292 fdesc_quotactl, 293 fdesc_statfs, 294 fdesc_sync, 295 fdesc_vget, 296 fdesc_fhtovp, 297 fdesc_vptofh, 298 fdesc_init, 299 }; 300