summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2014-05-12 12:04:44 +0000
committerae <ae@FreeBSD.org>2014-05-12 12:04:44 +0000
commit8e5289f450c978cf458941bf5d2dd8bd3a7d7a9b (patch)
tree1bd9c02e0cc5e45c1753672e0e8a7fd762b57d92 /sys/geom
parent8bd4b60954efb98793d3eb0c22a8d3f8c4ca0d48 (diff)
downloadFreeBSD-src-8e5289f450c978cf458941bf5d2dd8bd3a7d7a9b.zip
FreeBSD-src-8e5289f450c978cf458941bf5d2dd8bd3a7d7a9b.tar.gz
MFC r256690:
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. MFC r265336: Add an advice what to do when partition was automatically resized.
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/part/g_part.c28
-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.c6
-rw-r--r--sys/geom/part/g_part_pc98.c6
-rw-r--r--sys/geom/part/g_part_vtoc8.c40
8 files changed, 137 insertions, 1 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index 51b20b0..d5862a0 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -133,6 +133,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",
@@ -149,6 +150,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);
@@ -2049,6 +2051,32 @@ 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"
+ " Use `gpart commit %s` to save changes or "
+ "`gpart undo %s` to revert them.\n", cp->geom->name,
+ cp->geom->name, 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 7a61a68..dfeda58 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),
@@ -384,6 +387,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 efabfbc..b547f0b 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -733,8 +733,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 0782e01..73101ff 100644
--- a/sys/geom/part/g_part_mbr.c
+++ b/sys/geom/part/g_part_mbr.c
@@ -345,6 +345,12 @@ g_part_mbr_resize(struct g_part_table *basetable,
struct g_provider *pp;
uint32_t size;
+ if (baseentry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ basetable->gpt_last = MIN(pp->mediasize / pp->sectorsize,
+ UINT32_MAX) - 1;
+ return (0);
+ }
size = gpp->gpp_size;
if (mbr_align(basetable, NULL, &size) != 0)
return (EINVAL);
diff --git a/sys/geom/part/g_part_pc98.c b/sys/geom/part/g_part_pc98.c
index 4a15215..07d6a62 100644
--- a/sys/geom/part/g_part_pc98.c
+++ b/sys/geom/part/g_part_pc98.c
@@ -352,6 +352,12 @@ g_part_pc98_resize(struct g_part_table *basetable,
struct g_provider *pp;
uint32_t size;
+ if (baseentry == NULL) {
+ pp = LIST_FIRST(&basetable->gpt_gp->consumer)->provider;
+ basetable->gpt_last = MIN(pp->mediasize / SECSIZE,
+ UINT32_MAX) - 1;
+ return (0);
+ }
size = gpp->gpp_size;
if (pc98_align(basetable, NULL, &size) != 0)
return (EINVAL);
diff --git a/sys/geom/part/g_part_vtoc8.c b/sys/geom/part/g_part_vtoc8.c
index e22a590..514e3f7 100644
--- a/sys/geom/part/g_part_vtoc8.c
+++ b/sys/geom/part/g_part_vtoc8.c
@@ -317,6 +317,42 @@ 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)
{
@@ -324,6 +360,10 @@ g_part_vtoc8_resize(struct g_part_table *basetable,
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 (vtoc8_align(table, NULL, &size) != 0)
OpenPOWER on IntegriCloud