提交 c8af89af 编写于 作者: A Anthony Liguori

Merge remote-tracking branch 'kwolf/for-anthony' into staging

......@@ -48,6 +48,7 @@
typedef struct BDRVNBDState {
int sock;
uint32_t nbdflags;
off_t size;
size_t blocksize;
char *export_name; /* An NBD server may export several devices */
......@@ -111,7 +112,6 @@ static int nbd_establish_connection(BlockDriverState *bs)
int ret;
off_t size;
size_t blocksize;
uint32_t nbdflags;
if (s->host_spec[0] == '/') {
sock = unix_socket_outgoing(s->host_spec);
......@@ -126,7 +126,7 @@ static int nbd_establish_connection(BlockDriverState *bs)
}
/* NBD handshake */
ret = nbd_receive_negotiate(sock, s->export_name, &nbdflags, &size,
ret = nbd_receive_negotiate(sock, s->export_name, &s->nbdflags, &size,
&blocksize);
if (ret == -1) {
logout("Failed to negotiate with the NBD server\n");
......
......@@ -839,7 +839,14 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
static int raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
return qemu_fdatasync(s->fd);
int ret;
ret = qemu_fdatasync(s->fd);
if (ret < 0) {
return -errno;
}
return 0;
}
#ifdef CONFIG_XFS
......
......@@ -13,35 +13,33 @@
#include "qemu-common.h"
#include "qemu-error.h"
#include "block_int.h"
#include <rbd/librbd.h>
/*
* When specifying the image filename use:
*
* rbd:poolname/devicename[@snapshotname][:option1=value1[:option2=value2...]]
*
* poolname must be the name of an existing rados pool
* poolname must be the name of an existing rados pool.
*
* devicename is the basename for all objects used to
* emulate the raw device.
* devicename is the name of the rbd image.
*
* Each option given is used to configure rados, and may be
* any Ceph option, or "conf". The "conf" option specifies
* a Ceph configuration file to read.
* Each option given is used to configure rados, and may be any valid
* Ceph option, "id", or "conf".
*
* Metadata information (image size, ...) is stored in an
* object with the name "devicename.rbd".
* The "id" option indicates what user we should authenticate as to
* the Ceph cluster. If it is excluded we will use the Ceph default
* (normally 'admin').
*
* The raw device is split into 4MB sized objects by default.
* The sequencenumber is encoded in a 12 byte long hex-string,
* and is attached to the devicename, separated by a dot.
* e.g. "devicename.1234567890ab"
* The "conf" option specifies a Ceph configuration file to read. If
* it is not specified, we will read from the default Ceph locations
* (e.g., /etc/ceph/ceph.conf). To avoid reading _any_ configuration
* file, specify conf=/dev/null.
*
* Configuration values containing :, @, or = can be escaped with a
* leading "\".
*/
#define OBJ_MAX_SIZE (1UL << OBJ_DEFAULT_OBJ_ORDER)
......@@ -104,8 +102,15 @@ static int qemu_rbd_next_tok(char *dst, int dst_len,
*p = NULL;
if (delim != '\0') {
end = strchr(src, delim);
if (end) {
for (end = src; *end; ++end) {
if (*end == delim) {
break;
}
if (*end == '\\' && end[1] != '\0') {
end++;
}
}
if (*end == delim) {
*p = end + 1;
*end = '\0';
}
......@@ -124,6 +129,19 @@ static int qemu_rbd_next_tok(char *dst, int dst_len,
return 0;
}
static void qemu_rbd_unescape(char *src)
{
char *p;
for (p = src; *src; ++src, ++p) {
if (*src == '\\' && src[1] != '\0') {
src++;
}
*p = *src;
}
*p = '\0';
}
static int qemu_rbd_parsename(const char *filename,
char *pool, int pool_len,
char *snap, int snap_len,
......@@ -148,6 +166,7 @@ static int qemu_rbd_parsename(const char *filename,
ret = -EINVAL;
goto done;
}
qemu_rbd_unescape(pool);
if (strchr(p, '@')) {
ret = qemu_rbd_next_tok(name, name_len, p, '@', "object name", &p);
......@@ -155,9 +174,11 @@ static int qemu_rbd_parsename(const char *filename,
goto done;
}
ret = qemu_rbd_next_tok(snap, snap_len, p, ':', "snap name", &p);
qemu_rbd_unescape(snap);
} else {
ret = qemu_rbd_next_tok(name, name_len, p, ':', "object name", &p);
}
qemu_rbd_unescape(name);
if (ret < 0 || !p) {
goto done;
}
......@@ -213,6 +234,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
if (ret < 0) {
break;
}
qemu_rbd_unescape(name);
if (!p) {
error_report("conf option %s has no value", name);
......@@ -225,6 +247,7 @@ static int qemu_rbd_set_conf(rados_t cluster, const char *conf)
if (ret < 0) {
break;
}
qemu_rbd_unescape(value);
if (strcmp(name, "conf") == 0) {
ret = rados_conf_read_file(cluster, value);
......@@ -298,11 +321,8 @@ static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options)
}
if (strstr(conf, "conf=") == NULL) {
if (rados_conf_read_file(cluster, NULL) < 0) {
error_report("error reading config file");
rados_shutdown(cluster);
return -EIO;
}
/* try default location, but ignore failure */
rados_conf_read_file(cluster, NULL);
}
if (conf[0] != '\0' &&
......@@ -441,11 +461,8 @@ static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags)
}
if (strstr(conf, "conf=") == NULL) {
r = rados_conf_read_file(s->cluster, NULL);
if (r < 0) {
error_report("error reading config file");
goto failed_shutdown;
}
/* try default location, but ignore failure */
rados_conf_read_file(s->cluster, NULL);
}
if (conf[0] != '\0') {
......@@ -688,6 +705,17 @@ static BlockDriverAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
return rbd_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
}
static int qemu_rbd_flush(BlockDriverState *bs)
{
#if LIBRBD_VERSION_CODE >= LIBRBD_VERSION(0, 1, 1)
/* rbd_flush added in 0.1.1 */
BDRVRBDState *s = bs->opaque;
return rbd_flush(s->image);
#else
return 0;
#endif
}
static int qemu_rbd_getinfo(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVRBDState *s = bs->opaque;
......@@ -823,6 +851,7 @@ static BlockDriver bdrv_rbd = {
.bdrv_file_open = qemu_rbd_open,
.bdrv_close = qemu_rbd_close,
.bdrv_create = qemu_rbd_create,
.bdrv_flush = qemu_rbd_flush,
.bdrv_get_info = qemu_rbd_getinfo,
.create_options = qemu_rbd_create_options,
.bdrv_getlength = qemu_rbd_getlength,
......
......@@ -179,11 +179,16 @@ static void vmdk_free_extents(BlockDriverState *bs)
{
int i;
BDRVVmdkState *s = bs->opaque;
VmdkExtent *e;
for (i = 0; i < s->num_extents; i++) {
g_free(s->extents[i].l1_table);
g_free(s->extents[i].l2_cache);
g_free(s->extents[i].l1_backup_table);
e = &s->extents[i];
g_free(e->l1_table);
g_free(e->l2_cache);
g_free(e->l1_backup_table);
if (e->file != bs->file) {
bdrv_delete(e->file);
}
}
g_free(s->extents);
}
......@@ -619,12 +624,13 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
s->desc_offset = 0;
ret = vmdk_parse_extents(buf, bs, bs->file->filename);
if (ret) {
vmdk_free_extents(bs);
return ret;
}
/* try to open parent images, if exist */
if (vmdk_parent_open(bs)) {
g_free(s->extents);
vmdk_free_extents(bs);
return -EINVAL;
}
s->parent_cid = vmdk_read_cid(bs, 1);
......
......@@ -380,11 +380,6 @@ static int qemu_signal_init(void)
int sigfd;
sigset_t set;
/* SIGUSR2 used by posix-aio-compat.c */
sigemptyset(&set);
sigaddset(&set, SIGUSR2);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
/*
* SIG_IPI must be blocked in the main thread and must not be caught
* by sigwait() in the signal thread. Otherwise, the cpu thread will
......
......@@ -42,7 +42,8 @@ typedef struct {
BlockDriverAIOCB *acb;
QEMUSGList *sg;
uint64_t sector_num;
int is_write;
bool to_dev;
bool in_cancel;
int sg_cur_index;
target_phys_addr_t sg_cur_byte;
QEMUIOVector iov;
......@@ -58,7 +59,7 @@ static void reschedule_dma(void *opaque)
qemu_bh_delete(dbs->bh);
dbs->bh = NULL;
dma_bdrv_cb(opaque, 0);
dma_bdrv_cb(dbs, 0);
}
static void continue_after_map_failure(void *opaque)
......@@ -75,9 +76,29 @@ static void dma_bdrv_unmap(DMAAIOCB *dbs)
for (i = 0; i < dbs->iov.niov; ++i) {
cpu_physical_memory_unmap(dbs->iov.iov[i].iov_base,
dbs->iov.iov[i].iov_len, !dbs->is_write,
dbs->iov.iov[i].iov_len, !dbs->to_dev,
dbs->iov.iov[i].iov_len);
}
qemu_iovec_reset(&dbs->iov);
}
static void dma_complete(DMAAIOCB *dbs, int ret)
{
dma_bdrv_unmap(dbs);
if (dbs->common.cb) {
dbs->common.cb(dbs->common.opaque, ret);
}
qemu_iovec_destroy(&dbs->iov);
if (dbs->bh) {
qemu_bh_delete(dbs->bh);
dbs->bh = NULL;
}
if (!dbs->in_cancel) {
/* Requests may complete while dma_aio_cancel is in progress. In
* this case, the AIOCB should not be released because it is still
* referenced by dma_aio_cancel. */
qemu_aio_release(dbs);
}
}
static void dma_bdrv_cb(void *opaque, int ret)
......@@ -89,19 +110,16 @@ static void dma_bdrv_cb(void *opaque, int ret)
dbs->acb = NULL;
dbs->sector_num += dbs->iov.size / 512;
dma_bdrv_unmap(dbs);
qemu_iovec_reset(&dbs->iov);
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
dbs->common.cb(dbs->common.opaque, ret);
qemu_iovec_destroy(&dbs->iov);
qemu_aio_release(dbs);
dma_complete(dbs, ret);
return;
}
while (dbs->sg_cur_index < dbs->sg->nsg) {
cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte;
mem = cpu_physical_memory_map(cur_addr, &cur_len, !dbs->is_write);
mem = cpu_physical_memory_map(cur_addr, &cur_len, !dbs->to_dev);
if (!mem)
break;
qemu_iovec_add(&dbs->iov, mem, cur_len);
......@@ -120,9 +138,7 @@ static void dma_bdrv_cb(void *opaque, int ret)
dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
dbs->iov.size / 512, dma_bdrv_cb, dbs);
if (!dbs->acb) {
dma_bdrv_unmap(dbs);
qemu_iovec_destroy(&dbs->iov);
return;
dma_complete(dbs, -EIO);
}
}
......@@ -131,8 +147,14 @@ static void dma_aio_cancel(BlockDriverAIOCB *acb)
DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
if (dbs->acb) {
bdrv_aio_cancel(dbs->acb);
BlockDriverAIOCB *acb = dbs->acb;
dbs->acb = NULL;
dbs->in_cancel = true;
bdrv_aio_cancel(acb);
dbs->in_cancel = false;
}
dbs->common.cb = NULL;
dma_complete(dbs, 0);
}
static AIOPool dma_aio_pool = {
......@@ -143,7 +165,7 @@ static AIOPool dma_aio_pool = {
BlockDriverAIOCB *dma_bdrv_io(
BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
void *opaque, int is_write)
void *opaque, bool to_dev)
{
DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
......@@ -153,15 +175,11 @@ BlockDriverAIOCB *dma_bdrv_io(
dbs->sector_num = sector_num;
dbs->sg_cur_index = 0;
dbs->sg_cur_byte = 0;
dbs->is_write = is_write;
dbs->to_dev = to_dev;
dbs->io_func = io_func;
dbs->bh = NULL;
qemu_iovec_init(&dbs->iov, sg->nsg);
dma_bdrv_cb(dbs, 0);
if (!dbs->acb) {
qemu_aio_release(dbs);
return NULL;
}
return &dbs->common;
}
......@@ -170,12 +188,12 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
QEMUSGList *sg, uint64_t sector,
void (*cb)(void *opaque, int ret), void *opaque)
{
return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque, 0);
return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque, false);
}
BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
QEMUSGList *sg, uint64_t sector,
void (*cb)(void *opaque, int ret), void *opaque)
{
return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, 1);
return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, true);
}
......@@ -15,10 +15,13 @@
#include "hw/hw.h"
#include "block.h"
typedef struct {
typedef struct ScatterGatherEntry ScatterGatherEntry;
#if defined(TARGET_PHYS_ADDR_BITS)
struct ScatterGatherEntry {
target_phys_addr_t base;
target_phys_addr_t len;
} ScatterGatherEntry;
};
struct QEMUSGList {
ScatterGatherEntry *sg;
......@@ -31,6 +34,7 @@ void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint);
void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base,
target_phys_addr_t len);
void qemu_sglist_destroy(QEMUSGList *qsg);
#endif
typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
QEMUIOVector *iov, int nb_sectors,
......@@ -39,7 +43,7 @@ typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs,
QEMUSGList *sg, uint64_t sector_num,
DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
void *opaque, int is_write);
void *opaque, bool to_dev);
BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
QEMUSGList *sg, uint64_t sector,
BlockDriverCompletionFunc *cb, void *opaque);
......
......@@ -499,10 +499,7 @@ static void ahci_reset_port(AHCIState *s, int port)
ide_bus_reset(&d->port);
ide_state->ncq_queues = AHCI_MAX_CMDS;
pr->irq_stat = 0;
pr->irq_mask = 0;
pr->scr_stat = 0;
pr->scr_ctl = 0;
pr->scr_err = 0;
pr->scr_act = 0;
d->busy_slot = -1;
......@@ -1159,12 +1156,17 @@ void ahci_uninit(AHCIState *s)
void ahci_reset(void *opaque)
{
struct AHCIPCIState *d = opaque;
AHCIPortRegs *pr;
int i;
d->ahci.control_regs.irqstatus = 0;
d->ahci.control_regs.ghc = 0;
for (i = 0; i < d->ahci.ports; i++) {
pr = &d->ahci.dev[i].port_regs;
pr->irq_stat = 0;
pr->irq_mask = 0;
pr->scr_ctl = 0;
ahci_reset_port(&d->ahci, i);
}
}
......@@ -603,7 +603,7 @@ handle_rw_error:
break;
case IDE_DMA_TRIM:
s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
ide_issue_trim, ide_dma_cb, s, 1);
ide_issue_trim, ide_dma_cb, s, true);
break;
}
......
......@@ -156,7 +156,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
break;
case IDE_DMA_TRIM:
m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
ide_issue_trim, pmac_ide_transfer_cb, s, 1);
ide_issue_trim, pmac_ide_transfer_cb, s, true);
break;
}
......
......@@ -542,15 +542,15 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
break;
case 1:
case 2:
cmd->xfer = buf[8] | (buf[7] << 8);
cmd->xfer = lduw_be_p(&buf[7]);
cmd->len = 10;
break;
case 4:
cmd->xfer = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
cmd->xfer = ldl_be_p(&buf[10]);
cmd->len = 16;
break;
case 5:
cmd->xfer = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
cmd->xfer = ldl_be_p(&buf[6]);
cmd->len = 12;
break;
default:
......@@ -710,23 +710,15 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
switch (buf[0] >> 5) {
case 0:
lba = (uint64_t) buf[3] | ((uint64_t) buf[2] << 8) |
(((uint64_t) buf[1] & 0x1f) << 16);
lba = ldl_be_p(&buf[0]) & 0x1fffff;
break;
case 1:
case 2:
lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
case 5:
lba = ldl_be_p(&buf[2]);
break;
case 4:
lba = (uint64_t) buf[9] | ((uint64_t) buf[8] << 8) |
((uint64_t) buf[7] << 16) | ((uint64_t) buf[6] << 24) |
((uint64_t) buf[5] << 32) | ((uint64_t) buf[4] << 40) |
((uint64_t) buf[3] << 48) | ((uint64_t) buf[2] << 56);
break;
case 5:
lba = (uint64_t) buf[5] | ((uint64_t) buf[4] << 8) |
((uint64_t) buf[3] << 16) | ((uint64_t) buf[2] << 24);
lba = ldq_be_p(&buf[2]);
break;
default:
lba = -1;
......
......@@ -55,6 +55,7 @@ typedef struct SCSIDiskReq {
/* Both sector and sector_count are in terms of qemu 512 byte blocks. */
uint64_t sector;
uint32_t sector_count;
uint32_t buflen;
struct iovec iov;
QEMUIOVector qiov;
uint32_t status;
......@@ -78,13 +79,15 @@ struct SCSIDiskState
};
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type);
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf);
static int scsi_disk_emulate_command(SCSIDiskReq *r);
static void scsi_free_request(SCSIRequest *req)
{
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req);
qemu_vfree(r->iov.iov_base);
if (r->iov.iov_base) {
qemu_vfree(r->iov.iov_base);
}
}
/* Helper function for command completion with sense. */
......@@ -108,6 +111,19 @@ static void scsi_cancel_io(SCSIRequest *req)
r->req.aiocb = NULL;
}
static uint32_t scsi_init_iovec(SCSIDiskReq *r)
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
if (!r->iov.iov_base) {
r->buflen = SCSI_DMA_BUF_SIZE;
r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
}
r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
return r->qiov.size / 512;
}
static void scsi_read_complete(void * opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
......@@ -125,12 +141,12 @@ static void scsi_read_complete(void * opaque, int ret)
}
}
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->iov.iov_len);
DPRINTF("Data ready tag=0x%x len=%zd\n", r->req.tag, r->qiov.size);
n = r->iov.iov_len / 512;
n = r->qiov.size / 512;
r->sector += n;
r->sector_count -= n;
scsi_req_data(&r->req, r->iov.iov_len);
scsi_req_data(&r->req, r->qiov.size);
}
static void scsi_flush_complete(void * opaque, int ret)
......@@ -181,16 +197,10 @@ static void scsi_read_data(SCSIRequest *req)
return;
}
n = r->sector_count;
if (n > SCSI_DMA_BUF_SIZE / 512)
n = SCSI_DMA_BUF_SIZE / 512;
if (s->tray_open) {
scsi_read_complete(r, -ENOMEDIUM);
}
r->iov.iov_len = n * 512;
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
n = scsi_init_iovec(r);
bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
r->req.aiocb = bdrv_aio_readv(s->bs, r->sector, &r->qiov, n,
scsi_read_complete, r);
......@@ -239,7 +249,6 @@ static void scsi_write_complete(void * opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
uint32_t len;
uint32_t n;
if (r->req.aiocb != NULL) {
......@@ -253,19 +262,15 @@ static void scsi_write_complete(void * opaque, int ret)
}
}
n = r->iov.iov_len / 512;
n = r->qiov.size / 512;
r->sector += n;
r->sector_count -= n;
if (r->sector_count == 0) {
scsi_req_complete(&r->req, GOOD);
} else {
len = r->sector_count * 512;
if (len > SCSI_DMA_BUF_SIZE) {
len = SCSI_DMA_BUF_SIZE;
}
r->iov.iov_len = len;
DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, len);
scsi_req_data(&r->req, len);
scsi_init_iovec(r);
DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size);
scsi_req_data(&r->req, r->qiov.size);
}
}
......@@ -284,21 +289,19 @@ static void scsi_write_data(SCSIRequest *req)
return;
}
n = r->iov.iov_len / 512;
n = r->qiov.size / 512;
if (n) {
if (s->tray_open) {
scsi_write_complete(r, -ENOMEDIUM);
}
qemu_iovec_init_external(&r->qiov, &r->iov, 1);
bdrv_acct_start(s->bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
r->req.aiocb = bdrv_aio_writev(s->bs, r->sector, &r->qiov, n,
scsi_write_complete, r);
scsi_write_complete, r);
if (r->req.aiocb == NULL) {
scsi_write_complete(r, -ENOMEM);
}
} else {
/* Invoke completion routine to fetch data from host. */
/* Called for the first time. Ask the driver to send us more data. */
scsi_write_complete(r, 0);
}
}
......@@ -329,7 +332,7 @@ static void scsi_dma_restart_bh(void *opaque)
scsi_write_data(&r->req);
break;
case SCSI_REQ_STATUS_RETRY_FLUSH:
ret = scsi_disk_emulate_command(r, r->iov.iov_base);
ret = scsi_disk_emulate_command(r);
if (ret == 0) {
scsi_req_complete(&r->req, GOOD);
}
......@@ -844,13 +847,31 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
return 0;
}
static int scsi_disk_emulate_command(SCSIDiskReq *r, uint8_t *outbuf)
static int scsi_disk_emulate_command(SCSIDiskReq *r)
{
SCSIRequest *req = &r->req;
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
uint64_t nb_sectors;
uint8_t *outbuf;
int buflen = 0;
if (!r->iov.iov_base) {
/*
* FIXME: we shouldn't return anything bigger than 4k, but the code
* requires the buffer to be as big as req->cmd.xfer in several
* places. So, do not allow CDBs with a very large ALLOCATION
* LENGTH. The real fix would be to modify scsi_read_data and
* dma_buf_read, so that they return data beyond the buflen
* as all zeros.
*/
if (req->cmd.xfer > 65536) {
goto illegal_request;
}
r->buflen = MAX(4096, req->cmd.xfer);
r->iov.iov_base = qemu_blockalign(s->bs, r->buflen);
}
outbuf = r->iov.iov_base;
switch (req->cmd.buf[0]) {
case TEST_UNIT_READY:
if (s->tray_open || !bdrv_is_inserted(s->bs))
......@@ -1001,11 +1022,9 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
int32_t len;
uint8_t command;
uint8_t *outbuf;
int rc;
command = buf[0];
outbuf = (uint8_t *)r->iov.iov_base;
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", req->lun, req->tag, buf[0]);
#ifdef DEBUG_SCSI
......@@ -1034,7 +1053,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
case GET_CONFIGURATION:
case SERVICE_ACTION_IN_16:
case VERIFY_10:
rc = scsi_disk_emulate_command(r, outbuf);
rc = scsi_disk_emulate_command(r);
if (rc < 0) {
return 0;
}
......@@ -1285,11 +1304,8 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag,
{
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d);
SCSIRequest *req;
SCSIDiskReq *r;
req = scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun, hba_private);
r = DO_UPCAST(SCSIDiskReq, req, req);
r->iov.iov_base = qemu_blockalign(s->bs, SCSI_DMA_BUF_SIZE);
return req;
}
......
......@@ -244,12 +244,6 @@ static uint8_t *scsi_get_buf(SCSIRequest *req)
static void scsi_req_fixup(SCSIRequest *req)
{
switch(req->cmd.buf[0]) {
case WRITE_10:
req->cmd.buf[1] &= ~0x08; /* disable FUA */
break;
case READ_10:
req->cmd.buf[1] &= ~0x08; /* disable FUA */
break;
case REWIND:
case START_STOP:
if (req->dev->type == TYPE_TAPE) {
......
......@@ -68,15 +68,6 @@ static void qemu_laio_process_completion(struct qemu_laio_state *s,
qemu_aio_release(laiocb);
}
/*
* All requests are directly processed when they complete, so there's nothing
* left to do during qemu_aio_wait().
*/
static int qemu_laio_process_requests(void *opaque)
{
return 0;
}
static void qemu_laio_completion_cb(void *opaque)
{
struct qemu_laio_state *s = opaque;
......@@ -215,7 +206,7 @@ void *laio_init(void)
goto out_close_efd;
qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, NULL,
qemu_laio_flush_cb, qemu_laio_process_requests, s);
qemu_laio_flush_cb, NULL, s);
return s;
......
......@@ -30,6 +30,10 @@
#include <ctype.h>
#include <inttypes.h>
#ifdef __linux__
#include <linux/fs.h>
#endif
#include "qemu_socket.h"
//#define DEBUG_NBD
......@@ -63,6 +67,8 @@
#define NBD_PRINT_DEBUG _IO(0xab, 6)
#define NBD_SET_SIZE_BLOCKS _IO(0xab, 7)
#define NBD_DISCONNECT _IO(0xab, 8)
#define NBD_SET_TIMEOUT _IO(0xab, 9)
#define NBD_SET_FLAGS _IO(0xab, 10)
#define NBD_OPT_EXPORT_NAME (1 << 0)
......@@ -172,7 +178,7 @@ int unix_socket_outgoing(const char *path)
Request (type == 2)
*/
int nbd_negotiate(int csock, off_t size)
int nbd_negotiate(int csock, off_t size, uint32_t flags)
{
char buf[8 + 8 + 8 + 128];
......@@ -180,14 +186,16 @@ int nbd_negotiate(int csock, off_t size)
[ 0 .. 7] passwd ("NBDMAGIC")
[ 8 .. 15] magic (0x00420281861253)
[16 .. 23] size
[24 .. 151] reserved (0)
[24 .. 27] flags
[28 .. 151] reserved (0)
*/
TRACE("Beginning negotiation.");
memcpy(buf, "NBDMAGIC", 8);
cpu_to_be64w((uint64_t*)(buf + 8), 0x00420281861253LL);
cpu_to_be64w((uint64_t*)(buf + 16), size);
memset(buf + 24, 0, 128);
cpu_to_be32w((uint32_t*)(buf + 24), flags | NBD_FLAG_HAS_FLAGS);
memset(buf + 28, 0, 124);
if (write_sync(csock, buf, sizeof(buf)) != sizeof(buf)) {
LOG("write failed");
......@@ -337,8 +345,8 @@ int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
return 0;
}
#ifndef _WIN32
int nbd_init(int fd, int csock, off_t size, size_t blocksize)
#ifdef __linux__
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize)
{
TRACE("Setting block size to %lu", (unsigned long)blocksize);
......@@ -358,6 +366,26 @@ int nbd_init(int fd, int csock, off_t size, size_t blocksize)
return -1;
}
if (flags & NBD_FLAG_READ_ONLY) {
int read_only = 1;
TRACE("Setting readonly attribute");
if (ioctl(fd, BLKROSET, (unsigned long) &read_only) < 0) {
int serrno = errno;
LOG("Failed setting read-only attribute");
errno = serrno;
return -1;
}
}
if (ioctl(fd, NBD_SET_FLAGS, flags) < 0
&& errno != ENOTTY) {
int serrno = errno;
LOG("Failed setting flags");
errno = serrno;
return -1;
}
TRACE("Clearing NBD socket");
if (ioctl(fd, NBD_CLEAR_SOCK) == -1) {
......@@ -548,7 +576,7 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply)
}
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
off_t *offset, bool readonly, uint8_t *data, int data_size)
off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size)
{
struct nbd_request request;
struct nbd_reply reply;
......@@ -632,7 +660,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
return -1;
}
if (readonly) {
if (nbdflags & NBD_FLAG_READ_ONLY) {
TRACE("Server is read-only, return error");
reply.error = 1;
} else {
......
......@@ -37,10 +37,22 @@ struct nbd_reply {
uint64_t handle;
} QEMU_PACKED;
#define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */
#define NBD_FLAG_READ_ONLY (1 << 1) /* Device is read-only */
#define NBD_FLAG_SEND_FLUSH (1 << 2) /* Send FLUSH */
#define NBD_FLAG_SEND_FUA (1 << 3) /* Send FUA (Force Unit Access) */
#define NBD_FLAG_ROTATIONAL (1 << 4) /* Use elevator algorithm - rotational media */
#define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */
#define NBD_CMD_MASK_COMMAND 0x0000ffff
#define NBD_CMD_FLAG_FUA (1 << 16)
enum {
NBD_CMD_READ = 0,
NBD_CMD_WRITE = 1,
NBD_CMD_DISC = 2
NBD_CMD_DISC = 2,
NBD_CMD_FLUSH = 3,
NBD_CMD_TRIM = 4
};
#define NBD_DEFAULT_PORT 10809
......@@ -53,14 +65,14 @@ int tcp_socket_incoming_spec(const char *address_and_port);
int unix_socket_outgoing(const char *path);
int unix_socket_incoming(const char *path);
int nbd_negotiate(int csock, off_t size);
int nbd_negotiate(int csock, off_t size, uint32_t flags);
int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags,
off_t *size, size_t *blocksize);
int nbd_init(int fd, int csock, off_t size, size_t blocksize);
int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize);
int nbd_send_request(int csock, struct nbd_request *request);
int nbd_receive_reply(int csock, struct nbd_reply *reply);
int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
off_t *offset, bool readonly, uint8_t *data, int data_size);
off_t *offset, uint32_t nbdflags, uint8_t *data, int data_size);
int nbd_client(int fd);
int nbd_disconnect(int fd);
......
......@@ -42,7 +42,6 @@ struct qemu_paiocb {
int aio_niov;
size_t aio_nbytes;
#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */
int ev_signo;
off_t aio_offset;
QTAILQ_ENTRY(qemu_paiocb) node;
......@@ -181,7 +180,6 @@ qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
static ssize_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
{
size_t offset = 0;
ssize_t len;
do {
......@@ -189,12 +187,12 @@ static ssize_t handle_aiocb_rw_vector(struct qemu_paiocb *aiocb)
len = qemu_pwritev(aiocb->aio_fildes,
aiocb->aio_iov,
aiocb->aio_niov,
aiocb->aio_offset + offset);
aiocb->aio_offset);
else
len = qemu_preadv(aiocb->aio_fildes,
aiocb->aio_iov,
aiocb->aio_niov,
aiocb->aio_offset + offset);
aiocb->aio_offset);
} while (len == -1 && errno == EINTR);
if (len == -1)
......@@ -309,12 +307,10 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb)
return nbytes;
}
static void posix_aio_notify_event(void);
static void *aio_thread(void *unused)
{
pid_t pid;
pid = getpid();
mutex_lock(&lock);
pending_threads--;
mutex_unlock(&lock);
......@@ -381,7 +377,7 @@ static void *aio_thread(void *unused)
aiocb->ret = ret;
mutex_unlock(&lock);
if (kill(pid, aiocb->ev_signo)) die("kill failed");
posix_aio_notify_event();
}
cur_threads--;
......@@ -548,18 +544,14 @@ static int posix_aio_flush(void *opaque)
static PosixAioState *posix_aio_state;
static void aio_signal_handler(int signum)
static void posix_aio_notify_event(void)
{
if (posix_aio_state) {
char byte = 0;
ssize_t ret;
ret = write(posix_aio_state->wfd, &byte, sizeof(byte));
if (ret < 0 && errno != EAGAIN)
die("write()");
}
char byte = 0;
ssize_t ret;
qemu_service_io();
ret = write(posix_aio_state->wfd, &byte, sizeof(byte));
if (ret < 0 && errno != EAGAIN)
die("write()");
}
static void paio_remove(struct qemu_paiocb *acb)
......@@ -623,7 +615,6 @@ BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
return NULL;
acb->aio_type = type;
acb->aio_fildes = fd;
acb->ev_signo = SIGUSR2;
if (qiov) {
acb->aio_iov = qiov->iov;
......@@ -651,7 +642,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
return NULL;
acb->aio_type = QEMU_AIO_IOCTL;
acb->aio_fildes = fd;
acb->ev_signo = SIGUSR2;
acb->aio_offset = 0;
acb->aio_ioctl_buf = buf;
acb->aio_ioctl_cmd = req;
......@@ -665,7 +655,6 @@ BlockDriverAIOCB *paio_ioctl(BlockDriverState *bs, int fd,
int paio_init(void)
{
struct sigaction act;
PosixAioState *s;
int fds[2];
int ret;
......@@ -675,11 +664,6 @@ int paio_init(void)
s = g_malloc(sizeof(PosixAioState));
sigfillset(&act.sa_mask);
act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
act.sa_handler = aio_signal_handler;
sigaction(SIGUSR2, &act, NULL);
s->first_aio = NULL;
if (qemu_pipe(fds) == -1) {
fprintf(stderr, "failed to create pipe\n");
......
......@@ -185,7 +185,7 @@ int main(int argc, char **argv)
BlockDriverState *bs;
off_t dev_offset = 0;
off_t offset = 0;
bool readonly = false;
uint32_t nbdflags = 0;
bool disconnect = false;
const char *bindto = "0.0.0.0";
int port = NBD_DEFAULT_PORT;
......@@ -230,7 +230,6 @@ int main(int argc, char **argv)
int nb_fds = 0;
int max_fd;
int persistent = 0;
uint32_t nbdflags;
while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
switch (ch) {
......@@ -263,7 +262,7 @@ int main(int argc, char **argv)
}
break;
case 'r':
readonly = true;
nbdflags |= NBD_FLAG_READ_ONLY;
flags &= ~BDRV_O_RDWR;
break;
case 'P':
......@@ -398,13 +397,13 @@ int main(int argc, char **argv)
}
ret = nbd_receive_negotiate(sock, NULL, &nbdflags,
&size, &blocksize);
&size, &blocksize);
if (ret == -1) {
ret = 1;
goto out;
}
ret = nbd_init(fd, sock, size, blocksize);
ret = nbd_init(fd, sock, nbdflags, size, blocksize);
if (ret == -1) {
ret = 1;
goto out;
......@@ -463,7 +462,7 @@ int main(int argc, char **argv)
for (i = 1; i < nb_fds && ret; i++) {
if (FD_ISSET(sharing_fds[i], &fds)) {
if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset,
&offset, readonly, data, NBD_BUFFER_SIZE) != 0) {
&offset, nbdflags, data, NBD_BUFFER_SIZE) != 0) {
close(sharing_fds[i]);
nb_fds--;
sharing_fds[i] = sharing_fds[nb_fds];
......@@ -479,7 +478,7 @@ int main(int argc, char **argv)
(struct sockaddr *)&addr,
&addr_len);
if (sharing_fds[nb_fds] != -1 &&
nbd_negotiate(sharing_fds[nb_fds], fd_size) != -1) {
nbd_negotiate(sharing_fds[nb_fds], fd_size, nbdflags) != -1) {
if (sharing_fds[nb_fds] > max_fd)
max_fd = sharing_fds[nb_fds];
nb_fds++;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册