* THE SOFTWARE.
*/
#include "config-host.h"
-#ifdef HOST_BSD
+#ifdef CONFIG_BSD
/* include native header before sys-queue.h */
#include <sys/queue.h>
#endif
#include "block_int.h"
#include "module.h"
-#ifdef HOST_BSD
+#ifdef CONFIG_BSD
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#define SECTOR_BITS 9
#define SECTOR_SIZE (1 << SECTOR_BITS)
-typedef struct BlockDriverAIOCBSync {
- BlockDriverAIOCB common;
- QEMUBH *bh;
- int ret;
- /* vector translation state */
- QEMUIOVector *qiov;
- uint8_t *bounce;
- int is_write;
-} BlockDriverAIOCBSync;
-
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
-static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
}
}
-
void bdrv_register(BlockDriver *bdrv)
{
if (!bdrv->bdrv_aio_readv) {
/* add AIO emulation layer */
bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
- bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
- bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
} else if (!bdrv->bdrv_read) {
/* add synchronous IO emulation layer */
bdrv->bdrv_read = bdrv_read_em;
bdrv->bdrv_write = bdrv_write_em;
}
- aio_pool_init(&bdrv->aio_pool, bdrv->aiocb_size, bdrv->bdrv_aio_cancel);
bdrv->next = first_drv;
first_drv = bdrv;
}
filename[1] == ':');
}
-static int is_windows_drive(const char *filename)
+int is_windows_drive(const char *filename)
{
if (is_windows_drive_prefix(filename) &&
filename[2] == '\0')
return NULL;
}
-/* XXX: force raw format if block or character device ? It would
- simplify the BSD case */
+/*
+ * Detect host devices. By convention, /dev/cdrom[N] is always
+ * recognized as a host CDROM.
+ */
+static BlockDriver *find_hdev_driver(const char *filename)
+{
+ int score_max = 0, score;
+ BlockDriver *drv = NULL, *d;
+
+ for (d = first_drv; d; d = d->next) {
+ if (d->bdrv_probe_device) {
+ score = d->bdrv_probe_device(filename);
+ if (score > score_max) {
+ score_max = score;
+ drv = d;
+ }
+ }
+ }
+
+ return drv;
+}
+
static BlockDriver *find_image_format(const char *filename)
{
int ret, score, score_max;
uint8_t buf[2048];
BlockDriverState *bs;
- /* detect host devices. By convention, /dev/cdrom[N] is always
- recognized as a host CDROM */
- if (strstart(filename, "/dev/cdrom", NULL))
- return bdrv_find_format("host_device");
-#ifdef _WIN32
- if (is_windows_drive(filename))
- return bdrv_find_format("host_device");
-#else
- {
- struct stat st;
- if (stat(filename, &st) >= 0 &&
- (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
- return bdrv_find_format("host_device");
- }
- }
-#endif
-
drv = find_protocol(filename);
/* no need to test disk image formats for vvfat */
if (drv && strcmp(drv->format_name, "vvfat") == 0)
if (flags & BDRV_O_FILE) {
drv = find_protocol(filename);
} else if (!drv) {
- drv = find_image_format(filename);
+ drv = find_hdev_driver(filename);
+ if (!drv) {
+ drv = find_image_format(filename);
+ }
}
if (!drv) {
ret = -ENOENT;
return drv->bdrv_get_info(bs, bdi);
}
-int bdrv_put_buffer(BlockDriverState *bs, const uint8_t *buf, int64_t pos, int size)
+int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
+ int64_t pos, int size)
{
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_put_buffer)
+ if (!drv->bdrv_save_vmstate)
return -ENOTSUP;
- return drv->bdrv_put_buffer(bs, buf, pos, size);
+ return drv->bdrv_save_vmstate(bs, buf, pos, size);
}
-int bdrv_get_buffer(BlockDriverState *bs, uint8_t *buf, int64_t pos, int size)
+int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
+ int64_t pos, int size)
{
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_get_buffer)
+ if (!drv->bdrv_load_vmstate)
return -ENOTSUP;
- return drv->bdrv_get_buffer(bs, buf, pos, size);
+ return drv->bdrv_load_vmstate(bs, buf, pos, size);
}
/**************************************************************/
/**************************************************************/
/* async block device emulation */
+typedef struct BlockDriverAIOCBSync {
+ BlockDriverAIOCB common;
+ QEMUBH *bh;
+ int ret;
+ /* vector translation state */
+ QEMUIOVector *qiov;
+ uint8_t *bounce;
+ int is_write;
+} BlockDriverAIOCBSync;
+
+static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
+{
+ BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
+ qemu_bh_delete(acb->bh);
+ acb->bh = NULL;
+ qemu_aio_release(acb);
+}
+
+static AIOPool bdrv_em_aio_pool = {
+ .aiocb_size = sizeof(BlockDriverAIOCBSync),
+ .cancel = bdrv_aio_cancel_em,
+};
+
static void bdrv_aio_bh_cb(void *opaque)
{
BlockDriverAIOCBSync *acb = opaque;
qemu_iovec_from_buffer(acb->qiov, acb->bounce, acb->qiov->size);
qemu_vfree(acb->bounce);
acb->common.cb(acb->common.opaque, acb->ret);
-
+ qemu_bh_delete(acb->bh);
+ acb->bh = NULL;
qemu_aio_release(acb);
}
{
BlockDriverAIOCBSync *acb;
- acb = qemu_aio_get(bs, cb, opaque);
+ acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
acb->is_write = is_write;
acb->qiov = qiov;
acb->bounce = qemu_blockalign(bs, qiov->size);
return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
}
-
-static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
-{
- BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
- qemu_bh_cancel(acb->bh);
- qemu_aio_release(acb);
-}
-
/**************************************************************/
/* sync block device emulation */
module_call_init(MODULE_INIT_BLOCK);
}
-void aio_pool_init(AIOPool *pool, int aiocb_size,
- void (*cancel)(BlockDriverAIOCB *acb))
-{
- pool->aiocb_size = aiocb_size;
- pool->cancel = cancel;
- pool->free_aiocb = NULL;
-}
-
-void *qemu_aio_get_pool(AIOPool *pool, BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque)
+void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs,
+ BlockDriverCompletionFunc *cb, void *opaque)
{
BlockDriverAIOCB *acb;
return acb;
}
-void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
- void *opaque)
-{
- return qemu_aio_get_pool(&bs->drv->aio_pool, bs, cb, opaque);
-}
-
void qemu_aio_release(void *p)
{
BlockDriverAIOCB *acb = (BlockDriverAIOCB *)p;
/**
* If eject_flag is TRUE, eject the media. Otherwise, close the tray
*/
-void bdrv_eject(BlockDriverState *bs, int eject_flag)
+int bdrv_eject(BlockDriverState *bs, int eject_flag)
{
BlockDriver *drv = bs->drv;
int ret;
+ if (bs->locked) {
+ return -EBUSY;
+ }
+
if (!drv || !drv->bdrv_eject) {
ret = -ENOTSUP;
} else {
if (ret == -ENOTSUP) {
if (eject_flag)
bdrv_close(bs);
+ ret = 0;
}
+
+ return ret;
}
int bdrv_is_locked(BlockDriverState *bs)