summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/table.c
diff options
context:
space:
mode:
authorKarel Zak2017-07-14 10:51:14 +0200
committerKarel Zak2017-07-14 11:34:55 +0200
commit1dd63a3b05acd7640c688f9535508417fac950d1 (patch)
tree245abf4c0da52ec0d169dddd558b960e10526c7b /libfdisk/src/table.c
parentpartx: move partx.h to include/ (diff)
downloadkernel-qcow2-util-linux-1dd63a3b05acd7640c688f9535508417fac950d1.tar.gz
kernel-qcow2-util-linux-1dd63a3b05acd7640c688f9535508417fac950d1.tar.xz
kernel-qcow2-util-linux-1dd63a3b05acd7640c688f9535508417fac950d1.zip
libfdisk: use BLKPG ioctls to inform kernel about changes
This patch introduces fdisk_reread_changes(). The function is less invasive alternative to fdisk_reread_partition_table(). The new function uses BLKPG ioctls for modified partitions. The another partitions are not affected. This solution allows to successfully use fdisks on disk where some partitions are still use (mounted). For example if you want to resize the last partition on the device. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk/src/table.c')
-rw-r--r--libfdisk/src/table.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/libfdisk/src/table.c b/libfdisk/src/table.c
index f9751686b..903778426 100644
--- a/libfdisk/src/table.c
+++ b/libfdisk/src/table.c
@@ -709,3 +709,72 @@ int fdisk_apply_table(struct fdisk_context *cxt, struct fdisk_table *tb)
return rc;
}
+int fdisk_diff_tables(struct fdisk_table *a, struct fdisk_table *b,
+ struct fdisk_iter *itr,
+ struct fdisk_partition **res, int *change)
+{
+ struct fdisk_partition *pa, *pb;
+ int rc = 1;
+
+ assert(itr);
+ assert(res);
+ assert(change);
+
+ DBG(TAB, ul_debugobj(a, "table diff [new table=%p]", b));
+
+ if (a && (itr->head == NULL || itr->head == &a->parts)) {
+ DBG(TAB, ul_debugobj(a, " scanning old table"));
+ do {
+ rc = fdisk_table_next_partition(a, itr, &pa);
+ if (rc != 0)
+ break;
+ } while (!fdisk_partition_has_partno(pa));
+ }
+
+ if (rc == 1 && b) {
+ DBG(TAB, ul_debugobj(a, " scanning new table"));
+ if (itr->head != &b->parts) {
+ DBG(TAB, ul_debugobj(a, " initialize to TAB=%p", b));
+ fdisk_reset_iter(itr, FDISK_ITER_FORWARD);
+ }
+
+ while (fdisk_table_next_partition(b, itr, &pb) == 0) {
+ if (!fdisk_partition_has_partno(pb))
+ continue;
+ if (a == NULL ||
+ fdisk_table_get_partition_by_partno(a, pb->partno) == NULL) {
+ DBG(TAB, ul_debugobj(a, " #%zu ADDED", pb->partno));
+ *change = FDISK_DIFF_ADDED;
+ *res = pb;
+ return 0;
+ }
+ }
+ }
+
+ if (rc) {
+ DBG(TAB, ul_debugobj(a, "table diff done [rc=%d]", rc));
+ return rc; /* error or done */
+ }
+
+ pb = fdisk_table_get_partition_by_partno(b, pa->partno);
+
+ if (!pb) {
+ DBG(TAB, ul_debugobj(a, " #%zu REMOVED", pa->partno));
+ *change = FDISK_DIFF_REMOVED;
+ *res = pa;
+ } else if (pb->start != pa->start) {
+ DBG(TAB, ul_debugobj(a, " #%zu MOVED", pb->partno));
+ *change = FDISK_DIFF_MOVED;
+ *res = pb;
+ } else if (pb->size != pa->size) {
+ DBG(TAB, ul_debugobj(a, " #%zu RESIZED", pb->partno));
+ *change = FDISK_DIFF_RESIZED;
+ *res = pb;
+ } else {
+ DBG(TAB, ul_debugobj(a, " #%zu UNCHANGED", pb->partno));
+ *change = FDISK_DIFF_UNCHANGED;
+ *res = pa;
+ }
+ return 0;
+}
+