geom_vol_ffs.c revision 152967
1110290Sgordon/*- 2110290Sgordon * Copyright (c) 2002, 2003 Gordon Tetlow 3110290Sgordon * All rights reserved. 4110290Sgordon * 5110290Sgordon * Redistribution and use in source and binary forms, with or without 6110290Sgordon * modification, are permitted provided that the following conditions 7110290Sgordon * are met: 8110290Sgordon * 1. Redistributions of source code must retain the above copyright 9110290Sgordon * notice, this list of conditions and the following disclaimer. 10110290Sgordon * 2. Redistributions in binary form must reproduce the above copyright 11110290Sgordon * notice, this list of conditions and the following disclaimer in the 12110290Sgordon * documentation and/or other materials provided with the distribution. 13110290Sgordon * 14110290Sgordon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15110290Sgordon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16110290Sgordon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17110290Sgordon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18110290Sgordon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19110290Sgordon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20110290Sgordon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21110290Sgordon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22110290Sgordon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23110290Sgordon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24110290Sgordon * SUCH DAMAGE. 25110290Sgordon */ 26110290Sgordon 27116196Sobrien#include <sys/cdefs.h> 28116196Sobrien__FBSDID("$FreeBSD: head/sys/geom/geom_vol_ffs.c 152967 2005-11-30 19:24:51Z sobomax $"); 29116196Sobrien 30110290Sgordon#include <sys/param.h> 31110290Sgordon#include <sys/errno.h> 32110290Sgordon#include <sys/systm.h> 33110290Sgordon#include <sys/kernel.h> 34110290Sgordon#include <sys/malloc.h> 35110290Sgordon#include <sys/bio.h> 36110290Sgordon#include <sys/lock.h> 37110290Sgordon#include <sys/mutex.h> 38110290Sgordon 39110290Sgordon#include <ufs/ufs/dinode.h> 40110290Sgordon#include <ufs/ffs/fs.h> 41110290Sgordon 42110290Sgordon#include <geom/geom.h> 43110290Sgordon#include <geom/geom_slice.h> 44110290Sgordon 45110290Sgordon#define VOL_FFS_CLASS_NAME "VOL_FFS" 46110290Sgordon 47110290Sgordonstatic int superblocks[] = SBLOCKSEARCH; 48110290Sgordon 49110290Sgordonstruct g_vol_ffs_softc { 50110290Sgordon char * vol; 51110290Sgordon}; 52110290Sgordon 53110290Sgordonstatic int 54110290Sgordong_vol_ffs_start(struct bio *bp __unused) 55110290Sgordon{ 56110290Sgordon return(0); 57110290Sgordon} 58110290Sgordon 59110290Sgordonstatic struct g_geom * 60110290Sgordong_vol_ffs_taste(struct g_class *mp, struct g_provider *pp, int flags) 61110290Sgordon{ 62110290Sgordon struct g_geom *gp; 63110290Sgordon struct g_consumer *cp; 64110290Sgordon struct g_vol_ffs_softc *ms; 65110290Sgordon int error, sb, superblock; 66110290Sgordon struct fs *fs; 67110290Sgordon 68110290Sgordon g_trace(G_T_TOPOLOGY, "vol_taste(%s,%s)", mp->name, pp->name); 69110290Sgordon g_topology_assert(); 70110290Sgordon 71110513Sgordon /* 72110513Sgordon * XXX This is a really weak way to make sure we don't recurse. 73110513Sgordon * Probably ought to use BIO_GETATTR to check for this. 74110513Sgordon */ 75110290Sgordon if (flags == G_TF_NORMAL && 76110290Sgordon !strcmp(pp->geom->class->name, VOL_FFS_CLASS_NAME)) 77110290Sgordon return (NULL); 78110290Sgordon 79110290Sgordon gp = g_slice_new(mp, 1, pp, &cp, &ms, sizeof(*ms), g_vol_ffs_start); 80110290Sgordon if (gp == NULL) 81110290Sgordon return (NULL); 82110290Sgordon g_topology_unlock(); 83110290Sgordon /* 84110290Sgordon * Walk through the standard places that superblocks hide and look 85110290Sgordon * for UFS magic. If we find magic, then check that the size in the 86110290Sgordon * superblock corresponds to the size of the underlying provider. 87110291Sgordon * Finally, look for a volume label and create an appropriate 88110291Sgordon * provider based on that. 89110290Sgordon */ 90110290Sgordon for (sb=0; (superblock = superblocks[sb]) != -1; sb++) { 91141498Sdes /* 92141498Sdes * Take care not to issue an invalid I/O request. The 93141498Sdes * offset and size of the superblock candidate must be 94141498Sdes * multiples of the provider's sector size, otherwise an 95141498Sdes * FFS can't exist on the provider anyway. 96141498Sdes */ 97141498Sdes if (superblock % cp->provider->sectorsize != 0 || 98141498Sdes SBLOCKSIZE % cp->provider->sectorsize != 0) 99141498Sdes continue; 100141498Sdes 101110290Sgordon fs = (struct fs *) g_read_data(cp, superblock, 102110290Sgordon SBLOCKSIZE, &error); 103152967Ssobomax if (fs == NULL) 104110290Sgordon continue; 105110290Sgordon /* Check for magic and make sure things are the right size */ 106110290Sgordon if (fs->fs_magic == FS_UFS1_MAGIC) { 107110290Sgordon if (fs->fs_old_size * fs->fs_fsize != 108110290Sgordon (int32_t) pp->mediasize) { 109110290Sgordon g_free(fs); 110110290Sgordon continue; 111110290Sgordon } 112110290Sgordon } else if (fs->fs_magic == FS_UFS2_MAGIC) { 113110290Sgordon if (fs->fs_size * fs->fs_fsize != 114110290Sgordon (int64_t) pp->mediasize) { 115110290Sgordon g_free(fs); 116110290Sgordon continue; 117110290Sgordon } 118110290Sgordon } else { 119110290Sgordon g_free(fs); 120110290Sgordon continue; 121110290Sgordon } 122110290Sgordon /* Check for volume label */ 123110290Sgordon if (fs->fs_volname[0] == '\0') { 124110290Sgordon g_free(fs); 125110290Sgordon continue; 126110290Sgordon } 127110513Sgordon /* XXX We need to check for namespace conflicts. */ 128110513Sgordon /* XXX How do you handle a mirror set? */ 129110513Sgordon /* XXX We don't validate the volume name. */ 130110290Sgordon g_topology_lock(); 131110290Sgordon /* Alright, we have a label and a volume name, reconfig. */ 132110290Sgordon g_slice_config(gp, 0, G_SLICE_CONFIG_SET, (off_t) 0, 133110290Sgordon pp->mediasize, pp->sectorsize, "vol/%s", 134110290Sgordon fs->fs_volname); 135110290Sgordon g_free(fs); 136110290Sgordon g_topology_unlock(); 137110290Sgordon break; 138110290Sgordon } 139110290Sgordon g_topology_lock(); 140125755Sphk g_access(cp, -1, 0, 0); 141110290Sgordon if (LIST_EMPTY(&gp->provider)) { 142114518Sphk g_slice_spoiled(cp); 143110290Sgordon return (NULL); 144110290Sgordon } 145110290Sgordon return (gp); 146110290Sgordon} 147110290Sgordon 148110290Sgordonstatic struct g_class g_vol_ffs_class = { 149112552Sphk .name = VOL_FFS_CLASS_NAME, 150133318Sphk .version = G_VERSION, 151112552Sphk .taste = g_vol_ffs_taste, 152110290Sgordon}; 153110290Sgordon 154110290SgordonDECLARE_GEOM_CLASS(g_vol_ffs_class, g_vol_ffs); 155