summaryrefslogtreecommitdiffstats
path: root/disk-utils/sfdisk.c
diff options
context:
space:
mode:
authorKarel Zak2015-09-09 14:48:33 +0200
committerKarel Zak2015-09-09 14:48:33 +0200
commitd85a7fa744fdf96d585150202057de392b2733f1 (patch)
treee19cf77a5de517ee86d296d4bf4dbee599bdd98b /disk-utils/sfdisk.c
parenttests: add sfdisk --move-data test (diff)
downloadkernel-qcow2-util-linux-d85a7fa744fdf96d585150202057de392b2733f1.tar.gz
kernel-qcow2-util-linux-d85a7fa744fdf96d585150202057de392b2733f1.tar.xz
kernel-qcow2-util-linux-d85a7fa744fdf96d585150202057de392b2733f1.zip
sfdisk: cleanup and optimize --move-data
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'disk-utils/sfdisk.c')
-rw-r--r--disk-utils/sfdisk.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c
index 9f4861188..aa2257110 100644
--- a/disk-utils/sfdisk.c
+++ b/disk-utils/sfdisk.c
@@ -359,7 +359,7 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
struct fdisk_partition *pa = get_partition(sf->cxt, partno);
char *devname, *typescript;
FILE *f;
- int ok = 0, fd, backward;
+ int ok = 0, fd, backward = 0;
fdisk_sector_t nsectors, from, to, step, i;
size_t ss, step_bytes, cc;
uintmax_t src, dst;
@@ -386,26 +386,43 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
if (!ok)
return -EINVAL;
+ DBG(MISC, ul_debug("moving data"));
+
fd = fdisk_get_devfd(sf->cxt);
ss = fdisk_get_sector_size(sf->cxt);
nsectors = fdisk_partition_get_size(orig_pa);
from = fdisk_partition_get_start(orig_pa);
to = fdisk_partition_get_start(pa);
- backward = from < to;
-
- /* step cannot be bigger than gap between new and old location */
- step = from > to ? from - to : to - from;
- /* step cannot be bigger than original partition size */
- if (step > fdisk_partition_get_size(orig_pa))
- step = fdisk_partition_get_size(orig_pa);
- /* step cannot be begger than ~1MiB */
- if (step > (getpagesize() * 256) / ss)
+
+ if ((to >= from && from + nsectors >= to) ||
+ (from >= to && to + nsectors >= from)) {
+ /* source and target overlay, check if we need to copy
+ * backwardly from end of the source */
+ DBG(MISC, ul_debug("overlay between source and target"));
+ backward = from < to;
+ DBG(MISC, ul_debug(" copy order: %s", backward ? "backward" : "forward"));
+
+ step = from > to ? from - to : to - from;
+ if (step > nsectors)
+ step = nsectors;
+ } else
+ step = nsectors;
+
+ /* make step usable for malloc() */
+ if (step * ss > (getpagesize() * 256U))
step = (getpagesize() * 256) / ss;
+
+ /* align the step (note that nsectors does not have to be power of 2) */
+ while (nsectors % step)
+ step--;
+
step_bytes = step * ss;
+ DBG(MISC, ul_debug(" step: %ju (%ju bytes)", step, step_bytes));
#if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
- posix_fadvise(fd, from * ss, nsectors * ss, POSIX_FADV_SEQUENTIAL);
+ if (!backward)
+ posix_fadvise(fd, from * ss, nsectors * ss, POSIX_FADV_SEQUENTIAL);
#endif
devname = fdisk_partname(fdisk_get_devname(sf->cxt), partno+1);
typescript = mk_backup_filename_tpl(sf->move_typescript, devname, ".move");
@@ -439,9 +456,10 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
fprintf(f, "# Disk: %s\n", devname);
fprintf(f, "# Partition: %zu\n", partno + 1);
fprintf(f, "# Operation: move data\n");
- fprintf(f, "# Original start offset (in sectors): %ju\n", fdisk_partition_get_start(orig_pa));
- fprintf(f, "# New start offset (in sectors): %ju\n", fdisk_partition_get_start(pa));
- fprintf(f, "# Area size (in sectors): %ju\n", nsectors);
+ fprintf(f, "# Original start offset (sectors/bytes): %ju/%ju\n", from, from * ss);
+ fprintf(f, "# New start offset (sectors/bytes): %ju/%ju\n", to, to * ss);
+ fprintf(f, "# Area size (sectors/bytes): %ju/%ju\n", nsectors, nsectors * ss);
+ fprintf(f, "# Sector size: %zu\n", ss);
fprintf(f, "# Step size (in bytes): %zu\n", step_bytes);
fprintf(f, "# Steps: %zu\n", nsectors / step);
fprintf(f, "#\n");
@@ -451,18 +469,12 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
dst = (backward ? to + nsectors : to) * ss;
buf = xmalloc(step_bytes);
- /*
- fprintf(stderr, ">>>%s: src=%ju, dst=%ju, step=%ju (%ju bytes)\n",
- backward ? "backward" : "forward", src, dst, step, step_bytes);
- */
-
for (cc = 1, i = 0; i < nsectors; i += step, cc++) {
ssize_t rc;
if (backward)
src -= step_bytes, dst -= step_bytes;
-
lseek(fd, src, SEEK_SET);
rc = read(fd, buf, step_bytes);
if (rc < 0 || rc != (ssize_t) step_bytes)