diff options
author | Karel Zak | 2017-07-14 10:51:14 +0200 |
---|---|---|
committer | Karel Zak | 2017-07-14 11:34:55 +0200 |
commit | 1dd63a3b05acd7640c688f9535508417fac950d1 (patch) | |
tree | 245abf4c0da52ec0d169dddd558b960e10526c7b /libfdisk/src/table.c | |
parent | partx: move partx.h to include/ (diff) | |
download | kernel-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.c | 69 |
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; +} + |