diff mbox

[v2] raw-posix.c: remove raw device access for cdrom

Message ID B8BCD4C1-1928-4BC3-9FE6-4D238E87DFA8@gmail.com
State New
Headers show

Commit Message

Programmingkid July 3, 2015, 12:46 a.m. UTC
Allows QEMU running on Mac OS X guest to use the real
CD-ROM drive.

This patch doesn't actually remove raw device access. I'm just
using the same name as the last patch.

Why should we test for /dev/disk1s0 when /dev/rdisk1s0 works?
By avoiding using the raw device we gain speed. When a read
takes place for the raw CD-ROM device, it has to start spinning
up if it went to sleep. This takes time to do. Plus there is 
that annoying spin up sound. With the non-raw access, QEMU
can use the operating system's buffers to do its reading. 
This means faster and quieter access. 

I have noticed that in order to use /dev/disk1s0, the CD-ROM
had to be unmounted (but not ejected) from the desktop. 
Disk Utility is what I used to accomplish this. 

Signed-off-by: John Arbuckle <programmingkidx@gmail.com>

---
Tries more permutations of the CD-ROM device file.
Sets the needs_alignment variable.
Removes the unused kernResult variable.

 block/raw-posix.c |   62 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 52 insertions(+), 10 deletions(-)
diff mbox

Patch

diff --git a/block/raw-posix.c b/block/raw-posix.c
index cbe6574..2088c1f 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -484,6 +484,19 @@  static int raw_open_common(BlockDriverState *bs, QDict *options,
 
     filename = qemu_opt_get(opts, "filename");
 
+#ifdef __APPLE__
+
+    /*
+     * Raw CD-ROM access on a Macintosh needs to be aligned
+     * or reads will fail.
+     */
+
+    if (strncmp(filename, "/dev/r", 6) == 0) {
+        s->needs_alignment = true;
+    }
+
+#endif  /* __APPLE__ */
+
     ret = raw_normalize_devicepath(&filename);
     if (ret != 0) {
         error_setg_errno(errp, -ret, "Could not normalize device path");
@@ -2014,7 +2027,6 @@  kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma
         if ( bsdPathAsCFString ) {
             size_t devPathLength;
             strcpy( bsdPath, _PATH_DEV );
-            strcat( bsdPath, "r" );
             devPathLength = strlen( bsdPath );
             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
                 kernResult = KERN_SUCCESS;
@@ -2120,25 +2132,55 @@  static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
     const char *filename = qdict_get_str(options, "filename");
 
     if (strstart(filename, "/dev/cdrom", NULL)) {
-        kern_return_t kernResult;
         io_iterator_t mediaIterator;
         char bsdPath[ MAXPATHLEN ];
         int fd;
 
-        kernResult = FindEjectableCDMedia( &mediaIterator );
-        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
+        FindEjectableCDMedia(&mediaIterator);
+        GetBSDPath(mediaIterator, bsdPath, sizeof(bsdPath));
 
         if ( bsdPath[ 0 ] != '\0' ) {
-            strcat(bsdPath,"s0");
-            /* some CDs don't have a partition 0 */
-            fd = qemu_open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
-            if (fd < 0) {
-                bsdPath[strlen(bsdPath)-1] = '1';
-            } else {
+            int devStringLength = strlen("/dev/");
+            char baseDeviceName[MAXPATHLEN];
+            int numberOfOptions = 4;
+            char deviceNameArray[numberOfOptions][MAXPATHLEN];
+            int i = 0;
+
+            /* remove the "/dev/" part from the device file's name */
+            strcpy(baseDeviceName, bsdPath + devStringLength);
+
+            /* /dev/disk*s0 */
+            sprintf(deviceNameArray[i++], "/dev/%ss0", baseDeviceName);
+
+            /* /dev/disk*s1 */
+            sprintf(deviceNameArray[i++], "/dev/%ss1", baseDeviceName);
+
+            /* /dev/rdisk*s0 */
+            sprintf(deviceNameArray[i++], "/dev/r%ss0", baseDeviceName);
+
+            /* /dev/rdisk*s1 */
+            sprintf(deviceNameArray[i++], "/dev/r%ss1", baseDeviceName);
+
+            /* Try device file permutions until one works */
+            for (i = 0; i < numberOfOptions; i++) {
+                fd = qemu_open(deviceNameArray[i], O_RDONLY | O_BINARY
+                                                            | O_LARGEFILE);
+                if (fd < 0) {
+                    DPRINTF("Error opening %s: %s\n", deviceNameArray[i]
+                                                    , strerror(errno));
+                } else {
+                    strcpy(bsdPath, (char *)deviceNameArray[i]);
+                    break;
+                }
+            }
+
+            if (fd > 0) {
                 qemu_close(fd);
             }
+
             filename = bsdPath;
             qdict_put(options, "filename", qstring_from_str(filename));
+            DPRINTF("cdrom is using %s\n", filename);
         }
 
         if ( mediaIterator )