Changeset View
Changeset View
Standalone View
Standalone View
sys/geom/label/g_label_ufs.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include <geom/geom.h> | #include <geom/geom.h> | ||||
#include <geom/geom_dbg.h> | #include <geom/geom_dbg.h> | ||||
#include <geom/label/g_label.h> | #include <geom/label/g_label.h> | ||||
#define G_LABEL_UFS_VOLUME 0 | #define G_LABEL_UFS_VOLUME 0 | ||||
#define G_LABEL_UFS_ID 1 | #define G_LABEL_UFS_ID 1 | ||||
/* | /* | ||||
* G_LABEL_UFS_CMP returns true if difference between provider mediasize | * Try to find a superblock on the provider. If successful, look for a volume | ||||
* and filesystem size is less than G_LABEL_UFS_MAXDIFF sectors | * label and create an appropriate provider based on that. | ||||
*/ | */ | ||||
#define G_LABEL_UFS_CMP(prov, fsys, size) \ | |||||
( abs( ((fsys)->size) - ( (prov)->mediasize / (fsys)->fs_fsize )) \ | |||||
< G_LABEL_UFS_MAXDIFF ) | |||||
#define G_LABEL_UFS_MAXDIFF 0x100 | |||||
/* | |||||
* Try to find a superblock on the provider. If successful, then | |||||
* check that the size in the superblock corresponds to the size | |||||
* of the underlying provider. Finally, look for a volume label | |||||
* and create an appropriate provider based on that. | |||||
*/ | |||||
static void | static void | ||||
g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what) | g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what) | ||||
{ | { | ||||
struct g_provider *pp; | struct g_provider *pp; | ||||
struct fs *fs; | struct fs *fs; | ||||
g_topology_assert_not(); | g_topology_assert_not(); | ||||
pp = cp->provider; | pp = cp->provider; | ||||
label[0] = '\0'; | label[0] = '\0'; | ||||
fs = NULL; | fs = NULL; | ||||
if (SBLOCKSIZE % pp->sectorsize != 0 || ffs_sbget(cp, &fs, | if (SBLOCKSIZE % pp->sectorsize != 0 || ffs_sbget(cp, &fs, | ||||
STDSB_NOHASHFAIL, M_GEOM, g_use_g_read_data) != 0) { | STDSB_NOHASHFAIL, M_GEOM, g_use_g_read_data) != 0) { | ||||
KASSERT(fs == NULL, | KASSERT(fs == NULL, | ||||
("g_label_ufs_taste_common: non-NULL fs %p\n", fs)); | ("g_label_ufs_taste_common: non-NULL fs %p\n", fs)); | ||||
return; | return; | ||||
} | } | ||||
/* | /* Check for magic. */ | ||||
* Check for magic. We also need to check if file system size | if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0) { | ||||
* is almost equal to providers size, because sysinstall(8) | |||||
* used to bogusly put first partition at offset 0 | |||||
* instead of 16, and glabel/ufs would find file system on slice | |||||
* instead of partition. | |||||
* | |||||
* In addition, media size can be a bit bigger than file system | |||||
* size. For instance, mkuzip can append bytes to align data | |||||
* to large sector size (it improves compression rates). | |||||
*/ | |||||
if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 && | |||||
( G_LABEL_UFS_CMP(pp, fs, fs_old_size) | |||||
|| G_LABEL_UFS_CMP(pp, fs, fs_providersize))) { | |||||
/* Valid UFS1. */ | /* Valid UFS1. */ | ||||
} else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 && | } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0) { | ||||
( G_LABEL_UFS_CMP(pp, fs, fs_size) | |||||
|| G_LABEL_UFS_CMP(pp, fs, fs_providersize))) { | |||||
/* Valid UFS2. */ | /* Valid UFS2. */ | ||||
} else { | } else { | ||||
goto out; | goto out; | ||||
} | } | ||||
G_LABEL_DEBUG(1, "%s file system detected on %s.", | G_LABEL_DEBUG(1, "%s file system detected on %s.", | ||||
fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name); | fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name); | ||||
switch (what) { | switch (what) { | ||||
case G_LABEL_UFS_VOLUME: | case G_LABEL_UFS_VOLUME: | ||||
▲ Show 20 Lines • Show All 46 Lines • Show Last 20 Lines |