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 1.2 (Berkeley) 06/03/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 <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 #ifdef FDESC_DIAGNOSTIC 128 printf("fdesc_unmount: calling mntflushbuf\n"); 129 #endif 130 mntflushbuf(mp, 0); 131 #ifdef FDESC_DIAGNOSTIC 132 printf("fdesc_unmount: calling mntinvalbuf\n"); 133 #endif 134 if (mntinvalbuf(mp, 1)) 135 return (EBUSY); 136 if (rootvp->v_usecount > 1) 137 return (EBUSY); 138 #ifdef FDESC_DIAGNOSTIC 139 printf("fdesc_unmount: calling vflush\n"); 140 #endif 141 if (error = vflush(mp, rootvp, flags)) 142 return (error); 143 144 #ifdef FDESC_DIAGNOSTIC 145 vprint("fdesc root", rootvp); 146 #endif 147 /* 148 * Release reference on underlying root vnode 149 */ 150 vrele(rootvp); 151 /* 152 * And blow it away for future re-use 153 */ 154 vgone(rootvp); 155 /* 156 * Finally, throw away the fdescmount structure 157 */ 158 free(mp->mnt_data, M_UFSMNT); /* XXX */ 159 mp->mnt_data = 0; 160 return 0; 161 } 162 163 fdesc_root(mp, vpp) 164 struct mount *mp; 165 struct vnode **vpp; 166 { 167 USES_VOP_LOCK; 168 struct vnode *vp; 169 int error; 170 171 #ifdef FDESC_DIAGNOSTIC 172 printf("fdesc_root(mp = %x)\n", mp); 173 #endif 174 175 /* 176 * Return locked reference to root. 177 */ 178 vp = VFSTOFDESC(mp)->f_root; 179 VREF(vp); 180 VOP_LOCK(vp); 181 *vpp = vp; 182 return (0); 183 } 184 185 fdesc_quotactl(mp, cmd, uid, arg, p) 186 struct mount *mp; 187 int cmd; 188 uid_t uid; 189 caddr_t arg; 190 struct proc *p; 191 { 192 return (EOPNOTSUPP); 193 } 194 195 fdesc_statfs(mp, sbp, p) 196 struct mount *mp; 197 struct statfs *sbp; 198 struct proc *p; 199 { 200 struct filedesc *fdp; 201 int lim; 202 int i; 203 int last; 204 int freefd; 205 206 #ifdef FDESC_DIAGNOSTIC 207 printf("fdesc_statfs(mp = %x)\n", mp); 208 #endif 209 210 /* 211 * Compute number of free file descriptors. 212 * [ Strange results will ensue if the open file 213 * limit is ever reduced below the current number 214 * of open files... ] 215 */ 216 lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur; 217 fdp = p->p_fd; 218 last = min(fdp->fd_nfiles, lim); 219 freefd = 0; 220 for (i = fdp->fd_freefile; i < last; i++) 221 if (fdp->fd_ofiles[i] == NULL) 222 freefd++; 223 224 /* 225 * Adjust for the fact that the fdesc array may not 226 * have been fully allocated yet. 227 */ 228 if (fdp->fd_nfiles < lim) 229 freefd += (lim - fdp->fd_nfiles); 230 231 sbp->f_type = MOUNT_FDESC; 232 sbp->f_flags = 0; 233 sbp->f_bsize = DEV_BSIZE; 234 sbp->f_iosize = DEV_BSIZE; 235 sbp->f_blocks = 2; /* 1K to keep df happy */ 236 sbp->f_bfree = 0; 237 sbp->f_bavail = 0; 238 sbp->f_files = lim + 1; /* Allow for "." */ 239 sbp->f_ffree = freefd; /* See comments above */ 240 if (sbp != &mp->mnt_stat) { 241 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 242 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 243 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 244 } 245 return (0); 246 } 247 248 fdesc_sync(mp, waitfor) 249 struct mount *mp; 250 int waitfor; 251 { 252 return (0); 253 } 254 255 fdesc_fhtovp(mp, fhp, setgen, vpp) 256 struct mount *mp; 257 struct fid *fhp; 258 int setgen; 259 struct vnode **vpp; 260 { 261 return (EOPNOTSUPP); 262 } 263 264 fdesc_vptofh(vp, fhp) 265 struct vnode *vp; 266 struct fid *fhp; 267 { 268 return (EOPNOTSUPP); 269 } 270 271 struct vfsops fdesc_vfsops = { 272 fdesc_mount, 273 fdesc_start, 274 fdesc_unmount, 275 fdesc_root, 276 fdesc_quotactl, 277 fdesc_statfs, 278 fdesc_sync, 279 fdesc_fhtovp, 280 fdesc_vptofh, 281 fdesc_init, 282 }; 283