qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers
@ 2009-05-25  7:59 Christoph Hellwig
  2009-05-25 11:08 ` Avi Kivity
  2009-06-06 14:53 ` Christoph Hellwig
  0 siblings, 2 replies; 5+ messages in thread
From: Christoph Hellwig @ 2009-05-25  7:59 UTC (permalink / raw)
  To: qemu-devel

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);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers
  2009-05-25  7:59 [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers Christoph Hellwig
@ 2009-05-25 11:08 ` Avi Kivity
  2009-05-25 12:33   ` Christoph Hellwig
  2009-05-26  8:57   ` Christoph Hellwig
  2009-06-06 14:53 ` Christoph Hellwig
  1 sibling, 2 replies; 5+ messages in thread
From: Avi Kivity @ 2009-05-25 11:08 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: qemu-devel

Christoph Hellwig wrote:
> 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.
>
>   

Add a ->probe_host_device() which accepts the filename (or maybe an fd) 
as a parameter.  First pass does a ->probe_host_device() for all drivers 
that support it, second pass tries ->probe().

btw, ->probe_host_device() should use ioctls to identify the device, not 
the device name, which is controlled by udev (on Linux) and therefore 
nonstandard.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers
  2009-05-25 11:08 ` Avi Kivity
@ 2009-05-25 12:33   ` Christoph Hellwig
  2009-05-26  8:57   ` Christoph Hellwig
  1 sibling, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2009-05-25 12:33 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Christoph Hellwig, qemu-devel

On Mon, May 25, 2009 at 02:08:10PM +0300, Avi Kivity wrote:
> >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.
> >
> >  
> 
> Add a ->probe_host_device() which accepts the filename (or maybe an fd) 
> as a parameter.  First pass does a ->probe_host_device() for all drivers 
> that support it, second pass tries ->probe().

Yeah, we could probably do that.  That means we could also move the
is_windows_drive into raw-win32.c.

> btw, ->probe_host_device() should use ioctls to identify the device, not 
> the device name, which is controlled by udev (on Linux) and therefore 
> nonstandard.

At least the /dev/cdrom name is a symbolic overload in qemu and should
always resolve to a cdrom device, if it's for some reason not present
in the host namespace we need to do similar hacks as the windows raw
driver.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers
  2009-05-25 11:08 ` Avi Kivity
  2009-05-25 12:33   ` Christoph Hellwig
@ 2009-05-26  8:57   ` Christoph Hellwig
  1 sibling, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2009-05-26  8:57 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Christoph Hellwig, qemu-devel

On Mon, May 25, 2009 at 02:08:10PM +0300, Avi Kivity wrote:
> Christoph Hellwig wrote:
> >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.
> >
> >  
> 
> Add a ->probe_host_device() which accepts the filename (or maybe an fd) 
> as a parameter.  First pass does a ->probe_host_device() for all drivers 
> that support it, second pass tries ->probe().

Here's a patch to implement that incrementally.  I wonder why we have
the is_windows_drive check in find_protocol - shouldn't that be handled
entirely in find_hdev_driver?


Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: qemu/block/raw-posix.c
===================================================================
--- qemu.orig/block/raw-posix.c	2009-05-26 10:42:04.372841227 +0200
+++ qemu/block/raw-posix.c	2009-05-26 10:44:15.290813943 +0200
@@ -946,6 +946,22 @@ kern_return_t GetBSDPath( io_iterator_t 
 
 #endif
 
+static int hdev_probe_device(const char *filename)
+{
+    struct stat st;
+
+    /* allow a dedicated CD-ROM driver to match with a higher priority */
+    if (strstart(filename, "/dev/cdrom", NULL))
+        return 50;
+
+    if (stat(filename, &st) >= 0 &&
+            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
+        return 100;
+    }
+
+    return 0;
+}
+
 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVRawState *s = bs->opaque;
@@ -1138,6 +1154,7 @@ static int hdev_create(const char *filen
 static BlockDriver bdrv_host_device = {
     .format_name	= "host_device",
     .instance_size	= sizeof(BDRVRawState),
+    .bdrv_probe_device	= hdev_probe_device,
     .bdrv_open		= hdev_open,
     .bdrv_close		= raw_close,
     .bdrv_create        = hdev_create,
@@ -1187,6 +1204,14 @@ static int floppy_open(BlockDriverState 
     return 0;
 }
 
+static int floppy_probe_device(const char *filename)
+{
+    if (strstart(filename, "/dev/fd", NULL))
+        return 100;
+    return 0;
+}
+
+
 static int floppy_is_inserted(BlockDriverState *bs)
 {
     return fd_open(bs) >= 0;
@@ -1232,6 +1257,7 @@ static int floppy_eject(BlockDriverState
 static BlockDriver bdrv_host_floppy = {
     .format_name        = "host_floppy",
     .instance_size      = sizeof(BDRVRawState),
+    .bdrv_probe_device	= floppy_probe_device,
     .bdrv_open          = floppy_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
@@ -1265,6 +1291,13 @@ static int cdrom_open(BlockDriverState *
     return raw_open_common(bs, filename, flags);
 }
 
+static int cdrom_probe_device(const char *filename)
+{
+    if (strstart(filename, "/dev/cd", NULL))
+        return 100;
+    return 0;
+}
+
 static int cdrom_is_inserted(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
@@ -1309,6 +1342,7 @@ static int cdrom_set_locked(BlockDriverS
 static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
+    .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_open          = cdrom_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
@@ -1355,6 +1389,14 @@ static int cdrom_open(BlockDriverState *
     return 0;
 }
 
+static int cdrom_probe_device(const char *filename)
+{
+    if (strstart(filename, "/dev/cd", NULL) ||
+            strstart(filename, "/dev/acd", NULL))
+        return 100;
+    return 0;
+}
+
 static int cdrom_reopen(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
@@ -1425,6 +1467,7 @@ static int cdrom_set_locked(BlockDriverS
 static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
+    .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_open          = cdrom_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
Index: qemu/block_int.h
===================================================================
--- qemu.orig/block_int.h	2009-05-26 10:42:04.391815291 +0200
+++ qemu/block_int.h	2009-05-26 10:51:38.200838865 +0200
@@ -48,6 +48,7 @@ struct BlockDriver {
     const char *format_name;
     int instance_size;
     int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
+    int (*bdrv_probe_device)(const char *filename);
     int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
     int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
                      uint8_t *buf, int nb_sectors);
@@ -186,4 +187,8 @@ void *qemu_blockalign(BlockDriverState *
 
 extern BlockDriverState *bdrv_first;
 
+#ifdef _WIN32
+int is_windows_drive(const char *filename);
+#endif
+
 #endif /* BLOCK_INT_H */
Index: qemu/block.c
===================================================================
--- qemu.orig/block.c	2009-05-26 10:42:04.400815321 +0200
+++ qemu/block.c	2009-05-26 10:51:20.142813836 +0200
@@ -260,7 +260,7 @@ static int is_windows_drive_prefix(const
             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')
@@ -304,43 +304,23 @@ static BlockDriver *find_protocol(const 
  * 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)
 {
-    if (strstart(filename, "/dev/cdrom", NULL))
-        return bdrv_find_format("host_device");
-    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;
+    int score_max = 0, score;
+    BlockDriver *drv = NULL, *d;
 
-#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
-    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");
+    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 NULL;
+    return drv;
 }
-#endif
 
 static BlockDriver *find_image_format(const char *filename)
 {
Index: qemu/block/raw-win32.c
===================================================================
--- qemu.orig/block/raw-win32.c	2009-05-26 10:42:04.383816228 +0200
+++ qemu/block/raw-win32.c	2009-05-26 10:50:57.934985432 +0200
@@ -302,6 +302,15 @@ static int find_device_type(BlockDriverS
     }
 }
 
+static int hdev_probe_device(const char *filename)
+{
+    if (strstart(filename, "/dev/cdrom", NULL))
+        return 100;
+    if (is_windows_drive(filename))
+        return 100;
+    return 0;
+}
+
 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVRawState *s = bs->opaque;
@@ -387,6 +396,7 @@ static int raw_set_locked(BlockDriverSta
 static BlockDriver bdrv_host_device = {
     .format_name	= "host_device",
     .instance_size	= sizeof(BDRVRawState),
+    .bdrv_probe_device	= hdev_probe_device,
     .bdrv_open		= hdev_open,
     .bdrv_close		= raw_close,
     .bdrv_flush		= raw_flush,

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers
  2009-05-25  7:59 [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers Christoph Hellwig
  2009-05-25 11:08 ` Avi Kivity
@ 2009-06-06 14:53 ` Christoph Hellwig
  1 sibling, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2009-06-06 14:53 UTC (permalink / raw)
  To: qemu-devel

Updated version that applies to the current tree with the aio pool
changes already applied:

--

Subject: raw-posix: split hdev drivers
From: Christoph Hellwig <hch@lst.de>

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-06-06 16:49:33.437814623 +0200
+++ qemu/block.c	2009-06-06 16:50:46.175939285 +0200
@@ -249,32 +249,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)
@@ -394,7 +417,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-06-06 16:50:42.814818554 +0200
+++ qemu/block/raw-posix.c	2009-06-06 16:51:05.269939118 +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)
 {
@@ -808,7 +806,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;
             }
@@ -954,7 +952,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)) {
@@ -984,46 +981,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__)
@@ -1076,105 +1040,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;
@@ -1216,7 +1081,6 @@ static BlockDriverAIOCB *raw_aio_ioctl(B
 #endif
 
 #elif defined(__FreeBSD__)
-
 static int fd_open(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
@@ -1227,99 +1091,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;
@@ -1331,26 +1102,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;
@@ -1411,22 +1162,315 @@ 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,
+#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,
+#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,
+#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);

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-06-06 14:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-25  7:59 [Qemu-devel] [PATCH 3/4] raw-posix: split hdev drivers Christoph Hellwig
2009-05-25 11:08 ` Avi Kivity
2009-05-25 12:33   ` Christoph Hellwig
2009-05-26  8:57   ` Christoph Hellwig
2009-06-06 14:53 ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).