diff options
author | Karel Zak | 2015-09-09 14:48:33 +0200 |
---|---|---|
committer | Karel Zak | 2015-09-09 14:48:33 +0200 |
commit | d85a7fa744fdf96d585150202057de392b2733f1 (patch) | |
tree | e19cf77a5de517ee86d296d4bf4dbee599bdd98b /disk-utils/sfdisk.c | |
parent | tests: add sfdisk --move-data test (diff) | |
download | kernel-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.c | 52 |
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) |