]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/fdescfs/fdesc_vfsops.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / sys / fs / fdescfs / fdesc_vfsops.c
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  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      @(#)fdesc_vfsops.c      8.4 (Berkeley) 1/21/94
33  *
34  * $FreeBSD$
35  */
36
37 /*
38  * /dev/fd Filesystem
39  */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/filedesc.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/malloc.h>
48 #include <sys/mount.h>
49 #include <sys/proc.h>
50 #include <sys/resourcevar.h>
51 #include <sys/vnode.h>
52
53 #include <fs/fdescfs/fdesc.h>
54
55 static MALLOC_DEFINE(M_FDESCMNT, "FDESC mount", "FDESC mount structure");
56
57 static vfs_mount_t      fdesc_mount;
58 static vfs_unmount_t    fdesc_unmount;
59 static vfs_statfs_t     fdesc_statfs;
60 static vfs_root_t       fdesc_root;
61
62 /*
63  * Mount the per-process file descriptors (/dev/fd)
64  */
65 static int
66 fdesc_mount(struct mount *mp, struct thread *td)
67 {
68         int error = 0;
69         struct fdescmount *fmp;
70         struct vnode *rvp;
71
72         /*
73          * Update is a no-op
74          */
75         if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
76                 return (EOPNOTSUPP);
77
78         error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp, td);
79         if (error)
80                 return (error);
81
82         MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount),
83                                 M_FDESCMNT, M_WAITOK);  /* XXX */
84         rvp->v_type = VDIR;
85         rvp->v_vflag |= VV_ROOT;
86         fmp->f_root = rvp;
87         /* XXX -- don't mark as local to work around fts() problems */
88         /*mp->mnt_flag |= MNT_LOCAL;*/
89         mp->mnt_data = (qaddr_t) fmp;
90         vfs_getnewfsid(mp);
91
92         vfs_mountedfrom(mp, "fdescfs");
93         return (0);
94 }
95
96 static int
97 fdesc_unmount(mp, mntflags, td)
98         struct mount *mp;
99         int mntflags;
100         struct thread *td;
101 {
102         int error;
103         int flags = 0;
104
105         if (mntflags & MNT_FORCE)
106                 flags |= FORCECLOSE;
107
108         /*
109          * Clear out buffer cache.  I don't think we
110          * ever get anything cached at this level at the
111          * moment, but who knows...
112          *
113          * There is 1 extra root vnode reference corresponding
114          * to f_root.
115          */
116         if ((error = vflush(mp, 1, flags, td)) != 0)
117                 return (error);
118
119         /*
120          * Finally, throw away the fdescmount structure
121          */
122         free(mp->mnt_data, M_FDESCMNT); /* XXX */
123         mp->mnt_data = 0;
124
125         return (0);
126 }
127
128 static int
129 fdesc_root(mp, flags, vpp, td)
130         struct mount *mp;
131         int flags;
132         struct vnode **vpp;
133         struct thread *td;
134 {
135         struct vnode *vp;
136
137         /*
138          * Return locked reference to root.
139          */
140         vp = VFSTOFDESC(mp)->f_root;
141         VREF(vp);
142         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
143         *vpp = vp;
144         return (0);
145 }
146
147 static int
148 fdesc_statfs(mp, sbp, td)
149         struct mount *mp;
150         struct statfs *sbp;
151         struct thread *td;
152 {
153         struct filedesc *fdp;
154         int lim;
155         int i;
156         int last;
157         int freefd;
158
159         /*
160          * Compute number of free file descriptors.
161          * [ Strange results will ensue if the open file
162          * limit is ever reduced below the current number
163          * of open files... ]
164          */
165         PROC_LOCK(td->td_proc);
166         lim = lim_cur(td->td_proc, RLIMIT_NOFILE);
167         PROC_UNLOCK(td->td_proc);
168         fdp = td->td_proc->p_fd;
169         FILEDESC_LOCK_FAST(fdp);
170         last = min(fdp->fd_nfiles, lim);
171         freefd = 0;
172         for (i = fdp->fd_freefile; i < last; i++)
173                 if (fdp->fd_ofiles[i] == NULL)
174                         freefd++;
175
176         /*
177          * Adjust for the fact that the fdesc array may not
178          * have been fully allocated yet.
179          */
180         if (fdp->fd_nfiles < lim)
181                 freefd += (lim - fdp->fd_nfiles);
182         FILEDESC_UNLOCK_FAST(fdp);
183
184         sbp->f_flags = 0;
185         sbp->f_bsize = DEV_BSIZE;
186         sbp->f_iosize = DEV_BSIZE;
187         sbp->f_blocks = 2;              /* 1K to keep df happy */
188         sbp->f_bfree = 0;
189         sbp->f_bavail = 0;
190         sbp->f_files = lim + 1;         /* Allow for "." */
191         sbp->f_ffree = freefd;          /* See comments above */
192         return (0);
193 }
194
195 static struct vfsops fdesc_vfsops = {
196         .vfs_init =             fdesc_init,
197         .vfs_mount =            fdesc_mount,
198         .vfs_root =             fdesc_root,
199         .vfs_statfs =           fdesc_statfs,
200         .vfs_unmount =          fdesc_unmount,
201 };
202
203 VFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC);