--- /dev/null
+/*
+ * Copyright (c) 2011, XenSource Inc.
+ * All rights reserved.
+ */
+
+#ifndef _LINUX_BLKTAP_H
+#define _LINUX_BLKTAP_H
+
+/*
+ * Control
+ */
+
+#define BLKTAP_IOCTL_RESPOND 1
+#define BLKTAP_IOCTL_ALLOC_TAP 200
+#define BLKTAP_IOCTL_FREE_TAP 201
+#define BLKTAP_IOCTL_CREATE_DEVICE 208
+#define BLKTAP_IOCTL_REMOVE_DEVICE 207
+
+struct blktap_info {
+ unsigned int ring_major;
+ unsigned int bdev_major;
+ unsigned int ring_minor;
+};
+
+struct blktap_device_info {
+ unsigned long long capacity;
+ unsigned int sector_size;
+ unsigned int physical_sector_size;
+ unsigned long flags;
+ unsigned long __rsvd[4];
+};
+
+#define BLKTAP_DEVICE_RO 0x00000001UL
+
+/*
+ * I/O ring
+ */
+
+#ifdef __KERNEL__
+#include <asm/page.h>
+#define BLKTAP_PAGE_SIZE PAGE_SIZE
+
+#include <linux/log2.h>
+#define BLKTAP_RD32(_n) rounddown_pow_of_two(_n)
+#endif
+
+#define __BLKTAP_RING_SIZE(_sz) \
+ ((unsigned int) \
+ BLKTAP_RD32(((_sz) - offsetof(struct blktap_sring, entry)) / \
+ sizeof(union blktap_ring_entry)))
+
+typedef struct blktap_ring_request blktap_ring_req_t;
+typedef struct blktap_ring_response blktap_ring_rsp_t;
+
+struct blktap_segment {
+ uint32_t __pad;
+ uint8_t first_sect;
+ uint8_t last_sect;
+};
+
+#define BLKTAP_OP_READ 0
+#define BLKTAP_OP_WRITE 1
+
+#define BLKTAP_SEGMENT_MAX 11
+
+struct blktap_ring_request {
+ uint8_t operation;
+ uint8_t nr_segments;
+ uint16_t __pad;
+ uint64_t id;
+ uint64_t sector_number;
+ struct blktap_segment seg[BLKTAP_SEGMENT_MAX];
+};
+
+#define BLKTAP_RSP_EOPNOTSUPP -2
+#define BLKTAP_RSP_ERROR -1
+#define BLKTAP_RSP_OKAY 0
+
+struct blktap_ring_response {
+ uint64_t id;
+ uint8_t operation;
+ int16_t status;
+};
+
+union blktap_ring_entry {
+ struct blktap_ring_request req;
+ struct blktap_ring_response rsp;
+};
+
+struct blktap_sring {
+ uint32_t req_prod;
+ uint32_t __req_event;
+
+ uint32_t rsp_prod;
+ uint32_t __rsp_event;
+
+ uint8_t msg;
+ uint8_t __rsvd[47];
+
+ union blktap_ring_entry entry[0];
+};
+
+/*
+ * Ring messages + old ioctls (DEPRECATED)
+ */
+
+#define BLKTAP_RING_MESSAGE_CLOSE 3
+#define BLKTAP_IOCTL_CREATE_DEVICE_COMPAT 202
+#define BLKTAP_NAME_MAX 256
+
+struct blktap2_params {
+ char name[BLKTAP_NAME_MAX];
+ unsigned long long capacity;
+ unsigned long sector_size;
+};
+
+#endif /* _LINUX_BLKTAP_H */
#include "tapdisk-vbd.h"
#include "tapdisk-blktap.h"
#include "tapdisk-server.h"
+#include "linux-blktap.h"
-#define wmb() /* blktap is synchronous */
-#define BLKTAP_PAGE_SIZE sysconf(_SC_PAGE_SIZE)
#define BUG(_cond) td_panic()
#define BUG_ON(_cond) if (unlikely(_cond)) { td_panic(); }
#define WARN(_f, _a...) tlog_syslog(TLOG_WARN, "WARNING: "_f "in %s:%d", \
##_a, __func__, __LINE__)
+#define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
+#define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
+#define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
+#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
+#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
+
+#define BLKTAP_RD32(_n) __RD32(_n)
+#define BLKTAP_RING_SIZE __BLKTAP_RING_SIZE(BLKTAP_PAGE_SIZE)
+#define BLKTAP_PAGE_SIZE sysconf(_SC_PAGE_SIZE)
+
+#define BLKTAP_GET_RESPONSE(_tap, _idx) \
+ (&(_tap)->sring->entry[(_idx) % BLKTAP_RING_SIZE].rsp)
+#define BLKTAP_GET_REQUEST(_tap, _idx) \
+ (&(_tap)->sring->entry[(_idx) % BLKTAP_RING_SIZE].req)
+
static void __tapdisk_blktap_close(td_blktap_t *);
struct td_blktap_req {
}
static void
-__tapdisk_blktap_push_responses(td_blktap_t *tap, int final)
+__tapdisk_blktap_push_response(td_blktap_t *tap, int final)
{
- blktap_back_ring_t *ring = &tap->ring;
-
- ring->rsp_prod_pvt++;
+ tap->rsp_prod_pvt++;
if (final) {
- RING_PUSH_RESPONSES(&tap->ring);
+ tap->sring->rsp_prod = tap->rsp_prod_pvt;
tapdisk_blktap_kick(tap);
}
tapdisk_blktap_fail_request(td_blktap_t *tap,
blktap_ring_req_t *msg, int error)
{
- blktap_back_ring_t *ring = &tap->ring;
blktap_ring_rsp_t *rsp;
BUG_ON(!tap->vma);
- rsp = RING_GET_RESPONSE(&tap->ring, ring->rsp_prod_pvt);
+ rsp = BLKTAP_GET_RESPONSE(tap, tap->rsp_prod_pvt);
rsp->id = msg->id;
rsp->operation = msg->operation;
rsp->status = tapdisk_blktap_error_status(tap, error);
- __tapdisk_blktap_push_responses(tap, 1);
+ __tapdisk_blktap_push_response(tap, 1);
}
static void
tapdisk_blktap_put_response(td_blktap_t *tap,
td_blktap_req_t *req, int error, int final)
{
- blktap_back_ring_t *ring = &tap->ring;
blktap_ring_rsp_t *rsp;
int op = 0;
BUG_ON(!tap->vma);
- rsp = RING_GET_RESPONSE(&tap->ring, ring->rsp_prod_pvt);
+ rsp = BLKTAP_GET_RESPONSE(tap, tap->rsp_prod_pvt);
switch (req->vreq.op) {
case TD_OP_READ:
rsp->operation = op;
rsp->status = tapdisk_blktap_error_status(tap, error);
- __tapdisk_blktap_push_responses(tap, final);
+ __tapdisk_blktap_push_response(tap, final);
}
static void
static void
tapdisk_blktap_get_requests(td_blktap_t *tap)
{
- blktap_back_ring_t *ring = &tap->ring;
- RING_IDX rp, rc;
+ unsigned int rp, rc;
int err;
- rp = ring->sring->req_prod;
+ rp = tap->sring->req_prod;
- for (rc = ring->req_cons; rc != rp; rc++) {
- blktap_ring_req_t *msg = RING_GET_REQUEST(ring, rc);
+ for (rc = tap->req_cons; rc != rp; rc++) {
+ blktap_ring_req_t *msg = BLKTAP_GET_REQUEST(tap, rc);
td_blktap_req_t *req;
tap->stats.reqs.in++;
tapdisk_blktap_complete_request(tap, req, err, 1);
}
- ring->req_cons = rc;
+ tap->req_cons = rc;
return;
tap->vma = vma;
tap->vstart = vma + BLKTAP_PAGE_SIZE;
- BACK_RING_INIT(&tap->ring, (blktap_sring_t*)vma, BLKTAP_PAGE_SIZE);
+
+ tap->req_cons = 0;
+ tap->rsp_prod_pvt = 0;
+ tap->sring = vma;
return 0;