blktapctrl: Fix too early close of pipes
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 12 Mar 2009 18:46:26 +0000 (18:46 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 12 Mar 2009 18:46:26 +0000 (18:46 +0000)
Connections to ioemu have single_handler set, so they are closed as
soon as all images of a certain type are closed. This is wrong with
ioemu: All images that belong to the same domain are handled by the
same backend process (usually qemu-dm, but also tapdisk-ioemu for
domains without device model), regardless of the image type.

This patch checks for the same-domain condition for ioemu connections.

Signed-off-by: Kevin Wolf <kwolf@suse.de>
tools/blktap/drivers/blktapctrl.c

index b7ee572837b413f42a7d0748eda6d0001496eced..21cdfe5239e4bfda549e510fac9805d52a7d76f9 100644 (file)
@@ -231,6 +231,24 @@ static void add_disktype(blkif_t *blkif, int type)
        entry->pprev = pprev;
 }
 
+static int qemu_instance_has_disks(pid_t pid)
+{
+       int i;
+       int count = 0;
+       driver_list_entry_t *entry;
+
+       for (i = 0; i < MAX_DISK_TYPES; i++) {
+               entry = active_disks[i];
+               while (entry) {
+                       if ((entry->blkif->tappid == pid) && dtypes[i]->use_ioemu)
+                               count++;
+                       entry = entry->next;
+               }
+       }
+
+       return (count != 0);
+}
+
 static int del_disktype(blkif_t *blkif)
 {
        driver_list_entry_t *entry, **pprev;
@@ -255,6 +273,14 @@ static int del_disktype(blkif_t *blkif)
        DPRINTF("DEL_DISKTYPE: Freeing entry\n");
        free(entry);
 
+       /*
+        * When using ioemu, all disks of one VM are connected to the same
+        * qemu-dm instance. We may close the file handle only if there is
+        * no other disk left for this domain.
+        */
+       if (dtypes[type]->use_ioemu)
+               return !qemu_instance_has_disks(blkif->tappid);
+
        /* Caller should close() if no single controller, or list is empty. */
        return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
 }
@@ -721,6 +747,7 @@ static int unmap_blktapctrl(blkif_t *blkif)
        }
 
        if (del_disktype(blkif)) {
+               DPRINTF("Closing communication pipe to pid %d\n", blkif->tappid);
                close(blkif->fds[WRITE]);
                close(blkif->fds[READ]);
        }