[{"id":3680637,"web_url":"http://patchwork.ozlabs.org/comment/3680637/","msgid":"<aejLp-m2-0h6q0RE@bfoster>","list_archive_url":null,"date":"2026-04-22T13:22:47","subject":"Re: [PATCH] generic/790: test post-EOF gap zeroing persistence","submitter":{"id":13037,"url":"http://patchwork.ozlabs.org/api/people/13037/","name":"Brian Foster","email":"bfoster@redhat.com"},"content":"On Wed, Apr 22, 2026 at 09:52:46AM +0800, Zhang Yi wrote:\n> From: Zhang Yi <yi.zhang@huawei.com>\n> \n> Test that extending a file past a non-block-aligned EOF correctly\n> zero-fills the gap [old_EOF, block_boundary), and that this zeroing\n> persists through a filesystem shutdown+remount cycle.\n> \n> Stale data beyond EOF can persist on disk when append write data blocks\n> are flushed before the i_size metadata update, or when concurrent append\n> writeback and mmap writes persist non-zero data past EOF. Subsequent\n> post-EOF operations (append write, fallocate, truncate up) must\n> zero-fill and persist the gap to prevent exposing stale data.\n> \n> The test pollutes the file's last physical block (via FIEMAP + raw\n> device write) with a sentinel pattern beyond i_size, then performs each\n> extend operation and verifies the gap is zeroed both in memory and on\n> disk.\n> \n> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>\n> ---\n> This is the case Jan Kara pointed out during my work on the ext4\n> buffered I/O to iomap conversion. This case is similar to generic/363,\n> but generic/363 doesn't provide persistent testing. For details:\n> \n>  https://lore.kernel.org/linux-ext4/jgotl7vzzuzm6dvz5zfgk6haodxvunb4hq556pzh4hqqwvnhxq@lr3jiedhqh7c/\n> \n>  tests/generic/790     | 155 ++++++++++++++++++++++++++++++++++++++++++\n>  tests/generic/790.out |   4 ++\n>  2 files changed, 159 insertions(+)\n>  create mode 100755 tests/generic/790\n>  create mode 100644 tests/generic/790.out\n> \n> diff --git a/tests/generic/790 b/tests/generic/790\n> new file mode 100755\n> index 00000000..5d8f61f9\n> --- /dev/null\n> +++ b/tests/generic/790\n> @@ -0,0 +1,155 @@\n> +#! /bin/bash\n> +# SPDX-License-Identifier: GPL-2.0\n> +# Copyright (c) 2026 Huawei.  All Rights Reserved.\n> +#\n> +# FS QA Test No. 790\n> +#\n> +# Test that extending a file past a non-block-aligned EOF correctly zero-fills\n> +# the gap [old_EOF, block_boundary), and that this zeroing persists through a\n> +# filesystem shutdown+remount cycle.\n> +#\n\nNice test! This is a great idea.\n\n> +# Stale data beyond EOF can persist on disk when:\n> +# 1) append write data blocks are flushed before the i_size metadata update,\n> +#    and the system crashes in this window.\n\nMaybe it's wording or I'm missing something, but how would \"append write\ndata blocks\" be flushed before i_size updates? Wouldn't writeback toss\nthem or zero the post-eof range of a folio? Do you mean to refer to\n\"on-disk size update\" specifically (where I'm reading it as\ninode->i_isize)?\n\n> +# 2) concurrent append writeback and mmap writes persist non-zero data past EOF.\n> +#\n> +# Subsequent post-EOF operations (append write, fallocate, truncate up) must\n> +# zero-fill and persist the gap to prevent exposing stale data.\n> +#\n> +# The test pollutes the file's last physical block (via FIEMAP + raw device\n> +# write) with a sentinel pattern beyond i_size, then performs each extend\n> +# operation and verifies the gap is zeroed both in memory and on disk.\n> +#\n...\n> +_test_eof_zeroing()\n> +{\n> +\tlocal test_name=\"$1\"\n> +\tlocal extend_cmd=\"$2\"\n> +\tlocal file=$SCRATCH_MNT/testfile_${test_name}\n> +\n> +\techo \"$test_name\" | tee -a $seqres.full\n> +\n> +\t# Compute non-block-aligned EOF offset\n> +\tlocal gap_bytes=16\n> +\tlocal eof_offset=$((blksz - gap_bytes))\n> +\n> +\t# Step 1: Write one full block to ensure the filesystem allocates a\n> +\t#         physical block for the file instead of using inline data.\n> +\t$XFS_IO_PROG -f -c \"pwrite -S 0x5a 0 $blksz\" -c fsync \\\n> +\t\t\"$file\" >> $seqres.full 2>&1\n> +\n> +\t# Step 2: Get physical block offset on device via FIEMAP\n> +\tlocal phys_offset\n> +\tphys_offset=$(_get_phys_offset \"$file\")\n> +\tif [ -z \"$phys_offset\" ]; then\n> +\t\t_fail \"$test_name: failed to get physical block offset via fiemap\"\n> +\tfi\n> +\n> +\t# Step 3: Truncate file to non-block-aligned size and fsync.\n> +\t#         The on-disk region [eof_offset, blksz) may or may not be\n> +\t#         zeroed by the filesystem at this point.\n> +\t$XFS_IO_PROG -c \"truncate $eof_offset\" -c fsync \\\n> +\t\t\"$file\" >> $seqres.full 2>&1\n> +\n> +\t# Step 4: Unmount and restore the physical block to all-0x5a on disk.\n> +\t#         This bypasses the kernel's pagecache EOF-zeroing to ensure\n> +\t#         the stale pattern is present on disk. Then remount.\n> +\t_scratch_unmount\n> +\t$XFS_IO_PROG -d -c \"pwrite -S 0x5a $phys_offset $blksz\" \\\n> +\t\t$SCRATCH_DEV >> $seqres.full 2>&1\n> +\t_scratch_mount >> $seqres.full 2>&1\n> +\n> +\t# Verify file size is still eof_offset after remount\n> +\tlocal sz\n> +\tsz=$(stat -c %s \"$file\")\n> +\tif [ \"$sz\" -ne \"$eof_offset\" ]; then\n> +\t\t_fail \"$test_name: file size wrong after remount: $sz != $eof_offset\"\n> +\tfi\n\nI was initially curious why we'd want to do this, but after further\nthought I wonder if it might make more sense to check file size against\nthe extended size after the shutdown/mount cycle below (but before\nchecking the gap range). That way we know the size update was\nlogged/recovered correctly and we're about to read from a file range\nwithin eof. Hm?\n\nThose couple nits aside this all looks pretty good to me.\n\nBrian\n\n> +\n> +\t# Step 5: Execute the extend operation.\n> +\t$XFS_IO_PROG -c \"$extend_cmd\" \"$file\" >> $seqres.full 2>&1\n> +\n> +\t# Step 6: Verify gap [eof_offset, blksz) is zeroed BEFORE shutdown\n> +\t_check_gap_zero \"$file\" $eof_offset $gap_bytes \"before shutdown\" || return 1\n> +\n> +\t# Step 7: Sync the extended range and shutdown the filesystem with\n> +\t#         journal flush. This persists the file size extending, and\n> +\t#         the filesystem should persist the zeroed data in the gap\n> +\t#         range as well.\n> +\tif [ \"$extend_cmd\" != \"${extend_cmd#pwrite}\" ]; then\n> +\t\t$XFS_IO_PROG -c \"sync_range -w $blksz $blksz\" \\\n> +\t\t\t\"$file\" >> $seqres.full 2>&1\n> +\tfi\n> +\t_scratch_shutdown -f\n> +\n> +\t# Step 8: Remount and verify gap is still zeroed\n> +\t_scratch_cycle_mount\n> +\t_check_gap_zero \"$file\" $eof_offset $gap_bytes \"after shutdown+remount\" || return 1\n> +}\n> +\n> +_scratch_mkfs >> $seqres.full 2>&1\n> +_scratch_mount\n> +\n> +blksz=$(_get_block_size $SCRATCH_MNT)\n> +\n> +# Test three variants of EOF-extending operations\n> +_test_eof_zeroing \"append_write\" \"pwrite -S 0x42 $blksz $blksz\"\n> +_test_eof_zeroing \"truncate_up\" \"truncate $((blksz * 2))\"\n> +_test_eof_zeroing \"fallocate\" \"falloc $blksz $blksz\"\n> +\n> +# success, all done\n> +status=0\n> +exit\n> diff --git a/tests/generic/790.out b/tests/generic/790.out\n> new file mode 100644\n> index 00000000..e5e2cc09\n> --- /dev/null\n> +++ b/tests/generic/790.out\n> @@ -0,0 +1,4 @@\n> +QA output created by 790\n> +append_write\n> +truncate_up\n> +fallocate\n> -- \n> 2.52.0\n> \n>","headers":{"Return-Path":"\n <SRS0=y749=CV=vger.kernel.org=linux-ext4+bounces-15996-patchwork-incoming=ozlabs.org@ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-ext4@vger.kernel.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","patchwork-incoming@ozlabs.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=HgkX+nbB;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org\n (client-ip=2404:9400:2221:ea00::3; helo=mail.ozlabs.org;\n envelope-from=srs0=y749=cv=vger.kernel.org=linux-ext4+bounces-15996-patchwork-incoming=ozlabs.org@ozlabs.org;\n receiver=patchwork.ozlabs.org)","gandalf.ozlabs.org;\n arc=pass smtp.remote-ip=172.105.105.114 arc.chain=subspace.kernel.org","gandalf.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com","gandalf.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=HgkX+nbB;\n\tdkim-atps=neutral","gandalf.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.105.105.114; helo=tor.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15996-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.b=\"HgkX+nbB\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=170.10.133.124","smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=redhat.com"],"Received":["from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1 raw public key)\n server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g10Yy4Hg9z1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 23:34:13 +1000 (AEST)","from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\tby gandalf.ozlabs.org (Postfix) with ESMTP id 4g10Yr1Q3Kz4w02\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 23:34:08 +1000 (AEST)","by gandalf.ozlabs.org (Postfix)\n\tid 4g10Yr163nz4wD3; Wed, 22 Apr 2026 23:34:08 +1000 (AEST)","from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby gandalf.ozlabs.org (Postfix) with ESMTPS id 4g10Yl1ZTTz4w02\n\tfor <patchwork-incoming@ozlabs.org>; Wed, 22 Apr 2026 23:34:03 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 1EF2D30E7E8A\n\tfor <patchwork-incoming@ozlabs.org>; Wed, 22 Apr 2026 13:23:55 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 1C07E3EBF3A;\n\tWed, 22 Apr 2026 13:23:00 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 518EC3CEB85\n\tfor <linux-ext4@vger.kernel.org>; Wed, 22 Apr 2026 13:22:58 +0000 (UTC)","from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-34-Uhp1U9AIMkOWiK6O9CQbFg-1; Wed,\n 22 Apr 2026 09:22:54 -0400","from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 80B6B1955F18;\n\tWed, 22 Apr 2026 13:22:51 +0000 (UTC)","from bfoster (unknown [10.22.88.73])\n\tby mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with\n ESMTPS id E8C0F19560AB;\n\tWed, 22 Apr 2026 13:22:49 +0000 (UTC)"],"ARC-Seal":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707; t=1776864848; cv=pass;\n\tb=fDlc89CN8srah54jBlR7D1dSfRPUOc/1RiqnMH7uYIEoyNEzBPUaBNxaG0yxp07NF7nOsnY165zhkg9v1dokxBNKuKGkEICoLFKFXrqIyWw8+VlLt5qEOogWdPL9XVdjsHVpRom8cPxn8zqFSAgiY/1zXS9pqOLNx0l/OCDSvnPeCX2qN0R9AKkw+OHMTs0BP+W2kJHK1skiEnyrq/G9Dj3Aj9obvLL94Yjl25dDvmn2VPETzAAaiy4QPVITXHX7hdOZ6WJDmE2rf6QcrgXm7J7ISFhtLjf+gR7buJlwhsT7yqOOZA1WtLlDpKh0DpLS1g3v/3zr0bPjS5XUsmfwPQ==","i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776864179; cv=none;\n b=S6ayVfESNw4dzG1gcV/BMqRdgWLAEe8JCD/Dzb1No8bUaoJIYhl1WSglc6Ota3QHpAQtLiExz5JvbC2hNUm18h6BHWzkB9PMT8sh3y/x83+FXYeV4v95Co94qT/ZaA+ZOKNCfFDStPkjhwRIv5hBJHJ/RQ9vrvD8wBYEk7mC55I="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707;\n\tt=1776864848; c=relaxed/relaxed;\n\tbh=99lpaYvrEMn1O3IXIzKhH6DKTKViuZzIem8oOh6SGRU=;\n\th=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version:\n\t Content-Type:Content-Disposition:In-Reply-To;\n b=TITiaA16UZ3njzIKE+pMr2FxqHOnluYoHkoLbVvtlLw3KjcknISVqG1SZjcQSlEoa3ES+LISfZI5Y/+BwHU0zVtAJ4EahqVOKQwoiX4Yhg40Re0mGBG6bFYeVl9XJDQb5U7Bgr2Qhj0+sU2EX2iE0iHIuSlGvL3g6/EZvrWVGh+egdq3toFnHU8521DsZSW0NdMvGiSKJh8pnE4dbQJgCDuRyNpqSwe0xze25gmdZsbOrI1xc3Y8jo8EQe60vvs63doBJ6vD5oPkxwu6AVxbyICsunVG2QRaoO+gpD33HmopYezmF8+OHkJ0g1hguOxZoG8D/evG+rkr0zwNWc7JjA==","i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776864179; c=relaxed/simple;\n\tbh=sTbTl1ZyqHMDwGo0rU8YM51F5iFis9FwO8WjmorfwmI=;\n\th=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version:\n\t Content-Type:Content-Disposition:In-Reply-To;\n b=WOcd6LVnTk7EFrxCvhRBTrs0E92M+bcdYhrzx4RTcBZVTplCiHHN+KWSpGBjd8HTMuMaXhIL2JpEOMvHyPy9pXn0Zzm8yaPDcNsMFMbpcsP99LGhE6//GJzjIPFvHXBlwT0x9GUf1qrUvDgZhpvzs9ycSa662bczlrywsZX2PoE="],"ARC-Authentication-Results":["i=2; gandalf.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com;\n dkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=HgkX+nbB; dkim-atps=neutral;\n spf=pass (client-ip=172.105.105.114; helo=tor.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15996-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org) smtp.mailfrom=vger.kernel.org","i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=quarantine dis=none) header.from=redhat.com;\n spf=pass smtp.mailfrom=redhat.com;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.b=HgkX+nbB; arc=none smtp.client-ip=170.10.133.124"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1776864177;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\t to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\t in-reply-to:in-reply-to:references:references;\n\tbh=99lpaYvrEMn1O3IXIzKhH6DKTKViuZzIem8oOh6SGRU=;\n\tb=HgkX+nbBxrGR9plNkB2wFUiVUTuzu7zujClxyesAAgTzNJUBQK/TnVnAy3Pd6dcedJ8+O0\n\tMyEvP4FSiOHQmOnqDejR19syUBF/I7sCoNhGu0S91e0dd0/hXrQjkoTrWA/Z2ld+pU7b2z\n\tYTNxqN7mnAXUmRqSoaRG509kV5wxdQw=","X-MC-Unique":"Uhp1U9AIMkOWiK6O9CQbFg-1","X-Mimecast-MFC-AGG-ID":"Uhp1U9AIMkOWiK6O9CQbFg_1776864172","Date":"Wed, 22 Apr 2026 09:22:47 -0400","From":"Brian Foster <bfoster@redhat.com>","To":"Zhang Yi <yi.zhang@huaweicloud.com>","Cc":"fstests@vger.kernel.org, zlang@kernel.org, linux-ext4@vger.kernel.org,\n\tlinux-fsdevel@vger.kernel.org, jack@suse.cz, yi.zhang@huawei.com,\n\tyizhang089@gmail.com, yangerkun@huawei.com","Subject":"Re: [PATCH] generic/790: test post-EOF gap zeroing persistence","Message-ID":"<aejLp-m2-0h6q0RE@bfoster>","References":"<20260422015246.4132376-1-yi.zhang@huaweicloud.com>","Precedence":"bulk","X-Mailing-List":"linux-ext4@vger.kernel.org","List-Id":"<linux-ext4.vger.kernel.org>","List-Subscribe":"<mailto:linux-ext4+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-ext4+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20260422015246.4132376-1-yi.zhang@huaweicloud.com>","X-Scanned-By":"MIMEDefang 3.0 on 10.30.177.17","X-Spam-Status":"No, score=-1.2 required=5.0 tests=ARC_SIGNED,ARC_VALID,\n\tDKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DMARC_PASS,\n\tHEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE,\n\tSPF_PASS autolearn=disabled version=4.0.1","X-Spam-Checker-Version":"SpamAssassin 4.0.1 (2024-03-25) on gandalf.ozlabs.org"}},{"id":3681229,"web_url":"http://patchwork.ozlabs.org/comment/3681229/","msgid":"<4c3abdbc-0805-4e19-98b9-5a5e06b5db40@huaweicloud.com>","list_archive_url":null,"date":"2026-04-23T01:41:26","subject":"Re: [PATCH] generic/790: test post-EOF gap zeroing persistence","submitter":{"id":85428,"url":"http://patchwork.ozlabs.org/api/people/85428/","name":"Zhang Yi","email":"yi.zhang@huaweicloud.com"},"content":"On 4/22/2026 9:22 PM, Brian Foster wrote:\n> On Wed, Apr 22, 2026 at 09:52:46AM +0800, Zhang Yi wrote:\n>> From: Zhang Yi <yi.zhang@huawei.com>\n>>\n>> Test that extending a file past a non-block-aligned EOF correctly\n>> zero-fills the gap [old_EOF, block_boundary), and that this zeroing\n>> persists through a filesystem shutdown+remount cycle.\n>>\n>> Stale data beyond EOF can persist on disk when append write data blocks\n>> are flushed before the i_size metadata update, or when concurrent append\n>> writeback and mmap writes persist non-zero data past EOF. Subsequent\n>> post-EOF operations (append write, fallocate, truncate up) must\n>> zero-fill and persist the gap to prevent exposing stale data.\n>>\n>> The test pollutes the file's last physical block (via FIEMAP + raw\n>> device write) with a sentinel pattern beyond i_size, then performs each\n>> extend operation and verifies the gap is zeroed both in memory and on\n>> disk.\n>>\n>> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>\n>> ---\n>> This is the case Jan Kara pointed out during my work on the ext4\n>> buffered I/O to iomap conversion. This case is similar to generic/363,\n>> but generic/363 doesn't provide persistent testing. For details:\n>>\n>>  https://lore.kernel.org/linux-ext4/jgotl7vzzuzm6dvz5zfgk6haodxvunb4hq556pzh4hqqwvnhxq@lr3jiedhqh7c/\n>>\n>>  tests/generic/790     | 155 ++++++++++++++++++++++++++++++++++++++++++\n>>  tests/generic/790.out |   4 ++\n>>  2 files changed, 159 insertions(+)\n>>  create mode 100755 tests/generic/790\n>>  create mode 100644 tests/generic/790.out\n>>\n>> diff --git a/tests/generic/790 b/tests/generic/790\n>> new file mode 100755\n>> index 00000000..5d8f61f9\n>> --- /dev/null\n>> +++ b/tests/generic/790\n>> @@ -0,0 +1,155 @@\n>> +#! /bin/bash\n>> +# SPDX-License-Identifier: GPL-2.0\n>> +# Copyright (c) 2026 Huawei.  All Rights Reserved.\n>> +#\n>> +# FS QA Test No. 790\n>> +#\n>> +# Test that extending a file past a non-block-aligned EOF correctly zero-fills\n>> +# the gap [old_EOF, block_boundary), and that this zeroing persists through a\n>> +# filesystem shutdown+remount cycle.\n>> +#\n> \n> Nice test! This is a great idea.\n> \n>> +# Stale data beyond EOF can persist on disk when:\n>> +# 1) append write data blocks are flushed before the i_size metadata update,\n>> +#    and the system crashes in this window.\n> \n> Maybe it's wording or I'm missing something, but how would \"append write\n> data blocks\" be flushed before i_size updates? Wouldn't writeback toss\n> them or zero the post-eof range of a folio? Do you mean to refer to\n> \"on-disk size update\" specifically (where I'm reading it as\n> inode->i_isize)?\n\nIt's wording, I mean the \"on-disk file size update\", sorry for confusing.\n\n> \n>> +# 2) concurrent append writeback and mmap writes persist non-zero data past EOF.\n>> +#\n>> +# Subsequent post-EOF operations (append write, fallocate, truncate up) must\n>> +# zero-fill and persist the gap to prevent exposing stale data.\n>> +#\n>> +# The test pollutes the file's last physical block (via FIEMAP + raw device\n>> +# write) with a sentinel pattern beyond i_size, then performs each extend\n>> +# operation and verifies the gap is zeroed both in memory and on disk.\n>> +#\n> ...\n>> +_test_eof_zeroing()\n>> +{\n>> +\tlocal test_name=\"$1\"\n>> +\tlocal extend_cmd=\"$2\"\n>> +\tlocal file=$SCRATCH_MNT/testfile_${test_name}\n>> +\n>> +\techo \"$test_name\" | tee -a $seqres.full\n>> +\n>> +\t# Compute non-block-aligned EOF offset\n>> +\tlocal gap_bytes=16\n>> +\tlocal eof_offset=$((blksz - gap_bytes))\n>> +\n>> +\t# Step 1: Write one full block to ensure the filesystem allocates a\n>> +\t#         physical block for the file instead of using inline data.\n>> +\t$XFS_IO_PROG -f -c \"pwrite -S 0x5a 0 $blksz\" -c fsync \\\n>> +\t\t\"$file\" >> $seqres.full 2>&1\n>> +\n>> +\t# Step 2: Get physical block offset on device via FIEMAP\n>> +\tlocal phys_offset\n>> +\tphys_offset=$(_get_phys_offset \"$file\")\n>> +\tif [ -z \"$phys_offset\" ]; then\n>> +\t\t_fail \"$test_name: failed to get physical block offset via fiemap\"\n>> +\tfi\n>> +\n>> +\t# Step 3: Truncate file to non-block-aligned size and fsync.\n>> +\t#         The on-disk region [eof_offset, blksz) may or may not be\n>> +\t#         zeroed by the filesystem at this point.\n>> +\t$XFS_IO_PROG -c \"truncate $eof_offset\" -c fsync \\\n>> +\t\t\"$file\" >> $seqres.full 2>&1\n>> +\n>> +\t# Step 4: Unmount and restore the physical block to all-0x5a on disk.\n>> +\t#         This bypasses the kernel's pagecache EOF-zeroing to ensure\n>> +\t#         the stale pattern is present on disk. Then remount.\n>> +\t_scratch_unmount\n>> +\t$XFS_IO_PROG -d -c \"pwrite -S 0x5a $phys_offset $blksz\" \\\n>> +\t\t$SCRATCH_DEV >> $seqres.full 2>&1\n>> +\t_scratch_mount >> $seqres.full 2>&1\n>> +\n>> +\t# Verify file size is still eof_offset after remount\n>> +\tlocal sz\n>> +\tsz=$(stat -c %s \"$file\")\n>> +\tif [ \"$sz\" -ne \"$eof_offset\" ]; then\n>> +\t\t_fail \"$test_name: file size wrong after remount: $sz != $eof_offset\"\n>> +\tfi\n> \n> I was initially curious why we'd want to do this, but after further\n> thought I wonder if it might make more sense to check file size against\n> the extended size after the shutdown/mount cycle below (but before\n> checking the gap range). That way we know the size update was\n> logged/recovered correctly and we're about to read from a file range\n> within eof. Hm?\n\nYeah, this check should be more necessary after the shutdown/mount\ncycle.\n\n> \n> Those couple nits aside this all looks pretty good to me.\n\nThank you for the review.\n\nBest Regards,\nYi.\n\n> \n> Brian\n> \n>> +\n>> +\t# Step 5: Execute the extend operation.\n>> +\t$XFS_IO_PROG -c \"$extend_cmd\" \"$file\" >> $seqres.full 2>&1\n>> +\n>> +\t# Step 6: Verify gap [eof_offset, blksz) is zeroed BEFORE shutdown\n>> +\t_check_gap_zero \"$file\" $eof_offset $gap_bytes \"before shutdown\" || return 1\n>> +\n>> +\t# Step 7: Sync the extended range and shutdown the filesystem with\n>> +\t#         journal flush. This persists the file size extending, and\n>> +\t#         the filesystem should persist the zeroed data in the gap\n>> +\t#         range as well.\n>> +\tif [ \"$extend_cmd\" != \"${extend_cmd#pwrite}\" ]; then\n>> +\t\t$XFS_IO_PROG -c \"sync_range -w $blksz $blksz\" \\\n>> +\t\t\t\"$file\" >> $seqres.full 2>&1\n>> +\tfi\n>> +\t_scratch_shutdown -f\n>> +\n>> +\t# Step 8: Remount and verify gap is still zeroed\n>> +\t_scratch_cycle_mount\n>> +\t_check_gap_zero \"$file\" $eof_offset $gap_bytes \"after shutdown+remount\" || return 1\n>> +}\n>> +\n>> +_scratch_mkfs >> $seqres.full 2>&1\n>> +_scratch_mount\n>> +\n>> +blksz=$(_get_block_size $SCRATCH_MNT)\n>> +\n>> +# Test three variants of EOF-extending operations\n>> +_test_eof_zeroing \"append_write\" \"pwrite -S 0x42 $blksz $blksz\"\n>> +_test_eof_zeroing \"truncate_up\" \"truncate $((blksz * 2))\"\n>> +_test_eof_zeroing \"fallocate\" \"falloc $blksz $blksz\"\n>> +\n>> +# success, all done\n>> +status=0\n>> +exit\n>> diff --git a/tests/generic/790.out b/tests/generic/790.out\n>> new file mode 100644\n>> index 00000000..e5e2cc09\n>> --- /dev/null\n>> +++ b/tests/generic/790.out\n>> @@ -0,0 +1,4 @@\n>> +QA output created by 790\n>> +append_write\n>> +truncate_up\n>> +fallocate\n>> -- \n>> 2.52.0\n>>\n>>","headers":{"Return-Path":"\n <SRS0=jonZ=CW=vger.kernel.org=linux-ext4+bounces-16041-patchwork-incoming=ozlabs.org@ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-ext4@vger.kernel.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","patchwork-incoming@ozlabs.org"],"Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org\n (client-ip=2404:9400:2221:ea00::3; helo=mail.ozlabs.org;\n envelope-from=srs0=jonz=cw=vger.kernel.org=linux-ext4+bounces-16041-patchwork-incoming=ozlabs.org@ozlabs.org;\n receiver=patchwork.ozlabs.org)","gandalf.ozlabs.org;\n arc=pass smtp.remote-ip=\"2600:3c0a:e001:db::12fc:5321\"\n arc.chain=subspace.kernel.org","gandalf.ozlabs.org;\n dmarc=none (p=none dis=none) header.from=huaweicloud.com","gandalf.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-ext4+bounces-16041-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org)","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=45.249.212.51","smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=huaweicloud.com","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=huaweicloud.com"],"Received":["from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g1Jk125Kvz1yDD\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 11:42:16 +1000 (AEST)","from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\tby gandalf.ozlabs.org (Postfix) with ESMTP id 4g1Jk01gLjz4wKC\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 23 Apr 2026 11:42:16 +1000 (AEST)","by gandalf.ozlabs.org (Postfix)\n\tid 4g1Jk01DRQz4wKr; Thu, 23 Apr 2026 11:42:16 +1000 (AEST)","from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby gandalf.ozlabs.org (Postfix) with ESMTPS id 4g1Jjv4db0z4wKC\n\tfor <patchwork-incoming@ozlabs.org>; Thu, 23 Apr 2026 11:42:11 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 74C24303FA97\n\tfor <patchwork-incoming@ozlabs.org>; Thu, 23 Apr 2026 01:41:54 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id CA1BD3B52EF;\n\tThu, 23 Apr 2026 01:41:53 +0000 (UTC)","from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com\n [45.249.212.51])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id C7CF93B3C1C;\n\tThu, 23 Apr 2026 01:41:36 +0000 (UTC)","from mail.maildlp.com (unknown [172.19.163.177])\n\tby dggsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4g1Jgz67D9zYQtLc;\n\tThu, 23 Apr 2026 09:40:31 +0800 (CST)","from mail02.huawei.com (unknown [10.116.40.252])\n\tby mail.maildlp.com (Postfix) with ESMTP id B02A94058C;\n\tThu, 23 Apr 2026 09:41:30 +0800 (CST)","from [10.174.178.253] (unknown [10.174.178.253])\n\tby APP3 (Coremail) with SMTP id _Ch0CgBXBb_HeOlpUG6JBQ--.26218S3;\n\tThu, 23 Apr 2026 09:41:28 +0800 (CST)"],"ARC-Seal":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707; t=1776908536; cv=pass;\n\tb=QO0AX3eJ5dKYqfWksnkec2rABwSR/oVpoGwxfjImcRhjEhX7gNEiRNqyOJDNgs+/2Ym30Zu4Q85kEGgZgMQ3/Xeexu6mr0JMt/gsGFNy7zCSjsuwKM0ZOQ+zzs1KMB3McMy0soj4UuwWk9/IVlAM9MsFaTGsXJ1hYxPOMPV9NHP5z4pXAz2sgz+TYQ3Y8WFfylAuZnc6QToNFhN8bi1DDQ7WiAgZHsjBQuV4acWy3SqTV9saG5gdrBwMi7zE7BJY0G+28gLk6Ab50nrrQuDvX1t7PHxlxm8Er/khCBMGEdTXSHGZ+F5J0aAiB+QzD0Hz8gYKBVSNCm6ZxYwJAgpNSw==","i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776908509; cv=none;\n b=bHBbH0/tCrHsgzxpb2bC5UQ9A7O/9/HcHM1aWLfsEDGXz/pSIdZbklGYObpOPDB0lLq2r76nG2lkBcqSOZMeEbhAnxMyR0buvmuQYEGMd08kDFctwhJyfp3hXi8F2VfNSS9bO0BeRZ9GQmXePkj4UhM+48g+CNiHLC6X6MO8Nzk="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707;\n\tt=1776908536; c=relaxed/relaxed;\n\tbh=eHBsvWuKG4VahYvymBCQKE4c9A9omVi9zpyQ/XKw4M0=;\n\th=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From:\n\t In-Reply-To:Content-Type;\n b=Izv5IG6diE51rQEZN0rsutj6khswrAePdulVdi90H6kINR2+AW4fIJe4+yysa56iAwVKhNnUDOkw5EChHzdzgcVC+/x+8xQlM0h5Gt2pCeXFm/oFM/ZVmxGPnl5JaT46+JWIBteDK4JZX+tT0RVYrK0B/5wAgEROOZtO2OEWb4CY6Yk+/vCjkVFxJSwsUJ92Vj/MRJoPmkdbuQ/a89T0HIT1JhPrP9U9b+F38eUfCndJ7ELbQCdyOcYA6xOiYh2Y5YKYTcel4pe5IrEhoARX9CuysRFKYgi8fefhBNKUhZ2L/7nzIPAPJjW1E8NXZJZ3+plk4+FazvXZl+RCO8g3ow==","i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776908509; c=relaxed/simple;\n\tbh=i2d3ewWl750sGmnliN4gogPVayZVkHMiLtF3AynF5Ag=;\n\th=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From:\n\t In-Reply-To:Content-Type;\n b=K/HKkbwcWIFDN0cMjfG5l1vDFfAXGvFqi4M1YoOHM7seif/4hXOFwBzT9yMH4nrXMctgd3GCAohAfcmTGUjh4uebdoJT5EVBvpRzaQmTmHiLHY2t+3QkqWSlhXEwg3hk/WByLZcIU0pNWNq+wq8PX9hVZ0WP60QKOP2TJvdASPk="],"ARC-Authentication-Results":["i=2; gandalf.ozlabs.org;\n dmarc=none (p=none dis=none) header.from=huaweicloud.com;\n spf=pass (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-ext4+bounces-16041-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org) smtp.mailfrom=vger.kernel.org","i=1; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=huaweicloud.com;\n spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51"],"Message-ID":"<4c3abdbc-0805-4e19-98b9-5a5e06b5db40@huaweicloud.com>","Date":"Thu, 23 Apr 2026 09:41:26 +0800","Precedence":"bulk","X-Mailing-List":"linux-ext4@vger.kernel.org","List-Id":"<linux-ext4.vger.kernel.org>","List-Subscribe":"<mailto:linux-ext4+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-ext4+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] generic/790: test post-EOF gap zeroing persistence","To":"Brian Foster <bfoster@redhat.com>","Cc":"fstests@vger.kernel.org, zlang@kernel.org, linux-ext4@vger.kernel.org,\n linux-fsdevel@vger.kernel.org, jack@suse.cz, yi.zhang@huawei.com,\n yizhang089@gmail.com, yangerkun@huawei.com","References":"<20260422015246.4132376-1-yi.zhang@huaweicloud.com>\n <aejLp-m2-0h6q0RE@bfoster>","Content-Language":"en-US","From":"Zhang Yi <yi.zhang@huaweicloud.com>","In-Reply-To":"<aejLp-m2-0h6q0RE@bfoster>","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"7bit","X-CM-TRANSID":"_Ch0CgBXBb_HeOlpUG6JBQ--.26218S3","X-Coremail-Antispam":"1UD129KBjvJXoW3Xw1rZryDuFyxAr18tF43Jrb_yoWxuF1kpa\n\tyrKF1Yyr1xKF47J3s29Fn0qr1F9w4rZr4Uur92qryjvr98Jr1IqFZFqr4jg3yxJrn3Cw4I\n\tvr4kGa43uw1jyaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2\n\t9KBjDU0xBIdaVrnRJUUUylb4IE77IF4wAFF20E14v26r4j6ryUM7CY07I20VC2zVCF04k2\n\t6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rwA2F7IY1VAKz4\n\tvEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_tr0E3s1l84ACjcxK6xIIjxv20xvEc7Cj\n\txVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x\n\t0267AKxVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG\n\t6I80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFV\n\tCjc4AY6r1j6r4UM4x0Y48IcVAKI48JMxkF7I0En4kS14v26r1q6r43MxAIw28IcxkI7VAK\n\tI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7\n\txvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8ZwCIc40Y0x0EwIxGrwCI42IY6xII\n\tjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAIw2\n\t0EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x02\n\t67AKxVWUJVW8JbIYCTnIWIevJa73UjIFyTuYvjxUF1v3UUUUU","X-CM-SenderInfo":"d1lo6xhdqjqx5xdzvxpfor3voofrz/","X-Spam-Status":"No, score=-1.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,\n\tDMARC_MISSING,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,\n\tSPF_HELO_NONE,SPF_PASS autolearn=disabled version=4.0.1","X-Spam-Checker-Version":"SpamAssassin 4.0.1 (2024-03-25) on gandalf.ozlabs.org"}}]