summaryrefslogtreecommitdiffstats
path: root/sys/geom/part
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 /sys/geom/part
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.
Diffstat (limited to 'sys/geom/part')
-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