kernfs_vfsops.c revision 1.1.1.2 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 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)kernfs_vfsops.c 8.10 (Berkeley) 5/14/95
37 */
38
39 /*
40 * Kernel params Filesystem
41 */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/conf.h>
46 #include <sys/types.h>
47 #include <sys/proc.h>
48 #include <sys/vnode.h>
49 #include <sys/mount.h>
50 #include <sys/namei.h>
51 #include <sys/malloc.h>
52
53 #include <miscfs/specfs/specdev.h>
54 #include <miscfs/kernfs/kernfs.h>
55
56 dev_t rrootdev = NODEV;
57
58 kernfs_init(vfsp)
59 struct vfsconf *vfsp;
60 {
61
62 return (0);
63 }
64
65 void
66 kernfs_get_rrootdev()
67 {
68 static int tried = 0;
69 int cmaj;
70
71 if (tried) {
72 /* Already did it once. */
73 return;
74 }
75 tried = 1;
76
77 if (rootdev == NODEV)
78 return;
79 for (cmaj = 0; cmaj < nchrdev; cmaj++) {
80 rrootdev = makedev(cmaj, minor(rootdev));
81 if (chrtoblk(rrootdev) == rootdev)
82 return;
83 }
84 rrootdev = NODEV;
85 printf("kernfs_get_rrootdev: no raw root device\n");
86 }
87
88 /*
89 * Mount the Kernel params filesystem
90 */
91 kernfs_mount(mp, path, data, ndp, p)
92 struct mount *mp;
93 char *path;
94 caddr_t data;
95 struct nameidata *ndp;
96 struct proc *p;
97 {
98 int error = 0;
99 u_int size;
100 struct kernfs_mount *fmp;
101 struct vnode *rvp;
102
103 #ifdef KERNFS_DIAGNOSTIC
104 printf("kernfs_mount(mp = %x)\n", mp);
105 #endif
106
107 /*
108 * Update is a no-op
109 */
110 if (mp->mnt_flag & MNT_UPDATE)
111 return (EOPNOTSUPP);
112
113 error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp); /* XXX */
114 if (error)
115 return (error);
116
117 MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
118 M_UFSMNT, M_WAITOK); /* XXX */
119 rvp->v_type = VDIR;
120 rvp->v_flag |= VROOT;
121 #ifdef KERNFS_DIAGNOSTIC
122 printf("kernfs_mount: root vp = %x\n", rvp);
123 #endif
124 fmp->kf_root = rvp;
125 mp->mnt_flag |= MNT_LOCAL;
126 mp->mnt_data = (qaddr_t) fmp;
127 vfs_getnewfsid(mp);
128
129 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
130 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
131 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
132 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
133 #ifdef KERNFS_DIAGNOSTIC
134 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
135 #endif
136
137 kernfs_get_rrootdev();
138 return (0);
139 }
140
141 kernfs_start(mp, flags, p)
142 struct mount *mp;
143 int flags;
144 struct proc *p;
145 {
146 return (0);
147 }
148
149 kernfs_unmount(mp, mntflags, p)
150 struct mount *mp;
151 int mntflags;
152 struct proc *p;
153 {
154 int error;
155 int flags = 0;
156 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
157
158 #ifdef KERNFS_DIAGNOSTIC
159 printf("kernfs_unmount(mp = %x)\n", mp);
160 #endif
161
162 if (mntflags & MNT_FORCE)
163 flags |= FORCECLOSE;
164
165 /*
166 * Clear out buffer cache. I don't think we
167 * ever get anything cached at this level at the
168 * moment, but who knows...
169 */
170 if (rootvp->v_usecount > 1)
171 return (EBUSY);
172 #ifdef KERNFS_DIAGNOSTIC
173 printf("kernfs_unmount: calling vflush\n");
174 #endif
175 if (error = vflush(mp, rootvp, flags))
176 return (error);
177
178 #ifdef KERNFS_DIAGNOSTIC
179 vprint("kernfs root", rootvp);
180 #endif
181 /*
182 * Release reference on underlying root vnode
183 */
184 vrele(rootvp);
185 /*
186 * And blow it away for future re-use
187 */
188 vgone(rootvp);
189 /*
190 * Finally, throw away the kernfs_mount structure
191 */
192 free(mp->mnt_data, M_UFSMNT); /* XXX */
193 mp->mnt_data = 0;
194 return 0;
195 }
196
197 kernfs_root(mp, vpp)
198 struct mount *mp;
199 struct vnode **vpp;
200 {
201 struct proc *p = curproc; /* XXX */
202 struct vnode *vp;
203
204 #ifdef KERNFS_DIAGNOSTIC
205 printf("kernfs_root(mp = %x)\n", mp);
206 #endif
207
208 /*
209 * Return locked reference to root.
210 */
211 vp = VFSTOKERNFS(mp)->kf_root;
212 VREF(vp);
213 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
214 *vpp = vp;
215 return (0);
216 }
217
218 kernfs_statfs(mp, sbp, p)
219 struct mount *mp;
220 struct statfs *sbp;
221 struct proc *p;
222 {
223 #ifdef KERNFS_DIAGNOSTIC
224 printf("kernfs_statfs(mp = %x)\n", mp);
225 #endif
226
227 sbp->f_flags = 0;
228 sbp->f_bsize = DEV_BSIZE;
229 sbp->f_iosize = DEV_BSIZE;
230 sbp->f_blocks = 2; /* 1K to keep df happy */
231 sbp->f_bfree = 0;
232 sbp->f_bavail = 0;
233 sbp->f_files = 0;
234 sbp->f_ffree = 0;
235 if (sbp != &mp->mnt_stat) {
236 sbp->f_type = mp->mnt_vfc->vfc_typenum;
237 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
238 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
239 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
240 }
241 return (0);
242 }
243
244 struct vfsops kernfs_vfsops = {
245 kernfs_mount,
246 kernfs_start,
247 kernfs_unmount,
248 kernfs_root,
249 kernfs_quotactl,
250 kernfs_statfs,
251 kernfs_sync,
252 kernfs_vget,
253 kernfs_fhtovp,
254 kernfs_vptofh,
255 kernfs_init,
256 kernfs_sysctl,
257 };
258