All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <lvivier@redhat.com>
To: Programmingkid <programmingkidx@gmail.com>,
	Qemu-block <qemu-block@nongnu.org>, Kevin Wolf <kwolf@redhat.com>
Cc: qemu-devel qemu-devel <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH] raw-posix.c: Make physical devices usable in QEMU
Date: Thu, 09 Jul 2015 11:35:44 +0200	[thread overview]
Message-ID: <559E4070.6040700@redhat.com> (raw)
In-Reply-To: <F11A2BB4-9674-46A0-8ED0-352A8AEEA7F9@gmail.com>



On 07/07/2015 19:33, Programmingkid wrote:
> Make physical devices like a USB flash drive or a CDROM drive work in
> QEMU. With
> this patch I can use a USB flash drive like a hard drive. Before this
> patch, 
> QEMU would just quit with a message like "resource busy". Now it handles
> issues
> like these for the user. This patch unmounts volumes of physical devices
> before
> using them in QEMU. When QEMU quits, the physical devices are mounted again
> for the user. The user can find out which device files to use for their
> physical
> devices by running the mount command in the terminal. This patch makes
> "qemu-system-ppc -cdrom /dev/cdrom" work again on Mac OS X.
> 
> Signed-off-by: John Arbuckle <programmingkidx@gmail.com
> <mailto:programmingkidx@gmail.com>>

Two comments:
- you should not mix several fixes in one patch (raw block device
management, partition seek, unmount/mount cdrom...)
- according to Stefan answer, I think you should not unmount the CDROM
but you should inform the user he must unmount it manually to be able to
use it.

Laurent
> ---
>  block/raw-posix.c |  155
> ++++++++++++++++++++++++++++++++++++++++++++--------
>  1 files changed, 131 insertions(+), 24 deletions(-)
> 
> diff --git a/block/raw-posix.c b/block/raw-posix.c
> index cbe6574..af0981a 100644
> --- a/block/raw-posix.c
> +++ b/block/raw-posix.c
> @@ -42,9 +42,10 @@
>  #include <IOKit/storage/IOMediaBSDClient.h>
>  #include <IOKit/storage/IOMedia.h>
>  #include <IOKit/storage/IOCDMedia.h>
> -//#include <IOKit/storage/IOCDTypes.h>
>  #include <CoreFoundation/CoreFoundation.h>
> -#endif
> +#include <sys/syslimits.h>
> +#include <fcntl.h>
> +#endif /* (__APPLE__) && (__MACH__) */
> 
>  
> 
>  #ifdef __sun__
>  #define _POSIX_PTHREAD_SEMANTICS 1
> @@ -162,6 +163,25 @@ typedef struct BDRVRawState {
>      bool needs_alignment;
>  } BDRVRawState;
> 
>  
> 
> +#ifdef __APPLE__
> +
> +#define MAX_NUM_DEVICES 7
> +
> +/*
> + * Keeps track of devices that need to be mounted
> + * when QEMU exists.
> + */
> +typedef struct {
> +    int fd;
> +    char filePath[MAXPATHLEN];
> +} PhysicalDevice;
> +
> +PhysicalDevice deviceArray[MAX_NUM_DEVICES];
> +int numberOfDevices;
> +
> +#endif /* __APPLE__ */
> +
> +
>  typedef struct BDRVRawReopenState {
>      int fd;
>      int open_flags;
> @@ -1972,8 +1992,10 @@ BlockDriver bdrv_file = {
>  /* host device */
> 
>  
> 
>  #if defined(__APPLE__) && defined(__MACH__)
> -static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
> -static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char
> *bsdPath, CFIndex maxPathSize );
> +static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator);
> +static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath,
> +                                CFIndex maxPathSize, int flags);
> +void mountDevice(void);
> 
>  
> 
>  kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
>  {
> @@ -2001,7 +2023,8 @@ kern_return_t FindEjectableCDMedia( io_iterator_t
> *mediaIterator )
>      return kernResult;
>  }
> 
>  
> 
> -kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath,
> CFIndex maxPathSize )
> +kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath,
> +                         CFIndex maxPathSize, int flags)
>  {
>      io_object_t     nextMedia;
>      kern_return_t   kernResult = KERN_FAILURE;
> @@ -2014,7 +2037,9 @@ kern_return_t GetBSDPath( io_iterator_t
> mediaIterator, char *bsdPath, CFIndex ma
>          if ( bsdPathAsCFString ) {
>              size_t devPathLength;
>              strcpy( bsdPath, _PATH_DEV );
> -            strcat( bsdPath, "r" );
> +            if (flags & BDRV_O_NOCACHE) {
> +                strcat(bsdPath, "r");
> +            }
>              devPathLength = strlen( bsdPath );
>              if ( CFStringGetCString( bsdPathAsCFString, bsdPath +
> devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
>                  kernResult = KERN_SUCCESS;
> @@ -2027,7 +2052,54 @@ kern_return_t GetBSDPath( io_iterator_t
> mediaIterator, char *bsdPath, CFIndex ma
>      return kernResult;
>  }
> 
>  
> 
> -#endif
> +/* Mounts unmounted devices onto host computer's desktop */
> +void mountDevice(void)
> +{
> +    char commandBuffer[MAXPATHLEN];
> +    int result, index;
> +
> +    for (index = 0; index < numberOfDevices; index++) {
> +        qemu_close(deviceArray[index].fd);
> +        sprintf(commandBuffer, "diskutil mountDisk %s",
> +                                               
> deviceArray[index].filePath);
> +        DPRINTF("Issuing command: %s\n", commandBuffer);
> +        result = system(commandBuffer);
> +        if (result != 0) {
> +            printf("Warning: problem detected while mounting %s\n",
> +                                               
> deviceArray[index].filePath);
> +        }
> +    }
> +}
> +
> +/* Sets up a real cdrom for use in QEMU */
> +static void setupCDROM(char *bsdPath)
> +{
> +    int index, numOfTestPartitions = 2, fd;
> +    char testPartition[MAXPATHLEN];
> +    bool partitionFound = false;
> +
> +    /* look for a working partition */
> +    for (index = 0; index < numOfTestPartitions; index++) {
> +        strcpy(testPartition, bsdPath);
> +        sprintf(testPartition, "%ss%d", testPartition, index);
> +        fd = qemu_open(testPartition, O_RDONLY | O_BINARY | O_LARGEFILE);
> +        if (fd > 0) {
> +            partitionFound = true;
> +            qemu_close(fd);
> +            break;
> +        }
> +    }
> +
> +    /* if a working partition on the device was found */
> +    if (partitionFound == false) {
> +        printf("Error: Failed to find a working partition on CD!\n");
> +        exit(EXIT_FAILURE);
> +    }
> +
> +    strcpy(bsdPath, testPartition);
> +}
> +
> +#endif /* defined(__APPLE__) && defined(__MACH__) */
> 
>  
> 
>  static int hdev_probe_device(const char *filename)
>  {
> @@ -2119,30 +2191,52 @@ static int hdev_open(BlockDriverState *bs, QDict
> *options, int flags,
>  #if defined(__APPLE__) && defined(__MACH__)
>      const char *filename = qdict_get_str(options, "filename");
> 
>  
> 
> -    if (strstart(filename, "/dev/cdrom", NULL)) {
> -        kern_return_t kernResult;
> -        io_iterator_t mediaIterator;
> +    /* If using a physical device */
> +    if (strstart(filename, "/dev/", NULL)) {
>          char bsdPath[ MAXPATHLEN ];
> -        int fd;
> 
>  
> 
> -        kernResult = FindEjectableCDMedia( &mediaIterator );
> -        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof(
> bsdPath ) );
> +        /* If the physical device is a cdrom */
> +        if (strcmp(filename, "/dev/cdrom") == 0) {
> +            io_iterator_t mediaIterator;
> +            FindEjectableCDMedia(&mediaIterator);
> +            GetBSDPath(mediaIterator, bsdPath, sizeof(bsdPath), flags);
> +            if (mediaIterator) {
> +                IOObjectRelease(mediaIterator);
> +            }
> +        }
> 
>  
> 
> -        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 {
> -                qemu_close(fd);
> +        /* If the physical device is something else */
> +        else {
> +            strcpy(bsdPath, filename);
> +        }
> +
> +        /* if accessing a buffered device */
> +        if ((flags & BDRV_O_NOCACHE) == 0) {
> +            /*
> +            * Unmount the device from the desktop before
> +            * using the buffered device. A resource busy error
> +            * would happen if we don't.
> +            */
> +            char commandBuffer[MAXPATHLEN];
> +            int result;
> +            sprintf(commandBuffer, "diskutil unmountDisk %s", bsdPath);
> +            DPRINTF("Issuing command: %s\n", commandBuffer);
> +            result = system(commandBuffer);
> +            if (result != 0) {
> +                printf("Warning: problem detected while unmounting %s\n",
> +                                                                   
> bsdPath);
>              }
> +        }
> +
> +        atexit(mountDevice);
> +
> +        /* Setup a CDROM device if found */
> +        if (bsdPath[0] != '\0' && (strcmp(filename, "/dev/cdrom") == 0)) {
> +            setupCDROM(bsdPath);
> +            DPRINTF("Using %s as CDROM\n", bsdPath);
>              filename = bsdPath;
>              qdict_put(options, "filename", qstring_from_str(filename));
>          }
> -
> -        if ( mediaIterator )
> -            IOObjectRelease( mediaIterator );
>      }
>  #endif
> 
>  
> 
> @@ -2156,6 +2250,19 @@ static int hdev_open(BlockDriverState *bs, QDict
> *options, int flags,
>          return ret;
>      }
> 
>  
> 
> +#ifdef __APPLE__
> +
> +    /* Add the fd to the fd array for mounting at exit */
> +    if (strncmp(filename, "/dev/", 5) == 0) {
> +        int mountFD = ((BDRVRawState *) bs->opaque)->fd;
> +        DPRINTF("Queuing %s (fd: %d) for mounting at exit\n",
> +                                                            filename,
> mountFD);
> +        deviceArray[numberOfDevices].fd = mountFD;
> +        strcpy(deviceArray[numberOfDevices++].filePath, filename);
> +    }
> +
> +#endif /* __APPLE__ */
> +
>      /* Since this does ioctl the device must be already opened */
>      bs->sg = hdev_is_sg(bs);
> 
>  
> 
> -- 
> 1.7.5.4
> 

  reply	other threads:[~2015-07-09  9:35 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-07 17:33 [Qemu-devel] [PATCH] raw-posix.c: Make physical devices usable in QEMU Programmingkid
2015-07-09  9:35 ` Laurent Vivier [this message]
2015-07-09 14:05   ` Programmingkid
2015-07-09 10:52 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2015-07-09 14:02   ` Programmingkid
2015-07-16 13:19     ` Stefan Hajnoczi
2015-07-16 17:26       ` Programmingkid
2015-07-16 19:43         ` Stefan Hajnoczi
2015-07-16 19:51           ` Programmingkid

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=559E4070.6040700@redhat.com \
    --to=lvivier@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=programmingkidx@gmail.com \
    --cc=qemu-block@nongnu.org \
    --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.