coda_vfsops.c revision 1.1.1.1 1 1.1 rvb /*
2 1.1 rvb
3 1.1 rvb Coda: an Experimental Distributed File System
4 1.1 rvb Release 3.1
5 1.1 rvb
6 1.1 rvb Copyright (c) 1987-1998 Carnegie Mellon University
7 1.1 rvb All Rights Reserved
8 1.1 rvb
9 1.1 rvb Permission to use, copy, modify and distribute this software and its
10 1.1 rvb documentation is hereby granted, provided that both the copyright
11 1.1 rvb notice and this permission notice appear in all copies of the
12 1.1 rvb software, derivative works or modified versions, and any portions
13 1.1 rvb thereof, and that both notices appear in supporting documentation, and
14 1.1 rvb that credit is given to Carnegie Mellon University in all documents
15 1.1 rvb and publicity pertaining to direct or indirect use of this code or its
16 1.1 rvb derivatives.
17 1.1 rvb
18 1.1 rvb CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
19 1.1 rvb SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
20 1.1 rvb FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
21 1.1 rvb DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
22 1.1 rvb RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
23 1.1 rvb ANY DERIVATIVE WORK.
24 1.1 rvb
25 1.1 rvb Carnegie Mellon encourages users of this software to return any
26 1.1 rvb improvements or extensions that they make, and to grant Carnegie
27 1.1 rvb Mellon the rights to redistribute these changes without encumbrance.
28 1.1 rvb */
29 1.1 rvb
30 1.1 rvb /* $Header: /tank/opengrok/rsync2/NetBSD/src/sys/coda/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:26:45 rvb Exp $ */
31 1.1 rvb
32 1.1 rvb /*
33 1.1 rvb * Mach Operating System
34 1.1 rvb * Copyright (c) 1989 Carnegie-Mellon University
35 1.1 rvb * All rights reserved. The CMU software License Agreement specifies
36 1.1 rvb * the terms and conditions for use and redistribution.
37 1.1 rvb */
38 1.1 rvb
39 1.1 rvb /*
40 1.1 rvb * This code was written for the Coda file system at Carnegie Mellon
41 1.1 rvb * University. Contributers include David Steere, James Kistler, and
42 1.1 rvb * M. Satyanarayanan.
43 1.1 rvb */
44 1.1 rvb
45 1.1 rvb /*
46 1.1 rvb * HISTORY
47 1.1 rvb * $Log: coda_vfsops.c,v $
48 1.1 rvb * Revision 1.1.1.1 1998/08/29 21:26:45 rvb
49 1.1 rvb * Very Preliminary Coda
50 1.1 rvb *
51 1.1 rvb * Revision 1.11 1998/08/28 18:12:22 rvb
52 1.1 rvb * Now it also works on FreeBSD -current. This code will be
53 1.1 rvb * committed to the FreeBSD -current and NetBSD -current
54 1.1 rvb * trees. It will then be tailored to the particular platform
55 1.1 rvb * by flushing conditional code.
56 1.1 rvb *
57 1.1 rvb * Revision 1.10 1998/08/18 17:05:19 rvb
58 1.1 rvb * Don't use __RCSID now
59 1.1 rvb *
60 1.1 rvb * Revision 1.9 1998/08/18 16:31:44 rvb
61 1.1 rvb * Sync the code for NetBSD -current; test on 1.3 later
62 1.1 rvb *
63 1.1 rvb * Revision 1.8 98/02/24 22:22:48 rvb
64 1.1 rvb * Fixes up mainly to flush iopen and friends
65 1.1 rvb *
66 1.1 rvb * Revision 1.7 98/01/23 11:53:45 rvb
67 1.1 rvb * Bring RVB_CFS1_1 to HEAD
68 1.1 rvb *
69 1.1 rvb * Revision 1.6.2.6 98/01/23 11:21:07 rvb
70 1.1 rvb * Sync with 2.2.5
71 1.1 rvb *
72 1.1 rvb * Revision 1.6.2.5 98/01/22 13:05:33 rvb
73 1.1 rvb * Move makecfsnode ctlfid later so vfsp is known
74 1.1 rvb *
75 1.1 rvb * Revision 1.6.2.4 97/12/19 14:26:05 rvb
76 1.1 rvb * session id
77 1.1 rvb *
78 1.1 rvb * Revision 1.6.2.3 97/12/16 12:40:11 rvb
79 1.1 rvb * Sync with 1.3
80 1.1 rvb *
81 1.1 rvb * Revision 1.6.2.2 97/12/10 11:40:25 rvb
82 1.1 rvb * No more ody
83 1.1 rvb *
84 1.1 rvb * Revision 1.6.2.1 97/12/06 17:41:24 rvb
85 1.1 rvb * Sync with peters coda.h
86 1.1 rvb *
87 1.1 rvb * Revision 1.6 97/12/05 10:39:21 rvb
88 1.1 rvb * Read CHANGES
89 1.1 rvb *
90 1.1 rvb * Revision 1.5.14.8 97/11/24 15:44:46 rvb
91 1.1 rvb * Final cfs_venus.c w/o macros, but one locking bug
92 1.1 rvb *
93 1.1 rvb * Revision 1.5.14.7 97/11/21 13:22:03 rvb
94 1.1 rvb * Catch a few cfscalls in cfs_vfsops.c
95 1.1 rvb *
96 1.1 rvb * Revision 1.5.14.6 97/11/20 11:46:48 rvb
97 1.1 rvb * Capture current cfs_venus
98 1.1 rvb *
99 1.1 rvb * Revision 1.5.14.5 97/11/18 10:27:17 rvb
100 1.1 rvb * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
101 1.1 rvb * cfs_nb_foo and cfs_foo are joined
102 1.1 rvb *
103 1.1 rvb * Revision 1.5.14.4 97/11/13 22:03:01 rvb
104 1.1 rvb * pass2 cfs_NetBSD.h mt
105 1.1 rvb *
106 1.1 rvb * Revision 1.5.14.3 97/11/12 12:09:40 rvb
107 1.1 rvb * reorg pass1
108 1.1 rvb *
109 1.1 rvb * Revision 1.5.14.2 97/10/29 16:06:28 rvb
110 1.1 rvb * Kill DYING
111 1.1 rvb *
112 1.1 rvb * Revision 1.5.14.1 1997/10/28 23:10:17 rvb
113 1.1 rvb * >64Meg; venus can be killed!
114 1.1 rvb *
115 1.1 rvb * Revision 1.5 1997/01/13 17:11:07 bnoble
116 1.1 rvb * Coda statfs needs to return something other than -1 for blocks avail. and
117 1.1 rvb * files available for wabi (and other windowsish) programs to install
118 1.1 rvb * there correctly.
119 1.1 rvb *
120 1.1 rvb * Revision 1.4 1996/12/12 22:11:00 bnoble
121 1.1 rvb * Fixed the "downcall invokes venus operation" deadlock in all known cases.
122 1.1 rvb * There may be more
123 1.1 rvb *
124 1.1 rvb * Revision 1.3 1996/11/08 18:06:12 bnoble
125 1.1 rvb * Minor changes in vnode operation signature, VOP_UPDATE signature, and
126 1.1 rvb * some newly defined bits in the include files.
127 1.1 rvb *
128 1.1 rvb * Revision 1.2 1996/01/02 16:57:04 bnoble
129 1.1 rvb * Added support for Coda MiniCache and raw inode calls (final commit)
130 1.1 rvb *
131 1.1 rvb * Revision 1.1.2.1 1995/12/20 01:57:32 bnoble
132 1.1 rvb * Added CFS-specific files
133 1.1 rvb *
134 1.1 rvb * Revision 3.1.1.1 1995/03/04 19:08:02 bnoble
135 1.1 rvb * Branch for NetBSD port revisions
136 1.1 rvb *
137 1.1 rvb * Revision 3.1 1995/03/04 19:08:01 bnoble
138 1.1 rvb * Bump to major revision 3 to prepare for NetBSD port
139 1.1 rvb *
140 1.1 rvb * Revision 2.4 1995/02/17 16:25:22 dcs
141 1.1 rvb * These versions represent several changes:
142 1.1 rvb * 1. Allow venus to restart even if outstanding references exist.
143 1.1 rvb * 2. Have only one ctlvp per client, as opposed to one per mounted cfs device.d
144 1.1 rvb * 3. Allow ody_expand to return many members, not just one.
145 1.1 rvb *
146 1.1 rvb * Revision 2.3 94/10/14 09:58:21 dcs
147 1.1 rvb * Made changes 'cause sun4s have braindead compilers
148 1.1 rvb *
149 1.1 rvb * Revision 2.2 94/10/12 16:46:33 dcs
150 1.1 rvb * Cleaned kernel/venus interface by removing XDR junk, plus
151 1.1 rvb * so cleanup to allow this code to be more easily ported.
152 1.1 rvb *
153 1.1 rvb * Revision 1.3 93/05/28 16:24:29 bnoble
154 1.1 rvb * *** empty log message ***
155 1.1 rvb *
156 1.1 rvb * Revision 1.2 92/10/27 17:58:24 lily
157 1.1 rvb * merge kernel/latest and alpha/src/cfs
158 1.1 rvb *
159 1.1 rvb * Revision 2.3 92/09/30 14:16:32 mja
160 1.1 rvb * Added call to cfs_flush to cfs_unmount.
161 1.1 rvb * [90/12/15 dcs]
162 1.1 rvb *
163 1.1 rvb * Added contributors blurb.
164 1.1 rvb * [90/12/13 jjk]
165 1.1 rvb *
166 1.1 rvb * Revision 2.2 90/07/05 11:26:40 mrt
167 1.1 rvb * Created for the Coda File System.
168 1.1 rvb * [90/05/23 dcs]
169 1.1 rvb *
170 1.1 rvb * Revision 1.3 90/05/31 17:01:42 dcs
171 1.1 rvb * Prepare for merge with facilities kernel.
172 1.1 rvb *
173 1.1 rvb *
174 1.1 rvb */
175 1.1 rvb #include <vcfs.h>
176 1.1 rvb
177 1.1 rvb #include <sys/param.h>
178 1.1 rvb #include <sys/systm.h>
179 1.1 rvb #include <sys/malloc.h>
180 1.1 rvb #include <sys/conf.h>
181 1.1 rvb #include <sys/namei.h>
182 1.1 rvb #include <sys/mount.h>
183 1.1 rvb #include <sys/proc.h>
184 1.1 rvb #include <sys/select.h>
185 1.1 rvb
186 1.1 rvb #include <cfs/coda.h>
187 1.1 rvb #include <cfs/cnode.h>
188 1.1 rvb #include <cfs/cfs_vfsops.h>
189 1.1 rvb #include <cfs/cfs_venus.h>
190 1.1 rvb #include <cfs/cfs_subr.h>
191 1.1 rvb #include <cfs/coda_opstats.h>
192 1.1 rvb /* for VN_RDEV */
193 1.1 rvb #include <miscfs/specfs/specdev.h>
194 1.1 rvb
195 1.1 rvb #ifdef __FreeBSD__
196 1.1 rvb #ifdef __FreeBSD_version
197 1.1 rvb MALLOC_DEFINE(M_CFS, "CFS storage", "Various Coda Structures");
198 1.1 rvb #endif
199 1.1 rvb #endif
200 1.1 rvb
201 1.1 rvb int cfsdebug = 0;
202 1.1 rvb
203 1.1 rvb int cfs_vfsop_print_entry = 0;
204 1.1 rvb #ifdef __GNUC__
205 1.1 rvb #define ENTRY \
206 1.1 rvb if(cfs_vfsop_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
207 1.1 rvb #else
208 1.1 rvb #define ENTRY
209 1.1 rvb #endif
210 1.1 rvb
211 1.1 rvb
212 1.1 rvb struct vnode *cfs_ctlvp;
213 1.1 rvb struct cfs_mntinfo cfs_mnttbl[NVCFS]; /* indexed by minor device number */
214 1.1 rvb
215 1.1 rvb /* structure to keep statistics of internally generated/satisfied calls */
216 1.1 rvb
217 1.1 rvb struct cfs_op_stats cfs_vfsopstats[CFS_VFSOPS_SIZE];
218 1.1 rvb
219 1.1 rvb #define MARK_ENTRY(op) (cfs_vfsopstats[op].entries++)
220 1.1 rvb #define MARK_INT_SAT(op) (cfs_vfsopstats[op].sat_intrn++)
221 1.1 rvb #define MARK_INT_FAIL(op) (cfs_vfsopstats[op].unsat_intrn++)
222 1.1 rvb #define MRAK_INT_GEN(op) (cfs_vfsopstats[op].gen_intrn++)
223 1.1 rvb
224 1.1 rvb extern int cfsnc_initialized; /* Set if cache has been initialized */
225 1.1 rvb extern int vc_nb_open __P((dev_t, int, int, struct proc *));
226 1.1 rvb #ifdef __NetBSD__
227 1.1 rvb extern struct cdevsw cdevsw[]; /* For sanity check in cfs_mount */
228 1.1 rvb #endif
229 1.1 rvb /* NetBSD interface to statfs */
230 1.1 rvb
231 1.1 rvb #if defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 5)
232 1.1 rvb extern struct vnodeopv_desc cfs_vnodeop_opv_desc;
233 1.1 rvb
234 1.1 rvb struct vnodeopv_desc *cfs_vnodeopv_descs[] = {
235 1.1 rvb &cfs_vnodeop_opv_desc,
236 1.1 rvb NULL,
237 1.1 rvb };
238 1.1 rvb
239 1.1 rvb struct vfsops cfs_vfsops = {
240 1.1 rvb MOUNT_CFS,
241 1.1 rvb cfs_mount,
242 1.1 rvb cfs_start,
243 1.1 rvb cfs_unmount,
244 1.1 rvb cfs_root,
245 1.1 rvb cfs_quotactl,
246 1.1 rvb cfs_nb_statfs,
247 1.1 rvb cfs_sync,
248 1.1 rvb cfs_vget,
249 1.1 rvb (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
250 1.1 rvb int *, struct ucred **))
251 1.1 rvb eopnotsupp,
252 1.1 rvb (int (*) (struct vnode *, struct fid *)) eopnotsupp,
253 1.1 rvb cfs_init,
254 1.1 rvb #if (NetBSD1_3 >= 7)
255 1.1 rvb cfs_sysctl,
256 1.1 rvb #endif
257 1.1 rvb (int (*)(void)) eopnotsupp,
258 1.1 rvb cfs_vnodeopv_descs,
259 1.1 rvb 0
260 1.1 rvb };
261 1.1 rvb #elif defined(__NetBSD__)
262 1.1 rvb struct vfsops cfs_vfsops = {
263 1.1 rvb MOUNT_CFS,
264 1.1 rvb cfs_mount,
265 1.1 rvb cfs_start,
266 1.1 rvb cfs_unmount,
267 1.1 rvb cfs_root,
268 1.1 rvb cfs_quotactl,
269 1.1 rvb cfs_nb_statfs,
270 1.1 rvb cfs_sync,
271 1.1 rvb cfs_vget,
272 1.1 rvb (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
273 1.1 rvb int *, struct ucred **))
274 1.1 rvb eopnotsupp,
275 1.1 rvb (int (*) (struct vnode *, struct fid *)) eopnotsupp,
276 1.1 rvb cfs_init,
277 1.1 rvb #ifdef NetBSD1_3
278 1.1 rvb (int (*)(void)) eopnotsupp,
279 1.1 rvb #endif
280 1.1 rvb 0
281 1.1 rvb };
282 1.1 rvb
283 1.1 rvb #elif defined(__FreeBSD__)
284 1.1 rvb #ifdef __FreeBSD_version
285 1.1 rvb struct vfsops cfs_vfsops = {
286 1.1 rvb cfs_mount,
287 1.1 rvb cfs_start,
288 1.1 rvb cfs_unmount,
289 1.1 rvb cfs_root,
290 1.1 rvb cfs_quotactl,
291 1.1 rvb cfs_nb_statfs,
292 1.1 rvb cfs_sync,
293 1.1 rvb cfs_vget,
294 1.1 rvb (int (*) (struct mount *, struct fid *, struct sockaddr *, struct vnode **,
295 1.1 rvb int *, struct ucred **))
296 1.1 rvb eopnotsupp,
297 1.1 rvb (int (*) (struct vnode *, struct fid *)) eopnotsupp,
298 1.1 rvb cfs_init,
299 1.1 rvb };
300 1.1 rvb
301 1.1 rvb #else
302 1.1 rvb struct vfsops cfs_vfsops = {
303 1.1 rvb cfs_mount,
304 1.1 rvb cfs_start,
305 1.1 rvb cfs_unmount,
306 1.1 rvb cfs_root,
307 1.1 rvb cfs_quotactl,
308 1.1 rvb cfs_nb_statfs,
309 1.1 rvb cfs_sync,
310 1.1 rvb cfs_vget,
311 1.1 rvb (int (*) (struct mount *, struct fid *, struct mbuf *, struct vnode **,
312 1.1 rvb int *, struct ucred **))
313 1.1 rvb eopnotsupp,
314 1.1 rvb (int (*) (struct vnode *, struct fid *)) eopnotsupp,
315 1.1 rvb cfs_init,
316 1.1 rvb };
317 1.1 rvb
318 1.1 rvb #endif
319 1.1 rvb
320 1.1 rvb
321 1.1 rvb #include <sys/kernel.h>
322 1.1 rvb VFS_SET(cfs_vfsops, cfs, MOUNT_CFS, VFCF_NETWORK);
323 1.1 rvb #endif
324 1.1 rvb
325 1.1 rvb int
326 1.1 rvb cfs_vfsopstats_init(void)
327 1.1 rvb {
328 1.1 rvb register int i;
329 1.1 rvb
330 1.1 rvb for (i=0;i<CFS_VFSOPS_SIZE;i++) {
331 1.1 rvb cfs_vfsopstats[i].opcode = i;
332 1.1 rvb cfs_vfsopstats[i].entries = 0;
333 1.1 rvb cfs_vfsopstats[i].sat_intrn = 0;
334 1.1 rvb cfs_vfsopstats[i].unsat_intrn = 0;
335 1.1 rvb cfs_vfsopstats[i].gen_intrn = 0;
336 1.1 rvb }
337 1.1 rvb
338 1.1 rvb return 0;
339 1.1 rvb }
340 1.1 rvb
341 1.1 rvb
342 1.1 rvb /*
343 1.1 rvb * cfs mount vfsop
344 1.1 rvb * Set up mount info record and attach it to vfs struct.
345 1.1 rvb */
346 1.1 rvb /*ARGSUSED*/
347 1.1 rvb int
348 1.1 rvb cfs_mount(vfsp, path, data, ndp, p)
349 1.1 rvb struct mount *vfsp; /* Allocated and initialized by mount(2) */
350 1.1 rvb #ifdef NetBSD1_3
351 1.1 rvb const char *path; /* path covered: ignored by the fs-layer */
352 1.1 rvb void *data; /* Need to define a data type for this in netbsd? */
353 1.1 rvb #else
354 1.1 rvb char *path; /* path covered: ignored by the fs-layer */
355 1.1 rvb caddr_t data; /* Need to define a data type for this in netbsd? */
356 1.1 rvb #endif
357 1.1 rvb struct nameidata *ndp; /* Clobber this to lookup the device name */
358 1.1 rvb struct proc *p; /* The ever-famous proc pointer */
359 1.1 rvb {
360 1.1 rvb struct vnode *dvp;
361 1.1 rvb struct cnode *cp;
362 1.1 rvb dev_t dev;
363 1.1 rvb struct cfs_mntinfo *mi;
364 1.1 rvb struct vnode *rootvp;
365 1.1 rvb ViceFid rootfid;
366 1.1 rvb ViceFid ctlfid;
367 1.1 rvb int error;
368 1.1 rvb
369 1.1 rvb ENTRY;
370 1.1 rvb
371 1.1 rvb cfs_vfsopstats_init();
372 1.1 rvb cfs_vnodeopstats_init();
373 1.1 rvb
374 1.1 rvb MARK_ENTRY(CFS_MOUNT_STATS);
375 1.1 rvb if (CFS_MOUNTED(vfsp)) {
376 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
377 1.1 rvb return(EBUSY);
378 1.1 rvb }
379 1.1 rvb
380 1.1 rvb /* Validate mount device. Similar to getmdev(). */
381 1.1 rvb
382 1.1 rvb NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, data, p);
383 1.1 rvb error = namei(ndp);
384 1.1 rvb dvp = ndp->ni_vp;
385 1.1 rvb
386 1.1 rvb if (error) {
387 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
388 1.1 rvb return (error);
389 1.1 rvb }
390 1.1 rvb if (dvp->v_type != VCHR) {
391 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
392 1.1 rvb vrele(dvp);
393 1.1 rvb return(ENXIO);
394 1.1 rvb }
395 1.1 rvb dev = dvp->v_specinfo->si_rdev;
396 1.1 rvb vrele(dvp);
397 1.1 rvb if (major(dev) >= nchrdev || major(dev) < 0) {
398 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
399 1.1 rvb return(ENXIO);
400 1.1 rvb }
401 1.1 rvb
402 1.1 rvb /*
403 1.1 rvb * See if the device table matches our expectations.
404 1.1 rvb */
405 1.1 rvb #ifdef __NetBSD__
406 1.1 rvb if (cdevsw[major(dev)].d_open != vc_nb_open)
407 1.1 rvb #elif defined(__FreeBSD__)
408 1.1 rvb if (cdevsw[major(dev)]->d_open != vc_nb_open)
409 1.1 rvb #endif
410 1.1 rvb {
411 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
412 1.1 rvb return(ENXIO);
413 1.1 rvb }
414 1.1 rvb
415 1.1 rvb if (minor(dev) >= NVCFS || minor(dev) < 0) {
416 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
417 1.1 rvb return(ENXIO);
418 1.1 rvb }
419 1.1 rvb
420 1.1 rvb /*
421 1.1 rvb * Initialize the mount record and link it to the vfs struct
422 1.1 rvb */
423 1.1 rvb mi = &cfs_mnttbl[minor(dev)];
424 1.1 rvb
425 1.1 rvb if (!VC_OPEN(&mi->mi_vcomm)) {
426 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
427 1.1 rvb return(ENODEV);
428 1.1 rvb }
429 1.1 rvb
430 1.1 rvb /* No initialization (here) of mi_vcomm! */
431 1.1 rvb vfsp->mnt_data = (qaddr_t)mi;
432 1.1 rvb #ifdef __NetBSD__
433 1.1 rvb vfsp->mnt_stat.f_fsid.val[0] = 0;
434 1.1 rvb vfsp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_CFS);
435 1.1 rvb #elif defined(__FreeBSD__) && defined(__FreeBSD_version)
436 1.1 rvb
437 1.1 rvb vfs_getnewfsid (vfsp);
438 1.1 rvb
439 1.1 rvb #elif defined(__FreeBSD__)
440 1.1 rvb /* Seems a bit overkill, since usualy /coda is the only mount point
441 1.1 rvb * for cfs.
442 1.1 rvb */
443 1.1 rvb getnewfsid (vfsp, MOUNT_CFS);
444 1.1 rvb #endif
445 1.1 rvb mi->mi_vfsp = vfsp;
446 1.1 rvb
447 1.1 rvb /*
448 1.1 rvb * Make a root vnode to placate the Vnode interface, but don't
449 1.1 rvb * actually make the CFS_ROOT call to venus until the first call
450 1.1 rvb * to cfs_root in case a server is down while venus is starting.
451 1.1 rvb */
452 1.1 rvb rootfid.Volume = 0;
453 1.1 rvb rootfid.Vnode = 0;
454 1.1 rvb rootfid.Unique = 0;
455 1.1 rvb cp = makecfsnode(&rootfid, vfsp, VDIR);
456 1.1 rvb rootvp = CTOV(cp);
457 1.1 rvb rootvp->v_flag |= VROOT;
458 1.1 rvb
459 1.1 rvb ctlfid.Volume = CTL_VOL;
460 1.1 rvb ctlfid.Vnode = CTL_VNO;
461 1.1 rvb ctlfid.Unique = CTL_UNI;
462 1.1 rvb /* cp = makecfsnode(&ctlfid, vfsp, VCHR);
463 1.1 rvb The above code seems to cause a loop in the cnode links.
464 1.1 rvb I don't totally understand when it happens, it is caught
465 1.1 rvb when closing down the system.
466 1.1 rvb */
467 1.1 rvb cp = makecfsnode(&ctlfid, 0, VCHR);
468 1.1 rvb
469 1.1 rvb cfs_ctlvp = CTOV(cp);
470 1.1 rvb
471 1.1 rvb /* Add vfs and rootvp to chain of vfs hanging off mntinfo */
472 1.1 rvb mi->mi_vfsp = vfsp;
473 1.1 rvb mi->mi_rootvp = rootvp;
474 1.1 rvb
475 1.1 rvb /* set filesystem block size */
476 1.1 rvb vfsp->mnt_stat.f_bsize = 8192; /* XXX -JJK */
477 1.1 rvb #ifdef __FreeBSD__
478 1.1 rvb /* Set f_iosize. XXX -- inamura (at) isl.ntt.co.jp.
479 1.1 rvb For vnode_pager_haspage() references. The value should be obtained
480 1.1 rvb from underlying UFS. */
481 1.1 rvb /* Checked UFS. iosize is set as 8192 */
482 1.1 rvb vfsp->mnt_stat.f_iosize = 8192;
483 1.1 rvb #endif
484 1.1 rvb
485 1.1 rvb /* error is currently guaranteed to be zero, but in case some
486 1.1 rvb code changes... */
487 1.1 rvb CFSDEBUG(1,
488 1.1 rvb myprintf(("cfs_mount returned %d\n",error)););
489 1.1 rvb if (error)
490 1.1 rvb MARK_INT_FAIL(CFS_MOUNT_STATS);
491 1.1 rvb else
492 1.1 rvb MARK_INT_SAT(CFS_MOUNT_STATS);
493 1.1 rvb
494 1.1 rvb return(error);
495 1.1 rvb }
496 1.1 rvb
497 1.1 rvb int
498 1.1 rvb cfs_start(vfsp, flags, p)
499 1.1 rvb struct mount *vfsp;
500 1.1 rvb int flags;
501 1.1 rvb struct proc *p;
502 1.1 rvb {
503 1.1 rvb ENTRY;
504 1.1 rvb return (0);
505 1.1 rvb }
506 1.1 rvb
507 1.1 rvb int
508 1.1 rvb cfs_unmount(vfsp, mntflags, p)
509 1.1 rvb struct mount *vfsp;
510 1.1 rvb int mntflags;
511 1.1 rvb struct proc *p;
512 1.1 rvb {
513 1.1 rvb struct cfs_mntinfo *mi = vftomi(vfsp);
514 1.1 rvb int active, error = 0;
515 1.1 rvb
516 1.1 rvb ENTRY;
517 1.1 rvb MARK_ENTRY(CFS_UMOUNT_STATS);
518 1.1 rvb if (!CFS_MOUNTED(vfsp)) {
519 1.1 rvb MARK_INT_FAIL(CFS_UMOUNT_STATS);
520 1.1 rvb return(EINVAL);
521 1.1 rvb }
522 1.1 rvb
523 1.1 rvb if (mi->mi_vfsp == vfsp) { /* We found the victim */
524 1.1 rvb if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp)))
525 1.1 rvb return (EBUSY); /* Venus is still running */
526 1.1 rvb
527 1.1 rvb #ifdef DEBUG
528 1.1 rvb printf("cfs_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp, VTOC(mi->mi_rootvp));
529 1.1 rvb #endif
530 1.1 rvb vrele(mi->mi_rootvp);
531 1.1 rvb
532 1.1 rvb #ifdef NetBSD1_3
533 1.1 rvb active = cfs_kill(vfsp, NOT_DOWNCALL);
534 1.1 rvb
535 1.1 rvb #if defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 7)
536 1.1 rvb if (1)
537 1.1 rvb #else
538 1.1 rvb if ((error = vfs_busy(mi->mi_vfsp)) == 0)
539 1.1 rvb #endif
540 1.1 rvb {
541 1.1 rvb error = vflush(mi->mi_vfsp, NULLVP, FORCECLOSE);
542 1.1 rvb printf("cfs_unmount: active = %d, vflush active %d\n", active, error);
543 1.1 rvb error = 0;
544 1.1 rvb } else {
545 1.1 rvb printf("cfs_unmount: busy\n");
546 1.1 rvb }
547 1.1 rvb #else /* FreeBSD I guess */
548 1.1 rvb active = cfs_kill(vfsp, NOT_DOWNCALL);
549 1.1 rvb error = vflush(mi->mi_vfsp, NULLVP, FORCECLOSE);
550 1.1 rvb printf("cfs_unmount: active = %d, vflush active %d\n", active, error);
551 1.1 rvb error = 0;
552 1.1 rvb #endif
553 1.1 rvb /* I'm going to take this out to allow lookups to go through. I'm
554 1.1 rvb * not sure it's important anyway. -- DCS 2/2/94
555 1.1 rvb */
556 1.1 rvb /* vfsp->VFS_DATA = NULL; */
557 1.1 rvb
558 1.1 rvb /* No more vfsp's to hold onto */
559 1.1 rvb mi->mi_vfsp = NULL;
560 1.1 rvb mi->mi_rootvp = NULL;
561 1.1 rvb
562 1.1 rvb if (error)
563 1.1 rvb MARK_INT_FAIL(CFS_UMOUNT_STATS);
564 1.1 rvb else
565 1.1 rvb MARK_INT_SAT(CFS_UMOUNT_STATS);
566 1.1 rvb
567 1.1 rvb return(error);
568 1.1 rvb }
569 1.1 rvb return (EINVAL);
570 1.1 rvb }
571 1.1 rvb
572 1.1 rvb /*
573 1.1 rvb * find root of cfs
574 1.1 rvb */
575 1.1 rvb int
576 1.1 rvb cfs_root(vfsp, vpp)
577 1.1 rvb struct mount *vfsp;
578 1.1 rvb struct vnode **vpp;
579 1.1 rvb {
580 1.1 rvb struct cfs_mntinfo *mi = vftomi(vfsp);
581 1.1 rvb struct vnode **result;
582 1.1 rvb int error;
583 1.1 rvb struct proc *p = curproc; /* XXX - bnoble */
584 1.1 rvb ViceFid VFid;
585 1.1 rvb
586 1.1 rvb ENTRY;
587 1.1 rvb MARK_ENTRY(CFS_ROOT_STATS);
588 1.1 rvb result = NULL;
589 1.1 rvb
590 1.1 rvb if (vfsp == mi->mi_vfsp) {
591 1.1 rvb if ((VTOC(mi->mi_rootvp)->c_fid.Volume != 0) ||
592 1.1 rvb (VTOC(mi->mi_rootvp)->c_fid.Vnode != 0) ||
593 1.1 rvb (VTOC(mi->mi_rootvp)->c_fid.Unique != 0))
594 1.1 rvb { /* Found valid root. */
595 1.1 rvb *vpp = mi->mi_rootvp;
596 1.1 rvb /* On Mach, this is vref. On NetBSD, VOP_LOCK */
597 1.1 rvb vref(*vpp);
598 1.1 rvb VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
599 1.1 rvb MARK_INT_SAT(CFS_ROOT_STATS);
600 1.1 rvb return(0);
601 1.1 rvb }
602 1.1 rvb }
603 1.1 rvb
604 1.1 rvb error = venus_root(vftomi(vfsp), p->p_cred->pc_ucred, p, &VFid);
605 1.1 rvb
606 1.1 rvb if (!error) {
607 1.1 rvb /*
608 1.1 rvb * Save the new rootfid in the cnode, and rehash the cnode into the
609 1.1 rvb * cnode hash with the new fid key.
610 1.1 rvb */
611 1.1 rvb cfs_unsave(VTOC(mi->mi_rootvp));
612 1.1 rvb VTOC(mi->mi_rootvp)->c_fid = VFid;
613 1.1 rvb cfs_save(VTOC(mi->mi_rootvp));
614 1.1 rvb
615 1.1 rvb *vpp = mi->mi_rootvp;
616 1.1 rvb vref(*vpp);
617 1.1 rvb VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
618 1.1 rvb MARK_INT_SAT(CFS_ROOT_STATS);
619 1.1 rvb goto exit;
620 1.1 rvb } else if (error == ENODEV) {
621 1.1 rvb /* Gross hack here! */
622 1.1 rvb /*
623 1.1 rvb * If Venus fails to respond to the CFS_ROOT call, cfscall returns
624 1.1 rvb * ENODEV. Return the uninitialized root vnode to allow vfs
625 1.1 rvb * operations such as unmount to continue. Without this hack,
626 1.1 rvb * there is no way to do an unmount if Venus dies before a
627 1.1 rvb * successful CFS_ROOT call is done. All vnode operations
628 1.1 rvb * will fail.
629 1.1 rvb */
630 1.1 rvb *vpp = mi->mi_rootvp;
631 1.1 rvb vref(*vpp);
632 1.1 rvb VOP_X_LOCK(*vpp, LK_EXCLUSIVE);
633 1.1 rvb MARK_INT_FAIL(CFS_ROOT_STATS);
634 1.1 rvb error = 0;
635 1.1 rvb goto exit;
636 1.1 rvb } else {
637 1.1 rvb CFSDEBUG( CFS_ROOT, myprintf(("error %d in CFS_ROOT\n", error)); );
638 1.1 rvb MARK_INT_FAIL(CFS_ROOT_STATS);
639 1.1 rvb
640 1.1 rvb goto exit;
641 1.1 rvb }
642 1.1 rvb exit:
643 1.1 rvb return(error);
644 1.1 rvb }
645 1.1 rvb
646 1.1 rvb int
647 1.1 rvb cfs_quotactl(vfsp, cmd, uid, arg, p)
648 1.1 rvb struct mount *vfsp;
649 1.1 rvb int cmd;
650 1.1 rvb uid_t uid;
651 1.1 rvb caddr_t arg;
652 1.1 rvb struct proc *p;
653 1.1 rvb {
654 1.1 rvb ENTRY;
655 1.1 rvb return (EOPNOTSUPP);
656 1.1 rvb }
657 1.1 rvb
658 1.1 rvb /*
659 1.1 rvb * Get file system statistics.
660 1.1 rvb */
661 1.1 rvb int
662 1.1 rvb cfs_nb_statfs(vfsp, sbp, p)
663 1.1 rvb register struct mount *vfsp;
664 1.1 rvb struct statfs *sbp;
665 1.1 rvb struct proc *p;
666 1.1 rvb {
667 1.1 rvb ENTRY;
668 1.1 rvb /* MARK_ENTRY(CFS_STATFS_STATS); */
669 1.1 rvb if (!CFS_MOUNTED(vfsp)) {
670 1.1 rvb /* MARK_INT_FAIL(CFS_STATFS_STATS);*/
671 1.1 rvb return(EINVAL);
672 1.1 rvb }
673 1.1 rvb
674 1.1 rvb bzero(sbp, sizeof(struct statfs));
675 1.1 rvb /* XXX - what to do about f_flags, others? --bnoble */
676 1.1 rvb /* Below This is what AFS does
677 1.1 rvb #define NB_SFS_SIZ 0x895440
678 1.1 rvb */
679 1.1 rvb /* Note: Normal fs's have a bsize of 0x400 == 1024 */
680 1.1 rvb #ifdef __NetBSD__
681 1.1 rvb sbp->f_type = 0;
682 1.1 rvb #elif defined(__FreeBSD__)
683 1.1 rvb sbp->f_type = MOUNT_CFS;
684 1.1 rvb #endif
685 1.1 rvb sbp->f_bsize = 8192; /* XXX */
686 1.1 rvb sbp->f_iosize = 8192; /* XXX */
687 1.1 rvb #define NB_SFS_SIZ 0x8AB75D
688 1.1 rvb sbp->f_blocks = NB_SFS_SIZ;
689 1.1 rvb sbp->f_bfree = NB_SFS_SIZ;
690 1.1 rvb sbp->f_bavail = NB_SFS_SIZ;
691 1.1 rvb sbp->f_files = NB_SFS_SIZ;
692 1.1 rvb sbp->f_ffree = NB_SFS_SIZ;
693 1.1 rvb bcopy((caddr_t)&(vfsp->mnt_stat.f_fsid), (caddr_t)&(sbp->f_fsid), sizeof (fsid_t));
694 1.1 rvb #ifdef __NetBSD__
695 1.1 rvb strncpy(sbp->f_fstypename, MOUNT_CFS, MFSNAMELEN-1);
696 1.1 rvb #endif
697 1.1 rvb strcpy(sbp->f_mntonname, "/coda");
698 1.1 rvb strcpy(sbp->f_mntfromname, "CFS");
699 1.1 rvb /* MARK_INT_SAT(CFS_STATFS_STATS); */
700 1.1 rvb return(0);
701 1.1 rvb }
702 1.1 rvb
703 1.1 rvb /*
704 1.1 rvb * Flush any pending I/O.
705 1.1 rvb */
706 1.1 rvb int
707 1.1 rvb cfs_sync(vfsp, waitfor, cred, p)
708 1.1 rvb struct mount *vfsp;
709 1.1 rvb int waitfor;
710 1.1 rvb struct ucred *cred;
711 1.1 rvb struct proc *p;
712 1.1 rvb {
713 1.1 rvb ENTRY;
714 1.1 rvb MARK_ENTRY(CFS_SYNC_STATS);
715 1.1 rvb MARK_INT_SAT(CFS_SYNC_STATS);
716 1.1 rvb return(0);
717 1.1 rvb }
718 1.1 rvb
719 1.1 rvb int
720 1.1 rvb cfs_vget(vfsp, ino, vpp)
721 1.1 rvb struct mount *vfsp;
722 1.1 rvb ino_t ino;
723 1.1 rvb struct vnode **vpp;
724 1.1 rvb {
725 1.1 rvb ENTRY;
726 1.1 rvb return (EOPNOTSUPP);
727 1.1 rvb }
728 1.1 rvb
729 1.1 rvb /*
730 1.1 rvb * fhtovp is now what vget used to be in 4.3-derived systems. For
731 1.1 rvb * some silly reason, vget is now keyed by a 32 bit ino_t, rather than
732 1.1 rvb * a type-specific fid.
733 1.1 rvb */
734 1.1 rvb int
735 1.1 rvb cfs_fhtovp(vfsp, fhp, nam, vpp, exflagsp, creadanonp)
736 1.1 rvb register struct mount *vfsp;
737 1.1 rvb struct fid *fhp;
738 1.1 rvb struct mbuf *nam;
739 1.1 rvb struct vnode **vpp;
740 1.1 rvb int *exflagsp;
741 1.1 rvb struct ucred **creadanonp;
742 1.1 rvb {
743 1.1 rvb struct cfid *cfid = (struct cfid *)fhp;
744 1.1 rvb struct cnode *cp = 0;
745 1.1 rvb int error;
746 1.1 rvb struct proc *p = curproc; /* XXX -mach */
747 1.1 rvb ViceFid VFid;
748 1.1 rvb int vtype;
749 1.1 rvb
750 1.1 rvb ENTRY;
751 1.1 rvb
752 1.1 rvb MARK_ENTRY(CFS_VGET_STATS);
753 1.1 rvb /* Check for vget of control object. */
754 1.1 rvb if (IS_CTL_FID(&cfid->cfid_fid)) {
755 1.1 rvb *vpp = cfs_ctlvp;
756 1.1 rvb vref(cfs_ctlvp);
757 1.1 rvb MARK_INT_SAT(CFS_VGET_STATS);
758 1.1 rvb return(0);
759 1.1 rvb }
760 1.1 rvb
761 1.1 rvb error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, p->p_cred->pc_ucred, p, &VFid, &vtype);
762 1.1 rvb
763 1.1 rvb if (error) {
764 1.1 rvb CFSDEBUG(CFS_VGET, myprintf(("vget error %d\n",error));)
765 1.1 rvb *vpp = (struct vnode *)0;
766 1.1 rvb } else {
767 1.1 rvb CFSDEBUG(CFS_VGET,
768 1.1 rvb myprintf(("vget: vol %lx vno %lx uni %lx type %d result %d\n",
769 1.1 rvb VFid.Volume, VFid.Vnode, VFid.Unique, vtype, error)); )
770 1.1 rvb
771 1.1 rvb cp = makecfsnode(&VFid, vfsp, vtype);
772 1.1 rvb *vpp = CTOV(cp);
773 1.1 rvb }
774 1.1 rvb return(error);
775 1.1 rvb }
776 1.1 rvb
777 1.1 rvb int
778 1.1 rvb cfs_vptofh(vnp, fidp)
779 1.1 rvb struct vnode *vnp;
780 1.1 rvb struct fid *fidp;
781 1.1 rvb {
782 1.1 rvb ENTRY;
783 1.1 rvb return (EOPNOTSUPP);
784 1.1 rvb }
785 1.1 rvb
786 1.1 rvb #ifdef __NetBSD__
787 1.1 rvb void
788 1.1 rvb cfs_init(void)
789 1.1 rvb {
790 1.1 rvb ENTRY;
791 1.1 rvb }
792 1.1 rvb #elif defined(__FreeBSD__)
793 1.1 rvb #ifdef __FreeBSD_version
794 1.1 rvb int
795 1.1 rvb cfs_init(struct vfsconf *vfsp)
796 1.1 rvb {
797 1.1 rvb ENTRY;
798 1.1 rvb return 0;
799 1.1 rvb }
800 1.1 rvb #else
801 1.1 rvb int
802 1.1 rvb cfs_init(void)
803 1.1 rvb {
804 1.1 rvb ENTRY;
805 1.1 rvb return 0;
806 1.1 rvb }
807 1.1 rvb #endif
808 1.1 rvb #endif
809 1.1 rvb
810 1.1 rvb #if defined(__NetBSD__) && defined(NetBSD1_3) && (NetBSD1_3 >= 7)
811 1.1 rvb int
812 1.1 rvb cfs_sysctl(name, namelen, oldp, oldlp, newp, newl, p)
813 1.1 rvb int *name;
814 1.1 rvb u_int namelen;
815 1.1 rvb void *oldp;
816 1.1 rvb size_t *oldlp;
817 1.1 rvb void *newp;
818 1.1 rvb size_t newl;
819 1.1 rvb struct proc *p;
820 1.1 rvb {
821 1.1 rvb
822 1.1 rvb /* all sysctl names at this level are terminal */
823 1.1 rvb if (namelen != 1)
824 1.1 rvb return (ENOTDIR); /* overloaded */
825 1.1 rvb
826 1.1 rvb switch (name[0]) {
827 1.1 rvb /*
828 1.1 rvb case FFS_CLUSTERREAD:
829 1.1 rvb return (sysctl_int(oldp, oldlp, newp, newl, &doclusterread));
830 1.1 rvb */
831 1.1 rvb default:
832 1.1 rvb return (EOPNOTSUPP);
833 1.1 rvb }
834 1.1 rvb /* NOTREACHED */
835 1.1 rvb }
836 1.1 rvb #endif
837 1.1 rvb
838 1.1 rvb /*
839 1.1 rvb * To allow for greater ease of use, some vnodes may be orphaned when
840 1.1 rvb * Venus dies. Certain operations should still be allowed to go
841 1.1 rvb * through, but without propagating ophan-ness. So this function will
842 1.1 rvb * get a new vnode for the file from the current run of Venus. */
843 1.1 rvb
844 1.1 rvb int
845 1.1 rvb getNewVnode(vpp)
846 1.1 rvb struct vnode **vpp;
847 1.1 rvb {
848 1.1 rvb struct cfid cfid;
849 1.1 rvb struct cfs_mntinfo *mi = vftomi((*vpp)->v_mount);
850 1.1 rvb
851 1.1 rvb ENTRY;
852 1.1 rvb
853 1.1 rvb cfid.cfid_len = (short)sizeof(ViceFid);
854 1.1 rvb cfid.cfid_fid = VTOC(*vpp)->c_fid; /* Structure assignment. */
855 1.1 rvb /* XXX ? */
856 1.1 rvb
857 1.1 rvb /* We're guessing that if set, the 1st element on the list is a
858 1.1 rvb * valid vnode to use. If not, return ENODEV as venus is dead.
859 1.1 rvb */
860 1.1 rvb if (mi->mi_vfsp == NULL)
861 1.1 rvb return ENODEV;
862 1.1 rvb
863 1.1 rvb return cfs_fhtovp(mi->mi_vfsp, (struct fid*)&cfid, NULL, vpp,
864 1.1 rvb NULL, NULL);
865 1.1 rvb }
866 1.1 rvb
867 1.1 rvb #include <ufs/ufs/quota.h>
868 1.1 rvb #include <ufs/ufs/ufsmount.h>
869 1.1 rvb /* get the mount structure corresponding to a given device. Assume
870 1.1 rvb * device corresponds to a UFS. Return NULL if no device is found.
871 1.1 rvb */
872 1.1 rvb struct mount *devtomp(dev)
873 1.1 rvb dev_t dev;
874 1.1 rvb {
875 1.1 rvb struct mount *mp, *nmp;
876 1.1 rvb
877 1.1 rvb for (mp = mountlist.cqh_first; mp != (void*)&mountlist; mp = nmp) {
878 1.1 rvb nmp = mp->mnt_list.cqe_next;
879 1.1 rvb if (
880 1.1 rvb #ifdef __NetBSD__
881 1.1 rvb (!strcmp(mp->mnt_op->vfs_name, MOUNT_UFS)) &&
882 1.1 rvb #endif
883 1.1 rvb ((VFSTOUFS(mp))->um_dev == (dev_t) dev)) {
884 1.1 rvb /* mount corresponds to UFS and the device matches one we want */
885 1.1 rvb return(mp);
886 1.1 rvb }
887 1.1 rvb }
888 /* mount structure wasn't found */
889 return(NULL);
890 }
891