[TEST/REVIEW] boot0cfg/fdisk issue fix
Poul-Henning Kamp
phk at phk.freebsd.dk
Tue Jul 5 20:44:54 GMT 2005
This is an attempt to fix an boot0cfg/fdisk issue which I have
overlooked.
The patch adds a g_ctl method to geom_mbr and makes boot0cfg and
fdisk use it to modify the MBR if possible.
Please test and report ASAP in order to get this solution into
RELENG_6
Index: sys/geom/geom_mbr.c
===================================================================
RCS file: /home/ncvs/src/sys/geom/geom_mbr.c,v
retrieving revision 1.65
diff -u -r1.65 geom_mbr.c
--- sys/geom/geom_mbr.c 14 Mar 2005 15:22:18 -0000 1.65
+++ sys/geom/geom_mbr.c 5 Jul 2005 20:40:34 -0000
@@ -315,11 +315,54 @@
return (gp);
}
+static void
+g_mbr_config(struct gctl_req *req, struct g_class *mp, const char *verb)
+{
+ struct g_geom *gp;
+ struct g_consumer *cp;
+ struct g_mbr_softc *ms;
+ struct g_slicer *gsp;
+ int opened = 0, error = 0;
+ void *data;
+
+ g_topology_assert();
+ gp = gctl_get_geom(req, mp, "geom");
+ if (gp == NULL)
+ return;
+ if (strcmp(verb, "write sector zero")) {
+ gctl_error(req, "Unknown verb");
+ return;
+ }
+ gsp = gp->softc;
+ ms = gsp->softc;
+ data = gctl_get_paraml(req, "data", 512);
+ if (data == NULL)
+ return;
+ cp = LIST_FIRST(&gp->consumer);
+ if (cp->acw == 0) {
+ error = g_access(cp, 0, 1, 0);
+ if (error == 0)
+ opened = 1;
+ }
+ if (!error)
+ error = g_mbr_modify(gp, ms, data);
+ if (error)
+ gctl_error(req, "conflict with open slices");
+ if (!error)
+ error = g_write_data(cp, 0, data, 512);
+ if (error)
+ gctl_error(req, "sector zero write failed");
+ if (opened)
+ g_access(cp, 0, -1 , 0);
+ return;
+}
+
static struct g_class g_mbr_class = {
.name = MBR_CLASS_NAME,
.version = G_VERSION,
.taste = g_mbr_taste,
.dumpconf = g_mbr_dumpconf,
+ .ctlreq = g_mbr_config,
.ioctl = g_mbr_ioctl,
};
Index: sbin/fdisk/Makefile
===================================================================
RCS file: /home/ncvs/src/sbin/fdisk/Makefile,v
retrieving revision 1.11
diff -u -r1.11 Makefile
--- sbin/fdisk/Makefile 23 Feb 2004 20:13:51 -0000 1.11
+++ sbin/fdisk/Makefile 5 Jul 2005 20:28:05 -0000
@@ -7,6 +7,9 @@
.PATH: ${.CURDIR}/../../sys/geom
+DPADD += ${LIBGEOM}
+LDADD += -lgeom
+
.include <bsd.prog.mk>
test: ${PROG}
Index: sbin/fdisk/fdisk.c
===================================================================
RCS file: /home/ncvs/src/sbin/fdisk/fdisk.c,v
retrieving revision 1.79
diff -u -r1.79 fdisk.c
--- sbin/fdisk/fdisk.c 1 May 2005 09:50:02 -0000 1.79
+++ sbin/fdisk/fdisk.c 5 Jul 2005 20:36:58 -0000
@@ -38,6 +38,7 @@
#include <fcntl.h>
#include <err.h>
#include <errno.h>
+#include <libgeom.h>
#include <paths.h>
#include <regex.h>
#include <stdint.h>
@@ -80,7 +81,7 @@
};
static struct mboot mboot;
-static int fd, fdw;
+static int fd;
#define ACTIVE 0x80
@@ -226,7 +227,7 @@
static void dos(struct dos_partition *partp);
static int open_disk(int flag);
static ssize_t read_disk(off_t sector, void *buf);
-static ssize_t write_disk(off_t sector, void *buf);
+static int write_disk(off_t sector, void *buf);
static int get_params(void);
static int read_s0(void);
static int write_s0(void);
@@ -692,10 +693,8 @@
open_disk(int flag)
{
struct stat st;
- int rwmode, p;
- char *s;
+ int rwmode;
- fdw = -1;
if (stat(disk, &st) == -1) {
if (errno == ENOENT)
return -2;
@@ -706,23 +705,10 @@
warnx("device %s is not character special", disk);
rwmode = a_flag || I_flag || B_flag || flag ? O_RDWR : O_RDONLY;
fd = open(disk, rwmode);
+ if (fd == -1 && errno == EPERM && rwmode == O_RDWR)
+ fd = open(disk, O_RDONLY);
if (fd == -1 && errno == ENXIO)
return -2;
- if (fd == -1 && errno == EPERM && rwmode == O_RDWR) {
- fd = open(disk, O_RDONLY);
- if (fd == -1)
- return -3;
- for (p = 0; p < NDOSPART; p++) {
- asprintf(&s, "%ss%d", disk, p + 1);
- fdw = open(s, rwmode);
- free(s);
- if (fdw == -1)
- continue;
- break;
- }
- if (fdw == -1)
- return -4;
- }
if (fd == -1) {
warnx("can't open device %s", disk);
return -1;
@@ -755,17 +741,46 @@
return -1;
}
-static ssize_t
+static int
write_disk(off_t sector, void *buf)
{
-
- if (fdw != -1) {
- return ioctl(fdw, DIOCSMBR, buf);
- } else {
- lseek(fd, (sector * 512), 0);
- /* write out in the size that the read_disk found worked */
- return write(fd, buf, secsize);
+ int error;
+ struct gctl_req *grq;
+ const char *q;
+ char fbuf[BUFSIZ];
+ int i, fdw;
+
+ grq = gctl_get_handle();
+ gctl_ro_param(grq, "verb", -1, "write sector zero");
+ gctl_ro_param(grq, "class", -1, "MBR");
+ q = strrchr(disk, '/');
+ if (q == NULL)
+ q = disk;
+ else
+ q++;
+ gctl_ro_param(grq, "geom", -1, q);
+ gctl_ro_param(grq, "data", secsize, buf);
+ q = gctl_issue(grq);
+ if (q == NULL)
+ return(0);
+ warnx("%s", q);
+
+ 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)
+ return (0);
}
+ warnx("Failed to write sector zero");
+ return(EINVAL);
}
static int
Index: usr.sbin/boot0cfg/Makefile
===================================================================
RCS file: /home/ncvs/src/usr.sbin/boot0cfg/Makefile,v
retrieving revision 1.8
diff -u -r1.8 Makefile
--- usr.sbin/boot0cfg/Makefile 4 Apr 2003 17:49:12 -0000 1.8
+++ usr.sbin/boot0cfg/Makefile 5 Jul 2005 20:06:42 -0000
@@ -5,4 +5,7 @@
WARNS?= 2
+DPADD= ${LIBGEOM}
+LDADD= -lgeom
+
.include <bsd.prog.mk>
Index: usr.sbin/boot0cfg/boot0cfg.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/boot0cfg/boot0cfg.c,v
retrieving revision 1.19
diff -u -r1.19 boot0cfg.c
--- usr.sbin/boot0cfg/boot0cfg.c 18 Dec 2004 11:04:10 -0000 1.19
+++ usr.sbin/boot0cfg/boot0cfg.c 5 Jul 2005 20:19:31 -0000
@@ -35,6 +35,7 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <libgeom.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
@@ -256,6 +257,8 @@
int fd, p;
ssize_t n;
char *s;
+ const char *q;
+ struct gctl_req *grq;
fd = open(fname, O_WRONLY | flags, 0666);
if (fd != -1) {
@@ -265,12 +268,30 @@
errx(1, "%s: short write", fname);
return;
}
+
if (flags != 0)
err(1, "%s", fname);
+ grq = gctl_get_handle();
+ gctl_ro_param(grq, "verb", -1, "write sector zero");
+ gctl_ro_param(grq, "class", -1, "MBR");
+ q = strrchr(fname, '/');
+ if (q == NULL)
+ q = fname;
+ else
+ q++;
+ gctl_ro_param(grq, "geom", -1, q);
+ gctl_ro_param(grq, "data", mbr_size, mbr);
+ q = gctl_issue(grq);
+ if (q == NULL)
+ return;
+
+ warnx("%s: %s", fname, q);
+ gctl_free(grq);
+
#ifdef DIOCSMBR
for (p = 1; p < 5; p++) {
asprintf(&s, "%ss%d", fname, p);
- fd = open(s, O_RDWR);
+ fd = open(s, O_RDONLY);
if (fd < 0) {
free(s);
continue;
--
Poul-Henning Kamp | UNIX since Zilog Zeus 3.20
phk at FreeBSD.ORG | TCP/IP since RFC 956
FreeBSD committer | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.
More information about the freebsd-current
mailing list