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

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

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