]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Implement virDomainGetBlockInfo in QEMU driver
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 27 Apr 2010 19:31:09 +0000 (20:31 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 29 Apr 2010 16:21:26 +0000 (17:21 +0100)
* src/qemu/qemu_driver.c: Implementation of virDomainGetBlockInfo
* src/util/storage_file.h: Add DEV_BSIZE
* src/storage/storage_backend.c: Remove DEV_BSIZE

src/qemu/qemu_driver.c
src/storage/storage_backend.c
src/util/storage_file.h

index 0cac1300ee08b60f928a6aa4bcf6310126ff22c5..54c3f34953a779498d78bad3514e96a68cfef1f9 100644 (file)
@@ -84,6 +84,7 @@
 #include "macvtap.h"
 #include "nwfilter/nwfilter_gentech_driver.h"
 #include "hooks.h"
+#include "storage_file.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
@@ -9001,6 +9002,120 @@ cleanup:
 }
 
 
+static int qemuDomainGetBlockInfo(virDomainPtr dom,
+                                  const char *path,
+                                  virDomainBlockInfoPtr info,
+                                  unsigned int flags) {
+    struct qemud_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    int ret = -1;
+    int fd = -1;
+    off_t end;
+    virStorageFileMetadata meta;
+    struct stat sb;
+    int i;
+
+    virCheckFlags(0, -1);
+
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        qemuReportError(VIR_ERR_NO_DOMAIN,
+                        _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (!path || path[0] == '\0') {
+        qemuReportError(VIR_ERR_INVALID_ARG,
+                        "%s", _("NULL or empty path"));
+        goto cleanup;
+    }
+
+    /* Check the path belongs to this domain. */
+    for (i = 0 ; i < vm->def->ndisks ; i++) {
+        if (vm->def->disks[i]->src != NULL &&
+            STREQ (vm->def->disks[i]->src, path)) {
+            ret = 0;
+            break;
+        }
+    }
+
+    if (ret != 0) {
+        qemuReportError(VIR_ERR_INVALID_ARG,
+                        _("invalid path %s not assigned to domain"), path);
+        goto cleanup;
+    }
+
+    ret = -1;
+
+    /* The path is correct, now try to open it and get its size. */
+    fd = open (path, O_RDONLY);
+    if (fd == -1) {
+        virReportSystemError(errno,
+                             _("failed to open path '%s'"), path);
+        goto cleanup;
+    }
+
+    /* Probe for magic formats */
+    memset(&meta, 0, sizeof(meta));
+    if (virStorageFileGetMetadataFromFD(path, fd, &meta) < 0)
+        goto cleanup;
+
+    /* Get info for normal formats */
+    if (fstat(fd, &sb) < 0) {
+        virReportSystemError(errno,
+                             _("cannot stat file '%s'"), path);
+        goto cleanup;
+    }
+
+    if (S_ISREG(sb.st_mode)) {
+#ifndef __MINGW32__
+        info->physical = (unsigned long long)sb.st_blocks *
+            (unsigned long long)DEV_BSIZE;
+#else
+        info->physical = sb.st_size;
+#endif
+        /* Regular files may be sparse, so logical size (capacity) is not same
+         * as actual physical above
+         */
+        info->capacity = sb.st_size;
+    } else {
+        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
+         * be 64 bits on all platforms.
+         */
+        end = lseek (fd, 0, SEEK_END);
+        if (end == (off_t)-1) {
+            virReportSystemError(errno,
+                                 _("failed to seek to end of %s"), path);
+            goto cleanup;
+        }
+        info->physical = end;
+        info->capacity = end;
+    }
+
+    /* If the file we probed has a capacity set, then override
+     * what we calculated from file/block extents */
+    if (meta.capacity)
+        info->capacity = meta.capacity;
+
+    /* XXX allocation will need to be pulled from QEMU for
+     * the qcow inside LVM case */
+    info->allocation = info->physical;
+
+    ret = 0;
+
+cleanup:
+    if (fd != -1)
+        close(fd);
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+
 static int
 qemuDomainEventRegister(virConnectPtr conn,
                         virConnectDomainEventCallback callback,
@@ -11467,7 +11582,7 @@ static virDriver qemuDriver = {
     qemudDomainMemoryStats, /* domainMemoryStats */
     qemudDomainBlockPeek, /* domainBlockPeek */
     qemudDomainMemoryPeek, /* domainMemoryPeek */
-    NULL, /* domainBlockInfo */
+    qemuDomainGetBlockInfo, /* domainGetBlockInfo */
     nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
     nodeGetFreeMemory,  /* getFreeMemory */
     qemuDomainEventRegister, /* domainEventRegister */
index f0074ed04c0f3f3914811be8e26d470cb849ecbb..5003b8c6b4c46649801f3c1f315af44cf230721d 100644 (file)
 # include "storage_backend_fs.h"
 #endif
 
-#ifndef DEV_BSIZE
-# define DEV_BSIZE 512
-#endif
-
 #define VIR_FROM_THIS VIR_FROM_STORAGE
 
 static virStorageBackendPtr backends[] = {
index ef971006e9c0018a0beab612273479c9b43e8df5..c761dc6817dcf2478449d4c1cdae612605387453 100644 (file)
@@ -51,6 +51,10 @@ typedef struct _virStorageFileMetadata {
     bool encrypted;
 } virStorageFileMetadata;
 
+# ifndef DEV_BSIZE
+#  define DEV_BSIZE 512
+# endif
+
 int virStorageFileGetMetadata(const char *path,
                               virStorageFileMetadata *meta);
 int virStorageFileGetMetadataFromFD(const char *path,