From nobody Mon Sep 28 04:10:55 2026 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (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 5FFFA41A8F for ; Wed, 26 Aug 2026 21:39:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=209.85.208.44 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780385; cv=pass; b=CQkbyD3u2n5b2nKXv2yTmsUUEHjGBAsPWqTX82b7sCWjalpUOMD7MLNuu3hXZbRSaJSsQV8kJfmOtEa80CDCkfiGipwgwFRzAoF0TSz68BYKF8KrKClc04huqlrHtEMGRCyVMERHKIp23fkLrWXPNhP3jv6kngcTxXGSXUKvPBU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780385; c=relaxed/simple; bh=ArNFJkH4bUtnh6Np7CzAWvaFjCmzU4yvd1vJoMj1B+I=; h=From:MIME-Version:In-Reply-To:References:Date:Message-ID:Subject: To:Cc:Content-Type; b=sSYS5lIrv1FvmTppZGpftUBlSCi9j3dcFzJBVcZZX2kFO5C64CLaUet+5uhhLjQUm66Ff6uYIVhZo5lw5UYQR2674EXYF6nWEPs2mJKukG18jXkA1YZakB0pJ+p/HMd9KhfFHLHoMd/5K9KcXUelEU/jGidvLscgsMLWEiinDV0= ARC-Authentication-Results: i=2; 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=TRttob5d; arc=pass smtp.client-ip=209.85.208.44 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="TRttob5d" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-69fab5a852cso2464700a12.0 for ; Wed, 26 Aug 2026 14:39:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787780383; cv=none; d=google.com; s=arc-20260327; b=VvKGhqKap//G2YGDfVZIHk0gd+qms0BZ20OwrRp6Rfb7ZaAzWrzTHUVG2dCvd2FFQI o+bbOnFT1x74HvFgHWbfCKPbShGsPpmIGDXKqGTsrvnxhyiflqCQHTlnQPP6/ETmUlbs IBhayvo3oCpwV3k7tZcXGribVPR9lgar12cw8ScpjueFSBkwX5WcrTP9eHi5Ms0K5GNp 1RbuBypRBDFQHDxyIjiNy78JS8pUj+zQMaTz323DMFGddEy94RIRN7WKVW3ck2LpnPvK MxNjyr+yNTWNpjeH9c1jATiFrWgifZIF4Nx0wHmvhtkSMTekGNpMEDCv4PZ3KGUPCQe1 LOtg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:references:in-reply-to:mime-version :from:dkim-signature; bh=kPS8H8k9KpvigDORStPsZkpmZ1Nd6hAKRPDeRw+tD5M=; fh=6qZ6UBo18EreyTTXiLni/9OZQubErKqgX0AR0nb/MdI=; b=hgCFycC0wVJtza6g8vUkP7EQKSRL4AM7F6jr3KpHYGwRTyyTWOKX9hM4aAF5xiTJjW iyDsWa/+H5EYLQMETOl6gOELb/0ipdJWiACQopbcE5989CcAg8Jq8Qaw3B6+Ka0ymkwv arPbcfU9NqTYG5fAZA//pEyS0BciBbBVLk4zmNzRanuCupg1LG1AmW2gLhX1QfnBdX7V 7Q7cTPpF3FHI3RdiEK6LHujQJEUYe1HgoZxAKwQfqlNZABJl/unWtZAOAFMONHd7jqUX wnjGj5igrsH5aFZPnmoeImjlufd1hWBbDT3u1MrJMgqjyojPPehfD6zq2xTrtKzFewNz ex1g==; darn=vger.kernel.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780383; x=1788385183; darn=vger.kernel.org; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=kPS8H8k9KpvigDORStPsZkpmZ1Nd6hAKRPDeRw+tD5M=; b=TRttob5dvk4VcZEQyFVPruEbpzXQmuqTncnmX6TPcMsM83z5l6FAajqH5IDIMy2I/m vqL/fVv9G+ygUu1omVy23mQPovYEr6JKe7v9SOAhKGgwFlslLu753DTlZej2KcjVRFA1 FAZwnRpRNbvx6PpVzeVDvV0hfIMYsWGyiaj5utAKFQSsZyqacKUHlBd04sjWXzE9Ze+/ Eu8QCF3As0x6awIa0j+6zrbsAWL1GLIvpIFoRNogV8iUqwqMojzsS2BTAHjAWndvRRjY 7O1JX1GwwYL1Wv1YluH6JN9RHYxcYr2x4mHdC+Eco/9dwE27h+dSbcXLSXI+8TR6qfxj BXLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780383; x=1788385183; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=kPS8H8k9KpvigDORStPsZkpmZ1Nd6hAKRPDeRw+tD5M=; b=SHLy89fw/ZQynoCu/rkBIxnDP9QflBzuAh374SZeMjE2nZA06fy3EUrMQxwFwBR+4d hJ83VRRkrdqCwXLXY7eq5urqVxTwcxWSmXHGOsMT9rfzfvQVVLvAkXTwa8BC0Z+krpa3 CExYlT7WyaNH1NaInsSJwdMQ979lLIR0nexslc8KHVJD+YGPQ6WqLzchpkheAuYkTVb+ 7kQz54PepgE4Zn/tjhERdo+sXetsyDKSsciTeuvG3U/bb1e+rjAclfiTbXQv+FpYC7yK jkMQg6GNIq4rqTIfmyliejb22JXPPspNPtrLVY1idlYI7DzfRIYyM4Ke9OhZcLZytOsk Sf2Q== X-Forwarded-Encrypted: i=1; AHgh+Rqq2pqVxkJEw21ak0NFCqBdkJ98SaUG9TlvD/NEomK6JrY22U7yjFnpeGCvCN1wgxBTGEgaZMNrP4fVnVc=@vger.kernel.org X-Gm-Message-State: AFuF++nQbWC516OndRxBoGt9DE6/qNFHg15qd7JM8mIZieGRhLb/elJ0 WF5thS39qPs0Evz9Xo5x1Krd2C7d7TBWa96w6ktU9vu9gZ+agEu2izaSU4ebg7yFHaapxC1LCyT Xip0zvtg/nZGU8OAnLae5uH1PxKMhz7QgktFY15w= X-Gm-Gg: AR+sD11Jhy3S3wH6i3mc3pSdulUYzIXDN1khrsZ2W1UVLdVfl2c0AHdYX0T98uwL8qT GmxpgK9ukGRoQtxXQz/ttnFVBQ2hWdrjXR/N/6w1SRLNdBadkTc1ymdLlIVoV92R/h5Ynqg7She 157XjIV4tF+EORMDoYUagNCQkJrmGaOLn8MWOmtRH28fv494cgeNmAvP5MKj5vy1u16xFXA93pe km+VRbVV0KrI/7YILRCcHUUT0+T7+h3sYrTpnHQRTAMTFSfLpIeiDwLubxV1jORUuWcN8eKFzEp mTz69zq4raZoqiCCb4F1uvbS7bCgCCGC7H5AexSzVzKyPmRxHG3fdy5k3EmNbYV3rL6fiBuSG9b 7 X-Received: by 2002:a05:6402:304c:b0:69e:9213:11b with SMTP id 4fb4d7f45d1cf-6a5df63b59fmr10367592a12.13.1787780382483; Wed, 26 Aug 2026 14:39:42 -0700 (PDT) Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:42 -0500 Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:42 -0500 From: Xinping Zhang Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In-Reply-To: References: Date: Wed, 26 Aug 2026 16:39:42 -0500 X-Gm-Features: AcwNN1U2BbM36RbhmFCQr1E1D2roqKDYtg9A4YU1Yd15gl2_fxg9UZPTYYUjKjw Message-ID: Subject: [PATCH 1/5] f2fs: avoid underflow when counting free NIDs To: linux-f2fs-devel@lists.sourceforge.net Cc: jaegeuk@kernel.org, chao@kernel.org, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" __count_free_nids() subtracts the retention threshold before checking whether the cached count exceeds it. The operands are unsigned, so a smaller cache wraps before the result is assigned to long. The PAGE_SIZE-derived threshold happens to make this an unsigned long subtraction, whose wrapped result becomes negative when converted to long by supported toolchains. Do not rely on operand width or unsigned-to-signed conversion. Compare values before subtracting. Signed-off-by: Kelvin Zhang Reviewed-by: Chao Yu --- fs/f2fs/shrinker.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index 4f6bf5926de4..1fd0ee4f89a9 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -23,9 +23,10 @@ static unsigned long __count_nat_entries(struct f2fs_sb_info *sbi) static unsigned long __count_free_nids(struct f2fs_sb_info *sbi) { - long count =3D NM_I(sbi)->nid_cnt[FREE_NID] - MAX_FREE_NIDS; + unsigned long count =3D NM_I(sbi)->nid_cnt[FREE_NID]; + unsigned long max =3D MAX_FREE_NIDS; - return count > 0 ? count : 0; + return count > max ? count - max : 0; } static unsigned long __count_extent_cache(struct f2fs_sb_info *sbi, --=20 2.53.0 From nobody Mon Sep 28 04:10:55 2026 Received: from mail-ed1-f42.google.com (mail-ed1-f42.google.com [209.85.208.42]) (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 206D148986C for ; Wed, 26 Aug 2026 21:39:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=209.85.208.42 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780388; cv=pass; b=fp80H8/8IKDPSKu33UJUDqWBlOelm/gI0lQZZ21amw4ZSHqUY9CfeP1I6O0efsqIzhBmd1w96AD+QuJFAp0DJbXel3povilPSfVkGIdav35uZ7gSmL/U0lwqKlNlVBDRYV7t4xQk5I70WNirU0/ykj695bPoPXZPcLpr3gcbdX8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780388; c=relaxed/simple; bh=855eqWcH4YPivVcM+qG3Qw3zigZnec8Y2quliEWcEi8=; h=From:MIME-Version:In-Reply-To:References:Date:Message-ID:Subject: To:Cc:Content-Type; b=JmDYjn5NR6Dr0S5TSYqdR56V5E5Wkj+rjDrquXRykIDHa5LIjuirZ+E4zdVO6+dTuh4JS6HJiV/UYEM98/S2Y31+nuq4saiZBXclny3BPkquE/sxf7wavxm75WTFCh9F9rPwBe4HQeuaW/EiGFxFRbv+QwRpK0ij94RK1f0bdDY= ARC-Authentication-Results: i=2; 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=g2hDI0Me; arc=pass smtp.client-ip=209.85.208.42 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="g2hDI0Me" Received: by mail-ed1-f42.google.com with SMTP id 4fb4d7f45d1cf-69fab5a852cso2464744a12.0 for ; Wed, 26 Aug 2026 14:39:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787780385; cv=none; d=google.com; s=arc-20260327; b=ptQMfpt9/DTx2DVmOGmtgoZdaFKf18HDGgMjuv9G1gaN4xUi9tPN60NHoA8CYi+YRK AT52ouBiYDT57fFqZwMM7YCIUKnd8nDhytmfW7hWuiE5gd+I/1p02fBUhiHZDwDm1FJp CLoIX+SRPSmfBPobahfKUhaWiTrMXOnBdROkSG5Z4xs7q7gIChRUdQLpeXyPNSkhh6/9 E4kgRK+d1gFRR5rUWxgdL0EbmlpChIlslb+Hwj7VuOGH/7AibRm3xPTLeJp88mKFOBwn u1hguU97KeQBmqxoRmwITd9Dndjw2Q8xlv0uiktSPVwk7uluuDaNRAklQwSBV366KewZ iN9Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:references:in-reply-to:mime-version :from:dkim-signature; bh=hKvrCasOCKT/DyEhWxJp6Xu43dSEy3m9PcOA3nYVyys=; fh=ZsZvsxANxdIpyf4OX7aHPacuXS72z4ayyl1A1SduyLY=; b=Dj6zII6yMvI7nvSdNdEGwJnSpo/56cdZ9TdJ9ZkGL5dwNhg1GF/dBqdnkMwZbgOnJo JZNKXjqrM9edQFn2Iu9v2e1lJrXNDvZWQn6J/a2dcs1JMc6ShItbJplX8uQLgUmZiskT zBkWfWj+R3HLU7/yQCa/VFKKnzV2ChXxFmgdbUt/YBUPzdrm0rdQRR0Vw5ovqh8dbO65 25uKnMeYHX+HJng93Zafosymw6Kkt9Rnmv6NXya9cteUAVir8NKIq2M5DCpt3P1JjGE/ fA/NDtglzwORGXAmV+37BscbczwLTBv5pYwfIjg8TcEj4dDuWWtOHfnuON5xOC0D7Hjg TCww==; darn=vger.kernel.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780385; x=1788385185; darn=vger.kernel.org; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=hKvrCasOCKT/DyEhWxJp6Xu43dSEy3m9PcOA3nYVyys=; b=g2hDI0MewJ+Eo5ywn/Lx9pm+1kEyGoVK7akbBb6aknxZhEw8asIH4PmqG/xdpMKHPY 4AQP2FjjikSEE91dyo9KYq2Vv8YQ+XWtoGaPbHXYM54FQxY/npQYIan08+CzEq6euWfP RZszuxcabQMNoZgMnK0gYRJukPi6HbiJs9AbLuI0WAscqndhGdyZc4ejcrJzrrhrEkHM /2plcZu0s+nsmVDvYcJQYM4JQJZVnTtGmcuh09HEY7pe1COe3dU3ZP8U568RJPmTzR0V RIpuvnfH61G7F9WZRjr1VnshoyBnnZuhdpJ+b9yoWyVJ0kVId7H9tqEsFdfIoBtShF+G Gh9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780385; x=1788385185; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=hKvrCasOCKT/DyEhWxJp6Xu43dSEy3m9PcOA3nYVyys=; b=jvn7LBlrXShfL7UlzjvFmI5utf/7TlTPMuQNIuDj0iiy/EE9jpSAsq7NMUMEAv/WA1 x1+R3I5XJqFAuyFze5qo8zU0+wYW4BXs76nOoV6XssDwwwwrLaVMR3xm3nRQAFohyRBu KtGKk3E7h4eUyPU4E0HKK8AOdsGvuPDp1isyFHJ4VmpC5VFGat+lpzffpTYzGf6d42cv VIQUfamFyHIJ/nvFwabSd8tXDt3r5JRrA0JphPg2Werd+x36YrsiMcZld6nheHmGMa7E CE8EbKqhYLBwMHWHL/INDvQ79Ux2vUM3QRbbbhI+EYzXnynueaGaL4sTEnQFiiHzSCwi hmAg== X-Forwarded-Encrypted: i=1; AHgh+RrNnF+u7K4/aRoUNlTwq5Qi3JHKYu5BQCSY0k8WR+OhDw6fEvrFDBLtN/q3hfFTOSDTn2tcTvrtMm0Yrjs=@vger.kernel.org X-Gm-Message-State: AFuF++m+MRG6zudoT6FfcEy9fZS6oDM9EdG47lQsBf6bp1iKqrr2QOku +zEfBXKZBncvHiLWj9pbjHUAlkDe818qsI2fLat6MipWjZfrxP0KNz/enqbtr8OZKfl9v8ONLhC 6ykMsd7qn2tc+s6uGWUFZxOw2AApTPlg= X-Gm-Gg: AR+sD11i/liB7FOxcTI4JHdXjF5yHu7lctcCJGE9g4S4FpCRF2/2YNXNBudD88zKRK8 vJF7zZWNOZjSzNbBkXUkiLlDwIXJHk4ErlYTtJ8kQ0PVkkDmdxraY8D6AKoz35qjWEVMGvWVw25 MCnzsCKbtN9tf6lZffCVd14A2+0eBpL/SEbuBZ95g9Tvzv9HrHJ6uvdmLeR7Jl+89VVpARe8CY4 6ynQ0vzi9gMVUmNuF9p24FaSDc0gJ7YQvw9hPRHq8PE5UhbAjHpXzB8q3836Drq1l+9OAmtJP+9 ++kRwesm8YjfRsCmSMxXyXZxakdlZyHClJHVehrDa3c431pQ+VDaF1AKq9DE9OZ8i0SlGiv2gOi W X-Received: by 2002:a05:6402:50c9:b0:6a1:28d8:2306 with SMTP id 4fb4d7f45d1cf-6a5df5c688emr10352413a12.1.1787780385063; Wed, 26 Aug 2026 14:39:45 -0700 (PDT) Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:44 -0500 Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:44 -0500 From: Xinping Zhang Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In-Reply-To: References: Date: Wed, 26 Aug 2026 16:39:44 -0500 X-Gm-Features: AcwNN1WOHCzWgi6oQVYrqIg5x5GznlecK5ewJ3ew4weWTdxYqZzK2fCfuj1zNVg Message-ID: Subject: [PATCH 2/5] f2fs: describe SIT block layout dynamically To: linux-f2fs-devel@lists.sourceforge.net Cc: jaegeuk@kernel.org, chao@kernel.org, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An SIT block is a filesystem-block-sized array of SIT entries. A fixed-length array makes the C structure describe a particular block size rather than the on-disk layout. Use a C flexible array member to model that dynamic layout, retaining the entry count as an explicit filesystem geometry calculation. Unlike a zero-length GNU array, this lets bounds sanitizers retain the runtime extent. This is a layout-only change. Signed-off-by: Kelvin Zhang --- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 3 +++ fs/f2fs/segment.c | 15 ++++++++------- fs/f2fs/segment.h | 19 ++++++++++--------- fs/f2fs/super.c | 4 +++- include/linux/f2fs_fs.h | 9 ++++++--- 6 files changed, 31 insertions(+), 21 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 4b59f30ef45d..47c4a5c83a70 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -487,7 +487,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, goto out; /* get sit block addr */ fio.new_blkaddr =3D current_sit_addr(sbi, - blkno * SIT_ENTRY_PER_BLOCK); + blkno * SIT_ENTRY_PER_BLOCK(sbi)); break; case META_SSA: case META_CP: diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index a1f5f375045a..4423f899b2b5 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1862,6 +1862,7 @@ struct f2fs_sb_info { unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ unsigned int blocksize; /* block size */ + unsigned int sit_entries_per_block; /* SIT entries in a block */ unsigned int root_ino_num; /* root inode number*/ unsigned int node_ino_num; /* node inode number*/ unsigned int meta_ino_num; /* meta inode number*/ @@ -2249,6 +2250,8 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio) return F2FS_M_SB(folio->mapping); } +#define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block) + static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info = *sbi) { return (struct f2fs_super_block *)(sbi->raw_super); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 56decf9c691c..8b8fbd5072b6 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -4707,7 +4707,7 @@ static struct folio *get_next_sit_folio(struct f2fs_sb_info *sbi, seg_info_to_sit_folio(sbi, folio, start); folio_mark_dirty(folio); - set_to_next_sit(sit_i, start); + set_to_next_sit(sbi, sit_i, start); return folio; } @@ -4746,10 +4746,11 @@ static void adjust_sit_entry_set(struct sit_entry_set *ses, list_move_tail(&ses->set_list, head); } -static void add_sit_entry(unsigned int segno, struct list_head *head) +static void add_sit_entry(struct f2fs_sb_info *sbi, unsigned int segno, + struct list_head *head) { struct sit_entry_set *ses; - unsigned int start_segno =3D START_SEGNO(segno); + unsigned int start_segno =3D START_SEGNO(sbi, segno); list_for_each_entry(ses, head, set_list) { if (ses->start_segno =3D=3D start_segno) { @@ -4774,7 +4775,7 @@ static void add_sits_in_set(struct f2fs_sb_info *sbi) unsigned int segno; for_each_set_bit(segno, bitmap, MAIN_SEGS(sbi)) - add_sit_entry(segno, set_list); + add_sit_entry(sbi, segno, set_list); } static void remove_sits_in_journal(struct f2fs_sb_info *sbi) @@ -4792,7 +4793,7 @@ static void remove_sits_in_journal(struct f2fs_sb_info *sbi) dirtied =3D __mark_sit_entry_dirty(sbi, segno); if (!dirtied) - add_sit_entry(segno, &SM_I(sbi)->sit_entry_set); + add_sit_entry(sbi, segno, &SM_I(sbi)->sit_entry_set); } update_sits_in_cursum(journal, -i); up_write(&curseg->journal_rwsem); @@ -4842,7 +4843,7 @@ void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) struct folio *folio =3D NULL; struct f2fs_sit_block *raw_sit =3D NULL; unsigned int start_segno =3D ses->start_segno; - unsigned int end =3D min(start_segno + SIT_ENTRY_PER_BLOCK, + unsigned int end =3D min(start_segno + SIT_ENTRY_PER_BLOCK(sbi), (unsigned long)MAIN_SEGS(sbi)); unsigned int segno =3D start_segno; @@ -5007,7 +5008,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi) sit_i->written_valid_blocks =3D 0; sit_i->bitmap_size =3D sit_bitmap_size; sit_i->dirty_sentries =3D 0; - sit_i->sents_per_block =3D SIT_ENTRY_PER_BLOCK; + sit_i->sents_per_block =3D SIT_ENTRY_PER_BLOCK(sbi); sit_i->elapsed_time =3D le64_to_cpu(sbi->ckpt->elapsed_time); sit_i->mounted_time =3D ktime_get_boottime_seconds(); init_rwsem(&sit_i->sentry_lock); diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index db1079169a23..4f90f3bc2a7f 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -101,12 +101,12 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info *sbi, #define SIT_ENTRY_OFFSET(sit_i, segno) \ ((segno) % (sit_i)->sents_per_block) -#define SIT_BLOCK_OFFSET(segno) \ - ((segno) / SIT_ENTRY_PER_BLOCK) -#define START_SEGNO(segno) \ - (SIT_BLOCK_OFFSET(segno) * SIT_ENTRY_PER_BLOCK) +#define SIT_BLOCK_OFFSET(sbi, segno) \ + ((segno) / SIT_ENTRY_PER_BLOCK(sbi)) +#define START_SEGNO(sbi, segno) \ + (SIT_BLOCK_OFFSET(sbi, segno) * SIT_ENTRY_PER_BLOCK(sbi)) #define SIT_BLK_CNT(sbi) \ - DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK) + DIV_ROUND_UP(MAIN_SEGS(sbi), SIT_ENTRY_PER_BLOCK(sbi)) #define f2fs_bitmap_size(nr) \ (BITS_TO_LONGS(nr) * sizeof(unsigned long)) @@ -423,7 +423,7 @@ static inline void seg_info_to_sit_folio(struct f2fs_sb_info *sbi, struct f2fs_sit_block *raw_sit; struct seg_entry *se; struct f2fs_sit_entry *rs; - unsigned int end =3D min(start + SIT_ENTRY_PER_BLOCK, + unsigned int end =3D min(start + SIT_ENTRY_PER_BLOCK(sbi), (unsigned long)MAIN_SEGS(sbi)); int i; @@ -868,7 +868,7 @@ static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, unsigned int start) { struct sit_info *sit_i =3D SIT_I(sbi); - unsigned int offset =3D SIT_BLOCK_OFFSET(start); + unsigned int offset =3D SIT_BLOCK_OFFSET(sbi, start); block_t blk_addr =3D sit_i->sit_base_addr + offset; f2fs_bug_on(sbi, !valid_main_segno(sbi, start)); @@ -893,9 +893,10 @@ static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi, return block_addr + sit_i->sit_base_addr; } -static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int st= art) +static inline void set_to_next_sit(struct f2fs_sb_info *sbi, + struct sit_info *sit_i, unsigned int start) { - unsigned int block_off =3D SIT_BLOCK_OFFSET(start); + unsigned int block_off =3D SIT_BLOCK_OFFSET(sbi, start); f2fs_change_bit(block_off, sit_i->sit_bitmap); } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 3bdb0f891c35..f71a2b63f8ab 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4295,7 +4295,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi) return 1; } - sit_blk_cnt =3D DIV_ROUND_UP(main_segs, SIT_ENTRY_PER_BLOCK); + sit_blk_cnt =3D DIV_ROUND_UP(main_segs, SIT_ENTRY_PER_BLOCK(sbi)); if (sit_bitmap_size * 8 < sit_blk_cnt) { f2fs_err(sbi, "Wrong bitmap size: sit: %u, sit_blk_cnt:%u", sit_bitmap_size, sit_blk_cnt); @@ -4348,6 +4348,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi) le32_to_cpu(raw_super->log_sectors_per_block); sbi->log_blocksize =3D le32_to_cpu(raw_super->log_blocksize); sbi->blocksize =3D BIT(sbi->log_blocksize); + sbi->sit_entries_per_block =3D sbi->blocksize / + sizeof(struct f2fs_sit_entry); sbi->log_blocks_per_seg =3D le32_to_cpu(raw_super->log_blocks_per_seg); sbi->blocks_per_seg =3D BIT(sbi->log_blocks_per_seg); sbi->segs_per_sec =3D le32_to_cpu(raw_super->segs_per_sec); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index bb2b6cd5d507..324427cc29dc 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -396,8 +396,6 @@ struct f2fs_nat_block { * Not allow to change this. */ #define SIT_VBLOCK_MAP_SIZE 64 -#define SIT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / sizeof(struct f2fs_sit_entry)) - /* * F2FS uses 4 bytes to represent block address. As a result, supported si= ze of * disk is 16 TB for a 4K page size and 64 TB for a 16K page size and it e= quals @@ -424,8 +422,13 @@ struct f2fs_sit_entry { __le64 mtime; /* segment age for cleaning */ } __packed; +/* + * The on-disk SIT block is a filesystem-block-sized array of SIT entries. + * Its entry count depends on the filesystem block size, so it must be + * calculated by the caller rather than implied by this C structure. + */ struct f2fs_sit_block { - struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK]; + struct f2fs_sit_entry entries[]; } __packed; /* --=20 2.53.0 From nobody Mon Sep 28 04:10:55 2026 Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com [209.85.208.51]) (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 D141948986D for ; Wed, 26 Aug 2026 21:39:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=209.85.208.51 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780396; cv=pass; b=PRMVsD7RX0dKZnpr+H6dGNk+wQvgoAC4Fvvdtu+lMM75Wxnj2c/hkU8IVhUgv8eQt21d6Dvao8hggQQFOWqdKbnQkuSP/9EGJXxNhP/XAxsFMkBWA8NwawUGSXr3n8pFua+b14W6hKTLdhNXyDc75jmGpv9EkWUiNuDExhApEaY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780396; c=relaxed/simple; bh=CbpoPeQNsfLN3YdS4+fhyIWaGBfo5ktqkdsxM1heW8A=; h=From:MIME-Version:In-Reply-To:References:Date:Message-ID:Subject: To:Cc:Content-Type; b=ivkpp+3tRu+wCtYZDyzkuj6DmjaaGKawCZnCoXsLAdEd/8K4GPi51VYroI3ZcDijcbynlCmEgtV6090Z3sCsMCIYpfKiYmH76f3+TYOcIV15mlH+LJcMnEnXrG22nSYcWy1Z/dJt6dDJGmGvGcHG9ZMeYwZu1NJzUbg8yD6lQkE= ARC-Authentication-Results: i=2; 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=s4gscYPf; arc=pass smtp.client-ip=209.85.208.51 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="s4gscYPf" Received: by mail-ed1-f51.google.com with SMTP id 4fb4d7f45d1cf-6a0a4a28cbdso2680630a12.3 for ; Wed, 26 Aug 2026 14:39:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787780390; cv=none; d=google.com; s=arc-20260327; b=Edxuq8b0Ujy/6GmxkUzzqT+AmlNELnt1W7dFab0t5BxcxvukuE0BzzXQ0EQhbUDE9W I6ze6HxBMzF8qlF3jDEzvVBTsfeL10cnx8Pu9DO6wr+XBXVZuTcCneTmbXATSkOyhEm5 1AyfxIXO7JbW2XjOqOvHOwOnu3+PY3WccbDhA4yt4lKzIYa2FH/2Pvren7UBlBAkT0aH BMm3SQkDn0oZnCDt2rNL3docKXowahplHqPd8XIo/64SFsEwFFpgz0Sxtl/0br8/sKLt uNSAKx7R/xg3a9eL5Tx37nBB7HpHNYb026tR+X9dlAp5XpqgLjusVXFJ8W7yS+77LC4r W2WQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:references:in-reply-to:mime-version :from:dkim-signature; bh=LlsNfxWemhMviWnYnZ0KStlrqTocK5pZLQjuVsmOIfA=; fh=f4Wq6DAD03B3AikZBQ0yjR1w/9eImPHj5D49DMdvBq8=; b=sSZlasEM/sqkJG+PIJgLcnGabg3ffwSY+CTjAksh0DI5N8uoM+KveqCBGYPFgt6S1q sMEYg9xwtvh+TVvo9xT3roPXL/5ho9Oj60/rKAXY/3qRos9S/CBrRYcHK52qBR86Ed+t CnqzJjsejBQOYOCaxsCiPwogXgPY78gUdqj7TUGjBBpPj4IL/QQusQE95DaI6Feov8o1 zawAUqQJBoEAaukrLQ7qfwqLhF6JNTepZe4J+wkXDlAQnv8jfjCGbs6M1lhtyaIzVtFz kvTySrawkY9gn7+3oGOCisYVaipJHzRkgmxWuFyqCN+qFYnAr1NAapORevjK5J105KL6 KX3Q==; darn=vger.kernel.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780390; x=1788385190; darn=vger.kernel.org; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=LlsNfxWemhMviWnYnZ0KStlrqTocK5pZLQjuVsmOIfA=; b=s4gscYPfIm8SFr88dDGOsnCQgXp8HbtkywjZIcux2VPG1ePmEmakMis4gC93n9gyYM YRrZR0xioOaWnriOk7o+ocEViDLuZelIoMwMrjYsZrfS2n7zeOi+b4CyOg/2fnuTSJcp gWcfmAcvfAlIISNUZGOLvgsqwm/xT4ZYz3EIXA62MYSA2VVglM6yhgr8e8xOcqFoupQf aKBETU2omaAhck2Rr4ychnuEAZcE0sbH8Z2TtS3d/rxuHxFqGxIJ6MCMO29osmIFuJU7 ERIYrxJax4blvNSfSOk5IbrTd3uv6OquKgkEWeSG+VR+dn495Qd3OeUdQ0JMvK9buKbI 5Tqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780390; x=1788385190; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=LlsNfxWemhMviWnYnZ0KStlrqTocK5pZLQjuVsmOIfA=; b=c6VJvFvjdJjh3rmtLiWlFo3b+xzIC6xYEjQgc17RBzkujETcQHWyxvH1Xp2WEVXeYM lfWoFBZmqBfspv8DCkvpR+sQiOBMLCcuY9d3hTEL2Fux9kmsLN62YzTVZpKmeBxkpjkN atobJCfC4lERN9+ptgNQJ3a6gIYEkmwti0xcODUwY84unWE3jMhs1KjuunizXD1PjK35 8VJq+9Hptn7nijudCHZK9IXOP79eP4PtnSOw1EnjhS4iUjLSRoBQ6kqwhZiKOHOD2g02 Z012vRDihdyBGm/D0HuBiNoLy8qS3UfRE0Qo/ZG0cug1ObrkXAlN1eM24mtyGzpkqN5h 6RAg== X-Forwarded-Encrypted: i=1; AHgh+Rq4RkH4r4469OYoSoK6Uy1EEw3qQZ2+NB28fZdOFxU+PkXbtVfpRq+YwUrDlgFcqX940GnXDCAA6BjqKz8=@vger.kernel.org X-Gm-Message-State: AFuF++mOhRNNbLV45t3+bDqEYEyrD10rxUVMm80H7QiwB9YgNJx8ViAC mA7bGAyjxTsdobqWcMGyG5hqLXGAseNV85j1UmvGLkw7OQGGK9Qwjg4gMap8fu13h6rJ9HLfLHG z7JuGAEfKRhp4kHVYzgzc5usaBZOpESo= X-Gm-Gg: AR+sD13acjSbDfE6ujUGZuK/jUok0qWv9aXcrv1OjqNbW2uQ/12k86kLETEVVO6MHfl rn2LF7306eiJhyhFyaQS566PrH+5qXgzvHM5RbNknUL5eW/a7Iitklr519TUMmwqKA7ooKDHi9j 6ApPELNAAGT6pX4N5h6Rx8HfJKCwCYcV4ltFKU3BoKLC7O9FdPy8eIJ9OAv1kzO7edeeWzcEwpo HfrARwrXFGCH/o1PVaLEIfs22mpiuCp5iQsCve+BinXft8Q6ZcS3Yzs5/8OJZQDzebu/CZK4jo4 tmDVh2Eim1UcnKQ+ws36U+Y8qaC5Li7TLApjik69yelyNB6yn7u2VMiNI0jl+n7NaHTtUavbl3W R X-Received: by 2002:a05:6402:24d2:b0:6a5:f4e6:ec14 with SMTP id 4fb4d7f45d1cf-6a5f4e6edf0mr2052653a12.4.1787780388907; Wed, 26 Aug 2026 14:39:48 -0700 (PDT) Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:47 -0500 Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:47 -0500 From: Xinping Zhang Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In-Reply-To: References: Date: Wed, 26 Aug 2026 16:39:47 -0500 X-Gm-Features: AcwNN1XBh0dMCwkSFjy6ji5U2z__GZwMCCh_YD8MPyP62QjLX52Ik_B5vqVb1AU Message-ID: Subject: [PATCH 3/5] f2fs: describe orphan block layout dynamically To: linux-f2fs-devel@lists.sourceforge.net Cc: jaegeuk@kernel.org, chao@kernel.org, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An on-disk orphan block consists of a variable-length array of inode numbers followed by a fixed footer. The compile time definition of orphan block struct cannot describe a runtime block length layout. Remove the whole-block structure, document the exact layout, and add helpers that derive the inode capacity and footer address from a supplied block size. Access the inode array and footer separately. The caller still supplies the existing fixed F2FS block size, so valid filesystems retain the same on-disk format and behavior. This is a layout-only refactoring to accommodate a runtime block length. Signed-off-by: Kelvin Zhang --- fs/f2fs/checkpoint.c | 44 ++++++++++++++++++++++------------------- fs/f2fs/f2fs.h | 12 +++++++++++ fs/f2fs/super.c | 2 ++ include/linux/f2fs_fs.h | 18 ++++++++++------- 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 47c4a5c83a70..51ef4f421937 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1041,7 +1041,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *s= bi) for (i =3D 0; i < orphan_blocks; i++) { struct folio *folio; - struct f2fs_orphan_block *orphan_blk; + __le32 *orphan_inos; + struct f2fs_orphan_footer *footer; unsigned int entry_count; folio =3D f2fs_get_meta_folio(sbi, start_blk + i); @@ -1050,9 +1051,10 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *= sbi) goto out; } - orphan_blk =3D folio_address(folio); - entry_count =3D le32_to_cpu(orphan_blk->entry_count); - if (entry_count > F2FS_ORPHANS_PER_BLOCK) { + orphan_inos =3D folio_address(folio); + footer =3D f2fs_orphan_footer(orphan_inos, sbi); + entry_count =3D le32_to_cpu(footer->entry_count); + if (entry_count > F2FS_ORPHANS_PER_BLOCK(sbi)) { f2fs_err(sbi, "invalid orphan inode entry count %u", entry_count); set_sbi_flag(sbi, SBI_NEED_FSCK); @@ -1063,7 +1065,7 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *s= bi) } for (j =3D 0; j < entry_count; j++) { - nid_t ino =3D le32_to_cpu(orphan_blk->ino[j]); + nid_t ino =3D le32_to_cpu(orphan_inos[j]); err =3D recover_orphan_inode(sbi, ino); if (err) { @@ -1084,7 +1086,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *s= bi) static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_bl= k) { struct list_head *head; - struct f2fs_orphan_block *orphan_blk =3D NULL; + __le32 *orphan_inos =3D NULL; + struct f2fs_orphan_footer *footer =3D NULL; unsigned int nentries =3D 0; unsigned short index =3D 1; unsigned short orphan_blocks; @@ -1092,7 +1095,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) struct ino_entry *orphan =3D NULL; struct inode_management *im =3D &sbi->im[ORPHAN_INO]; - orphan_blocks =3D GET_ORPHAN_BLOCKS(im->ino_num); + orphan_blocks =3D GET_ORPHAN_BLOCKS(sbi, im->ino_num); /* * we don't need to do spin_lock(&im->ino_lock) here, since all the @@ -1105,21 +1108,22 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) list_for_each_entry(orphan, head, list) { if (!folio) { folio =3D f2fs_grab_meta_folio(sbi, start_blk++); - orphan_blk =3D folio_address(folio); - memset(orphan_blk, 0, sizeof(*orphan_blk)); + orphan_inos =3D folio_address(folio); + footer =3D f2fs_orphan_footer(orphan_inos, sbi); + memset(orphan_inos, 0, sbi->blocksize); } - orphan_blk->ino[nentries++] =3D cpu_to_le32(orphan->ino); + orphan_inos[nentries++] =3D cpu_to_le32(orphan->ino); - if (nentries =3D=3D F2FS_ORPHANS_PER_BLOCK) { + if (nentries =3D=3D F2FS_ORPHANS_PER_BLOCK(sbi)) { /* - * an orphan block is full of 1020 entries, + * an orphan block is full, * then we need to flush current orphan blocks * and bring another one in memory */ - orphan_blk->blk_addr =3D cpu_to_le16(index); - orphan_blk->blk_count =3D cpu_to_le16(orphan_blocks); - orphan_blk->entry_count =3D cpu_to_le32(nentries); + footer->blk_addr =3D cpu_to_le16(index); + footer->blk_count =3D cpu_to_le16(orphan_blocks); + footer->entry_count =3D cpu_to_le32(nentries); folio_mark_dirty(folio); f2fs_folio_put(folio, true); index++; @@ -1129,9 +1133,9 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) } if (folio) { - orphan_blk->blk_addr =3D cpu_to_le16(index); - orphan_blk->blk_count =3D cpu_to_le16(orphan_blocks); - orphan_blk->entry_count =3D cpu_to_le32(nentries); + footer->blk_addr =3D cpu_to_le16(index); + footer->blk_count =3D cpu_to_le16(orphan_blocks); + footer->entry_count =3D cpu_to_le32(nentries); folio_mark_dirty(folio); f2fs_folio_put(folio, true); } @@ -1824,7 +1828,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) __clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); spin_unlock_irqrestore(&sbi->cp_lock, flags); - orphan_blocks =3D GET_ORPHAN_BLOCKS(orphan_num); + orphan_blocks =3D GET_ORPHAN_BLOCKS(sbi, orphan_num); ckpt->cp_pack_start_sum =3D cpu_to_le32(1 + cp_payload_blks + orphan_blocks); @@ -2080,7 +2084,7 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sb= i) sbi->max_orphans =3D (BLKS_PER_SEG(sbi) - F2FS_CP_PACKS - NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) * - F2FS_ORPHANS_PER_BLOCK; + F2FS_ORPHANS_PER_BLOCK(sbi); } int __init f2fs_create_checkpoint_caches(void) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4423f899b2b5..d1235ba80331 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1863,6 +1863,7 @@ struct f2fs_sb_info { unsigned int log_blocksize; /* log2 block size */ unsigned int blocksize; /* block size */ unsigned int sit_entries_per_block; /* SIT entries in a block */ + unsigned int orphans_per_block; /* orphan inodes in a block */ unsigned int root_ino_num; /* root inode number*/ unsigned int node_ino_num; /* node inode number*/ unsigned int meta_ino_num; /* meta inode number*/ @@ -2251,6 +2252,17 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio) } #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block) +#define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block) +#define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \ + F2FS_ORPHANS_PER_BLOCK(sbi)) + +static inline struct f2fs_orphan_footer * +f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi) +{ + return (struct f2fs_orphan_footer *) + ((char *)orphan_block + sbi->blocksize - + sizeof(struct f2fs_orphan_footer)); +} static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info = *sbi) { diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index f71a2b63f8ab..f324e9cf4264 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4350,6 +4350,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi) sbi->blocksize =3D BIT(sbi->log_blocksize); sbi->sit_entries_per_block =3D sbi->blocksize / sizeof(struct f2fs_sit_entry); + sbi->orphans_per_block =3D (sbi->blocksize - + sizeof(struct f2fs_orphan_footer)) / sizeof(__le32); sbi->log_blocks_per_seg =3D le32_to_cpu(raw_super->log_blocks_per_seg); sbi->blocks_per_seg =3D BIT(sbi->log_blocks_per_seg); sbi->segs_per_sec =3D le32_to_cpu(raw_super->segs_per_sec); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 324427cc29dc..a5111556d923 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -220,14 +220,18 @@ struct f2fs_checkpoint { /* * For orphan inode management + * + * An orphan block has no fixed-size C structure because the number of ino= de + * entries depends on the filesystem block size. Its exact on-disk layout= is: + * + * 0 blocksize - 16 blocksize + * +--------------------------+--------------------------+ + * | ino[0] ... ino[n - 1] | struct f2fs_orphan_footer | + * +--------------------------+--------------------------+ + * + * n =3D (blocksize - sizeof(struct f2fs_orphan_footer)) / sizeof(__le32) */ -#define F2FS_ORPHANS_PER_BLOCK ((F2FS_BLKSIZE - 4 * sizeof(__le32)) / sizeof(__le32)) - -#define GET_ORPHAN_BLOCKS(n) (((n) + F2FS_ORPHANS_PER_BLOCK - 1) / \ - F2FS_ORPHANS_PER_BLOCK) - -struct f2fs_orphan_block { - __le32 ino[F2FS_ORPHANS_PER_BLOCK]; /* inode numbers */ +struct f2fs_orphan_footer { __le32 reserved; /* reserved */ __le16 blk_addr; /* block index in current CP */ __le16 blk_count; /* Number of orphan inode blocks in CP */ --=20 2.53.0 From nobody Mon Sep 28 04:10:55 2026 Received: from mail-ed1-f42.google.com (mail-ed1-f42.google.com [209.85.208.42]) (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 857FF48987C for ; Wed, 26 Aug 2026 21:39:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=209.85.208.42 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780397; cv=pass; b=bUQWwxTlLTjIRS2SPd3uJVCZhX2URyhpdgu6JzMI706gq6r38S54ywtwa7Dh0pSTilTNZ7WiSvsSPzYENhHw10uEQ3Iq4A1/6vU5uRiO0KzlSjy5EZHbkWFHcCwYQZzjuQjX+br6Y2uyRPMSfJSNP+GPLJCxEehjL7CiHUObsSY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780397; c=relaxed/simple; bh=VUo3QPoi2BGr4DMDng71zn2kUh4mhgbxnFqsGb8ly6k=; h=From:MIME-Version:In-Reply-To:References:Date:Message-ID:Subject: To:Cc:Content-Type; b=UKTnKTZ3uhVUcxw7ZH1tEIQIZa2wFu7PmYVGO/Pa3KTi8obqhqKs+SHsNxVex+5LwxkTGj54TTr1BDg1KUfSnNbwR9nFHfnhy+9XsM9MWWLkFMUjWUQUG0xq7Qr34tb0Cs+xbkFIuqTGaBoF1p/MaXGgUKYX0MMx9A5/52AOzIQ= ARC-Authentication-Results: i=2; 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=NIVjQvc8; arc=pass smtp.client-ip=209.85.208.42 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="NIVjQvc8" Received: by mail-ed1-f42.google.com with SMTP id 4fb4d7f45d1cf-6a17211b9ecso3485122a12.2 for ; Wed, 26 Aug 2026 14:39:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787780390; cv=none; d=google.com; s=arc-20260327; b=bQRtgl1tomcE4kuxVeCJlZxHplA6/GVxBpZWief1HBvgTZqAPK9bNxvxGPf9Tk+NEH wdoCo8dEbbeBlf5v4kT9/hLxZWihBisy/J85Eo3MYWwwUD767d4pTcgNR5qfTooHrRHi y8DGlcc7CCFXyNIpVTYZti2JP6yuybiMQxnftrJf5XOnvtuBAdSEVuTgnCX626yGPhT4 aW05nuO7s5HHGBXCP7YeS+bCwUX+Adz/W9azZbzNDFCvwtWMqQi/ZB4Ni1/TktG9dLMY iRNmnDhVmFrhVumLMLgrsy/L0fMQ+KnW/vViPnbYmQHPfWPv1/ZauuYcT8qLtNnxutkD y/hg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:references:in-reply-to:mime-version :from:dkim-signature; bh=N0Ysmq4yr2zIiKUTJ1RbVuURkuCynPkrReTeG+GnH4Q=; fh=eica1wZFXwHjih8iCsaSnPUqt9JUeFaNNsic00JExF8=; b=VYjz9rDSYngtjtQQMkNF/E3365O3fw5HDs5EODJA2GPA0uiPws9Kp3zjFPX0s9F1P6 TOmEvGBURTC0m3sNJHTJDFFbY1VYPfCGINFaZpqlnfFDE6s7hHXSDe+fl6CsRfNc+3XB AOgqgJ2oTS+Amnsa4BbZ0p2KtZlSFTPWmquiKLayc8iWDy59fFb0zXZZdHdC5Q42oC/w R0HHOvzsHhXUd4FskEVSOIwgYudUBzFUli6e4aa7P/vZdwKfELLQ9ECh7E+GZYyScojO KcE1DSRhKrqG784J5yOiI5RpkC6gCkWHBPVQgQNSSWQiXl+3G2c9+B0U0IJXAptaKZre OKIw==; darn=vger.kernel.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780390; x=1788385190; darn=vger.kernel.org; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=N0Ysmq4yr2zIiKUTJ1RbVuURkuCynPkrReTeG+GnH4Q=; b=NIVjQvc8mWUiXPRPxwDcgg612GVOsSsz8pcKRaJuX/He/KpVWIkRZKVJbdqvKnriQ5 HU7M0wxRqlKYp3hbFM/TzqODHmxHQyQOoa7MwnzBUgr9MgvFj+jmvk9XVrqiuADSz1jV T8L3veOFS0d86hXuEuVIW7PoFVpwvAmt08CIbf9YVhyCT0YSoSdivPIe2Ptc8KNNSs8g g1hGzMXeAmDcEh0x2qRk1XduyB7PFTUwEA0U2+ZukcKJ5ft/pwqSkWRsyLvf8bqzhnaZ 4CZ/fcl4BdmHWEuMy+va7aTA90QP5W9IHyohqN4/dkvxIv44wyMpYOOrXY5x7rCm5qtj xVBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780390; x=1788385190; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=N0Ysmq4yr2zIiKUTJ1RbVuURkuCynPkrReTeG+GnH4Q=; b=qqrlh15eZXwvtuT07ZumcKpkskMgoIOmHMTycAblL85yZEoCC1yt0N1YOV8bzUeaDu SL7msnfJj0IzADUU0fuiiEu98JD3yoBVMghAXFrbma51PsIJ9tmIvu/UMJjd4iS/fA/4 M4r2CS8jHg8UfUqN6aoWphXijg7EsLAPTCi+emml/lCA0G1uhac56B6O+K3VhYwbjrhb EMeTLbjGJr1Rvqiq5PyszRxEKNOx98+nutqWkZw8qWPXIw+40oZy3Lpm/EAG2iA+gLr8 QBG9MrR3XlwqYsBIR6rBwm2uoW8p4CA8LTid/7T9d2ybE3D47UU29p9lDoEPq0UCI4v/ FoDA== X-Forwarded-Encrypted: i=1; AHgh+RoDYZZUrd1SDQ4RmHdnbrPoMavjvMu3q5xsKQU2fGIRRVNytQ6mJ2SHKw66YCMv1CUdOYzcKfz0qmPUbH8=@vger.kernel.org X-Gm-Message-State: AFuF++nF0ghTh5O+rRaqzpuBEe8YdB/CRVBYB+DSznFVpLjdK/O+9bqP umYF8iWfO05Z/Cs4jsW+ywWNpFGzzvPx84A2qEkCYKRJdMbrbQCADznEGeCMhkGEWSAnDQPYxKq Ppn1ca/7dmsOxitV0ev7Pi0p+w02o4h4= X-Gm-Gg: AR+sD12Sho/xaNcudtImV3IW7zuKU/jfHm7UdU5wA0ghWBk6+kDzRBVN5KQf9P3ScD/ /V94uhZLzsd/vll6c27f0VJX8Jr9F9x94nnh64tVeZlJJQOk47EQJEuEjMPW0S8c2gik2crev56 mYQX1yOcT3aXF7MFOK3US+xcdcXuuwwV+oJZ/LhEyZMvdg037E12jLyZaBKTc9vO3uhd3/5sH5s 3r6J8HftplEOMx1boyZ2cgT3HMqzHwyni2yXjBSMVnN8Ib+7JEZ47SuOJSAIxxkOMWIGQ+Mww6f ZfD9aa3iqWSziFjW1NBFTLgF+A+nc1tVG6F7cV/fEn4vbzVLcTfqZ6we32m7788dGJkzn2JN4cV P X-Received: by 2002:a05:6402:3548:b0:6a0:927e:39e2 with SMTP id 4fb4d7f45d1cf-6a5df5ce41cmr11749992a12.5.1787780390417; Wed, 26 Aug 2026 14:39:50 -0700 (PDT) Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:50 -0500 Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:50 -0500 From: Xinping Zhang Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In-Reply-To: References: Date: Wed, 26 Aug 2026 16:39:50 -0500 X-Gm-Features: AcwNN1W4yUHj4WUCahU17IRauz1lZ0unZYR40qWPD2vMGb0Yk7WErJxZG95yvYY Message-ID: Subject: [PATCH 4/5] f2fs: describe dentry block layout dynamically To: linux-f2fs-devel@lists.sourceforge.net Cc: jaegeuk@kernel.org, chao@kernel.org, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An on-disk dentry block contains a bitmap, reserved padding, a variable-length dir-entry array, and matching filename slots. A fixed C structure ties their offsets to the compile-time block size and requires error-prone reserved-size definitions. Remove the whole-block structure and its compile-time layout macros. Compute the offsets from the block size and expose the regions through the existing zero-copy dentry pointer. Pass the owning directory inode at every block-view initialization to keep the helper contract consistent. No functional change is intended; this commit continues to use the fixed F2FS block size. Signed-off-by: Kelvin Zhang --- fs/f2fs/dir.c | 51 +++++++++++++++++++++-------------------- fs/f2fs/f2fs.h | 31 ++++++++++++++++--------- fs/f2fs/inline.c | 2 +- fs/f2fs/super.c | 6 +++++ include/linux/f2fs_fs.h | 31 ++++++++++++------------- 5 files changed, 68 insertions(+), 53 deletions(-) diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index fd0e2cd31a81..75ff36a13f60 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -195,7 +195,7 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir, int *max_slots, bool use_hash) { - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; struct f2fs_dentry_ptr d; dentry_blk =3D folio_address(dentry_folio); @@ -518,7 +518,7 @@ static int make_empty_dir(struct inode *inode, struct inode *parent, struct folio *folio) { struct folio *dentry_folio; - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; struct f2fs_dentry_ptr d; if (f2fs_has_inline_dentry(inode)) @@ -530,7 +530,7 @@ static int make_empty_dir(struct inode *inode, dentry_blk =3D folio_address(dentry_folio); - make_dentry_ptr_block(NULL, &d, dentry_blk); + make_dentry_ptr_block(inode, &d, dentry_blk); f2fs_do_make_empty_dir(inode, parent, &d); folio_mark_dirty(dentry_folio); @@ -690,7 +690,7 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname, unsigned long bidx, block; unsigned int nbucket, nblock; struct folio *dentry_folio =3D NULL; - struct f2fs_dentry_block *dentry_blk =3D NULL; + void *dentry_blk =3D NULL; struct f2fs_dentry_ptr d; struct folio *folio =3D NULL; int slots, err =3D 0; @@ -727,9 +727,9 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname, return PTR_ERR(dentry_folio); dentry_blk =3D folio_address(dentry_folio); - bit_pos =3D f2fs_room_for_filename(&dentry_blk->dentry_bitmap, - slots, NR_DENTRY_IN_BLOCK); - if (bit_pos < NR_DENTRY_IN_BLOCK) + make_dentry_ptr_block(dir, &d, dentry_blk); + bit_pos =3D f2fs_room_for_filename(d.bitmap, slots, d.max); + if (bit_pos < d.max) goto add_dentry; f2fs_folio_put(dentry_folio, true); @@ -750,7 +750,6 @@ int f2fs_add_regular_entry(struct inode *dir, const struct f2fs_filename *fname, } } - make_dentry_ptr_block(NULL, &d, dentry_blk); f2fs_update_dentry(ino, mode, &d, &fname->disk_name, fname->hash, bit_pos); @@ -887,7 +886,8 @@ void f2fs_drop_nlink(struct inode *dir, struct inode *i= node) void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct folio *folio, struct inode *dir, struct inode *inode) { - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; + struct f2fs_dentry_ptr d; unsigned int bit_pos; int slots =3D GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); pgoff_t index =3D folio->index; @@ -905,18 +905,17 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct folio *folio, f2fs_folio_wait_writeback(folio, DATA, true, true); dentry_blk =3D folio_address(folio); - bit_pos =3D dentry - dentry_blk->dentry; + make_dentry_ptr_block(dir, &d, dentry_blk); + bit_pos =3D dentry - d.dentry; for (i =3D 0; i < slots; i++) - __clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); + __clear_bit_le(bit_pos + i, d.bitmap); /* Let's check and deallocate this dentry page */ - bit_pos =3D find_next_bit_le(&dentry_blk->dentry_bitmap, - NR_DENTRY_IN_BLOCK, - 0); + bit_pos =3D find_next_bit_le(d.bitmap, d.max, 0); folio_mark_dirty(folio); - if (bit_pos =3D=3D NR_DENTRY_IN_BLOCK && - !f2fs_truncate_hole(dir, index, index + 1)) { + if (bit_pos =3D=3D d.max && + !f2fs_truncate_hole(dir, index, index + 1)) { f2fs_clear_page_cache_dirty_tag(folio); folio_clear_dirty_for_io(folio); folio_clear_uptodate(folio); @@ -938,7 +937,8 @@ bool f2fs_empty_dir(struct inode *dir) { unsigned long bidx =3D 0; unsigned int bit_pos; - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; + struct f2fs_dentry_ptr d; unsigned long nblock =3D dir_blocks(dir); if (f2fs_has_inline_dentry(dir)) @@ -959,17 +959,16 @@ bool f2fs_empty_dir(struct inode *dir) } dentry_blk =3D folio_address(dentry_folio); + make_dentry_ptr_block(dir, &d, dentry_blk); if (bidx =3D=3D 0) bit_pos =3D 2; else bit_pos =3D 0; - bit_pos =3D find_next_bit_le(&dentry_blk->dentry_bitmap, - NR_DENTRY_IN_BLOCK, - bit_pos); + bit_pos =3D find_next_bit_le(d.bitmap, d.max, bit_pos); f2fs_folio_put(dentry_folio, false); - if (bit_pos < NR_DENTRY_IN_BLOCK) + if (bit_pos < d.max) return false; bidx++; @@ -1066,10 +1065,12 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) { struct inode *inode =3D file_inode(file); unsigned long npages =3D dir_blocks(inode); - struct f2fs_dentry_block *dentry_blk =3D NULL; + void *dentry_blk =3D NULL; struct file_ra_state *ra =3D &file->f_ra; loff_t start_pos =3D ctx->pos; - unsigned int n =3D ((unsigned long)ctx->pos / NR_DENTRY_IN_BLOCK); + struct f2fs_sb_info *sbi =3D F2FS_I_SB(inode); + unsigned int entries =3D sbi->dentries_per_block; + unsigned int n =3D (unsigned long)ctx->pos / entries; struct f2fs_dentry_ptr d; struct fscrypt_str fstr =3D FSTR_INIT(NULL, 0); int err =3D 0; @@ -1089,7 +1090,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) goto out_free; } - for (; n < npages; ctx->pos =3D n * NR_DENTRY_IN_BLOCK) { + for (; n < npages; ctx->pos =3D n * entries) { struct folio *dentry_folio; pgoff_t next_pgofs; @@ -1122,7 +1123,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) make_dentry_ptr_block(inode, &d, dentry_blk); err =3D f2fs_fill_dentries(ctx, &d, - n * NR_DENTRY_IN_BLOCK, &fstr); + n * entries, &fstr); f2fs_folio_put(dentry_folio, false); if (err) break; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d1235ba80331..026419aed2e9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -668,17 +668,6 @@ struct f2fs_dentry_ptr { int nr_bitmap; }; -static inline void make_dentry_ptr_block(struct inode *inode, - struct f2fs_dentry_ptr *d, struct f2fs_dentry_block *t) -{ - d->inode =3D inode; - d->max =3D NR_DENTRY_IN_BLOCK; - d->nr_bitmap =3D SIZE_OF_DENTRY_BITMAP; - d->bitmap =3D t->dentry_bitmap; - d->dentry =3D t->dentry; - d->filename =3D t->filename; -} - static inline void make_dentry_ptr_inline(struct inode *inode, struct f2fs_dentry_ptr *d, void *t) { @@ -1864,6 +1853,9 @@ struct f2fs_sb_info { unsigned int blocksize; /* block size */ unsigned int sit_entries_per_block; /* SIT entries in a block */ unsigned int orphans_per_block; /* orphan inodes in a block */ + unsigned int dentries_per_block; /* dentries in a block */ + unsigned int dentry_bitmap_size; /* dentry bitmap size in bytes */ + unsigned int dentry_reserved_size; /* dentry reserved bytes */ unsigned int root_ino_num; /* root inode number*/ unsigned int node_ino_num; /* node inode number*/ unsigned int meta_ino_num; /* meta inode number*/ @@ -2264,6 +2256,23 @@ f2fs_orphan_footer(void *orphan_block, struct f2fs_sb_info *sbi) sizeof(struct f2fs_orphan_footer)); } +static inline void make_dentry_ptr_block(struct inode *inode, + struct f2fs_dentry_ptr *d, void *t) +{ + struct f2fs_sb_info *sbi =3D F2FS_I_SB(inode); + unsigned int entries =3D sbi->dentries_per_block; + unsigned int bitmap_size =3D sbi->dentry_bitmap_size; + unsigned int reserved_size =3D sbi->dentry_reserved_size; + + d->inode =3D inode; + d->max =3D entries; + d->nr_bitmap =3D bitmap_size; + d->bitmap =3D t; + d->dentry =3D t + bitmap_size + reserved_size; + d->filename =3D t + bitmap_size + reserved_size + + SIZE_OF_DIR_ENTRY * entries; +} + static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info = *sbi) { return (struct f2fs_super_block *)(sbi->raw_super); diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index aec06fb4fd76..718dd785865a 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -415,7 +415,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct folio *ifolio, { struct folio *folio; struct dnode_of_data dn; - struct f2fs_dentry_block *dentry_blk; + void *dentry_blk; struct f2fs_dentry_ptr src, dst; int err; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index f324e9cf4264..133c279b9931 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4352,6 +4352,12 @@ static void init_sb_info(struct f2fs_sb_info *sbi) sizeof(struct f2fs_sit_entry); sbi->orphans_per_block =3D (sbi->blocksize - sizeof(struct f2fs_orphan_footer)) / sizeof(__le32); + sbi->dentries_per_block =3D (BITS_PER_BYTE * sbi->blocksize) / + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1); + sbi->dentry_bitmap_size =3D DIV_ROUND_UP(sbi->dentries_per_block, + BITS_PER_BYTE); + sbi->dentry_reserved_size =3D sbi->blocksize - sbi->dentry_bitmap_size - + (SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * sbi->dentries_per_block; sbi->log_blocks_per_seg =3D le32_to_cpu(raw_super->log_blocks_per_seg); sbi->blocks_per_seg =3D BIT(sbi->log_blocks_per_seg); sbi->segs_per_sec =3D le32_to_cpu(raw_super->segs_per_sec); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index a5111556d923..b4bb4e2f99b3 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -602,15 +602,7 @@ typedef __le32 f2fs_hash_t; * dentry, when converting inline dentry we should handle this carefully. */ -/* the number of dentry in a block */ -#define NR_DENTRY_IN_BLOCK ((BITS_PER_BYTE * F2FS_BLKSIZE) / \ - ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1)) #define SIZE_OF_DIR_ENTRY 11 /* by byte */ -#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \ - BITS_PER_BYTE) -#define SIZE_OF_RESERVED (F2FS_BLKSIZE - ((SIZE_OF_DIR_ENTRY + \ - F2FS_SLOT_LEN) * \ - NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP)) #define MIN_INLINE_DENTRY_SIZE 40 /* just include '.' and '..' entries */ /* One directory entry slot representing F2FS_SLOT_LEN-sized file name */ @@ -621,14 +613,21 @@ struct f2fs_dir_entry { __u8 file_type; /* file type */ } __packed; -/* Block-sized directory entry block */ -struct f2fs_dentry_block { - /* validity bitmap for directory entries in each block */ - __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP]; - __u8 reserved[SIZE_OF_RESERVED]; - struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK]; - __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; -} __packed; +/* + * A dentry block is laid out as follows, where the number of entries and = all + * offsets are determined by the filesystem block size at runtime: + * + * 0 blocksize + * +--------+----------+-------------------+-----------------------+ + * | bitmap | reserved | dir_entry[entries]| filename[entries][8] | + * +--------+----------+-------------------+-----------------------+ + * + * entries =3D (BITS_PER_BYTE * blocksize) / + * ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * BITS_PER_BYTE + 1) + * bitmap_size =3D DIV_ROUND_UP(entries, BITS_PER_BYTE) + * reserved_size =3D blocksize - bitmap_size - + * (SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * entries + */ #define F2FS_DEF_PROJID 0 /* default project ID */ --=20 2.53.0 From nobody Mon Sep 28 04:10:55 2026 Received: from mail-ed1-f41.google.com (mail-ed1-f41.google.com [209.85.208.41]) (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 A54BF3BA23F for ; Wed, 26 Aug 2026 21:39:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=209.85.208.41 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780401; cv=pass; b=pgxhrnak6wQWIIMwjM59DMrwxGjKFHzbOpOp/DVf1lWNog0FQfcX/NTBcYWuUyys3KcykXjgR85d+JrkbL6Gohn5TDVSRDeA9cAIPB32xDAUAnab5SD/vn/O/E56g/mtDPaxItD2zBf38U3QKCLXCkdQR7pxK2RSXqTrCw1pRfA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787780401; c=relaxed/simple; bh=il790Qh8ouORS9ItXr1smomGok8BB1WfSbINgiYK04c=; h=From:MIME-Version:In-Reply-To:References:Date:Message-ID:Subject: To:Cc:Content-Type; b=W36Zv8e9e7qweUz7O2LaLW7ubuCjXBCzIOpa6joIOGW/YCfEYOo476Adxyi/sAqiaxR3rHmQFFc8LGkX0APLothzXn/ck8RKf6GCA/jd/Pv8Nj/6hd4VS0e+Eu0E9sIY0NogMJUt4FaEXwThCQ5KTLjXia+xpMgrutkJmjQF4UI= ARC-Authentication-Results: i=2; 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=Q+DYJZhG; arc=pass smtp.client-ip=209.85.208.41 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="Q+DYJZhG" Received: by mail-ed1-f41.google.com with SMTP id 4fb4d7f45d1cf-6a5e329c0f2so1703180a12.3 for ; Wed, 26 Aug 2026 14:39:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787780394; cv=none; d=google.com; s=arc-20260327; b=TSaWQaQbGBCXwRq4aOXEB7XKBPO+xd4rAj/sNSWLATauDCmqFORjwBYfFJOXdO7FxK USf4eizUf1GTjJ/Dva3p9K3eG/6JZhwOQV5WLH5JpoeCHScae1hykdyac3JY8m8UBFY/ tFjy45Q8NsFdQ1T47vmnNSM9zkd3Ap8qUrpuJ9XSmFxKcWLprKY7fg1g7T0Y7KRMU0J5 sOVijVNqX7HAWDwZj5RgMUsIRBvVoZLU7vfAID3Oq7whYJnAF/vHPBXmORRPsl0QJc8A I36tHmVq3OzJwfnp3PF69IM/29hszneb2kqyUdptJ9yE2VZK73t0L3vM0vkvjiBhpxv0 0u6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:references:in-reply-to:mime-version :from:dkim-signature; bh=OdE2tE4SZovbK921ryjtFVs/TiWS2M8qf75lm4EcWdQ=; fh=TBZF2Qm5cebEeJ3TkvD66xd4JnbDdbvVcTqO/dJOH0A=; b=i53oZOTsiKLMmHl2r8xXrZHv1jWLHdpJxFDyN41IxeZsk1NtqthfqSncR6xU74JHO/ TsBUg2ZL+nfoRIH2p1vH2hSLTq70oyuXzidzB2Q81y47xeVNu4dtVohV3RcChWtUyJuT zuaJWLu3MVwUe22UqtWh9B51NqrWDk43QcxJN2ERnRXY4gr62PnlKGQG2afPXY2QqfBh ulZm3m+GHoH+A994tbiOLWzZQ2DdV4G3Izwgf14cupIYoONIuEywSvaxnU+JMaCrwYz7 9hcHZ9bS/dyOrr0DuBWWqxnbDdHdm8TRWnHtFhV+Nc2F5O/eMXpi37jKfPaReXCGDDA8 FWXw==; darn=vger.kernel.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787780394; x=1788385194; darn=vger.kernel.org; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=OdE2tE4SZovbK921ryjtFVs/TiWS2M8qf75lm4EcWdQ=; b=Q+DYJZhG8R6WgRuubhPFRz1MurQVpUdlZDrN6/msUgIj8SWVIiMKKyJx99objbhVBX 1/O6I4YRcxtQA3ylvUVOBKUCm/O9nC+WLIk5gbwfIIJ2TF8Yt+Xi9Ws+EMFe880USeiY J9TkgrYqUzCkuRjW9BNWSOP3IHEb6WByaWg2WIKw8FlxKdhQHqRz5Vm+ryfb/V6B8sUi adr+UZET5JFItH+sujzvVEB8B9vKZN4PD0FPGPsFECWR8X2JsCdZzzrkWbV3h94tr8C1 e++q10YU94GIyJmP292f+rXF1FrzFIg7N3HQVkvKsU+ijB48qv6O/H/6YzEZn96qSqFc p31w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787780394; x=1788385194; h=content-type:cc:to:subject:message-id:date:references:in-reply-to :mime-version:from:x-gm-gg:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to:content-type; bh=OdE2tE4SZovbK921ryjtFVs/TiWS2M8qf75lm4EcWdQ=; b=mj+TweAr/MJeGKtwDzBAZcVj973kYSgiFyWMrDFrsEp+4JBGbdzGREUCmzvn+Azize bUM0tOzuvHilICGLQxO5w/8z3tFI6KD2rVRztdpEKsHoNYtQGPxrPowJZBuIIvmPU+Dz jCzsK1tBd0P9aBM8ouBLw9dYOiyQr6Q2KpPw2gpH9d41Wuwwv+24ry2SdPRmaZCxUDUY 7lspG7Hq6GCrOHSyEtAYsa45dyAodiF2wbiLKc82Vq5Ggz5sEEsxmBL2HmJIYrz+raG+ xQUAQHtNnZayO2UFt2Cfj+AhKiBIo6Fkm5OUpZRss3hOAnhxaB1IA6cLOfca3G1FlmRD 5FPA== X-Forwarded-Encrypted: i=1; AHgh+RpaPlKVfzDpj/bisO7cHrVIkhD+7wMxVBxOVioN8jVlR4lvmLUBGGtHn/ySfajGVRifMHD+lODrPDql5NA=@vger.kernel.org X-Gm-Message-State: AFuF++nkC6c6sEhNyubXiqmGLC4UFDMPWt63V6UpFQ1hCC2aOgHNkr+A 7lmlP3bNFKl6SDg6VtlrVYMjXR5Wxodgr+Y6I5+M5PCo8aNcnVkFT7OyjgpY27LCCRPEjsCLk3g Y819pRNWkyVCY9l7yy9iZlMOxwhJe5m3lKfJmfoA= X-Gm-Gg: AR+sD13QHarykN2mEY+2rWX1jbhPaHXxquyafo9LLtdTdB8YIzwnrsn5tAgGQB2Igtf N2cBGTRjy+ZKBg5dyILBAoq7L/u5bTf3AmF5vXFDCE9zhdwfY+F5NkceuEhuOwg6BNrBZPbL1DO AKJ7jZjgM6piwktNmoltnFQiLP79zHmjPaIpun+9PXqqyV4JIIRG7oCajIUURSuuwozGPqVH4FA gJaqYCUztem8ZuSpxiSRVOc+L2uWHe6G1WqpR72mprwvrJ/njQ0wFQlbwYaAwYYwe2ILL032bnZ gnX2Zo+X3KKpB/xk+JoXgStJGckTNKDA1Y0g33VIxDlUjcVuPDF3rQ9Z7Oovqdqg3osoZ0l72O9 1 X-Received: by 2002:a05:6402:504d:b0:6a5:d6b5:cf80 with SMTP id 4fb4d7f45d1cf-6a5df62099amr12557395a12.11.1787780393640; Wed, 26 Aug 2026 14:39:53 -0700 (PDT) Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:52 -0500 Received: from 637551599889 named unknown by gmailapi.google.com with HTTPREST; Wed, 26 Aug 2026 16:39:52 -0500 From: Xinping Zhang Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In-Reply-To: References: Date: Wed, 26 Aug 2026 16:39:52 -0500 X-Gm-Features: AcwNN1UjKRqo2AqQlvvf01g0D71uwgUFZX0PGdW4Pee1BMpqjid7-3LsLlmYLs4 Message-ID: Subject: [PATCH 5/5] f2fs: describe inode node layout dynamically To: linux-f2fs-devel@lists.sourceforge.net Cc: jaegeuk@kernel.org, chao@kernel.org, linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" An inode node block ends with its five i_nid entries followed by the node footer. Because the i_addr array spans all preceding space, the offset of i_nid depends on the filesystem block size. Describe f2fs_inode and the direct and indirect node types with maximum-size arrays, then calculate the locations of i_nid and the node footer from the actual filesystem block size. Replace all direct accesses to those tail fields with F2FS_INODE_NIDS() and F2FS_NODE_FOOTER(). Keep the former i_nid and footer declarations as comments documenting the exact on-disk layout. This is a layout-only cleanup while the filesystem block size is still fixed; the following change makes the helpers use the runtime geometry. Signed-off-by: Kelvin Zhang --- fs/f2fs/data.c | 2 +- fs/f2fs/f2fs.h | 30 ++++++++++++++++------- fs/f2fs/gc.c | 2 +- fs/f2fs/inline.c | 3 +-- fs/f2fs/inode.c | 5 ++-- fs/f2fs/node.c | 4 +--- fs/f2fs/node.h | 53 +++++++++++++++++++---------------------- fs/f2fs/super.c | 2 ++ include/linux/f2fs_fs.h | 26 +++++++++++++++----- 9 files changed, 74 insertions(+), 53 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6ae0eb37d20f..751b7a457d9a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2027,7 +2027,7 @@ static int f2fs_xattr_fiemap(struct inode *inode, phys =3D F2FS_BLK_TO_BYTES(ni.blk_addr); offset =3D offsetof(struct f2fs_inode, i_addr) + - sizeof(__le32) * (DEF_ADDRS_PER_INODE - + sizeof(__le32) * (DEF_ADDRS_PER_INODE_SBI(sbi) - get_inline_xattr_addrs(inode)); phys +=3D offset; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 026419aed2e9..1413aa7acc09 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1851,6 +1851,7 @@ struct f2fs_sb_info { unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ unsigned int blocksize; /* block size */ + unsigned int addrs_per_inode; /* addresses in an inode block */ unsigned int sit_entries_per_block; /* SIT entries in a block */ unsigned int orphans_per_block; /* orphan inodes in a block */ unsigned int dentries_per_block; /* dentries in a block */ @@ -2244,6 +2245,7 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio) } #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block) +#define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode) #define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block) #define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \ F2FS_ORPHANS_PER_BLOCK(sbi)) @@ -2293,6 +2295,12 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi) return (struct f2fs_checkpoint *)(sbi->ckpt); } +static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *fol= io) +{ + return folio_address(folio) + F2FS_BLKSIZE - + sizeof(struct node_footer); +} + static inline struct f2fs_node *F2FS_NODE(const struct folio *folio) { return (struct f2fs_node *)folio_address(folio); @@ -2303,6 +2311,12 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio) return &((struct f2fs_node *)folio_address(folio))->i; } +static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio) +{ + return folio_address(folio) + F2FS_BLKSIZE - sizeof(struct node_footer) - + SIZE_OF_I_NID; +} + static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi) { return (struct f2fs_nm_info *)(sbi->nm_info); @@ -3273,13 +3287,11 @@ static inline void f2fs_radix_tree_insert(struct radix_tree_root *root, cond_resched(); } -#define RAW_IS_INODE(p) ((p)->footer.nid =3D=3D (p)->footer.ino) - static inline bool IS_INODE(const struct folio *folio) { - struct f2fs_node *p =3D F2FS_NODE(folio); + struct node_footer *footer =3D F2FS_NODE_FOOTER(folio); - return RAW_IS_INODE(p); + return footer->nid =3D=3D footer->ino; } static inline int offset_in_addr(struct f2fs_inode *i) @@ -3288,9 +3300,11 @@ static inline int offset_in_addr(struct f2fs_inode *= i) (le16_to_cpu(i->i_extra_isize) / sizeof(__le32)) : 0; } -static inline __le32 *blkaddr_in_node(struct f2fs_node *node) +static inline __le32 *blkaddr_in_node(const struct folio *folio) { - return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr; + struct f2fs_node *node =3D F2FS_NODE(folio); + + return IS_INODE(folio) ? node->i.i_addr : node->dn.addr; } static inline int f2fs_has_extra_attr(struct inode *inode); @@ -3307,7 +3321,7 @@ static inline unsigned int get_dnode_base(struct inode *inode, static inline __le32 *get_dnode_addr(struct inode *inode, struct folio *node_folio) { - return blkaddr_in_node(F2FS_NODE(node_folio)) + + return blkaddr_in_node(node_folio) + get_dnode_base(inode, node_folio); } @@ -3635,7 +3649,7 @@ void *inline_xattr_addr(struct inode *inode, const struct folio *folio) { struct f2fs_inode *ri =3D F2FS_INODE(folio); - return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE - + return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE_SBI(F2FS_I_SB(inode)) - get_inline_xattr_addrs(inode)]); } diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 0c17038fcfd7..666acf9d528a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1176,7 +1176,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, if (IS_INODE(node_folio)) { base =3D offset_in_addr(F2FS_INODE(node_folio)); - max_addrs =3D DEF_ADDRS_PER_INODE; + max_addrs =3D DEF_ADDRS_PER_INODE_SBI(sbi); } else { base =3D 0; max_addrs =3D DEF_ADDRS_PER_BLOCK; diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 718dd785865a..73cd9b6ddcc5 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -36,14 +36,13 @@ bool f2fs_may_inline_data(struct inode *inode) static bool inode_has_blocks(struct inode *inode, struct folio *ifolio) { - struct f2fs_inode *ri =3D F2FS_INODE(ifolio); int i; if (F2FS_HAS_BLOCKS(inode)) return true; for (i =3D 0; i < DEF_NIDS_PER_INODE; i++) { - if (ri->i_nid[i]) + if (F2FS_INODE_NIDS(ifolio)[i]) return true; } return false; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index bac1e360d966..046cc21547eb 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -150,9 +150,8 @@ bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio) static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *fol= io) { - struct f2fs_node *node =3D F2FS_NODE(folio); - struct f2fs_inode *ri =3D &node->i; - __le32 ino =3D node->footer.ino; + struct f2fs_inode *ri =3D F2FS_INODE(folio); + __le32 ino =3D F2FS_NODE_FOOTER(folio)->ino; __le32 gen =3D ri->i_generation; __u32 chksum, chksum_seed; __u32 dummy_cs =3D 0; diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 968e5ed38816..3c8bb24e68b6 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -2993,7 +2993,6 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio) int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum) { - struct f2fs_node *rn; struct f2fs_summary *sum_entry; block_t addr; int i, idx, last_offset, nrpages; @@ -3015,8 +3014,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sb= i, if (IS_ERR(folio)) return PTR_ERR(folio); - rn =3D F2FS_NODE(folio); - sum_entry->nid =3D rn->footer.nid; + sum_entry->nid =3D F2FS_NODE_FOOTER(folio)->nid; sum_entry->version =3D 0; sum_entry->ofs_in_node =3D 0; sum_entry++; diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 5e114f352099..6e0097486e9b 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -242,73 +242,68 @@ static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid) static inline nid_t ino_of_node(const struct folio *node_folio) { - struct f2fs_node *rn =3D F2FS_NODE(node_folio); - return le32_to_cpu(rn->footer.ino); + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->ino); } static inline nid_t nid_of_node(const struct folio *node_folio) { - struct f2fs_node *rn =3D F2FS_NODE(node_folio); - return le32_to_cpu(rn->footer.nid); + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->nid); } static inline unsigned int ofs_of_node(const struct folio *node_folio) { - struct f2fs_node *rn =3D F2FS_NODE(node_folio); - unsigned flag =3D le32_to_cpu(rn->footer.flag); + unsigned int flag =3D le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->flag); return flag >> OFFSET_BIT_SHIFT; } static inline __u64 cpver_of_node(const struct folio *node_folio) { - struct f2fs_node *rn =3D F2FS_NODE(node_folio); - return le64_to_cpu(rn->footer.cp_ver); + return le64_to_cpu(F2FS_NODE_FOOTER(node_folio)->cp_ver); } static inline block_t next_blkaddr_of_node(const struct folio *node_folio) { - struct f2fs_node *rn =3D F2FS_NODE(node_folio); - return le32_to_cpu(rn->footer.next_blkaddr); + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->next_blkaddr); } static inline void fill_node_footer(const struct folio *folio, nid_t nid, nid_t ino, unsigned int ofs, bool reset) { struct f2fs_node *rn =3D F2FS_NODE(folio); + struct node_footer *footer =3D F2FS_NODE_FOOTER(folio); unsigned int old_flag =3D 0; if (reset) - memset(rn, 0, sizeof(*rn)); + memset(rn, 0, F2FS_BLKSIZE); else - old_flag =3D le32_to_cpu(rn->footer.flag); + old_flag =3D le32_to_cpu(footer->flag); - rn->footer.nid =3D cpu_to_le32(nid); - rn->footer.ino =3D cpu_to_le32(ino); + footer->nid =3D cpu_to_le32(nid); + footer->ino =3D cpu_to_le32(ino); /* should remain old flag bits such as COLD_BIT_SHIFT */ - rn->footer.flag =3D cpu_to_le32((ofs << OFFSET_BIT_SHIFT) | + footer->flag =3D cpu_to_le32((ofs << OFFSET_BIT_SHIFT) | (old_flag & OFFSET_BIT_MASK)); } static inline void copy_node_footer(const struct folio *dst, const struct folio *src) { - struct f2fs_node *src_rn =3D F2FS_NODE(src); - struct f2fs_node *dst_rn =3D F2FS_NODE(dst); - memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer)); + memcpy(F2FS_NODE_FOOTER(dst), F2FS_NODE_FOOTER(src), + sizeof(struct node_footer)); } static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr) { struct f2fs_checkpoint *ckpt =3D F2FS_CKPT(F2FS_F_SB(folio)); - struct f2fs_node *rn =3D F2FS_NODE(folio); + struct node_footer *footer =3D F2FS_NODE_FOOTER(folio); __u64 cp_ver =3D cur_cp_version(ckpt); if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) cp_ver |=3D (cur_cp_crc(ckpt) << 32); - rn->footer.cp_ver =3D cpu_to_le64(cp_ver); - rn->footer.next_blkaddr =3D cpu_to_le32(blkaddr); + footer->cp_ver =3D cpu_to_le64(cp_ver); + footer->next_blkaddr =3D cpu_to_le32(blkaddr); } static inline bool is_recoverable_dnode(const struct folio *folio) @@ -368,11 +363,12 @@ static inline bool IS_DNODE(const struct folio *node_folio) static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i) { struct f2fs_node *rn =3D F2FS_NODE(folio); + __le32 *inode_nids =3D F2FS_INODE_NIDS(folio); f2fs_folio_wait_writeback(folio, NODE, true, true); if (i) - rn->i.i_nid[off - NODE_DIR1_BLOCK] =3D cpu_to_le32(nid); + inode_nids[off - NODE_DIR1_BLOCK] =3D cpu_to_le32(nid); else rn->in.nid[off] =3D cpu_to_le32(nid); return folio_mark_dirty(folio); @@ -381,9 +377,10 @@ static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i) static inline nid_t get_nid(const struct folio *folio, int off, bool i) { struct f2fs_node *rn =3D F2FS_NODE(folio); + const __le32 *inode_nids =3D F2FS_INODE_NIDS(folio); if (i) - return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); + return le32_to_cpu(inode_nids[off - NODE_DIR1_BLOCK]); return le32_to_cpu(rn->in.nid[off]); } @@ -396,8 +393,7 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i) static inline int is_node(const struct folio *folio, int type) { - struct f2fs_node *rn =3D F2FS_NODE(folio); - return le32_to_cpu(rn->footer.flag) & BIT(type); + return le32_to_cpu(F2FS_NODE_FOOTER(folio)->flag) & BIT(type); } #define is_cold_node(folio) is_node(folio, COLD_BIT_SHIFT) @@ -406,14 +402,13 @@ static inline int is_node(const struct folio *folio, int type) static inline void __set_mark(const struct folio *folio, bool mark, int ty= pe) { - struct f2fs_node *rn =3D F2FS_NODE(folio); - unsigned int flag =3D le32_to_cpu(rn->footer.flag); - + struct node_footer *footer =3D F2FS_NODE_FOOTER(folio); + unsigned int flag =3D le32_to_cpu(footer->flag); if (mark) flag |=3D BIT(type); else flag &=3D ~BIT(type); - rn->footer.flag =3D cpu_to_le32(flag); + footer->flag =3D cpu_to_le32(flag); } static inline void set_cold_node(const struct folio *folio, bool is_dir) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 133c279b9931..1f6dcb890eab 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4348,6 +4348,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi) le32_to_cpu(raw_super->log_sectors_per_block); sbi->log_blocksize =3D le32_to_cpu(raw_super->log_blocksize); sbi->blocksize =3D BIT(sbi->log_blocksize); + sbi->addrs_per_inode =3D (sbi->blocksize - OFFSET_OF_END_OF_I_EXT - + SIZE_OF_I_NID - sizeof(struct node_footer)) / sizeof(__le32); sbi->sit_entries_per_block =3D sbi->blocksize / sizeof(struct f2fs_sit_entry); sbi->orphans_per_block =3D (sbi->blocksize - diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index b4bb4e2f99b3..34c19bcd50e3 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -16,6 +16,7 @@ #define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */ #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */ #define F2FS_BLKSIZE PAGE_SIZE /* support only block =3D=3D page */ +#define F2FS_MAX_BLKSIZE PAGE_SIZE #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ #define F2FS_EXTENSION_LEN 8 /* max size of extension */ @@ -343,18 +344,25 @@ struct f2fs_inode { */ __le32 i_extra_end[0]; /* for attribute size calculation */ } __packed; - __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ + __le32 i_addr[]; /* data block pointers */ }; - __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2), - double_indirect(1) node id */ + /* + * __le32 i_nid[DEF_NIDS_PER_INODE]; + * + * It is stored immediately before the node footer at the end of the + * filesystem block. Its offset depends on the filesystem block size, so + * locate it dynamically with F2FS_INODE_NIDS(). + */ } __packed; struct direct_node { - __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */ + __le32 addr[(F2FS_MAX_BLKSIZE - sizeof(struct node_footer)) / + sizeof(__le32)]; /* array of data block address */ } __packed; struct indirect_node { - __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */ + __le32 nid[(F2FS_MAX_BLKSIZE - sizeof(struct node_footer)) / + sizeof(__le32)]; /* array of data block address */ } __packed; enum { @@ -373,7 +381,13 @@ struct f2fs_node { struct direct_node dn; struct indirect_node in; }; - struct node_footer footer; + /* + * struct node_footer footer; + * + * It is stored at the end of the filesystem block, after the inode or + * direct/indirect node data. Its offset depends on the filesystem block + * size, so locate it dynamically with F2FS_NODE_FOOTER(). + */ } __packed; /* --=20 2.53.0