Skip to content

Commit 6592287

Browse files
committed
hfs: fix incorrect inode ID assignment in hfs_new_inode()
The xfstests' test-case generic/003 reveals the HFS volume corruption: sudo ./check generic/003 FSTYP -- hfs PLATFORM -- Linux/x86_64 hfsplus-testing-0001 7.0.0-rc1+ #18 SMP PREEMPT_DYNAMIC Fri Mar 13 17:54:19 PDT 2026 MKFS_OPTIONS -- /dev/loop51 MOUNT_OPTIONS -- /dev/loop51 /mnt/scratch generic/003 51s ... _check_generic_filesystem: filesystem on /dev/loop51 is inconsistent sudo fsck.hfs -d /dev/loop51 ** /dev/loop51 Using cacheBlockSize=32K cacheTotalBlock=1024 cacheSize=32768K. Executing fsck_hfs (version 540.1-Linux). ** Checking HFS volume. The volume name is untitled ** Checking extents overflow file. ** Checking catalog file. ** Checking catalog hierarchy. ** Checking volume bitmap. ** Checking volume information. invalid MDB drNxtCNID Master Directory Block needs minor repair (1, 0) Verify Status: VIStat = 0x8000, ABTStat = 0x0000 EBTStat = 0x0000 CBTStat = 0x0000 CatStat = 0x00000000 ** Repairing volume. ** Rechecking volume. ** Checking HFS volume. The volume name is untitled ** Checking extents overflow file. ** Checking catalog file. ** Checking catalog hierarchy. ** Checking volume bitmap. ** Checking volume information. ** The volume untitled was repaired successfully. The reason of corruption is incorrect value of drNxtCNID (next CNID) in the MDB or superblock. The generic/003 test-case creates several new inodes: kernel: run fstests generic/003 hfs: hfs_mdb_get():179 next_id 16 hfs: hfs_mdb_get():179 next_id 16 hfs: hfs_new_inode():208 next_id 17 hfs: hfs_new_inode():208 next_id 18 hfs: hfs_mdb_commit():307 next_id 18 hfs: hfs_mdb_get():179 next_id 18 hfs: hfs_new_inode():208 next_id 19 hfs: hfs_new_inode():208 next_id 20 hfs_mdb_commit():307 next_id 20 hfs: hfs_mdb_get():179 next_id 20 hfs: hfs_new_inode():208 next_id 21 hfs: hfs_mdb_commit():307 next_id 21 hfs: hfs_mdb_get():179 next_id 21 The final assigned CNID was 21 but fsck correct it on 22. It is possible to see that the reason of the issue is incrementing the next_id value at first and assigning already incremented value to the inode->i_ino: struct inode *hfs_new_inode(...) { <skipped> next_id = atomic64_inc_return(&HFS_SB(sb)->next_id); <skipped> inode->i_ino = (u32)next_id; <skipped> } This patch fixes the issue by assigning the decremented value to inode->i_ino. Fixes: a06ec28 ("hfs: add logic of correcting a next unused CNID") cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> cc: Yangtao Li <frank.li@vivo.com> cc: linux-fsdevel@vger.kernel.org Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com> Link: https://lore.kernel.org/r/20260514195518.354108-2-slava@dubeyko.com Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
1 parent 4b04964 commit 6592287

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

fs/hfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t
204204
pr_err("cannot create new inode: next CNID exceeds limit\n");
205205
goto out_discard;
206206
}
207-
inode->i_ino = (u32)next_id;
207+
inode->i_ino = (u32)next_id - 1;
208208
inode->i_mode = mode;
209209
inode->i_uid = current_fsuid();
210210
inode->i_gid = current_fsgid();

0 commit comments

Comments
 (0)