diff --git a/SOURCES/0079-blkdiscard-backport-zeroout-support.patch b/SOURCES/0079-blkdiscard-backport-zeroout-support.patch new file mode 100644 index 00000000..d33cefc3 --- /dev/null +++ b/SOURCES/0079-blkdiscard-backport-zeroout-support.patch @@ -0,0 +1,277 @@ +From ca291153ff2c696696c1406aca6433aab6e412a1 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Fri, 24 Jun 2016 13:36:32 +0200 +Subject: [PATCH 79/84] blkdiscard: backport --zeroout support + +The patch also includes upstream cleanups. + +Upstream: http://github.com/karelzak/util-linux/commit/0e765365798c54d412e355798ad584a52035f228 +Upstream: http://github.com/karelzak/util-linux/commit/a3e91e26467a0f644ee568bb0b3d481591834015 +Upstream: http://github.com/karelzak/util-linux/commit/eeae448805c0eb2ef130a6ac301750706bb80420 +Upstream: http://github.com/karelzak/util-linux/commit/7154cc892688f3c58cbbcdc2055f2635c1d0ef5b +Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1327886 +Signed-off-by: Karel Zak +--- + bash-completion/blkdiscard | 2 +- + sys-utils/blkdiscard.8 | 7 +-- + sys-utils/blkdiscard.c | 122 ++++++++++++++++++++++++++++++++++----------- + 3 files changed, 98 insertions(+), 33 deletions(-) + +diff --git a/bash-completion/blkdiscard b/bash-completion/blkdiscard +index 310cdfb..fb3cb1e 100644 +--- a/bash-completion/blkdiscard ++++ b/bash-completion/blkdiscard +@@ -15,7 +15,7 @@ _blkdiscard_module() + esac + case $cur in + -*) +- OPTS="--offset --length --secure --verbose --help --version" ++ OPTS="--offset --length --secure --zeroout --verbose --help --version" + COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) ) + return 0 + ;; +diff --git a/sys-utils/blkdiscard.8 b/sys-utils/blkdiscard.8 +index 5e094d4..71180e9 100644 +--- a/sys-utils/blkdiscard.8 ++++ b/sys-utils/blkdiscard.8 +@@ -1,15 +1,13 @@ +-.\" -*- nroff -*- + .TH BLKDISCARD 8 "July 2014" "util-linux" "System Administration" + .SH NAME + blkdiscard \- discard sectors on a device + .SH SYNOPSIS + .B blkdiscard ++[options] + .RB [ \-o + .IR offset ] + .RB [ \-l + .IR length ] +-.RB [ \-s ] +-.RB [ \-v ] + .I device + .SH DESCRIPTION + .B blkdiscard +@@ -59,6 +57,9 @@ Perform a secure discard. A secure discard is the same as a regular discard + except that all copies of the discarded blocks that were possibly created by + garbage collection must also be erased. This requires support from the device. + .TP ++.BR \-z , " \-\-zeroout" ++Zero-fill rather than discard. ++.TP + .BR \-v , " \-\-verbose" + Display the aligned values of + .I offset +diff --git a/sys-utils/blkdiscard.c b/sys-utils/blkdiscard.c +index 92ca52a..0ba99ee 100644 +--- a/sys-utils/blkdiscard.c ++++ b/sys-utils/blkdiscard.c +@@ -44,43 +44,95 @@ + #include "closestream.h" + + #ifndef BLKDISCARD +-#define BLKDISCARD _IO(0x12,119) ++# define BLKDISCARD _IO(0x12,119) + #endif + + #ifndef BLKSECDISCARD +-#define BLKSECDISCARD _IO(0x12,125) ++# define BLKSECDISCARD _IO(0x12,125) + #endif + +-#define print_stats(path, stats) \ +- printf(_("%s: Discarded %" PRIu64 " bytes from the " \ +- "offset %" PRIu64"\n"), path, stats[1], stats[0]); ++#ifndef BLKZEROOUT ++# define BLKZEROOUT _IO(0x12,127) ++#endif ++ ++enum { ++ ACT_DISCARD = 0, /* default */ ++ ACT_ZEROOUT, ++ ACT_SECURE ++}; ++ ++/* RHEL: backport from upstream lib/monotonic.c */ ++static int gettime_monotonic(struct timeval *tv) ++{ ++#ifdef CLOCK_MONOTONIC ++ /* Can slew only by ntp and adjtime */ ++ int ret; ++ struct timespec ts; ++ ++# ifdef CLOCK_MONOTONIC_RAW ++ /* Linux specific, can't slew */ ++ if (!(ret = clock_gettime(CLOCK_MONOTONIC_RAW, &ts))) { ++# else ++ if (!(ret = clock_gettime(CLOCK_MONOTONIC, &ts))) { ++# endif ++ tv->tv_sec = ts.tv_sec; ++ tv->tv_usec = ts.tv_nsec / 1000; ++ } ++ return ret; ++#else ++ return gettimeofday(tv, NULL); ++#endif ++} ++ ++static void print_stats(int act, char *path, uint64_t stats[]) ++{ ++ switch (act) { ++ case ACT_ZEROOUT: ++ printf(_("%s: Zero-filled %" PRIu64 " bytes from the offset %" PRIu64"\n"), \ ++ path, stats[1], stats[0]); ++ break; ++ case ACT_SECURE: ++ case ACT_DISCARD: ++ printf(_("%s: Discarded %" PRIu64 " bytes from the offset %" PRIu64"\n"), \ ++ path, stats[1], stats[0]); ++ break; ++ } ++} + + static void __attribute__((__noreturn__)) usage(FILE *out) + { + fputs(USAGE_HEADER, out); + fprintf(out, + _(" %s [options] \n"), program_invocation_short_name); ++ ++ fputs(USAGE_SEPARATOR, out); ++ fputs(_("Discard the content of sectors on a device.\n"), out); ++ + fputs(USAGE_OPTIONS, out); +- fputs(_(" -o, --offset offset in bytes to discard from\n" +- " -l, --length length of bytes to discard from the offset\n" +- " -p, --step size of the discard iterations within the offset\n" +- " -s, --secure perform secure discard\n" +- " -v, --verbose print aligned length and offset\n"), +- out); ++ fputs(_(" -o, --offset offset in bytes to discard from\n"), out); ++ fputs(_(" -l, --length length of bytes to discard from the offset\n"), out); ++ fputs(_(" -p, --step size of the discard iterations within the offset\n"), out); ++ fputs(_(" -s, --secure perform secure discard\n"), out); ++ fputs(_(" -z, --zeroout zero-fill rather than discard\n"), out); ++ fputs(_(" -v, --verbose print aligned length and offset\n"), out); ++ + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); ++ + fprintf(out, USAGE_MAN_TAIL("blkdiscard(8)")); + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); + } + ++ + int main(int argc, char **argv) + { + char *path; +- int c, fd, verbose = 0, secure = 0, secsize; ++ int c, fd, verbose = 0, secsize; + uint64_t end, blksize, step, range[2], stats[2]; + struct stat sb; +- struct timespec now, last; ++ struct timeval now, last; ++ int act = ACT_DISCARD; + + static const struct option longopts[] = { + { "help", 0, 0, 'h' }, +@@ -90,6 +142,7 @@ int main(int argc, char **argv) + { "step", 1, 0, 'p' }, + { "secure", 0, 0, 's' }, + { "verbose", 0, 0, 'v' }, ++ { "zeroout", 0, 0, 'z' }, + { NULL, 0, 0, 0 } + }; + +@@ -102,7 +155,7 @@ int main(int argc, char **argv) + range[1] = ULLONG_MAX; + step = 0; + +- while ((c = getopt_long(argc, argv, "hVsvo:l:p:", longopts, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "hVsvo:l:p:z", longopts, NULL)) != -1) { + switch(c) { + case 'h': + usage(stdout); +@@ -123,11 +176,14 @@ int main(int argc, char **argv) + _("failed to parse step")); + break; + case 's': +- secure = 1; ++ act = ACT_SECURE; + break; + case 'v': + verbose = 1; + break; ++ case 'z': ++ act = ACT_ZEROOUT; ++ break; + default: + usage(stderr); + break; +@@ -149,7 +205,7 @@ int main(int argc, char **argv) + err(EXIT_FAILURE, _("cannot open %s"), path); + + if (fstat(fd, &sb) == -1) +- err(EXIT_FAILURE, _("stat failed %s"), path); ++ err(EXIT_FAILURE, _("stat of %s failed"), path); + if (!S_ISBLK(sb.st_mode)) + errx(EXIT_FAILURE, _("%s: not a block device"), path); + +@@ -178,35 +234,43 @@ int main(int argc, char **argv) + "to sector size %i"), path, range[1], secsize); + + stats[0] = range[0], stats[1] = 0; +- clock_gettime(CLOCK_MONOTONIC, &last); ++ gettime_monotonic(&last); + +- for (range[0] = range[0]; range[0] < end; range[0] += range[1]) { ++ for (/* nothing */; range[0] < end; range[0] += range[1]) { + if (range[0] + range[1] > end) + range[1] = end - range[0]; + +- if (secure) { ++ switch (act) { ++ case ACT_ZEROOUT: ++ if (ioctl(fd, BLKZEROOUT, &range)) ++ err(EXIT_FAILURE, _("%s: BLKZEROOUT ioctl failed"), path); ++ break; ++ case ACT_SECURE: + if (ioctl(fd, BLKSECDISCARD, &range)) + err(EXIT_FAILURE, _("%s: BLKSECDISCARD ioctl failed"), path); +- } else { ++ break; ++ case ACT_DISCARD: + if (ioctl(fd, BLKDISCARD, &range)) + err(EXIT_FAILURE, _("%s: BLKDISCARD ioctl failed"), path); ++ break; + } + +- /* reporting progress */ ++ stats[1] += range[1]; ++ ++ /* reporting progress at most once per second */ + if (verbose && step) { +- clock_gettime(CLOCK_MONOTONIC, &now); +- if (last.tv_sec < now.tv_sec) { +- print_stats(path, stats); +- stats[0] = range[0], stats[1] = 0; ++ gettime_monotonic(&now); ++ if (now.tv_sec > last.tv_sec && ++ (now.tv_usec >= last.tv_usec || now.tv_sec > last.tv_sec + 1)) { ++ print_stats(act, path, stats); ++ stats[0] += stats[1], stats[1] = 0; + last = now; + } + } +- +- stats[1] += range[1]; + } + +- if (verbose) +- print_stats(path, stats); ++ if (verbose && stats[1]) ++ print_stats(act, path, stats); + + close(fd); + return EXIT_SUCCESS; +-- +2.7.4