vfs_init.c revision 12577
1139747Simp/*
24Srgrimes * Copyright (c) 1989, 1993
34Srgrimes *	The Regents of the University of California.  All rights reserved.
44Srgrimes *
58876Srgrimes * This code is derived from software contributed
64Srgrimes * to Berkeley by John Heidemann of the UCLA Ficus project.
74Srgrimes *
84Srgrimes * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
94Srgrimes *
104Srgrimes * Redistribution and use in source and binary forms, with or without
118876Srgrimes * modification, are permitted provided that the following conditions
128876Srgrimes * are met:
134Srgrimes * 1. Redistributions of source code must retain the above copyright
144Srgrimes *    notice, this list of conditions and the following disclaimer.
158876Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
164Srgrimes *    notice, this list of conditions and the following disclaimer in the
178876Srgrimes *    documentation and/or other materials provided with the distribution.
184Srgrimes * 3. All advertising materials mentioning features or use of this software
194Srgrimes *    must display the following acknowledgement:
204Srgrimes *	This product includes software developed by the University of
214Srgrimes *	California, Berkeley and its contributors.
228876Srgrimes * 4. Neither the name of the University nor the names of its contributors
234Srgrimes *    may be used to endorse or promote products derived from this software
244Srgrimes *    without specific prior written permission.
254Srgrimes *
264Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
274Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
284Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
294Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
304Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
314Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
324Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
334Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34116176Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35116176Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36116176Sobrien * SUCH DAMAGE.
37116176Sobrien *
382056Swollman *	@(#)vfs_init.c	8.3 (Berkeley) 1/4/94
39131952Smarcel * $Id: vfs_init.c,v 1.15 1995/12/02 17:10:53 bde Exp $
40145053Speter */
4112734Sbde
42131952Smarcel
43131952Smarcel#include <sys/param.h>
44131952Smarcel#include <sys/systm.h>
4512662Sdg#include <sys/kernel.h>
4612734Sbde#include <sys/mount.h>
472056Swollman#include <sys/time.h>
484Srgrimes#include <sys/vnode.h>
494Srgrimes#include <sys/stat.h>
504Srgrimes#include <sys/namei.h>
514Srgrimes#include <sys/ucred.h>
524Srgrimes#include <sys/buf.h>
534Srgrimes#include <sys/errno.h>
544Srgrimes#include <sys/malloc.h>
55272958Spfg#include <sys/proc.h>
564Srgrimes#include <vm/vm.h>
57308418Skib#include <sys/sysctl.h>
584Srgrimes
59308418Skibextern void	vfs_op_init __P((void));
60283248Spfg
6112720Sphkstatic void vfsinit __P((void *));
6212720SphkSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL)
634Srgrimes
644Srgrimesvoid vfs_op_init __P((void));
654Srgrimes
664Srgrimes/*
674Srgrimes * Sigh, such primitive tools are these...
68291407Szbb */
69291407Szbb#if 0
70291407Szbb#define DODEBUG(A) A
71291407Szbb#else
72291407Szbb#define DODEBUG(A)
734Srgrimes#endif
74131952Smarcel
754Srgrimesstruct vfsconf void_vfsconf;
764Srgrimes
77131952Smarcelextern struct linker_set vfs_opv_descs_;
784Srgrimes#define vfs_opv_descs ((struct vnodeopv_desc **)vfs_opv_descs_.ls_items)
79291407Szbb
80291407Szbbextern struct linker_set vfs_set;
81291407Szbbstruct vfsops *vfssw[MOUNT_MAXTYPE + 1];
82291407Szbbstruct vfsconf *vfsconf[MOUNT_MAXTYPE + 1];
83137974Scognet
84291407Szbbextern struct vnodeop_desc *vfs_op_descs[];
85291407Szbb				/* and the operations they perform */
86291407Szbb/*
87137974Scognet * This code doesn't work if the defn is **vnodop_defns with cc.
88291407Szbb * The problem is because of the compiler sometimes putting in an
89291407Szbb * extra level of indirection for arrays.  It's an interesting
90291407Szbb * "feature" of C.
91137974Scognet */
92283248Spfgint vfs_opv_numops;
93308418Skib
944Srgrimes/*
95283315Spfg * A miscellaneous routine.
96283315Spfg * A generic "default" routine that just returns an error.
974Srgrimes */
98308418Skibint
99308418Skibvn_default_error()
100137974Scognet{
101291407Szbb
102283088Spfg	return (EOPNOTSUPP);
103137974Scognet}
104131952Smarcel
1054Srgrimes/*
1064Srgrimes * vfs_init.c
1074Srgrimes *
1084Srgrimes * Allocate and fill in operations vectors.
1094Srgrimes *
1104Srgrimes * An undocumented feature of this approach to defining operations is that
1114Srgrimes * there can be multiple entries in vfs_opv_descs for the same operations
1124Srgrimes * vector. This allows third parties to extend the set of operations
1134Srgrimes * supported by another layer in a binary compatibile way. For example,
1144Srgrimes * assume that NFS needed to be modified to support Ficus. NFS has an entry
115131952Smarcel * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by
1164Srgrimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions)
1174Srgrimes * listing those new operations Ficus adds to NFS, all without modifying the
1184Srgrimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but
1194Srgrimes * that is a(whole)nother story.) This is a feature.
1204Srgrimes */
1214Srgrimesvoid
1224Srgrimesvfs_opv_init(struct vnodeopv_desc **them)
1234Srgrimes{
1244Srgrimes	int i, j, k;
1254Srgrimes	vop_t ***opv_desc_vector_p;
126283088Spfg	vop_t **opv_desc_vector;
127283088Spfg	struct vnodeopv_entry_desc *opve_descp;
1284Srgrimes
129308418Skib	/*
1304Srgrimes	 * Allocate the dynamic vectors and fill them in.
13183506Sdfr	 */
13283506Sdfr	for (i=0; them[i]; i++) {
13336735Sdfr		opv_desc_vector_p = them[i]->opv_desc_vector_p;
1344Srgrimes		/*
1358876Srgrimes		 * Allocate and init the vector, if it needs it.
136308418Skib		 * Also handle backwards compatibility.
1374Srgrimes		 */
138308418Skib		if (*opv_desc_vector_p == NULL) {
139308418Skib			/* XXX - shouldn't be M_VNODE */
140308418Skib			MALLOC(*opv_desc_vector_p, vop_t **,
141308418Skib			       vfs_opv_numops * sizeof(vop_t *), M_VNODE,
142308418Skib			       M_WAITOK);
143308418Skib			bzero(*opv_desc_vector_p,
144308418Skib			      vfs_opv_numops * sizeof(vop_t *));
145308418Skib			DODEBUG(printf("vector at %x allocated\n",
146308418Skib			    opv_desc_vector_p));
147308418Skib		}
148308418Skib		opv_desc_vector = *opv_desc_vector_p;
149308418Skib		for (j=0; them[i]->opv_desc_ops[j].opve_op; j++) {
150308418Skib			opve_descp = &(them[i]->opv_desc_ops[j]);
151308418Skib
152308418Skib			/*
153308418Skib			 * Sanity check:  is this operation listed
154308418Skib			 * in the list of operations?  We check this
155308418Skib			 * by seeing if its offest is zero.  Since
156308418Skib			 * the default routine should always be listed
157308418Skib			 * first, it should be the only one with a zero
158308418Skib			 * offset.  Any other operation with a zero
159308418Skib			 * offset is probably not listed in
160308418Skib			 * vfs_op_descs, and so is probably an error.
161308418Skib			 *
162308418Skib			 * A panic here means the layer programmer
1634Srgrimes			 * has committed the all-too common bug
1644Srgrimes			 * of adding a new operation to the layer's
165283088Spfg			 * list of vnode operations but
1664Srgrimes			 * not adding the operation to the system-wide
1674Srgrimes			 * list of supported operations.
168283088Spfg			 */
1694Srgrimes			if (opve_descp->opve_op->vdesc_offset == 0 &&
1704Srgrimes				    opve_descp->opve_op->vdesc_offset !=
1714Srgrimes				    	VOFFSET(vop_default)) {
1724Srgrimes				printf("operation %s not listed in %s.\n",
1734Srgrimes				    opve_descp->opve_op->vdesc_name,
1744Srgrimes				    "vfs_op_descs");
1754Srgrimes				panic ("vfs_opv_init: bad operation");
1764Srgrimes			}
177283088Spfg			/*
1784Srgrimes			 * Fill in this entry.
1794Srgrimes			 */
1804Srgrimes			opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
1814Srgrimes					opve_descp->opve_impl;
18298694Smux		}
1834Srgrimes	}
184283088Spfg	/*
1854Srgrimes	 * Finally, go back and replace unfilled routines
1864Srgrimes	 * with their default.  (Sigh, an O(n^3) algorithm.  I
1874Srgrimes	 * could make it better, but that'd be work, and n is small.)
1884Srgrimes	 */
189283315Spfg	for (i = 0; them[i]; i++) {
1904Srgrimes		opv_desc_vector = *(them[i]->opv_desc_vector_p);
1914Srgrimes		/*
1924Srgrimes		 * Force every operations vector to have a default routine.
1934Srgrimes		 */
1944Srgrimes		if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
1954Srgrimes			panic("vfs_opv_init: operation vector without default routine.");
1964Srgrimes		}
1974Srgrimes		for (k = 0; k<vfs_opv_numops; k++)
1984Srgrimes			if (opv_desc_vector[k] == NULL)
1994Srgrimes				opv_desc_vector[k] =
200283088Spfg					opv_desc_vector[VOFFSET(vop_default)];
2014Srgrimes	}
2024Srgrimes}
2034Srgrimes
2044Srgrimes/*
20598694Smux * Initialize known vnode operations vectors.
2064Srgrimes */
207283088Spfgvoid
2084Srgrimesvfs_op_init()
2094Srgrimes{
2104Srgrimes	int i;
211283088Spfg
2124Srgrimes	DODEBUG(printf("Vnode_interface_init.\n"));
2134Srgrimes	/*
214283088Spfg	 * Set all vnode vectors to a well known value.
2154Srgrimes	 */
2164Srgrimes	for (i = 0; vfs_opv_descs[i]; i++)
2174Srgrimes		*(vfs_opv_descs[i]->opv_desc_vector_p) = NULL;
218283248Spfg	/*
2194Srgrimes	 * Figure out how many ops there are by counting the table,
220283315Spfg	 * and assign each its offset.
2214Srgrimes	 */
2224Srgrimes	for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) {
223308418Skib		vfs_op_descs[i]->vdesc_offset = vfs_opv_numops;
2244Srgrimes		vfs_opv_numops++;
2254Srgrimes	}
2264Srgrimes	DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops));
2274Srgrimes}
2284Srgrimes
2294Srgrimes/*
230269982Simp * Routines having to do with the management of the vnode table.
231269982Simp */
232269982Simpextern struct vnodeops dead_vnodeops;
233283088Spfgextern struct vnodeops spec_vnodeops;
2344Srgrimesstruct vattr va_null;
2354Srgrimes
2364Srgrimes/*
2374Srgrimes * Initialize the vnode structures and initialize each file system type.
2384Srgrimes */
2394Srgrimes/* ARGSUSED*/
2404Srgrimesstatic void
241283088Spfgvfsinit(dummy)
2424Srgrimes	void *dummy;
2434Srgrimes{
2444Srgrimes	struct vfsops **vfsp;
2454Srgrimes	struct vfsconf **vfc;
24681670Sobrien	int i;
2474Srgrimes
2484Srgrimes	/*
2494Srgrimes	 * Initialize the VFS switch table
2504Srgrimes	 */
2514Srgrimes	for(i = 0; i < MOUNT_MAXTYPE + 1; i++) {
2524Srgrimes		vfsconf[i] = &void_vfsconf;
2534Srgrimes	}
2544Srgrimes
255131952Smarcel	vfc = (struct vfsconf **)vfs_set.ls_items;
2564Srgrimes	while(*vfc) {
2574Srgrimes		vfssw[(**vfc).vfc_index] = (**vfc).vfc_vfsops;
2584Srgrimes		vfsconf[(**vfc).vfc_index] = *vfc;
2594Srgrimes		vfc++;
2604Srgrimes	}
261131952Smarcel
2624Srgrimes	/*
2634Srgrimes	 * Initialize the vnode table
2644Srgrimes	 */
2654Srgrimes	vntblinit();
2664Srgrimes	/*
2674Srgrimes	 * Initialize the vnode name cache
2684Srgrimes	 */
2694Srgrimes	nchinit();
2704Srgrimes	/*
2714Srgrimes	 * Build vnode operation vectors.
2724Srgrimes	 */
2734Srgrimes	vfs_op_init();
274283248Spfg	vfs_opv_init(vfs_opv_descs);   /* finish the job */
2754Srgrimes	/*
2764Srgrimes	 * Initialize each file system type.
2774Srgrimes	 */
2784Srgrimes	vattr_null(&va_null);
2794Srgrimes	for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) {
2804Srgrimes		if (*vfsp == NULL)
2814Srgrimes			continue;
2828876Srgrimes		(*(*vfsp)->vfs_init)();
2834Srgrimes	}
2844Srgrimes}
2854Srgrimes
2864Srgrimes/*
2874Srgrimes * kernel related system variables.
2884Srgrimes */
2894Srgrimes
2904Srgrimesstatic int
2914Srgrimessysctl_fs_vfsconf SYSCTL_HANDLER_ARGS
2924Srgrimes{
2934Srgrimes	int i, error;
2948876Srgrimes
2954Srgrimes	if (req->newptr)
2964Srgrimes		return EINVAL;
297131952Smarcel	for(i = 0; i < MOUNT_MAXTYPE + 1; i++) {
2984Srgrimes		error = SYSCTL_OUT(req, vfsconf[i], sizeof *vfsconf[i]);
299131952Smarcel		if(error)
300131952Smarcel			return error;
3014Srgrimes	}
3024Srgrimes	return (error);
3034Srgrimes
3044Srgrimes}
3054Srgrimes
306283088SpfgSYSCTL_PROC(_fs, FS_VFSCONF, vfsconf, CTLTYPE_OPAQUE|CTLFLAG_RD,
307181175Scognet	0, 0, sysctl_fs_vfsconf, "");
308131952Smarcel
309131952Smarcel/*
310131952Smarcel * This goop is here to support a loadable NFS module... grumble...
311131952Smarcel */
312131952Smarcelvoid (*lease_check) __P((struct vnode *, struct proc *, struct ucred *, int))
3134Srgrimes     = 0;
314131952Smarcelvoid (*lease_updatetime) __P((int))
3154Srgrimes     = 0;
3164Srgrimes
3174Srgrimes