mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ali Ahmet Memis <ali@iusegentoo.com>
To: Alexander Viro <viro@zeniv.linux.org.uk>,
	Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
Subject: [PATCH 06/10] ufs: fix fragment relocation offsets within a folio
Date: Sat,  1 Aug 2026 22:55:26 +0000	[thread overview]
Message-ID: <20260801225530.148386-7-ali@iusegentoo.com> (raw)
In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com>

ufs_change_blocknr() walks the buffers covering the fragments being
moved from oldb to newb. Inside a folio it starts at the buffer holding
the first fragment:

	pos = i & mask;
	for (j = 0; j < pos; ++j)
		bh = bh->b_this_page;

so j is a buffer index within the folio, not an offset into the range
being relocated. The body then uses it as if it were one:

	pos = (i - beg) + j;

On the first folio i equals beg, so pos comes out as beg & mask where it
should be zero. Every fragment is then shifted by that amount, both the
source it is read from, oldb + pos, and the destination recorded in
bh->b_blocknr, newb + pos. The tail of the relocation ends up past the
end of the new allocation, which is only count fragments long, leaving
dirty buffers pointing at fragments that can belong to another file or
to metadata. Later folios start folio aligned and are unaffected.

Reaching it needs a page larger than the filesystem block. beg is the
start of the existing tail and so is always a multiple of fs_frag, while
mask is blks_per_page - 1. When PAGE_SIZE is at most fs_bsize the two
are powers of two with fs_frag the larger, beg & mask is zero and
nothing goes wrong. ufs_fill_super() already refuses fs_bsize below
4096, so every 4 KiB page system is in that case. A 16 KiB or 64 KiB
page kernel, as used on arm64 and ppc64, mounting a filesystem with a
smaller block is not.

Keep the starting buffer index and subtract it, so pos counts from the
start of the relocated range again.

Reproduced on an arm64 64 KiB page kernel with a 4096/512 UFS1
filesystem, where a block is 8 fragments and blks_per_page is 128. A
file with a one fragment tail in its second block has beg 8, so
beg & mask is 8. Filling the fragments that physically follow that tail
and then extending the file forces the relocation:

  ufs: RELOC: beg=8 count=1 oldb=1457 newb=1528 mask=127 beg&mask=8

Before this patch the first byte of the relocated tail reads back as 0
instead of the written data; after it the file compares equal. The same
test on a 4 KiB page kernel never gets beg & mask nonzero, as expected.

Fixes: 5431bf97ce69 ("[PATCH] ufs: prepare write + change blocks on the fly")
Cc: stable@vger.kernel.org
Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com>
---
 fs/ufs/balloc.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 628edfde3a9f..f617df64c45b 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -241,7 +241,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
 	const unsigned mask = blks_per_page - 1;
 	struct address_space * const mapping = inode->i_mapping;
 	pgoff_t index, cur_index, last_index;
-	unsigned pos, j, lblock;
+	unsigned int pos, j, lblock, first;
 	sector_t end, i;
 	struct buffer_head *head, *bh;
 
@@ -272,8 +272,8 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
 
 		head = folio_buffers(folio);
 		bh = head;
-		pos = i & mask;
-		for (j = 0; j < pos; ++j)
+		first = i & mask;
+		for (j = 0; j < first; ++j)
 			bh = bh->b_this_page;
 
 		if (unlikely(index == last_index))
@@ -284,7 +284,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg,
 		do {
 			if (j >= lblock)
 				break;
-			pos = (i - beg) + j;
+			pos = (i - beg) + (j - first);
 
 			if (!buffer_mapped(bh))
 					map_bh(bh, inode->i_sb, oldb + pos);
-- 
2.55.0


  parent reply	other threads:[~2026-08-01 22:56 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-01 22:55 [PATCH 00/10] ufs: correctness fixes for valid on-disk filesystems Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 01/10] ufs: name the modern UFS2 superblock fields Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 02/10] ufs: use i_size to detect fast symlinks Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 03/10] ufs: free UFS2 external attribute blocks on inode deletion Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 04/10] ufs: do not inherit file flags from the parent directory Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 05/10] ufs: honour on-disk immutable and append-only flags Ali Ahmet Memis
2026-08-01 22:55 ` Ali Ahmet Memis [this message]
2026-08-01 22:55 ` [PATCH 07/10] ufs: revalidate filesystem state before remounting read-write Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 08/10] ufs: refuse read-write mount when fsck or journal replay is needed Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 09/10] ufs: refuse read-write mount of filesystems with active snapshots Ali Ahmet Memis
2026-08-01 22:55 ` [PATCH 10/10] ufs: refuse read-write mount of check-hashed filesystems Ali Ahmet Memis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260801225530.148386-7-ali@iusegentoo.com \
    --to=ali@iusegentoo.com \
    --cc=brauner@kernel.org \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®