From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 EEA0D1B78F3 for ; Fri, 3 Jul 2026 00:17:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783037842; cv=none; b=cvWZ5VX7/8Zi7pSmK1krcgPgJdZg7YCYiXK83oNI7N7/weeGLmcGGiT2jYpGwFSI8Mn2mG8D7pF7F6ZcXEnSsAxMmZ7cXUtEQIP2cu9s/dDBJL6lZlYpGVekUp1fvF+MYZ++UKkh70nz2JKmeDWqPlC5AMiArH8omIRGgsdZFn0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783037842; c=relaxed/simple; bh=iVVKpW1k+O1eRNuOPk4FswTHDMI0CGQu/Hn+se4XnY8=; h=Message-ID:Date:MIME-Version:Cc:Subject:To:References:From: In-Reply-To:Content-Type; b=Ute9OfHUJCRELjYSZHrbGkXWNxP4FWv6vdUInK4MoJshennqKOYSZQfwcbwOdwKejmd82WB/G/NpPGH6/fQ3K5rQ0UCEYFH7Z+/QGwEiTfM91GSqX6KSLgXuJsOjF3i/LGjMXF9ieKsKOeJcAF+xOINewPA7u1AcMHqYGaktCiM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PMG4b5Uj; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PMG4b5Uj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1FBA61F000E9; Fri, 3 Jul 2026 00:17:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1783037840; bh=lEJr4PdzfS4BNp+gMvKovO0r2bUllJAAVk5U8aS8WEw=; h=Date:Cc:Subject:To:References:From:In-Reply-To; b=PMG4b5Uj3XeKoi/WUxa746e2MoxA0xs0I1BBv5MJ4JpGd8xYzValdSFk1KRmazN0+ DctQrjZtgNURjrCdI8sbMK2kKCT1ji2qTofhgErMUBB5z1CuNq4dZO6Lqh1L2mwQk0 ignw+Utnmwr8VgC9F3jcML67OhqL9zCbkgboh0sgKw/QpcU5ZxrAERc6xKh1bQHxvA V3yzkQGnHl8d++lGyn363r9xUo2UHbJ74ZV9Sflg4LfqvKSY4oxRA6axMhC3kJK3Lr VTt/8mTmZnFRRUxDPiF8NK7+XbyX+HsddMFCyi898RRTyariZqG3xVmp/q20WApnHX NPRoTRLevkemA== Message-ID: <703b2fea-5a20-4b48-be9d-f0787d2f22b5@kernel.org> Date: Fri, 3 Jul 2026 08:17:16 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Cc: chao@kernel.org, stable@kernel.org, Daeho Jeong , linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net Subject: Re: [f2fs-dev] [PATCH] f2fs: fix to avoid potential section-unaligned pinfile To: Jaegeuk Kim References: <20260629114918.224537-1-chao@kernel.org> Content-Language: en-US From: Chao Yu In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 7/2/26 22:26, Jaegeuk Kim wrote: > Hi Chao, > > On 06/29, Chao Yu via Linux-f2fs-devel wrote: >> Blocks of pinfile may not aligned to section size due to wrong use >> on pinfile, result in heavy overhead of GC, let avoid this by >> adding additional check condition in f2fs_setattr(). >> >> - truncate -s 8mb pinfile >> : random checkpoint may persist filesize w/ inode >> - fallocate -o 0 -l 8mb pinfile >> - f2fs_fallocate >> - f2fs_expand_inode_data >> - f2fs_allocate_pinning_section >> - f2fs_map_blocks >> - f2fs_map_lock >> - __allocate_data_block >> - file_need_truncate >> : w/ FADVISE_TRUNC_BIT, we can expect unaligned mapping can be >> truncated while open() if f2fs is not umount abnormally >> - f2fs_map_unlock >> : following f2fs checkpoint and sudden power-cut >> >> - mount >> - open pinfile >> - f2fs_file_open >> - finish_preallocate_blocks >> - truncate_setsize >> : filesize is 8mb >> - f2fs_truncate >> : can only truncate block outside filesize, rather than truncating >> unaligned blocks inside filesize > > Have we reproduced this? Jaegeuk, I reproduced w/ below script: #!/bin/bash set -euo pipefail DEV="/dev/vdb" MNT="/mnt/f2fs" PINFILE="${MNT}/pinfile" CHUNK_SIZE=$((2 * 1024 * 1024)) # 2MB # Ensure running as root if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then echo "Error: This script must be run as root." >&2 exit 1 fi # 0. Format f2fs image w/ /dev/vdb, and mount /dev/vdb to /mnt/f2fs/ echo "[+] Unmounting ${MNT} if currently mounted..." umount "${MNT}" 2>/dev/null || true echo "[+] Formatting ${DEV} with f2fs..." mkfs.f2fs -f "${DEV}" echo "[+] Creating mount point ${MNT} and mounting..." mkdir -p "${MNT}" mount "${DEV}" "${MNT}" # 1. Create a pinfile in f2fs image echo "[+] Creating pinfile at ${PINFILE}..." touch "${PINFILE}" f2fs_io pinfile set "${PINFILE}" 2>/dev/null || f2fs_io pinfile 1 "${PINFILE}" truncate -s 8G "${PINFILE}" sync # Task 1: Call appendly fallocate on pinfile inside the range of [0, filesize] task1_fallocate_append() { local file="$1" local chunk="$2" local max_size max_size=$(stat -c %s "$file" 2>/dev/null || echo 0) if [ "$max_size" -eq 0 ]; then max_size=$((8 * 1024 * 1024 * 1024)) fi local offset=0 while true; do # Try standard fallocate, fallback to f2fs_io fallocate fallocate -o "$offset" -l "$chunk" "$file" 2>/dev/null || \ f2fs_io fallocate 0 "$offset" "$chunk" "$file" 2>/dev/null || break offset=$((offset + chunk)) if [ "$offset" -ge "$max_size" ]; then offset=0 fi done } # Task 2: Call f2fs checkpoint ioctl and then call shutdown 2 ioctl task2_checkpoint_shutdown() { local target="$1" # Small delay to allow Task 1 to begin appending sleep 2 # Call F2FS shutdown ioctl level 2 f2fs_io shutdown 1 "$target" } # Check mapping alignment using f2fs_io fiemap check_mapping_alignment() { local file="$1" local align_2mb=$((2 * 1024 * 1024)) # 2MB in bytes local align_blocks=512 # 2MB in 4KB blocks local fiemap_out fiemap_out=$(f2fs_io fiemap 0 4294967295 "$file" 2>/dev/null || f2fs_io fiemap "$file" 2>/dev/null || true) if [[ -z "$fiemap_out" ]]; then echo "Error: Failed to run f2fs_io fiemap on $file" >&2 return 1 fi echo "$fiemap_out" local aligned=true while IFS= read -r line; do [[ -z "$line" || "$line" =~ [Ff]iemap|[Ll]ogical|[Pp]hysical|[Ll]ength|[Ff]lags ]] && continue local -a cols read -r -a cols <<< "$line" local phy_str len_str if [[ ${#cols[@]} -ge 5 ]]; then phy_str="${cols[2]}" len_str="${cols[3]}" elif [[ ${#cols[@]} -ge 3 ]]; then phy_str="${cols[1]}" len_str="${cols[2]}" else continue fi local phy_val len_val if [[ "$phy_str" =~ ^0x || "$phy_str" =~ [a-fA-F] || "${#phy_str}" -gt 10 ]]; then phy_val=$((16#${phy_str#0x})) else phy_val=$((phy_str)) fi if [[ "$len_str" =~ ^0x || "$len_str" =~ [a-fA-F] || "${#len_str}" -gt 10 ]]; then len_val=$((16#${len_str#0x})) else len_val=$((len_str)) fi local unit_align=$align_blocks [[ "$len_val" -ge 4096 ]] && unit_align=$align_2mb if [[ $((phy_val % unit_align)) -ne 0 || $((len_val % unit_align)) -ne 0 ]]; then echo "[!] Unaligned extent mapping detected: $line" >&2 aligned=false fi done <<< "$fiemap_out" $aligned } # 2. Test loop running the two tasks iteration=0 while true; do iteration=$((iteration + 1)) echo "[*] --- Iteration ${iteration} ---" # Task 1: call appendly fallocate on pinfile inside [0, filesize] task1_fallocate_append "${PINFILE}" "${CHUNK_SIZE}" & task1_pid=$! # Task 2: call f2fs checkpoint ioctl and then call shutdown 2 ioctl task2_checkpoint_shutdown "${PINFILE}" & task2_pid=$! # Wait for Task 2 to complete shutdown wait "${task2_pid}" 2>/dev/null || true # Terminate Task 1 and any child fallocate processes pkill -9 -P "${task1_pid}" 2>/dev/null || true kill -9 "${task1_pid}" 2>/dev/null || true wait "${task1_pid}" 2>/dev/null || true # Umount the image -> mount the image umount "${MNT}" mount "${DEV}" "${MNT}" # Use f2fs_io fiemap to check mapping if ! check_mapping_alignment "${PINFILE}"; then echo "[-] Mapping is not 2MB aligned. Print and break out." break fi echo "[+] Mapping is 2MB aligned." # Check space after test; if space exceed 80%, remove the file and call sync used_pct=$(df --output=pcent "${MNT}" | tail -n 1 | tr -dc '0-9') if [[ "${used_pct:-0}" -ge 80 ]]; then echo "[!] Space (${used_pct}%) exceeded 80%. Removing file and calling sync..." rm -f "${PINFILE}" sync touch "${PINFILE}" f2fs_io pinfile set "${PINFILE}" 2>/dev/null || f2fs_io pinfile 1 "${PINFILE}" truncate -s 8G "${PINFILE}" fi done > >> >> Fixes: f5a53edcf01e ("f2fs: support aligned pinned file") >> Cc: stable@kernel.org >> Cc: Daeho Jeong >> Signed-off-by: Chao Yu >> --- >> fs/f2fs/file.c | 28 +++++++++++++++++----------- >> 1 file changed, 17 insertions(+), 11 deletions(-) >> >> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c >> index f4facd409d9b..11cc8d79c235 100644 >> --- a/fs/f2fs/file.c >> +++ b/fs/f2fs/file.c >> @@ -1107,17 +1107,23 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, >> !IS_ALIGNED(attr->ia_size, >> F2FS_BLK_TO_BYTES(fi->i_cluster_size))) >> return -EINVAL; >> - /* >> - * To prevent scattered pin block generation, we don't allow >> - * smaller/equal size unaligned truncation for pinned file. >> - * We only support overwrite IO to pinned file, so don't >> - * care about larger size truncation. >> - */ >> - if (f2fs_is_pinned_file(inode) && >> - attr->ia_size <= i_size_read(inode) && >> - !IS_ALIGNED(attr->ia_size, >> - F2FS_BLK_TO_BYTES(CAP_BLKS_PER_SEC(sbi)))) >> - return -EINVAL; >> + >> + if (f2fs_is_pinned_file(inode)) { >> + /* >> + * It may break section-aligned fallocate recovery >> + * mechanism, so do not allow larger size truncation. >> + */ >> + if (attr->ia_size > i_size_read(inode)) >> + return -EINVAL; >> + /* >> + * To prevent scattered pin block generation, we don't >> + * allow smaller/equal size unaligned truncation for >> + * pinned file. >> + */ >> + else if (!IS_ALIGNED(attr->ia_size, >> + F2FS_BLK_TO_BYTES(CAP_BLKS_PER_SEC(sbi)))) >> + return -EINVAL; >> + } >> } >> >> if (is_quota_modification(idmap, inode, attr)) { >> -- >> 2.49.0 >> >> >> >> _______________________________________________ >> Linux-f2fs-devel mailing list >> Linux-f2fs-devel@lists.sourceforge.net >> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel