Index: sys/geom/label/g_label_ufs.c =================================================================== --- sys/geom/label/g_label_ufs.c +++ sys/geom/label/g_label_ufs.c @@ -48,6 +48,39 @@ #define G_LABEL_UFS_VOLUME 0 #define G_LABEL_UFS_ID 1 +/* + * G_LABEL_UFS_CMP returns true if difference between provider mediasize + * and filesystem size is less than G_LABEL_UFS_MAXDIFF sectors + */ +#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 + +/* + * For MBR and EBR we need to check if file system size 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). + */ +static bool +g_label_ufs_ignore_possible_bsdlabel_slice(struct g_provider *pp, + struct fs *fs) +{ + const char *provider_name = pp->geom->class->name; + + if (strcmp(provider_name, "MBR") == 0 || + strcmp(provider_name, "EBR") == 0) + return (!G_LABEL_UFS_CMP(pp, fs, fs_old_size) && + !G_LABEL_UFS_CMP(pp, fs, fs_providersize)); + + return (true); +} + /* * Try to find a superblock on the provider. If successful, look for a volume * label and create an appropriate provider based on that. @@ -78,6 +111,9 @@ } else { goto out; } + /* Check if this should be ignored for compatibility. */ + if (g_label_ufs_ignore_possible_bsdlabel_slice(pp, fs)) + goto out; G_LABEL_DEBUG(1, "%s file system detected on %s.", fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name); switch (what) {