1e1237b28SPawel Jakub Dawidek /*- 2e1237b28SPawel Jakub Dawidek * Copyright (c) 2002, 2003 Gordon Tetlow 3c058f512SPawel Jakub Dawidek * Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org> 4e1237b28SPawel Jakub Dawidek * All rights reserved. 5e1237b28SPawel Jakub Dawidek * 6e1237b28SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 7e1237b28SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 8e1237b28SPawel Jakub Dawidek * are met: 9e1237b28SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 10e1237b28SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 11e1237b28SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 12e1237b28SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 13e1237b28SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 14e1237b28SPawel Jakub Dawidek * 15c058f512SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 16e1237b28SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e1237b28SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18c058f512SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 19e1237b28SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e1237b28SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e1237b28SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e1237b28SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e1237b28SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e1237b28SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e1237b28SPawel Jakub Dawidek * SUCH DAMAGE. 26e1237b28SPawel Jakub Dawidek */ 27e1237b28SPawel Jakub Dawidek 28e1237b28SPawel Jakub Dawidek #include <sys/cdefs.h> 29e1237b28SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 30e1237b28SPawel Jakub Dawidek 31e1237b28SPawel Jakub Dawidek #include <sys/param.h> 32e1237b28SPawel Jakub Dawidek #include <sys/systm.h> 33e1237b28SPawel Jakub Dawidek #include <sys/kernel.h> 34e1237b28SPawel Jakub Dawidek #include <sys/malloc.h> 35e1237b28SPawel Jakub Dawidek 36e1237b28SPawel Jakub Dawidek #include <ufs/ufs/dinode.h> 37e1237b28SPawel Jakub Dawidek #include <ufs/ffs/fs.h> 38e1237b28SPawel Jakub Dawidek 39e1237b28SPawel Jakub Dawidek #include <geom/geom.h> 40e1237b28SPawel Jakub Dawidek #include <geom/label/g_label.h> 41e1237b28SPawel Jakub Dawidek 42e1237b28SPawel Jakub Dawidek #define G_LABEL_UFS_DIR "ufs" 43e1237b28SPawel Jakub Dawidek 44e1237b28SPawel Jakub Dawidek static const int superblocks[] = SBLOCKSEARCH; 45e1237b28SPawel Jakub Dawidek 46e1237b28SPawel Jakub Dawidek static void 47e1237b28SPawel Jakub Dawidek g_label_ufs_taste(struct g_consumer *cp, char *label, size_t size) 48e1237b28SPawel Jakub Dawidek { 49e1237b28SPawel Jakub Dawidek struct g_provider *pp; 50b53a1cf3SMaxim Sobolev int sb, superblock; 51e1237b28SPawel Jakub Dawidek struct fs *fs; 52e1237b28SPawel Jakub Dawidek 53e1237b28SPawel Jakub Dawidek g_topology_assert_not(); 54e1237b28SPawel Jakub Dawidek pp = cp->provider; 55e1237b28SPawel Jakub Dawidek label[0] = '\0'; 5633361bb5SPawel Jakub Dawidek 5733361bb5SPawel Jakub Dawidek if (SBLOCKSIZE % cp->provider->sectorsize != 0) 5817fb8ae7SPawel Jakub Dawidek return; 5933361bb5SPawel Jakub Dawidek 60e1237b28SPawel Jakub Dawidek /* 61e1237b28SPawel Jakub Dawidek * Walk through the standard places that superblocks hide and look 62e1237b28SPawel Jakub Dawidek * for UFS magic. If we find magic, then check that the size in the 63e1237b28SPawel Jakub Dawidek * superblock corresponds to the size of the underlying provider. 64e1237b28SPawel Jakub Dawidek * Finally, look for a volume label and create an appropriate 65e1237b28SPawel Jakub Dawidek * provider based on that. 66e1237b28SPawel Jakub Dawidek */ 67e1237b28SPawel Jakub Dawidek for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { 6804550802SDag-Erling Smørgrav /* 6933361bb5SPawel Jakub Dawidek * Take care not to issue an invalid I/O request. The offset of 7033361bb5SPawel Jakub Dawidek * the superblock candidate must be multiples of the provider's 7133361bb5SPawel Jakub Dawidek * sector size, otherwise an FFS can't exist on the provider 7233361bb5SPawel Jakub Dawidek * anyway. 7304550802SDag-Erling Smørgrav */ 7433361bb5SPawel Jakub Dawidek if (superblock % cp->provider->sectorsize != 0) 7504550802SDag-Erling Smørgrav continue; 7604550802SDag-Erling Smørgrav 7733361bb5SPawel Jakub Dawidek fs = (struct fs *)g_read_data(cp, superblock, SBLOCKSIZE, NULL); 788a4a44b5SMaxim Sobolev if (fs == NULL) 79e1237b28SPawel Jakub Dawidek continue; 80e1237b28SPawel Jakub Dawidek /* Check for magic and make sure things are the right size */ 81f8aa16c6SPawel Jakub Dawidek if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 && 82f8aa16c6SPawel Jakub Dawidek pp->mediasize / fs->fs_fsize == fs->fs_old_size) { 8399c889fcSPawel Jakub Dawidek /* Valid UFS1. */ 8499c889fcSPawel Jakub Dawidek } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 && 8599c889fcSPawel Jakub Dawidek pp->mediasize / fs->fs_fsize == fs->fs_size) { 8699c889fcSPawel Jakub Dawidek /* Valid UFS2. */ 8799c889fcSPawel Jakub Dawidek } else { 88e1237b28SPawel Jakub Dawidek g_free(fs); 89e1237b28SPawel Jakub Dawidek continue; 90e1237b28SPawel Jakub Dawidek } 91c058f512SPawel Jakub Dawidek if (fs->fs_sblockloc != superblock || fs->fs_ncg < 1 || 92c058f512SPawel Jakub Dawidek fs->fs_bsize < MINBSIZE || 93c058f512SPawel Jakub Dawidek fs->fs_bsize < sizeof(struct fs)) { 94e1237b28SPawel Jakub Dawidek g_free(fs); 95e1237b28SPawel Jakub Dawidek continue; 96e1237b28SPawel Jakub Dawidek } 97c058f512SPawel Jakub Dawidek G_LABEL_DEBUG(1, "%s file system detected on %s.", 98c058f512SPawel Jakub Dawidek fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name); 99e1237b28SPawel Jakub Dawidek /* Check for volume label */ 100e1237b28SPawel Jakub Dawidek if (fs->fs_volname[0] == '\0') { 101e1237b28SPawel Jakub Dawidek g_free(fs); 102e1237b28SPawel Jakub Dawidek continue; 103e1237b28SPawel Jakub Dawidek } 104e1237b28SPawel Jakub Dawidek strlcpy(label, fs->fs_volname, size); 105e1237b28SPawel Jakub Dawidek g_free(fs); 106e1237b28SPawel Jakub Dawidek break; 107e1237b28SPawel Jakub Dawidek } 108e1237b28SPawel Jakub Dawidek } 109e1237b28SPawel Jakub Dawidek 110e1237b28SPawel Jakub Dawidek const struct g_label_desc g_label_ufs = { 111e1237b28SPawel Jakub Dawidek .ld_taste = g_label_ufs_taste, 112e1237b28SPawel Jakub Dawidek .ld_dir = G_LABEL_UFS_DIR 113e1237b28SPawel Jakub Dawidek }; 114