summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2013-10-12 19:41:35 +0000
committergrehan <grehan@FreeBSD.org>2013-10-12 19:41:35 +0000
commitc1abbfde2d2ed6e8b37eddbb9bf305f79d3ce103 (patch)
treeaebebffbe7cd5057972c6019de689ebf5345cda8 /usr.sbin
parent2a6361507410ac1bd935b61f13d48c2512bb6cc3 (diff)
downloadFreeBSD-src-c1abbfde2d2ed6e8b37eddbb9bf305f79d3ce103.zip
FreeBSD-src-c1abbfde2d2ed6e8b37eddbb9bf305f79d3ce103.tar.gz
MFC r256389
Implement the virtio block 'get-ident' operation. This eliminates the annoying verbose boot error of the form g_handleattr: vtbd0 bio_length 24 len 28 -> EFAULT The ident returned by bhyve is a text string 'BHYVE-XXXX-XXXX', where the X's are the first bytes of the md5 hash of the backing filename. Approved by: re (gjb)
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bhyve/pci_virtio_block.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
index 529cd42..a190497 100644
--- a/usr.sbin/bhyve/pci_virtio_block.c
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -46,17 +46,25 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
+#include <md5.h>
#include "bhyverun.h"
#include "pci_emul.h"
#include "virtio.h"
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
#define VTBLK_RINGSZ 64
#define VTBLK_MAXSEGS 32
#define VTBLK_S_OK 0
#define VTBLK_S_IOERR 1
+#define VTBLK_S_UNSUPP 2
+
+#define VTBLK_BLK_ID_BYTES 20
/*
* Host capabilities
@@ -85,6 +93,7 @@ struct vtblk_config {
struct virtio_blk_hdr {
#define VBH_OP_READ 0
#define VBH_OP_WRITE 1
+#define VBH_OP_IDENT 8
#define VBH_FLAG_BARRIER 0x80000000 /* OR'ed into vbh_type */
uint32_t vbh_type;
uint32_t vbh_ioprio;
@@ -106,6 +115,7 @@ struct pci_vtblk_softc {
struct vqueue_info vbsc_vq;
int vbsc_fd;
struct vtblk_config vbsc_cfg;
+ char vbsc_ident[VTBLK_BLK_ID_BYTES];
};
static void pci_vtblk_reset(void *);
@@ -180,7 +190,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vqueue_info *vq)
for (i = 1; i < n; i++) {
/*
* - write op implies read-only descriptor,
- * - read op implies write-only descriptor,
+ * - read/ident op implies write-only descriptor,
* therefore test the inverse of the descriptor bit
* to the op.
*/
@@ -189,14 +199,34 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vqueue_info *vq)
}
DPRINTF(("virtio-block: %s op, %d bytes, %d segs, offset %ld\n\r",
- writeop ? "write" : "read", iolen, i - 1, offset));
+ writeop ? "write" : "read/ident", iolen, i - 1, offset));
- if (writeop)
+ switch (type) {
+ case VBH_OP_WRITE:
err = pwritev(sc->vbsc_fd, iov + 1, i - 1, offset);
- else
+ break;
+ case VBH_OP_READ:
err = preadv(sc->vbsc_fd, iov + 1, i - 1, offset);
+ break;
+ case VBH_OP_IDENT:
+ /* Assume a single buffer */
+ strlcpy(iov[1].iov_base, sc->vbsc_ident,
+ min(iov[1].iov_len, sizeof(sc->vbsc_ident)));
+ err = 0;
+ break;
+ default:
+ err = -ENOSYS;
+ break;
+ }
- *status = err < 0 ? VTBLK_S_IOERR : VTBLK_S_OK;
+ /* convert errno into a virtio block error return */
+ if (err < 0) {
+ if (err == -ENOSYS)
+ *status = VTBLK_S_UNSUPP;
+ else
+ *status = VTBLK_S_IOERR;
+ } else
+ *status = VTBLK_S_OK;
/*
* Return the descriptor back to the host.
@@ -220,6 +250,8 @@ static int
pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
struct stat sbuf;
+ MD5_CTX mdctx;
+ u_char digest[16];
struct pci_vtblk_softc *sc;
off_t size;
int fd;
@@ -274,6 +306,16 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
sc->vbsc_vq.vq_qsize = VTBLK_RINGSZ;
/* sc->vbsc_vq.vq_notify = we have no per-queue notify */
+ /*
+ * Create an identifier for the backing file. Use parts of the
+ * md5 sum of the filename
+ */
+ MD5Init(&mdctx);
+ MD5Update(&mdctx, opts, strlen(opts));
+ MD5Final(digest, &mdctx);
+ sprintf(sc->vbsc_ident, "BHYVE-%02X%02X-%02X%02X-%02X%02X",
+ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5]);
+
/* setup virtio block config space */
sc->vbsc_cfg.vbc_capacity = size / sectsz;
sc->vbsc_cfg.vbc_seg_max = VTBLK_MAXSEGS;
OpenPOWER on IntegriCloud