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