[PATCH 3/3] logwrites: only use BLKDISCARD if we know discard zeroes data

Darrick J. Wong
2025-01-16T23:31:57Z

Building off the checks established in the previous patch, only enable
the use of BLKDISCARD if we know that the logwrites device guarantees
that reads after a discard return zeroes.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
common/dmlogwrites | 10 ++++++++--
src/log-writes/replay-log.c | 8 ++++++++
2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/common/dmlogwrites b/common/dmlogwrites
index 96101d53c38b4a..fbc8beb5ce597e 100644
--- a/common/dmlogwrites
+++ b/common/dmlogwrites
@@ -81,7 +81,10 @@ _log_writes_check_bdev()
test "$(cat "$sysfs/queue/discard_max_bytes")" -eq 0 && return

# dm-thinp guarantees that reads after discards return zeroes
- dmsetup status "$blkdev" 2>/dev/null | grep -q '^0.* thin ' && return
+ if dmsetup status "$blkdev" 2>/dev/null | grep -q '^0.* thin '; then
+ LOGWRITES_REPLAY_ARGS+=(--discard-zeroes-data)
+ return
+ fi

echo "HINT: $blkdev doesn't guarantee that reads after DISCARD will return zeroes" >> $seqres.hints
echo " This is required for correct journal replay on some filesystems (e.g. xfs)" >> $seqres.hints
@@ -110,6 +113,7 @@ _log_writes_init()
BLK_DEV_SIZE=$((length / blksz))
fi

+ LOGWRITES_REPLAY_ARGS=()
LOGWRITES_NAME=logwrites-test
LOGWRITES_DMDEV=/dev/mapper/$LOGWRITES_NAME
LOGWRITES_TABLE="0 $BLK_DEV_SIZE log-writes $blkdev $LOGWRITES_DEV"
@@ -161,7 +165,8 @@ _log_writes_replay_log()
[ $? -ne 0 ] && _fail "mark '$_mark' does not exist"

$here/src/log-writes/replay-log --log $LOGWRITES_DEV --replay $_blkdev \
- --end-mark $_mark >> $seqres.full 2>&1
+ --end-mark $_mark "${LOGWRITES_REPLAY_ARGS[@]}" \
+ >> $seqres.full 2>&1
[ $? -ne 0 ] && _fail "replay failed"
}

@@ -231,6 +236,7 @@ _log_writes_replay_log_range()
echo "=== replay to $end ===" >> $seqres.full
$here/src/log-writes/replay-log -vv --log $LOGWRITES_DEV \
--replay $blkdev --limit $(($end + 1)) \
+ "${LOGWRITES_REPLAY_ARGS[@]}" \
>> $seqres.full 2>&1
[ $? -ne 0 ] && _fail "replay failed"
}
diff --git a/src/log-writes/replay-log.c b/src/log-writes/replay-log.c
index 968c82ab64a9ad..e07401f63af573 100644
--- a/src/log-writes/replay-log.c
+++ b/src/log-writes/replay-log.c
@@ -18,6 +18,7 @@ enum option_indexes {
FIND,
NUM_ENTRIES,
NO_DISCARD,
+ DISCARD_ZEROES_DATA,
FSCK,
CHECK,
START_MARK,
@@ -37,6 +38,7 @@ static struct option long_options[] = {
{"find", no_argument, NULL, 0},
{"num-entries", no_argument, NULL, 0},
{"no-discard", no_argument, NULL, 0},
+ {"discard-zeroes-data", no_argument, NULL, 0},
{"fsck", required_argument, NULL, 0},
{"check", required_argument, NULL, 0},
{"start-mark", required_argument, NULL, 0},
@@ -155,6 +157,7 @@ int main(int argc, char **argv)
int ret;
int print_num_entries = 0;
int discard = 1;
+ int use_kernel_discard = 0;
enum log_replay_check_mode check_mode = 0;

while ((c = getopt_long(argc, argv, "v", long_options,
@@ -242,6 +245,9 @@ int main(int argc, char **argv)
case NO_DISCARD:
discard = 0;
break;
+ case DISCARD_ZEROES_DATA:
+ use_kernel_discard = 1;
+ break;
case FSCK:
fsck_command = strdup(optarg);
if (!fsck_command) {
@@ -299,6 +305,8 @@ int main(int argc, char **argv)

if (!discard)
log->flags |= LOG_IGNORE_DISCARD;
+ if (!use_kernel_discard)
+ log->flags |= LOG_DISCARD_NOT_SUPP;

log->start_sector = start_sector;
log->end_sector = end_sector;