From a1735eae55448bc79c2da6593455791e886f6ed8 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 3 Jul 2026 01:07:19 +0900 Subject: nilfs2: reject invalid block index in GC ioctl Syzbot reported list corruption caused by a double list_add_tail() call on bh->b_assoc_buffers within nilfs_lookup_dirty_data_buffers(). Analysis revealed that the root cause was the insertion of a page/folio with a page index of ULONG_MAX into the page cache via the GC ioctl. filemap_get_folios_tag(), called by nilfs_lookup_dirty_data_buffers(), repeatedly detects a dirty folio with a page index of ULONG_MAX due to index wrap-around, leading to duplicate processing of dirty buffers. As a preparatory step, the GC ioctl loads the page/folio of the block to be moved during GC and inserts it into the page cache based on information in the nilfs_vdesc structure passed as an argument. Normally, this does not cause issues because the user-space GC library configures the nilfs_vdesc structure properly. However, since there is no range check on the parameters determining the page index, a request with artificially crafted parameters -- such as those generated by Syzbot -- can result in a page/folio being inserted with a page index of ULONG_MAX, triggering the above problem. This resolves the issue by checking the ranges of 'vd_offset' and 'vd_vblocknr' in the nilfs_vdesc structure that determine the page index, thereby preventing the invalid page/folio insertions. Reported-by: syzbot+c37bed40868932d790e9@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=c37bed40868932d790e9 Fixes: 7942b919f732 ("nilfs2: ioctl operations") Cc: wuyankun Cc: stable@vger.kernel.org Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/ioctl.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index b73f2c5d10f0..0957316e58b8 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -527,6 +527,7 @@ static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, * Return: 0 on success, or one of the following negative error codes on * failure: * * %-EEXIST - Block conflict detected. + * * %-EINVAL - Invalid virtual block descriptor. * * %-EIO - I/O error. * * %-ENOENT - Requested block doesn't exist. * * %-ENOMEM - Insufficient memory available. @@ -536,15 +537,30 @@ static int nilfs_ioctl_move_inode_block(struct inode *inode, struct list_head *buffers) { struct buffer_head *bh; + __u64 limit_blkidx = (__u64)inode->i_sb->s_maxbytes >> inode->i_blkbits; int ret; - if (vdesc->vd_flags == 0) + /* + * vblocknr 0 is reserved as an invalid pointer. Also, limit_blkidx + * ensures that the page index converted from vd_vblocknr never + * overflows the page cache limit and respects the architecture's bmap + * key width. + */ + if (unlikely(vdesc->vd_vblocknr == 0 || + vdesc->vd_vblocknr >= limit_blkidx)) + return -EINVAL; + + if (vdesc->vd_flags == 0) { + if (unlikely(vdesc->vd_offset >= limit_blkidx)) + return -EINVAL; + ret = nilfs_gccache_submit_read_data( inode, vdesc->vd_offset, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh); - else + } else { ret = nilfs_gccache_submit_read_node( inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh); + } if (unlikely(ret < 0)) { if (ret == -ENOENT) -- cgit v1.2.3 From 74504945c3f653660b25780f9110c4f4be4abc75 Mon Sep 17 00:00:00 2001 From: Igor Putko Date: Tue, 7 Jul 2026 16:59:41 +0900 Subject: nilfs2: handle corrupted checkpoint count gracefully during deletion Syzkaller reported a kernel warning in nilfs_cpfile_delete_checkpoints() due to a corrupted checkpoint count on the storage medium where le32_to_cpu(cp->cp_checkpoints_count) is less than the number of checkpoints being deleted. Triggering a WARN_ON() for disk image corruption is suboptimal. Fix this by returning -EIO and reporting a filesystem error via nilfs_error() instead of interrupting execution with a kernel warning. Reported-by: syzbot+79b815da3aec0a6a4d02@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=79b815da3aec0a6a4d02 Signed-off-by: Igor Putko Fixes: 1f5abe7e7dbc ("nilfs2: replace BUG_ON and BUG calls triggerable from ioctl") Cc: stable+noautosel@kernel.org # Warning suppression primarily; will request backport individually if needed Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/cpfile.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c index 4bbdc832d7f2..d3349fa58abe 100644 --- a/fs/nilfs2/cpfile.c +++ b/fs/nilfs2/cpfile.c @@ -81,18 +81,26 @@ nilfs_cpfile_block_add_valid_checkpoints(const struct inode *cpfile, return count; } -static unsigned int +static int nilfs_cpfile_block_sub_valid_checkpoints(const struct inode *cpfile, struct buffer_head *bh, unsigned int n) { struct nilfs_checkpoint *cp; - unsigned int count; + unsigned int checkpoints_count; + int count; cp = kmap_local_folio(bh->b_folio, offset_in_folio(bh->b_folio, bh->b_data)); - WARN_ON(le32_to_cpu(cp->cp_checkpoints_count) < n); - count = le32_to_cpu(cp->cp_checkpoints_count) - n; + checkpoints_count = le32_to_cpu(cp->cp_checkpoints_count); + if (unlikely(checkpoints_count < n)) { + nilfs_error(cpfile->i_sb, + "deleted checkpoints count %u exceeds block count %u", + n, checkpoints_count); + kunmap_local(cp); + return -EIO; + } + count = checkpoints_count - n; cp->cp_checkpoints_count = cpu_to_le32(count); kunmap_local(cp); return count; @@ -522,6 +530,10 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile, count = nilfs_cpfile_block_sub_valid_checkpoints(cpfile, cp_bh, nicps); brelse(cp_bh); + if (unlikely(count < 0)) { + ret = count; + break; + } if (count) continue; -- cgit v1.2.3 From 6e2b15013658ad631e482dbbbd50cc79dec02a66 Mon Sep 17 00:00:00 2001 From: Manoj K M Date: Sat, 25 Jul 2026 10:06:58 +0000 Subject: Documentation: fix grammar in description of nilfs2 recovery code Include the word 'at' to make the sentence grammatically correct inside the description for nilfs2 recovery code. This improves documentation without changing the original meaning. Signed-off-by: Manoj K M Acked-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- Documentation/filesystems/nilfs2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/filesystems/nilfs2.rst b/Documentation/filesystems/nilfs2.rst index e3a5c8977f2c..a0124d22a237 100644 --- a/Documentation/filesystems/nilfs2.rst +++ b/Documentation/filesystems/nilfs2.rst @@ -252,7 +252,7 @@ The following figure shows a typical organization of the logs:: To stride over segment boundaries, this sequence of files may be split into multiple logs. The sequence of logs that should be treated as logically one log, is delimited with flags marked in the segment -summary. The recovery code of nilfs2 looks this boundary information +summary. The recovery code of nilfs2 looks at this boundary information to ensure atomicity of updates. The super root block is inserted for every checkpoints. It includes -- cgit v1.2.3 From 45662dedb8f272ef7f16e69f13424c4bd0399240 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 17 Jul 2026 13:39:43 +0900 Subject: nilfs2: fix slab-out-of-bounds in nilfs_direct_propagate after truncation Shuangpeng Bai reported that KASAN detected a slab-out-of-bounds error in nilfs_direct_propagate() during testing. Analysis revealed that after truncating a file, a node block immediately below the B-tree root was not deleted. Instead, it remained in the B-tree node cache in a dirty state. The log writer subsequently detected this block and incorrectly invoked nilfs_direct_propagate() on it, which is designed to handle only data blocks in direct mapping. B-tree nodes in the cache are managed by virtual block numbers, and their logical keys typically exceed the range expected by direct mapping. Consequently, processing such a node as a direct mapping entry triggers a slab-out-of-bounds access. The root cause is that when a B-tree mapping collapses into a direct mapping during truncation, an intermediate node block pointed to by the root node is left behind as garbage instead of being explicitly deleted. This resolves the issue by adding a nilfs_btree_discard() operation to delete the remaining intermediate node block during the conversion. A 'deform' flag is added to the bop_delete interface to explicitly signal that the deletion is part of a mapping transformation. This allows the B-tree mapping implementation to perform the necessary cleanup and discarding of the residual node structure that would be otherwise be left orphaned after the transition. Reported-by: Shuangpeng Bai Closes: https://lore.kernel.org/r/08A3603A-ADB6-484C-9015-9AC1340E6FB8@gmail.com Fixes: 36a580eb489f ("nilfs2: direct block mapping") Cc: stable@vger.kernel.org Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/bmap.c | 2 +- fs/nilfs2/bmap.h | 2 +- fs/nilfs2/btree.c | 39 ++++++++++++++++++++++++++++++++------- fs/nilfs2/direct.c | 4 ++-- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 5f0f1f283af0..83f6ea30cc8b 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -175,7 +175,7 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key) return ret; } - return bmap->b_ops->bop_delete(bmap, key); + return bmap->b_ops->bop_delete(bmap, key, false); } /** diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index 4656df392722..a72f3c308a5d 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h @@ -63,7 +63,7 @@ struct nilfs_bmap_operations { int (*bop_lookup_contig)(const struct nilfs_bmap *, __u64, __u64 *, unsigned int); int (*bop_insert)(struct nilfs_bmap *, __u64, __u64); - int (*bop_delete)(struct nilfs_bmap *, __u64); + int (*bop_delete)(struct nilfs_bmap *bmap, __u64 key, bool deform); void (*bop_clear)(struct nilfs_bmap *); int (*bop_propagate)(struct nilfs_bmap *, struct buffer_head *); diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 64d5f7c5ab44..64bac66af25b 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1425,6 +1425,28 @@ static void nilfs_btree_shrink(struct nilfs_bmap *btree, path[level].bp_bh = NULL; } +/** + * nilfs_btree_discard - discard the last node for the mapping transformation + * @btree: bmap struct of btree + * @path: array of nilfs_btree_path struct + * @level: level of the B-tree node being operated on + * @keyp: argument for passing a key (unused) + * @ptrp: argument for passing a pointer (unused) + */ +static void nilfs_btree_discard(struct nilfs_bmap *btree, + struct nilfs_btree_path *path, int level, + __u64 *keyp, __u64 *ptrp) +{ + struct nilfs_btree_node *root = nilfs_btree_get_root(btree); + + nilfs_btree_node_delete(root, 0, NULL, NULL, + NILFS_BTREE_ROOT_NCHILDREN_MAX); + nilfs_btree_node_set_level(root, level); + + nilfs_btnode_delete(path[level].bp_bh); + path[level].bp_bh = NULL; +} + static void nilfs_btree_nop(struct nilfs_bmap *btree, struct nilfs_btree_path *path, int level, __u64 *keyp, __u64 *ptrp) @@ -1435,7 +1457,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, struct nilfs_btree_path *path, int *levelp, struct nilfs_bmap_stats *stats, - struct inode *dat) + struct inode *dat, bool deform) { struct buffer_head *bh; struct nilfs_btree_node *node, *parent, *sib; @@ -1522,15 +1544,17 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, if (nilfs_btree_node_get_nchildren(node) - 1 <= NILFS_BTREE_ROOT_NCHILDREN_MAX) { path[level].bp_op = nilfs_btree_shrink; - stats->bs_nblocks += 2; - level++; - path[level].bp_op = nilfs_btree_nop; - goto shrink_root_child; + } else if (deform) { + path[level].bp_op = nilfs_btree_discard; } else { path[level].bp_op = nilfs_btree_do_delete; stats->bs_nblocks++; goto out; } + stats->bs_nblocks += 2; + level++; + path[level].bp_op = nilfs_btree_nop; + goto shrink_root_child; } } @@ -1581,7 +1605,7 @@ static void nilfs_btree_commit_delete(struct nilfs_bmap *btree, nilfs_bmap_set_dirty(btree); } -static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key) +static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key, bool deform) { struct nilfs_btree_path *path; @@ -1601,7 +1625,8 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key) dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; - ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat); + ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat, + deform); if (ret < 0) goto out; nilfs_btree_commit_delete(btree, path, level, dat); diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 8bd0b1374e25..b8643d3aa2f8 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c @@ -144,7 +144,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) return ret; } -static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) +static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key, bool deform) { union nilfs_bmap_ptr_req req; struct inode *dat; @@ -234,7 +234,7 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, /* no need to allocate any resource for conversion */ /* delete */ - ret = bmap->b_ops->bop_delete(bmap, key); + ret = bmap->b_ops->bop_delete(bmap, key, true); if (ret < 0) return ret; -- cgit v1.2.3 From ce5a5ad1a8330a2fcfdd9ec2ab341be739e89a18 Mon Sep 17 00:00:00 2001 From: Joshua Crofts Date: Fri, 17 Jul 2026 10:58:54 +0000 Subject: nilfs2: fix infinite loop in nilfs_clean_segments() syzbot reported a hung task in nilfs_transaction_begin(). This occurs because the cleaner ioctl falls into an infinite loop if nilfs_segctor_construct() repeatedly returns -EROFS (e.g. the device is remounted as read-only after an I/O error). Currently in nilfs_clean_segments(), if err is non-zero, it logs the error and sleeps but doesn't abort when it encounters a terminal error like -EROFS. This causes the thread to loop forever. Fix this by breaking out of the loop if nilfs_segctor_construct() returns -EROFS. This matches the behaviour in nilfs_segctor_write_out(), which also handles -EROFS. Reported-by: syzbot+cae54346a70bbceeff2c@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=cae54346a70bbceeff2c Fixes: 9ff05123e3bf ("nilfs2: segment constructor") Assisted-by: gemini:gemini-3.1-pro Signed-off-by: Joshua Crofts Acked-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/segment.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 9332f5ac6083..2189267894d2 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2561,6 +2561,10 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, break; nilfs_warn(sb, "error %d cleaning segments", err); + + if (unlikely(err == -EROFS)) + goto out_unlock; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(sci->sc_interval); } -- cgit v1.2.3 From 7cb2f76a6a2ba2130b577cb8ac13e1e46c4fc689 Mon Sep 17 00:00:00 2001 From: David Lee Date: Sat, 18 Jul 2026 01:56:21 +0900 Subject: nilfs2: prevent out-of-bounds read in super root block parsing super-root inode metadata size is trusted before nilfs_read_inode_common(). Reject super-root inode sizes whose computed on-disk footprint exceeds the filesystem block size. This prevents malformed filesystem images from making nilfs_read_inode_common() read past the end of the super-root block. [ryusuke: clarify the commit title] Fixes: 8a9d2191e9f4 ("nilfs2: operations for the_nilfs core object") Signed-off-by: David Lee Assisted-by: Codex:gpt-5.5 Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/the_nilfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 7b23e373a106..f3805e7aabeb 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -461,6 +461,12 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs, nilfs->ns_inode_size); return -EINVAL; } + if (NILFS_SR_BYTES(nilfs->ns_inode_size) > nilfs->ns_blocksize) { + nilfs_err(nilfs->ns_sb, + "too large inode size for super root: %d bytes", + nilfs->ns_inode_size); + return -EINVAL; + } nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino); if (nilfs->ns_first_ino < NILFS_USER_INO) { -- cgit v1.2.3 From 66f4ad3ce158902e5f98afea93189972ed8750c2 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 20 Jul 2026 23:16:52 +0900 Subject: nilfs2: fix BUG in nilfs_copy_dirty_pages() on dirty state mismatch Syzbot reported a kernel BUG triggered within nilfs_copy_dirty_pages(), which copies dirty DAT file folios/pages to its shadow page cache. The BUG occurs when a retrieved dirty folio/page unexpectedly loses its 'dirty' status. This issue arises because, since the commit referenced below, the 'dirty' flag of a folio/page can be cleared asynchronously after the filesystem detects metadata corruption and transitions to read-only mode. Resolve the issue by returning an -EROFS error if the filesystem has transitioned to read-only mode. Also change the behavior to issue a kernel warning only once instead of triggering a kernel BUG when this unexpected 'dirty' state is detected while the filesystem is not in read-only mode. Reported-by: syzbot+8baf9a79a3ffc6271cb6@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=8baf9a79a3ffc6271cb6 Fixes: 8c26c4e2694a ("nilfs2: fix issue with flush kernel thread after remount in RO mode because of driver's internal error or metadata corruption") Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/page.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index a9d8aa65416f..1d00bce21c37 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c @@ -243,6 +243,7 @@ static void nilfs_copy_folio(struct folio *dst, struct folio *src, int nilfs_copy_dirty_pages(struct address_space *dmap, struct address_space *smap) { + struct inode *smap_inode = smap->host; struct folio_batch fbatch; unsigned int i; pgoff_t index = 0; @@ -258,8 +259,19 @@ repeat: struct folio *folio = fbatch.folios[i], *dfolio; folio_lock(folio); - if (unlikely(!folio_test_dirty(folio))) - NILFS_FOLIO_BUG(folio, "inconsistent dirty state"); + if (unlikely(!folio_test_dirty(folio))) { + if (WARN_ONCE(!sb_rdonly(smap_inode->i_sb), + "inconsistent dirty state\n")) + goto unlock_folio; + + /* + * If the filesystem has been forced to read-only + * due to metadata corruption. + */ + folio_unlock(folio); + err = -EROFS; + break; + } dfolio = filemap_grab_folio(dmap, folio->index); if (IS_ERR(dfolio)) { @@ -277,6 +289,7 @@ repeat: folio_unlock(dfolio); folio_put(dfolio); +unlock_folio: folio_unlock(folio); } folio_batch_release(&fbatch); -- cgit v1.2.3 From 6b38b82be46b242a64db8b3efc33cd15565efd08 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 7 Aug 2026 03:13:39 +0900 Subject: nilfs2: suppress false positive WARN_ONs for sufile after an FS error After applying the commit associated with the Fixes tag, metadata file buffers can be evicted from memory even after being marked dirty. Consequently, operations such as rolling back sufile changes upon error - which modify the buffer and were previously assumed incapable of failure - can now fail. This behavior causes syzbot to trigger a WARN_ON check immediately following sufile function calls within the log writer. Resolve this issue by introducing a macro, nilfs_sufile_warn_on_error(), which uses WARN_ONCE to report unexpected errors only when the filesystem has not degraded to read-only mode, returning -EIO or -EROFS accordingly. Replace existing WARN_ON checks for unexpected errors following sufile operations with this new macro. Additionally, for nilfs_segctor_truncate_segments() - where an error must be propagated to halt log writing if a sufile operation fails - modify the function to return the error code appropriately. Reported-by: syzbot+5957361606d7b750b874@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=5957361606d7b750b874 Fixes: 8c26c4e2694a ("nilfs2: fix issue with flush kernel thread after remount in RO mode because of driver's internal error or metadata corruption") Cc: stable+noautosel@kernel.org # Warning suppression primarily; will request backport individually if needed Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/segment.c | 36 ++++++++++++++++++++---------------- fs/nilfs2/sufile.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 2189267894d2..5896fdae5669 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1433,7 +1433,7 @@ static int nilfs_segctor_extend_segments(struct nilfs_sc_info *sci, failed: list_for_each_entry(segbuf, &list, sb_list) { ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); /* never fails */ + nilfs_sufile_warn_on_error(sufile, ret); } nilfs_destroy_logs(&list); return err; @@ -1449,7 +1449,7 @@ static void nilfs_free_incomplete_logs(struct list_head *logs, segbuf = NILFS_FIRST_SEGBUF(logs); if (nilfs->ns_nextnum != segbuf->sb_nextnum) { ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); /* never fails */ + nilfs_sufile_warn_on_error(sufile, ret); } if (atomic_read(&segbuf->sb_err)) { /* Case 1: The first segment failed */ @@ -1468,7 +1468,7 @@ static void nilfs_free_incomplete_logs(struct list_head *logs, list_for_each_entry_continue(segbuf, logs, sb_list) { if (prev->sb_nextnum != segbuf->sb_nextnum) { ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); /* never fails */ + nilfs_sufile_warn_on_error(sufile, ret); } if (atomic_read(&segbuf->sb_err) && segbuf->sb_segnum != nilfs->ns_nextnum) @@ -1491,7 +1491,7 @@ static void nilfs_segctor_update_segusage(struct nilfs_sc_info *sci, ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, live_blocks, sci->sc_seg_ctime); - WARN_ON(ret); /* always succeed because the segusage is dirty */ + nilfs_sufile_warn_on_error(sufile, ret); } } @@ -1504,28 +1504,32 @@ static void nilfs_cancel_segusage(struct list_head *logs, struct inode *sufile) ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, segbuf->sb_pseg_start - segbuf->sb_fseg_start, 0); - WARN_ON(ret); /* always succeed because the segusage is dirty */ + nilfs_sufile_warn_on_error(sufile, ret); list_for_each_entry_continue(segbuf, logs, sb_list) { ret = nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, 0, 0); - WARN_ON(ret); /* always succeed */ + nilfs_sufile_warn_on_error(sufile, ret); } } -static void nilfs_segctor_truncate_segments(struct nilfs_sc_info *sci, - struct nilfs_segment_buffer *last, - struct inode *sufile) +static int nilfs_segctor_truncate_segments(struct nilfs_sc_info *sci, + struct nilfs_segment_buffer *last, + struct inode *sufile) { struct nilfs_segment_buffer *segbuf = last; - int ret; + int ret, err = 0; list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { sci->sc_segbuf_nblocks -= segbuf->sb_rest_blocks; - ret = nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); + + ret = nilfs_sufile_warn_on_error( + sufile, nilfs_sufile_free(sufile, segbuf->sb_nextnum)); + if (unlikely(ret) && err != -EROFS) + err = ret; } nilfs_truncate_logs(&sci->sc_segbufs, last); + return err; } @@ -1564,7 +1568,7 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, sci->sc_freesegs, sci->sc_nfreesegs, NULL); - WARN_ON(err); /* do not happen */ + nilfs_sufile_warn_on_error(nilfs->ns_sufile, err); sci->sc_stage.flags &= ~NILFS_CF_SUFREED; } @@ -1576,8 +1580,8 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, sci->sc_stage = prev_stage; } nilfs_segctor_zeropad_segsum(sci); - nilfs_segctor_truncate_segments(sci, sci->sc_curseg, nilfs->ns_sufile); - return 0; + err = nilfs_segctor_truncate_segments(sci, sci->sc_curseg, + nilfs->ns_sufile); failed: return err; @@ -1878,7 +1882,7 @@ static void nilfs_segctor_abort_construction(struct nilfs_sc_info *sci, sci->sc_freesegs, sci->sc_nfreesegs, NULL); - WARN_ON(ret); /* do not happen */ + nilfs_sufile_warn_on_error(nilfs->ns_sufile, ret); } nilfs_destroy_logs(&logs); diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h index cd6f28ab3521..5888ed479c8b 100644 --- a/fs/nilfs2/sufile.h +++ b/fs/nilfs2/sufile.h @@ -10,6 +10,7 @@ #ifndef _NILFS_SUFILE_H #define _NILFS_SUFILE_H +#include #include #include #include "mdt.h" @@ -54,6 +55,33 @@ int nilfs_sufile_read(struct super_block *sb, size_t susize, struct nilfs_inode *raw_inode, struct inode **inodep); int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range); +/** + * nilfs_sufile_warn_on_error - warn on unexpected sufile error + * @sufile: inode of segment usage file + * @err: status code returned by a sufile function + * + * Even if buffer heads of blocks containing segment usage entries have + * been dirtied in advance by calling functions such as + * nilfs_sufile_mark_dirty() or nilfs_sufile_{alloc,free}(), those buffers + * can be discarded from memory after the file system detects corruption and + * degrades to read-only mode, which may cause sufile operations, including + * cancel operations, to return errors. nilfs_sufile_warn_on_error() is used + * to detect unexpected errors other than during read-only degradation. + * + * Return: 0 if @err is 0, %-EROFS if in read-only degraded mode, and %-EIO + * otherwise. + */ +#define nilfs_sufile_warn_on_error(sufile, err) \ + ({ \ + int _err = (err); \ + \ + if (unlikely(_err)) \ + _err = WARN_ONCE(!sb_rdonly((sufile)->i_sb), \ + "unexpected sufile error %d\n", _err) ? \ + -EIO : -EROFS; \ + _err; \ + }) + /** * nilfs_sufile_scrap - make a segment garbage * @sufile: inode of segment usage file -- cgit v1.2.3 From d7d54599a132408ee8ce857393974dddfb88357c Mon Sep 17 00:00:00 2001 From: Wang Jianjian Date: Mon, 10 Aug 2026 23:20:52 +0900 Subject: nilfs2: enhance btree node keys check syzbot reported a warning on nilfs_btree_assign: WARNING: fs/nilfs2/btree.c:2302 at nilfs_btree_assign+0x983/0xbe0 fs/nilfs2/btree.c:2302, Analysis found that a corrupted file has the following btree layout: Level2(key/ptr): [ 256/15 ] Level1(key/ptr): [ 0/8, 1/9, 0/10, 3/11, 4/12, 5/13, 6/14, 139637976727559/16, 0/17 ] The test truncated the file to 2 bytes, which partially zeroes the first block and adds the file to the dirty list. When the segment constructor writes it and assigns a new blocknr for the index block, it searches the btree with key=0 and min level=2, and apparently returns -ENOENT. Therefore, we should perform more checks on the btree nodes and return early. [ryusuke: split long lines in btree.c to satisfy checkpatch and improved the error message format for clarity] Reported-by: syzbot+158be45e4d99232e1900@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=158be45e4d99232e1900 Signed-off-by: Wang Jianjian Fixes: 17c76b0104e4 ("nilfs2: B-tree based block mapping") Cc: stable+noautosel@kernel.org # Warning suppression primarily Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/btree.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 64bac66af25b..6b8332e8c0db 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -341,7 +341,8 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, sector_t blocknr) { int level, flags, nchildren; - int ret = 0; + __u64 key, prev_key; + int i; level = nilfs_btree_node_get_level(node); flags = nilfs_btree_node_get_flags(node); @@ -356,9 +357,21 @@ static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, "bad btree node (ino=%llu, blocknr=%llu): level = %d, flags = 0x%x, nchildren = %d", inode->i_ino, (unsigned long long)blocknr, level, flags, nchildren); - ret = 1; + return 1; } - return ret; + + for (i = 1, prev_key = nilfs_btree_node_get_key(node, 0); + i < nchildren; i++, prev_key = key) { + key = nilfs_btree_node_get_key(node, i); + if (unlikely(key <= prev_key)) { + nilfs_crit(inode->i_sb, + "bad btree node (ino=%llu, blocknr=%llu): unsorted keys at index %d (%llu) and %d (%llu)", + inode->i_ino, (unsigned long long)blocknr, + i - 1, prev_key, i, key); + return 1; + } + } + return 0; } /** -- cgit v1.2.3 From 24a098541a765ed017274f8094004404a83b0daf Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Tue, 11 Aug 2026 02:48:18 +0900 Subject: nilfs2: standardize the inode number type to u64 Variables handling inode numbers - such as the 'i_ino' member of the inode structure - have been converted to 'u64' within the kernel to ensure consistency. However, some parts of the nilfs2 implementation still use 'ino_t' or 'unsigned long' - both of which are architecture-dependent types - to handle inode numbers. Replace those remaining instances of 'ino_t' or 'unsigned long' with 'u64'. Signed-off-by: Ryusuke Konishi Signed-off-by: Viacheslav Dubeyko --- fs/nilfs2/dir.c | 11 +++++------ fs/nilfs2/ifile.c | 13 ++++++------- fs/nilfs2/ifile.h | 10 ++++++---- fs/nilfs2/inode.c | 24 +++++++++++------------- fs/nilfs2/ioctl.c | 2 +- fs/nilfs2/namei.c | 6 +++--- fs/nilfs2/nilfs.h | 15 +++++++-------- fs/nilfs2/page.c | 9 ++++----- fs/nilfs2/recovery.c | 4 ++-- fs/nilfs2/segment.c | 2 +- 10 files changed, 46 insertions(+), 50 deletions(-) diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 3653db5cdb65..8b53802b6ebd 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -169,17 +169,16 @@ Einumber: error = "disallowed inode number"; bad_entry: nilfs_error(sb, - "bad entry in directory #%llu: %s - offset=%lu, inode=%lu, rec_len=%zd, name_len=%d", + "bad entry in directory #%llu: %s - offset=%lu, inode=%llu, rec_len=%zd, name_len=%d", dir->i_ino, error, (folio->index << PAGE_SHIFT) + offs, - (unsigned long)le64_to_cpu(p->inode), - rec_len, p->name_len); + le64_to_cpu(p->inode), rec_len, p->name_len); goto fail; Eend: p = (struct nilfs_dir_entry *)(kaddr + offs); nilfs_error(sb, - "entry in directory #%llu spans the page boundary offset=%lu, inode=%lu", + "entry in directory #%llu spans the page boundary offset=%lu, inode=%llu", dir->i_ino, (folio->index << PAGE_SHIFT) + offs, - (unsigned long)le64_to_cpu(p->inode)); + le64_to_cpu(p->inode)); fail: return false; } @@ -387,7 +386,7 @@ fail: return NULL; } -int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino) +int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, u64 *ino) { struct nilfs_dir_entry *de; struct folio *folio; diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c index 99eb8a59009e..c99e1e6356ae 100644 --- a/fs/nilfs2/ifile.c +++ b/fs/nilfs2/ifile.c @@ -49,7 +49,7 @@ static inline struct nilfs_ifile_info *NILFS_IFILE_I(struct inode *ifile) * * %-ENOMEM - Insufficient memory available. * * %-ENOSPC - No inode left. */ -int nilfs_ifile_create_inode(struct inode *ifile, ino_t *out_ino, +int nilfs_ifile_create_inode(struct inode *ifile, u64 *out_ino, struct buffer_head **out_bh) { struct nilfs_palloc_req req; @@ -72,7 +72,7 @@ int nilfs_ifile_create_inode(struct inode *ifile, ino_t *out_ino, nilfs_palloc_commit_alloc_entry(ifile, &req); mark_buffer_dirty(req.pr_entry_bh); nilfs_mdt_mark_dirty(ifile); - *out_ino = (ino_t)req.pr_entry_nr; + *out_ino = req.pr_entry_nr; *out_bh = req.pr_entry_bh; return 0; } @@ -88,7 +88,7 @@ int nilfs_ifile_create_inode(struct inode *ifile, ino_t *out_ino, * * %-ENOENT - Inode number unallocated. * * %-ENOMEM - Insufficient memory available. */ -int nilfs_ifile_delete_inode(struct inode *ifile, ino_t ino) +int nilfs_ifile_delete_inode(struct inode *ifile, u64 ino) { struct nilfs_palloc_req req = { .pr_entry_nr = ino, .pr_entry_bh = NULL @@ -123,21 +123,20 @@ int nilfs_ifile_delete_inode(struct inode *ifile, ino_t ino) return 0; } -int nilfs_ifile_get_inode_block(struct inode *ifile, ino_t ino, +int nilfs_ifile_get_inode_block(struct inode *ifile, u64 ino, struct buffer_head **out_bh) { struct super_block *sb = ifile->i_sb; int err; if (unlikely(!NILFS_VALID_INODE(sb, ino))) { - nilfs_error(sb, "bad inode number: %lu", (unsigned long)ino); + nilfs_error(sb, "bad inode number: %llu", ino); return -EINVAL; } err = nilfs_palloc_get_entry_block(ifile, ino, 0, out_bh); if (unlikely(err)) - nilfs_warn(sb, "error %d reading inode: ino=%lu", - err, (unsigned long)ino); + nilfs_warn(sb, "error %d reading inode: ino=%llu", err, ino); return err; } diff --git a/fs/nilfs2/ifile.h b/fs/nilfs2/ifile.h index 5d116a566d9e..d38a46f5ae41 100644 --- a/fs/nilfs2/ifile.h +++ b/fs/nilfs2/ifile.h @@ -19,7 +19,7 @@ static inline struct nilfs_inode * -nilfs_ifile_map_inode(struct inode *ifile, ino_t ino, struct buffer_head *ibh) +nilfs_ifile_map_inode(struct inode *ifile, u64 ino, struct buffer_head *ibh) { size_t __offset_in_folio = nilfs_palloc_entry_offset(ifile, ino, ibh); @@ -31,9 +31,11 @@ static inline void nilfs_ifile_unmap_inode(struct nilfs_inode *raw_inode) kunmap_local(raw_inode); } -int nilfs_ifile_create_inode(struct inode *, ino_t *, struct buffer_head **); -int nilfs_ifile_delete_inode(struct inode *, ino_t); -int nilfs_ifile_get_inode_block(struct inode *, ino_t, struct buffer_head **); +int nilfs_ifile_create_inode(struct inode *ifile, u64 *out_ino, + struct buffer_head **out_bh); +int nilfs_ifile_delete_inode(struct inode *ifile, u64 ino); +int nilfs_ifile_get_inode_block(struct inode *ifile, u64 ino, + struct buffer_head **out_bh); int nilfs_ifile_count_free_inodes(struct inode *, u64 *, u64 *); diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 51f7e125a311..34e6096069ad 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -287,8 +287,7 @@ const struct address_space_operations nilfs_buffer_cache_aops = { }; static int nilfs_insert_inode_locked(struct inode *inode, - struct nilfs_root *root, - unsigned long ino) + struct nilfs_root *root, u64 ino) { struct nilfs_iget_args args = { .ino = ino, .root = root, .cno = 0, .type = NILFS_I_TYPE_NORMAL @@ -305,7 +304,7 @@ struct inode *nilfs_new_inode(struct inode *dir, umode_t mode) struct nilfs_root *root; struct buffer_head *bh; int err = -ENOMEM; - ino_t ino; + u64 ino; inode = new_inode(sb); if (unlikely(!inode)) @@ -443,7 +442,7 @@ int nilfs_read_inode_common(struct inode *inode, } static int __nilfs_read_inode(struct super_block *sb, - struct nilfs_root *root, unsigned long ino, + struct nilfs_root *root, u64 ino, struct inode *inode) { struct the_nilfs *nilfs = sb->s_fs_info; @@ -482,8 +481,8 @@ static int __nilfs_read_inode(struct super_block *sb, huge_decode_dev(le64_to_cpu(raw_inode->i_device_code))); } else { nilfs_error(sb, - "invalid file type bits in mode 0%o for inode %lu", - inode->i_mode, ino); + "invalid file type bits in mode 0%o for inode %llu", + inode->i_mode, ino); err = -EIO; goto failed_unmap; } @@ -533,7 +532,7 @@ static int nilfs_iget_set(struct inode *inode, void *opaque) } struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root, - unsigned long ino) + u64 ino) { struct nilfs_iget_args args = { .ino = ino, .root = root, .cno = 0, .type = NILFS_I_TYPE_NORMAL @@ -542,8 +541,8 @@ struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root, return ilookup5(sb, ino, nilfs_iget_test, &args); } -struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root, - unsigned long ino) +struct inode *nilfs_iget_locked(struct super_block *sb, + struct nilfs_root *root, u64 ino) { struct nilfs_iget_args args = { .ino = ino, .root = root, .cno = 0, .type = NILFS_I_TYPE_NORMAL @@ -553,7 +552,7 @@ struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root, } struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, - unsigned long ino) + u64 ino) { struct inode *inode; int err; @@ -579,8 +578,7 @@ struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, return inode; } -struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino, - __u64 cno) +struct inode *nilfs_iget_for_gc(struct super_block *sb, u64 ino, __u64 cno) { struct nilfs_iget_args args = { .ino = ino, .root = NULL, .cno = cno, .type = NILFS_I_TYPE_GC @@ -740,7 +738,7 @@ void nilfs_write_inode_common(struct inode *inode, void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh, int flags) { - ino_t ino = inode->i_ino; + u64 ino = inode->i_ino; struct nilfs_inode_info *ii = NILFS_I(inode); struct inode *ifile = ii->i_root->ifile; struct nilfs_inode *raw_inode; diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 0957316e58b8..01a04080ef70 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -612,7 +612,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb, struct nilfs_vdesc *vdesc; struct buffer_head *bh, *n; LIST_HEAD(buffers); - ino_t ino; + u64 ino; __u64 cno; int i, ret; diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index e2fe95de3d71..6a482da7c682 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -54,7 +54,7 @@ static struct dentry * nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct inode *inode; - ino_t ino; + u64 ino; int res; if (dentry->d_name.len > NILFS_NAME_LEN) @@ -69,7 +69,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino); if (inode == ERR_PTR(-ESTALE)) { nilfs_error(dir->i_sb, - "deleted inode referenced: %lu", ino); + "deleted inode referenced: %llu", ino); return ERR_PTR(-EIO); } } @@ -463,7 +463,7 @@ out: */ static struct dentry *nilfs_get_parent(struct dentry *child) { - ino_t ino; + u64 ino; int res; struct nilfs_root *root; diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index b7e3d91b6243..4fc42d3787a4 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -144,7 +144,7 @@ enum { ((ino) < NILFS_USER_INO && (NILFS_SYS_INO_BITS & BIT(ino)))) #define NILFS_PRIVATE_INODE(ino) ({ \ - ino_t __ino = (ino); \ + u64 __ino = (ino); \ ((__ino) < NILFS_USER_INO && (__ino) != NILFS_ROOT_INO && \ (__ino) != NILFS_SKETCH_INO); }) @@ -255,7 +255,7 @@ static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags) /* dir.c */ int nilfs_add_link(struct dentry *, struct inode *); -int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, ino_t *ino); +int nilfs_inode_by_name(struct inode *dir, const struct qstr *qstr, u64 *ino); int nilfs_make_empty(struct inode *, struct inode *); struct nilfs_dir_entry *nilfs_find_entry(struct inode *, const struct qstr *, struct folio **); @@ -287,13 +287,12 @@ extern int nilfs_read_inode_common(struct inode *, struct nilfs_inode *); void nilfs_write_inode_common(struct inode *inode, struct nilfs_inode *raw_inode); struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root, - unsigned long ino); -struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root, - unsigned long ino); + u64 ino); +struct inode *nilfs_iget_locked(struct super_block *sb, + struct nilfs_root *root, u64 ino); struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root, - unsigned long ino); -extern struct inode *nilfs_iget_for_gc(struct super_block *sb, - unsigned long ino, __u64 cno); + u64 ino); +struct inode *nilfs_iget_for_gc(struct super_block *sb, u64 ino, __u64 cno); int nilfs_attach_btree_node_cache(struct inode *inode); void nilfs_detach_btree_node_cache(struct inode *inode); struct inode *nilfs_iget_for_shadow(struct inode *inode); diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 1d00bce21c37..cf4f1c6798f5 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c @@ -154,7 +154,7 @@ void nilfs_folio_bug(struct folio *folio) { struct buffer_head *bh, *head; struct address_space *m; - unsigned long ino; + u64 ino; if (unlikely(!folio)) { printk(KERN_CRIT "NILFS_FOLIO_BUG(NULL)\n"); @@ -164,10 +164,9 @@ void nilfs_folio_bug(struct folio *folio) m = folio->mapping; ino = m ? m->host->i_ino : 0; - printk(KERN_CRIT "NILFS_FOLIO_BUG(%p): cnt=%d index#=%llu flags=0x%lx " - "mapping=%p ino=%lu\n", - folio, folio_ref_count(folio), - (unsigned long long)folio->index, folio->flags.f, m, ino); + printk(KERN_CRIT "NILFS_FOLIO_BUG(%p): cnt=%d index#=%lu flags=0x%lx mapping=%p ino=%llu\n", + folio, folio_ref_count(folio), folio->index, folio->flags.f, + m, ino); head = folio_buffers(folio); if (head) { diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index 4d5a6aa5214c..45fb37215669 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -34,7 +34,7 @@ enum { /* work structure for recovery */ struct nilfs_recovery_block { - ino_t ino; /* + u64 ino; /* * Inode number of the file that this block * belongs to */ @@ -333,7 +333,7 @@ static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr, unsigned int offset; u32 nfinfo, sumbytes; sector_t blocknr; - ino_t ino; + u64 ino; int err = -EIO; nfinfo = le32_to_cpu(sum->ss_nfinfo); diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 5896fdae5669..829573cb6131 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1610,7 +1610,7 @@ nilfs_segctor_update_payload_blocknr(struct nilfs_sc_info *sci, struct nilfs_finfo *finfo = NULL; union nilfs_binfo binfo; struct buffer_head *bh, *bh_org; - ino_t ino = 0; + u64 ino = 0; int err = 0; if (!nfinfo) -- cgit v1.2.3