Author: bryanv
Date: Thu Jul  4 17:53:02 2013
New Revision: 252703
URL: http://svnweb.freebsd.org/changeset/base/252703

Log:
  Merge several virtio_blk changes from projects/virtio
  
  The notable changes of this commit are support for disk resizing
  and chases updates to the spec regarding write caching.
  
  Contains projects/virtio commits:
  
  r245713:
      virtio_blk: Replace __FUNCTION__ with __func__
  r245714:
      virtio_blk: Use more consistent mutex name
  r245715:
      virtio_blk: Print device name too if failed to reinit during dump
  r245716:
      virtio_blk: Remove an unuseful ASSERT
  r245723:
      virtio_blk: Record the vendor and device information
  r245724:
      virtio_blk: Add resize support
  r245726:
      virtio_blk: More verbose ASSERT messages
  r245730:
      virtio_blk: Tweak resize announcement message
  r246061:
      virtio_blk: Do not always read entire config
  r246062:
      virtio_blk: Use topology to set the stripe size/offset
  r246307:
      virtio_blk: Correct stripe offset calculation
  r246063:
      virtio_blk: Add support for write cache enable feature
  r246303:
      virtio_blk: Expand a comment
  r252529:
      virtio_blk: Improve write cache handling
  r252681:
      virtio_blk: Remove unneeded curly braces
  
  MFC after:    1 month

Modified:
  head/share/man/man4/virtio_blk.4
  head/sys/dev/virtio/block/virtio_blk.c
  head/sys/dev/virtio/block/virtio_blk.h

Modified: head/share/man/man4/virtio_blk.4
==============================================================================
--- head/share/man/man4/virtio_blk.4    Thu Jul  4 17:50:11 2013        
(r252702)
+++ head/share/man/man4/virtio_blk.4    Thu Jul  4 17:53:02 2013        
(r252703)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 22, 2012
+.Dd July 2, 2013
 .Dt VIRTIO_BLK 4
 .Os
 .Sh NAME
@@ -53,11 +53,33 @@ Tunables can be set at the
 .Xr loader 8
 prompt before booting the kernel or stored in
 .Xr loader.conf 5 .
-.Bl -tag -width "xxxxxx"
+.Bl -tag -width indent
 .It Va hw.vtblk.no_ident
-This tunable disables retrieving the device identification string
-from the hypervisor.
+.It Va hw.vtblk. Ns Ar X Ns Va .no_ident
+.Pp
+These tunables disable retrieving the device identification string
+from the hypervisor either globally or per-device.
 The default value is 0.
+.It Va hw.vtblk.writecache_mode
+.It Va hw.vtblk. Ns Ar X Ns Va .writecache_mode
+.Pp
+These tunables determine the write cache mode globally or per-device.
+The mode can changed only if the ConfigWCE feature is negotiated.
+Set to 0 for writethrough mode, 1 for writeback mode, and -1 to leave
+it as-is.
+The default value is to leave as-is.
+.El
+.Sh SYSCTL VARIABLES
+The following variables are available as
+.Xr sysctl 8
+variables.
+.Bl -tag -width indent
+.It Va dev.vtblk. Ns Ar X Ns Va .writecache_mode
+.Pp
+The write cache mode of the device can be either writethrough (0) or
+writeback (1).
+If the ConfigWCE feature is negotiated, the write cache mode can
+be toggled between writethrough and writeback.
 .El
 .Sh SEE ALSO
 .Xr virtio 4

Modified: head/sys/dev/virtio/block/virtio_blk.c
==============================================================================
--- head/sys/dev/virtio/block/virtio_blk.c      Thu Jul  4 17:50:11 2013        
(r252702)
+++ head/sys/dev/virtio/block/virtio_blk.c      Thu Jul  4 17:53:02 2013        
(r252703)
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/sglist.h>
+#include <sys/sysctl.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/queue.h>
@@ -61,6 +62,12 @@ struct vtblk_request {
        TAILQ_ENTRY(vtblk_request)       vbr_link;
 };
 
+enum vtblk_cache_mode {
+       VTBLK_CACHE_WRITETHROUGH,
+       VTBLK_CACHE_WRITEBACK,
+       VTBLK_CACHE_MAX
+};
+
 struct vtblk_softc {
        device_t                 vtblk_dev;
        struct mtx               vtblk_mtx;
@@ -72,6 +79,7 @@ struct vtblk_softc {
 #define VTBLK_FLAG_SUSPEND     0x0008
 #define VTBLK_FLAG_DUMPING     0x0010
 #define VTBLK_FLAG_BARRIER     0x0020
+#define VTBLK_FLAG_WC_CONFIG   0x0040
 
        struct virtqueue        *vtblk_vq;
        struct sglist           *vtblk_sglist;
@@ -86,6 +94,7 @@ struct vtblk_softc {
 
        int                      vtblk_max_nsegs;
        int                      vtblk_request_count;
+       enum vtblk_cache_mode    vtblk_write_cache;
 
        struct vtblk_request     vtblk_dump_request;
 };
@@ -98,8 +107,9 @@ static struct virtio_feature_desc vtblk_
        { VIRTIO_BLK_F_RO,              "ReadOnly"      },
        { VIRTIO_BLK_F_BLK_SIZE,        "BlockSize"     },
        { VIRTIO_BLK_F_SCSI,            "SCSICmds"      },
-       { VIRTIO_BLK_F_FLUSH,           "FlushCmd"      },
+       { VIRTIO_BLK_F_WCE,             "WriteCache"    },
        { VIRTIO_BLK_F_TOPOLOGY,        "Topology"      },
+       { VIRTIO_BLK_F_CONFIG_WCE,      "ConfigWCE"     },
 
        { 0, NULL }
 };
@@ -112,6 +122,7 @@ static int  vtblk_detach(device_t);
 static int     vtblk_suspend(device_t);
 static int     vtblk_resume(device_t);
 static int     vtblk_shutdown(device_t);
+static int     vtblk_config_change(device_t);
 
 static int     vtblk_open(struct disk *);
 static int     vtblk_close(struct disk *);
@@ -124,6 +135,11 @@ static void        vtblk_negotiate_features(str
 static int     vtblk_maximum_segments(struct vtblk_softc *,
                    struct virtio_blk_config *);
 static int     vtblk_alloc_virtqueue(struct vtblk_softc *);
+static void    vtblk_resize_disk(struct vtblk_softc *, uint64_t);
+static void    vtblk_set_write_cache(struct vtblk_softc *, int);
+static int     vtblk_write_cache_enabled(struct vtblk_softc *sc,
+                   struct virtio_blk_config *);
+static int     vtblk_write_cache_sysctl(SYSCTL_HANDLER_ARGS);
 static void    vtblk_alloc_disk(struct vtblk_softc *,
                    struct virtio_blk_config *);
 static void    vtblk_create_disk(struct vtblk_softc *);
@@ -138,6 +154,8 @@ static void vtblk_vq_intr(void *);
 
 static void    vtblk_stop(struct vtblk_softc *);
 
+static void    vtblk_read_config(struct vtblk_softc *,
+                   struct virtio_blk_config *);
 static void    vtblk_get_ident(struct vtblk_softc *);
 static void    vtblk_prepare_dump(struct vtblk_softc *);
 static int     vtblk_write_dump(struct vtblk_softc *, void *, off_t, size_t);
@@ -162,9 +180,14 @@ static void        vtblk_enqueue_ready(struct v
 static int     vtblk_request_error(struct vtblk_request *);
 static void    vtblk_finish_bio(struct bio *, int);
 
+static void    vtblk_setup_sysctl(struct vtblk_softc *);
+static int     vtblk_tunable_int(struct vtblk_softc *, const char *, int);
+
 /* Tunables. */
 static int vtblk_no_ident = 0;
 TUNABLE_INT("hw.vtblk.no_ident", &vtblk_no_ident);
+static int vtblk_writecache_mode = -1;
+TUNABLE_INT("hw.vtblk.writecache_mode", &vtblk_writecache_mode);
 
 /* Features desired/implemented by this driver. */
 #define VTBLK_FEATURES \
@@ -174,13 +197,14 @@ TUNABLE_INT("hw.vtblk.no_ident", &vtblk_
      VIRTIO_BLK_F_GEOMETRY             | \
      VIRTIO_BLK_F_RO                   | \
      VIRTIO_BLK_F_BLK_SIZE             | \
-     VIRTIO_BLK_F_FLUSH                        | \
+     VIRTIO_BLK_F_WCE                  | \
+     VIRTIO_BLK_F_CONFIG_WCE           | \
      VIRTIO_RING_F_INDIRECT_DESC)
 
 #define VTBLK_MTX(_sc)         &(_sc)->vtblk_mtx
 #define VTBLK_LOCK_INIT(_sc, _name) \
                                mtx_init(VTBLK_MTX((_sc)), (_name), \
-                                   "VTBLK Lock", MTX_DEF)
+                                   "VirtIO Block Lock", MTX_DEF)
 #define VTBLK_LOCK(_sc)                mtx_lock(VTBLK_MTX((_sc)))
 #define VTBLK_UNLOCK(_sc)      mtx_unlock(VTBLK_MTX((_sc)))
 #define VTBLK_LOCK_DESTROY(_sc)        mtx_destroy(VTBLK_MTX((_sc)))
@@ -206,6 +230,9 @@ static device_method_t vtblk_methods[] =
        DEVMETHOD(device_resume,        vtblk_resume),
        DEVMETHOD(device_shutdown,      vtblk_shutdown),
 
+       /* VirtIO methods. */
+       DEVMETHOD(virtio_config_change, vtblk_config_change),
+
        DEVMETHOD_END
 };
 
@@ -279,10 +306,13 @@ vtblk_attach(device_t dev)
                sc->vtblk_flags |= VTBLK_FLAG_READONLY;
        if (virtio_with_feature(dev, VIRTIO_BLK_F_BARRIER))
                sc->vtblk_flags |= VTBLK_FLAG_BARRIER;
+       if (virtio_with_feature(dev, VIRTIO_BLK_F_CONFIG_WCE))
+               sc->vtblk_flags |= VTBLK_FLAG_WC_CONFIG;
+
+       vtblk_setup_sysctl(sc);
 
        /* Get local copy of config. */
-       virtio_read_device_config(dev, 0, &blkcfg,
-           sizeof(struct virtio_blk_config));
+       vtblk_read_config(sc, &blkcfg);
 
        /*
         * With the current sglist(9) implementation, it is not easy
@@ -418,6 +448,26 @@ vtblk_shutdown(device_t dev)
 }
 
 static int
+vtblk_config_change(device_t dev)
+{
+       struct vtblk_softc *sc;
+       struct virtio_blk_config blkcfg;
+       uint64_t capacity;
+
+       sc = device_get_softc(dev);
+
+       vtblk_read_config(sc, &blkcfg);
+
+       /* Capacity is always in 512-byte units. */
+       capacity = blkcfg.capacity * 512;
+
+       if (sc->vtblk_disk->d_mediasize != capacity)
+               vtblk_resize_disk(sc, capacity);
+
+       return (0);
+}
+
+static int
 vtblk_open(struct disk *dp)
 {
        struct vtblk_softc *sc;
@@ -518,8 +568,8 @@ vtblk_strategy(struct bio *bp)
                max_nsegs = sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS;
 
                KASSERT(nsegs <= max_nsegs,
-                   ("bio %p spanned too many segments: %d, max: %d",
-                   bp, nsegs, max_nsegs));
+                   ("%s: bio %p spanned too many segments: %d, max: %d",
+                   __func__, bp, nsegs, max_nsegs));
        }
 #endif
 
@@ -583,6 +633,84 @@ vtblk_alloc_virtqueue(struct vtblk_softc
 }
 
 static void
+vtblk_resize_disk(struct vtblk_softc *sc, uint64_t new_capacity)
+{
+       device_t dev;
+       struct disk *dp;
+       int error;
+
+       dev = sc->vtblk_dev;
+       dp = sc->vtblk_disk;
+
+       dp->d_mediasize = new_capacity;
+       if (bootverbose) {
+               device_printf(dev, "resized to %juMB (%ju %u byte sectors)\n",
+                   (uintmax_t) dp->d_mediasize >> 20,
+                   (uintmax_t) dp->d_mediasize / dp->d_sectorsize,
+                   dp->d_sectorsize);
+       }
+
+       error = disk_resize(dp, M_NOWAIT);
+       if (error) {
+               device_printf(dev,
+                   "disk_resize(9) failed, error: %d\n", error);
+       }
+}
+
+static void
+vtblk_set_write_cache(struct vtblk_softc *sc, int wc)
+{
+
+       /* Set either writeback (1) or writethrough (0) mode. */
+       virtio_write_dev_config_1(sc->vtblk_dev,
+           offsetof(struct virtio_blk_config, writeback), wc);
+}
+
+static int
+vtblk_write_cache_enabled(struct vtblk_softc *sc,
+    struct virtio_blk_config *blkcfg)
+{
+       int wc;
+
+       if (sc->vtblk_flags & VTBLK_FLAG_WC_CONFIG) {
+               wc = vtblk_tunable_int(sc, "writecache_mode",
+                   vtblk_writecache_mode);
+               if (wc >= 0 && wc < VTBLK_CACHE_MAX)
+                       vtblk_set_write_cache(sc, wc);
+               else
+                       wc = blkcfg->writeback;
+       } else
+               wc = virtio_with_feature(sc->vtblk_dev, VIRTIO_BLK_F_WCE);
+
+       return (wc);
+}
+
+static int
+vtblk_write_cache_sysctl(SYSCTL_HANDLER_ARGS)
+{
+       struct vtblk_softc *sc;
+       int wc, error;
+
+       sc = oidp->oid_arg1;
+       wc = sc->vtblk_write_cache;
+
+       error = sysctl_handle_int(oidp, &wc, 0, req);
+       if (error || req->newptr == NULL)
+               return (error);
+       if ((sc->vtblk_flags & VTBLK_FLAG_WC_CONFIG) == 0)
+               return (EPERM);
+       if (wc < 0 || wc >= VTBLK_CACHE_MAX)
+               return (EINVAL);
+
+       VTBLK_LOCK(sc);
+       sc->vtblk_write_cache = wc;
+       vtblk_set_write_cache(sc, sc->vtblk_write_cache);
+       VTBLK_UNLOCK(sc);
+
+       return (0);
+}
+
+static void
 vtblk_alloc_disk(struct vtblk_softc *sc, struct virtio_blk_config *blkcfg)
 {
        device_t dev;
@@ -598,6 +726,11 @@ vtblk_alloc_disk(struct vtblk_softc *sc,
        dp->d_name = VTBLK_DISK_NAME;
        dp->d_unit = device_get_unit(dev);
        dp->d_drv1 = sc;
+       dp->d_flags = DISKFLAG_CANFLUSHCACHE;
+       dp->d_hba_vendor = virtio_get_vendor(dev);
+       dp->d_hba_device = virtio_get_device(dev);
+       dp->d_hba_subvendor = virtio_get_subvendor(dev);
+       dp->d_hba_subdevice = virtio_get_subdevice(dev);
 
        if ((sc->vtblk_flags & VTBLK_FLAG_READONLY) == 0)
                dp->d_dump = vtblk_dump;
@@ -633,8 +766,18 @@ vtblk_alloc_disk(struct vtblk_softc *sc,
                dp->d_fwheads = blkcfg->geometry.heads;
        }
 
-       if (virtio_with_feature(dev, VIRTIO_BLK_F_FLUSH))
-               dp->d_flags |= DISKFLAG_CANFLUSHCACHE;
+       if (virtio_with_feature(dev, VIRTIO_BLK_F_TOPOLOGY)) {
+               dp->d_stripesize = dp->d_sectorsize *
+                   (1 << blkcfg->topology.physical_block_exp);
+               dp->d_stripeoffset = (dp->d_stripesize -
+                   blkcfg->topology.alignment_offset * dp->d_sectorsize) %
+                   dp->d_stripesize;
+       }
+
+       if (vtblk_write_cache_enabled(sc, blkcfg) != 0)
+               sc->vtblk_write_cache = VTBLK_CACHE_WRITEBACK;
+       else
+               sc->vtblk_write_cache = VTBLK_CACHE_WRITETHROUGH;
 }
 
 static void
@@ -742,8 +885,7 @@ vtblk_bio_request(struct vtblk_softc *sc
                req->vbr_hdr.sector = bp->bio_offset / 512;
                break;
        default:
-               panic("%s: bio with unhandled cmd: %d", __FUNCTION__,
-                   bp->bio_cmd);
+               panic("%s: bio with unhandled cmd: %d", __func__, bp->bio_cmd);
        }
 
        return (req);
@@ -786,14 +928,13 @@ vtblk_execute_request(struct vtblk_softc
        }
 
        sglist_reset(sg);
-
        sglist_append(sg, &req->vbr_hdr, sizeof(struct virtio_blk_outhdr));
 
        if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
                error = sglist_append(sg, bp->bio_data, bp->bio_bcount);
                if (error || sg->sg_nseg == sg->sg_maxseg)
                        panic("%s: data buffer too big bio:%p error:%d",
-                           __FUNCTION__, bp, error);
+                           __func__, bp, error);
 
                /* BIO_READ means the host writes into our buffer. */
                if (bp->bio_cmd == BIO_READ)
@@ -851,6 +992,37 @@ vtblk_stop(struct vtblk_softc *sc)
        virtio_stop(sc->vtblk_dev);
 }
 
+#define VTBLK_GET_CONFIG(_dev, _feature, _field, _cfg)                 \
+       if (virtio_with_feature(_dev, _feature)) {                      \
+               virtio_read_device_config(_dev,                         \
+                   offsetof(struct virtio_blk_config, _field),         \
+                   &(_cfg)->_field, sizeof((_cfg)->_field));           \
+       }
+
+static void
+vtblk_read_config(struct vtblk_softc *sc, struct virtio_blk_config *blkcfg)
+{
+       device_t dev;
+
+       dev = sc->vtblk_dev;
+
+       bzero(blkcfg, sizeof(struct virtio_blk_config));
+
+       /* The capacity is always available. */
+       virtio_read_device_config(dev, offsetof(struct virtio_blk_config,
+           capacity), &blkcfg->capacity, sizeof(blkcfg->capacity));
+
+       /* Read the configuration if the feature was negotiated. */
+       VTBLK_GET_CONFIG(dev, VIRTIO_BLK_F_SIZE_MAX, size_max, blkcfg);
+       VTBLK_GET_CONFIG(dev, VIRTIO_BLK_F_SEG_MAX, seg_max, blkcfg);
+       VTBLK_GET_CONFIG(dev, VIRTIO_BLK_F_GEOMETRY, geometry, blkcfg);
+       VTBLK_GET_CONFIG(dev, VIRTIO_BLK_F_BLK_SIZE, blk_size, blkcfg);
+       VTBLK_GET_CONFIG(dev, VIRTIO_BLK_F_TOPOLOGY, topology, blkcfg);
+       VTBLK_GET_CONFIG(dev, VIRTIO_BLK_F_CONFIG_WCE, writeback, blkcfg);
+}
+
+#undef VTBLK_GET_CONFIG
+
 static void
 vtblk_get_ident(struct vtblk_softc *sc)
 {
@@ -862,7 +1034,7 @@ vtblk_get_ident(struct vtblk_softc *sc)
        dp = sc->vtblk_disk;
        len = MIN(VIRTIO_BLK_ID_BYTES, DISK_IDENT_SIZE);
 
-       if (vtblk_no_ident != 0)
+       if (vtblk_tunable_int(sc, "no_ident", vtblk_no_ident) != 0)
                return;
 
        req = vtblk_dequeue_request(sc);
@@ -912,8 +1084,10 @@ vtblk_prepare_dump(struct vtblk_softc *s
         */
        vtblk_drain_vq(sc, 1);
 
-       if (virtio_reinit(dev, sc->vtblk_features) != 0)
-               panic("cannot reinit VirtIO block device during dump");
+       if (virtio_reinit(dev, sc->vtblk_features) != 0) {
+               panic("%s: cannot reinit VirtIO block device during dump",
+                   device_get_nameunit(dev));
+       }
 
        virtqueue_disable_intr(vq);
        virtio_reinit_complete(dev);
@@ -966,7 +1140,6 @@ static int
 vtblk_poll_request(struct vtblk_softc *sc, struct vtblk_request *req)
 {
        struct virtqueue *vq;
-       struct vtblk_request *r;
        int error;
 
        vq = sc->vtblk_vq;
@@ -979,14 +1152,12 @@ vtblk_poll_request(struct vtblk_softc *s
                return (error);
 
        virtqueue_notify(vq);
-
-       r = virtqueue_poll(vq, NULL);
-       KASSERT(r == req, ("unexpected request response: %p/%p", r, req));
+       virtqueue_poll(vq, NULL);
 
        error = vtblk_request_error(req);
        if (error && bootverbose) {
                device_printf(sc->vtblk_dev,
-                   "%s: IO error: %d\n", __FUNCTION__, error);
+                   "%s: IO error: %d\n", __func__, error);
        }
 
        return (error);
@@ -1117,7 +1288,7 @@ vtblk_free_requests(struct vtblk_softc *
        struct vtblk_request *req;
 
        KASSERT(TAILQ_EMPTY(&sc->vtblk_req_ready),
-           ("ready requests left on queue"));
+           ("%s: ready requests left on queue", __func__));
 
        while ((req = vtblk_dequeue_request(sc)) != NULL) {
                sc->vtblk_request_count--;
@@ -1125,7 +1296,7 @@ vtblk_free_requests(struct vtblk_softc *
        }
 
        KASSERT(sc->vtblk_request_count == 0,
-           ("leaked requests: %d", sc->vtblk_request_count));
+           ("%s: leaked %d requests", __func__, sc->vtblk_request_count));
 }
 
 static struct vtblk_request *
@@ -1199,3 +1370,33 @@ vtblk_finish_bio(struct bio *bp, int err
 
        biodone(bp);
 }
+
+static void
+vtblk_setup_sysctl(struct vtblk_softc *sc)
+{
+       device_t dev;
+       struct sysctl_ctx_list *ctx;
+       struct sysctl_oid *tree;
+       struct sysctl_oid_list *child;
+
+       dev = sc->vtblk_dev;
+       ctx = device_get_sysctl_ctx(dev);
+       tree = device_get_sysctl_tree(dev);
+       child = SYSCTL_CHILDREN(tree);
+
+       SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "writecache_mode",
+           CTLTYPE_INT | CTLFLAG_RW, sc, 0, vtblk_write_cache_sysctl,
+           "I", "Write cache mode (writethrough (0) or writeback (1))");
+}
+
+static int
+vtblk_tunable_int(struct vtblk_softc *sc, const char *knob, int def)
+{
+       char path[64];
+
+       snprintf(path, sizeof(path),
+           "hw.vtblk.%d.%s", device_get_unit(sc->vtblk_dev), knob);
+       TUNABLE_INT_FETCH(path, &def);
+
+       return (def);
+}

Modified: head/sys/dev/virtio/block/virtio_blk.h
==============================================================================
--- head/sys/dev/virtio/block/virtio_blk.h      Thu Jul  4 17:50:11 2013        
(r252702)
+++ head/sys/dev/virtio/block/virtio_blk.h      Thu Jul  4 17:53:02 2013        
(r252703)
@@ -39,8 +39,9 @@
 #define VIRTIO_BLK_F_RO                0x0020  /* Disk is read-only */
 #define VIRTIO_BLK_F_BLK_SIZE  0x0040  /* Block size of disk is available*/
 #define VIRTIO_BLK_F_SCSI      0x0080  /* Supports scsi command passthru */
-#define VIRTIO_BLK_F_FLUSH     0x0200  /* Cache flush command support */
+#define VIRTIO_BLK_F_WCE       0x0200  /* Writeback mode enabled after reset */
 #define VIRTIO_BLK_F_TOPOLOGY  0x0400  /* Topology information is available */
+#define VIRTIO_BLK_F_CONFIG_WCE 0x0800 /* Writeback mode available in config */
 
 #define VIRTIO_BLK_ID_BYTES    20      /* ID string length */
 
@@ -51,15 +52,27 @@ struct virtio_blk_config {
        uint32_t size_max;
        /* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
        uint32_t seg_max;
-       /* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
+       /* Geometry of the device (if VIRTIO_BLK_F_GEOMETRY) */
        struct virtio_blk_geometry {
                uint16_t cylinders;
                uint8_t heads;
                uint8_t sectors;
        } geometry;
 
-       /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
+       /* Block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
        uint32_t blk_size;
+
+       /* Topology of the device (if VIRTIO_BLK_F_TOPOLOGY) */
+       struct virtio_blk_topology {
+               uint8_t physical_block_exp;
+               uint8_t alignment_offset;
+               uint16_t min_io_size;
+               uint16_t opt_io_size;
+       } topology;
+
+       /* Writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
+       uint8_t writeback;
+
 } __packed;
 
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to