summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2017-08-22 14:55:51 +0200
committerKarel Zak2017-08-22 14:55:51 +0200
commitadf09b5c380fe616fa28b1975703b83e75d0b32b (patch)
tree779ed6403b989552397369bf80b28dfc7d09e204
parentlibfdisk: (dos) use size-=1 when alignment not used later (diff)
downloadkernel-qcow2-util-linux-adf09b5c380fe616fa28b1975703b83e75d0b32b.tar.gz
kernel-qcow2-util-linux-adf09b5c380fe616fa28b1975703b83e75d0b32b.tar.xz
kernel-qcow2-util-linux-adf09b5c380fe616fa28b1975703b83e75d0b32b.zip
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 <kzak@redhat.com>
-rw-r--r--libfdisk/docs/libfdisk-sections.txt1
-rw-r--r--libfdisk/src/alignment.c41
-rw-r--r--libfdisk/src/fdiskP.h1
-rw-r--r--libfdisk/src/libfdisk.h.in3
-rw-r--r--libfdisk/src/libfdisk.sym1
5 files changed, 46 insertions, 1 deletions
diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt
index 68ca0927f..37ceffa86 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
</SECTION>
diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c
index 6b395b48c..4c9fbcb9a 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, ...
*
@@ -314,6 +314,36 @@ int fdisk_save_user_sector_size(struct fdisk_context *cxt,
}
/**
+ * 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 1796e18e1..23903b4b4 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 1c16fe4b3..3586d6626 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 0d274847a..2c892a0c3 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;