summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Kabelac <zkabelac@redhat.com>2020-10-02 19:32:28 +0200
committerZdenek Kabelac <zkabelac@redhat.com>2020-10-02 21:04:16 +0200
commite7fff97b8dc4c0a9170bed84388f9ccf55b09169 (patch)
tree65ad08080d64609cfcd54b5735ccf71505894dd8
parentc65d3a6b8a79b7ba68f56194a12d66b9c5f41547 (diff)
downloadlvm2-e7fff97b8dc4c0a9170bed84388f9ccf55b09169.tar.gz
wipe_lv: use BLKZEROOUT when possible
Since BLKZEROOUT ioctl should be supposedly fastest way how to clear block device start using this ioctl for zeroing a device. Commonly we do zero typically small portion of a device (8KiB) - however since we now also started to zero metadata devices, in the case of i.e. thin-pool metadata this can go upto ~16GiB and here the performance starts to be noticable.
-rw-r--r--WHATS_NEW1
-rw-r--r--lib/metadata/lv_manip.c32
2 files changed, 33 insertions, 0 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 270b9d0f8..16a8baf34 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.11 -
==================================
+ Support using BLKZEROOUT for clearing devices.
Support interruption when wipping LVs.
Support interruption for bcache waiting.
Fix bcache when device has too many failing writes.
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index b72e08060..4f59900d1 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -33,6 +33,11 @@
#include "lib/label/label.h"
#include "lib/misc/lvm-signal.h"
+#ifdef HAVE_BLKZEROOUT
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#endif
+
typedef enum {
PREFERRED,
USE_AREA,
@@ -7713,6 +7718,33 @@ int wipe_lv(struct logical_volume *lv, struct wipe_params wp)
display_size(lv->vg->cmd, zero_sectors),
display_lvname(lv), wp.zero_value);
+#ifdef HAVE_BLKZEROOUT
+ if (!test_mode() && !wp.zero_value) {
+ /* TODO: maybe integrate with bcache_zero_set() */
+ const uint64_t end = zero_sectors << SECTOR_SHIFT;
+ uint64_t range[2] = { 0, 1024 * 1024 }; /* zeroing with 1M steps (for better ^C support) */
+ for (/* empty */ ; range[0] < end; range[0] += range[1]) {
+ if ((range[0] + range[1]) > end)
+ range[1] = end - range[0];
+
+ if (ioctl(dev->bcache_fd, BLKZEROOUT, &range)) {
+ if (errno == EINVAL)
+ goto retry_with_dev_set; /* Kernel without support for BLKZEROOUT */
+ log_sys_debug("ioctl", "BLKZEROOUT");
+ sigint_restore();
+ label_scan_invalidate(dev);
+ if (sigint_caught())
+ log_error("Interrupted initialization logical volume %s.",
+ display_lvname(lv));
+ else
+ log_error("Failed to initialize logical volume %s at position " FMTu64 " and size " FMTu64 ".",
+ display_lvname(lv), range[0], range[1]);
+ return 0;
+ }
+ }
+ } else
+retry_with_dev_set:
+#endif
if (!dev_set_bytes(dev, UINT64_C(0), (size_t) zero_sectors << SECTOR_SHIFT, wp.zero_value)) {
sigint_restore();
if (sigint_caught()) {