Implement "force" (-F) option for gpart destroy verb.
This option doesn't passed to kernel and handled in user-space. With -F option gpart creates new "delete" request for each partition in table. Each request has flags="X" that disables auto-commit feature. Last request is the original "destroy" request. It has own flags and can have disabled or enabled auto-commit feature. If error is occurred when deleting partitions, then new "undo" request is created and all changes will be rolled back. Approved by: kib (mentor)
This commit is contained in:
parent
93ea4a71bf
commit
6305a96c20
@ -67,6 +67,7 @@ static char ssize[32];
|
||||
#define GPART_PARAM_BOOTCODE "bootcode"
|
||||
#define GPART_PARAM_INDEX "index"
|
||||
#define GPART_PARAM_PARTCODE "partcode"
|
||||
#define GPART_PARAM_FORCE "force"
|
||||
|
||||
static struct gclass *find_class(struct gmesh *, const char *);
|
||||
static struct ggeom * find_geom(struct gclass *, const char *);
|
||||
@ -84,6 +85,8 @@ static void gpart_show_geom(struct ggeom *, const char *);
|
||||
static int gpart_show_hasopt(struct gctl_req *, const char *, const char *);
|
||||
static void gpart_write_partcode(struct ggeom *, int, void *, ssize_t);
|
||||
static void gpart_write_partcode_vtoc8(struct ggeom *, int, void *);
|
||||
static void gpart_destroy(struct gctl_req *, unsigned int);
|
||||
static void gpart_print_error(const char *);
|
||||
|
||||
struct g_command PUBSYM(class_commands)[] = {
|
||||
{ "add", 0, gpart_issue, {
|
||||
@ -120,10 +123,11 @@ struct g_command PUBSYM(class_commands)[] = {
|
||||
G_OPT_SENTINEL },
|
||||
"-i index [-f flags] geom"
|
||||
},
|
||||
{ "destroy", 0, gpart_issue, {
|
||||
{ "destroy", 0, gpart_destroy, {
|
||||
{ 'F', GPART_PARAM_FORCE, NULL, G_TYPE_BOOL },
|
||||
{ 'f', "flags", GPART_FLAGS, G_TYPE_STRING },
|
||||
G_OPT_SENTINEL },
|
||||
"[-f flags] geom"
|
||||
"[-F] [-f flags] geom"
|
||||
},
|
||||
{ "modify", 0, gpart_issue, {
|
||||
{ 'i', GPART_PARAM_INDEX, NULL, G_TYPE_NUMBER },
|
||||
@ -853,11 +857,105 @@ gpart_bootcode(struct gctl_req *req, unsigned int fl)
|
||||
geom_deletetree(&mesh);
|
||||
}
|
||||
|
||||
static void
|
||||
gpart_destroy(struct gctl_req *req, unsigned int fl)
|
||||
{
|
||||
struct gmesh mesh;
|
||||
struct gclass *classp;
|
||||
struct gctl_req *req2;
|
||||
struct ggeom *gp;
|
||||
struct gprovider *pp;
|
||||
const char *s;
|
||||
int error, val;
|
||||
intmax_t idx;
|
||||
|
||||
if (gctl_has_param(req, GPART_PARAM_FORCE)) {
|
||||
val = gctl_get_int(req, GPART_PARAM_FORCE);
|
||||
error = gctl_delete_param(req, GPART_PARAM_FORCE);
|
||||
if (error)
|
||||
errc(EXIT_FAILURE, error, "internal error");
|
||||
if (val == 0)
|
||||
goto done;
|
||||
s = gctl_get_ascii(req, "class");
|
||||
if (s == NULL)
|
||||
abort();
|
||||
error = geom_gettree(&mesh);
|
||||
if (error != 0)
|
||||
errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
|
||||
classp = find_class(&mesh, s);
|
||||
if (classp == NULL) {
|
||||
geom_deletetree(&mesh);
|
||||
errx(EXIT_FAILURE, "Class %s not found.", s);
|
||||
}
|
||||
s = gctl_get_ascii(req, "arg0");
|
||||
if (s == NULL)
|
||||
abort();
|
||||
gp = find_geom(classp, s);
|
||||
if (gp == NULL)
|
||||
errx(EXIT_FAILURE, "No such geom: %s.", s);
|
||||
val = 0;
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider){
|
||||
s = find_provcfg(pp, "index");
|
||||
if (s == NULL)
|
||||
errx(EXIT_FAILURE, "Index not found for %s.",
|
||||
pp->lg_name);
|
||||
idx = strtoimax(s, NULL, 0);
|
||||
req2 = gctl_get_handle();
|
||||
gctl_ro_param(req2, "class", -1, classp->lg_name);
|
||||
gctl_ro_param(req2, "arg0", -1, gp->lg_name);
|
||||
gctl_ro_param(req2, "verb", -1, "delete");
|
||||
gctl_ro_param(req2, GPART_PARAM_INDEX,
|
||||
sizeof(intmax_t), &idx);
|
||||
gctl_ro_param(req2, "flags", -1, "X");
|
||||
s = gctl_issue(req2);
|
||||
if (s != NULL && s[0] != '\0') {
|
||||
gpart_print_error(s);
|
||||
gctl_free(req2);
|
||||
if (val) { /* try to undo changes */
|
||||
req2 = gctl_get_handle();
|
||||
gctl_ro_param(req2, "verb", -1,
|
||||
"undo");
|
||||
gctl_ro_param(req2, "class", -1,
|
||||
classp->lg_name);
|
||||
gctl_ro_param(req2, "arg0", -1,
|
||||
gp->lg_name);
|
||||
gctl_issue(req2);
|
||||
gctl_free(req2);
|
||||
}
|
||||
geom_deletetree(&mesh);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
gctl_free(req2);
|
||||
val = 1;
|
||||
}
|
||||
geom_deletetree(&mesh);
|
||||
}
|
||||
done:
|
||||
gpart_issue(req, fl);
|
||||
}
|
||||
|
||||
static void
|
||||
gpart_print_error(const char *errstr)
|
||||
{
|
||||
char *errmsg;
|
||||
int error;
|
||||
|
||||
error = strtol(errstr, &errmsg, 0);
|
||||
if (errmsg != errstr) {
|
||||
while (errmsg[0] == ' ')
|
||||
errmsg++;
|
||||
if (errmsg[0] != '\0')
|
||||
warnc(error, "%s", errmsg);
|
||||
else
|
||||
warnc(error, NULL);
|
||||
} else
|
||||
warnx("%s", errmsg);
|
||||
}
|
||||
|
||||
static void
|
||||
gpart_issue(struct gctl_req *req, unsigned int fl __unused)
|
||||
{
|
||||
char buf[4096];
|
||||
char *errmsg;
|
||||
const char *errstr;
|
||||
int error, status;
|
||||
|
||||
@ -883,17 +981,7 @@ gpart_issue(struct gctl_req *req, unsigned int fl __unused)
|
||||
goto done;
|
||||
}
|
||||
|
||||
error = strtol(errstr, &errmsg, 0);
|
||||
if (errmsg != errstr) {
|
||||
while (errmsg[0] == ' ')
|
||||
errmsg++;
|
||||
if (errmsg[0] != '\0')
|
||||
warnc(error, "%s", errmsg);
|
||||
else
|
||||
warnc(error, NULL);
|
||||
} else
|
||||
warnx("%s", errmsg);
|
||||
|
||||
gpart_print_error(errstr);
|
||||
status = EXIT_FAILURE;
|
||||
|
||||
done:
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 27, 2010
|
||||
.Dd Sep 24, 2010
|
||||
.Dt GPART 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -118,6 +118,7 @@ utility:
|
||||
.\" ==== DESTROY ====
|
||||
.Nm
|
||||
.Cm destroy
|
||||
.Op Fl F
|
||||
.Op Fl f Ar flags
|
||||
.Ar geom
|
||||
.\" ==== MODIFY ====
|
||||
@ -317,6 +318,8 @@ Destroy the partitioning scheme as implemented by geom
|
||||
.Pp
|
||||
Additional options include:
|
||||
.Bl -tag -width 10n
|
||||
.It Fl F
|
||||
Forced destroying of the partition table even if it is not empty.
|
||||
.It Fl f Ar flags
|
||||
Additional operational flags.
|
||||
See the section entitled
|
||||
|
Loading…
Reference in New Issue
Block a user