Here is a updated patch that defines a enum for mapping parition code to
parted's fs-type.
/Henrik
--- libvirt-0.6.4.patches/src/storage_conf.h 2009-06-23 18:05:39.054877000 +0200
+++ libvirt-0.6.4/src/storage_conf.h 2009-06-25 18:24:46.374696000 +0200
@@ -460,4 +460,22 @@ enum virStorageVolTypeDisk {
VIR_STORAGE_VOL_DISK_TYPE_LAST,
};
+/*
+ * Mapping of Parted fs-types
+ * MUST be kept in the same order
+ * as virStorageVolFormatDisk
+ */
+enum virStoragePartedFsType {
+ VIR_STORAGE_PARTED_FS_TYPE_NONE = 0,
+ VIR_STORAGE_PARTED_FS_TYPE_LINUX,
+ VIR_STORAGE_PARTED_FS_TYPE_FAT16,
+ VIR_STORAGE_PARTED_FS_TYPE_FAT32,
+ VIR_STORAGE_PARTED_FS_TYPE_LINUX_SWAP,
+ VIR_STORAGE_PARTED_FS_TYPE_LINUX_LVM,
+ VIR_STORAGE_PARTED_FS_TYPE_LINUX_RAID,
+ VIR_STORAGE_PARTED_FS_TYPE_EXTENDED,
+ VIR_STORAGE_PARTED_FS_TYPE_LAST,
+};
+VIR_ENUM_DECL(virStoragePartedFsType)
+
#endif /* __VIR_STORAGE_CONF_H__ */
--- libvirt-0.6.4.patches/src/storage_conf.c 2009-06-23 13:07:20.684649000 +0200
+++ libvirt-0.6.4/src/storage_conf.c 2009-06-25 18:22:46.136945000 +0200
@@ -93,6 +93,12 @@ VIR_ENUM_IMPL(virStorageVolFormatFileSys
"cloop", "cow", "dmg", "iso",
"qcow", "qcow2", "vmdk", "vpc")
+VIR_ENUM_IMPL(virStoragePartedFsType,
+ VIR_STORAGE_PARTED_FS_TYPE_LAST,
+ "none", "ext2", "fat16",
+ "fat32", "linux-swap",
+ "ext2", "ext2",
+ "extended")
typedef const char *(*virStorageVolFormatToString)(int format);
typedef int (*virStorageVolFormatFromString)(const char *format);
--- libvirt-0.6.4.patches/src/libvirt_private.syms 2009-06-23 13:07:38.206045000 +0200
+++ libvirt-0.6.4/src/libvirt_private.syms 2009-06-26 12:06:30.517758000 +0200
@@ -287,6 +287,7 @@ virStoragePoolFormatFileSystemNetTypeToS
virStorageVolFormatFileSystemTypeToString;
virStorageVolFormatFileSystemTypeFromString;
virStoragePoolTypeFromString;
+virStoragePartedFsTypeTypeToString;
virStoragePoolObjLock;
virStoragePoolObjUnlock;
--- libvirt-0.6.4.patches/src/storage_backend_disk.c 2009-06-23 18:17:30.885038000 +0200
+++ libvirt-0.6.4/src/storage_backend_disk.c 2009-06-26 12:44:42.478755000 +0200
@@ -382,46 +382,218 @@ virStorageBackendDiskBuildPool(virConnec
return 0;
}
+/**
+ * Decides what kind of partition type that should be created.
+ * Important when the partition table is of msdos type
+ */
static int
-virStorageBackendDiskCreateVol(virConnectPtr conn,
- virStoragePoolObjPtr pool,
- virStorageVolDefPtr vol)
+virStorageBackendDiskPartTypeToCreate(virStoragePoolObjPtr pool)
+{
+ if (pool->def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
+ /* count primary and extended paritions,
+ can't be more than 3 to create a new primary partition */
+ int i;
+ int count = 0;
+ for (i = 0; i < pool->volumes.count; i++) {
+ if (pool->volumes.objs[i]->target.type == VIR_STORAGE_VOL_DISK_TYPE_PRIMARY ||
+ pool->volumes.objs[i]->target.type == VIR_STORAGE_VOL_DISK_TYPE_EXTENDED) {
+ count++;
+ }
+ }
+ if (count >= 4) {
+ return VIR_STORAGE_VOL_DISK_TYPE_LOGICAL;
+ }
+ }
+
+ /* for all other cases, all partitions are primary */
+ return VIR_STORAGE_VOL_DISK_TYPE_PRIMARY;
+}
+
+static int
+virStorageBackendDiskPartFormat(virConnectPtr conn, virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol,
+ char* partFormat)
+{
+ int i;
+ if (pool->def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
+ const char *partedFormat = virStoragePartedFsTypeTypeToString(vol->target.format);
+ if(partedFormat == NULL) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Invalid partition type"));
+ return -1;
+ }
+ if (vol->target.format == VIR_STORAGE_VOL_DISK_EXTENDED) {
+ /* make sure we don't have a extended partition already */
+ for (i = 0; i < pool->volumes.count; i++) {
+ if (pool->volumes.objs[i]->target.format == VIR_STORAGE_VOL_DISK_EXTENDED) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("extended partition already exists"));
+ return -1;
+ }
+ }
+ sprintf(partFormat, "%s", partedFormat);
+ } else {
+ /* create primary partition as long as it is possible
+ and after that check if an extended partition exists
+ to create logical partitions. */
+ /* XXX Only support one extended partition */
+ switch (virStorageBackendDiskPartTypeToCreate(pool)) {
+ case VIR_STORAGE_VOL_DISK_TYPE_PRIMARY:
+ sprintf(partFormat, "primary %s", partedFormat);
+ break;
+ case VIR_STORAGE_VOL_DISK_TYPE_LOGICAL:
+ /* make sure we have a extended partition */
+ for (i = 0; i < pool->volumes.count; i++) {
+ if (pool->volumes.objs[i]->target.format == VIR_STORAGE_VOL_DISK_EXTENDED) {
+ sprintf(partFormat, "logical %s", partedFormat);
+ break;
+ }
+ }
+ if (i == pool->volumes.count) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("no extended partition found and no primary partition available"));
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ sprintf(partFormat, "primary");
+ }
+ return 0;
+}
+
+/**
+ * Aligns a new partition to nearest cylinder boundry
+ * when haveing a msdos partition table type
+ * to avoid any problem with all ready existing
+ * partitions
+ */
+static int
+virStorageBackendDiskPartBoundries(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ unsigned long long *start,
+ unsigned long long *end,
+ unsigned long long allocation)
{
int i;
- char start[100], end[100];
- unsigned long long startOffset, endOffset, smallestSize = 0;
int smallestExtent = -1;
+ unsigned long long smallestSize = 0;
+ unsigned long long extraBytes = 0;
+ unsigned long long alignedAllocation = allocation;
virStoragePoolSourceDevicePtr dev = &pool->def->source.devices[0];
- /* XXX customizable partition types */
+ unsigned long long cylinderSize = dev->geometry.heads *
+ dev->geometry.sectors * SECTOR_SIZE;
+
+ DEBUG("find free area: allocation %llu, cyl size %llu\n", allocation, cylinderSize);
+ int partType = virStorageBackendDiskPartTypeToCreate(pool);
+
+ /* how many extra bytes we have since we allocate
+ aligned to the cylinder boundry */
+ extraBytes = cylinderSize - (allocation % cylinderSize);
+
+ for (i = 0 ; i < dev->nfreeExtent ; i++) {
+ unsigned long long size =
+ dev->freeExtents[i].end -
+ dev->freeExtents[i].start;
+ unsigned long long neededSize = allocation;
+
+ if (pool->def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
+ /* align to cylinder boundry */
+ neededSize += extraBytes;
+ if ((*start % cylinderSize) > extraBytes) {
+ /* add an extra cylinder if the offset can't fit within
+ the extra bytes we have */
+ neededSize += cylinderSize;
+ }
+ /* if we are creating a logical patition, we need one extra
+ block between partitions (or actually move start one block) */
+ if (partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL) {
+ size -= SECTOR_SIZE;
+ }
+ }
+ if (size > neededSize &&
+ (smallestSize == 0 ||
+ size < smallestSize)) {
+ /* for logical partition, the free extent
+ must be within a logical free area */
+ if (partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL &&
+ dev->freeExtents[i].type != VIR_STORAGE_FREE_LOGICAL) {
+ continue;
+ /* for primary partition, the free extent
+ must not be within a logical free area */
+ } else if(partType == VIR_STORAGE_VOL_DISK_TYPE_PRIMARY &&
+ dev->freeExtents[i].type != VIR_STORAGE_FREE_NORMAL) {
+ continue;
+ }
+ smallestSize = size;
+ smallestExtent = i;
+ alignedAllocation = neededSize;
+ }
+ }
+
+ if (smallestExtent == -1) {
+ virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("no large enough free extent"));
+ return -1;
+ }
+
+ DEBUG("aligned alloc %llu\n", alignedAllocation);
+ *start = dev->freeExtents[smallestExtent].start;
+
+ if (partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL) {
+ /* for logical partition, skip one block */
+ *start += SECTOR_SIZE;
+ }
+
+ *end = *start + alignedAllocation;
+ if (pool->def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
+ /* adjust our allocation if start is not at a cylinder boundry */
+ *end -= (*start % cylinderSize);
+ }
+
+ /* counting in byte, we want the last byte of the current sector */
+ *end -= 1;
+ DEBUG("final aligned start %llu, end %llu\n", *start, *end);
+ return 0;
+}
+
+
+static int
+virStorageBackendDiskCreateVol(virConnectPtr conn,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
+{
+ char start[100], end[100], partFormat[100];
+ unsigned long long startOffset = 0, endOffset = 0;
const char *cmdargv[] = {
PARTED,
pool->def->source.devices[0].path,
"mkpart",
"--script",
- "ext2",
+ partFormat,
start,
end,
NULL
};
- for (i = 0 ; i < dev->nfreeExtent ; i++) {
- unsigned long long size =
- dev->freeExtents[i].end -
- dev->freeExtents[i].start;
- if (size > vol->allocation &&
- (smallestSize == 0 ||
- size < smallestSize)) {
- smallestSize = size;
- smallestExtent = i;
+ if (virStorageBackendDiskPartFormat(conn, pool, vol, partFormat) != 0) {
+ return -1;
+ }
+
+ if (vol->key == NULL) {
+ /* XXX base off a unique key of the underlying disk */
+ if ((vol->key = strdup(vol->target.path)) == NULL) {
+ virReportOOMError(conn);
+ return -1;
}
}
- if (smallestExtent == -1) {
- virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
- "%s", _("no large enough free extent"));
- return -1;
+
+ if(virStorageBackendDiskPartBoundries(conn, pool, &startOffset, &endOffset, vol->allocation) != 0) {
+ return -1;
}
- startOffset = dev->freeExtents[smallestExtent].start;
- endOffset = startOffset + vol->allocation;
snprintf(start, sizeof(start)-1, "%lluB", startOffset);
start[sizeof(start)-1] = '\0';
@@ -431,6 +603,9 @@ virStorageBackendDiskCreateVol(virConnec
if (virRun(conn, cmdargv, NULL) < 0)
return -1;
+ /* wait for device node to show up */
+ virStorageBackendWaitForDevices(conn);
+
/* Blow away free extent info, as we're about to re-populate it */
VIR_FREE(pool->def->source.devices[0].freeExtents);
pool->def->source.devices[0].nfreeExtent = 0;
--
Libvir-list mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libvir-list