On Sat, 5 Oct 2002, Ian Dowse wrote:

> >The divide by zero problem seems to be caused by an interaction
> >between two bugs: GEOM refuses to return the sector size because
> ...
> >The next failure I get is:
> >
> >     Can't write config to /dev/da1s1d, error 45 (EOPNOTSUPP)
> 
> This turns out to be vinum doing a DIOCWLABEL to make the label writable
> before writing its configuration, but GEOM does not support that ioctl I
> presume. It should be safe to ignore these DIOCWLABEL ioctl return
> values as the actual writing of the vinum data should give a suitable
> error if making the label writable fails and is important. The patch
> below is Robert's patch with all 3 other issues fixed, and together,
> this seems to be enough to make vinum work again. 

Wonderful.  I just committed a fix so that vinum.ko can be unloaded
without a panic when WITNESS is present.  I'll give the combined patch a
spin on my crashbox and see if it does the trick here.  Thanks!

Robert N M Watson             FreeBSD Core Team, TrustedBSD Projects
[EMAIL PROTECTED]      Network Associates Laboratories

> Index: vinumio.c
> ===================================================================
> RCS file: /dump/FreeBSD-CVS/src/sys/dev/vinum/vinumio.c,v
> retrieving revision 1.75
> diff -u -r1.75 vinumio.c
> --- vinumio.c 21 Aug 2002 23:39:51 -0000      1.75
> +++ vinumio.c 5 Oct 2002 02:40:18 -0000
> @@ -50,92 +50,25 @@
>  int
>  open_drive(struct drive *drive, struct thread *td, int verbose)
>  {
> -    int devmajor;                                        /* major devs for disk 
>device */
> -    int devminor;                                        /* minor devs for disk 
>device */
> -    int unit;
> -    char *dname;
> +    struct nameidata nd;
>      struct cdevsw *dsw;                                          /* pointer to 
>cdevsw entry */
> +    int error;
>  
> -    if (bcmp(drive->devicename, "/dev/", 5))             /* device name doesn't 
>start with /dev */
> -     return ENOENT;                                      /* give up */
>      if (drive->flags & VF_OPEN)                                  /* open already, */
>       return EBUSY;                                       /* don't do it again */
>  
> -    /*
> -     * Yes, Bruce, I know this is horrible, but we
> -     * don't have a root filesystem when we first
> -     * try to do this.  If you can come up with a
> -     * better solution, I'd really like it.  I'm
> -     * just putting it in now to add ammuntion to
> -     * moving the system to devfs.
> -     */
> -    dname = &drive->devicename[5];
> -    drive->dev = NULL;                                           /* no device yet */
> -
> -    /* Find the device */
> -    if (bcmp(dname, "ad", 2) == 0)                       /* IDE disk */
> -     devmajor = 116;
> -    else if (bcmp(dname, "wd", 2) == 0)                          /* IDE disk */
> -     devmajor = 3;
> -    else if (bcmp(dname, "da", 2) == 0)
> -     devmajor = 13;
> -    else if (bcmp(dname, "vn", 2) == 0)
> -     devmajor = 43;
> -    else if (bcmp(dname, "md", 2) == 0)
> -     devmajor = 95;
> -    else if (bcmp(dname, "ar", 2) == 0)
> -        devmajor = 157;
> -    else if (bcmp(dname, "amrd", 4) == 0) {
> -     devmajor = 133;
> -     dname += 2;
> -    } else if (bcmp(dname, "mlxd", 4) == 0) {
> -     devmajor = 131;
> -     dname += 2;
> -    } else if (bcmp(dname, "idad", 4) == 0) {
> -     devmajor = 109;
> -     dname += 2;
> -    } else if (bcmp(dname, "twed", 4) == 0) {               /* 3ware raid */
> -      devmajor = 147;
> -      dname += 2;
> -    } else
> -      return ENODEV;
> -    dname += 2;                                                  /* point past */
> -
> -    /*
> -     * Found the device.  We can expect one of
> -     * two formats for the rest: a unit number,
> -     * then either a partition letter for the
> -     * compatiblity partition (e.g. h) or a
> -     * slice ID and partition (e.g. s2e).
> -     * Create a minor number for each of them.
> -     */
> -    unit = 0;
> -    while ((*dname >= '0')                               /* unit number */
> -    &&(*dname <= '9')) {
> -     unit = unit * 10 + *dname - '0';
> -     dname++;
> -    }
> -
> -    if (*dname == 's') {                                 /* slice */
> -     if (((dname[1] < '1') || (dname[1] > '4'))          /* invalid slice */
> -     ||((dname[2] < 'a') || (dname[2] > 'h')))           /* or invalid partition */
> -         return ENODEV;
> -     devminor = ((unit & 31) << 3)                       /* unit */
> -     +(dname[2] - 'a')                                   /* partition */
> -     +((dname[1] - '0' + 1) << 16)                       /* slice */
> -     +((unit & ~31) << 16);                              /* high-order unit bits */
> -    } else {                                             /* compatibility partition 
>*/
> -     if ((*dname < 'a') || (*dname > 'h'))               /* or invalid partition */
> -         return ENODEV;
> -     devminor = (*dname - 'a')                           /* partition */
> -     +((unit & 31) << 3)                                 /* unit */
> -     +((unit & ~31) << 16);                              /* high-order unit bits */
> +    NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, drive->devicename,
> +        curthread);
> +    error = namei(&nd);
> +    if (error)
> +     return (error);
> +    if (!vn_isdisk(nd.ni_vp, &error)) {
> +     NDFREE(&nd, 0);
> +     return (error);
>      }
> +    drive->dev = udev2dev(nd.ni_vp->v_rdev->si_udev, 0);
> +    NDFREE(&nd, 0);
>  
> -    if ((devminor & 7) == 2)                             /* partition c */
> -     return ENOTTY;                                      /* not buying that */
> -
> -    drive->dev = makedev(devmajor, devminor);                    /* find the device 
>*/
>      if (drive->dev == NULL)                              /* didn't find anything */
>       return ENODEV;
>  
> @@ -144,7 +77,7 @@
>      if (dsw == NULL)
>       drive->lasterror = ENOENT;
>      else
> -     drive->lasterror = (dsw->d_open) (drive->dev, FWRITE, 0, NULL);
> +     drive->lasterror = (dsw->d_open) (drive->dev, FWRITE | FREAD, 0, NULL);
>  
>      if (drive->lasterror != 0) {                         /* failed */
>       drive->state = drive_down;                          /* just force it down */
> @@ -278,13 +211,17 @@
>  void
>  close_locked_drive(struct drive *drive)
>  {
> +    int error;
> +
>      /*
>       * If we can't access the drive, we can't flush
>       * the queues, which spec_close() will try to
>       * do.  Get rid of them here first.
>       */
> -    drive->lasterror = (*devsw(drive->dev)->d_close) (drive->dev, 0, 0, NULL);
> +    error = (*devsw(drive->dev)->d_close) (drive->dev, 0, 0, NULL);
>      drive->flags &= ~VF_OPEN;                                    /* no longer open 
>*/
> +    if (drive->lasterror == 0)
> +     drive->lasterror = error;
>  }
>  
>  /*
> @@ -678,20 +615,18 @@
>               if ((drive->state != drive_unallocated)
>                   && (drive->state != drive_referenced)) { /* and it's a real drive 
>*/
>                   wlabel_on = 1;                          /* enable writing the 
>label */
> -                 error = (*devsw(drive->dev)->d_ioctl) (drive->dev, /* make the 
>label writeable */
> +                 (void) (*devsw(drive->dev)->d_ioctl) (drive->dev, /* make the 
>label writeable */
>                       DIOCWLABEL,
>                       (caddr_t) & wlabel_on,
>                       FWRITE,
>                       curthread);
> -                 if (error == 0)
> -                     error = write_drive(drive, (char *) vhdr, VINUMHEADERLEN, 
>VINUM_LABEL_OFFSET);
> +                 error = write_drive(drive, (char *) vhdr, VINUMHEADERLEN, 
>VINUM_LABEL_OFFSET);
>                   if (error == 0)
>                       error = write_drive(drive, config, MAXCONFIG, 
>VINUM_CONFIG_OFFSET); /* first config copy */
>                   if (error == 0)
>                       error = write_drive(drive, config, MAXCONFIG, 
>VINUM_CONFIG_OFFSET + MAXCONFIG); /* second copy */
>                   wlabel_on = 0;                          /* enable writing the 
>label */
> -                 if (error == 0)
> -                     error = (*devsw(drive->dev)->d_ioctl) (drive->dev, /* make the 
>label non-writeable again */
> +                 (void) (*devsw(drive->dev)->d_ioctl) (drive->dev, /* make the 
>label non-writeable again */
>                           DIOCWLABEL,
>                           (caddr_t) & wlabel_on,
>                           FWRITE,
> 


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to