aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Grosbein <eugen@FreeBSD.org>2020-09-21 12:37:41 +0000
committerEugene Grosbein <eugen@FreeBSD.org>2020-09-21 12:37:41 +0000
commita8c2d3888a18878b5d4e4ce0382bbbe0bf1b2a10 (patch)
tree5ebcae8edbc5f54e4d77f308707c0d680a73bdaa
parent54acd65f6f6162873aa3f9b4c6a115ad50bb0d84 (diff)
downloadsrc-a8c2d3888a18878b5d4e4ce0382bbbe0bf1b2a10.tar.gz
src-a8c2d3888a18878b5d4e4ce0382bbbe0bf1b2a10.zip
MFS r365667,r365920: extend kern.geom.part.check_integrity to work on GPT
There are multiple USB/SATA bridges on the market that unconditionally cut some LBAs off connected media. This could be a problem for pre-partitioned drives so GEOM complains and does not create devices in /dev for slices/partitions preventing access to existing data. We have a knob kern.geom.part.check_integrity that allows us to correct partitioning if changed from default 1 to 0 but it works for MBR only. If backup copy of GPT is unavailable due to decreased number of LBAs, the kernel does not give access to partitions still and prints to dmesg: GEOM: md0: corrupt or invalid GPT detected. GEOM: md0: GPT rejected -- may not be recoverable. This change makes it work for GPT too, so it created partitions in /dev and prints to dmesg this instead: GEOM: md0: the secondary GPT table is corrupt or invalid. GEOM: md0: using the primary only -- recovery suggested. Then "gpart recover" re-creates backup copy of GPT and allows further manipulations with partitions. This change is no-op for default configuration having kern.geom.part.check_integrity=1 Reported by: Alex Korchmar Approved by: re (gjb)
Notes
Notes: svn path=/releng/12.2/; revision=365944
-rw-r--r--sys/geom/part/g_part.c9
-rw-r--r--sys/geom/part/g_part_gpt.c7
2 files changed, 10 insertions, 6 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index c969b9e7cc64..8b79b6404a6d 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -135,9 +135,9 @@ struct g_part_alias_list {
SYSCTL_DECL(_kern_geom);
SYSCTL_NODE(_kern_geom, OID_AUTO, part, CTLFLAG_RW, 0,
"GEOM_PART stuff");
-static u_int check_integrity = 1;
+u_int geom_part_check_integrity = 1;
SYSCTL_UINT(_kern_geom_part, OID_AUTO, check_integrity,
- CTLFLAG_RWTUN, &check_integrity, 1,
+ CTLFLAG_RWTUN, &geom_part_check_integrity, 1,
"Enable integrity checking");
static u_int auto_resize = 1;
SYSCTL_UINT(_kern_geom_part, OID_AUTO, auto_resize,
@@ -420,7 +420,7 @@ g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp)
if (failed != 0) {
printf("GEOM_PART: integrity check failed (%s, %s)\n",
pp->name, table->gpt_scheme->name);
- if (check_integrity != 0)
+ if (geom_part_check_integrity != 0)
return (EINVAL);
table->gpt_corrupt = 1;
}
@@ -1846,7 +1846,8 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
table = gpp.gpp_geom->softc;
if (table != NULL && table->gpt_corrupt &&
ctlreq != G_PART_CTL_DESTROY &&
- ctlreq != G_PART_CTL_RECOVER) {
+ ctlreq != G_PART_CTL_RECOVER &&
+ geom_part_check_integrity) {
gctl_error(req, "%d table '%s' is corrupt",
EPERM, gpp.gpp_geom->name);
return;
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index a17cb30ea806..8fd3b490c4fc 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -64,6 +64,8 @@ SYSCTL_UINT(_kern_geom_part_gpt, OID_AUTO, allow_nesting,
CTASSERT(offsetof(struct gpt_hdr, padding) == 92);
CTASSERT(sizeof(struct gpt_ent) == 128);
+extern u_int geom_part_check_integrity;
+
#define EQUUID(a,b) (memcmp(a, b, sizeof(struct uuid)) == 0)
#define MBRSIZE 512
@@ -460,8 +462,9 @@ gpt_read_hdr(struct g_part_gpt_table *table, struct g_consumer *cp,
if (hdr->hdr_lba_self != table->lba[elt])
goto fail;
hdr->hdr_lba_alt = le64toh(buf->hdr_lba_alt);
- if (hdr->hdr_lba_alt == hdr->hdr_lba_self ||
- hdr->hdr_lba_alt > last)
+ if (hdr->hdr_lba_alt == hdr->hdr_lba_self)
+ goto fail;
+ if (hdr->hdr_lba_alt > last && geom_part_check_integrity)
goto fail;
/* Check the managed area. */