Chris Lalancette wrote:
> 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.

Updated patch based on jim's feedback.  I did not remove the pc98 type; if
everyone else thinks it's a good idea, I'll remove it, but it is part of the ABI
in some sense.  Otherwise, I followed all of jim's suggestions.

-- 
Chris Lalancette
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 09:49:01 -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,41 @@
         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;
+        }
+        bytes = saferead(fd, buffer, sizeof(buffer));
+        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 (disk_types[i].offset + disk_types[i].length > bytes)
+                continue;
+            if (memcmp(buffer+disk_types[i].offset, &disk_types[i].magic,
+                disk_types[i].length) == 0) {
+                vol->target.format = disk_types[i].part_table_type;
+                break;
+            }
+        }
+    }
+
     vol->target.perms.mode = sb.st_mode;
     vol->target.perms.uid = sb.st_uid;
     vol->target.perms.gid = sb.st_gid;
@@ -348,6 +407,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].part_table_type;
+    }
+
+    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].part_table_type)
+            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 09:49:01 -0000
@@ -56,6 +56,29 @@
     VIR_STORAGE_BACKEND_POOL_SOURCE_NAME    = (1<<4),
 };
 
+enum partTableType {
+    VIR_STORAGE_POOL_DISK_DOS = 1,
+    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;
+    enum partTableType part_table_type;
+    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 +155,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 09:49:01 -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 09:49:02 -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,
+    }
 };
--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to