vfs_mount.c revision 51388
1/* 2 * Copyright (c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1995 Artisoft, Inc. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by the University of 17 * California, Berkeley and its contributors. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)vfs_conf.c 8.8 (Berkeley) 3/31/94 35 * $FreeBSD: head/sys/kern/vfs_mount.c 51388 1999-09-19 06:24:21Z dillon $ 36 */ 37 38/* 39 * PURPOSE: This file abstracts the root mounting interface from 40 * the per file system semantics for handling mounts, 41 * the overall intent of which is to move the BSD 42 * internals dependence out of the FS code, both to 43 * make the FS code more portable and to free up some 44 * of the BSD internals so that they may more easily 45 * be changed. 46 * 47 * NOTE1: Code is single entry/single exit to aid debugging 48 * and conversion for kernel multithreading. 49 * 50 * NOTE2: Code notes lock state in headers on entry and exit 51 * as an aid to conversion for kernel multithreading 52 * on SMP reentrancy 53 */ 54#include "opt_bootp.h" 55 56#include <sys/param.h> /* dev_t (types.h)*/ 57#include <sys/kernel.h> 58#include <sys/systm.h> /* rootvp*/ 59#include <sys/proc.h> /* curproc*/ 60#include <sys/vnode.h> /* NULLVP*/ 61#include <sys/mount.h> /* struct mount*/ 62#include <sys/malloc.h> /* M_MOUNT*/ 63 64/* 65 * GLOBALS 66 */ 67 68MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct"); 69 70/* 71 * These define the root filesystem, device, and root filesystem type. 72 */ 73dev_t rootdevs[] = { NODEV, NODEV }; 74char *rootdevnames[2]; 75struct vnode *rootvnode; 76char *mountrootfsname; 77#ifdef BOOTP 78extern void bootpc_init __P((void)); 79#endif 80 81/* 82 * vfs_init() will set maxvfsconf 83 * to the highest defined type number. 84 */ 85int maxvfsconf; 86struct vfsconf *vfsconf; 87 88/* 89 * Common root mount code shared by all filesystems 90 */ 91#define ROOTNAME "root_device" 92 93/* 94 * vfs_mountrootfs 95 * 96 * Common entry point for root mounts 97 * 98 * PARAMETERS: 99 * NONE 100 * 101 * RETURNS: 0 Success 102 * !0 error number (errno.h) 103 * 104 * LOCK STATE: 105 * ENTRY 106 * <no locks held> 107 * EXIT 108 * <no locks held> 109 * 110 * NOTES: 111 * This code is currently supported only for use for 112 * the FFS file system type. This is a matter of 113 * fixing the other file systems, not this code! 114 */ 115static void 116vfs_mountrootfs(void *unused) 117{ 118 struct mount *mp; 119 int err; 120 struct proc *p = curproc; /* XXX */ 121 int s; 122 int i; 123 dev_t orootdev; 124 125#ifdef BOOTP 126 bootpc_init(); 127#endif 128 /* 129 * New root mount structure 130 */ 131 if ((err = vfs_rootmountalloc(mountrootfsname, ROOTNAME, &mp))) { 132 printf("rootdev=%p error=%d, ", (void *)rootdev, err); 133 panic("cannot mount root\n"); 134 return ; 135 } 136 mp->mnt_flag |= MNT_ROOTFS; 137 138 /* 139 * If we have no idea what the device is because the VFS root mount 140 * initialization code couldn't figure it out, take a guess by 141 * assuming that vfs_getnewfsid() will be called when we try the 142 * mount. For the moment this is necessary for NFS-baesd BOOTP 143 * boots. Ultimately we would like to get rid of 'rootdev' entirely 144 * and go with a linked list of possible roots and device-specific 145 * auxillary data that we do not try to interpret ourselves. 146 */ 147 if (rootdev == NODEV && rootdevs[0] == NODEV) 148 rootdev = vfs_getrootfsid(mp); 149 150 /* 151 * Attempt the mount. This is rather messy due to many historical 152 * layers. Basically what it comes down to is that 'rootdev' is an 153 * override to the rootdevs[] array. The rootdevs[] array itself 154 * cannot normally be accessed directly by other modules, but FFS 155 * plays with it. NFS, on the otherhand, has no clue what the 156 * device assignment for a mount will be until it actually does it. 157 * 158 * During the loop we set rootdev to rootdevs[i]. This is used 159 * by FFS and a few other modules. It is ignored by NFS. 160 */ 161 err = ENXIO; 162 orootdev = rootdev; 163 if (rootdevs[0] == NODEV) 164 rootdevs[0] = rootdev; 165 for (i = 0; i < sizeof(rootdevs) / sizeof(rootdevs[0]); i++) { 166 if (rootdevs[i] == NODEV) 167 break; 168 rootdev = rootdevs[i]; 169 if (rootdev != orootdev) { 170 s = splbio(); /* Overkill, but harmless.. */ 171 printf("changing root device to %s\n", rootdevnames[i]); 172 splx(s); 173 orootdev = rootdev; 174 } 175 strncpy(mp->mnt_stat.f_mntfromname, 176 rootdevnames[i] ? rootdevnames[i] : ROOTNAME, MNAMELEN - 1); 177 err = VFS_MOUNT(mp, NULL, NULL, NULL, p); 178 if (err != ENXIO) 179 break; 180 } 181 if (err) { 182 /* 183 * XXX should ask the user for the name in some cases. 184 * Why do we call vfs_unbusy() here and not after ENXIO 185 * is returned above? 186 */ 187 vfs_unbusy(mp, p); 188 /* 189 * free mount struct before failing 190 * (hardly worthwhile with the PANIC eh?) 191 */ 192 free( mp, M_MOUNT); 193 printf("rootdev=%p error=%d, ", (void *)rootdev, err); 194 panic("cannot mount root (2)\n"); 195 return; 196 } 197 198 simple_lock(&mountlist_slock); 199 200 /* 201 * Add fs to list of mounted file systems 202 */ 203 CIRCLEQ_INSERT_HEAD(&mountlist, mp, mnt_list); 204 205 simple_unlock(&mountlist_slock); 206 vfs_unbusy(mp, p); 207 208 /* root mount, update system time from FS specific data*/ 209 inittodr(mp->mnt_time); 210 return; 211} 212 213SYSINIT(mountroot, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, vfs_mountrootfs, NULL) 214 215