From f6aa3fccce0566aaec9861e77b7bd25807991ed7 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Wed, 18 Jun 2008 01:13:34 +0000 Subject: [PATCH] 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. --- sys/geom/part/g_part.c | 77 +++++++++++++++++++++++++++++++++++++- sys/geom/part/g_part.h | 4 +- sys/geom/part/g_part_if.m | 10 ++++- sys/geom/part/g_part_mbr.c | 44 +++++++++++++++++++++- 4 files changed, 130 insertions(+), 5 deletions(-) diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index 68b2515277f3..4650b4ac25e6 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002, 2005, 2006, 2007 Marcel Moolenaar + * Copyright (c) 2002, 2005-2008 Marcel Moolenaar * All rights reserved. * * 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_RECOVER, 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); } +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 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; } 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': if (!strcmp(verb, "undo")) { ctlreq = G_PART_CTL_UNDO; mparms |= G_PART_PARM_GEOM; 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; } @@ -1147,6 +1207,10 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb) ap = &req->arg[i]; parm = 0; switch (ap->name[0]) { + case 'a': + if (!strcmp(ap->name, "attrib")) + parm = G_PART_PARM_ATTRIB; + break; case 'b': if (!strcmp(ap->name, "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; } switch (parm) { + case G_PART_PARM_ATTRIB: + error = g_part_parm_str(p, &gpp.gpp_attrib); + break; case G_PART_PARM_BOOTCODE: gpp.gpp_codeptr = p; 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: error = g_part_ctl_resize(req, &gpp); break; + case G_PART_CTL_SET: + error = g_part_ctl_setunset(req, &gpp, 1); + break; case G_PART_CTL_UNDO: error = g_part_ctl_undo(req, &gpp); break; + case G_PART_CTL_UNSET: + error = g_part_ctl_setunset(req, &gpp, 0); + break; } /* Implement automatic commit. */ diff --git a/sys/geom/part/g_part.h b/sys/geom/part/g_part.h index 196332a1e527..94e17148857c 100644 --- a/sys/geom/part/g_part.h +++ b/sys/geom/part/g_part.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2006, 2007 Marcel Moolenaar + * Copyright (c) 2006-2008 Marcel Moolenaar * All rights reserved. * * 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_VERSION 0x0800 #define G_PART_PARM_BOOTCODE 0x1000 +#define G_PART_PARM_ATTRIB 0x2000 struct g_part_parms { unsigned int gpp_parms; @@ -152,6 +153,7 @@ struct g_part_parms { unsigned int gpp_version; const void *gpp_codeptr; unsigned int gpp_codesize; + const char *gpp_attrib; }; void g_part_geometry_heads(off_t, u_int, off_t *, u_int *); diff --git a/sys/geom/part/g_part_if.m b/sys/geom/part/g_part_if.m index bd3885435c89..2a0a1829f03a 100644 --- a/sys/geom/part/g_part_if.m +++ b/sys/geom/part/g_part_if.m @@ -1,5 +1,5 @@ #- -# Copyright (c) 2006, 2007 Marcel Moolenaar +# Copyright (c) 2006-2008 Marcel Moolenaar # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -108,6 +108,14 @@ METHOD int read { 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. # Preferrably, the alias names. METHOD const char * type { diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index 89877803197c..9e3e809c7d51 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2007 Marcel Moolenaar + * Copyright (c) 2007, 2008 Marcel Moolenaar * All rights reserved. * * 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); 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_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 *, char *, size_t); 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_probe, g_part_mbr_probe), 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_write, g_part_mbr_write), { 0, 0 } @@ -262,6 +265,8 @@ g_part_mbr_dumpconf(struct g_part_table *table, struct g_part_entry *baseentry, /* confxml: partition entry information */ sbuf_printf(sb, "%s%u\n", indent, entry->ent.dp_typ); + if (entry->ent.dp_flag & 0x80) + sbuf_printf(sb, "%sactive\n", indent); } else { /* confxml: scheme information */ } @@ -420,6 +425,43 @@ g_part_mbr_read(struct g_part_table *basetable, struct g_consumer *cp) 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 * g_part_mbr_type(struct g_part_table *basetable, struct g_part_entry *baseentry, char *buf, size_t bufsz)