Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F132901475
D19245.id54075.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D19245.id54075.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D19245: Add support for legacy 512-byte block size MBRs on 4K block size disks
Attached
Detach File
Event Timeline
Log In to Comment