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