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
fdesc_mount(mp,path,data,ndp,p)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
fdesc_start(mp,flags,p)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
fdesc_unmount(mp,mntflags,p)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
fdesc_root(mp,vpp)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
fdesc_statfs(mp,sbp,p)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
fdesc_sync(mp,waitfor)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