Blob Blame History Raw
diff -up parted-1.9.0/configure.ac.export-align parted-1.9.0/configure.ac
--- parted-1.9.0/configure.ac.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/configure.ac	2009-11-03 11:30:46.000000000 +0100
@@ -519,6 +519,18 @@ HOST=$(hostname)
 BUILDINFO="$USER@$HOST, $DATE"
 AC_SUBST([BUILDINFO])
 
+LIB_BLKID=
+AC_SUBST([LIB_BLKID])
+pe_saved_libs=$LIBS
+  AC_SEARCH_LIBS([blkid_probe_get_topology], [blkid],
+    [test "$ac_cv_search_blkid_probe_get_topology" = "none required" \
+     || LIB_BLKID=$ac_cv_search_blkid_probe_get_topology])
+  AC_CHECK_FUNC([blkid_probe_get_topology], [use_blkid=1], [use_blkid=0])
+LIBS=$pe_saved_libs
+AC_DEFINE_UNQUOTED([USE_BLKID], [$use_blkid],
+  [Define if you have sufficient blkid support.])
+AC_CHECK_HEADERS_ONCE([blkid/blkid.h])
+
 AC_OUTPUT([
 Makefile
 lib/Makefile
diff -up parted-1.9.0/include/parted/device.h.export-align parted-1.9.0/include/parted/device.h
--- parted-1.9.0/include/parted/device.h.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/include/parted/device.h	2009-11-03 11:30:46.000000000 +0100
@@ -92,6 +92,8 @@ struct _PedDevice {
         void*           arch_specific;
 };
 
+#include <parted/natmath.h>
+
 /**
  * List of functions implementing architecture-specific operations.
  */
@@ -112,6 +114,9 @@ struct _PedDeviceArchOps {
         PedSector (*check) (PedDevice* dev, void* buffer,
                             PedSector start, PedSector count);
         void (*probe_all) ();
+        /* These functions are optional */
+        PedAlignment *(*get_minimum_alignment)(const PedDevice *dev);
+        PedAlignment *(*get_optimum_alignment)(const PedDevice *dev);
 };
 
 #include <parted/constraint.h>
@@ -141,6 +146,14 @@ extern PedSector ped_device_check (PedDe
                                    PedSector start, PedSector count);
 extern PedConstraint* ped_device_get_constraint (PedDevice* dev);
 
+extern PedConstraint *ped_device_get_minimal_aligned_constraint(
+                                                         const PedDevice *dev);
+extern PedConstraint *ped_device_get_optimal_aligned_constraint(
+                                                         const PedDevice *dev);
+
+extern PedAlignment *ped_device_get_minimum_alignment(const PedDevice *dev);
+extern PedAlignment *ped_device_get_optimum_alignment(const PedDevice *dev);
+
 /* private stuff ;-) */
 
 extern void _ped_device_probe (const char* path);
diff -up parted-1.9.0/include/parted/disk.h.export-align parted-1.9.0/include/parted/disk.h
--- parted-1.9.0/include/parted/disk.h.export-align	2009-11-03 11:30:46.000000000 +0100
+++ parted-1.9.0/include/parted/disk.h	2009-11-03 11:30:46.000000000 +0100
@@ -214,6 +214,7 @@ struct _PedDiskOps {
         int (*get_max_primary_partition_count) (const PedDisk* disk);
         bool (*get_max_supported_partition_count) (const PedDisk* disk,
                                                    int* supported);
+        PedAlignment *(*get_partition_alignment)(const PedDisk *disk);
 };
 
 struct _PedDiskType {
@@ -263,6 +264,7 @@ extern int ped_disk_get_last_partition_n
 extern int ped_disk_get_max_primary_partition_count (const PedDisk* disk);
 extern bool ped_disk_get_max_supported_partition_count(const PedDisk* disk,
                                                        int* supported);
+extern PedAlignment *ped_disk_get_partition_alignment(const PedDisk *disk);
 
 /** @} */
 
diff -up parted-1.9.0/include/parted/natmath.h.export-align parted-1.9.0/include/parted/natmath.h
--- parted-1.9.0/include/parted/natmath.h.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/include/parted/natmath.h	2009-11-03 11:30:46.000000000 +0100
@@ -31,6 +31,7 @@ typedef struct _PedAlignment	PedAlignmen
 
 #include <parted/disk.h>
 #include <parted/device.h>
+#include <parted/geom.h>
 
 #define PED_MIN(a, b)	( ((a)<(b)) ? (a) : (b) )
 #define PED_MAX(a, b)	( ((a)>(b)) ? (a) : (b) )
diff -up parted-1.9.0/libparted/Makefile.am.export-align parted-1.9.0/libparted/Makefile.am
--- parted-1.9.0/libparted/Makefile.am.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/libparted/Makefile.am	2009-11-03 11:30:46.000000000 +0100
@@ -50,6 +50,7 @@ libparted_la_LIBADD =	\
   $(DL_LIBS)		\
   $(DM_LIBS)		\
   $(SELINUX_LIBS)	\
+  $(LIB_BLKID)		\
   $(INTLLIBS)
 
 EXTRA_DIST	      = mbr.s
diff -up parted-1.9.0/libparted/arch/linux.c.export-align parted-1.9.0/libparted/arch/linux.c
--- parted-1.9.0/libparted/arch/linux.c.export-align	2009-11-03 11:30:46.000000000 +0100
+++ parted-1.9.0/libparted/arch/linux.c	2009-11-03 11:30:46.000000000 +0100
@@ -598,7 +598,24 @@ _have_kern26 ()
         kver = _get_linux_version();
         return have_kern26 = kver >= KERNEL_VERSION (2,6,0) ? 1 : 0;
 }
-  
+
+#if USE_BLKID
+static void
+get_blkid_topology (LinuxSpecific *arch_specific)
+{
+        arch_specific->probe = blkid_new_probe ();
+        if (!arch_specific->probe)
+                return;
+
+        if (blkid_probe_set_device(arch_specific->probe,
+                                   arch_specific->fd, 0, 0))
+                return;
+
+        arch_specific->topology =
+                blkid_probe_get_topology(arch_specific->probe);
+}
+#endif
+
 static void
 _device_set_sector_size (PedDevice* dev)
 {
@@ -626,6 +643,9 @@ _device_set_sector_size (PedDevice* dev)
                 dev->sector_size = (long long)sector_size;
         }
 
+#if USE_BLKID
+        get_blkid_topology(arch_specific);
+#endif
         /* Return PED_SECTOR_SIZE_DEFAULT for DASDs. */
         if (dev->type == PED_DEVICE_DASD) {
                 dev->sector_size = PED_SECTOR_SIZE_DEFAULT;
@@ -1215,6 +1235,10 @@ linux_new (const char* path)
                 goto error_free_path;
         arch_specific = LINUX_SPECIFIC (dev);
         arch_specific->dmtype = NULL;
+#if USE_BLKID
+        arch_specific->probe = NULL;
+        arch_specific->topology = NULL;
+#endif
 
         dev->open_count = 0;
         dev->read_only = 0;
@@ -1335,7 +1359,12 @@ error:
 static void
 linux_destroy (PedDevice* dev)
 {
-        free (((LinuxSpecific*)dev->arch_specific)->dmtype);
+        LinuxSpecific *arch_specific = LINUX_SPECIFIC(dev);
+#if USE_BLKID
+        if (arch_specific->probe)
+                blkid_free_probe(arch_specific->probe);
+#endif
+        free (arch_specific->dmtype);
         free (dev->arch_specific);
         free (dev->path);
         free (dev->model);
@@ -2446,6 +2475,34 @@ linux_disk_commit (PedDisk* disk)
         return 1;
 }
 
+#if HAVE_BLKID_BLKID_H
+PedAlignment*
+linux_get_minimum_alignment(const PedDevice *dev)
+{
+        blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
+
+        if (!tp || blkid_topology_get_minimum_io_size(tp) == 0)
+                return NULL; /* ped_alignment_none */
+
+        return ped_alignment_new(
+                blkid_topology_get_alignment_offset(tp) / dev->sector_size,
+                blkid_topology_get_minimum_io_size(tp) / dev->sector_size);
+}
+
+PedAlignment*
+linux_get_optimum_alignment(const PedDevice *dev)
+{
+        blkid_topology tp = LINUX_SPECIFIC(dev)->topology;
+
+        if (!tp || blkid_topology_get_optimal_io_size(tp) == 0)
+                return NULL; /* ped_alignment_none */
+
+        return ped_alignment_new(
+                blkid_topology_get_alignment_offset(tp) / dev->sector_size,
+                blkid_topology_get_optimal_io_size(tp) / dev->sector_size);
+}
+#endif
+
 static PedDeviceArchOps linux_dev_ops = {
         _new:           linux_new,
         destroy:        linux_destroy,
@@ -2459,7 +2516,11 @@ static PedDeviceArchOps linux_dev_ops = 
         check:          linux_check,
         sync:           linux_sync,
         sync_fast:      linux_sync_fast,
-        probe_all:      linux_probe_all
+        probe_all:      linux_probe_all,
+#if HAVE_BLKID_BLKID_H
+        get_minimum_alignment:	linux_get_minimum_alignment,
+        get_optimum_alignment:	linux_get_optimum_alignment,
+#endif
 };
 
 PedDiskArchOps linux_disk_ops =  {
diff -up parted-1.9.0/libparted/arch/linux.h.export-align parted-1.9.0/libparted/arch/linux.h
--- parted-1.9.0/libparted/arch/linux.h.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/libparted/arch/linux.h	2009-11-03 11:30:46.000000000 +0100
@@ -22,6 +22,10 @@
 #  include <parted/fdasd.h>
 #endif
 
+#if HAVE_BLKID_BLKID_H
+#  include <blkid/blkid.h>
+#endif
+
 #define LINUX_SPECIFIC(dev)	((LinuxSpecific*) (dev)->arch_specific)
 
 typedef	struct _LinuxSpecific	LinuxSpecific;
@@ -34,6 +38,10 @@ struct _LinuxSpecific {
 	/* IBM internal dasd structure (i guess ;), required. */
 	struct fdasd_anchor *anchor;
 #endif
+#if HAVE_BLKID_BLKID_H
+        blkid_probe probe;
+        blkid_topology topology;
+#endif
 };
 
 #endif /* PED_ARCH_LINUX_H_INCLUDED */
diff -up parted-1.9.0/libparted/device.c.export-align parted-1.9.0/libparted/device.c
--- parted-1.9.0/libparted/device.c.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/libparted/device.c	2009-11-03 11:30:46.000000000 +0100
@@ -416,33 +416,146 @@ ped_device_sync_fast (PedDevice* dev)
 }
 
 /**
- * Get a constraint that represents hardware requirements on alignment and
- * geometry.
- * This is, for example, important for media that have a physical sector
- * size that is a multiple of the logical sector size.
+ * Get a constraint that represents hardware requirements on geometry.
+ * This function will return a constraint representing the limits imposed
+ * by the size of the disk, it will *not* provide any alignment constraints.
  *
- * \warning This function is experimental for physical sector sizes not equal to
- *          2^9.
+ * Alignment constraints may be desirable when using media that have a physical
+ * sector size that is a multiple of the logical sector size, as in this case
+ * proper partition alignment can benefit disk performance signigicantly.
+ * When you want a constraint with alignment info, use
+ * ped_device_get_minimal_aligned_constraint() or
+ * ped_device_get_optimal_aligned_constraint().
+ *
+ * \return NULL on error, otherwise a pointer to a dynamically allocated
+ *         constraint.
  */
 PedConstraint*
 ped_device_get_constraint (PedDevice* dev)
 {
-        int multiplier = dev->phys_sector_size / dev->sector_size;
-
-        PedAlignment* start_align = ped_alignment_new (multiplier, multiplier);
-
         PedGeometry *s, *e;
         PedConstraint* c = ped_constraint_new (
-                                start_align, ped_alignment_any,
+                                ped_alignment_any, ped_alignment_any,
                                 s = ped_geometry_new (dev, 0, dev->length),
                                 e = ped_geometry_new (dev, 0, dev->length),
                                 1, dev->length);
 
         free (s);
         free (e);
+        return c;
+}
+
+static PedConstraint*
+_ped_device_get_aligned_constraint(const PedDevice *dev,
+                                   PedAlignment* start_align)
+{
+        PedAlignment *end_align = NULL;
+        PedGeometry *whole_dev_geom = NULL;
+        PedConstraint *c = NULL;
+
+        if (start_align) {
+                end_align = ped_alignment_new(start_align->offset - 1,
+                                              start_align->grain_size);
+                if (!end_align)
+                        goto free_start_align;
+        }
+
+        whole_dev_geom = ped_geometry_new (dev, 0, dev->length);
+
+        if (start_align)
+                c =  ped_constraint_new (start_align, end_align,
+                                         whole_dev_geom, whole_dev_geom,
+                                         1, dev->length);
+        else
+                c =  ped_constraint_new (ped_alignment_any, ped_alignment_any,
+                                         whole_dev_geom, whole_dev_geom,
+                                         1, dev->length);
+
+        free (whole_dev_geom);
+        free (end_align);
+free_start_align:
         free (start_align);
         return c;
 }
 
+/**
+ * Get a constraint that represents hardware requirements on geometry and
+ * alignment.
+ *
+ * This function will return a constraint representing the limits imposed
+ * by the size of the disk and the minimal alignment requirements for proper
+ * performance of the disk.
+ *
+ * \return NULL on error, otherwise a pointer to a dynamically allocated
+ *         constraint.
+ */
+PedConstraint*
+ped_device_get_minimal_aligned_constraint(const PedDevice *dev)
+{
+        return _ped_device_get_aligned_constraint(dev,
+                                         ped_device_get_minimum_alignment(dev));
+}
+
+/**
+ * Get a constraint that represents hardware requirements on geometry and
+ * alignment.
+ *
+ * This function will return a constraint representing the limits imposed
+ * by the size of the disk and the alignment requirements for optimal
+ * performance of the disk.
+ *
+ * \return NULL on error, otherwise a pointer to a dynamically allocated
+ *         constraint.
+ */
+PedConstraint*
+ped_device_get_optimal_aligned_constraint(const PedDevice *dev)
+{
+        return _ped_device_get_aligned_constraint(dev,
+                                         ped_device_get_optimum_alignment(dev));
+}
+
+/**
+ * Get an alignment that represents minimum hardware requirements on alignment.
+ * When for example using media that has a physical sector size that is a
+ * multiple of the logical sector size, it is desirable to have disk accesses
+ * (and thus partitions) properly aligned. Having partitions not aligned to
+ * the minimum hardware requirements may lead to a performance penalty.
+ *
+ * The returned alignment describes the alignment for the start sector of the
+ * partition, the end sector should be aligned too, to get the end sector
+ * alignment decrease the returned alignment's offset by 1.
+ *
+ * \return the minimum alignment of partition start sectors, or NULL if this
+ *         information is not available.
+ */
+PedAlignment*
+ped_device_get_minimum_alignment(const PedDevice *dev)
+{
+        if (ped_architecture->dev_ops->get_minimum_alignment)
+                return ped_architecture->dev_ops->get_minimum_alignment(dev);
+
+        return NULL; /* ped_alignment_none */
+}
+
+/**
+ * Get an alignment that represents the hardware requirements for optimal
+ * performance.
+ *
+ * The returned alignment describes the alignment for the start sector of the
+ * partition, the end sector should be aligned too, to get the end sector
+ * alignment decrease the returned alignment's offset by 1.
+ *
+ * \return the optimal alignment of partition start sectors, or NULL if this
+ *         information is not available.
+ */
+PedAlignment*
+ped_device_get_optimum_alignment(const PedDevice *dev)
+{
+        if (ped_architecture->dev_ops->get_optimum_alignment)
+                return ped_architecture->dev_ops->get_optimum_alignment(dev);
+
+        return NULL; /* ped_alignment_none */
+}
+
 /** @} */
 
diff -up parted-1.9.0/libparted/disk.c.export-align parted-1.9.0/libparted/disk.c
--- parted-1.9.0/libparted/disk.c.export-align	2009-11-03 11:30:46.000000000 +0100
+++ parted-1.9.0/libparted/disk.c	2009-11-03 11:30:46.000000000 +0100
@@ -703,6 +703,26 @@ ped_disk_get_max_supported_partition_cou
 }
 
 /**
+ * Get the alignment needed for partition boundaries on this disk.
+ * The returned alignment describes the alignment for the start sector of the
+ * partition, for all disklabel types which require alignment, except Sun
+ * disklabels, the end sector must be aligned too. To get the end sector
+ * alignment decrease the PedAlignment offset by 1.
+ *
+ * \return NULL on error, otherwise a pointer to a dynamically allocated
+ *         alignment.
+ */
+PedAlignment*
+ped_disk_get_partition_alignment(const PedDisk *disk)
+{
+        /* disklabel handlers which don't need alignment don't define this */
+        if (!disk->type->ops->get_partition_alignment)
+                return ped_alignment_duplicate(ped_alignment_any);
+
+        return disk->type->ops->get_partition_alignment(disk);
+}
+
+/**
  * Get the maximum number of (primary) partitions the disk label supports.
  *
  * For example, MacIntosh partition maps can have different sizes,
diff -up parted-1.9.0/libparted/labels/dasd.c.export-align parted-1.9.0/libparted/labels/dasd.c
--- parted-1.9.0/libparted/labels/dasd.c.export-align	2009-11-03 11:30:46.000000000 +0100
+++ parted-1.9.0/libparted/labels/dasd.c	2009-11-03 11:32:19.000000000 +0100
@@ -646,6 +646,16 @@ dasd_get_max_supported_partition_count (
 	return true;
 }
 
+static PedAlignment*
+dasd_get_partition_alignment(const PedDisk *disk)
+{
+        DasdDiskSpecific* disk_specific = disk->disk_specific;
+        PedSector sector_size =
+                disk_specific->real_sector_size / disk->dev->sector_size;
+
+        return ped_alignment_new(0, disk->dev->hw_geom.sectors * sector_size);
+}
+
 static PedConstraint*
 _primary_constraint (PedDisk* disk)
 {
@@ -830,6 +840,7 @@ static PedDiskOps dasd_disk_ops = {
 	alloc_metadata: dasd_alloc_metadata,
 	get_max_primary_partition_count: dasd_get_max_primary_partition_count,
 	get_max_supported_partition_count: dasd_get_max_supported_partition_count,
+	get_partition_alignment: dasd_get_partition_alignment,
 
 	partition_duplicate: NULL
 };
diff -up parted-1.9.0/libparted/labels/mac.c.export-align parted-1.9.0/libparted/labels/mac.c
--- parted-1.9.0/libparted/labels/mac.c.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/libparted/labels/mac.c	2009-11-03 11:30:46.000000000 +0100
@@ -1375,6 +1375,14 @@ mac_partition_get_name (const PedPartiti
 	return mac_data->volume_name;
 }
 
+static PedAlignment*
+mac_get_partition_alignment(const PedDisk *disk)
+{
+        PedSector sector_size = disk->dev->sector_size / 512;
+
+        return ped_alignment_new(0, sector_size);
+}
+
 static PedConstraint*
 _primary_constraint (PedDisk* disk)
 {
@@ -1606,7 +1614,8 @@ static PedDiskOps mac_disk_ops = {
 	get_max_primary_partition_count:
 				mac_get_max_primary_partition_count,
 	get_max_supported_partition_count:
-				mac_get_max_supported_partition_count
+				mac_get_max_supported_partition_count,
+	get_partition_alignment: mac_get_partition_alignment,
 };
 
 static PedDiskType mac_disk_type = {
diff -up parted-1.9.0/libparted/labels/pc98.c.export-align parted-1.9.0/libparted/labels/pc98.c
--- parted-1.9.0/libparted/labels/pc98.c.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/libparted/labels/pc98.c	2009-11-03 11:30:46.000000000 +0100
@@ -720,6 +720,15 @@ pc98_partition_get_name (const PedPartit
 	return pc98_data->name;
 }
 
+static PedAlignment*
+pc98_get_partition_alignment(const PedDisk *disk)
+{
+	PedSector cylinder_size =
+		disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads;
+
+        return ped_alignment_new(0, cylinder_size);
+}
+
 static PedConstraint*
 _primary_constraint (PedDisk* disk)
 {
@@ -872,7 +881,8 @@ static PedDiskOps pc98_disk_ops = {
 	get_max_primary_partition_count:
 				pc98_get_max_primary_partition_count,
 	get_max_supported_partition_count:
-				pc98_get_max_supported_partition_count
+				pc98_get_max_supported_partition_count,
+	get_partition_alignment: pc98_get_partition_alignment,
 };
 
 static PedDiskType pc98_disk_type = {
diff -up parted-1.9.0/libparted/labels/rdb.c.export-align parted-1.9.0/libparted/labels/rdb.c
--- parted-1.9.0/libparted/labels/rdb.c.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/libparted/labels/rdb.c	2009-11-03 11:30:46.000000000 +0100
@@ -1024,6 +1024,15 @@ amiga_partition_get_name (const PedParti
 	return _amiga_get_bstr(partition->pb_DriveName);
 }
 
+static PedAlignment*
+amiga_get_partition_alignment(const PedDisk *disk)
+{
+	PedSector cylinder_size =
+		disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads;
+
+        return ped_alignment_new(0, cylinder_size);
+}
+
 static PedConstraint*
 _amiga_get_constraint (const PedDisk *disk)
 {
@@ -1166,7 +1175,8 @@ static PedDiskOps amiga_disk_ops = {
 	get_max_primary_partition_count:
 				amiga_get_max_primary_partition_count,
 	get_max_supported_partition_count:
-				amiga_get_max_supported_partition_count
+				amiga_get_max_supported_partition_count,
+	get_partition_alignment: amiga_get_partition_alignment,
 };
 
 static PedDiskType amiga_disk_type = {
diff -up parted-1.9.0/libparted/labels/sun.c.export-align parted-1.9.0/libparted/labels/sun.c
--- parted-1.9.0/libparted/labels/sun.c.export-align	2009-07-23 19:52:08.000000000 +0200
+++ parted-1.9.0/libparted/labels/sun.c	2009-11-03 11:30:46.000000000 +0100
@@ -677,6 +677,15 @@ sun_get_max_primary_partition_count (con
 	return SUN_DISK_MAXPARTITIONS;
 }
 
+static PedAlignment*
+sun_get_partition_alignment(const PedDisk *disk)
+{
+	PedSector block =
+		disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads;
+
+        return ped_alignment_new(0, block);
+}
+
 static PedConstraint*
 _get_strict_constraint (PedDisk* disk)
 {
@@ -867,6 +876,7 @@ static PedDiskOps sun_disk_ops = {
 				sun_get_max_primary_partition_count,
 	get_max_supported_partition_count:
 				sun_get_max_supported_partition_count,
+	get_partition_alignment: sun_get_partition_alignment,
 
 	partition_set_name:		NULL,
 	partition_get_name:		NULL,