From nobody Tue Jun 30 13:04:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E102C433EF for ; Mon, 17 Jan 2022 09:37:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235920AbiAQJh0 (ORCPT ); Mon, 17 Jan 2022 04:37:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235703AbiAQJhX (ORCPT ); Mon, 17 Jan 2022 04:37:23 -0500 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4560EC06161C for ; Mon, 17 Jan 2022 01:37:23 -0800 (PST) Received: by mail-pl1-x635.google.com with SMTP id n11so18688110plf.4 for ; Mon, 17 Jan 2022 01:37:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/oislcibWwGVzrAINuQT2hU5CHo3zB1lWarxdo9wT0s=; b=b5th21Et7tFT+ClwOpqMu4Agy7U/yZLD/T0yUxrn3ZU25o1V63BHFHjJoO/nT3H1Z8 XzmzAjp9LL0K13QW1vEOVTFeVRDLOimJKhj9RVhnNERvt9e7NdGNiGB1+9ZZsPXYOneB z9eGr1CnEPwDD55nsCQAPRsmoKY7SMEBUK3e5MvHj2lSPp2/IVNFvpark3FhtG2TdCC/ wH948Ln6gqCKKj0ZPMHzKNmPQiWhTsePHdHu5pvTjpEZ51ZPXuogi3DV90VmYcQY3PKy OGi+fCD1I81+9HMsCwTsjxI7Td6xNCr5te5apIJufJ4zAVeEZI8Hf5TZUjsMfVp5OV8X m8iA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/oislcibWwGVzrAINuQT2hU5CHo3zB1lWarxdo9wT0s=; b=b152yJtYbY1tQUyQcnuSA5khNAZ+pRHhO+ALGYqzM8mnOln3GKuG08PJ8U+NOp3qTO Ez+ABRbKw7bHf5Zrl5LKCTvD48CQ8H2F2uWzwt94SXpSOTkSDRfIYfsPUthi37gWM+Yb EZHoUV+nKAhMoFchAal4hAxBbL/v4H1nL0D5fIOS60X41FIep7TykQJNAy6BiCd3tcN5 45gBxGaUOD0bSEEoppHvupWd6QLkDSLsd3W9VY08u/5jKKyvsv6FPYKO1xc1B9tWJ5GC jzcwhlswJaYCScqceO9grm+s+eVYwjEM2o1Fc3MWwg5UUCSRcVIwD1h3h+PT9rEKLFuv hzWg== X-Gm-Message-State: AOAM532Z2VA3f2BDCcLsv7G1CsWlPVSvQLgu9R4fUtvuXike3bPlfFYM CGgK4kwEWRjwoBmu8b0dScXWHQ== X-Google-Smtp-Source: ABdhPJy2118DgqrUVisbC9X3bUyHa46chPOgaUGN9puXtVVUtKi1iq5xcfl4PEg5ElO5oJKpmwPmNg== X-Received: by 2002:a17:902:9682:b0:149:15d2:55ae with SMTP id n2-20020a170902968200b0014915d255aemr21215753plp.59.1642412242730; Mon, 17 Jan 2022 01:37:22 -0800 (PST) Received: from yinxin.bytedance.net ([139.177.225.228]) by smtp.gmail.com with ESMTPSA id z16sm11426497pgi.89.2022.01.17.01.37.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Jan 2022 01:37:22 -0800 (PST) From: Xin Yin To: harshadshirwadkar@gmail.com, tytso@mit.edu, adilger.kernel@dilger.ca Cc: dan.carpenter@oracle.com, riteshh@linux.ibm.com, linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org, Xin Yin , kernel test robot Subject: [PATCH v3 1/2] ext4: fast commit may not fallback for ineligible commit Date: Mon, 17 Jan 2022 17:36:54 +0800 Message-Id: <20220117093655.35160-2-yinxin.x@bytedance.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220117093655.35160-1-yinxin.x@bytedance.com> References: <20220117093655.35160-1-yinxin.x@bytedance.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" for the follow scenario: 1. jbd start commit transaction n 2. task A get new handle for transaction n+1 3. task A do some ineligible actions and mark FC_INELIGIBLE 4. jbd complete transaction n and clean FC_INELIGIBLE 5. task A call fsync in this case fast commit will not fallback to full commit and transaction n+1 also not handled by jbd. make ext4_fc_mark_ineligible() also record transaction tid for latest ineligible case, when call ext4_fc_cleanup() check current transaction tid, if small than latest ineligible tid do not clear the EXT4_MF_FC_INELIGIBLE. Reported-by: kernel test robot Reported-by: Dan Carpenter Reported-by: Ritesh Harjani Suggested-by: Harshad Shirwadkar Signed-off-by: Xin Yin --- v3: Fix use-after-free issue for improper use of the 'handle' parameter in ext4_xattr_set() and ext4_evict_inode(). Record current running transaction tid as latest ineligible tid if 'handle' passed as NULL. Update comments for ext4_fc_mark_ineligible(). --- fs/ext4/ext4.h | 3 ++- fs/ext4/extents.c | 4 ++-- fs/ext4/fast_commit.c | 33 +++++++++++++++++++++++++-------- fs/ext4/inode.c | 4 ++-- fs/ext4/ioctl.c | 4 ++-- fs/ext4/namei.c | 4 ++-- fs/ext4/super.c | 1 + fs/ext4/xattr.c | 6 +++--- fs/jbd2/commit.c | 2 +- fs/jbd2/journal.c | 2 +- include/linux/jbd2.h | 2 +- 11 files changed, 42 insertions(+), 23 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 457b76d35473..881f480dd150 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1750,6 +1750,7 @@ struct ext4_sb_info { spinlock_t s_fc_lock; struct buffer_head *s_fc_bh; struct ext4_fc_stats s_fc_stats; + tid_t s_fc_ineligible_tid; #ifdef CONFIG_EXT4_DEBUG int s_fc_debug_max_replay; #endif @@ -2926,7 +2927,7 @@ void __ext4_fc_track_create(handle_t *handle, struct = inode *inode, struct dentry *dentry); void ext4_fc_track_create(handle_t *handle, struct dentry *dentry); void ext4_fc_track_inode(handle_t *handle, struct inode *inode); -void ext4_fc_mark_ineligible(struct super_block *sb, int reason); +void ext4_fc_mark_ineligible(struct super_block *sb, int reason, handle_t = *handle); void ext4_fc_start_update(struct inode *inode); void ext4_fc_stop_update(struct inode *inode); void ext4_fc_del(struct inode *inode); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 01d318645421..880a61dcd81b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -5334,7 +5334,7 @@ static int ext4_collapse_range(struct inode *inode, l= off_t offset, loff_t len) ret =3D PTR_ERR(handle); goto out_mmap; } - ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE); + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle); =20 down_write(&EXT4_I(inode)->i_data_sem); ext4_discard_preallocations(inode, 0); @@ -5474,7 +5474,7 @@ static int ext4_insert_range(struct inode *inode, lof= f_t offset, loff_t len) ret =3D PTR_ERR(handle); goto out_mmap; } - ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE); + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle); =20 /* Expand file to avoid data loss if there is error while shifting */ inode->i_size +=3D len; diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c index 1abe78b8d84f..e031afee42de 100644 --- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -300,18 +300,32 @@ void ext4_fc_del(struct inode *inode) } =20 /* - * Mark file system as fast commit ineligible. This means that next commit - * operation would result in a full jbd2 commit. + * Mark file system as fast commit ineligible, and record latest + * ineligible transaction tid. This means until the recorded + * transaction, commit operation would result in a full jbd2 commit. */ -void ext4_fc_mark_ineligible(struct super_block *sb, int reason) +void ext4_fc_mark_ineligible(struct super_block *sb, int reason, handle_t = *handle) { struct ext4_sb_info *sbi =3D EXT4_SB(sb); + tid_t tid; =20 if (!test_opt2(sb, JOURNAL_FAST_COMMIT) || (EXT4_SB(sb)->s_mount_state & EXT4_FC_REPLAY)) return; =20 ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); + if (handle && !IS_ERR(handle)) + tid =3D handle->h_transaction->t_tid; + else { + read_lock(&sbi->s_journal->j_state_lock); + tid =3D sbi->s_journal->j_running_transaction ? + sbi->s_journal->j_running_transaction->t_tid : 0; + read_unlock(&sbi->s_journal->j_state_lock); + } + spin_lock(&sbi->s_fc_lock); + if (sbi->s_fc_ineligible_tid < tid) + sbi->s_fc_ineligible_tid =3D tid; + spin_unlock(&sbi->s_fc_lock); WARN_ON(reason >=3D EXT4_FC_REASON_MAX); sbi->s_fc_stats.fc_ineligible_reason_count[reason]++; } @@ -387,7 +401,7 @@ static int __track_dentry_update(struct inode *inode, v= oid *arg, bool update) mutex_unlock(&ei->i_fc_lock); node =3D kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS); if (!node) { - ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM); + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL); mutex_lock(&ei->i_fc_lock); return -ENOMEM; } @@ -400,7 +414,7 @@ static int __track_dentry_update(struct inode *inode, v= oid *arg, bool update) if (!node->fcd_name.name) { kmem_cache_free(ext4_fc_dentry_cachep, node); ext4_fc_mark_ineligible(inode->i_sb, - EXT4_FC_REASON_NOMEM); + EXT4_FC_REASON_NOMEM, NULL); mutex_lock(&ei->i_fc_lock); return -ENOMEM; } @@ -502,7 +516,7 @@ void ext4_fc_track_inode(handle_t *handle, struct inode= *inode) =20 if (ext4_should_journal_data(inode)) { ext4_fc_mark_ineligible(inode->i_sb, - EXT4_FC_REASON_INODE_JOURNAL_DATA); + EXT4_FC_REASON_INODE_JOURNAL_DATA, handle); return; } =20 @@ -1179,7 +1193,7 @@ int ext4_fc_commit(journal_t *journal, tid_t commit_t= id) * Fast commit cleanup routine. This is called after every fast commit and * full commit. full is true if we are called after a full commit. */ -static void ext4_fc_cleanup(journal_t *journal, int full) +static void ext4_fc_cleanup(journal_t *journal, int full, tid_t tid) { struct super_block *sb =3D journal->j_private; struct ext4_sb_info *sbi =3D EXT4_SB(sb); @@ -1227,7 +1241,10 @@ static void ext4_fc_cleanup(journal_t *journal, int = full) &sbi->s_fc_q[FC_Q_MAIN]); =20 ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); - ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); + if (tid >=3D sbi->s_fc_ineligible_tid) { + sbi->s_fc_ineligible_tid =3D 0; + ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); + } =20 if (full) sbi->s_fc_bytes =3D 0; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5f79d265d06a..60a1bab59f10 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -338,7 +338,7 @@ void ext4_evict_inode(struct inode *inode) return; no_delete: if (!list_empty(&EXT4_I(inode)->i_fc_list)) - ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM); + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM, NULL); ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ } =20 @@ -5983,7 +5983,7 @@ int ext4_change_inode_journal_flag(struct inode *inod= e, int val) return PTR_ERR(handle); =20 ext4_fc_mark_ineligible(inode->i_sb, - EXT4_FC_REASON_JOURNAL_FLAG_CHANGE); + EXT4_FC_REASON_JOURNAL_FLAG_CHANGE, handle); err =3D ext4_mark_inode_dirty(handle, inode); ext4_handle_sync(handle); ext4_journal_stop(handle); diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index bbbedf27b71c..a8022c2c6a58 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -411,7 +411,7 @@ static long swap_inode_boot_loader(struct super_block *= sb, err =3D -EINVAL; goto err_out; } - ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_SWAP_BOOT); + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_SWAP_BOOT, handle); =20 /* Protect extent tree against block allocations via delalloc */ ext4_double_down_write_data_sem(inode, inode_bl); @@ -1373,7 +1373,7 @@ static long __ext4_ioctl(struct file *filp, unsigned = int cmd, unsigned long arg) =20 err =3D ext4_resize_fs(sb, n_blocks_count); if (EXT4_SB(sb)->s_journal) { - ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE); + ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, NULL); jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); err2 =3D jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0); jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 52c9bd154122..47b9f87dbc6f 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -3889,7 +3889,7 @@ static int ext4_rename(struct user_namespace *mnt_use= rns, struct inode *old_dir, * dirents in directories. */ ext4_fc_mark_ineligible(old.inode->i_sb, - EXT4_FC_REASON_RENAME_DIR); + EXT4_FC_REASON_RENAME_DIR, handle); } else { if (new.inode) ext4_fc_track_unlink(handle, new.dentry); @@ -4049,7 +4049,7 @@ static int ext4_cross_rename(struct inode *old_dir, s= truct dentry *old_dentry, if (unlikely(retval)) goto end_rename; ext4_fc_mark_ineligible(new.inode->i_sb, - EXT4_FC_REASON_CROSS_RENAME); + EXT4_FC_REASON_CROSS_RENAME, handle); if (old.dir_bh) { retval =3D ext4_rename_dir_finish(handle, &old, new.dir->i_ino); if (retval) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0343f682504d..38b496745825 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5087,6 +5087,7 @@ static int __ext4_fill_super(struct fs_context *fc, s= truct super_block *sb) sbi->s_fc_bytes =3D 0; ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); + sbi->s_fc_ineligible_tid =3D 0; spin_lock_init(&sbi->s_fc_lock); memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats)); sbi->s_fc_replay_state.fc_regions =3D NULL; diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 1e0fc1ed845b..042325349098 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -2408,7 +2408,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode = *inode, int name_index, if (IS_SYNC(inode)) ext4_handle_sync(handle); } - ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle); =20 cleanup: brelse(is.iloc.bh); @@ -2486,7 +2486,7 @@ ext4_xattr_set(struct inode *inode, int name_index, c= onst char *name, if (error =3D=3D 0) error =3D error2; } - ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, NULL); =20 return error; } @@ -2920,7 +2920,7 @@ int ext4_xattr_delete_inode(handle_t *handle, struct = inode *inode, error); goto cleanup; } - ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR); + ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, handle); } error =3D 0; cleanup: diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 3cc4ab2ba7f4..d188fa913a07 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -1170,7 +1170,7 @@ void jbd2_journal_commit_transaction(journal_t *journ= al) if (journal->j_commit_callback) journal->j_commit_callback(journal, commit_transaction); if (journal->j_fc_cleanup_callback) - journal->j_fc_cleanup_callback(journal, 1); + journal->j_fc_cleanup_callback(journal, 1, commit_transaction->t_tid); =20 trace_jbd2_end_commit(journal, commit_transaction); jbd_debug(1, "JBD2: commit %d complete, head %d\n", diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 0b86a4365b66..a8e64ad11ae3 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -771,7 +771,7 @@ static int __jbd2_fc_end_commit(journal_t *journal, tid= _t tid, bool fallback) { jbd2_journal_unlock_updates(journal); if (journal->j_fc_cleanup_callback) - journal->j_fc_cleanup_callback(journal, 0); + journal->j_fc_cleanup_callback(journal, 0, tid); write_lock(&journal->j_state_lock); journal->j_flags &=3D ~JBD2_FAST_COMMIT_ONGOING; if (fallback) diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index fd933c45281a..d63b8106796e 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1295,7 +1295,7 @@ struct journal_s * Clean-up after fast commit or full commit. JBD2 calls this function * after every commit operation. */ - void (*j_fc_cleanup_callback)(struct journal_s *journal, int); + void (*j_fc_cleanup_callback)(struct journal_s *journal, int full, tid_t = tid); =20 /** * @j_fc_replay_callback: --=20 2.25.1 From nobody Tue Jun 30 13:04:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 996E0C433FE for ; Mon, 17 Jan 2022 09:37:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235897AbiAQJhd (ORCPT ); Mon, 17 Jan 2022 04:37:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56072 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235895AbiAQJh3 (ORCPT ); Mon, 17 Jan 2022 04:37:29 -0500 Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C63D9C06161C for ; Mon, 17 Jan 2022 01:37:28 -0800 (PST) Received: by mail-pf1-x42b.google.com with SMTP id r5so2604160pfl.2 for ; Mon, 17 Jan 2022 01:37:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qwbnUDZTqvWR5Enash5noKPvbQSY5R+v73OYAxJe5K8=; b=7o6XQmk1OKSS6hbwLK1eNu6qpTq82aozArTSDhioFS3twKocyTkb303A87d++wi7cU EQfPGMjChPI01v8jrTxlOrVlTyAPSUdlHhvWSItVRKdEQopap6OUw19r3HIYmWUMfrSR b3WJJkXJN2Xp5yQM9HtzRvw855+XcLGmfEuWsL2pGSz2p+3C9SUCyiMnrXZbuJeMEgII KnMEP6aCMawuvJAW+eoBMKneAtMLvr7ayRmED1NKoDClCrT0W1WKRFFis6at8J0niL/s CilYe07bPGlXZBidSvPqA7XLbpUloQQz33ICM5xMIvCQedSH3FeiCL2bbQjDQUBLR/7A 8/qQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qwbnUDZTqvWR5Enash5noKPvbQSY5R+v73OYAxJe5K8=; b=GHbIxWs88MER/CYKX6siI5WvBFeIP1y7Hi9zry75AyfUhOU7gI9n3SNCSDWYRgGfls KlzDYu5R0X3piVss1qdw5chN03RBbnK6ZFBCJXExJJCylBomrZ5l02U25ii+ilRxmMEt orfg614PDUL76emQ4uvvfls04VRKAFraFEeV3IPqntN35HJ9n7U8aD1Lf6ra0ORj5Fgb Q6wqtLF1qt8eiCaSw8+Vck65A5lAAJQm0Dd6HdtqZ4mq5y2TCefc+2XxrwYO76kAEbIR e6MyvMZJdNGjKKQWPMZd5aD5vv693/xrkAPw7KmKO+Dxq16e3huFPzMwFMfl9OPgyZZX pGnQ== X-Gm-Message-State: AOAM532MEpD6Q31LS6ry3uB0HDapbWrveScbAdGoSX4we88klUdiDcRS +gVJg5ehb1AmflU2/PC9hSIvRg== X-Google-Smtp-Source: ABdhPJzb1kyryG9lqB84bttxxHy+emvZ1fmbrVjtAhLQ888ATFjo9RkAoqfSjRjgXU05ambSDD+9Ug== X-Received: by 2002:a63:b812:: with SMTP id p18mr18841018pge.22.1642412248353; Mon, 17 Jan 2022 01:37:28 -0800 (PST) Received: from yinxin.bytedance.net ([139.177.225.228]) by smtp.gmail.com with ESMTPSA id z16sm11426497pgi.89.2022.01.17.01.37.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Jan 2022 01:37:27 -0800 (PST) From: Xin Yin To: harshadshirwadkar@gmail.com, tytso@mit.edu, adilger.kernel@dilger.ca Cc: dan.carpenter@oracle.com, riteshh@linux.ibm.com, linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org, Xin Yin Subject: [PATCH v3 2/2] ext4: fast commit may miss file actions Date: Mon, 17 Jan 2022 17:36:55 +0800 Message-Id: <20220117093655.35160-3-yinxin.x@bytedance.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220117093655.35160-1-yinxin.x@bytedance.com> References: <20220117093655.35160-1-yinxin.x@bytedance.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" in the follow scenario: 1. jbd start transaction n 2. task A get new handle for transaction n+1 3. task A do some actions and add inode to FC_Q_MAIN fc_q 4. jbd complete transaction n and clear FC_Q_MAIN fc_q 5. task A call fsync fast commit will lost the file actions during a full commit. we should also add updates to staging queue during a full commit. and in ext4_fc_cleanup(), when reset a inode's fc track range, check it's i_sync_tid, if it bigger than current transaction tid, do not rest it, or we will lost the track range. And EXT4_MF_FC_COMMITTING is not needed anymore, so drop it. Signed-off-by: Xin Yin --- v2: drop EXT4_MF_FC_COMMITTING --- fs/ext4/ext4.h | 5 +---- fs/ext4/fast_commit.c | 11 ++++++----- fs/ext4/super.c | 1 - 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 881f480dd150..22a954fb0c20 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1796,10 +1796,7 @@ static inline int ext4_valid_inum(struct super_block= *sb, unsigned long ino) enum { EXT4_MF_MNTDIR_SAMPLED, EXT4_MF_FS_ABORTED, /* Fatal error detected */ - EXT4_MF_FC_INELIGIBLE, /* Fast commit ineligible */ - EXT4_MF_FC_COMMITTING /* File system underoing a fast - * commit. - */ + EXT4_MF_FC_INELIGIBLE /* Fast commit ineligible */ }; =20 static inline void ext4_set_mount_flag(struct super_block *sb, int bit) diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c index e031afee42de..ccd2b216d6ba 100644 --- a/fs/ext4/fast_commit.c +++ b/fs/ext4/fast_commit.c @@ -375,7 +375,8 @@ static int ext4_fc_track_template( spin_lock(&sbi->s_fc_lock); if (list_empty(&EXT4_I(inode)->i_fc_list)) list_add_tail(&EXT4_I(inode)->i_fc_list, - (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) ? + (sbi->s_journal->j_flags & JBD2_FULL_COMMIT_ONGOING || + sbi->s_journal->j_flags & JBD2_FAST_COMMIT_ONGOING) ? &sbi->s_fc_q[FC_Q_STAGING] : &sbi->s_fc_q[FC_Q_MAIN]); spin_unlock(&sbi->s_fc_lock); @@ -428,7 +429,8 @@ static int __track_dentry_update(struct inode *inode, v= oid *arg, bool update) node->fcd_name.len =3D dentry->d_name.len; =20 spin_lock(&sbi->s_fc_lock); - if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FC_COMMITTING)) + if (sbi->s_journal->j_flags & JBD2_FULL_COMMIT_ONGOING || + sbi->s_journal->j_flags & JBD2_FAST_COMMIT_ONGOING) list_add_tail(&node->fcd_list, &sbi->s_fc_dentry_q[FC_Q_STAGING]); else @@ -893,7 +895,6 @@ static int ext4_fc_submit_inode_data_all(journal_t *jou= rnal) int ret =3D 0; =20 spin_lock(&sbi->s_fc_lock); - ext4_set_mount_flag(sb, EXT4_MF_FC_COMMITTING); list_for_each_entry(ei, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) { ext4_set_inode_state(&ei->vfs_inode, EXT4_STATE_FC_COMMITTING); while (atomic_read(&ei->i_fc_updates)) { @@ -1211,7 +1212,8 @@ static void ext4_fc_cleanup(journal_t *journal, int f= ull, tid_t tid) list_del_init(&iter->i_fc_list); ext4_clear_inode_state(&iter->vfs_inode, EXT4_STATE_FC_COMMITTING); - ext4_fc_reset_inode(&iter->vfs_inode); + if (iter->i_sync_tid <=3D tid) + ext4_fc_reset_inode(&iter->vfs_inode); /* Make sure EXT4_STATE_FC_COMMITTING bit is clear */ smp_mb(); #if (BITS_PER_LONG < 64) @@ -1240,7 +1242,6 @@ static void ext4_fc_cleanup(journal_t *journal, int f= ull, tid_t tid) list_splice_init(&sbi->s_fc_q[FC_Q_STAGING], &sbi->s_fc_q[FC_Q_MAIN]); =20 - ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); if (tid >=3D sbi->s_fc_ineligible_tid) { sbi->s_fc_ineligible_tid =3D 0; ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 38b496745825..2b0a7e4fa379 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5086,7 +5086,6 @@ static int __ext4_fill_super(struct fs_context *fc, s= truct super_block *sb) INIT_LIST_HEAD(&sbi->s_fc_dentry_q[FC_Q_STAGING]); sbi->s_fc_bytes =3D 0; ext4_clear_mount_flag(sb, EXT4_MF_FC_INELIGIBLE); - ext4_clear_mount_flag(sb, EXT4_MF_FC_COMMITTING); sbi->s_fc_ineligible_tid =3D 0; spin_lock_init(&sbi->s_fc_lock); memset(&sbi->s_fc_stats, 0, sizeof(sbi->s_fc_stats)); --=20 2.25.1