mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-18 15:30:21 +00:00
Implement the resize verb and add support for resizing partitions
for all schemes but EBR. Quality work by Andrey! Submitted by: "Andrey V. Elsukov" <bu7cher@yandex.ru>
This commit is contained in:
parent
efa50b120d
commit
3f71c319f4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=207094
@ -971,9 +971,85 @@ g_part_ctl_recover(struct gctl_req *req, struct g_part_parms *gpp)
|
||||
static int
|
||||
g_part_ctl_resize(struct gctl_req *req, struct g_part_parms *gpp)
|
||||
{
|
||||
gctl_error(req, "%d verb 'resize'", ENOSYS);
|
||||
return (ENOSYS);
|
||||
}
|
||||
struct g_geom *gp;
|
||||
struct g_provider *pp;
|
||||
struct g_part_entry *pe, *entry;
|
||||
struct g_part_table *table;
|
||||
struct sbuf *sb;
|
||||
quad_t end;
|
||||
int error;
|
||||
|
||||
gp = gpp->gpp_geom;
|
||||
G_PART_TRACE((G_T_TOPOLOGY, "%s(%s)", __func__, gp->name));
|
||||
g_topology_assert();
|
||||
table = gp->softc;
|
||||
|
||||
/* check gpp_index */
|
||||
LIST_FOREACH(entry, &table->gpt_entry, gpe_entry) {
|
||||
if (entry->gpe_deleted || entry->gpe_internal)
|
||||
continue;
|
||||
if (entry->gpe_index == gpp->gpp_index)
|
||||
break;
|
||||
}
|
||||
if (entry == NULL) {
|
||||
gctl_error(req, "%d index '%d'", ENOENT, gpp->gpp_index);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/* check gpp_size */
|
||||
end = entry->gpe_start + gpp->gpp_size - 1;
|
||||
if (gpp->gpp_size < 1 || end > table->gpt_last) {
|
||||
gctl_error(req, "%d size '%jd'", EINVAL,
|
||||
(intmax_t)gpp->gpp_size);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
LIST_FOREACH(pe, &table->gpt_entry, gpe_entry) {
|
||||
if (pe->gpe_deleted || pe->gpe_internal || pe == entry)
|
||||
continue;
|
||||
if (end >= pe->gpe_start && end <= pe->gpe_end) {
|
||||
gctl_error(req, "%d end '%jd'", ENOSPC,
|
||||
(intmax_t)end);
|
||||
return (ENOSPC);
|
||||
}
|
||||
if (entry->gpe_start < pe->gpe_start && end > pe->gpe_end) {
|
||||
gctl_error(req, "%d size '%jd'", ENOSPC,
|
||||
(intmax_t)gpp->gpp_size);
|
||||
return (ENOSPC);
|
||||
}
|
||||
}
|
||||
|
||||
pp = entry->gpe_pp;
|
||||
if ((g_debugflags & 16) == 0 &&
|
||||
(pp->acr > 0 || pp->acw > 0 || pp->ace > 0)) {
|
||||
gctl_error(req, "%d", EBUSY);
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
error = G_PART_RESIZE(table, entry, gpp);
|
||||
if (error) {
|
||||
gctl_error(req, "%d", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (!entry->gpe_created)
|
||||
entry->gpe_modified = 1;
|
||||
|
||||
/* update mediasize of changed provider */
|
||||
pp->mediasize = (entry->gpe_end - entry->gpe_start + 1) *
|
||||
pp->sectorsize;
|
||||
|
||||
/* Provide feedback if so requested. */
|
||||
if (gpp->gpp_parms & G_PART_PARM_OUTPUT) {
|
||||
sb = sbuf_new_auto();
|
||||
G_PART_FULLNAME(table, entry, sb, gp->name);
|
||||
sbuf_cat(sb, " resized\n");
|
||||
sbuf_finish(sb);
|
||||
gctl_set_param(req, "output", sbuf_data(sb), sbuf_len(sb) + 1);
|
||||
sbuf_delete(sb);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
g_part_ctl_setunset(struct gctl_req *req, struct g_part_parms *gpp,
|
||||
@ -1194,7 +1270,8 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
|
||||
mparms |= G_PART_PARM_GEOM;
|
||||
} else if (!strcmp(verb, "resize")) {
|
||||
ctlreq = G_PART_CTL_RESIZE;
|
||||
mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX;
|
||||
mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX |
|
||||
G_PART_PARM_SIZE;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
|
@ -74,6 +74,8 @@ static int g_part_apm_read(struct g_part_table *, struct g_consumer *);
|
||||
static const char *g_part_apm_type(struct g_part_table *, struct g_part_entry *,
|
||||
char *, size_t);
|
||||
static int g_part_apm_write(struct g_part_table *, struct g_consumer *);
|
||||
static int g_part_apm_resize(struct g_part_table *, struct g_part_entry *,
|
||||
struct g_part_parms *);
|
||||
|
||||
static kobj_method_t g_part_apm_methods[] = {
|
||||
KOBJMETHOD(g_part_add, g_part_apm_add),
|
||||
@ -82,6 +84,7 @@ static kobj_method_t g_part_apm_methods[] = {
|
||||
KOBJMETHOD(g_part_dumpconf, g_part_apm_dumpconf),
|
||||
KOBJMETHOD(g_part_dumpto, g_part_apm_dumpto),
|
||||
KOBJMETHOD(g_part_modify, g_part_apm_modify),
|
||||
KOBJMETHOD(g_part_resize, g_part_apm_resize),
|
||||
KOBJMETHOD(g_part_name, g_part_apm_name),
|
||||
KOBJMETHOD(g_part_probe, g_part_apm_probe),
|
||||
KOBJMETHOD(g_part_read, g_part_apm_read),
|
||||
@ -318,6 +321,19 @@ g_part_apm_modify(struct g_part_table *basetable,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
|
||||
entry = (struct g_part_apm_entry *)baseentry;
|
||||
baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
|
||||
entry->ent.ent_size = gpp->gpp_size;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
g_part_apm_name(struct g_part_table *table, struct g_part_entry *baseentry,
|
||||
char *buf, size_t bufsz)
|
||||
|
@ -73,6 +73,8 @@ static int g_part_bsd_read(struct g_part_table *, struct g_consumer *);
|
||||
static const char *g_part_bsd_type(struct g_part_table *, struct g_part_entry *,
|
||||
char *, size_t);
|
||||
static int g_part_bsd_write(struct g_part_table *, struct g_consumer *);
|
||||
static int g_part_bsd_resize(struct g_part_table *, struct g_part_entry *,
|
||||
struct g_part_parms *);
|
||||
|
||||
static kobj_method_t g_part_bsd_methods[] = {
|
||||
KOBJMETHOD(g_part_add, g_part_bsd_add),
|
||||
@ -82,6 +84,7 @@ static kobj_method_t g_part_bsd_methods[] = {
|
||||
KOBJMETHOD(g_part_dumpconf, g_part_bsd_dumpconf),
|
||||
KOBJMETHOD(g_part_dumpto, g_part_bsd_dumpto),
|
||||
KOBJMETHOD(g_part_modify, g_part_bsd_modify),
|
||||
KOBJMETHOD(g_part_resize, g_part_bsd_resize),
|
||||
KOBJMETHOD(g_part_name, g_part_bsd_name),
|
||||
KOBJMETHOD(g_part_probe, g_part_bsd_probe),
|
||||
KOBJMETHOD(g_part_read, g_part_bsd_read),
|
||||
@ -288,6 +291,19 @@ g_part_bsd_modify(struct g_part_table *basetable,
|
||||
return (0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
entry = (struct g_part_bsd_entry *)baseentry;
|
||||
baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
|
||||
entry->part.p_size = gpp->gpp_size;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
g_part_bsd_name(struct g_part_table *table, struct g_part_entry *baseentry,
|
||||
char *buf, size_t bufsz)
|
||||
|
@ -103,6 +103,8 @@ static int g_part_gpt_read(struct g_part_table *, struct g_consumer *);
|
||||
static const char *g_part_gpt_type(struct g_part_table *, struct g_part_entry *,
|
||||
char *, size_t);
|
||||
static int g_part_gpt_write(struct g_part_table *, struct g_consumer *);
|
||||
static int g_part_gpt_resize(struct g_part_table *, struct g_part_entry *,
|
||||
struct g_part_parms *);
|
||||
|
||||
static kobj_method_t g_part_gpt_methods[] = {
|
||||
KOBJMETHOD(g_part_add, g_part_gpt_add),
|
||||
@ -112,6 +114,7 @@ static kobj_method_t g_part_gpt_methods[] = {
|
||||
KOBJMETHOD(g_part_dumpconf, g_part_gpt_dumpconf),
|
||||
KOBJMETHOD(g_part_dumpto, g_part_gpt_dumpto),
|
||||
KOBJMETHOD(g_part_modify, g_part_gpt_modify),
|
||||
KOBJMETHOD(g_part_resize, g_part_gpt_resize),
|
||||
KOBJMETHOD(g_part_name, g_part_gpt_name),
|
||||
KOBJMETHOD(g_part_probe, g_part_gpt_probe),
|
||||
KOBJMETHOD(g_part_read, g_part_gpt_read),
|
||||
@ -550,6 +553,19 @@ g_part_gpt_modify(struct g_part_table *basetable,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
|
||||
baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1;
|
||||
entry->ent.ent_lba_end = baseentry->gpe_end;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
g_part_gpt_name(struct g_part_table *table, struct g_part_entry *baseentry,
|
||||
char *buf, size_t bufsz)
|
||||
|
@ -58,6 +58,13 @@ CODE {
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
default_resize(struct g_part_table *t __unused,
|
||||
struct g_part_entry *e __unused, struct g_part_parms *p __unused)
|
||||
{
|
||||
return (ENOSYS);
|
||||
}
|
||||
};
|
||||
|
||||
# add() - scheme specific processing for the add verb.
|
||||
@ -114,6 +121,13 @@ METHOD int modify {
|
||||
struct g_part_parms *gpp;
|
||||
};
|
||||
|
||||
# resize() - scheme specific processing for the resize verb.
|
||||
METHOD int resize {
|
||||
struct g_part_table *table;
|
||||
struct g_part_entry *entry;
|
||||
struct g_part_parms *gpp;
|
||||
} DEFAULT default_resize;
|
||||
|
||||
# name() - return the name of the given partition entry.
|
||||
# Typical names are "p1", "s0" or "c".
|
||||
METHOD const char * name {
|
||||
|
@ -76,6 +76,8 @@ static int g_part_mbr_setunset(struct g_part_table *, struct g_part_entry *,
|
||||
static const char *g_part_mbr_type(struct g_part_table *, struct g_part_entry *,
|
||||
char *, size_t);
|
||||
static int g_part_mbr_write(struct g_part_table *, struct g_consumer *);
|
||||
static int g_part_mbr_resize(struct g_part_table *, struct g_part_entry *,
|
||||
struct g_part_parms *);
|
||||
|
||||
static kobj_method_t g_part_mbr_methods[] = {
|
||||
KOBJMETHOD(g_part_add, g_part_mbr_add),
|
||||
@ -85,6 +87,7 @@ static kobj_method_t g_part_mbr_methods[] = {
|
||||
KOBJMETHOD(g_part_dumpconf, g_part_mbr_dumpconf),
|
||||
KOBJMETHOD(g_part_dumpto, g_part_mbr_dumpto),
|
||||
KOBJMETHOD(g_part_modify, g_part_mbr_modify),
|
||||
KOBJMETHOD(g_part_resize, g_part_mbr_resize),
|
||||
KOBJMETHOD(g_part_name, g_part_mbr_name),
|
||||
KOBJMETHOD(g_part_probe, g_part_mbr_probe),
|
||||
KOBJMETHOD(g_part_read, g_part_mbr_read),
|
||||
@ -302,6 +305,31 @@ g_part_mbr_modify(struct g_part_table *basetable,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
uint32_t size, sectors;
|
||||
|
||||
sectors = basetable->gpt_sectors;
|
||||
size = gpp->gpp_size;
|
||||
|
||||
if (size < sectors)
|
||||
return (EINVAL);
|
||||
if (size % sectors)
|
||||
size = size - (size % sectors);
|
||||
if (size < sectors)
|
||||
return (EINVAL);
|
||||
|
||||
entry = (struct g_part_mbr_entry *)baseentry;
|
||||
baseentry->gpe_end = baseentry->gpe_start + size - 1;
|
||||
entry->ent.dp_size = size;
|
||||
mbr_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
|
||||
&entry->ent.dp_ehd, &entry->ent.dp_esect);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
g_part_mbr_name(struct g_part_table *table, struct g_part_entry *baseentry,
|
||||
char *buf, size_t bufsz)
|
||||
|
@ -77,6 +77,8 @@ static int g_part_pc98_setunset(struct g_part_table *, struct g_part_entry *,
|
||||
static const char *g_part_pc98_type(struct g_part_table *,
|
||||
struct g_part_entry *, char *, size_t);
|
||||
static int g_part_pc98_write(struct g_part_table *, struct g_consumer *);
|
||||
static int g_part_pc98_resize(struct g_part_table *, struct g_part_entry *,
|
||||
struct g_part_parms *);
|
||||
|
||||
static kobj_method_t g_part_pc98_methods[] = {
|
||||
KOBJMETHOD(g_part_add, g_part_pc98_add),
|
||||
@ -86,6 +88,7 @@ static kobj_method_t g_part_pc98_methods[] = {
|
||||
KOBJMETHOD(g_part_dumpconf, g_part_pc98_dumpconf),
|
||||
KOBJMETHOD(g_part_dumpto, g_part_pc98_dumpto),
|
||||
KOBJMETHOD(g_part_modify, g_part_pc98_modify),
|
||||
KOBJMETHOD(g_part_resize, g_part_pc98_resize),
|
||||
KOBJMETHOD(g_part_name, g_part_pc98_name),
|
||||
KOBJMETHOD(g_part_probe, g_part_pc98_probe),
|
||||
KOBJMETHOD(g_part_read, g_part_pc98_read),
|
||||
@ -308,6 +311,31 @@ g_part_pc98_modify(struct g_part_table *basetable,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
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;
|
||||
uint32_t size, cyl;
|
||||
|
||||
cyl = basetable->gpt_heads * basetable->gpt_sectors;
|
||||
size = gpp->gpp_size;
|
||||
|
||||
if (size < cyl)
|
||||
return (EINVAL);
|
||||
if (size % cyl)
|
||||
size = size - (size % cyl);
|
||||
if (size < cyl)
|
||||
return (EINVAL);
|
||||
|
||||
entry = (struct g_part_pc98_entry *)baseentry;
|
||||
baseentry->gpe_end = baseentry->gpe_start + size - 1;
|
||||
pc98_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
|
||||
&entry->ent.dp_ehd, &entry->ent.dp_esect);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
g_part_pc98_name(struct g_part_table *table, struct g_part_entry *baseentry,
|
||||
char *buf, size_t bufsz)
|
||||
|
@ -67,6 +67,8 @@ static int g_part_vtoc8_read(struct g_part_table *, struct g_consumer *);
|
||||
static const char *g_part_vtoc8_type(struct g_part_table *, struct g_part_entry *,
|
||||
char *, size_t);
|
||||
static int g_part_vtoc8_write(struct g_part_table *, struct g_consumer *);
|
||||
static int g_part_vtoc8_resize(struct g_part_table *, struct g_part_entry *,
|
||||
struct g_part_parms *);
|
||||
|
||||
static kobj_method_t g_part_vtoc8_methods[] = {
|
||||
KOBJMETHOD(g_part_add, g_part_vtoc8_add),
|
||||
@ -75,6 +77,7 @@ static kobj_method_t g_part_vtoc8_methods[] = {
|
||||
KOBJMETHOD(g_part_dumpconf, g_part_vtoc8_dumpconf),
|
||||
KOBJMETHOD(g_part_dumpto, g_part_vtoc8_dumpto),
|
||||
KOBJMETHOD(g_part_modify, g_part_vtoc8_modify),
|
||||
KOBJMETHOD(g_part_resize, g_part_vtoc8_resize),
|
||||
KOBJMETHOD(g_part_name, g_part_vtoc8_name),
|
||||
KOBJMETHOD(g_part_probe, g_part_vtoc8_probe),
|
||||
KOBJMETHOD(g_part_read, g_part_vtoc8_read),
|
||||
@ -294,6 +297,26 @@ g_part_vtoc8_modify(struct g_part_table *basetable,
|
||||
return (0);
|
||||
}
|
||||
|
||||
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;
|
||||
uint64_t size;
|
||||
|
||||
table = (struct g_part_vtoc8_table *)basetable;
|
||||
size = gpp->gpp_size;
|
||||
if (size % table->secpercyl)
|
||||
size = size - (size % table->secpercyl);
|
||||
if (size < table->secpercyl)
|
||||
return (EINVAL);
|
||||
|
||||
entry->gpe_end = entry->gpe_start + size - 1;
|
||||
be32enc(&table->vtoc.map[entry->gpe_index - 1].nblks, size);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
g_part_vtoc8_name(struct g_part_table *table, struct g_part_entry *baseentry,
|
||||
char *buf, size_t bufsz)
|
||||
|
Loading…
Reference in New Issue
Block a user