From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 B407D386450; Sat, 1 Aug 2026 22:56:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624994; cv=pass; b=Fhhy4mmuR7N6vupajkVhy+2Du8J+X//VcWZUZ35sZRpwse1kKWWc4GXkIHVUzFDtGp4YJNVpZqeBUXta9/K1GUxsbfpKVAbIuM/eGG9LIaeLq2drEb3B245ByR6g/pmYvtTV05TdAeRymjgAej+hRFVF9C4q14+txtRP6WQ7Au8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624994; c=relaxed/simple; bh=/NoyGdJ9moH/axh6d3ycP6BhBtVeLPCfJmdyuh5IoXE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZnIhbid+vZS2qv2BLZWcsX7dhm19uM+G6t2YnGn9usxONCUJEqu8PVgrnERw2xwq5kkhtrkvr/844LEqfTzIU0coP3MckB+YId8eL49uZ72tEC+wz74IBXjLSq4jMZJ6OzyLBOgoXHHT4lFvQvLR925A2Ar77tlkG6i9mKTabG0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=qFEpNcFx; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="qFEpNcFx" ARC-Seal: i=1; a=rsa-sha256; t=1785624968; cv=none; d=zohomail.eu; s=zohoarc; b=HFPkMPVzyfalcf6x7As5reKcu9PwOhCHf3RSg1W2ctprKtX4wChU9HD73MKvEUPbukCVbmXQaQeUPzYCEwBBCe8ue0scOGKZTLF6b54+Dt4oZr/l7oPg0vdBrsvkr3DMCsKKgbbOwJ+0iXQNtbe4J1fMInrA6d2465YC1GR1qks= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624968; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=Ko2TnwIe3lyl7C9oAsBcfzPhCKT0Je6i14RhDjnEQXI=; b=GCHlbWzZ4eYg3ELqb6lWUxwOiDv+UkBP9uHNpAdtmfzqyu6PK+iHQdCOO0/xR7iohpzvJhmKYhVBVvDbAJJ6BHtot0saK1b9oi61KWwmsdw/DmlRUHtAJomXuRliL6Lt/O1g2e9dls45Z266ZU5j5PLqbmBClLq4an2vmVUExoE= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624968; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=Ko2TnwIe3lyl7C9oAsBcfzPhCKT0Je6i14RhDjnEQXI=; b=qFEpNcFxg+zeDWbW04F8H8F5VkaYgQXbKy5YhdFCshV0Nqdu5ZChBFbDebWKyBik jBx+BGDjqwxeSyP5mEyMTd0khpDkeXo5dKXzjz8VaYOsnwJnQJhF68iJQ4/G/OMVvyv T7kenweyWhsAadGYCeQ70KfvinSYuv1LOq/ryETw= Received: by mx.zoho.eu with SMTPS id 1785624965764458.8001401329035; Sun, 2 Aug 2026 00:56:05 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 01/10] ufs: name the modern UFS2 superblock fields Date: Sat, 1 Aug 2026 22:55:21 +0000 Message-ID: <20260801225530.148386-2-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" The 4.4BSD derived superblock that UFS2 uses has grown a number of fields since Linux last looked at it. All of them currently sit inside fs_44.fs_sparecon[50], so nothing in fs/ufs can tell that a filesystem uses snapshots, soft updates journalling or metadata check hashes. Split fs_sparecon[] into the fields FreeBSD defines, counting from fs_pendinginodes: fs_snapinum[20], fs_avgfilesize, fs_avgfpdir, fs_available_spare, fs_mtime, fs_sujfree, 21 remaining spare words, fs_ckhash, fs_metackhash and the 32 bit fs_flags, followed by the already named fs_contigsumsize. That is exactly 50 words, so the layout does not change; sizeof(struct ufs_super_block_third) stays 356 and fs_contigsumsize stays at offset 292. The 8 bit fs_flags next to fs_clean is a different field, FreeBSD's fs_old_flags. Rename it accordingly so the two cannot be confused. It has no users. Add the UFS_FS_* values for the 32 bit fs_flags and UFS_FSMAXSNAP. No functional change; later patches use these. Signed-off-by: Ali Ahmet Memis --- fs/ufs/ufs_fs.h | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/fs/ufs/ufs_fs.h b/fs/ufs/ufs_fs.h index b8dc354ae90f..32925c356fa2 100644 --- a/fs/ufs/ufs_fs.h +++ b/fs/ufs/ufs_fs.h @@ -154,6 +154,26 @@ typedef __u16 __bitwise __fs16; #define UFS_FSLOG ((__s8)0xfd) /* logging fs */ #define UFS_FSFIX ((__s8)0xfc) /* being repaired while mounted */ =20 +/* maximum number of snapshots recorded in fs_snapinum */ +#define UFS_FSMAXSNAP 20 + +/* + * Values for the 32 bit fs_flags of the modern (4.4BSD derived) superbloc= k. + * Not to be confused with the historic 8 bit fs_old_flags. + */ +#define UFS_FS_UNCLEAN 0x00000001 +#define UFS_FS_DOSOFTDEP 0x00000002 +#define UFS_FS_NEEDSFSCK 0x00000004 +#define UFS_FS_SUJ 0x00000008 +#define UFS_FS_ACLS 0x00000010 +#define UFS_FS_MULTILABEL 0x00000020 +#define UFS_FS_GJOURNAL 0x00000040 +#define UFS_FS_FLAGS_UPDATED 0x00000080 +#define UFS_FS_NFS4ACLS 0x00000100 +#define UFS_FS_METACKHASH 0x00000200 +#define UFS_FS_TRIM 0x00000400 +#define UFS_FS_INDEXDIRS 0x01000000 + /* From here to next blank line, s_flags for ufs_sb_info */ /* directory entry encoding */ #define UFS_DE_MASK 0x00000010 /* mask for the following */ @@ -865,7 +885,7 @@ struct ufs_super_block_first { __s8 fs_fmod; __s8 fs_clean; __s8 fs_ronly; - __s8 fs_flags; + __s8 fs_old_flags; __s8 fs_fsmnt[UFS_MAXMNTLEN - 212]; =20 }; @@ -937,7 +957,16 @@ struct ufs_super_block_third { __fs32 fs_qfmask[2]; /* ~usb_fmask */ } fs_sunx86; struct { - __fs32 fs_sparecon[50];/* reserved for future constants */ + __fs32 fs_snapinum[UFS_FSMAXSNAP];/* snapshot inode numbers */ + __fs32 fs_avgfilesize; /* expected average file size */ + __fs32 fs_avgfpdir; /* expected # of files per directory */ + __fs32 fs_available_spare;/* old scratch space */ + __fs32 fs_mtime[2]; /* last mount or fsck time */ + __fs32 fs_sujfree; /* SUJ free list */ + __fs32 fs_sparecon[21];/* reserved for future constants */ + __fs32 fs_ckhash; /* if CK_SUPERBLOCK, its check-hash */ + __fs32 fs_metackhash; /* metadata check-hash, see CK_ */ + __fs32 fs_flags; /* see UFS_FS_* above */ __fs32 fs_contigsumsize;/* size of cluster summary array */ __fs32 fs_maxsymlinklen;/* max length of an internal symlink */ __fs32 fs_inodefmt; /* format of on-disk inodes */ --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 3A84C3955CD; Sat, 1 Aug 2026 22:56:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624997; cv=pass; b=fbKlGFcLr0DP87bYN7NgaQOGY7XkZc3uVCEqpZ/NppCrNImq/5Eoi3VxqryzQ7y/IW7UcPB3czODrdviTnCl/0i1OY0CIGAH3t3NzhbgTlvfjWaHXlwpSot6gmDUZmR0nqsA+BCxJTigbFx9EjwiE1GMUOIly0Yj3AWuLDRaByQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624997; c=relaxed/simple; bh=6NYd6in0rzVfgUh8gjPpc/kYd9uu5M96agV9tYIQgcM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AdefJBvwz8/S40CjbzxgynfhGaB8PD774ccPO1Q+O8EHIFPY8ua1ZdwXQdGLZFw0BIB+pI52UWKbiWEVy7HylZiJIPxgy1Sxek9Aft86sJsNtpcK+yqNoL/sRQnqYQHWepA+3sjC9HgD6sMPcr61KuRChs0Bzm0sHEevYDVHk7M= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=SBA37Rrx; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="SBA37Rrx" ARC-Seal: i=1; a=rsa-sha256; t=1785624969; cv=none; d=zohomail.eu; s=zohoarc; b=R8N92I0M+ViE86cxahige+4EwK/EjPC4yApsIndD5VhvdvsLWTJ8wB69Jxb+98HxHCkqjWuYO/OaB7GR7JVWHq+4Eoh5DbgBcu4bctYfkhSblzkQluROuZ98CCjWwbEerEfGbKiHES4Oee7zK0p/r2G6KAyXf0h5L/Nb+Ma3hMY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624969; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=KJceAGSvicSHI55BXIH/luGROGrl7VGF+MQRV7iaMTM=; b=OvknFy9cD6ljgO90HnIGJVmRYxK5qmakrkolRCuz9+6tZBWvCap1XliTjEgYAqLW7+NI357/8frUHaWUGezROuuyglRyIchGSd35fO/GIs4Dkk9AppKLC9OAwDxQQHq2OcLAlJK4wRQsOT9YzznKFqwaf0O0raiXszL0qoKEkaE= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624969; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=KJceAGSvicSHI55BXIH/luGROGrl7VGF+MQRV7iaMTM=; b=SBA37RrxmBlaXuFChukkvMl3N7eOufWGZZNntjS2n55cCjSfsFc+Cq2YhvJPA3ai UO5oILxWw4IZIxk8CyloqzIoc7xieT210Uh/+vgIUL0VV6Z8Twr5BRPtCP9bGZs1KF2 TnDK6+rmDdTZhAx1NZH5KkOtMkB+i+GRs7kccLPM= Received: by mx.zoho.eu with SMTPS id 1785624966606460.58651198992493; Sun, 2 Aug 2026 00:56:06 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 02/10] ufs: use i_size to detect fast symlinks Date: Sat, 1 Aug 2026 22:55:22 +0000 Message-ID: <20260801225530.148386-3-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Whether a symlink stores its target inline is decided by testing i_blocks =3D=3D 0. The on-disk criterion is i_size < fs_maxsymlinklen; FreeBSD's ufs_readlink() and ufs_symlink() both use it, and our own ufs_symlink() already checks s_maxsymlinklen on the write side. The two disagree on UFS2 inodes with extended attributes. ffs_alloc() adds every allocation to di_blocks, including the IO_EXT path, so a symlink carrying an extended attribute, an ACL or a MAC label has di_blocks !=3D 0 while its target is still stored inline. Linux then takes it for a slow symlink. readlink() reads the target through ufs_getfrag_block(), treating the ASCII bytes of the target as block pointers. On a read-write mount unlinking it reaches ufs_truncate_blocks() from ufs_evict_inode(), which hands the same bytes to ufs_free_fragments() as block numbers. Values built from printable characters fall outside the device, so this ends in ufs_panic() with the inode already modified. Add ufs_is_fast_symlink() and use it in the read, write and evict paths. In ufs_evict_inode() it has to run before i_size is cleared. Flavours that leave s_maxsymlinklen at 0 keep the old i_blocks heuristic, so only 44BSD and UFS2 change behaviour. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Ali Ahmet Memis --- fs/ufs/inode.c | 54 +++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 440d014cc5ed..802bc6e01db2 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -517,6 +517,17 @@ const struct address_space_operations ufs_aops =3D { .bmap =3D ufs_bmap }; =20 +// on-disk criterion is i_size < fs_maxsymlinklen, not i_blocks +static bool ufs_is_fast_symlink(struct inode *inode) +{ + struct ufs_sb_private_info *uspi =3D UFS_SB(inode->i_sb)->s_uspi; + + if (uspi->s_maxsymlinklen) + return inode->i_size < uspi->s_maxsymlinklen; + + return inode->i_blocks =3D=3D 0; +} + static void ufs_set_inode_ops(struct inode *inode) { if (S_ISREG(inode->i_mode)) { @@ -528,7 +539,7 @@ static void ufs_set_inode_ops(struct inode *inode) inode->i_fop =3D &ufs_dir_operations; inode->i_mapping->a_ops =3D &ufs_aops; } else if (S_ISLNK(inode->i_mode)) { - if (!inode->i_blocks) { + if (ufs_is_fast_symlink(inode)) { inode->i_link =3D (char *)UFS_I(inode)->i_u1.i_symlink; inode->i_op =3D &simple_symlink_inode_operations; } else { @@ -578,13 +589,13 @@ static int ufs1_read_inode(struct inode *inode, struc= t ufs_inode *ufs_inode) ufsi->i_oeftflag =3D fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); =20 =20 - if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { - memcpy(ufsi->i_u1.i_data, &ufs_inode->ui_u2.ui_addr, - sizeof(ufs_inode->ui_u2.ui_addr)); - } else { + if (S_ISLNK(mode) && ufs_is_fast_symlink(inode)) { memcpy(ufsi->i_u1.i_symlink, ufs_inode->ui_u2.ui_symlink, sizeof(ufs_inode->ui_u2.ui_symlink) - 1); ufsi->i_u1.i_symlink[sizeof(ufs_inode->ui_u2.ui_symlink) - 1] =3D 0; + } else { + memcpy(ufsi->i_u1.i_data, &ufs_inode->ui_u2.ui_addr, + sizeof(ufs_inode->ui_u2.ui_addr)); } return 0; } @@ -625,13 +636,13 @@ static int ufs2_read_inode(struct inode *inode, struc= t ufs2_inode *ufs2_inode) ufsi->i_oeftflag =3D fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); */ =20 - if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { - memcpy(ufsi->i_u1.u2_i_data, &ufs2_inode->ui_u2.ui_addr, - sizeof(ufs2_inode->ui_u2.ui_addr)); - } else { + if (S_ISLNK(mode) && ufs_is_fast_symlink(inode)) { memcpy(ufsi->i_u1.i_symlink, ufs2_inode->ui_u2.ui_symlink, sizeof(ufs2_inode->ui_u2.ui_symlink) - 1); ufsi->i_u1.i_symlink[sizeof(ufs2_inode->ui_u2.ui_symlink) - 1] =3D 0; + } else { + memcpy(ufsi->i_u1.u2_i_data, &ufs2_inode->ui_u2.ui_addr, + sizeof(ufs2_inode->ui_u2.ui_addr)); } return 0; } @@ -731,13 +742,12 @@ static void ufs1_update_inode(struct inode *inode, st= ruct ufs_inode *ufs_inode) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { /* ufs_inode->ui_u2.ui_addr.ui_db[0] =3D cpu_to_fs32(sb, inode->i_rdev);= */ ufs_inode->ui_u2.ui_addr.ui_db[0] =3D ufsi->i_u1.i_data[0]; - } else if (inode->i_blocks) { - memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.i_data, - sizeof(ufs_inode->ui_u2.ui_addr)); - } - else { + } else if (S_ISLNK(inode->i_mode) && ufs_is_fast_symlink(inode)) { memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink, sizeof(ufs_inode->ui_u2.ui_symlink)); + } else { + memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.i_data, + sizeof(ufs_inode->ui_u2.ui_addr)); } =20 if (!inode->i_nlink) @@ -774,13 +784,13 @@ static void ufs2_update_inode(struct inode *inode, st= ruct ufs2_inode *ufs_inode) if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { /* ufs_inode->ui_u2.ui_addr.ui_db[0] =3D cpu_to_fs32(sb, inode->i_rdev);= */ ufs_inode->ui_u2.ui_addr.ui_db[0] =3D ufsi->i_u1.u2_i_data[0]; - } else if (inode->i_blocks) { - memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.u2_i_data, - sizeof(ufs_inode->ui_u2.ui_addr)); - } else { + } else if (S_ISLNK(inode->i_mode) && ufs_is_fast_symlink(inode)) { memcpy(&ufs_inode->ui_u2.ui_symlink, ufsi->i_u1.i_symlink, sizeof(ufs_inode->ui_u2.ui_symlink)); - } + } else { + memcpy(&ufs_inode->ui_u2.ui_addr, ufsi->i_u1.u2_i_data, + sizeof(ufs_inode->ui_u2.ui_addr)); + } =20 if (!inode->i_nlink) memset (ufs_inode, 0, sizeof(struct ufs2_inode)); @@ -839,14 +849,18 @@ int ufs_sync_inode (struct inode *inode) void ufs_evict_inode(struct inode * inode) { int want_delete =3D 0; + bool fast_symlink; =20 if (!inode->i_nlink && !is_bad_inode(inode)) want_delete =3D 1; =20 + // must be evaluated before i_size is cleared below + fast_symlink =3D S_ISLNK(inode->i_mode) && ufs_is_fast_symlink(inode); + truncate_inode_pages_final(&inode->i_data); if (want_delete) { inode->i_size =3D 0; - if (inode->i_blocks && + if (inode->i_blocks && !fast_symlink && (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) ufs_truncate_blocks(inode); --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 B38ED3859C2; Sat, 1 Aug 2026 22:56:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624994; cv=pass; b=mo93BZKgfXEE55A3EOxI4UFYpRbybhNZJss/OqVZ1arT9YeTiUkQbdvc/+hQpnxaAVoLwrGpIKw4m/QvNhP9v92jNwwT38W27lmTZICSksiwibNLi0OtPlNqLCCS0cFgitZgRA/9eAenpHHYJbGo4dWBmq2LHj7fNhwVWhLJgeY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624994; c=relaxed/simple; bh=B5qx66ga9t+tzyzyQzw/g4F5wGoX2yCKJ/Ebtec5eto=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ncNxjD3ALSvtMkLJ+NitIKtx55gLOlUkIZ/zxnf59YlSz+DuyDxKZmsceDI7H2T+qQypHCiBVMUQYFg1w90WJpHRlLepZn9sKY7G5JrFmfF5P5NwkaCAHT0+uV7msh0ui8q5moswaHaUD7cJh5I7666pKyCCfXE+LIjVN4h21iA= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=NLtJ7Msn; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="NLtJ7Msn" ARC-Seal: i=1; a=rsa-sha256; t=1785624969; cv=none; d=zohomail.eu; s=zohoarc; b=ZhnDD4nNfSbTb3tEuXXdsvdKm0eFX5jowtc1aFMnargHxB1gy+RM42EBEaaJaS/WOZsLZ3lSdJ0yVr4CImN/l0TA2/XSc/zWcdoza3z+3rkGfExIDUNuM/6xiQVpayriI8+aWXpNm24tl42jtnOLeOliFZllqG92V64/QirpCMg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624969; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=+yIzktvg7jzlKW2ywu6nga4OYqtDSuEi2C9eSFYa+h0=; b=TgkOq4iYLp8sC3aqdjbSr8Q7ajkwFNpuX8khXdfN5v99nJSsUlKpMGCSAXlEnbrNCrc8mqxn6SX3uw7D5CjO/Q5KwBRyDqxWBQv6CDnONr1FxGqgr53JGPmHQHNgCNLI1DMJRXv67sIydnOU8aGxbf67Sv+EE/8574uaJt3mAYo= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624969; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=+yIzktvg7jzlKW2ywu6nga4OYqtDSuEi2C9eSFYa+h0=; b=NLtJ7MsnEnm3k8cD4ponZ8nPSszXRKED/xLZ8nXorT7tyssJMR2onjTvOs0x8QsD 6ke1VhZRHzBExPwGNC/l69jWFvgD+CerzgRj2nGC031dQQfV6lD5yUW5upUNsy5HUHr hfV5NC9SPYrnOEZ+2ygd/619OcSCSpUDHRtZtKb0= Received: by mx.zoho.eu with SMTPS id 1785624967356866.9833602936747; Sun, 2 Aug 2026 00:56:07 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 03/10] ufs: free UFS2 external attribute blocks on inode deletion Date: Sat, 1 Aug 2026 22:55:23 +0000 Message-ID: <20260801225530.148386-4-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" A UFS2 inode can own up to UFS_NXADDR blocks holding extended attributes, described by di_extsize and di_extb[]. They sit outside the block tree of the file, but ffs_alloc() counts them in di_blocks like any other allocation. Linux never reads those two fields. ufs_truncate_blocks() only walks di_db[] and di_ib[], so on unlink the extattr blocks stay marked in use while ufs_update_inode() clears the whole on-disk inode, di_extb[] included. The only record of where the blocks were is gone, and nothing can ever free them. Deleting FreeBSD files that carry an extended attribute, an ACL or a MAC label therefore leaks disk space until fsck reclaims it. Keep di_extsize and di_extb[] in the in-core inode and release them from ufs_evict_inode(), before the on-disk inode is cleared. The last block of the area can be a fragment, so size it the way FreeBSD's sblksize() does rather than assuming a full block. An external attribute size larger than the area can describe means the inode is corrupted and the block numbers cannot be trusted. Warn and leave the blocks alone in that case; leaking them is better than freeing blocks that may belong to something else. Signed-off-by: Ali Ahmet Memis --- fs/ufs/ialloc.c | 2 ++ fs/ufs/inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/ufs/ufs.h | 2 ++ 3 files changed, 59 insertions(+) diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 8e51f4630d18..4c3c76c4e7ff 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -294,6 +294,8 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t = mode) inode->i_generation =3D 0; simple_inode_init_ts(inode); ufsi->i_flags =3D UFS_I(dir)->i_flags; + ufsi->i_extsize =3D 0; + memset(ufsi->i_extb, 0, sizeof(ufsi->i_extb)); ufsi->i_lastfrag =3D 0; ufsi->i_shadow =3D 0; ufsi->i_osync =3D 0; diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 802bc6e01db2..7079285bac2a 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -585,6 +585,8 @@ static int ufs1_read_inode(struct inode *inode, struct = ufs_inode *ufs_inode) inode->i_blocks =3D fs32_to_cpu(sb, ufs_inode->ui_blocks); inode->i_generation =3D fs32_to_cpu(sb, ufs_inode->ui_gen); ufsi->i_flags =3D fs32_to_cpu(sb, ufs_inode->ui_flags); + ufsi->i_extsize =3D 0; + memset(ufsi->i_extb, 0, sizeof(ufsi->i_extb)); ufsi->i_shadow =3D fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); ufsi->i_oeftflag =3D fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); =20 @@ -605,6 +607,7 @@ static int ufs2_read_inode(struct inode *inode, struct = ufs2_inode *ufs2_inode) struct ufs_inode_info *ufsi =3D UFS_I(inode); struct super_block *sb =3D inode->i_sb; umode_t mode; + unsigned int i; =20 UFSD("Reading ufs2 inode, ino %llu\n", inode->i_ino); /* @@ -631,6 +634,9 @@ static int ufs2_read_inode(struct inode *inode, struct = ufs2_inode *ufs2_inode) inode->i_blocks =3D fs64_to_cpu(sb, ufs2_inode->ui_blocks); inode->i_generation =3D fs32_to_cpu(sb, ufs2_inode->ui_gen); ufsi->i_flags =3D fs32_to_cpu(sb, ufs2_inode->ui_flags); + ufsi->i_extsize =3D fs32_to_cpu(sb, ufs2_inode->ui_extsize); + for (i =3D 0; i < UFS_NXADDR; i++) + ufsi->i_extb[i] =3D fs64_to_cpu(sb, ufs2_inode->ui_extb[i]); /* ufsi->i_shadow =3D fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); ufsi->i_oeftflag =3D fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); @@ -846,6 +852,54 @@ int ufs_sync_inode (struct inode *inode) return ufs_update_inode (inode, 1); } =20 +/* + * UFS2 keeps extended attributes in up to UFS_NXADDR blocks of their own. + * They live outside the block tree of the file but are counted in di_bloc= ks. + * Linux does not implement extended attributes, but it still has to relea= se + * those blocks when the inode goes away: ufs_update_inode() clears the wh= ole + * on-disk inode, taking di_extb[] with it, so nothing would ever free the= m. + */ +static void ufs_free_ext_blocks(struct inode *inode) +{ + struct super_block *sb =3D inode->i_sb; + struct ufs_sb_private_info *uspi =3D UFS_SB(sb)->s_uspi; + struct ufs_inode_info *ufsi =3D UFS_I(inode); + u64 size =3D ufsi->i_extsize; + unsigned int i; + + if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) !=3D UFS_TYPE_UFS2 || !size) + return; + + if (size > ((u64)UFS_NXADDR << uspi->s_bshift)) { + // leaking is better than freeing something we cannot locate + ufs_warning(sb, __func__, + "inode %llu: bad external attribute size %llu\n", + inode->i_ino, size); + return; + } + + for (i =3D 0; i < UFS_NXADDR; i++) { + u64 off =3D (u64)i << uspi->s_bshift; + u64 block =3D ufsi->i_extb[i]; + unsigned int frags; + + if (!block || size <=3D off) + continue; + + if (size - off >=3D uspi->s_bsize) + frags =3D uspi->s_fpb; + else + frags =3D (size - off + uspi->s_fsize - 1) >> uspi->s_fshift; + + ufsi->i_extb[i] =3D 0; + if (frags =3D=3D uspi->s_fpb) + ufs_free_blocks(inode, block, frags); + else + ufs_free_fragments(inode, block, frags); + } + ufsi->i_extsize =3D 0; +} + void ufs_evict_inode(struct inode * inode) { int want_delete =3D 0; @@ -864,6 +918,7 @@ void ufs_evict_inode(struct inode * inode) (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) ufs_truncate_blocks(inode); + ufs_free_ext_blocks(inode); ufs_update_inode(inode, inode_needs_sync(inode)); } =20 diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 788e025056b2..6cac5f8222eb 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -40,6 +40,8 @@ struct ufs_inode_info { __fs64 u2_i_data[15]; } i_u1; __u32 i_flags; + __u32 i_extsize; /* UFS2 external attribute area size */ + __u64 i_extb[UFS_NXADDR]; /* UFS2 external attribute blocks */ __u32 i_shadow; __u32 i_unused1; __u32 i_unused2; --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 3CC143955F5; Sat, 1 Aug 2026 22:56:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624996; cv=pass; b=V9xq/jJsvFWtpuGcSRxfmIc/Qrc8XMKCZuKK2Ppdxgg6RpiAg5Vj0beLilSMffiFFMlhKj77LzmJr5v05YFvbKNlL9GpPguoSNE8z90SbCQ29hHf6WUXR4Rj2S9J0GhodFciyPmGv4hL80n+9vglshhpYy8rILN5Tcsrl3efggI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624996; c=relaxed/simple; bh=Q7dj7BQprXlnZbjS0SsRoqo1cWqGisRdNcocbERTD7Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KqzXNExJWDLUv/AENdZ1WhRQPaMTlBqhw/wNF49wAhl0GGLXl8JCoVhZ0gCLCc5SBBYfh72udpi2f7Y6Yy6Bwcjr5DSGnd+zqJeAc+DWYo0BSbxKTXB5nRf7fSX8glhZ7+lUqSItiCyMa7E6NVb1cDCNnS67mSMySVgx5e2D9SU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=YPEbllBh; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="YPEbllBh" ARC-Seal: i=1; a=rsa-sha256; t=1785624970; cv=none; d=zohomail.eu; s=zohoarc; b=iTszdlM8eB8EaxMOs+QUd+Gh6tjj9ChUNHUeHNoQCzhopZyfKxDeX2GBtHMgtmv35gfX/2wYawzCDUw8uKyb7pGIPILFd8l2YXVe0uMl5Wj2dPA45JfeW8GCbWUs5py7Kh4LukTBXkNPeiB2Hp+OTN8esgppcID9m0o9EuYAFN4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624970; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=viKdxApTKU/QG20WA2d1bHFxKpleUTdUSspfk9OhC+8=; b=GvPkGn0SESeB8rOfTnwSLlZIDWmh/Hk6AghpPRN8GiV8wdgXRPLtselQ2jHzWXZclOl5Pz3nrGNWHdE2tVuWPwc2z8D6Bgg4DMs90DvSBqMwfQbJ054GhlwVF9i2NBrMrnY25qjxvgvIfYQ4Y6tlVdpNgpGLQrlU7KdlETa4v8o= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624970; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=viKdxApTKU/QG20WA2d1bHFxKpleUTdUSspfk9OhC+8=; b=YPEbllBhDooOgnj/IdbcPiL0LQ9VzseD7CmybI/KkK3XS1Fv/6pz9DHoE4jyHc3s gje4xUXWFdEJLjZiy3p+6xdoUX0Q/BkpmZLrj8sAPJAE1CGCWge4wrwn/rzbYZTBFIt RYm7YDxo0pebx/ol9MszSlzUw37PHWESwPki2pGs= Received: by mx.zoho.eu with SMTPS id 1785624968196832.0307099448886; Sun, 2 Aug 2026 00:56:08 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 04/10] ufs: do not inherit file flags from the parent directory Date: Sat, 1 Aug 2026 22:55:24 +0000 Message-ID: <20260801225530.148386-5-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" ufs_new_inode() starts a new inode off with the parent directory's on-disk flags: ufsi->i_flags =3D UFS_I(dir)->i_flags; These are BSD chflags, and they have no inheritance semantics. FreeBSD's ufs_makeinode() leaves di_flags at zero and only ever sets UF_OPAQUE, and only for a whiteout. The line comes from the ext2 code fs/ufs/ialloc.c was derived from, where the flags are Linux inode flags that do have an inherited subset. The result is that a file created on Linux inside a directory FreeBSD marked with chflags schg or sappnd is written out carrying SF_IMMUTABLE or SF_APPEND itself. Linux does not act on those bits, so nothing looks wrong at the time, but back on FreeBSD the new file is immutable or append-only and cannot be removed without lowering the securelevel. Nothing asked for that. Start new inodes with no flags set. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Ali Ahmet Memis --- fs/ufs/ialloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 4c3c76c4e7ff..dc3eeb415876 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -293,7 +293,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t = mode) inode->i_blocks =3D 0; inode->i_generation =3D 0; simple_inode_init_ts(inode); - ufsi->i_flags =3D UFS_I(dir)->i_flags; + ufsi->i_flags =3D 0; ufsi->i_extsize =3D 0; memset(ufsi->i_extb, 0, sizeof(ufsi->i_extb)); ufsi->i_lastfrag =3D 0; --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 E54A638AC79; Sat, 1 Aug 2026 22:56:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624995; cv=pass; b=m5iuYaxcQgrxKPEptx0MbxJlZIs92jA7WW3SQZ+47ANQEfiFpbsJLK0ekglmOS4z9fCcyA2TVrFTYMoBCiIBxw5v1rwSNY3ap+AWgUDSC00gTVKx8dzOJTC5+SzHifp81Vl7GVKdRUiDPj6GggmBpxtogglk8D9WoeNleaqQ8Sw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624995; c=relaxed/simple; bh=R4u7/bKEg9i84hjJCm4SMqcUG7IyauuWymJ28/yL+zM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GPd7N3fqyYdkdF0bKJjugf9jv6a+rYWsQjUHEwgDVR9z6eFH6zQbKpDoxj3BVh6a3sAmX1Yvvut9GKqgwBkBKSjPrC62WswOMNEff2zG5e8D2EExLU7i1UlALQnGPB+9QDlftkuAsL8JZybjckNSaenvU4iDmDIZjAVl2jsb6b0= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=S9+k2A8n; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="S9+k2A8n" ARC-Seal: i=1; a=rsa-sha256; t=1785624970; cv=none; d=zohomail.eu; s=zohoarc; b=RZdVJJgD2yiF8tcsz5RLvTWXOfLu7B7U+bWcwNzmoXO67rDpdxJJecH628K1J3kSJAUq4DoGwblizF4D4dkQlT9KffzxGXprKffavmIUGUqcIpgFKFekbqpBRw3Qc6hjcwTHerkJPhjfH1v1cqp3iBn6BnabRAsg0eatB734IoQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624970; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=MF2VMMsgjFNzzRTYjvZAPgcacW+ZbpDTdl6P3sBfAcM=; b=gq8QGdevp5pjJZvNM1G0cF1bkVJq9dOAautp3WLXpoepAOd5lXDk8ZSnOp2+nOWgFsk7mdG5Qld+b4hCutr3+S9WYJiWtNDyeoCObAhYz5ev6B8d7llSiMn0jJ5fSQKcCpoUZTUwqOsSKO+pXMNY1rvVGQL1PQVbkIDcX5hMkGw= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624970; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=MF2VMMsgjFNzzRTYjvZAPgcacW+ZbpDTdl6P3sBfAcM=; b=S9+k2A8nssAfu3QZy9Oef+9TmsKaU8qyCyMG0rMvZIMNZar25LpcVufU6lDEPkh8 ifzb+6hiI93bfFv/zgfZuGv5bO1YQNlbJSQaSGf2e1a6ekHhrEEvyf5fZbcn2//7EoQ Gw+dZwd6qMc5k4FOTAIW2K5+txCdFFxuINlMsA0U= Received: by mx.zoho.eu with SMTPS id 17856249689741021.5164796163593; Sun, 2 Aug 2026 00:56:08 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 05/10] ufs: honour on-disk immutable and append-only flags Date: Sat, 1 Aug 2026 22:55:25 +0000 Message-ID: <20260801225530.148386-6-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" ui_flags holds the BSD chflags of the inode. ufs1_read_inode() and ufs2_read_inode() copy it into ufsi->i_flags and nothing else ever looks at it. In particular it never reaches inode->i_flags, so IS_IMMUTABLE() and IS_APPEND() are always false for a UFS inode. The check in ufs_truncate(), if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return -EPERM; can never fire, and neither can the generic ones in the VFS. A file that FreeBSD marked with chflags schg or uchg is therefore freely writable and removable once the filesystem is mounted on Linux, and an sappnd file can be rewritten rather than only appended to. Map the immutable and append-only bits onto S_IMMUTABLE and S_APPEND when the inode is read. Only 44BSD and UFS2 are handled: the other flavours put something else at that offset and their ui_flags is not a chflags word. NOUNLINK has no equivalent in inode->i_flags. Mapping it to S_IMMUTABLE would be wrong, since it is meant to allow modification, so files marked that way stay removable for now. Note that Linux offers no way to clear these flags again; UFS has no FS_IOC_SETFLAGS support. Filesystems carrying them have to be edited from an operating system that implements chflags. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Ali Ahmet Memis --- fs/ufs/inode.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 7079285bac2a..029f6771b214 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -517,6 +517,22 @@ const struct address_space_operations ufs_aops =3D { .bmap =3D ufs_bmap }; =20 +// only 44BSD and UFS2 store BSD chflags in ui_flags +static void ufs_set_inode_flags(struct inode *inode) +{ + unsigned int flavour =3D UFS_SB(inode->i_sb)->s_flavour; + unsigned int flags =3D UFS_I(inode)->i_flags; + + if (flavour !=3D UFS_MOUNT_UFSTYPE_44BSD && + flavour !=3D UFS_MOUNT_UFSTYPE_UFS2) + return; + + if (flags & (UFS_UF_IMMUTABLE | UFS_SF_IMMUTABLE)) + inode->i_flags |=3D S_IMMUTABLE; + if (flags & (UFS_UF_APPEND | UFS_SF_APPEND)) + inode->i_flags |=3D S_APPEND; +} + // on-disk criterion is i_size < fs_maxsymlinklen, not i_blocks static bool ufs_is_fast_symlink(struct inode *inode) { @@ -704,6 +720,7 @@ struct inode *ufs_iget(struct super_block *sb, unsigned= long ino) ufsi->i_dir_start_lookup =3D 0; ufsi->i_osync =3D 0; =20 + ufs_set_inode_flags(inode); ufs_set_inode_ops(inode); =20 UFSD("EXIT\n"); --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o57.zoho.eu (sender-of-o57.zoho.eu [136.143.169.57]) (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 9C05E3D7D8D; Sat, 1 Aug 2026 22:56:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785625002; cv=pass; b=q2hVqZazmrO2SKjZ7vhdMgMJ+ChzSvOZY5fSlZ/pW+bukiMidJJ1p9ytNqMS8z+5NRmXgOkdSqIxcuLPfiQI3MiLSrYsV1agIND2Cif0uQrY0kcp4CZmaEnIhpm1seUE4TSY1VXuYcUb/m0IqbYo8ki4ugqF3dkI6wrdKrOT8Ac= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785625002; c=relaxed/simple; bh=XdkxGDfzSI7P6MMJk62hR0JJOfNVTLTtD0YeeEO23Cs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nfhp1IU099NLRzZCQMO3x/2CdgFbVR3bVZeJJrU9dFJAHL8uzkcQv8IiQpVY+2RCV2NdBJ9e3nWhKkVIoS5gVnyABDTFySCa9JvkcQjuxsN6CJDKpTLHZN10KIqgNevvCurSfxXvxxylWCFJ2aSTLVApgVMhm9cZDPoSep7Qe4Y= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=pNv5cwU9; arc=pass smtp.client-ip=136.143.169.57 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="pNv5cwU9" ARC-Seal: i=1; a=rsa-sha256; t=1785624971; cv=none; d=zohomail.eu; s=zohoarc; b=jt7sRDIDN01YmpNDQD2JZw3uk2DdwbrICvORWzJXdc2nNeYeU+9fOv+oqkyBAynjTAD97R996oq1NgvjlvNmNPMekuHu9SETwCyc6RFPxtft6X2o/Loyas5KiCaCkeEtiaw2slwLlEg8/XIMRBXkbrADnEAIPLYVHFAGYrSsN9c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624971; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=oPnFqlEANbkxNnysV+MSTA5NNFDMwBcEWEn1p+4Ko4s=; b=XWfwFvvZ/YNfeEAbIAcY5XvJhcnPag1k1jHe4BJWc6OyoaXePH+zkd3x0pPUolluPbtiiIwRFlYLWjqv/G4MdpXRexYFxgEw5Ux/ThSdyqnOmvvQBppngSbZArYdVQPjLxZfRU3hFxQUs0rftTEGKYhEQuSO1UMVAp+8aYRPvic= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624971; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=oPnFqlEANbkxNnysV+MSTA5NNFDMwBcEWEn1p+4Ko4s=; b=pNv5cwU9dUWyxx2DprP+0yhrDe+G2Q/p8T6ImYk6PP79vtlB6/wIA0NkPKbcFUBq oLwzChfbE5L+NnZfIDIW7NCBnSDvfqna+KWdGSceyD4cetVFDuQHPtvWEX8DL1urCZi 84E+vLknDDKz5OK6GXuRN2gGM7ZSae/5oVGYii5U= Received: by mx.zoho.eu with SMTPS id 1785624969818237.25911884847096; Sun, 2 Aug 2026 00:56:09 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , 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 Message-ID: <20260801225530.148386-7-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" 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 =3D i & mask; for (j =3D 0; j < pos; ++j) bh =3D 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 =3D (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=3D8 count=3D1 oldb=3D1457 newb=3D1528 mask=3D127 beg&mask= =3D8 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 --- 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, sec= tor_t beg, const unsigned mask =3D blks_per_page - 1; struct address_space * const mapping =3D 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; =20 @@ -272,8 +272,8 @@ static void ufs_change_blocknr(struct inode *inode, sec= tor_t beg, =20 head =3D folio_buffers(folio); bh =3D head; - pos =3D i & mask; - for (j =3D 0; j < pos; ++j) + first =3D i & mask; + for (j =3D 0; j < first; ++j) bh =3D bh->b_this_page; =20 if (unlikely(index =3D=3D last_index)) @@ -284,7 +284,7 @@ static void ufs_change_blocknr(struct inode *inode, sec= tor_t beg, do { if (j >=3D lblock) break; - pos =3D (i - beg) + j; + pos =3D (i - beg) + (j - first); =20 if (!buffer_mapped(bh)) map_bh(bh, inode->i_sb, oldb + pos); --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 3E26B3AE1A0; Sat, 1 Aug 2026 22:56:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624996; cv=pass; b=ccihFmWnW6aH87l0tGq8+0EMMWLttc+KLT8EI3t+GEcSPy8UygcbaQ/1Ge/o0I3ivcPhlWWHq/wqDZfQ/Qkh6poQVzkBmGJkOR7pIh6+BkjUXqOC+UurbRMaH8aJyHRFgHLSCa2fBaQq+9MdPCLNCjlbTyz++dwN7b9E/ovcFds= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624996; c=relaxed/simple; bh=ARELwG4smiQJY4RoGP2F62wyVT5EpvIEtT3QiSzanl0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=vEunlBHPDzfky133QTjp5KXKgXm5PGfFZsT46/nAYgbIFke5T4idJOBJJRWa2o0Sq/Slp0p6pZf74sWuFvZbjwGxbDakUPZfYwygdS9e6r5WLQeSw+yGCFZwFvlQ6oIszzWQ6qF0dNgebY/WlQRlvhJoS77TzZ8D825dViie5fc= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=krvQdEpy; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="krvQdEpy" ARC-Seal: i=1; a=rsa-sha256; t=1785624973; cv=none; d=zohomail.eu; s=zohoarc; b=XoIPaoTMNvGNTMQMlrBV+2OLfnn7wtHS0vgvYWqY+mpIg+kH2U2oAr7nYooWitYITCtTfLZA1rUHZvM8CC4P1hien0GBKkyprWeN658vs8DXixykZRlaoI/LUU5FTfJBi/YtxFjW0Br3N1mDocWG5h7e82Z+KaWc1vAcNdnKciw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624973; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=sZXXVA4cQF/3eoF04SvShy+8ExTKpzntj+7/qwKq35c=; b=F+qSyCXg+9yX+6bzasv6ExXbG2eKJaRlW9TFZa+lFZfJ9BmHIfOjQi+z475gjWfClCwxukyMzTmNxrcXMXlfb1WRPBLxnRo8tlFjHj/qCys1plDcD2G1V8UuiPHjME9FtpZoxRsMXYow4icioCnQXfWOUgZngses7uJWHkz0/1U= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624973; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=sZXXVA4cQF/3eoF04SvShy+8ExTKpzntj+7/qwKq35c=; b=krvQdEpy+7jMBqr7mX3TBri4ZyvonXkrwlX3RfdlH3pz62eiWXntmjMBw/caFP1E bEuZ8xZzMfkmgZeuaTciOxNRsGznNeh1Ll6b8GftKTwYMIDJsP28jpRBhsTFbaWIAdh 5BwKRQuDwplAYsj5LYi/1XwgjpYlV2imtwUB8PWU= Received: by mx.zoho.eu with SMTPS id 1785624970638779.209646431028; Sun, 2 Aug 2026 00:56:10 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 07/10] ufs: revalidate filesystem state before remounting read-write Date: Sat, 1 Aug 2026 22:55:27 +0000 Message-ID: <20260801225530.148386-8-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" ufs_fill_super() inspects fs_clean and, for the Solaris flavours, the state timestamp, and forces SB_RDONLY when the filesystem was not shut down cleanly. The remount path never repeats that work. Going from read-only to read-write only checks that the flavour has write support at all and that the cylinder groups can be read: if (!ufs_read_cylinder_structures(sb)) { ... } sb->s_flags &=3D ~SB_RDONLY; So the decision taken at mount time can simply be undone: mount -t ufs -o ufstype=3Dufs2,rw bad.img /mnt # forced read-only mount -o remount,rw /mnt # writable again touch /mnt/x A filesystem that is active, bad or in need of fsck becomes writable after all, which makes the check at mount time close to meaningless. Move the state test into ufs_state_allows_write() and call it from both places, returning -EROFS from the remount when it fails. Linux never writes fs_clean itself outside of the error paths, so the value the helper sees on remount is still the one that came off the disk. No change in which filesystems are accepted at mount time. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Ali Ahmet Memis --- fs/ufs/super.c | 95 +++++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index c4831a8b9b3f..4b0e9196fa41 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -713,6 +713,60 @@ static u64 ufs_max_bytes(struct super_block *sb) return res << uspi->s_bshift; } =20 +/* + * Does the recorded state of the filesystem allow us to write to it? + * Called both when mounting and when remounting read-write. + */ +static bool ufs_state_allows_write(struct super_block *sb) +{ + struct ufs_sb_private_info *uspi =3D UFS_SB(sb)->s_uspi; + struct ufs_super_block_first *usb1 =3D ubh_get_usb_first(uspi); + struct ufs_super_block_third *usb3 =3D ubh_get_usb_third(uspi); + + switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) { + case UFS_ST_44BSD: + case UFS_ST_OLD: + break; + case UFS_ST_SUN: + case UFS_ST_SUNOS: + case UFS_ST_SUNx86: + if (ufs_get_fs_state(sb, usb1, usb3) !=3D + UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)) { + pr_err("%s(): fs needs fsck\n", __func__); + return false; + } + break; + default: + pr_err("%s(): fs needs fsck\n", __func__); + return false; + } + + switch (usb1->fs_clean) { + case UFS_FSCLEAN: + UFSD("fs is clean\n"); + return true; + case UFS_FSSTABLE: + UFSD("fs is stable\n"); + return true; + case UFS_FSLOG: + UFSD("fs is logging fs\n"); + return true; + case UFS_FSOSF1: + UFSD("fs is DEC OSF/1\n"); + return true; + case UFS_FSACTIVE: + pr_err("%s(): fs is active\n", __func__); + return false; + case UFS_FSBAD: + pr_err("%s(): fs is bad\n", __func__); + return false; + default: + pr_err("%s(): can't grok fs_clean 0x%x\n", + __func__, usb1->fs_clean); + return false; + } +} + static int ufs_fill_super(struct super_block *sb, struct fs_context *fc) { struct ufs_fs_context *ctx =3D fc->fs_private; @@ -1049,43 +1103,8 @@ static int ufs_fill_super(struct super_block *sb, st= ruct fs_context *fc) * Check, if file system was correctly unmounted. * If not, make it read only. */ - if (((flags & UFS_ST_MASK) =3D=3D UFS_ST_44BSD) || - ((flags & UFS_ST_MASK) =3D=3D UFS_ST_OLD) || - (((flags & UFS_ST_MASK) =3D=3D UFS_ST_SUN || - (flags & UFS_ST_MASK) =3D=3D UFS_ST_SUNOS || - (flags & UFS_ST_MASK) =3D=3D UFS_ST_SUNx86) && - (ufs_get_fs_state(sb, usb1, usb3) =3D=3D (UFS_FSOK - fs32_to_cpu(sb, us= b1->fs_time))))) { - switch(usb1->fs_clean) { - case UFS_FSCLEAN: - UFSD("fs is clean\n"); - break; - case UFS_FSSTABLE: - UFSD("fs is stable\n"); - break; - case UFS_FSLOG: - UFSD("fs is logging fs\n"); - break; - case UFS_FSOSF1: - UFSD("fs is DEC OSF/1\n"); - break; - case UFS_FSACTIVE: - pr_err("%s(): fs is active\n", __func__); - sb->s_flags |=3D SB_RDONLY; - break; - case UFS_FSBAD: - pr_err("%s(): fs is bad\n", __func__); - sb->s_flags |=3D SB_RDONLY; - break; - default: - pr_err("%s(): can't grok fs_clean 0x%x\n", - __func__, usb1->fs_clean); - sb->s_flags |=3D SB_RDONLY; - break; - } - } else { - pr_err("%s(): fs needs fsck\n", __func__); + if (!ufs_state_allows_write(sb)) sb->s_flags |=3D SB_RDONLY; - } =20 /* * Read ufs_super_block into internal data structures @@ -1291,6 +1310,10 @@ static int ufs_reconfigure(struct fs_context *fc) mutex_unlock(&UFS_SB(sb)->s_lock); return -EINVAL; } + if (!ufs_state_allows_write(sb)) { + mutex_unlock(&UFS_SB(sb)->s_lock); + return -EROFS; + } if (!ufs_read_cylinder_structures(sb)) { pr_err("failed during remounting\n"); mutex_unlock(&UFS_SB(sb)->s_lock); --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 756153BFAD4; Sat, 1 Aug 2026 22:56:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624998; cv=pass; b=X+4v7yo6PYV23JcqTRZM7fdk3wKdYPOcyQQoadeC1NcfhfLdBtK8AQO6hsvGjApMeKKDuUQySuGcU3lEJJK3jF8/CJ0RvgVCZ21pvcNx9NaJTajDCivRZdREGKWbBd4ICEHeOKdj+G7KXouSH/ZsJ3P1B+GMZ+wNjy84pmDtFRw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624998; c=relaxed/simple; bh=6aYR/PtG6cnzRncR674UokAGDmIUKc2o1lWR65Jt/n4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HbR4KQegfZ+cHfv/7ZXHE9mFqGgo9A2DVyWzcoDvaUZuZp74Z+wGIP2rB65Te0JUP/LcJKfeBJAm7tZ1Sm1OM2+f0ASMs8T4EF7e4APpwftI/dn5QszR/WFFWj0CG7AR9FBzOEHUyZR9E4gYfeMzTcKSncYqqSlQvQec+LV4LQ4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=Bt7pLdlX; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="Bt7pLdlX" ARC-Seal: i=1; a=rsa-sha256; t=1785624974; cv=none; d=zohomail.eu; s=zohoarc; b=P1owJqSvQkJZlkz/Vl58ScdbEHvcCxLNEeZl+3XLuGyPm7CLefW5rjKHazt/hSNAxtUa/ee6onzvtv+7nZBLxRMuBHY0/vvs402OvvFYdBOq3eyFN2hSD6HsBHfCOSLrpoi2z2/iKEXRMhyj7K+Lj/obcuZvAFPZtbYuYMVEZlQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624974; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=wrd1BPWzTmr3/PZ0rIQk/dUqDEZiWESRgrvFaPrkgXQ=; b=RPmb7c4AnUA5OQHrBfbb7xNpNGEKKFkppF59e20gU4z+4bqpUd5dMFEw0NLy5/FT29rEgp95DAQUH/ZIoq0LH5OiLc8iE7m8x5pz9JSNrsEmHgwkb9dBrEOUAxrDSvB0++L1TR+QELliaBDC9b2umY5hsDNCd7p0CxYSGgyv4QU= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624974; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=wrd1BPWzTmr3/PZ0rIQk/dUqDEZiWESRgrvFaPrkgXQ=; b=Bt7pLdlXw/GSR3WHYyyFovWDe5ij6tA/153mw/N2fV/cce2iv9h/7HsW48lcLpuU 9A1xhBzTGbW2RA8MZ9tXBeCKUTh/Q84amV5IbsVSpSUYdHOI6CRLccEY3AlalIWlPRR g1tPHPTRQ3FPT3omgpAGJsA39MbtVmNCzvs4gsU4= Received: by mx.zoho.eu with SMTPS id 1785624971437922.1356418553123; Sun, 2 Aug 2026 00:56:11 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 08/10] ufs: refuse read-write mount when fsck or journal replay is needed Date: Sat, 1 Aug 2026 22:55:28 +0000 Message-ID: <20260801225530.148386-9-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" FS_NEEDSFSCK, FS_SUJ and FS_GJOURNAL live in the 32 bit fs_flags of the modern superblock, which Linux has never read. A UFS2 filesystem that FreeBSD marked as needing a foreground fsck, or that carries soft updates journalling or a GEOM journal, therefore mounts read-write here and is written to with the pending recovery work still outstanding. FreeBSD itself will not do this. ffs_mountfs() only accepts an unclean filesystem when neither flag is set: (fs->fs_flags & (FS_SUJ | FS_NEEDSFSCK)) =3D=3D 0 && (fs->fs_flags & FS_DOSOFTDEP) and otherwise refuses with "Filesystem is not clean - run fsck". Linux has no journal replay for either journal and no way to run the recovery, so the only safe thing it can do is stay read-only. Check the flags on mount and on remount read-write. Only UFS2 is examined. On older layouts the same offset is scratch space that may hold anything, and misreading it would wrongly refuse filesystems that are perfectly fine. Signed-off-by: Ali Ahmet Memis --- fs/ufs/super.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 4b0e9196fa41..df95502e039e 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -767,6 +767,34 @@ static bool ufs_state_allows_write(struct super_block = *sb) } } =20 +/* + * Refuse to write to a filesystem using features we do not implement. + * Only UFS2 is examined: the 32 bit fs_flags lives in the modern part of + * the superblock, which older layouts leave as scratch space. + */ +static bool ufs_features_allow_write(struct super_block *sb) +{ + struct ufs_sb_private_info *uspi =3D UFS_SB(sb)->s_uspi; + struct ufs_super_block_third *usb3 =3D ubh_get_usb_third(uspi); + u32 fsflags; + + if (uspi->fs_magic !=3D UFS2_MAGIC) + return true; + + fsflags =3D fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_flags); + + if (fsflags & UFS_FS_NEEDSFSCK) { + pr_err("%s(): fs is marked as needing fsck\n", __func__); + return false; + } + if (fsflags & (UFS_FS_SUJ | UFS_FS_GJOURNAL)) { + pr_err("%s(): journalled fs, journal replay is not supported\n", + __func__); + return false; + } + return true; +} + static int ufs_fill_super(struct super_block *sb, struct fs_context *fc) { struct ufs_fs_context *ctx =3D fc->fs_private; @@ -1103,7 +1131,7 @@ static int ufs_fill_super(struct super_block *sb, str= uct fs_context *fc) * Check, if file system was correctly unmounted. * If not, make it read only. */ - if (!ufs_state_allows_write(sb)) + if (!ufs_state_allows_write(sb) || !ufs_features_allow_write(sb)) sb->s_flags |=3D SB_RDONLY; =20 /* @@ -1310,7 +1338,8 @@ static int ufs_reconfigure(struct fs_context *fc) mutex_unlock(&UFS_SB(sb)->s_lock); return -EINVAL; } - if (!ufs_state_allows_write(sb)) { + if (!ufs_state_allows_write(sb) || + !ufs_features_allow_write(sb)) { mutex_unlock(&UFS_SB(sb)->s_lock); return -EROFS; } --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 7741D3BFAFA; Sat, 1 Aug 2026 22:56:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624997; cv=pass; b=PZRf5qoaXcvOk/4Q4Bdjik5EnnfAAvCJE4m2T2h23KQdx3dV9BFuwwRoz9uymXRh7qFNqa7whvAetgh2TNmWtfcmAZhbeOfUYgMOBygpk4XtsSvp8Xz6Y7Mxt7ehfU//6VJ7Pn0HHfUoHOPBCX+qIQADNx/5z73quRDlmbK3QV0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624997; c=relaxed/simple; bh=d1geiDUwKdYDEeo4Q9yzQSbg010Ij28kV8ydpJRb4hg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gi79TKydrCs2Mx8FP015kYMO6tg68StXzVbr0MQIQfuKWvvkv38qZEejUIT3NB+GhGsVrGuIdkWrbF3/PltaIyCoOSDoTkXNyctwYa3hA2YMZafyR5B5whpD7GL2AX43RXshE9t+LjHLLeASaTtaR4Ov7Co3uBMtPNL9F6qIQl4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=NmlXZZH6; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="NmlXZZH6" ARC-Seal: i=1; a=rsa-sha256; t=1785624974; cv=none; d=zohomail.eu; s=zohoarc; b=kYnKyOd72RO7oaJ3gwsbA3wZbJVVNBn6bTyf/rww5eaoSa/hkAJO/fto4qZTs2OUgeH2kw8A1QJdrr2pbAT+9oNzllNp1clJR1G3IJXGvFG6Q+R9S4byFkHRCqvbvS5Ofwk7l6EWNk7Z58IKzhw19gWHxVWIMXf5e7AzVBTOrM4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624974; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=PVaOx+p8YnrWRXBYpD2LawNTpt/9Sm/LDvB5QnWaisA=; b=UMVxTiQdo3WazkcmvSrCl0oEXg/4UiQAlWbKLO2WUjN+mVcznSgekRoN2n9NgllJpu9TZUVHSIgfItWm+9FAk0gnu0rbidz1+FppgzsAKGhFOTYoyXuTCt1QtQdWpPpmV/yHoS0PgsLz2JSSc70bTYHUjuwOlFVCegcClV1Lr5o= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624974; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=PVaOx+p8YnrWRXBYpD2LawNTpt/9Sm/LDvB5QnWaisA=; b=NmlXZZH6TPj4LzSIWijV3TUG+zXFPtn00xXj+o2pK9rbQrEyN6fnwStqOre5EOoS 1MR/3car7Q8USPifM1i1R3AVziqYPDAY4H9GkndpJtdvlWOpCMyahhKCC9hOpRhb5d5 hT0ard8kCyLZdzq2aZrwWCmPJo0iHxYp+ybIIdQw= Received: by mx.zoho.eu with SMTPS id 1785624972241544.0244080962553; Sun, 2 Aug 2026 00:56:12 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 09/10] ufs: refuse read-write mount of filesystems with active snapshots Date: Sat, 1 Aug 2026 22:55:29 +0000 Message-ID: <20260801225530.148386-10-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" A UFS2 filesystem can hold up to FSMAXSNAP snapshots, recorded in fs_snapinum[]. A snapshot is an inode whose block pointers describe the state of the filesystem at the moment it was taken, using the reserved values BLK_NOCOPY and BLK_SNAP alongside ordinary block numbers. Keeping one valid requires copy on write: before a block that the snapshot references is overwritten or freed, its old contents have to be copied into the snapshot. Linux implements none of this. It does not read fs_snapinum[], does not know the SF_SNAPSHOT inode flag, and treats the reserved block pointer values 1 and 2 as ordinary fragment addresses. Mounting such a filesystem read-write and changing a single file is enough for every snapshot on it to stop describing the point in time it was taken at, and there is no way to notice afterwards. Refuse the read-write mount while any snapshot is recorded. Read-only access is unaffected. Signed-off-by: Ali Ahmet Memis --- fs/ufs/super.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index df95502e039e..6132c28c4308 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -776,6 +776,7 @@ static bool ufs_features_allow_write(struct super_block= *sb) { struct ufs_sb_private_info *uspi =3D UFS_SB(sb)->s_uspi; struct ufs_super_block_third *usb3 =3D ubh_get_usb_third(uspi); + unsigned int i; u32 fsflags; =20 if (uspi->fs_magic !=3D UFS2_MAGIC) @@ -792,6 +793,12 @@ static bool ufs_features_allow_write(struct super_bloc= k *sb) __func__); return false; } + for (i =3D 0; i < UFS_FSMAXSNAP; i++) { + if (usb3->fs_un2.fs_44.fs_snapinum[i]) { + pr_err("%s(): fs has active snapshots\n", __func__); + return false; + } + } return true; } =20 --=20 2.55.0 From nobody Fri Oct 2 11:42:23 2026 Received: from sender-of-o58.zoho.eu (sender-of-o58.zoho.eu [136.143.169.58]) (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 73EDA3BFACC; Sat, 1 Aug 2026 22:56:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.169.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624997; cv=pass; b=uZrfKaOj7USuTYPr+/6b/WqUDdfpEUa7n1cCKGDopancB6rzKuTNti+gpPGW4Oq1mDGoyOEj4xOsydHn1fE2gLcjiaR2MlGfbwqtPTIOvr7zjDZvZPmtw8eS9V1drv41j6iSjEcrAclofmOLBXSUt4g9QSzRBmIUKwDkwLw2w7Y= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785624997; c=relaxed/simple; bh=CkrOf14Qi/QRj7G3amp5nZc7yDEUko522z1kVOiew8k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DnzKxYl5Mtc8lD2MX3/9BXtFiMEV3wkYZb9B3UJkOIoejoExL7st+oFXJ444mGlH1r37oUAXhHpw+O0GLzNIOtiAy/ZMnYrClUvl5Iym18AsKRDbDhZ+SmeRNNiJgRHv8GX+t1iieCL4QLhJvjqQZIA617G5ceRKh5gmEOzYl9s= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com; spf=pass smtp.mailfrom=iusegentoo.com; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b=Pezl9Myl; arc=pass smtp.client-ip=136.143.169.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iusegentoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=iusegentoo.com header.i=ali@iusegentoo.com header.b="Pezl9Myl" ARC-Seal: i=1; a=rsa-sha256; t=1785624975; cv=none; d=zohomail.eu; s=zohoarc; b=BNddOK6BWsVqCLMKT41L+TNQRq5PPJaZeb/YKsiywPRf2WFdKycBWEqAWe1UiLFbGRcNaIiNnXA9K6SAJNyFy7FaI3ST2WvvL8FAPpPz8hZS3I5GHyRxA323TCtoykbBeSLl3TG+kUNqtKz9WTP9COh/pKU9UpSRgShWnT4mzmI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.eu; s=zohoarc; t=1785624975; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:Subject:Subject:To:To:Message-Id:Reply-To; bh=wlluxfYC8YUM/sMEVN4s4A7dgNizPsQ2P60nHRuy2Pg=; b=kJRfevskGvcfc3a63xLcxlFe3zZZvAZRfwmkUeFSMuL82ctypnnt6WPfYzTGBK0SUPvcpDLjSx72wpL/mVA4lKz+luR3mc5H/YUrCx1Fa4yX0zmtdaaEHUdznC2loOj2e0usrtd+oBB+XUuwsOn53uzqHHiliAwWwz4go9rftx8= ARC-Authentication-Results: i=1; mx.zohomail.eu; dkim=pass header.i=iusegentoo.com; spf=pass smtp.mailfrom=ali@iusegentoo.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1785624975; s=zmail; d=iusegentoo.com; i=ali@iusegentoo.com; h=From:From:To:To:Cc:Cc:Subject:Subject:Date:Date:Message-ID:In-Reply-To:MIME-Version:Content-Transfer-Encoding:Message-Id:Reply-To; bh=wlluxfYC8YUM/sMEVN4s4A7dgNizPsQ2P60nHRuy2Pg=; b=Pezl9MylAA2oclOBZdnkru3chTX81i+zxWbbfsDsrzM1oA6fQ8OVxqv7ZCVqUBc8 i3XwFUy/ruq+rPL6/FfW39kBBb8gysmchgla7BCbTKkeQyibV7jWutsSYl4XERVy9GF nlCgMEjS61FYS+n7KCIuQneqDJ0clHiR1NBP7vLc= Received: by mx.zoho.eu with SMTPS id 178562497303091.11323045647384; Sun, 2 Aug 2026 00:56:13 +0200 (CEST) From: Ali Ahmet Memis To: Alexander Viro , Christian Brauner Cc: Jan Kara , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 10/10] ufs: refuse read-write mount of check-hashed filesystems Date: Sat, 1 Aug 2026 22:55:30 +0000 Message-ID: <20260801225530.148386-11-ali@iusegentoo.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260801225530.148386-1-ali@iusegentoo.com> References: <20260801225530.148386-1-ali@iusegentoo.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMailClient: External Content-Type: text/plain; charset="utf-8" Modern UFS2 protects metadata with check hashes. fs_metackhash says which kinds are in use, CK_SUPERBLOCK, CK_CYLGRP, CK_INODE, CK_INDIR and CK_DIR, and the hashes themselves live in fs_ckhash, cg_ckhash and di_ckhash. FreeBSD recomputes them on every metadata write, for inodes in ffs_update() right before the inode goes to disk, and treats a mismatch as an integrity failure. Linux knows about none of these fields. It happily allocates blocks, changes inodes and rewrites cylinder groups without touching a single hash, so an ordinary touch /mnt/x chmod 600 /mnt/x leaves the filesystem valid by its own rules but failing every check hash it advertises. Back on FreeBSD that surfaces as inode, cylinder group and superblock check-hash failures on a filesystem that was never damaged in any other way. Implementing the hashes is a lot more work than this series is doing, so stay read-only instead. Both the flag and a non-zero fs_metackhash are required, so a filesystem that advertises the feature without actually maintaining any hash is still writable. This does change what userspace can do with an existing image: modern FreeBSD enables check hashes by default, so filesystems that mount read-write today will start coming up read-only. That is the point, but it is a policy call rather than a plain bug fix, and it is the one patch here that could be dropped without affecting the rest. Signed-off-by: Ali Ahmet Memis --- fs/ufs/super.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 6132c28c4308..52de393aebe2 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -799,6 +799,11 @@ static bool ufs_features_allow_write(struct super_bloc= k *sb) return false; } } + if ((fsflags & UFS_FS_METACKHASH) && + fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_metackhash)) { + pr_err("%s(): fs uses metadata check hashes\n", __func__); + return false; + } return true; } =20 --=20 2.55.0