summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2008-06-18 01:13:34 +0000
committermarcel <marcel@FreeBSD.org>2008-06-18 01:13:34 +0000
commit1fee86b4dc8e173a05f104332711818c58f3b894 (patch)
tree91fc1b7cc4b65705836c11f19a911650e1440078
parent4cbff60e70193c5d4747899ced3384fcaec94049 (diff)
downloadFreeBSD-src-1fee86b4dc8e173a05f104332711818c58f3b894.zip
FreeBSD-src-1fee86b4dc8e173a05f104332711818c58f3b894.tar.gz
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.
-rw-r--r--sys/geom/part/g_part.c77
-rw-r--r--sys/geom/part/g_part.h4
-rw-r--r--sys/geom/part/g_part_if.m10
-rw-r--r--sys/geom/part/g_part_mbr.c44
4 files changed, 130 insertions, 5 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index 68b2515..4650b4a 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
};
/*
@@ -954,6 +956,53 @@ g_part_ctl_resize(struct gctl_req *req, struct g_part_parms *gpp)
}
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)
{
struct g_consumer *cp;
@@ -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 196332a..94e1714 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 bd38854..2a0a182 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 8987780..9e3e809 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<rawtype>%u</rawtype>\n", indent,
entry->ent.dp_typ);
+ if (entry->ent.dp_flag & 0x80)
+ sbuf_printf(sb, "%s<attrib>active</attrib>\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)
OpenPOWER on IntegriCloud