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 42f7b16839SIvan Voras #define G_LABEL_UFS_VOLUME_DIR "ufs" 43f7b16839SIvan Voras #define G_LABEL_UFS_ID_DIR "ufsid" 44f7b16839SIvan Voras 45f7b16839SIvan Voras #define G_LABEL_UFS_VOLUME 0 46f7b16839SIvan Voras #define G_LABEL_UFS_ID 1 47e1237b28SPawel Jakub Dawidek 48e1237b28SPawel Jakub Dawidek static const int superblocks[] = SBLOCKSEARCH; 49e1237b28SPawel Jakub Dawidek 50e1237b28SPawel Jakub Dawidek static void 51f7b16839SIvan Voras g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what) 52e1237b28SPawel Jakub Dawidek { 53e1237b28SPawel Jakub Dawidek struct g_provider *pp; 54b53a1cf3SMaxim Sobolev int sb, superblock; 55e1237b28SPawel Jakub Dawidek struct fs *fs; 56e1237b28SPawel Jakub Dawidek 57e1237b28SPawel Jakub Dawidek g_topology_assert_not(); 58e1237b28SPawel Jakub Dawidek pp = cp->provider; 59e1237b28SPawel Jakub Dawidek label[0] = '\0'; 6033361bb5SPawel Jakub Dawidek 6133361bb5SPawel Jakub Dawidek if (SBLOCKSIZE % cp->provider->sectorsize != 0) 6217fb8ae7SPawel Jakub Dawidek return; 6333361bb5SPawel Jakub Dawidek 64e1237b28SPawel Jakub Dawidek /* 65e1237b28SPawel Jakub Dawidek * Walk through the standard places that superblocks hide and look 66e1237b28SPawel Jakub Dawidek * for UFS magic. If we find magic, then check that the size in the 67e1237b28SPawel Jakub Dawidek * superblock corresponds to the size of the underlying provider. 68e1237b28SPawel Jakub Dawidek * Finally, look for a volume label and create an appropriate 69e1237b28SPawel Jakub Dawidek * provider based on that. 70e1237b28SPawel Jakub Dawidek */ 71e1237b28SPawel Jakub Dawidek for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { 7204550802SDag-Erling Smørgrav /* 7333361bb5SPawel Jakub Dawidek * Take care not to issue an invalid I/O request. The offset of 7433361bb5SPawel Jakub Dawidek * the superblock candidate must be multiples of the provider's 7533361bb5SPawel Jakub Dawidek * sector size, otherwise an FFS can't exist on the provider 7633361bb5SPawel Jakub Dawidek * anyway. 7704550802SDag-Erling Smørgrav */ 7833361bb5SPawel Jakub Dawidek if (superblock % cp->provider->sectorsize != 0) 7904550802SDag-Erling Smørgrav continue; 8004550802SDag-Erling Smørgrav 8133361bb5SPawel Jakub Dawidek fs = (struct fs *)g_read_data(cp, superblock, SBLOCKSIZE, NULL); 828a4a44b5SMaxim Sobolev if (fs == NULL) 83e1237b28SPawel Jakub Dawidek continue; 84e1237b28SPawel Jakub Dawidek /* Check for magic and make sure things are the right size */ 85f8aa16c6SPawel Jakub Dawidek if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 && 86f8aa16c6SPawel Jakub Dawidek pp->mediasize / fs->fs_fsize == fs->fs_old_size) { 8799c889fcSPawel Jakub Dawidek /* Valid UFS1. */ 8899c889fcSPawel Jakub Dawidek } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 && 8999c889fcSPawel Jakub Dawidek pp->mediasize / fs->fs_fsize == fs->fs_size) { 9099c889fcSPawel Jakub Dawidek /* Valid UFS2. */ 9199c889fcSPawel Jakub Dawidek } else { 92e1237b28SPawel Jakub Dawidek g_free(fs); 93e1237b28SPawel Jakub Dawidek continue; 94e1237b28SPawel Jakub Dawidek } 95c058f512SPawel Jakub Dawidek if (fs->fs_sblockloc != superblock || fs->fs_ncg < 1 || 96c058f512SPawel Jakub Dawidek fs->fs_bsize < MINBSIZE || 97c058f512SPawel Jakub Dawidek fs->fs_bsize < sizeof(struct fs)) { 98e1237b28SPawel Jakub Dawidek g_free(fs); 99e1237b28SPawel Jakub Dawidek continue; 100e1237b28SPawel Jakub Dawidek } 101c058f512SPawel Jakub Dawidek G_LABEL_DEBUG(1, "%s file system detected on %s.", 102c058f512SPawel Jakub Dawidek fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name); 103f7b16839SIvan Voras switch (what) { 104f7b16839SIvan Voras case G_LABEL_UFS_VOLUME: 105e1237b28SPawel Jakub Dawidek /* Check for volume label */ 106e1237b28SPawel Jakub Dawidek if (fs->fs_volname[0] == '\0') { 107e1237b28SPawel Jakub Dawidek g_free(fs); 108e1237b28SPawel Jakub Dawidek continue; 109e1237b28SPawel Jakub Dawidek } 110e1237b28SPawel Jakub Dawidek strlcpy(label, fs->fs_volname, size); 111f7b16839SIvan Voras break; 112f7b16839SIvan Voras case G_LABEL_UFS_ID: 113f7b16839SIvan Voras if (fs->fs_id[0] == 0 && fs->fs_id[1] == 0) { 114f7b16839SIvan Voras g_free(fs); 115f7b16839SIvan Voras continue; 116f7b16839SIvan Voras } 117f7b16839SIvan Voras snprintf(label, size, "%08x%08x", fs->fs_id[0], 118f7b16839SIvan Voras fs->fs_id[1]); 119f7b16839SIvan Voras break; 120f7b16839SIvan Voras } 121e1237b28SPawel Jakub Dawidek g_free(fs); 122e1237b28SPawel Jakub Dawidek break; 123e1237b28SPawel Jakub Dawidek } 124e1237b28SPawel Jakub Dawidek } 125e1237b28SPawel Jakub Dawidek 126f7b16839SIvan Voras static void 127f7b16839SIvan Voras g_label_ufs_volume_taste(struct g_consumer *cp, char *label, size_t size) 128f7b16839SIvan Voras { 129f7b16839SIvan Voras 130f7b16839SIvan Voras g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_VOLUME); 131f7b16839SIvan Voras } 132f7b16839SIvan Voras 133f7b16839SIvan Voras static void 134f7b16839SIvan Voras g_label_ufs_id_taste(struct g_consumer *cp, char *label, size_t size) 135f7b16839SIvan Voras { 136f7b16839SIvan Voras 137f7b16839SIvan Voras g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_ID); 138f7b16839SIvan Voras } 139f7b16839SIvan Voras 1403ce9ca89SEdward Tomasz Napierala struct g_label_desc g_label_ufs_volume = { 141f7b16839SIvan Voras .ld_taste = g_label_ufs_volume_taste, 1423ce9ca89SEdward Tomasz Napierala .ld_dir = G_LABEL_UFS_VOLUME_DIR, 1433ce9ca89SEdward Tomasz Napierala .ld_enabled = 1 144f7b16839SIvan Voras }; 145f7b16839SIvan Voras 1463ce9ca89SEdward Tomasz Napierala struct g_label_desc g_label_ufs_id = { 147f7b16839SIvan Voras .ld_taste = g_label_ufs_id_taste, 1483ce9ca89SEdward Tomasz Napierala .ld_dir = G_LABEL_UFS_ID_DIR, 1493ce9ca89SEdward Tomasz Napierala .ld_enabled = 1 150e1237b28SPawel Jakub Dawidek }; 1513ce9ca89SEdward Tomasz Napierala 1523ce9ca89SEdward Tomasz Napierala G_LABEL_INIT(ufsid, g_label_ufs_id, "Create device nodes for UFS file system IDs"); 1533ce9ca89SEdward Tomasz Napierala G_LABEL_INIT(ufs, g_label_ufs_volume, "Create device nodes for UFS volume names"); 154