[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-block] ping Re: [PATCH v12] block/raw-posix.c: Make physical devic
From: |
Programmingkid |
Subject: |
[Qemu-block] ping Re: [PATCH v12] block/raw-posix.c: Make physical devices usable in QEMU under Mac OS X host |
Date: |
Fri, 18 Dec 2015 18:58:10 -0500 |
https://patchwork.ozlabs.org/patch/555945/
On Dec 11, 2015, at 10:27 PM, Programmingkid wrote:
> Mac OS X can be picky when it comes to allowing the user
> to use physical devices in QEMU. Most mounted volumes
> appear to be off limits to QEMU. If an issue is detected,
> a message is displayed showing the user how to unmount a
> volume. Now QEMU uses both CD and DVD media.
>
> Signed-off-by: John Arbuckle <address@hidden>
>
> ---
> Removed mediaType parameter from FindEjectableOpticalMedia().
> Added goto statements to hdev_open.
> Replaced snprintf() with g_strdup() in FindEjectableOpticalMedia().
> Put back return statement in hdev_open for Linux compatibility.
>
> block/raw-posix.c | 163 ++++++++++++++++++++++++++++++++++++++++-------------
> 1 files changed, 124 insertions(+), 39 deletions(-)
>
> diff --git a/block/raw-posix.c b/block/raw-posix.c
> index d9162fd..82e8e62 100644
> --- a/block/raw-posix.c
> +++ b/block/raw-posix.c
> @@ -43,6 +43,7 @@
> #include <IOKit/storage/IOMedia.h>
> #include <IOKit/storage/IOCDMedia.h>
> //#include <IOKit/storage/IOCDTypes.h>
> +#include <IOKit/storage/IODVDMedia.h>
> #include <CoreFoundation/CoreFoundation.h>
> #endif
>
> @@ -1975,33 +1976,46 @@ 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, int flags);
> -kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
> +static char *FindEjectableOpticalMedia(io_iterator_t *mediaIterator)
> {
> - kern_return_t kernResult;
> + kern_return_t kernResult = KERN_FAILURE;
> mach_port_t masterPort;
> CFMutableDictionaryRef classesToMatch;
> + const char *matching_array[] = {kIODVDMediaClass, kIOCDMediaClass};
> + char *mediaType = NULL;
>
> kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
> if ( KERN_SUCCESS != kernResult ) {
> printf( "IOMasterPort returned %d\n", kernResult );
> }
>
> - classesToMatch = IOServiceMatching( kIOCDMediaClass );
> - if ( classesToMatch == NULL ) {
> - printf( "IOServiceMatching returned a NULL dictionary.\n" );
> - } else {
> - CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ),
> kCFBooleanTrue );
> - }
> - kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch,
> mediaIterator );
> - if ( KERN_SUCCESS != kernResult )
> - {
> - printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
> - }
> + int index;
> + for (index = 0; index < ARRAY_SIZE(matching_array); index++) {
> + classesToMatch = IOServiceMatching(matching_array[index]);
> + if (classesToMatch == NULL) {
> + error_report("IOServiceMatching returned NULL for %s",
> + matching_array[index]);
> + continue;
> + }
> + CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey),
> + kCFBooleanTrue);
> + kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch,
> + mediaIterator);
> + if (kernResult != KERN_SUCCESS) {
> + error_report("Note: IOServiceGetMatchingServices returned %d",
> + kernResult);
> + }
>
> - return kernResult;
> + /* If a match was found, leave the loop */
> + if (*mediaIterator != 0) {
> + DPRINTF("Matching using %s\n", matching_array[index]);
> + mediaType = g_strdup(matching_array[index]);
> + break;
> + }
> + }
> + return mediaType;
> }
>
> kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath,
> @@ -2033,7 +2047,35 @@ kern_return_t GetBSDPath(io_iterator_t mediaIterator,
> char *bsdPath,
> return kernResult;
> }
>
> -#endif
> +/* Sets up a real cdrom for use in QEMU */
> +static bool setup_cdrom(char *bsd_path, Error **errp)
> +{
> + int index, num_of_test_partitions = 2, fd;
> + char test_partition[MAXPATHLEN];
> + bool partition_found = false;
> +
> + /* look for a working partition */
> + for (index = 0; index < num_of_test_partitions; index++) {
> + snprintf(test_partition, sizeof(test_partition), "%ss%d", bsd_path,
> + index);
> + fd = qemu_open(test_partition, O_RDONLY | O_BINARY | O_LARGEFILE);
> + if (fd >= 0) {
> + partition_found = true;
> + qemu_close(fd);
> + break;
> + }
> + }
> +
> + /* if a working partition on the device was not found */
> + if (partition_found == false) {
> + error_setg(errp, "Failed to find a working partition on disc");
> + } else {
> + DPRINTF("Using %s as optical disc\n", test_partition);
> + pstrcpy(bsd_path, MAXPATHLEN, test_partition);
> + }
> + return partition_found;
> +}
> +#endif /* defined(__APPLE__) && defined(__MACH__) */
>
> static int hdev_probe_device(const char *filename)
> {
> @@ -2115,6 +2157,16 @@ static bool hdev_is_sg(BlockDriverState *bs)
> return false;
> }
>
> +/* Prints directions on mounting and unmounting a device */
> +static void print_unmounting_directions(const char *file_name)
> +{
> + error_report("If device %s is mounted on the desktop, unmount"
> + " it first before using it in QEMU", file_name);
> + error_report("Command to unmount device: diskutil unmountDisk %s",
> + file_name);
> + error_report("Command to mount device: diskutil mountDisk %s",
> file_name);
> +}
> +
> static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
> Error **errp)
> {
> @@ -2125,32 +2177,55 @@ 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;
> - char bsdPath[ MAXPATHLEN ];
> - int fd;
> -
> - kernResult = FindEjectableCDMedia( &mediaIterator );
> - kernResult = GetBSDPath(mediaIterator, bsdPath, sizeof(bsdPath),
> - flags);
> - 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);
> - }
> - filename = bsdPath;
> - qdict_put(options, "filename", qstring_from_str(filename));
> + /* If using a real cdrom */
> + if (strcmp(filename, "/dev/cdrom") == 0) {
> + char bsd_path[MAXPATHLEN];
> + char *mediaType = NULL;
> + kern_return_t ret_val;
> + io_iterator_t mediaIterator = 0;
> +
> + mediaType = FindEjectableOpticalMedia(&mediaIterator);
> + if (mediaType == NULL) {
> + error_setg(errp, "Please make sure your CD/DVD is in the optical"
> + " drive");
> + goto hdev_open_Mac_error;
> + }
> +
> + ret_val = GetBSDPath(mediaIterator, bsd_path, sizeof(bsd_path),
> flags);
> + if (ret_val != KERN_SUCCESS) {
> + error_setg(errp, "Could not get BSD path for optical drive");
> + goto hdev_open_Mac_error;
> + }
> +
> + /* If a real optical drive was not found */
> + if (bsd_path[0] == '\0') {
> + error_setg(errp, "Failed to obtain bsd path for optical drive");
> + goto hdev_open_Mac_error;
> + }
> +
> + /* If using a cdrom disc and finding a partition on the disc failed
> */
> + if (strncmp(mediaType, "IOCDMedia", 9) == 0 &&
> + setup_cdrom(bsd_path, errp) ==
> false) {
> + print_unmounting_directions(bsd_path);
> + goto hdev_open_Mac_error;
> }
>
> - if ( mediaIterator )
> - IOObjectRelease( mediaIterator );
> + g_free(mediaType);
> + filename = bsd_path;
> + qdict_put(options, "filename", qstring_from_str(filename));
> + goto continue_as_normal; /* skip over error handling code */
> +
> + /* If an error occurred above */
> + hdev_open_Mac_error:
> + if (mediaIterator) {
> + IOObjectRelease(mediaIterator);
> + }
> + g_free(mediaType);
> + return -1;
> +
> + continue_as_normal: ;
> }
> -#endif
> +#endif /* defined(__APPLE__) && defined(__MACH__) */
>
> s->type = FTYPE_FILE;
>
> @@ -2159,8 +2234,18 @@ static int hdev_open(BlockDriverState *bs, QDict
> *options, int flags,
> if (local_err) {
> error_propagate(errp, local_err);
> }
> + #if !defined(__APPLE__) && !defined(__MACH__)
> return ret;
> + #endif /* !defined(__APPLE__) && !defined(__MACH__) */
> + }
> +
> +#if defined(__APPLE__) && defined(__MACH__)
> + /* if a physical device experienced an error while being opened */
> + if (strncmp(filename, "/dev/", 5) == 0 && ret != 0) {
> + print_unmounting_directions(filename);
> + return -1;
> }
> +#endif /* defined(__APPLE__) && defined(__MACH__) */
>
> /* Since this does ioctl the device must be already opened */
> bs->sg = hdev_is_sg(bs);
> --
> 1.7.5.4
>
>