Skip to content

Commit 602ce7b

Browse files
konisakpm00
authored andcommitted
nilfs2: prevent WARNING in nilfs_dat_commit_end()
If nilfs2 reads a corrupted disk image and its DAT metadata file contains invalid lifetime data for a virtual block number, a kernel warning can be generated by the WARN_ON check in nilfs_dat_commit_end() and can panic if the kernel is booted with panic_on_warn. This patch avoids the issue with a sanity check that treats it as an error. Since error return is not allowed in the execution phase of nilfs_dat_commit_end(), this inserts that sanity check in nilfs_dat_prepare_end(), which prepares for nilfs_dat_commit_end(). As the error code, -EINVAL is returned to notify bmap layer of the metadata corruption. When the bmap layer sees this code, it handles the abnormal situation and replaces the return code with -EIO as it should. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ryusuke Konishi <[email protected]> Reported-by: <[email protected]> Tested-by: Ryusuke Konishi <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent e89bd9e commit 602ce7b

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

fs/nilfs2/dat.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
158158
int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
159159
{
160160
struct nilfs_dat_entry *entry;
161+
__u64 start;
161162
sector_t blocknr;
162163
void *kaddr;
163164
int ret;
@@ -169,6 +170,7 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
169170
kaddr = kmap_atomic(req->pr_entry_bh->b_page);
170171
entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
171172
req->pr_entry_bh, kaddr);
173+
start = le64_to_cpu(entry->de_start);
172174
blocknr = le64_to_cpu(entry->de_blocknr);
173175
kunmap_atomic(kaddr);
174176

@@ -179,6 +181,15 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
179181
return ret;
180182
}
181183
}
184+
if (unlikely(start > nilfs_mdt_cno(dat))) {
185+
nilfs_err(dat->i_sb,
186+
"vblocknr = %llu has abnormal lifetime: start cno (= %llu) > current cno (= %llu)",
187+
(unsigned long long)req->pr_entry_nr,
188+
(unsigned long long)start,
189+
(unsigned long long)nilfs_mdt_cno(dat));
190+
nilfs_dat_abort_entry(dat, req);
191+
return -EINVAL;
192+
}
182193

183194
return 0;
184195
}

0 commit comments

Comments
 (0)