[TEST/REVIEW] boot0cfg/fdisk issue fix

From: Poul-Henning Kamp (phk_at_phk.freebsd.dk)
Date: 07/05/05

  • Next message: Poul-Henning Kamp: "Re: Summary: experiences with NanoBSD, successes and nits on a Soekris 4801"
    To: current@freebsd.org
    Date: Tue, 05 Jul 2005 22:44:50 +0200
    
    

    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@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.
    _______________________________________________
    freebsd-current@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-current
    To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org"
    

  • Next message: Poul-Henning Kamp: "Re: Summary: experiences with NanoBSD, successes and nits on a Soekris 4801"

    Relevant Pages