From adf09b5c380fe616fa28b1975703b83e75d0b32b Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 22 Aug 2017 14:55:51 +0200 Subject: [PATCH] libfdisk: add fdisk_save_user_grain() Let's provide API for applications that don't want to use the default 1MiB grain. The new function allow to use "as minimal as possible" if grain is set by fdisk_save_user_grain() to 512. If the phy sector size (or minimal I/O size) is greater than specified grain size than smallest possible setting is used. Signed-off-by: Karel Zak --- libfdisk/docs/libfdisk-sections.txt | 1 + libfdisk/src/alignment.c | 41 ++++++++++++++++++++++++++++- libfdisk/src/fdiskP.h | 1 + libfdisk/src/libfdisk.h.in | 3 +++ libfdisk/src/libfdisk.sym | 1 + 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt index 68ca0927fd..37ceffa864 100644 --- a/libfdisk/docs/libfdisk-sections.txt +++ b/libfdisk/docs/libfdisk-sections.txt @@ -69,6 +69,7 @@ fdisk_override_geometry fdisk_reset_alignment fdisk_reset_device_properties fdisk_save_user_geometry +fdisk_save_user_grain fdisk_save_user_sector_size diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c index 6b395b48cd..4c9fbcb9a7 100644 --- a/libfdisk/src/alignment.c +++ b/libfdisk/src/alignment.c @@ -26,7 +26,7 @@ * It's recommended to not change any alignment or device properties. All is * initialized by default by fdisk_assign_device(). * - * Note that terminology used by libfdisk is: + * Note that terminology used by libfdisk is: * - device properties: I/O limits (topology), geometry, sector size, ... * - alignment: first, last LBA, grain, ... * @@ -313,6 +313,36 @@ int fdisk_save_user_sector_size(struct fdisk_context *cxt, return 0; } +/** + * fdisk_save_user_grain: + * @cxt: context + * @grain: size in bytes (>= 512, multiple of 512) + * + * Save user define grain size. The size is used to align partitions. + * + * The default is 1MiB (or optimal I/O size if greater than 1MiB). It's strongly + * recommended to use the default. + * + * The smallest possible granularity for partitioning is physical sector size + * (or minimal I/O size; the bigger number win). If the user's @grain size is + * too small than the smallest possible granularity is used. It means + * fdisk_save_user_grain(cxt, 512) forces libfdisk to use grain as small as + * possible. + * + * The setting is applied by fdisk_assign_device() or + * fdisk_reset_device_properties(). + * + * Returns: <0 on error, 0 on success. + */ +int fdisk_save_user_grain(struct fdisk_context *cxt, unsigned long grain) +{ + if (!cxt || grain % 512) + return -EINVAL; + + cxt->user_grain = grain; + return 0; +} + /** * fdisk_has_user_device_properties: * @cxt: context @@ -322,6 +352,7 @@ int fdisk_save_user_sector_size(struct fdisk_context *cxt, int fdisk_has_user_device_properties(struct fdisk_context *cxt) { return (cxt->user_pyh_sector || cxt->user_log_sector || + cxt->user_grain || fdisk_has_user_device_geometry(cxt)); } @@ -363,6 +394,14 @@ int fdisk_apply_user_device_properties(struct fdisk_context *cxt) recount_geometry(cxt); fdisk_reset_alignment(cxt); + + if (cxt->user_grain) { + unsigned long granularity = max(cxt->phy_sector_size, cxt->min_io_size); + + cxt->grain = cxt->user_grain < granularity ? granularity : cxt->user_grain; + DBG(CXT, ul_debugobj(cxt, "new grain: %lu", cxt->grain)); + } + if (cxt->firstsector_bufsz != cxt->sector_size) fdisk_read_firstsector(cxt); diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index 1796e18e1c..23903b4b47 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -399,6 +399,7 @@ struct fdisk_context { struct fdisk_geometry user_geom; unsigned long user_pyh_sector; unsigned long user_log_sector; + unsigned long user_grain; struct fdisk_label *label; /* current label, pointer to labels[] */ diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in index 1c16fe4b34..3586d66267 100644 --- a/libfdisk/src/libfdisk.h.in +++ b/libfdisk/src/libfdisk.h.in @@ -503,6 +503,9 @@ int fdisk_save_user_geometry(struct fdisk_context *cxt, int fdisk_save_user_sector_size(struct fdisk_context *cxt, unsigned int phy, unsigned int log); + +int fdisk_save_user_grain(struct fdisk_context *cxt, unsigned long grain); + int fdisk_has_user_device_properties(struct fdisk_context *cxt); int fdisk_reset_alignment(struct fdisk_context *cxt); int fdisk_reset_device_properties(struct fdisk_context *cxt); diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym index 0d274847a0..2c892a0c39 100644 --- a/libfdisk/src/libfdisk.sym +++ b/libfdisk/src/libfdisk.sym @@ -289,4 +289,5 @@ FDISK_2.31 { fdisk_reread_changes; fdisk_disable_dialogs; fdisk_has_dialogs; + fdisk_save_user_grain; } FDISK_2.30; -- 2.47.2