[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH]: Export the 'label' on block devices



To support LVM partitioning in oVirt, one of the things we need is the ability
to tell what kind of label is currently on a block device.  Here, a 'label' is
used in the same sense that it is used in parted; namely, it defines which kind
of partition table is on the disk, whether it be DOS, LVM2, SUN, BSD, etc.  Note
that this is different than the partition type; those are things like Linux,
FAT16, FAT32, etc.

This actually turns out to be fairly easy to implement; there are really only a
few labels that are in common use, and they all have an easy signature to
recognize (but see comments in the code about pc98).  This patch implements
label detection on block devices in virStorageBackendUpdateVolInfoFD, and hooks
it up to the iSCSI backend so it works there.

To keep code duplication down, I moved some of the enum's from
storage_backend_disk.c into a common place.  Note, however, that there is a
slight semantic change because of this.  Previously, if no label was found on a
disk in storage_backend_disk.c, it would always return "dos" as the label type.
 That's not actually true, though; if it's a completely zeroed disk, for
instance, it really just has label type of 'unknown'.  This patch changes to the
new semantic of 'unknown' for label types we don't understand.  I don't think
this will be a huge issue for compatibility, but there could be something I'm
missing.

Otherwise, this patch has been tested by me to work, and now when you do:

# virsh vol-dumpxml --pool iscsitest lun-1

you'll get:

<volume>
...
  <target>
      ...
      <format type='dos' />

Which should be sufficient for oVirt to do it's detection.

Signed-off-by: Chris Lalancette <clalance redhat com>
Index: src/storage_backend.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_backend.c,v
retrieving revision 1.21
diff -u -r1.21 storage_backend.c
--- src/storage_backend.c	5 Sep 2008 12:03:45 -0000	1.21
+++ src/storage_backend.c	16 Oct 2008 07:29:46 -0000
@@ -192,6 +192,30 @@
     return ret;
 }
 
+struct diskType disk_types[] = {
+    { "lvm2", VIR_STORAGE_POOL_DISK_LVM2, 0x218, 8, 0x31303020324D564CUL },
+    { "gpt",  VIR_STORAGE_POOL_DISK_GPT,  0x200, 8, 0x5452415020494645UL },
+    { "dvh",  VIR_STORAGE_POOL_DISK_DVH,  0x0,   4, 0x41A9E50BUL },
+    { "mac",  VIR_STORAGE_POOL_DISK_MAC,  0x0,   2, 0x5245UL },
+    { "bsd",  VIR_STORAGE_POOL_DISK_BSD,  0x40,  4, 0x82564557UL },
+    { "sun",  VIR_STORAGE_POOL_DISK_SUN,  0x1fc, 2, 0xBEDAUL },
+    /*
+     * NOTE: pc98 is funky; the actual signature is 0x55AA (just like dos), so
+     * we can't use that.  At the moment I'm relying on the "dummy" IPL
+     * bootloader data that comes from parted.  Luckily, the chances of running
+     * into a pc98 machine running libvirt are approximately nil.
+     */
+    /*{ "pc98", 0x1fe, 2, 0xAA55UL },*/
+    { "pc98", VIR_STORAGE_POOL_DISK_PC98, 0x0,   8, 0x314C5049000000CBUL },
+    /*
+     * NOTE: the order is important here; some other disk types (like GPT and
+     * and PC98) also have 0x55AA at this offset.  For that reason, the DOS
+     * one must be the last one.
+     */
+    { "dos",  VIR_STORAGE_POOL_DISK_DOS,  0x1fe, 2, 0xAA55UL },
+    { NULL,   -1,                         0x0,   0, 0x0UL },
+};
+
 int
 virStorageBackendUpdateVolInfoFD(virConnectPtr conn,
                                  virStorageVolDefPtr vol,
@@ -245,6 +269,40 @@
         if (withCapacity) vol->capacity = end;
     }
 
+    /* make sure to set the target format "unknown" to begin with */
+    vol->target.format = VIR_STORAGE_POOL_DISK_UNKNOWN;
+
+    if (S_ISBLK(sb.st_mode)) {
+        off_t start;
+        int i;
+        unsigned char buffer[1024];
+        ssize_t bytes;
+
+        start = lseek(fd, 0, SEEK_SET);
+        if (start < 0) {
+            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                  _("cannot seek to beginning of file '%s':%s"),
+                                  vol->target.path, strerror(errno));
+            return -1;
+        }
+        memset(buffer, 0, 1024);
+        bytes = saferead(fd, buffer, 1024);
+        if (bytes < 0) {
+            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                  _("cannot read beginning of file '%s':%s"),
+                                  vol->target.path, strerror(errno));
+            return -1;
+        }
+
+        for (i = 0; disk_types[i].name != NULL; i++) {
+            if (memcmp(buffer+disk_types[i].offset, &disk_types[i].magic,
+                disk_types[i].length) == 0) {
+                vol->target.format = disk_types[i].label;
+                break;
+            }
+        }
+    }
+
     vol->target.perms.mode = sb.st_mode;
     vol->target.perms.uid = sb.st_uid;
     vol->target.perms.gid = sb.st_gid;
@@ -348,6 +406,34 @@
     return devpath;
 }
 
+int
+virStorageBackendDiskLabelFormatFromString(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                           const char *format) {
+    int i;
+
+    if (format == NULL)
+        return VIR_STORAGE_POOL_DISK_UNKNOWN;
+
+    for (i = 0; disk_types[i].name != NULL; i++) {
+        if (STREQ(format, disk_types[i].name))
+	    return disk_types[i].label;
+    }
+
+    return VIR_STORAGE_POOL_DISK_UNKNOWN;
+}
+
+const char *
+virStorageBackendDiskLabelFormatToString(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                         int format) {
+    int i;
+
+    for (i = 0; disk_types[i].name != NULL; i++) {
+        if (format == disk_types[i].label)
+            return disk_types[i].name;
+    }
+
+    return "unknown";
+}
 
 #ifndef __MINGW32__
 /*
Index: src/storage_backend.h
===================================================================
RCS file: /data/cvs/libvirt/src/storage_backend.h,v
retrieving revision 1.7
diff -u -r1.7 storage_backend.h
--- src/storage_backend.h	2 Sep 2008 14:15:42 -0000	1.7
+++ src/storage_backend.h	16 Oct 2008 07:29:46 -0000
@@ -56,6 +56,30 @@
     VIR_STORAGE_BACKEND_POOL_SOURCE_NAME    = (1<<4),
 };
 
+enum diskLabel {
+    VIR_STORAGE_POOL_DISK_DOS = 0,
+    VIR_STORAGE_POOL_DISK_DVH,
+    VIR_STORAGE_POOL_DISK_GPT,
+    VIR_STORAGE_POOL_DISK_MAC,
+    VIR_STORAGE_POOL_DISK_BSD,
+    VIR_STORAGE_POOL_DISK_PC98,
+    VIR_STORAGE_POOL_DISK_SUN,
+    VIR_STORAGE_POOL_DISK_LVM2,
+    /* the "unknown" disk is 1 billion (and not, for instance, -1), to make
+       sure it doesn't run afoul of error checking */
+    VIR_STORAGE_POOL_DISK_UNKNOWN = 1 * 1024 * 1024 * 1024,
+};
+
+struct diskType {
+    const char *name;
+    /* the 'label' terminology comes from parted */
+    enum diskLabel label;
+    unsigned short offset;
+    unsigned short length;
+    unsigned long long magic;
+};
+extern struct diskType disk_types[];
+
 typedef struct _virStorageBackendPoolOptions virStorageBackendPoolOptions;
 typedef virStorageBackendPoolOptions *virStorageBackendPoolOptionsPtr;
 struct _virStorageBackendPoolOptions {
@@ -132,6 +156,11 @@
                                                char **const groups,
                                                void *data);
 
+int virStorageBackendDiskLabelFormatFromString(virConnectPtr conn ATTRIBUTE_UNUSED,
+					       const char *format);
+const char *virStorageBackendDiskLabelFormatToString(virConnectPtr conn ATTRIBUTE_UNUSED,
+						     int format);
+
 int virStorageBackendRunProgRegex(virConnectPtr conn,
                                   virStoragePoolObjPtr pool,
                                   const char *const*prog,
Index: src/storage_backend_disk.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_backend_disk.c,v
retrieving revision 1.14
diff -u -r1.14 storage_backend_disk.c
--- src/storage_backend_disk.c	13 Oct 2008 16:46:29 -0000	1.14
+++ src/storage_backend_disk.c	16 Oct 2008 07:29:46 -0000
@@ -30,16 +30,6 @@
 #include "util.h"
 #include "memory.h"
 
-enum {
-    VIR_STORAGE_POOL_DISK_DOS = 0,
-    VIR_STORAGE_POOL_DISK_DVH,
-    VIR_STORAGE_POOL_DISK_GPT,
-    VIR_STORAGE_POOL_DISK_MAC,
-    VIR_STORAGE_POOL_DISK_BSD,
-    VIR_STORAGE_POOL_DISK_PC98,
-    VIR_STORAGE_POOL_DISK_SUN,
-};
-
 /*
  * XXX these are basically partition types.
  *
@@ -63,57 +53,6 @@
 #define PARTHELPER BINDIR "/libvirt_parthelper"
 
 static int
-virStorageBackendDiskPoolFormatFromString(virConnectPtr conn,
-                                          const char *format) {
-    if (format == NULL)
-        return VIR_STORAGE_POOL_DISK_DOS;
-
-    if (STREQ(format, "dos"))
-        return VIR_STORAGE_POOL_DISK_DOS;
-    if (STREQ(format, "dvh"))
-        return VIR_STORAGE_POOL_DISK_DVH;
-    if (STREQ(format, "gpt"))
-        return VIR_STORAGE_POOL_DISK_GPT;
-    if (STREQ(format, "mac"))
-        return VIR_STORAGE_POOL_DISK_MAC;
-    if (STREQ(format, "bsd"))
-        return VIR_STORAGE_POOL_DISK_BSD;
-    if (STREQ(format, "pc98"))
-        return VIR_STORAGE_POOL_DISK_PC98;
-    if (STREQ(format, "sun"))
-        return VIR_STORAGE_POOL_DISK_SUN;
-
-    virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                          _("unsupported pool format %s"), format);
-    return -1;
-}
-
-static const char *
-virStorageBackendDiskPoolFormatToString(virConnectPtr conn,
-                                        int format) {
-    switch (format) {
-    case VIR_STORAGE_POOL_DISK_DOS:
-        return "dos";
-    case VIR_STORAGE_POOL_DISK_DVH:
-        return "dvh";
-    case VIR_STORAGE_POOL_DISK_GPT:
-        return "gpt";
-    case VIR_STORAGE_POOL_DISK_MAC:
-        return "mac";
-    case VIR_STORAGE_POOL_DISK_BSD:
-        return "bsd";
-    case VIR_STORAGE_POOL_DISK_PC98:
-        return "pc98";
-    case VIR_STORAGE_POOL_DISK_SUN:
-        return "sun";
-    }
-
-    virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
-                          _("unsupported pool format %d"), format);
-    return NULL;
-}
-
-static int
 virStorageBackendDiskVolFormatFromString(virConnectPtr conn,
                                          const char *format) {
     if (format == NULL)
@@ -414,8 +353,8 @@
         "mklabel",
         "--script",
         ((pool->def->source.format == VIR_STORAGE_POOL_DISK_DOS) ? "msdos" :
-          virStorageBackendDiskPoolFormatToString(conn,
-                                                  pool->def->source.format)),
+          virStorageBackendDiskLabelFormatToString(conn,
+                                                   pool->def->source.format)),
         NULL,
     };
 
@@ -557,8 +496,8 @@
 
     .poolOptions = {
         .flags = (VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE),
-        .formatFromString = virStorageBackendDiskPoolFormatFromString,
-        .formatToString = virStorageBackendDiskPoolFormatToString,
+        .formatFromString = virStorageBackendDiskLabelFormatFromString,
+        .formatToString = virStorageBackendDiskLabelFormatToString,
     },
     .volOptions = {
         .formatFromString = virStorageBackendDiskVolFormatFromString,
Index: src/storage_backend_iscsi.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_backend_iscsi.c,v
retrieving revision 1.14
diff -u -r1.14 storage_backend_iscsi.c
--- src/storage_backend_iscsi.c	10 Oct 2008 15:13:28 -0000	1.14
+++ src/storage_backend_iscsi.c	16 Oct 2008 07:29:46 -0000
@@ -636,18 +636,20 @@
     return 0;
 }
 
-
 virStorageBackend virStorageBackendISCSI = {
-  .type = VIR_STORAGE_POOL_ISCSI,
+    .type = VIR_STORAGE_POOL_ISCSI,
 
-  .startPool = virStorageBackendISCSIStartPool,
-  .refreshPool = virStorageBackendISCSIRefreshPool,
-  .stopPool = virStorageBackendISCSIStopPool,
+    .startPool = virStorageBackendISCSIStartPool,
+    .refreshPool = virStorageBackendISCSIRefreshPool,
+    .stopPool = virStorageBackendISCSIStopPool,
 
-  .poolOptions = {
+    .poolOptions = {
         .flags = (VIR_STORAGE_BACKEND_POOL_SOURCE_HOST |
                   VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE)
     },
 
-  .volType = VIR_STORAGE_VOL_BLOCK,
+    .volType = VIR_STORAGE_VOL_BLOCK,
+    .volOptions = {
+        .formatToString = virStorageBackendDiskLabelFormatToString,
+    }
 };

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]