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