xref: /freebsd/sys/geom/label/g_label_ufs.c (revision f8aa16c66c6e7e987af621f2185b7313cc9fe8e4)
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