Merge from vendor branch FILE:
[dragonfly.git] / sys / kern / subr_disk.c
index d017977..ae17396 100644 (file)
@@ -77,7 +77,7 @@
  *     @(#)ufs_disksubr.c      8.5 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/subr_disk.c,v 1.20.2.6 2001/10/05 07:14:57 peter Exp $
  * $FreeBSD: src/sys/ufs/ufs/ufs_disksubr.c,v 1.44.2.3 2001/03/05 05:42:19 obrien Exp $
- * $DragonFly: src/sys/kern/subr_disk.c,v 1.15 2005/04/30 23:04:21 swildner Exp $
+ * $DragonFly: src/sys/kern/subr_disk.c,v 1.26 2006/09/10 01:26:39 dillon Exp $
  */
 
 #include <sys/param.h>
 
 static MALLOC_DEFINE(M_DISK, "disk", "disk data");
 
-static d_strategy_t diskstrategy;
 static d_open_t diskopen;
 static d_close_t diskclose; 
 static d_ioctl_t diskioctl;
+static d_strategy_t diskstrategy;
 static d_psize_t diskpsize;
 static d_clone_t diskclone;
-static int disk_putport(lwkt_port_t port, lwkt_msg_t msg);
+static d_dump_t diskdump;
 
 static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist);
 
+static struct dev_ops disk_ops = {
+       { "disk" },
+       .d_open = diskopen,
+       .d_close = diskclose,
+       .d_read = physread,
+       .d_write = physwrite,
+       .d_ioctl = diskioctl,
+       .d_strategy = diskstrategy,
+       .d_dump = diskdump,
+       .d_psize = diskpsize,
+       .d_clone = diskclone
+};
+
 /*
- * Create a slice and unit managed disk.
- *
- * Our port layer will be responsible for assigning pblkno and handling
- * high level partition operations, then forwarding the requests to the
- * raw device.
+ * Create a raw device for the dev_ops template (which is returned).  Also
+ * create a slice and unit managed disk and overload the user visible
+ * device space with it.
  *
- * The raw device (based on rawsw) is returned to the caller, NOT the
- * slice and unit managed cdev.  The caller typically sets various
- * driver parameters and IO limits on the returned rawdev which we must
- * inherit when our managed device is opened.
+ * NOTE: The returned raw device is NOT a slice and unit managed device.
+ * It is an actual raw device representing the raw disk as specified by
+ * the passed dev_ops.  The disk layer not only returns such a raw device,
+ * it also uses it internally when passing (modified) commands through.
  */
-dev_t
-disk_create(int unit, struct disk *dp, int flags, struct cdevsw *rawsw)
+cdev_t
+disk_create(int unit, struct disk *dp, int flags, struct dev_ops *raw_ops)
 {
-       dev_t rawdev;
-       struct cdevsw *devsw;
+       cdev_t rawdev;
+       struct dev_ops *dev_ops;
 
        /*
         * Create the raw backing device
         */
-       compile_devsw(rawsw);
-       rawdev = make_dev(rawsw, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
+       compile_dev_ops(raw_ops);
+       rawdev = make_dev(raw_ops,
+                           dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
                            UID_ROOT, GID_OPERATOR, 0640,
-                           "%s%d", rawsw->d_name, unit);
+                           "%s%d", raw_ops->head.name, unit);
 
-       /*
-        * Initialize our intercept port
-        */
        bzero(dp, sizeof(*dp));
-       lwkt_initport(&dp->d_port, NULL);
-       dp->d_port.mp_putport = disk_putport;
-       dp->d_rawsw = rawsw;
 
        /*
         * We install a custom cdevsw rather then the passed cdevsw,
         * and save our disk structure in d_data so we can get at it easily
         * without any complex cloning code.
         */
-       devsw = cdevsw_add_override(rawdev, dkunitmask(), dkmakeunit(unit));
-       devsw->d_port = &dp->d_port;
-       devsw->d_data = dp;
-       devsw->d_clone = diskclone;
-       dp->d_devsw = devsw;
+       dev_ops = dev_ops_add_override(rawdev, &disk_ops,
+                                      dkunitmask(), dkmakeunit(unit));
+       dev_ops->head.data = dp;
+
        dp->d_rawdev = rawdev;
-       dp->d_cdev = make_dev(devsw, 
+       dp->d_raw_ops = raw_ops;
+       dp->d_dev_ops = dev_ops;
+       dp->d_cdev = make_dev(dev_ops, 
                            dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
                            UID_ROOT, GID_OPERATOR, 0640,
-                           "%s%d", devsw->d_name, unit);
+                           "%s%d", dev_ops->head.name, unit);
 
        dp->d_dsflags = flags;
        LIST_INSERT_HEAD(&disklist, dp, d_list);
@@ -175,20 +182,20 @@ disk_create(int unit, struct disk *dp, int flags, struct cdevsw *rawsw)
 void
 disk_destroy(struct disk *disk)
 {
-       if (disk->d_devsw) {
-           cdevsw_remove(disk->d_devsw, dkunitmask(), 
+       if (disk->d_dev_ops) {
+           dev_ops_remove(disk->d_dev_ops, dkunitmask(), 
                            dkmakeunit(dkunit(disk->d_cdev)));
            LIST_REMOVE(disk, d_list);
        }
-       if (disk->d_rawsw) {
-           destroy_all_dev(disk->d_rawsw, dkunitmask(), 
+       if (disk->d_raw_ops) {
+           destroy_all_devs(disk->d_raw_ops, dkunitmask(), 
                            dkmakeunit(dkunit(disk->d_rawdev)));
        }
        bzero(disk, sizeof(*disk));
 }
 
 int
-disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize)
+disk_dumpcheck(cdev_t dev, u_int *count, u_int *blkno, u_int *secsize)
 {
        struct disk *dp;
        struct disklabel *dl;
@@ -248,7 +255,8 @@ sysctl_disks(SYSCTL_HANDLER_ARGS)
                } else {
                        first = 0;
                }
-               error = SYSCTL_OUT(req, disk->d_rawdev->si_name, strlen(disk->d_rawdev->si_name));
+               error = SYSCTL_OUT(req, disk->d_rawdev->si_name,
+                                  strlen(disk->d_rawdev->si_name));
                if (error)
                        return error;
        }
@@ -259,123 +267,24 @@ sysctl_disks(SYSCTL_HANDLER_ARGS)
 SYSCTL_PROC(_kern, OID_AUTO, disks, CTLTYPE_STRING | CTLFLAG_RD, 0, NULL, 
     sysctl_disks, "A", "names of available disks");
 
-/*
- * The port intercept functions
- */
-static
-int
-disk_putport(lwkt_port_t port, lwkt_msg_t lmsg)
-{
-       struct disk *disk = (struct disk *)port;
-       cdevallmsg_t msg = (cdevallmsg_t)lmsg;
-       int error;
-
-       switch(msg->am_lmsg.ms_cmd.cm_op) {
-       case CDEV_CMD_OPEN:
-               error = diskopen(
-                           msg->am_open.msg.dev,
-                           msg->am_open.oflags,
-                           msg->am_open.devtype,
-                           msg->am_open.td);
-               break;
-       case CDEV_CMD_CLOSE:
-               error = diskclose(
-                           msg->am_close.msg.dev,
-                           msg->am_close.fflag,
-                           msg->am_close.devtype,
-                           msg->am_close.td);
-               break;
-       case CDEV_CMD_IOCTL:
-               error = diskioctl(
-                           msg->am_ioctl.msg.dev,
-                           msg->am_ioctl.cmd,
-                           msg->am_ioctl.data,
-                           msg->am_ioctl.fflag,
-                           msg->am_ioctl.td);
-               break;
-       case CDEV_CMD_STRATEGY:
-               diskstrategy(msg->am_strategy.bp);
-               error = 0;
-               break;
-       case CDEV_CMD_PSIZE:
-               msg->am_psize.result = diskpsize(msg->am_psize.msg.dev);
-               error = 0;      /* XXX */
-               break;
-       case CDEV_CMD_READ:
-               error = physio(msg->am_read.msg.dev, 
-                               msg->am_read.uio, msg->am_read.ioflag);
-               break;
-       case CDEV_CMD_WRITE:
-               error = physio(msg->am_write.msg.dev, 
-                               msg->am_write.uio, msg->am_write.ioflag);
-               break;
-       case CDEV_CMD_POLL:
-       case CDEV_CMD_KQFILTER:
-               error = ENODEV;
-       case CDEV_CMD_MMAP:
-               error = -1;
-               break;
-       case CDEV_CMD_DUMP:
-               error = disk_dumpcheck(msg->am_dump.msg.dev,
-                               &msg->am_dump.count,
-                               &msg->am_dump.blkno,
-                               &msg->am_dump.secsize);
-               if (error == 0) {
-                       msg->am_dump.msg.dev = disk->d_rawdev;
-                       error = lwkt_forwardmsg(disk->d_rawdev->si_port,
-                                               &msg->am_dump.msg.msg);
-                       printf("error2 %d\n", error);
-               }
-               break;
-       default:
-               error = ENOTSUP;
-               break;
-       }
-       return(error);
-}
-
-/*
- * When new device entries are instantiated, make sure they inherit our
- * si_disk structure and block and iosize limits from the raw device.
- *
- * This routine is always called synchronously in the context of the 
- * client.
- *
- * XXX The various io and block size constraints are not always initialized
- * properly by devices.
- */
-static
-int
-diskclone(dev_t dev)
-{
-       struct disk *dp;
-
-       dp = dev->si_devsw->d_data;
-       KKASSERT(dp != NULL);
-       dev->si_disk = dp;
-       dev->si_iosize_max = dp->d_rawdev->si_iosize_max;
-       dev->si_bsize_phys = dp->d_rawdev->si_bsize_phys;
-       dev->si_bsize_best = dp->d_rawdev->si_bsize_best;
-       return(0);
-}
-
 /*
  * Open a disk device or partition.
  */
 static
 int
-diskopen(dev_t dev, int oflags, int devtype, struct thread *td)
+diskopen(struct dev_open_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        struct disk *dp;
        int error;
 
        /*
         * dp can't be NULL here XXX.
         */
-       error = 0;
        dp = dev->si_disk;
        if (dp == NULL)
                return (ENXIO);
+       error = 0;
 
        /*
         * Deal with open races
@@ -396,22 +305,24 @@ diskopen(dev_t dev, int oflags, int devtype, struct thread *td)
                if (!pdev->si_iosize_max)
                        pdev->si_iosize_max = dev->si_iosize_max;
 #endif
-               error = dev_dopen(dp->d_rawdev, oflags, devtype, td);
+               error = dev_dopen(dp->d_rawdev, ap->a_oflags,
+                                 ap->a_devtype, ap->a_cred);
        }
 
        /*
         * Inherit properties from the underlying device now that it is
         * open.
         */
-       diskclone(dev);
+       dev_dclone(dev);
 
        if (error)
                goto out;
        
-       error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label);
+       error = dsopen(dev, ap->a_devtype, dp->d_dsflags,
+                      &dp->d_slice, &dp->d_label);
 
        if (!dsisopen(dp->d_slice)) 
-               dev_dclose(dp->d_rawdev, oflags, devtype, td);
+               dev_dclose(dp->d_rawdev, ap->a_oflags, ap->a_devtype);
 out:   
        dp->d_flags &= ~DISKFLAG_LOCK;
        if (dp->d_flags & DISKFLAG_WANTED) {
@@ -427,17 +338,41 @@ out:
  */
 static
 int
-diskclose(dev_t dev, int fflag, int devtype, struct thread *td)
+diskclose(struct dev_close_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        struct disk *dp;
        int error;
 
        error = 0;
        dp = dev->si_disk;
 
-       dsclose(dev, devtype, dp->d_slice);
+       dsclose(dev, ap->a_devtype, dp->d_slice);
        if (!dsisopen(dp->d_slice))
-               error = dev_dclose(dp->d_rawdev, fflag, devtype, td);
+               error = dev_dclose(dp->d_rawdev, ap->a_fflag, ap->a_devtype);
+       return (error);
+}
+
+/*
+ * First execute the ioctl on the disk device, and if it isn't supported 
+ * try running it on the backing device.
+ */
+static
+int
+diskioctl(struct dev_ioctl_args *ap)
+{
+       cdev_t dev = ap->a_head.a_dev;
+       struct disk *dp;
+       int error;
+
+       dp = dev->si_disk;
+       if (dp == NULL)
+               return (ENXIO);
+       error = dsioctl(dev, ap->a_cmd, ap->a_data, ap->a_fflag, &dp->d_slice);
+       if (error == ENOIOCTL) {
+               error = dev_dioctl(dp->d_rawdev, ap->a_cmd, ap->a_data,
+                                  ap->a_fflag, ap->a_cred);
+       }
        return (error);
 }
 
@@ -445,73 +380,97 @@ diskclose(dev_t dev, int fflag, int devtype, struct thread *td)
  * Execute strategy routine
  */
 static
-void
-diskstrategy(struct buf *bp)
+int
+diskstrategy(struct dev_strategy_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
+       struct bio *bio = ap->a_bio;
+       struct bio *nbio;
        struct disk *dp;
 
-       dp = bp->b_dev->si_disk;
+       dp = dev->si_disk;
 
        if (dp == NULL) {
-               bp->b_error = ENXIO;
-               bp->b_flags |= B_ERROR;
-               biodone(bp);
-               return;
+               bio->bio_buf->b_error = ENXIO;
+               bio->bio_buf->b_flags |= B_ERROR;
+               biodone(bio);
+               return(0);
        }
-       KKASSERT(bp->b_dev->si_disk == dp);
+       KKASSERT(dev->si_disk == dp);
 
-       if (dscheck(bp, dp->d_slice) <= 0) {
-               biodone(bp);
-               return;
-       }
-       bp->b_dev = dp->d_rawdev;
-       dev_dstrategy(dp->d_rawdev, bp);
+       /*
+        * The dscheck() function will also transform the slice relative
+        * block number i.e. bio->bio_offset into a block number that can be
+        * passed directly to the underlying raw device.  If dscheck()
+        * returns NULL it will have handled the bio for us (e.g. EOF
+        * or error due to being beyond the device size).
+        */
+       if ((nbio = dscheck(dev, bio, dp->d_slice)) != NULL)
+               dev_dstrategy(dp->d_rawdev, nbio);
+       else
+               biodone(bio);
+       return(0);
 }
 
 /*
- * First execute the ioctl on the disk device, and if it isn't supported 
- * try running it on the backing device.
+ * Return the partition size in ?blocks?
  */
 static
 int
-diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
+diskpsize(struct dev_psize_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        struct disk *dp;
-       int error;
 
        dp = dev->si_disk;
        if (dp == NULL)
-               return (ENXIO);
-
-       error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);
-       if (error == ENOIOCTL)
-               error = dev_dioctl(dp->d_rawdev, cmd, data, fflag, td);
-       return (error);
+               return(ENODEV);
+       ap->a_result = dssize(dev, &dp->d_slice);
+       return(0);
 }
 
 /*
+ * When new device entries are instantiated, make sure they inherit our
+ * si_disk structure and block and iosize limits from the raw device.
+ *
+ * This routine is always called synchronously in the context of the 
+ * client.
  *
+ * XXX The various io and block size constraints are not always initialized
+ * properly by devices.
  */
 static
 int
-diskpsize(dev_t dev)
+diskclone(struct dev_clone_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        struct disk *dp;
 
-       dp = dev->si_disk;
-       if (dp == NULL)
-               return (-1);
-       return(dssize(dev, &dp->d_slice));
-#if 0
-       if (dp != dev->si_disk) {
-               dev->si_drv1 = pdev->si_drv1;
-               dev->si_drv2 = pdev->si_drv2;
-               /* XXX: don't set bp->b_dev->si_disk (?) */
+       dp = dev->si_ops->head.data;
+       KKASSERT(dp != NULL);
+       dev->si_disk = dp;
+       dev->si_iosize_max = dp->d_rawdev->si_iosize_max;
+       dev->si_bsize_phys = dp->d_rawdev->si_bsize_phys;
+       dev->si_bsize_best = dp->d_rawdev->si_bsize_best;
+       return(0);
+}
+
+int
+diskdump(struct dev_dump_args *ap)
+{
+       cdev_t dev = ap->a_head.a_dev;
+       struct disk *dp = dev->si_ops->head.data;
+       int error;
+
+       error = disk_dumpcheck(dev, &ap->a_count, &ap->a_blkno, &ap->a_secsize);
+       if (error == 0) {
+               ap->a_head.a_dev = dp->d_rawdev;
+               error = dev_doperate(&ap->a_head);
        }
-#endif
+
+       return(error);
 }
 
-SYSCTL_DECL(_debug_sizeof);
 
 SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 
     0, sizeof(struct disklabel), "sizeof(struct disklabel)");
@@ -526,7 +485,7 @@ SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD,
 /*
  * Seek sort for disks.
  *
- * The buf_queue keep two queues, sorted in ascending block order.  The first
+ * The bio_queue keep two queues, sorted in ascending block order.  The first
  * queue holds those requests which are positioned after the current block
  * (in the first request); the second, which starts at queue->switch_point,
  * holds requests which came in after their block number was passed.  Thus
@@ -538,22 +497,22 @@ SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD,
  * allocated.
  */
 void
-bufqdisksort(struct buf_queue_head *bufq, struct buf *bp)
+bioqdisksort(struct bio_queue_head *bioq, struct bio *bio)
 {
-       struct buf *bq;
-       struct buf *bn;
-       struct buf *be;
+       struct bio *bq;
+       struct bio *bn;
+       struct bio *be;
        
-       be = TAILQ_LAST(&bufq->queue, buf_queue);
+       be = TAILQ_LAST(&bioq->queue, bio_queue);
        /*
         * If the queue is empty or we are an
         * ordered transaction, then it's easy.
         */
-       if ((bq = bufq_first(bufq)) == NULL || 
-           (bp->b_flags & B_ORDERED) != 0) {
-               bufq_insert_tail(bufq, bp);
+       if ((bq = bioq_first(bioq)) == NULL || 
+           (bio->bio_buf->b_flags & B_ORDERED) != 0) {
+               bioq_insert_tail(bioq, bio);
                return;
-       } else if (bufq->insert_point != NULL) {
+       } else if (bioq->insert_point != NULL) {
 
                /*
                 * A certain portion of the list is
@@ -561,7 +520,7 @@ bufqdisksort(struct buf_queue_head *bufq, struct buf *bp)
                 * we can only insert after the insert
                 * point.
                 */
-               bq = bufq->insert_point;
+               bq = bioq->insert_point;
        } else {
 
                /*
@@ -570,16 +529,15 @@ bufqdisksort(struct buf_queue_head *bufq, struct buf *bp)
                 * "locked" portion of the list, then we must add ourselves
                 * to the second request list.
                 */
-               if (bp->b_pblkno < bufq->last_pblkno) {
-
-                       bq = bufq->switch_point;
+               if (bio->bio_offset < bioq->last_offset) {
+                       bq = bioq->switch_point;
                        /*
                         * If we are starting a new secondary list,
                         * then it's easy.
                         */
                        if (bq == NULL) {
-                               bufq->switch_point = bp;
-                               bufq_insert_tail(bufq, bp);
+                               bioq->switch_point = bio;
+                               bioq_insert_tail(bioq, bio);
                                return;
                        }
                        /*
@@ -587,21 +545,21 @@ bufqdisksort(struct buf_queue_head *bufq, struct buf *bp)
                         * insert us before the switch point and move
                         * the switch point.
                         */
-                       if (bp->b_pblkno < bq->b_pblkno) {
-                               bufq->switch_point = bp;
-                               TAILQ_INSERT_BEFORE(bq, bp, b_act);
+                       if (bio->bio_offset < bq->bio_offset) {
+                               bioq->switch_point = bio;
+                               TAILQ_INSERT_BEFORE(bq, bio, bio_act);
                                return;
                        }
                } else {
-                       if (bufq->switch_point != NULL)
-                               be = TAILQ_PREV(bufq->switch_point,
-                                               buf_queue, b_act);
+                       if (bioq->switch_point != NULL)
+                               be = TAILQ_PREV(bioq->switch_point,
+                                               bio_queue, bio_act);
                        /*
-                        * If we lie between last_pblkno and bq,
+                        * If we lie between last_offset and bq,
                         * insert before bq.
                         */
-                       if (bp->b_pblkno < bq->b_pblkno) {
-                               TAILQ_INSERT_BEFORE(bq, bp, b_act);
+                       if (bio->bio_offset < bq->bio_offset) {
+                               TAILQ_INSERT_BEFORE(bq, bio, bio_act);
                                return;
                        }
                }
@@ -611,25 +569,25 @@ bufqdisksort(struct buf_queue_head *bufq, struct buf *bp)
         * Request is at/after our current position in the list.
         * Optimize for sequential I/O by seeing if we go at the tail.
         */
-       if (bp->b_pblkno > be->b_pblkno) {
-               TAILQ_INSERT_AFTER(&bufq->queue, be, bp, b_act);
+       if (bio->bio_offset > be->bio_offset) {
+               TAILQ_INSERT_AFTER(&bioq->queue, be, bio, bio_act);
                return;
        }
 
        /* Otherwise, insertion sort */
-       while ((bn = TAILQ_NEXT(bq, b_act)) != NULL) {
+       while ((bn = TAILQ_NEXT(bq, bio_act)) != NULL) {
                
                /*
                 * We want to go after the current request if it is the end
                 * of the first request list, or if the next request is a
                 * larger cylinder than our request.
                 */
-               if (bn == bufq->switch_point
-                || bp->b_pblkno < bn->b_pblkno)
+               if (bn == bioq->switch_point
+                || bio->bio_offset < bn->bio_offset)
                        break;
                bq = bn;
        }
-       TAILQ_INSERT_AFTER(&bufq->queue, bq, bp, b_act);
+       TAILQ_INSERT_AFTER(&bioq->queue, bq, bio, bio_act);
 }
 
 
@@ -641,19 +599,18 @@ bufqdisksort(struct buf_queue_head *bufq, struct buf *bp)
  * Returns NULL on success and an error string on failure.
  */
 char *
-readdisklabel(dev_t dev, struct disklabel *lp)
+readdisklabel(cdev_t dev, struct disklabel *lp)
 {
        struct buf *bp;
        struct disklabel *dlp;
        char *msg = NULL;
 
        bp = geteblk((int)lp->d_secsize);
-       bp->b_dev = dev;
-       bp->b_blkno = LABELSECTOR * ((int)lp->d_secsize/DEV_BSIZE);
+       bp->b_bio1.bio_offset = (off_t)LABELSECTOR * lp->d_secsize;
        bp->b_bcount = lp->d_secsize;
        bp->b_flags &= ~B_INVAL;
-       bp->b_flags |= B_READ;
-       BUF_STRATEGY(bp, 1);
+       bp->b_cmd = BUF_CMD_READ;
+       dev_dstrategy(dev, &bp->b_bio1);
        if (biowait(bp))
                msg = "I/O error";
        else for (dlp = (struct disklabel *)bp->b_data;
@@ -730,7 +687,7 @@ setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_long openmask)
  * Write disk label back to device after modification.
  */
 int
-writedisklabel(dev_t dev, struct disklabel *lp)
+writedisklabel(cdev_t dev, struct disklabel *lp)
 {
        struct buf *bp;
        struct disklabel *dlp;
@@ -739,8 +696,7 @@ writedisklabel(dev_t dev, struct disklabel *lp)
        if (lp->d_partitions[RAW_PART].p_offset != 0)
                return (EXDEV);                 /* not quite right */
        bp = geteblk((int)lp->d_secsize);
-       bp->b_dev = dkmodpart(dev, RAW_PART);
-       bp->b_blkno = LABELSECTOR * ((int)lp->d_secsize/DEV_BSIZE);
+       bp->b_bio1.bio_offset = (off_t)LABELSECTOR * lp->d_secsize;
        bp->b_bcount = lp->d_secsize;
 #if 1
        /*
@@ -751,8 +707,8 @@ writedisklabel(dev_t dev, struct disklabel *lp)
         * (also stupid.. how do you write the first one? by raw writes?)
         */
        bp->b_flags &= ~B_INVAL;
-       bp->b_flags |= B_READ;
-       BUF_STRATEGY(bp, 1);
+       bp->b_cmd = BUF_CMD_READ;
+       dev_dstrategy(dkmodpart(dev, RAW_PART), &bp->b_bio1);
        error = biowait(bp);
        if (error)
                goto done;
@@ -763,10 +719,8 @@ writedisklabel(dev_t dev, struct disklabel *lp)
                if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
                    dkcksum(dlp) == 0) {
                        *dlp = *lp;
-                       bp->b_flags &= ~(B_DONE | B_READ);
-                       bp->b_flags |= B_WRITE;
-                       bp->b_dev = dkmodpart(dev, RAW_PART);
-                       BUF_STRATEGY(bp, 1);
+                       bp->b_cmd = BUF_CMD_WRITE;
+                       dev_dstrategy(dkmodpart(dev, RAW_PART), &bp->b_bio1);
                        error = biowait(bp);
                        goto done;
                }
@@ -778,7 +732,7 @@ done:
        dlp = (struct disklabel *)bp->b_data;
        *dlp = *lp;
        bp->b_flags &= ~B_INVAL;
-       bp->b_flags |= B_WRITE;
+       bp->b_cmd = BUF_CMD_WRITE;
        BUF_STRATEGY(bp, 1);
        error = biowait(bp);
 #endif
@@ -802,46 +756,21 @@ hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
  * or addlog, respectively.  There is no trailing space.
  */
 void
-diskerr(struct buf *bp, dev_t dev, char *what, int pri, 
-       int blkdone, struct disklabel *lp)
+diskerr(struct bio *bio, cdev_t dev, const char *what, int pri, 
+       int donecnt, struct disklabel *lp)
 {
+       struct buf *bp = bio->bio_buf;
        int unit = dkunit(dev);
        int slice = dkslice(dev);
        int part = dkpart(dev);
        char partname[2];
        char *sname;
-       daddr_t sn;
 
        sname = dsname(dev, unit, slice, part, partname);
-       printf("%s%s: %s %sing fsbn ", sname, partname, what,
-             bp->b_flags & B_READ ? "read" : "writ");
-       sn = bp->b_blkno;
-       if (bp->b_bcount <= DEV_BSIZE) {
-               printf("%ld", (long)sn);
-       } else {
-               if (blkdone >= 0) {
-                       sn += blkdone;
-                       printf("%ld of ", (long)sn);
-               }
-               printf("%ld-%ld", (long)bp->b_blkno,
-                   (long)(bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE));
-       }
-       if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
-#ifdef tahoe
-               sn *= DEV_BSIZE / lp->d_secsize;                /* XXX */
-#endif
-               sn += lp->d_partitions[part].p_offset;
-               /*
-                * XXX should add slice offset and not print the slice,
-                * but we don't know the slice pointer.
-                * XXX should print bp->b_pblkno so that this will work
-                * independent of slices, labels and bad sector remapping,
-                * but some drivers don't set bp->b_pblkno.
-                */
-               printf(" (%s bn %ld; cn %ld", sname, (long)sn,
-                   (long)(sn / lp->d_secpercyl));
-               sn %= (long)lp->d_secpercyl;
-               printf(" tn %ld sn %ld)", (long)(sn / lp->d_nsectors),
-                   (long)(sn % lp->d_nsectors));
-       }
+       printf("%s%s: %s %sing ", sname, partname, what,
+             (bp->b_cmd == BUF_CMD_READ) ? "read" : "writ");
+       printf("offset %012llx for %d", bio->bio_offset, bp->b_bcount);
+       if (donecnt)
+               printf(" (%d bytes completed)", donecnt);
 }
+