From nobody Tue Aug 25 14:34:08 2026 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13C79356754 for ; Fri, 14 Aug 2026 03:49:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786679347; cv=none; b=ePxubo8BMiSMKJMnePYUSFRE86yJyyrX2Ck7SMCY26ZMz+a6+oWinby2+czs7bFOrb5dqlOV5v6wnMuT5+GGuG336gBAehQ2nj2EC7sEJ6PS4cRnIIjyEi+NZbiRHIXVAYBwPMI3aXrUdN4ELHJLWV7LX7Pb9iM35ZkOny9Ey0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786679347; c=relaxed/simple; bh=+87YqiqJu7d9RxaLFWzXE7nZwfjSUQ27OKyRS8HpYl4=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=P+7HOgnvTn2m855sxZosOf+QsuwZ4JSqDuns0+P8ierJaRS2s+mfhvrEW3n8z2DFqaYSvuPb15KmeDy4lJeOI/9sQMHj4K/JH49y/UeAL5OeSfjfAwyIbsV6sTC+U4ySGSWdCUTYZZ70Ebkzv3PTWc/szH+RuxGdXRVIwGegVZ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=rNULR4dY; arc=none smtp.client-ip=209.85.214.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rNULR4dY" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2cfbbdfa60bso6361605ad.3 for ; Thu, 13 Aug 2026 20:49:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786679345; x=1787284145; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=qBZfZK4P3lmJ4BfMzqjxl2Q8NxSCA00MLYzImtjOXNw=; b=rNULR4dYvcKQLgcJVF9j4iRQ8rcaruzaNe9NbozNLlNEZo/1WiJx9UvPO0+gBh0eUX NJgE7cVrqWpEFYU3uiRa3lDh3OrOTyS0Hz+syRSKUs5m1ZOKIJOyYr2rGYcHKGNopeu2 ns4mk9j2w9VBWcyYOZsk42s9SFdDLmyGZ/xeYydKgjJYMK40+zIKDp2Ayy8W6oyUpFfV 2+Gvo2/TUl0+8EPXYyxDHncqccyIc5EorpFdRjwbJvY7RECDJ/bbRWI46w4smQ2W3gUI bcopZmYsJ7oT314w8XX4tfOXk5sLuUDy5JWfWymGAiD/AtWE50a/ZHYPodobpRDhAGKw xUuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786679345; x=1787284145; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=qBZfZK4P3lmJ4BfMzqjxl2Q8NxSCA00MLYzImtjOXNw=; b=FpBzRoxRdo97LI6Q0+8jKBscNVfJv0zt3WTz0WCZhpcMQO2xB2A0HNcoIO+8ZkuTW1 KoHppPvaC2N4lagsOpkC2w1g5mPgfsRkl8mAOMqE2+adIqW7n6comzyPP+H8jsUzQICR gB2csdLq21BzEsmNyd3s52y5FcuEMaEMtafcf9j6J4oCd+SUXRpWI3vCSX1ifQTo8IxF MF34nh5dXMbE3nKaNVQBzO1vRBt91qB4AprbUH9cINQOJ5TkpFiVccI5ST/GyatFybFu eCLxta72gP2slYYDe/n0oksKInPNb9EtsE6/QadfMvOnWzZrTysLRGoNEHta66Vb2GKc C37w== X-Forwarded-Encrypted: i=1; AHgh+Rpm6q2kqkKJclx/HZV0NbrGgji5qsETZShQdlWE+pdclc4BfHTK8qiEphuRC/QwZkSkixLXHlK27pDDR10=@vger.kernel.org X-Gm-Message-State: AOJu0Yw58a5gbItaDYUt8IQIccpVrsw6tjz7pUs7pNdlnUCgIzqfp155 tE+bSMRINZuQCppB7j6Fyrmyst8Tbbc4wawY8QKSJaLIc8oHncpJnFbG X-Gm-Gg: AR+sD11G2yQv80bQ5bH9NifFOQk8XrlTPForVsKqpBmAMPPkdj+hUPzBjTHH170TlRv F+0/KqA33bMfDscVe2TWaTfJEjcCgDlkJprjVpXUw+gb75lzNrTdIWGngnOG510itNc+/TTGGFb OnMED3wzpf371CGp4hkQ8qbP/UuuLN12wHII6wRGHJQjb6thM6DNWqE26oGHRDvcqQKRn52t8L4 GywkB3lrfR5S422fWq+8O8v0B/2ansTMbWIRSXZ/25V5QTKYL+gKBml9GCRSwKR/+HHALaHYAMH nLIuQ5hq/li8jLZqIBiQjpV+rk0gsDdXBYKJhbs5F3y4AQtOfGgrX1uEDSFar3lJ76djVPqxDKC PInT1YzY5NIy+zXU7Nnk4u2CyQc2cLO85jQvGd8sNjOWSwpwb+CA3pRmCo07Et8WwpKTEkfbSPA yB9ISRhKVhqyby2Y8hPCXEOFY8XgV+1skMRQeJcouuQtys6rIsekypHFiRoJpjkHDBSlLjSmGH3 sV6k/0= X-Received: by 2002:a17:90a:da8f:b0:380:21b7:e727 with SMTP id 98e67ed59e1d1-3933b95e327mr2864052a91.14.1786679345041; Thu, 13 Aug 2026 20:49:05 -0700 (PDT) Received: from n232-175-066.byted.org ([36.110.163.105]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-394ebc32b24sm641057a91.17.2026.08.13.20.49.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Aug 2026 20:49:04 -0700 (PDT) From: guzebing To: linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org Cc: tytso@mit.edu, adilger.kernel@dilger.ca, libaokun@linux.alibaba.com, jack@suse.cz, ojaswin@linux.ibm.com, ritesh.list@gmail.com, yi.zhang@huawei.com, bretznic@gmail.com, guzebing , stable@vger.kernel.org Subject: [PATCH] ext4: reject delalloc to nodelalloc before applying remount options Date: Fri, 14 Aug 2026 11:48:55 +0800 Message-Id: <20260814034855.1573759-1-guzebing1612@gmail.com> X-Mailer: git-send-email 2.20.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Commit 97f5ec3b166d ("ext4: prevent delalloc to nodelalloc on remount") rejects switching a mounted filesystem from delalloc to nodelalloc. However, it performs the check after ext4_apply_options() has already cleared EXT4_MOUNT_DELALLOC in the live superblock. The failure path eventually restores the bit, but leaves a window where other CPUs can observe nodelalloc. test_opt() reads s_mount_opt directly without a lock shared with remount. If a concurrent truncate's __es_remove_extent() hits this window and observes nodelalloc, it sets count_reserved to false. Delayed extent status entries are then removed without calculating their cluster reservations, leaving reserved at zero. ext4_es_remove_extent() therefore calls ext4_da_release_space() with zero, leaving i_reserved_data_blocks and s_dirtyclusters_counter elevated. When the inode is later evicted after unlink, ext4_destroy_inode() reports: i_reserved_data_blocks (...) not cleared! CPU 0 CPU 1 ksys_truncate() ... ext4_es_remove_extent() ext4_reconfigure() ext4_check_opt_consistency() __ext4_remount() ext4_apply_options() clear EXT4_MOUNT_DELALLOC __es_remove_extent() test_opt() sees !DELALLOC count_reserved =3D false reject delalloc -> nodelalloc restore EXT4_MOUNT_DELALLOC remove delayed ES ext4_da_release_space(0) Follow the pre-apply validation approach used by ext4_check_quota_consistency() and reject the transition in ext4_check_opt_consistency(), before ext4_apply_options() changes live state. Use mask_s_mount_opt to determine whether delalloc/nodelalloc was specified and ctx_test_mount_opt() to check the final parsed value. Fixes: 97f5ec3b166d ("ext4: prevent delalloc to nodelalloc on remount") Cc: stable@vger.kernel.org Signed-off-by: guzebing Reviewed-by: Jan Kara Reviewed-by: Ojaswin Mujoo --- This issue was first observed in a production environment. It can now be reproduced with a shell script. 1. Create a 768 MiB ext4 filesystem and mount it with delalloc. 2. Start 16 workers. Each worker repeatedly runs: xfs_io -f -c 'pwrite -q 0 32m' file-N truncate -s 262144 file-N 3. In parallel, repeatedly run "mount -o remount,nodelalloc". Every remount is expected to fail. 4. Continuously sample the live mount options with findmnt and record any transient nodelalloc state. 5. After 300 seconds, stop the workers and unmount the filesystem, then inspect dmesg for "i_reserved_data_blocks (...) not cleared!". On an affected kernel, 7 transient nodelalloc samples and 9 reservation warnings were observed during 101 rejected remounts. With this fix, no transient nodelalloc state or reservation warning was observed. fs/ext4/super.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 245f67d10ded3..9e1ea94664775 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -2816,6 +2816,14 @@ static int ext4_check_opt_consistency(struct fs_cont= ext *fc, } =20 if (is_remount) { + if (test_opt(sb, DELALLOC) && + (ctx->mask_s_mount_opt & EXT4_MOUNT_DELALLOC) && + !ctx_test_mount_opt(ctx, EXT4_MOUNT_DELALLOC)) { + ext4_msg(sb, KERN_ERR, + "can't disable delalloc during remount"); + return -EINVAL; + } + if (!sbi->s_journal && ctx_test_mount_opt(ctx, EXT4_MOUNT_DATA_ERR_ABORT)) { ext4_msg(NULL, KERN_WARNING, @@ -6660,13 +6668,6 @@ static int __ext4_remount(struct fs_context *fc, str= uct super_block *sb) goto restore_opts; } =20 - if ((old_opts.s_mount_opt & EXT4_MOUNT_DELALLOC) && - !test_opt(sb, DELALLOC)) { - ext4_msg(sb, KERN_ERR, "can't disable delalloc during remount"); - err =3D -EINVAL; - goto restore_opts; - } - sb->s_flags =3D (sb->s_flags & ~SB_POSIXACL) | (test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);