summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2013-10-17 16:18:43 +0000
committerae <ae@FreeBSD.org>2013-10-17 16:18:43 +0000
commit05ca533af6819555c1c445085cd62d92ae824773 (patch)
treed6dabf99cb440907a870facf2c88d50d546c19fb /sys/geom
parent2a36c1745bb5c396e5e5d8f8afa1a5234a17b16a (diff)
downloadFreeBSD-src-05ca533af6819555c1c445085cd62d92ae824773.zip
FreeBSD-src-05ca533af6819555c1c445085cd62d92ae824773.tar.gz
Add an automatic resize support to the GEOM_PART class.
When parent provider has been resized, the scheme specific G_PART_RESIZE method does an update of scheme's metadata. But all changes are not saved to disk, until `gpart commit` will be called. Discussed with: trasz MFC after: 1 month
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/part/g_part.c26
-rw-r--r--sys/geom/part/g_part_apm.c8
-rw-r--r--sys/geom/part/g_part_bsd.c28
-rw-r--r--sys/geom/part/g_part_ebr.c17
-rw-r--r--sys/geom/part/g_part_gpt.c5
-rw-r--r--sys/geom/part/g_part_mbr.c7
-rw-r--r--sys/geom/part/g_part_pc98.c7
-rw-r--r--sys/geom/part/g_part_vtoc8.c41
8 files changed, 138 insertions, 1 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index db46dd3..993b9a2 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -132,6 +132,7 @@ static g_dumpconf_t g_part_dumpconf;
static g_orphan_t g_part_orphan;
static g_spoiled_t g_part_spoiled;
static g_start_t g_part_start;
+static g_resize_t g_part_resize;
static struct g_class g_part_class = {
.name = "PART",
@@ -148,6 +149,7 @@ static struct g_class g_part_class = {
.orphan = g_part_orphan,
.spoiled = g_part_spoiled,
.start = g_part_start,
+ .resize = g_part_resize
};
DECLARE_GEOM_CLASS(g_part_class, g_part);
@@ -2043,6 +2045,30 @@ g_part_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
}
static void
+g_part_resize(struct g_consumer *cp)
+{
+ struct g_part_table *table;
+
+ G_PART_TRACE((G_T_TOPOLOGY, "%s(%s)", __func__, cp->provider->name));
+ g_topology_assert();
+
+ table = cp->geom->softc;
+ if (table->gpt_opened == 0) {
+ if (g_access(cp, 1, 1, 1) != 0)
+ return;
+ table->gpt_opened = 1;
+ }
+ if (G_PART_RESIZE(table, NULL, NULL) == 0)
+ printf("GEOM_PART: %s was automatically resized\n",
+ cp->geom->name);
+ if (g_part_check_integrity(table, cp) != 0) {
+ g_access(cp, -1, -1, -1);
+ table->gpt_opened = 0;
+ g_part_wither(table->gpt_gp, ENXIO);
+ }
+}
+
+static void
g_part_orphan(struct g_consumer *cp)
{
struct g_provider *pp;
diff --git a/sys/geom/part/g_part_apm.c b/sys/geom/part/g_part_apm.c
index 6abd12e..66c0295 100644
--- a/sys/geom/part/g_part_apm.c
+++ b/sys/geom/part/g_part_apm.c
@@ -359,6 +359,14 @@ g_part_apm_resize(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_apm_entry *entry;
+ struct g_provider *pp;
+
+ if (baseentry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ basetable->gpt_last = MIN(pp->mediasize / pp->sectorsize,
+ UINT32_MAX) - 1;
+ return (0);
+ }
entry = (struct g_part_apm_entry *)baseentry;
baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
diff --git a/sys/geom/part/g_part_bsd.c b/sys/geom/part/g_part_bsd.c
index a53781c..487bf23 100644
--- a/sys/geom/part/g_part_bsd.c
+++ b/sys/geom/part/g_part_bsd.c
@@ -304,12 +304,40 @@ g_part_bsd_modify(struct g_part_table *basetable,
return (0);
}
+static void
+bsd_set_rawsize(struct g_part_table *basetable, struct g_provider *pp)
+{
+ struct g_part_bsd_table *table;
+ struct g_part_bsd_entry *entry;
+ struct g_part_entry *baseentry;
+ uint32_t msize;
+
+ table = (struct g_part_bsd_table *)basetable;
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
+ le32enc(table->bbarea + pp->sectorsize + 60, msize); /* d_secperunit */
+ basetable->gpt_last = msize - 1;
+ LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) {
+ if (baseentry->gpe_index != RAW_PART + 1)
+ continue;
+ baseentry->gpe_end = basetable->gpt_last;
+ entry = (struct g_part_bsd_entry *)baseentry;
+ entry->part.p_size = msize;
+ return;
+ }
+}
+
static int
g_part_bsd_resize(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_bsd_entry *entry;
+ struct g_provider *pp;
+ if (baseentry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ bsd_set_rawsize(basetable, pp);
+ return (0);
+ }
entry = (struct g_part_bsd_entry *)baseentry;
baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
entry->part.p_size = gpp->gpp_size;
diff --git a/sys/geom/part/g_part_ebr.c b/sys/geom/part/g_part_ebr.c
index 03b9aac..a8a940d 100644
--- a/sys/geom/part/g_part_ebr.c
+++ b/sys/geom/part/g_part_ebr.c
@@ -93,6 +93,8 @@ static int g_part_ebr_setunset(struct g_part_table *, struct g_part_entry *,
static const char *g_part_ebr_type(struct g_part_table *, struct g_part_entry *,
char *, size_t);
static int g_part_ebr_write(struct g_part_table *, struct g_consumer *);
+static int g_part_ebr_resize(struct g_part_table *, struct g_part_entry *,
+ struct g_part_parms *);
static kobj_method_t g_part_ebr_methods[] = {
KOBJMETHOD(g_part_add, g_part_ebr_add),
@@ -108,6 +110,7 @@ static kobj_method_t g_part_ebr_methods[] = {
KOBJMETHOD(g_part_precheck, g_part_ebr_precheck),
KOBJMETHOD(g_part_probe, g_part_ebr_probe),
KOBJMETHOD(g_part_read, g_part_ebr_read),
+ KOBJMETHOD(g_part_resize, g_part_ebr_resize),
KOBJMETHOD(g_part_setunset, g_part_ebr_setunset),
KOBJMETHOD(g_part_type, g_part_ebr_type),
KOBJMETHOD(g_part_write, g_part_ebr_write),
@@ -377,6 +380,20 @@ g_part_ebr_modify(struct g_part_table *basetable,
return (0);
}
+static int
+g_part_ebr_resize(struct g_part_table *basetable,
+ struct g_part_entry *baseentry, struct g_part_parms *gpp)
+{
+ struct g_provider *pp;
+
+ if (baseentry != NULL)
+ return (EOPNOTSUPP);
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ basetable->gpt_last = MIN(pp->mediasize / pp->sectorsize,
+ UINT32_MAX) - 1;
+ return (0);
+}
+
static const char *
g_part_ebr_name(struct g_part_table *table, struct g_part_entry *entry,
char *buf, size_t bufsz)
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index 8634b1e..13adf47 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -731,8 +731,11 @@ g_part_gpt_resize(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_gpt_entry *entry;
- entry = (struct g_part_gpt_entry *)baseentry;
+ if (baseentry == NULL)
+ return (EOPNOTSUPP);
+
+ entry = (struct g_part_gpt_entry *)baseentry;
baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
entry->ent.ent_lba_end = baseentry->gpe_end;
diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c
index 459aee6..e9085b1 100644
--- a/sys/geom/part/g_part_mbr.c
+++ b/sys/geom/part/g_part_mbr.c
@@ -336,8 +336,15 @@ g_part_mbr_resize(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_mbr_entry *entry;
+ struct g_provider *pp;
uint32_t size, sectors;
+ if (baseentry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ basetable->gpt_last = MIN(pp->mediasize / pp->sectorsize,
+ UINT32_MAX) - 1;
+ return (0);
+ }
sectors = basetable->gpt_sectors;
size = gpp->gpp_size;
diff --git a/sys/geom/part/g_part_pc98.c b/sys/geom/part/g_part_pc98.c
index d18d5cf..bd59431 100644
--- a/sys/geom/part/g_part_pc98.c
+++ b/sys/geom/part/g_part_pc98.c
@@ -343,8 +343,15 @@ g_part_pc98_resize(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_pc98_entry *entry;
+ struct g_provider *pp;
uint32_t size, cyl;
+ if (baseentry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ basetable->gpt_last = MIN(pp->mediasize / SECSIZE,
+ UINT32_MAX) - 1;
+ return (0);
+ }
cyl = basetable->gpt_heads * basetable->gpt_sectors;
size = gpp->gpp_size;
diff --git a/sys/geom/part/g_part_vtoc8.c b/sys/geom/part/g_part_vtoc8.c
index e993eff..833eceb 100644
--- a/sys/geom/part/g_part_vtoc8.c
+++ b/sys/geom/part/g_part_vtoc8.c
@@ -306,12 +306,53 @@ g_part_vtoc8_modify(struct g_part_table *basetable,
}
static int
+vtoc8_set_rawsize(struct g_part_table *basetable, struct g_provider *pp)
+{
+ struct g_part_vtoc8_table *table;
+ struct g_part_entry *baseentry;
+ off_t msize;
+ uint32_t acyls, ncyls, pcyls;
+
+ table = (struct g_part_vtoc8_table *)basetable;
+ msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX);
+ pcyls = msize / table->secpercyl;
+ if (pcyls > UINT16_MAX)
+ return (ERANGE);
+ acyls = be16dec(&table->vtoc.altcyls);
+ ncyls = pcyls - acyls;
+ msize = ncyls * table->secpercyl;
+ basetable->gpt_last = msize - 1;
+
+ bzero(table->vtoc.ascii, sizeof(table->vtoc.ascii));
+ sprintf(table->vtoc.ascii, "FreeBSD%lldM cyl %u alt %u hd %u sec %u",
+ (long long)(msize / 2048), ncyls, acyls, basetable->gpt_heads,
+ basetable->gpt_sectors);
+ be16enc(&table->vtoc.physcyls, pcyls);
+ be16enc(&table->vtoc.ncyls, ncyls);
+ be32enc(&table->vtoc.map[VTOC_RAW_PART].nblks, msize);
+ if (be32dec(&table->vtoc.sanity) == VTOC_SANITY)
+ be16enc(&table->vtoc.part[VTOC_RAW_PART].tag, VTOC_TAG_BACKUP);
+ LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) {
+ if (baseentry->gpe_index == VTOC_RAW_PART + 1) {
+ baseentry->gpe_end = basetable->gpt_last;
+ return (0);
+ }
+ }
+ return (ENXIO);
+}
+
+static int
g_part_vtoc8_resize(struct g_part_table *basetable,
struct g_part_entry *entry, struct g_part_parms *gpp)
{
struct g_part_vtoc8_table *table;
+ struct g_provider *pp;
uint64_t size;
+ if (entry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ return (vtoc8_set_rawsize(basetable, pp));
+ }
table = (struct g_part_vtoc8_table *)basetable;
size = gpp->gpp_size;
if (size % table->secpercyl)
OpenPOWER on IntegriCloud