Add the set and unset verbs used to set and clear attributes for

partition entries. Implement the setunset method for the MBR
scheme to control the active flag.
This commit is contained in:
Marcel Moolenaar 2008-06-18 01:13:34 +00:00
parent dd76dbbb9c
commit f6aa3fccce
4 changed files with 130 additions and 5 deletions

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2002, 2005, 2006, 2007 Marcel Moolenaar * Copyright (c) 2002, 2005-2008 Marcel Moolenaar
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -121,7 +121,9 @@ enum g_part_ctl {
G_PART_CTL_MOVE, G_PART_CTL_MOVE,
G_PART_CTL_RECOVER, G_PART_CTL_RECOVER,
G_PART_CTL_RESIZE, G_PART_CTL_RESIZE,
G_PART_CTL_UNDO G_PART_CTL_SET,
G_PART_CTL_UNDO,
G_PART_CTL_UNSET
}; };
/* /*
@ -953,6 +955,53 @@ g_part_ctl_resize(struct gctl_req *req, struct g_part_parms *gpp)
return (ENOSYS); return (ENOSYS);
} }
static int
g_part_ctl_setunset(struct gctl_req *req, struct g_part_parms *gpp,
unsigned int set)
{
char buf[32];
struct g_geom *gp;
struct g_part_entry *entry;
struct g_part_table *table;
struct sbuf *sb;
int error;
gp = gpp->gpp_geom;
G_PART_TRACE((G_T_TOPOLOGY, "%s(%s)", __func__, gp->name));
g_topology_assert();
table = gp->softc;
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);
}
error = G_PART_SETUNSET(table, entry, gpp->gpp_attrib, set);
if (error) {
gctl_error(req, "%d attrib '%s'", error, gpp->gpp_attrib);
return (error);
}
/* Provide feedback if so requested. */
if (gpp->gpp_parms & G_PART_PARM_OUTPUT) {
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
sbuf_printf(sb, "%s%s has %s %sset\n", gp->name,
G_PART_NAME(table, entry, buf, sizeof(buf)),
gpp->gpp_attrib, (set) ? "" : "un");
sbuf_finish(sb);
gctl_set_param(req, "output", sbuf_data(sb), sbuf_len(sb) + 1);
sbuf_delete(sb);
}
return (0);
}
static int static int
g_part_ctl_undo(struct gctl_req *req, struct g_part_parms *gpp) g_part_ctl_undo(struct gctl_req *req, struct g_part_parms *gpp)
{ {
@ -1129,11 +1178,22 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX; mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX;
} }
break; break;
case 's':
if (!strcmp(verb, "set")) {
ctlreq = G_PART_CTL_SET;
mparms |= G_PART_PARM_ATTRIB | G_PART_PARM_GEOM |
G_PART_PARM_INDEX;
}
break;
case 'u': case 'u':
if (!strcmp(verb, "undo")) { if (!strcmp(verb, "undo")) {
ctlreq = G_PART_CTL_UNDO; ctlreq = G_PART_CTL_UNDO;
mparms |= G_PART_PARM_GEOM; mparms |= G_PART_PARM_GEOM;
modifies = 0; modifies = 0;
} else if (!strcmp(verb, "unset")) {
ctlreq = G_PART_CTL_UNSET;
mparms |= G_PART_PARM_ATTRIB | G_PART_PARM_GEOM |
G_PART_PARM_INDEX;
} }
break; break;
} }
@ -1147,6 +1207,10 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
ap = &req->arg[i]; ap = &req->arg[i];
parm = 0; parm = 0;
switch (ap->name[0]) { switch (ap->name[0]) {
case 'a':
if (!strcmp(ap->name, "attrib"))
parm = G_PART_PARM_ATTRIB;
break;
case 'b': case 'b':
if (!strcmp(ap->name, "bootcode")) if (!strcmp(ap->name, "bootcode"))
parm = G_PART_PARM_BOOTCODE; parm = G_PART_PARM_BOOTCODE;
@ -1215,6 +1279,9 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
return; return;
} }
switch (parm) { switch (parm) {
case G_PART_PARM_ATTRIB:
error = g_part_parm_str(p, &gpp.gpp_attrib);
break;
case G_PART_PARM_BOOTCODE: case G_PART_PARM_BOOTCODE:
gpp.gpp_codeptr = p; gpp.gpp_codeptr = p;
gpp.gpp_codesize = len; gpp.gpp_codesize = len;
@ -1328,9 +1395,15 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
case G_PART_CTL_RESIZE: case G_PART_CTL_RESIZE:
error = g_part_ctl_resize(req, &gpp); error = g_part_ctl_resize(req, &gpp);
break; break;
case G_PART_CTL_SET:
error = g_part_ctl_setunset(req, &gpp, 1);
break;
case G_PART_CTL_UNDO: case G_PART_CTL_UNDO:
error = g_part_ctl_undo(req, &gpp); error = g_part_ctl_undo(req, &gpp);
break; break;
case G_PART_CTL_UNSET:
error = g_part_ctl_setunset(req, &gpp, 0);
break;
} }
/* Implement automatic commit. */ /* Implement automatic commit. */

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2006, 2007 Marcel Moolenaar * Copyright (c) 2006-2008 Marcel Moolenaar
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -136,6 +136,7 @@ struct g_part_entry *g_part_new_entry(struct g_part_table *, int, quad_t,
#define G_PART_PARM_TYPE 0x0400 #define G_PART_PARM_TYPE 0x0400
#define G_PART_PARM_VERSION 0x0800 #define G_PART_PARM_VERSION 0x0800
#define G_PART_PARM_BOOTCODE 0x1000 #define G_PART_PARM_BOOTCODE 0x1000
#define G_PART_PARM_ATTRIB 0x2000
struct g_part_parms { struct g_part_parms {
unsigned int gpp_parms; unsigned int gpp_parms;
@ -152,6 +153,7 @@ struct g_part_parms {
unsigned int gpp_version; unsigned int gpp_version;
const void *gpp_codeptr; const void *gpp_codeptr;
unsigned int gpp_codesize; unsigned int gpp_codesize;
const char *gpp_attrib;
}; };
void g_part_geometry_heads(off_t, u_int, off_t *, u_int *); void g_part_geometry_heads(off_t, u_int, off_t *, u_int *);

View File

@ -1,5 +1,5 @@
#- #-
# Copyright (c) 2006, 2007 Marcel Moolenaar # Copyright (c) 2006-2008 Marcel Moolenaar
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -108,6 +108,14 @@ METHOD int read {
struct g_consumer *cp; struct g_consumer *cp;
}; };
# setunset() - set or unset partition entry attributes.
METHOD int setunset {
struct g_part_table *table;
struct g_part_entry *entry;
const char *attrib;
unsigned int set;
};
# type() - return a string representation of the partition type. # type() - return a string representation of the partition type.
# Preferrably, the alias names. # Preferrably, the alias names.
METHOD const char * type { METHOD const char * type {

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2007 Marcel Moolenaar * Copyright (c) 2007, 2008 Marcel Moolenaar
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -71,6 +71,8 @@ static char *g_part_mbr_name(struct g_part_table *, struct g_part_entry *,
char *, size_t); char *, size_t);
static int g_part_mbr_probe(struct g_part_table *, struct g_consumer *); static int g_part_mbr_probe(struct g_part_table *, struct g_consumer *);
static int g_part_mbr_read(struct g_part_table *, struct g_consumer *); static int g_part_mbr_read(struct g_part_table *, struct g_consumer *);
static int g_part_mbr_setunset(struct g_part_table *, struct g_part_entry *,
const char *, unsigned int);
static const char *g_part_mbr_type(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); char *, size_t);
static int g_part_mbr_write(struct g_part_table *, struct g_consumer *); static int g_part_mbr_write(struct g_part_table *, struct g_consumer *);
@ -86,6 +88,7 @@ static kobj_method_t g_part_mbr_methods[] = {
KOBJMETHOD(g_part_name, g_part_mbr_name), KOBJMETHOD(g_part_name, g_part_mbr_name),
KOBJMETHOD(g_part_probe, g_part_mbr_probe), KOBJMETHOD(g_part_probe, g_part_mbr_probe),
KOBJMETHOD(g_part_read, g_part_mbr_read), KOBJMETHOD(g_part_read, g_part_mbr_read),
KOBJMETHOD(g_part_setunset, g_part_mbr_setunset),
KOBJMETHOD(g_part_type, g_part_mbr_type), KOBJMETHOD(g_part_type, g_part_mbr_type),
KOBJMETHOD(g_part_write, g_part_mbr_write), KOBJMETHOD(g_part_write, g_part_mbr_write),
{ 0, 0 } { 0, 0 }
@ -262,6 +265,8 @@ g_part_mbr_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry,
/* confxml: partition entry information */ /* confxml: partition entry information */
sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent, sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent,
entry->ent.dp_typ); entry->ent.dp_typ);
if (entry->ent.dp_flag & 0x80)
sbuf_printf(sb, "%s<attrib>active</attrib>\n", indent);
} else { } else {
/* confxml: scheme information */ /* confxml: scheme information */
} }
@ -420,6 +425,43 @@ g_part_mbr_read(struct g_part_table *basetable, struct g_consumer *cp)
return (0); return (0);
} }
static int
g_part_mbr_setunset(struct g_part_table *table, struct g_part_entry *baseentry,
const char *attrib, unsigned int set)
{
struct g_part_entry *iter;
struct g_part_mbr_entry *entry;
int changed;
if (strcasecmp(attrib, "active") != 0)
return (EINVAL);
/* Only one entry can have the active attribute. */
LIST_FOREACH(iter, &table->gpt_entry, gpe_entry) {
if (iter->gpe_deleted)
continue;
changed = 0;
entry = (struct g_part_mbr_entry *)iter;
if (iter == baseentry) {
if (set && (entry->ent.dp_flag & 0x80) == 0) {
entry->ent.dp_flag |= 0x80;
changed = 1;
} else if (!set && (entry->ent.dp_flag & 0x80)) {
entry->ent.dp_flag &= ~0x80;
changed = 1;
}
} else {
if (set && (entry->ent.dp_flag & 0x80)) {
entry->ent.dp_flag &= ~0x80;
changed = 1;
}
}
if (changed && !iter->gpe_created)
iter->gpe_modified = 1;
}
return (0);
}
static const char * static const char *
g_part_mbr_type(struct g_part_table *basetable, struct g_part_entry *baseentry, g_part_mbr_type(struct g_part_table *basetable, struct g_part_entry *baseentry,
char *buf, size_t bufsz) char *buf, size_t bufsz)