From: Christoph Hellwig <hch@lst.de>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers
Date: Mon, 25 May 2009 09:59:49 +0200 [thread overview]
Message-ID: <20090525075949.GC2936@lst.de> (raw)
Instead of declaring one BlockDriver for all host devices declared one
for each type: a generic one for normal disk devices, a Linux floppy
driver and a CDROM driver for Linux and FreeBSD. This gets rid of a lot
of messy ifdefs and switching based on the type in the various removal
device methods.
block.c grows a new method to find the correct host device driver based
on OS-sepcific criteria. I would love to move this into some OS-dependant
file but I don't think we have a place where it fits nicely yet.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: qemu/block.c
===================================================================
--- qemu.orig/block.c 2009-05-25 09:20:12.001840379 +0200
+++ qemu/block.c 2009-05-25 09:29:12.989848226 +0200
@@ -300,32 +300,55 @@ static BlockDriver *find_protocol(const
return NULL;
}
-/* XXX: force raw format if block or character device ? It would
- simplify the BSD case */
-static BlockDriver *find_image_format(const char *filename)
+/*
+ * Detect host devices. By convention, /dev/cdrom[N] is always
+ * recognized as a host CDROM.
+ */
+#ifdef _WIN32
+static BlockDriver *find_hdev_driver(const char *filename)
{
- int ret, score, score_max;
- BlockDriver *drv1, *drv;
- 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");
+ return NULL;
+}
+#else
+static BlockDriver *find_hdev_driver(const char *filename)
+{
+ struct stat st;
+
+#ifdef __linux__
+ if (strstart(filename, "/dev/fd", NULL))
+ return bdrv_find_format("host_floppy");
+ if (strstart(filename, "/dev/cd", NULL))
+ return bdrv_find_format("host_cdrom");
+#elif defined(__FreeBSD__)
+ if (strstart(filename, "/dev/cd", NULL) ||
+ strstart(filename, "/dev/acd", NULL)) {
+ return bdrv_find_format("host_cdrom");
+ }
#else
- {
- struct stat st;
- if (stat(filename, &st) >= 0 &&
+ if (strstart(filename, "/dev/cdrom", NULL))
+ return bdrv_find_format("host_device");
+#endif
+
+ if (stat(filename, &st) >= 0 &&
(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
- return bdrv_find_format("host_device");
- }
+ return bdrv_find_format("host_device");
}
+
+ return NULL;
+}
#endif
+static BlockDriver *find_image_format(const char *filename)
+{
+ int ret, score, score_max;
+ BlockDriver *drv1, *drv;
+ uint8_t buf[2048];
+ BlockDriverState *bs;
+
drv = find_protocol(filename);
/* no need to test disk image formats for vvfat */
if (drv && strcmp(drv->format_name, "vvfat") == 0)
@@ -434,7 +457,10 @@ int bdrv_open2(BlockDriverState *bs, con
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;
Index: qemu/block/raw-posix.c
===================================================================
--- qemu.orig/block/raw-posix.c 2009-05-25 09:24:54.482814647 +0200
+++ qemu/block/raw-posix.c 2009-05-25 09:44:43.931816385 +0200
@@ -119,11 +119,9 @@ static int posix_aio_init(void);
static int fd_open(BlockDriverState *bs);
#if defined(__FreeBSD__)
-static int cd_open(BlockDriverState *bs);
+static int cdrom_reopen(BlockDriverState *bs);
#endif
-static int raw_is_inserted(BlockDriverState *bs);
-
static int raw_open_common(BlockDriverState *bs, const char *filename,
int flags)
{
@@ -803,7 +801,7 @@ again:
if (size == 2048LL * (unsigned)-1)
size = 0;
/* XXX no disc? maybe we need to reopen... */
- if (size <= 0 && !reopened && cd_open(bs) >= 0) {
+ if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
reopened = 1;
goto again;
}
@@ -951,7 +949,6 @@ kern_return_t GetBSDPath( io_iterator_t
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
- int ret;
#ifdef CONFIG_COCOA
if (strstart(filename, "/dev/cdrom", NULL)) {
@@ -981,46 +978,13 @@ static int hdev_open(BlockDriverState *b
#endif
s->type = FTYPE_FILE;
-#if defined(__linux__)
- if (strstart(filename, "/dev/cd", NULL)) {
- /* open will not fail even if no CD is inserted */
- s->open_flags |= O_NONBLOCK;
- s->type = FTYPE_CD;
- } else if (strstart(filename, "/dev/fd", NULL)) {
- s->type = FTYPE_FD;
- /* open will not fail even if no floppy is inserted */
- s->open_flags |= O_NONBLOCK;
-#ifdef CONFIG_AIO
- } else if (strstart(filename, "/dev/sg", NULL)) {
+#if defined(__linux__) && defined(CONFIG_AIO)
+ if (strstart(filename, "/dev/sg", NULL)) {
bs->sg = 1;
-#endif
}
#endif
-#if defined(__FreeBSD__)
- if (strstart(filename, "/dev/cd", NULL) ||
- strstart(filename, "/dev/acd", NULL)) {
- s->type = FTYPE_CD;
- }
-#endif
-
- ret = raw_open_common(bs, filename, flags);
- if (ret)
- return ret;
-#if defined(__FreeBSD__)
- /* make sure the door isnt locked at this time */
- if (s->type == FTYPE_CD)
- ioctl (s->fd, CDIOCALLOW);
-#endif
-#if defined(__linux__)
- /* close fd so that we can reopen it as needed */
- if (s->type == FTYPE_FD) {
- close(s->fd);
- s->fd = -1;
- s->fd_media_changed = 1;
- }
-#endif
- return 0;
+ return raw_open_common(bs, filename, flags);
}
#if defined(__linux__)
@@ -1073,105 +1037,6 @@ static int fd_open(BlockDriverState *bs)
return 0;
}
-static int raw_is_inserted(BlockDriverState *bs)
-{
- BDRVRawState *s = bs->opaque;
- int ret;
-
- switch(s->type) {
- case FTYPE_CD:
- ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
- if (ret == CDS_DISC_OK)
- return 1;
- else
- return 0;
- break;
- case FTYPE_FD:
- ret = fd_open(bs);
- return (ret >= 0);
- default:
- return 1;
- }
-}
-
-/* currently only used by fdc.c, but a CD version would be good too */
-static int raw_media_changed(BlockDriverState *bs)
-{
- BDRVRawState *s = bs->opaque;
-
- switch(s->type) {
- case FTYPE_FD:
- {
- int ret;
- /* XXX: we do not have a true media changed indication. It
- does not work if the floppy is changed without trying
- to read it */
- fd_open(bs);
- ret = s->fd_media_changed;
- s->fd_media_changed = 0;
-#ifdef DEBUG_FLOPPY
- printf("Floppy changed=%d\n", ret);
-#endif
- return ret;
- }
- default:
- return -ENOTSUP;
- }
-}
-
-static int raw_eject(BlockDriverState *bs, int eject_flag)
-{
- BDRVRawState *s = bs->opaque;
-
- switch(s->type) {
- case FTYPE_CD:
- if (eject_flag) {
- if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
- perror("CDROMEJECT");
- } else {
- if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
- perror("CDROMEJECT");
- }
- break;
- case FTYPE_FD:
- {
- int fd;
- if (s->fd >= 0) {
- close(s->fd);
- s->fd = -1;
- }
- fd = open(bs->filename, s->open_flags | O_NONBLOCK);
- if (fd >= 0) {
- if (ioctl(fd, FDEJECT, 0) < 0)
- perror("FDEJECT");
- close(fd);
- }
- }
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
-}
-
-static int raw_set_locked(BlockDriverState *bs, int locked)
-{
- BDRVRawState *s = bs->opaque;
-
- switch(s->type) {
- case FTYPE_CD:
- if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
- /* Note: an error can happen if the distribution automatically
- mounts the CD-ROM */
- // perror("CDROM_LOCKDOOR");
- }
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
-}
-
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
BDRVRawState *s = bs->opaque;
@@ -1213,7 +1078,6 @@ static BlockDriverAIOCB *raw_aio_ioctl(B
#endif
#elif defined(__FreeBSD__)
-
static int fd_open(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
@@ -1224,99 +1088,6 @@ static int fd_open(BlockDriverState *bs)
return -EIO;
}
-static int cd_open(BlockDriverState *bs)
-{
-#if defined(__FreeBSD__)
- BDRVRawState *s = bs->opaque;
- int fd;
-
- switch(s->type) {
- case FTYPE_CD:
- /* XXX force reread of possibly changed/newly loaded disc,
- * FreeBSD seems to not notice sometimes... */
- if (s->fd >= 0)
- close (s->fd);
- fd = open(bs->filename, s->open_flags, 0644);
- if (fd < 0) {
- s->fd = -1;
- return -EIO;
- }
- s->fd = fd;
- /* make sure the door isnt locked at this time */
- ioctl (s->fd, CDIOCALLOW);
- }
-#endif
- return 0;
-}
-
-static int raw_is_inserted(BlockDriverState *bs)
-{
- BDRVRawState *s = bs->opaque;
-
- switch(s->type) {
- case FTYPE_CD:
- return (raw_getlength(bs) > 0);
- case FTYPE_FD:
- /* XXX handle this */
- /* FALLTHRU */
- default:
- return 1;
- }
-}
-
-static int raw_media_changed(BlockDriverState *bs)
-{
- return -ENOTSUP;
-}
-
-static int raw_eject(BlockDriverState *bs, int eject_flag)
-{
- BDRVRawState *s = bs->opaque;
-
- switch(s->type) {
- case FTYPE_CD:
- if (s->fd < 0)
- return -ENOTSUP;
- (void) ioctl (s->fd, CDIOCALLOW);
- if (eject_flag) {
- if (ioctl (s->fd, CDIOCEJECT) < 0)
- perror("CDIOCEJECT");
- } else {
- if (ioctl (s->fd, CDIOCCLOSE) < 0)
- perror("CDIOCCLOSE");
- }
- if (cd_open(bs) < 0)
- return -ENOTSUP;
- break;
- case FTYPE_FD:
- /* XXX handle this */
- /* FALLTHRU */
- default:
- return -ENOTSUP;
- }
- return 0;
-}
-
-static int raw_set_locked(BlockDriverState *bs, int locked)
-{
- BDRVRawState *s = bs->opaque;
-
- switch(s->type) {
- case FTYPE_CD:
- if (s->fd < 0)
- return -ENOTSUP;
- if (ioctl (s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
- /* Note: an error can happen if the distribution automatically
- mounts the CD-ROM */
- // perror("CDROM_LOCKDOOR");
- }
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
-}
-
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
return -ENOTSUP;
@@ -1328,26 +1099,6 @@ static int fd_open(BlockDriverState *bs)
return 0;
}
-static int raw_is_inserted(BlockDriverState *bs)
-{
- return 1;
-}
-
-static int raw_media_changed(BlockDriverState *bs)
-{
- return -ENOTSUP;
-}
-
-static int raw_eject(BlockDriverState *bs, int eject_flag)
-{
- return -ENOTSUP;
-}
-
-static int raw_set_locked(BlockDriverState *bs, int locked)
-{
- return -ENOTSUP;
-}
-
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
return -ENOTSUP;
@@ -1419,22 +1170,321 @@ static BlockDriver bdrv_host_device = {
.bdrv_write = raw_write,
.bdrv_getlength = raw_getlength,
+ /* generic scsi device */
+ .bdrv_ioctl = raw_ioctl,
+#ifdef CONFIG_AIO
+ .bdrv_aio_ioctl = raw_aio_ioctl,
+#endif
+};
+
+#ifdef __linux__
+static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
+{
+ BDRVRawState *s = bs->opaque;
+ int ret;
+
+ posix_aio_init();
+
+ s->type = FTYPE_FD;
+ /* open will not fail even if no floppy is inserted */
+ s->open_flags |= O_NONBLOCK;
+
+ ret = raw_open_common(bs, filename, flags);
+ if (ret)
+ return ret;
+
+ /* close fd so that we can reopen it as needed */
+ close(s->fd);
+ s->fd = -1;
+ s->fd_media_changed = 1;
+
+ return 0;
+}
+
+static int floppy_is_inserted(BlockDriverState *bs)
+{
+ return fd_open(bs) >= 0;
+}
+
+static int floppy_media_changed(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+ int ret;
+
+ /*
+ * XXX: we do not have a true media changed indication.
+ * It does not work if the floppy is changed without trying to read it.
+ */
+ fd_open(bs);
+ ret = s->fd_media_changed;
+ s->fd_media_changed = 0;
+#ifdef DEBUG_FLOPPY
+ printf("Floppy changed=%d\n", ret);
+#endif
+ return ret;
+}
+
+static int floppy_eject(BlockDriverState *bs, int eject_flag)
+{
+ BDRVRawState *s = bs->opaque;
+ int fd;
+
+ if (s->fd >= 0) {
+ close(s->fd);
+ s->fd = -1;
+ }
+ fd = open(bs->filename, s->open_flags | O_NONBLOCK);
+ if (fd >= 0) {
+ if (ioctl(fd, FDEJECT, 0) < 0)
+ perror("FDEJECT");
+ close(fd);
+ }
+
+ return 0;
+}
+
+static BlockDriver bdrv_host_floppy = {
+ .format_name = "host_floppy",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_open = floppy_open,
+ .bdrv_close = raw_close,
+ .bdrv_create = hdev_create,
+ .bdrv_flush = raw_flush,
+
+#ifdef CONFIG_AIO
+ .bdrv_aio_readv = raw_aio_readv,
+ .bdrv_aio_writev = raw_aio_writev,
+ .bdrv_aio_cancel = raw_aio_cancel,
+ .aiocb_size = sizeof(RawAIOCB),
+#endif
+
+ .bdrv_read = raw_read,
+ .bdrv_write = raw_write,
+ .bdrv_getlength = raw_getlength,
+
/* removable device support */
- .bdrv_is_inserted = raw_is_inserted,
- .bdrv_media_changed = raw_media_changed,
- .bdrv_eject = raw_eject,
- .bdrv_set_locked = raw_set_locked,
+ .bdrv_is_inserted = floppy_is_inserted,
+ .bdrv_media_changed = floppy_media_changed,
+ .bdrv_eject = floppy_eject,
+
/* generic scsi device */
- .bdrv_ioctl = raw_ioctl,
+ .bdrv_ioctl = raw_ioctl,
#ifdef CONFIG_AIO
- .bdrv_aio_ioctl = raw_aio_ioctl,
+ .bdrv_aio_ioctl = raw_aio_ioctl,
#endif
};
+static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
+{
+ BDRVRawState *s = bs->opaque;
+
+ /* open will not fail even if no CD is inserted */
+ s->open_flags |= O_NONBLOCK;
+ s->type = FTYPE_CD;
+
+ return raw_open_common(bs, filename, flags);
+}
+
+static int cdrom_is_inserted(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+ int ret;
+
+ ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+ if (ret == CDS_DISC_OK)
+ return 1;
+ return 0;
+}
+
+static int cdrom_eject(BlockDriverState *bs, int eject_flag)
+{
+ BDRVRawState *s = bs->opaque;
+
+ if (eject_flag) {
+ if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
+ perror("CDROMEJECT");
+ } else {
+ if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
+ perror("CDROMEJECT");
+ }
+
+ return 0;
+}
+
+static int cdrom_set_locked(BlockDriverState *bs, int locked)
+{
+ BDRVRawState *s = bs->opaque;
+
+ if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
+ /*
+ * Note: an error can happen if the distribution automatically
+ * mounts the CD-ROM
+ */
+ /* perror("CDROM_LOCKDOOR"); */
+ }
+
+ return 0;
+}
+
+static BlockDriver bdrv_host_cdrom = {
+ .format_name = "host_cdrom",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_open = cdrom_open,
+ .bdrv_close = raw_close,
+ .bdrv_create = hdev_create,
+ .bdrv_flush = raw_flush,
+
+#ifdef CONFIG_AIO
+ .bdrv_aio_readv = raw_aio_readv,
+ .bdrv_aio_writev = raw_aio_writev,
+ .bdrv_aio_cancel = raw_aio_cancel,
+ .aiocb_size = sizeof(RawAIOCB),
+#endif
+
+ .bdrv_read = raw_read,
+ .bdrv_write = raw_write,
+ .bdrv_getlength = raw_getlength,
+
+ /* removable device support */
+ .bdrv_is_inserted = cdrom_is_inserted,
+ .bdrv_eject = cdrom_eject,
+ .bdrv_set_locked = cdrom_set_locked,
+
+ /* generic scsi device */
+ .bdrv_ioctl = raw_ioctl,
+#ifdef CONFIG_AIO
+ .bdrv_aio_ioctl = raw_aio_ioctl,
+#endif
+};
+#endif /* __linux__ */
+
+#ifdef __FreeBSD__
+static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
+{
+ BDRVRawState *s = bs->opaque;
+ int ret;
+
+ s->type = FTYPE_CD;
+
+ ret = raw_open_common(bs, filename, flags);
+ if (ret)
+ return ret;
+
+ /* make sure the door isnt locked at this time */
+ ioctl(s->fd, CDIOCALLOW);
+ return 0;
+}
+
+static int cdrom_reopen(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+ int fd;
+
+ /*
+ * Force reread of possibly changed/newly loaded disc,
+ * FreeBSD seems to not notice sometimes...
+ */
+ if (s->fd >= 0)
+ close(s->fd);
+ fd = open(bs->filename, s->open_flags, 0644);
+ if (fd < 0) {
+ s->fd = -1;
+ return -EIO;
+ }
+ s->fd = fd;
+
+ /* make sure the door isnt locked at this time */
+ ioctl(s->fd, CDIOCALLOW);
+ return 0;
+}
+
+static int cdrom_is_inserted(BlockDriverState *bs)
+{
+ return raw_getlength(bs) > 0;
+}
+
+static int cdrom_eject(BlockDriverState *bs, int eject_flag)
+{
+ BDRVRawState *s = bs->opaque;
+
+ if (s->fd < 0)
+ return -ENOTSUP;
+
+ (void) ioctl(s->fd, CDIOCALLOW);
+
+ if (eject_flag) {
+ if (ioctl(s->fd, CDIOCEJECT) < 0)
+ perror("CDIOCEJECT");
+ } else {
+ if (ioctl(s->fd, CDIOCCLOSE) < 0)
+ perror("CDIOCCLOSE");
+ }
+
+ if (cdrom_reopen(bs) < 0)
+ return -ENOTSUP;
+ return 0;
+}
+
+static int cdrom_set_locked(BlockDriverState *bs, int locked)
+{
+ BDRVRawState *s = bs->opaque;
+
+ if (s->fd < 0)
+ return -ENOTSUP;
+ if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
+ /*
+ * Note: an error can happen if the distribution automatically
+ * mounts the CD-ROM
+ */
+ /* perror("CDROM_LOCKDOOR"); */
+ }
+
+ return 0;
+}
+
+static BlockDriver bdrv_host_cdrom = {
+ .format_name = "host_cdrom",
+ .instance_size = sizeof(BDRVRawState),
+ .bdrv_open = cdrom_open,
+ .bdrv_close = raw_close,
+ .bdrv_create = hdev_create,
+ .bdrv_flush = raw_flush,
+
+#ifdef CONFIG_AIO
+ .bdrv_aio_readv = raw_aio_readv,
+ .bdrv_aio_writev = raw_aio_writev,
+ .bdrv_aio_cancel = raw_aio_cancel,
+ .aiocb_size = sizeof(RawAIOCB),
+#endif
+
+ .bdrv_read = raw_read,
+ .bdrv_write = raw_write,
+ .bdrv_getlength = raw_getlength,
+
+ /* removable device support */
+ .bdrv_is_inserted = cdrom_is_inserted,
+ .bdrv_eject = cdrom_eject,
+ .bdrv_set_locked = cdrom_set_locked,
+
+ /* generic scsi device */
+ .bdrv_ioctl = raw_ioctl,
+#ifdef CONFIG_AIO
+ .bdrv_aio_ioctl = raw_aio_ioctl,
+#endif
+};
+#endif /* __FreeBSD__ */
+
static void bdrv_raw_init(void)
{
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_host_device);
+#ifdef __linux__
+ bdrv_register(&bdrv_host_floppy);
+ bdrv_register(&bdrv_host_cdrom);
+#endif
+#ifdef __FreeBSD__
+ bdrv_register(&bdrv_host_cdrom);
+#endif
}
block_init(bdrv_raw_init);
next reply other threads:[~2009-05-25 7:59 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-25 7:59 Christoph Hellwig [this message]
2009-05-25 11:08 ` [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers Avi Kivity
2009-05-25 12:33 ` Christoph Hellwig
2009-05-26 8:57 ` Christoph Hellwig
2009-06-06 14:53 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090525075949.GC2936@lst.de \
--to=hch@lst.de \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.