]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - disk-utils/sfdisk.c
sfdisk: (move-data) improve MiB/s progress bar
[thirdparty/util-linux.git] / disk-utils / sfdisk.c
index e7481aab79dab7fcb4280192cdfe68527719ce4b..3bda79cecaf2a8e865d497307f82e4a75993982c 100644 (file)
@@ -37,6 +37,7 @@
 # include <readline/readline.h>
 #endif
 #include <libgen.h>
+#include <sys/time.h>
 
 #include "c.h"
 #include "xalloc.h"
@@ -49,6 +50,7 @@
 #include "all-io.h"
 #include "rpmatch.h"
 #include "optutils.h"
+#include "ttyutils.h"
 
 #include "libfdisk.h"
 #include "fdisk-list.h"
@@ -111,6 +113,7 @@ struct sfdisk {
                     append : 1,        /* don't create new PT, append partitions only */
                     json : 1,          /* JSON dump */
                     movedata: 1,       /* move data after resize */
+                    movefsync: 1, /* use fsync() afetr each write() */
                     notell : 1,        /* don't tell kernel aout new PT */
                     noact  : 1;        /* do not write to device */
 };
@@ -369,10 +372,12 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
        char *devname = NULL, *typescript = NULL, *buf = NULL;
        FILE *f = NULL;
        int ok = 0, fd, backward = 0;
-       fdisk_sector_t nsectors, from, to, step, i;
+       fdisk_sector_t nsectors, from, to, step, i, prev;
        size_t io, ss, step_bytes, cc;
        uintmax_t src, dst;
-       int errsv;
+       int errsv, progress = 0;
+       struct timeval prev_time;
+       uint64_t bytes_per_sec = 0;
 
        assert(sf->movedata);
 
@@ -451,6 +456,9 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
                printf(_("  step size: %zu bytes\n"), step_bytes);
                putchar('\n');
                fflush(stdout);
+
+               if (isatty(fileno(stdout)))
+                       progress = 1;
        }
 
        if (sf->interactive) {
@@ -493,6 +501,9 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
 
        DBG(MISC, ul_debug(" initial: src=%ju dst=%ju", src, dst));
 
+       gettimeofday(&prev_time, NULL);
+       prev = 0;
+
        for (cc = 1, i = 0; i < nsectors; i += step, cc++) {
                ssize_t rc;
 
@@ -515,21 +526,59 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
                        rc = write(fd, buf, step_bytes);
                        if (rc < 0 || rc != (ssize_t) step_bytes)
                                goto fail;
-                       fsync(fd);
+                       if (sf->movefsync)
+                               fsync(fd);
                }
 
                /* write log */
                if (f)
                        fprintf(f, "%05zu: %12ju %12ju\n", cc, src, dst);
 
-#if defined(POSIX_FADV_DONTNEED) && defined(HAVE_POSIX_FADVISE)
-               if (!sf->noact)
-                       posix_fadvise(fd, src, step_bytes, POSIX_FADV_DONTNEED);
-#endif
+               if (progress && i % 10 == 0) {
+                       unsigned int elapsed = 0;       /* usec */
+                       struct timeval cur_time;
+
+                       gettimeofday(&cur_time, NULL);
+                       if (cur_time.tv_sec - prev_time.tv_sec > 1) {
+                               elapsed = ((cur_time.tv_sec - prev_time.tv_sec) * 1000000) +
+                                         (cur_time.tv_usec - prev_time.tv_usec);
+
+                               bytes_per_sec = ((i - prev) * ss) / elapsed;    /* per usec */
+                               bytes_per_sec *= 1000000;                       /* per sec */
+
+                               prev_time = cur_time;
+                               prev = i;
+                       }
+
+                       if (bytes_per_sec)
+                               fprintf(stdout, _("Moved %ju from %ju sectors (%.3f%%, %.1f MiB/s)."),
+                                       i + 1, nsectors,
+                                       100.0 / ((double) nsectors/(i+1)),
+                                       (double) (bytes_per_sec / (1024 * 1024)));
+                       else
+                               fprintf(stdout, _("Moved %ju from %ju sectors (%.3f%%)."),
+                                       i + 1, nsectors,
+                                       100.0 / ((double) nsectors/(i+1)));
+                       fflush(stdout);
+                        fputc('\r', stdout);
+
+               }
+
                if (!backward)
                        src += step_bytes, dst += step_bytes;
        }
 
+       if (progress) {
+               int x = get_terminal_width(80);
+               for (; x > 0; x--)
+                       fputc(' ', stdout);
+               fflush(stdout);
+               fputc('\r', stdout);
+               fprintf(stdout, _("Moved %ju from %ju sectors (%.3f%%)."),
+                               i, nsectors,
+                               100.0 / ((double) nsectors/(i+1)));
+               fputc('\n', stdout);
+       }
        if (f)
                fclose(f);
        free(buf);
@@ -1898,6 +1947,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -b, --backup              backup partition table sectors (see -O)\n"), out);
        fputs(_("     --bytes               print SIZE in bytes rather than in human readable format\n"), out);
        fputs(_("     --move-data[=<typescript>] move partition data after relocation (requires -N)\n"), out);
+       fputs(_("     --move-use-fsync      use fsync after each write when move data\n"), out);
        fputs(_(" -f, --force               disable all consistency checking\n"), out);
        fprintf(out,
              _("     --color[=<when>]      colorize output (%s, %s or %s)\n"), "auto", "always", "never");
@@ -1956,6 +2006,7 @@ int main(int argc, char *argv[])
                OPT_BYTES,
                OPT_COLOR,
                OPT_MOVEDATA,
+               OPT_MOVEFSYNC,
                OPT_DELETE,
                OPT_NOTELL
        };
@@ -1981,6 +2032,7 @@ int main(int argc, char *argv[])
                { "no-reread", no_argument,     NULL, OPT_NOREREAD },
                { "no-tell-kernel", no_argument, NULL, OPT_NOTELL },
                { "move-data", optional_argument, NULL, OPT_MOVEDATA },
+               { "move-use-fsync", no_argument, NULL, OPT_MOVEFSYNC },
                { "output",  required_argument, NULL, 'o' },
                { "partno",  required_argument, NULL, 'N' },
                { "reorder", no_argument,       NULL, 'r' },
@@ -2152,6 +2204,9 @@ int main(int argc, char *argv[])
                        sf->movedata = 1;
                        sf->move_typescript = optarg;
                        break;
+               case OPT_MOVEFSYNC:
+                       sf->movefsync = 1;
+                       break;
                case OPT_DELETE:
                        sf->act = ACT_DELETE;
                        break;