Improve error reporting when MBR can not be written.
Remove obsolete code which uses DIOCSMBR ioctl. When writing MBR first check that GEOM_MBR is available, if it is not available, then try write MBR directly to provider. If both are failed, then recommend to use gpart(8). MFC after: 2 week
This commit is contained in:
parent
add89852d6
commit
fd1ca22afb
@ -232,6 +232,7 @@ get_type(int t)
|
||||
}
|
||||
|
||||
|
||||
static int geom_class_available(const char *);
|
||||
static void print_s0(void);
|
||||
static void print_part(const struct dos_partition *);
|
||||
static void init_sector0(unsigned long start);
|
||||
@ -768,50 +769,75 @@ read_disk(off_t sector, void *buf)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
geom_class_available(const char *name)
|
||||
{
|
||||
struct gclass *class;
|
||||
struct gmesh mesh;
|
||||
int error;
|
||||
|
||||
error = geom_gettree(&mesh);
|
||||
if (error != 0)
|
||||
errc(1, error, "Cannot get GEOM tree");
|
||||
|
||||
LIST_FOREACH(class, &mesh.lg_class, lg_class) {
|
||||
if (strcmp(class->lg_name, name) == 0) {
|
||||
geom_deletetree(&mesh);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
geom_deletetree(&mesh);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
write_disk(off_t sector, void *buf)
|
||||
{
|
||||
int error;
|
||||
struct gctl_req *grq;
|
||||
const char *errmsg;
|
||||
char fbuf[BUFSIZ], *pname;
|
||||
int i, fdw;
|
||||
char *pname;
|
||||
int error;
|
||||
|
||||
grq = gctl_get_handle();
|
||||
gctl_ro_param(grq, "verb", -1, "write MBR");
|
||||
gctl_ro_param(grq, "class", -1, "MBR");
|
||||
pname = g_providername(fd);
|
||||
if (pname == NULL) {
|
||||
warn("Error getting providername for %s", disk);
|
||||
return (-1);
|
||||
}
|
||||
gctl_ro_param(grq, "geom", -1, pname);
|
||||
gctl_ro_param(grq, "data", secsize, buf);
|
||||
errmsg = gctl_issue(grq);
|
||||
free(pname);
|
||||
if (errmsg == NULL) {
|
||||
/* Check that GEOM_MBR is available */
|
||||
if (geom_class_available("MBR") != 0) {
|
||||
grq = gctl_get_handle();
|
||||
gctl_ro_param(grq, "verb", -1, "write MBR");
|
||||
gctl_ro_param(grq, "class", -1, "MBR");
|
||||
pname = g_providername(fd);
|
||||
if (pname == NULL) {
|
||||
warn("Error getting providername for %s", disk);
|
||||
return (-1);
|
||||
}
|
||||
gctl_ro_param(grq, "geom", -1, pname);
|
||||
gctl_ro_param(grq, "data", secsize, buf);
|
||||
errmsg = gctl_issue(grq);
|
||||
free(pname);
|
||||
if (errmsg == NULL) {
|
||||
gctl_free(grq);
|
||||
return(0);
|
||||
}
|
||||
if (!q_flag)
|
||||
warnx("GEOM_MBR: %s", errmsg);
|
||||
gctl_free(grq);
|
||||
return(0);
|
||||
}
|
||||
if (!q_flag) /* GEOM errors are benign, not all devices supported */
|
||||
warnx("%s", errmsg);
|
||||
gctl_free(grq);
|
||||
|
||||
error = pwrite(fd, buf, secsize, (sector * 512));
|
||||
if (error == secsize)
|
||||
return (0);
|
||||
|
||||
for (i = 1; i < 5; i++) {
|
||||
sprintf(fbuf, "%ss%d", disk, i);
|
||||
fdw = open(fbuf, O_RDWR, 0);
|
||||
if (fdw < 0)
|
||||
continue;
|
||||
error = ioctl(fdw, DIOCSMBR, buf);
|
||||
close(fdw);
|
||||
if (error == 0)
|
||||
} else {
|
||||
/* Try to write MBR directly. This may help when disk
|
||||
* is not in use.
|
||||
* XXX: hardcoded sectorsize
|
||||
*/
|
||||
error = pwrite(fd, buf, secsize, (sector * 512));
|
||||
if (error == secsize)
|
||||
return (0);
|
||||
}
|
||||
warnx("Failed to write sector zero");
|
||||
|
||||
/* GEOM_MBR is not available or failed to write MBR.
|
||||
* Now check that we have GEOM_PART and recommend to use gpart (8).
|
||||
*/
|
||||
if (geom_class_available("PART") != 0)
|
||||
warnx("Failed to write MBR. Try to use gpart(8).");
|
||||
else
|
||||
warnx("Failed to write sector zero");
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user