1 /* 2 * Copyright (c) 1992, 1993, 1995 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.10 (Berkeley) 05/14/95 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 vfs_getnewfsid(mp); 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 struct vnode *rootvp = VFSTOFDESC(mp)->f_root; 93 94 if (mntflags & MNT_FORCE) 95 flags |= FORCECLOSE; 96 97 /* 98 * Clear out buffer cache. I don't think we 99 * ever get anything cached at this level at the 100 * moment, but who knows... 101 */ 102 if (rootvp->v_usecount > 1) 103 return (EBUSY); 104 if (error = vflush(mp, rootvp, flags)) 105 return (error); 106 107 /* 108 * Release reference on underlying root vnode 109 */ 110 vrele(rootvp); 111 /* 112 * And blow it away for future re-use 113 */ 114 vgone(rootvp); 115 /* 116 * Finally, throw away the fdescmount structure 117 */ 118 free(mp->mnt_data, M_UFSMNT); /* XXX */ 119 mp->mnt_data = 0; 120 121 return (0); 122 } 123 124 int 125 fdesc_root(mp, vpp) 126 struct mount *mp; 127 struct vnode **vpp; 128 { 129 struct proc *p = curproc; /* XXX */ 130 struct vnode *vp; 131 132 /* 133 * Return locked reference to root. 134 */ 135 vp = VFSTOFDESC(mp)->f_root; 136 VREF(vp); 137 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 138 *vpp = vp; 139 return (0); 140 } 141 142 int 143 fdesc_statfs(mp, sbp, p) 144 struct mount *mp; 145 struct statfs *sbp; 146 struct proc *p; 147 { 148 struct filedesc *fdp; 149 int lim; 150 int i; 151 int last; 152 int freefd; 153 154 /* 155 * Compute number of free file descriptors. 156 * [ Strange results will ensue if the open file 157 * limit is ever reduced below the current number 158 * of open files... ] 159 */ 160 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 161 fdp = p->p_fd; 162 last = min(fdp->fd_nfiles, lim); 163 freefd = 0; 164 for (i = fdp->fd_freefile; i < last; i++) 165 if (fdp->fd_ofiles[i] == NULL) 166 freefd++; 167 168 /* 169 * Adjust for the fact that the fdesc array may not 170 * have been fully allocated yet. 171 */ 172 if (fdp->fd_nfiles < lim) 173 freefd += (lim - fdp->fd_nfiles); 174 175 sbp->f_flags = 0; 176 sbp->f_bsize = DEV_BSIZE; 177 sbp->f_iosize = DEV_BSIZE; 178 sbp->f_blocks = 2; /* 1K to keep df happy */ 179 sbp->f_bfree = 0; 180 sbp->f_bavail = 0; 181 sbp->f_files = lim + 1; /* Allow for "." */ 182 sbp->f_ffree = freefd; /* See comments above */ 183 if (sbp != &mp->mnt_stat) { 184 sbp->f_type = mp->mnt_vfc->vfc_typenum; 185 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 186 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 187 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 188 } 189 return (0); 190 } 191 192 int 193 fdesc_sync(mp, waitfor) 194 struct mount *mp; 195 int waitfor; 196 { 197 198 return (0); 199 } 200 201 #define fdesc_fhtovp ((int (*) __P((struct mount *, struct fid *, \ 202 struct mbuf *, struct vnode **, int *, struct ucred **)))eopnotsupp) 203 #define fdesc_quotactl ((int (*) __P((struct mount *, int, uid_t, caddr_t, \ 204 struct proc *)))eopnotsupp) 205 #define fdesc_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ 206 size_t, struct proc *)))eopnotsupp) 207 #define fdesc_vget ((int (*) __P((struct mount *, ino_t, struct vnode **))) \ 208 eopnotsupp) 209 #define fdesc_vptofh ((int (*) __P((struct vnode *, struct fid *)))eopnotsupp) 210 211 struct vfsops fdesc_vfsops = { 212 fdesc_mount, 213 fdesc_start, 214 fdesc_unmount, 215 fdesc_root, 216 fdesc_quotactl, 217 fdesc_statfs, 218 fdesc_sync, 219 fdesc_vget, 220 fdesc_fhtovp, 221 fdesc_vptofh, 222 fdesc_init, 223 fdesc_sysctl, 224 }; 225