Page MenuHomeFreeBSD

D19245.id54075.diff
No OneTemporary

D19245.id54075.diff

Index: sys/geom/geom_io.c
===================================================================
--- sys/geom/geom_io.c
+++ sys/geom/geom_io.c
@@ -925,17 +925,25 @@
struct bio *bp;
void *ptr;
int errorc;
+ off_t start_align;
+ off_t end_align;
- KASSERT(length > 0 && length >= cp->provider->sectorsize &&
- length <= MAXPHYS, ("g_read_data(): invalid length %jd",
- (intmax_t)length));
+ KASSERT(length > 0 && length <= MAXPHYS,
+ ("g_read_data(): invalid length %jd", (intmax_t)length));
+ /* allow unaligned reads */
+ start_align = (offset % cp->provider->sectorsize);
+ end_align = (cp->provider->sectorsize - ((offset + length) %
+ cp->provider->sectorsize)) % cp->provider->sectorsize;
+
+ /* setup BIO request */
bp = g_alloc_bio();
bp->bio_cmd = BIO_READ;
bp->bio_done = NULL;
- bp->bio_offset = offset;
- bp->bio_length = length;
- ptr = g_malloc(length, M_WAITOK);
+ bp->bio_offset = offset - start_align;
+ bp->bio_length = length + start_align + end_align;
+
+ ptr = g_malloc(bp->bio_length, M_WAITOK);
bp->bio_data = ptr;
g_io_request(bp, cp);
errorc = biowait(bp, "gread");
@@ -945,6 +953,10 @@
if (errorc) {
g_free(ptr);
ptr = NULL;
+ } else {
+ /* check if buffer data should be shifted down */
+ if (start_align != 0)
+ memmove(ptr, (uint8_t *)ptr + start_align, length);
}
return (ptr);
}
@@ -979,21 +991,42 @@
g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length)
{
struct bio *bp;
+ void *fixup;
int error;
+ off_t start_align;
+ off_t end_align;
- KASSERT(length > 0 && length >= cp->provider->sectorsize &&
- length <= MAXPHYS, ("g_write_data(): invalid length %jd",
- (intmax_t)length));
+ KASSERT(length > 0 && length <= MAXPHYS,
+ ("g_write_data(): invalid length %jd", (intmax_t)length));
+ /* allow unaligned writes */
+ start_align = (offset % cp->provider->sectorsize);
+ end_align = (cp->provider->sectorsize - ((offset + length) %
+ cp->provider->sectorsize)) % cp->provider->sectorsize;
+
+ /* check if we need to do a fixup request */
+ if (start_align != 0 || end_align != 0) {
+ fixup = g_read_data(cp, offset - start_align,
+ length + start_align + end_align, &error);
+ if (fixup == NULL)
+ return (error);
+ memcpy((uint8_t *)fixup + start_align, ptr, length);
+ } else {
+ fixup = ptr;
+ }
+
+ /* setup BIO request */
bp = g_alloc_bio();
bp->bio_cmd = BIO_WRITE;
bp->bio_done = NULL;
- bp->bio_offset = offset;
- bp->bio_length = length;
- bp->bio_data = ptr;
+ bp->bio_offset = offset - start_align;
+ bp->bio_length = length + start_align + end_align;
+ bp->bio_data = fixup;
g_io_request(bp, cp);
error = biowait(bp, "gwrite");
g_destroy_bio(bp);
+ if (fixup != ptr)
+ g_free(fixup);
return (error);
}
Index: sys/geom/part/g_part_bsd.c
===================================================================
--- sys/geom/part/g_part_bsd.c
+++ sys/geom/part/g_part_bsd.c
@@ -48,6 +48,7 @@
#include "g_part_if.h"
+#define MIN_SECT_SIZE MAX(sizeof(struct disklabel), 512)
#define BOOT1_SIZE 512
#define LABEL_SIZE 512
#define BOOT2_OFF (BOOT1_SIZE + LABEL_SIZE)
@@ -55,10 +56,20 @@
FEATURE(geom_part_bsd, "GEOM partitioning class for BSD disklabels");
+SYSCTL_DECL(_kern_geom_part);
+static SYSCTL_NODE(_kern_geom_part, OID_AUTO, bsd, CTLFLAG_RW, 0,
+ "GEOM_PART_BSD BSD disklabels");
+
+static u_int enforce_512bbs = 1;
+SYSCTL_UINT(_kern_geom_part_bsd, OID_AUTO, enforce_512bbs,
+ CTLFLAG_RWTUN, &enforce_512bbs, 0, "Enforce 512 byte block size");
+
struct g_part_bsd_table {
struct g_part_table base;
u_char *bbarea;
uint32_t offset;
+ off_t sectorsize;
+ off_t sectorfact;
};
struct g_part_bsd_entry {
@@ -204,7 +215,7 @@
pp = gpp->gpp_provider;
- if (pp->sectorsize < sizeof(struct disklabel))
+ if (pp->sectorsize < MIN_SECT_SIZE)
return (ENOSPC);
if (BBSIZE % pp->sectorsize)
return (ENOTBLK);
@@ -215,15 +226,24 @@
table = (struct g_part_bsd_table *)basetable;
table->bbarea = g_malloc(BBSIZE, M_WAITOK | M_ZERO);
- ptr = table->bbarea + pp->sectorsize;
+ if (enforce_512bbs) {
+ table->sectorfact = pp->sectorsize / 512;
+ table->sectorsize = 512;
+ } else {
+ table->sectorfact = 1;
+ table->sectorsize = pp->sectorsize;
+ }
+
+ ptr = table->bbarea + table->sectorsize;
+
le32enc(ptr + 0, DISKMAGIC); /* d_magic */
- le32enc(ptr + 40, pp->sectorsize); /* d_secsize */
+ le32enc(ptr + 40, table->sectorsize); /* d_secsize */
le32enc(ptr + 44, basetable->gpt_sectors); /* d_nsectors */
le32enc(ptr + 48, basetable->gpt_heads); /* d_ntracks */
le32enc(ptr + 52, ncyls); /* d_ncylinders */
le32enc(ptr + 56, secpercyl); /* d_secpercyl */
- le32enc(ptr + 60, msize); /* d_secperunit */
+ le32enc(ptr + 60, msize * table->sectorfact); /* d_secperunit */
le16enc(ptr + 72, 3600); /* d_rpm */
le32enc(ptr + 132, DISKMAGIC); /* d_magic2 */
le16enc(ptr + 138, basetable->gpt_entries); /* d_npartitions */
@@ -313,7 +333,7 @@
table = (struct g_part_bsd_table *)basetable;
msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
- le32enc(table->bbarea + pp->sectorsize + 60, msize); /* d_secperunit */
+ le32enc(table->bbarea + pp->sectorsize + 60, msize * table->sectorfact); /* d_secperunit */
basetable->gpt_last = msize - 1;
LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) {
if (baseentry->gpe_index != RAW_PART + 1)
@@ -354,24 +374,33 @@
}
static int
-g_part_bsd_probe(struct g_part_table *table, struct g_consumer *cp)
+g_part_bsd_probe(struct g_part_table *basetable, struct g_consumer *cp)
{
+ struct g_part_bsd_table *table;
struct g_provider *pp;
u_char *buf;
uint32_t magic1, magic2;
int error;
+ table = (struct g_part_bsd_table *)basetable;
pp = cp->provider;
/* Sanity-check the provider. */
- if (pp->sectorsize < sizeof(struct disklabel) ||
- pp->mediasize < BBSIZE)
+ if (pp->sectorsize < MIN_SECT_SIZE || pp->mediasize < BBSIZE)
return (ENOSPC);
if (BBSIZE % pp->sectorsize)
return (ENOTBLK);
+ if (enforce_512bbs) {
+ table->sectorfact = pp->sectorsize / 512;
+ table->sectorsize = 512;
+ } else {
+ table->sectorfact = 1;
+ table->sectorsize = pp->sectorsize;
+ }
+
/* Check that there's a disklabel. */
- buf = g_read_data(cp, pp->sectorsize, pp->sectorsize, &error);
+ buf = g_read_data(cp, table->sectorsize, table->sectorsize, &error);
if (buf == NULL)
return (error);
magic1 = le32dec(buf + 0);
@@ -402,9 +431,9 @@
if (table->bbarea == NULL)
return (error);
- buf = table->bbarea + pp->sectorsize;
+ buf = table->bbarea + table->sectorsize;
- if (le32dec(buf + 40) != pp->sectorsize)
+ if (le32dec(buf + 40) != table->sectorsize)
goto invalid_label;
sectors = le32dec(buf + 44);
if (sectors < 1 || sectors > 255)
@@ -423,8 +452,10 @@
basetable->gpt_heads = heads;
chs = le32dec(buf + 60);
- if (chs < 1)
+ if ((chs % table->sectorfact) != 0 || chs < 1)
goto invalid_label;
+ chs /= table->sectorfact;
+
/* Fix-up a sysinstall bug. */
if (chs > msize) {
chs = msize;
@@ -449,10 +480,12 @@
part.p_fstype = p[12];
part.p_frag = p[13];
part.p_cpg = le16dec(p + 14);
- if (part.p_size == 0)
+ if (part.p_size == 0 || (part.p_size % table->sectorfact) != 0)
continue;
- if (part.p_offset < table->offset)
+ part.p_size /= table->sectorfact;
+ if (part.p_offset < table->offset || (part.p_offset % table->sectorfact) != 0)
continue;
+ part.p_offset /= table->sectorfact;
if (part.p_offset - table->offset > basetable->gpt_last)
goto invalid_label;
baseentry = g_part_new_entry(basetable, index + 1,
@@ -510,14 +543,14 @@
pp = cp->provider;
table = (struct g_part_bsd_table *)basetable;
baseentry = LIST_FIRST(&basetable->gpt_entry);
- label = table->bbarea + pp->sectorsize;
+ label = table->bbarea + table->sectorsize;
for (index = 1; index <= basetable->gpt_entries; index++) {
p = label + 148 + (index - 1) * 16;
entry = (baseentry != NULL && index == baseentry->gpe_index)
? (struct g_part_bsd_entry *)baseentry : NULL;
if (entry != NULL && !baseentry->gpe_deleted) {
- le32enc(p + 0, entry->part.p_size);
- le32enc(p + 4, entry->part.p_offset);
+ le32enc(p + 0, entry->part.p_size * table->sectorfact);
+ le32enc(p + 4, entry->part.p_offset * table->sectorfact);
le32enc(p + 8, entry->part.p_fsize);
p[12] = entry->part.p_fstype;
p[13] = entry->part.p_frag;
Index: sys/geom/part/g_part_mbr.c
===================================================================
--- sys/geom/part/g_part_mbr.c
+++ sys/geom/part/g_part_mbr.c
@@ -59,10 +59,15 @@
SYSCTL_UINT(_kern_geom_part_mbr, OID_AUTO, enforce_chs,
CTLFLAG_RWTUN, &enforce_chs, 0, "Enforce alignment to CHS addressing");
+static u_int enforce_512bbs = 1;
+SYSCTL_UINT(_kern_geom_part_mbr, OID_AUTO, enforce_512bbs,
+ CTLFLAG_RWTUN, &enforce_512bbs, 0, "Enforce 512 byte block size");
+
#define MBRSIZE 512
struct g_part_mbr_table {
struct g_part_table base;
+ off_t sectorfact;
u_char mbr[MBRSIZE];
};
@@ -295,6 +300,11 @@
table = (struct g_part_mbr_table *)basetable;
le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC);
+
+ if (enforce_512bbs)
+ table->sectorfact = pp->sectorsize / MBRSIZE;
+ else
+ table->sectorfact = 1;
return (0);
}
@@ -366,6 +376,7 @@
g_part_mbr_resize(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
+ struct g_part_mbr_table *table;
struct g_part_mbr_entry *entry;
struct g_provider *pp;
uint32_t size;
@@ -384,6 +395,7 @@
if ((g_debugflags & 0x10) == 0 && size < gpp->gpp_size &&
pp->mediasize / pp->sectorsize > size)
return (EBUSY);
+ table = (struct g_part_mbr_table *)basetable;
entry = (struct g_part_mbr_entry *)baseentry;
baseentry->gpe_end = baseentry->gpe_start + size - 1;
entry->ent.dp_size = size;
@@ -402,14 +414,16 @@
}
static int
-g_part_mbr_probe(struct g_part_table *table, struct g_consumer *cp)
+g_part_mbr_probe(struct g_part_table *basetable, struct g_consumer *cp)
{
+ struct g_part_mbr_table *table;
char psn[8];
struct g_provider *pp;
u_char *buf, *p;
int error, index, res, sum;
uint16_t magic;
+ table = (struct g_part_mbr_table *)basetable;
pp = cp->provider;
/* Sanity-check the provider. */
@@ -418,13 +432,18 @@
if (pp->sectorsize > 4096)
return (ENXIO);
+ if (enforce_512bbs)
+ table->sectorfact = pp->sectorsize / MBRSIZE;
+ else
+ table->sectorfact = 1;
+
/* We don't nest under an MBR (see EBR instead). */
error = g_getattr("PART::scheme", cp, &psn);
if (error == 0 && strcmp(psn, g_part_mbr_scheme.name) == 0)
return (ELOOP);
/* Check that there's a MBR. */
- buf = g_read_data(cp, 0L, pp->sectorsize, &error);
+ buf = g_read_data(cp, 0L, MBRSIZE, &error);
if (buf == NULL)
return (error);
@@ -477,7 +496,7 @@
first = basetable->gpt_sectors;
msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
- buf = g_read_data(cp, 0L, pp->sectorsize, &error);
+ buf = g_read_data(cp, 0L, MBRSIZE, &error);
if (buf == NULL)
return (error);
@@ -494,6 +513,12 @@
ent.dp_ecyl = p[7];
ent.dp_start = le32dec(p + 8);
ent.dp_size = le32dec(p + 12);
+ if (ent.dp_start % table->sectorfact)
+ continue;
+ ent.dp_start /= table->sectorfact;
+ if (ent.dp_size % table->sectorfact)
+ continue;
+ ent.dp_size /= table->sectorfact;
if (ent.dp_typ == 0 || ent.dp_typ == DOSPTYP_PMBR)
continue;
if (ent.dp_start == 0 || ent.dp_size == 0)
@@ -604,8 +629,8 @@
p[5] = entry->ent.dp_ehd;
p[6] = entry->ent.dp_esect;
p[7] = entry->ent.dp_ecyl;
- le32enc(p + 8, entry->ent.dp_start);
- le32enc(p + 12, entry->ent.dp_size);
+ le32enc(p + 8, entry->ent.dp_start * table->sectorfact);
+ le32enc(p + 12, entry->ent.dp_size * table->sectorfact);
} else
bzero(p, DOSPARTSIZE);
@@ -613,6 +638,6 @@
baseentry = LIST_NEXT(baseentry, gpe_entry);
}
- error = g_write_data(cp, 0, table->mbr, cp->provider->sectorsize);
+ error = g_write_data(cp, 0, table->mbr, MBRSIZE);
return (error);
}

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 22, 12:32 AM (1 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24034502
Default Alt Text
D19245.id54075.diff (11 KB)

Event Timeline