From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E5A5156861; Mon, 10 Mar 2025 18:21:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741630900; cv=none; b=cROHu3PKXcjkMXSEsSYTjN0/oDuojXAffLCp1/kUqc68f9Iy5SN60JRLV+pgphpsl9LEbyH+cJhxvnBXfvXIQ0abCPc3l6aJiRvm6/VwYl3FlyQ6frXOwDJIDJo/gdE1rfpBxebR4N8E4h9pCrFUymTdQi8ZdxvvRINOk+ikweI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741630900; c=relaxed/simple; bh=cxo0GFoJEqq1Wd1nMgeGWqFC8tCge2324ek8kyVtRNw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jRCi3/Jv3PvOIn8MH9Ct7UADONpSMtUxxPzWLW2LjEykcojBqa3sjrgzWXAcCjr7mhrYGsbmjvx5ZVE2Jgtgg09okJE9L2o3X0nKAa5dO3KjdL5zQDU6axPurWom8q5vUlKWNImljXkLU34DgbCeEHvTY+N9Y0ek6anMmQfFjEw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=lTrrIlR0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="lTrrIlR0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A7380C4CEE5; Mon, 10 Mar 2025 18:21:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1741630900; bh=cxo0GFoJEqq1Wd1nMgeGWqFC8tCge2324ek8kyVtRNw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lTrrIlR0ViDooch+edvqMVe1+Y1upD3LUHJ/bWr1lDeoOmY7gwVks3u1Gm3anFl+H hdoPeqV++MrFT4HANquBj18jEZTPvSjaaKwJNttGNIBg8GjjCK3qyGIJUGi0ld6yvQ EEDa4/FyoBLx2+llX76CUUu9EafzJ8DFYjLEmHKY= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Sungjong Seo , Namjae Jeon , Sasha Levin , Kun Hu Subject: [PATCH 5.15 574/620] exfat: fix soft lockup in exfat_clear_bitmap Date: Mon, 10 Mar 2025 18:07:00 +0100 Message-ID: <20250310170608.197637530@linuxfoundation.org> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250310170545.553361750@linuxfoundation.org> References: <20250310170545.553361750@linuxfoundation.org> User-Agent: quilt/0.68 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 5.15-stable review patch. If anyone has any objections, please let me know. ------------------ From: Namjae Jeon [ Upstream commit 9da33619e0ca53627641bc97d1b93ec741299111 ] bitmap clear loop will take long time in __exfat_free_cluster() if data size of file/dir enty is invalid. If cluster bit in bitmap is already clear, stop clearing bitmap go to out of loop. Fixes: 31023864e67a ("exfat: add fat entry operations") Reported-by: Kun Hu , Jiaji Qin Reviewed-by: Sungjong Seo Signed-off-by: Namjae Jeon Signed-off-by: Sasha Levin --- fs/exfat/balloc.c | 10 ++++++++-- fs/exfat/exfat_fs.h | 2 +- fs/exfat/fatent.c | 11 +++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c index 144617066a2bf..26808f0d3e9ff 100644 --- a/fs/exfat/balloc.c +++ b/fs/exfat/balloc.c @@ -160,7 +160,7 @@ int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync) return 0; } -void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) +int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) { int i, b; unsigned int ent_idx; @@ -169,13 +169,17 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) struct exfat_mount_options *opts = &sbi->options; if (!is_valid_cluster(sbi, clu)) - return; + return -EIO; ent_idx = CLUSTER_TO_BITMAP_ENT(clu); i = BITMAP_OFFSET_SECTOR_INDEX(sb, ent_idx); b = BITMAP_OFFSET_BIT_IN_SECTOR(sb, ent_idx); + if (!test_bit_le(b, sbi->vol_amap[i]->b_data)) + return -EIO; + clear_bit_le(b, sbi->vol_amap[i]->b_data); + exfat_update_bh(sbi->vol_amap[i], sync); if (opts->discard) { @@ -190,6 +194,8 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync) opts->discard = 0; } } + + return 0; } /* diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index 58816ee3162c4..e242d7758f782 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -420,7 +420,7 @@ int exfat_count_num_clusters(struct super_block *sb, int exfat_load_bitmap(struct super_block *sb); void exfat_free_bitmap(struct exfat_sb_info *sbi); int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync); -void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync); +int exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync); unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu); int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count); int exfat_trim_fs(struct inode *inode, struct fstrim_range *range); diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c index 8f07504e53458..9c116a58544da 100644 --- a/fs/exfat/fatent.c +++ b/fs/exfat/fatent.c @@ -174,6 +174,7 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain BITMAP_OFFSET_SECTOR_INDEX(sb, CLUSTER_TO_BITMAP_ENT(clu)); if (p_chain->flags == ALLOC_NO_FAT_CHAIN) { + int err; unsigned int last_cluster = p_chain->dir + p_chain->size - 1; do { bool sync = false; @@ -188,7 +189,9 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain cur_cmap_i = next_cmap_i; } - exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); + err = exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); + if (err) + break; clu++; num_clusters++; } while (num_clusters < p_chain->size); @@ -209,12 +212,13 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain cur_cmap_i = next_cmap_i; } - exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode))); + if (exfat_clear_bitmap(inode, clu, (sync && IS_DIRSYNC(inode)))) + break; clu = n_clu; num_clusters++; if (err) - goto dec_used_clus; + break; if (num_clusters >= sbi->num_clusters - EXFAT_FIRST_CLUSTER) { /* @@ -228,7 +232,6 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain } while (clu != EXFAT_EOF_CLUSTER); } -dec_used_clus: sbi->used_clusters -= num_clusters; return 0; } -- 2.39.5