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 + /** * 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 @@ -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,8 @@ 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); + extern int ped_disk_align_to_cylinders_on(); extern int ped_disk_align_to_cylinders_toggle(); /** @} */ 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 #include +#include #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 #endif +#if HAVE_BLKID_BLKID_H +# include +#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,