diff options
Diffstat (limited to 'fs/bfs/inode.c')
-rw-r--r-- | fs/bfs/inode.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 0ed57b5ee012..cc4062d12ca2 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
@@ -213,6 +213,9 @@ static void bfs_put_super(struct super_block *s) | |||
213 | { | 213 | { |
214 | struct bfs_sb_info *info = BFS_SB(s); | 214 | struct bfs_sb_info *info = BFS_SB(s); |
215 | 215 | ||
216 | if (!info) | ||
217 | return; | ||
218 | |||
216 | brelse(info->si_sbh); | 219 | brelse(info->si_sbh); |
217 | mutex_destroy(&info->bfs_lock); | 220 | mutex_destroy(&info->bfs_lock); |
218 | kfree(info->si_imap); | 221 | kfree(info->si_imap); |
@@ -327,6 +330,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
327 | unsigned i, imap_len; | 330 | unsigned i, imap_len; |
328 | struct bfs_sb_info *info; | 331 | struct bfs_sb_info *info; |
329 | long ret = -EINVAL; | 332 | long ret = -EINVAL; |
333 | unsigned long i_sblock, i_eblock, i_eoff, s_size; | ||
330 | 334 | ||
331 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 335 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
332 | if (!info) | 336 | if (!info) |
@@ -350,6 +354,12 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
350 | 354 | ||
351 | s->s_magic = BFS_MAGIC; | 355 | s->s_magic = BFS_MAGIC; |
352 | info->si_sbh = bh; | 356 | info->si_sbh = bh; |
357 | |||
358 | if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) { | ||
359 | printf("Superblock is corrupted\n"); | ||
360 | goto out; | ||
361 | } | ||
362 | |||
353 | info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / | 363 | info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / |
354 | sizeof(struct bfs_inode) | 364 | sizeof(struct bfs_inode) |
355 | + BFS_ROOT_INO - 1; | 365 | + BFS_ROOT_INO - 1; |
@@ -380,6 +390,18 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
380 | - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; | 390 | - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; |
381 | info->si_freei = 0; | 391 | info->si_freei = 0; |
382 | info->si_lf_eblk = 0; | 392 | info->si_lf_eblk = 0; |
393 | |||
394 | /* can we read the last block? */ | ||
395 | bh = sb_bread(s, info->si_blocks - 1); | ||
396 | if (!bh) { | ||
397 | printf("Last block not available: %lu\n", info->si_blocks - 1); | ||
398 | iput(inode); | ||
399 | ret = -EIO; | ||
400 | kfree(info->si_imap); | ||
401 | goto out; | ||
402 | } | ||
403 | brelse(bh); | ||
404 | |||
383 | bh = NULL; | 405 | bh = NULL; |
384 | for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) { | 406 | for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) { |
385 | struct bfs_inode *di; | 407 | struct bfs_inode *di; |
@@ -397,6 +419,29 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
397 | 419 | ||
398 | di = (struct bfs_inode *)bh->b_data + off; | 420 | di = (struct bfs_inode *)bh->b_data + off; |
399 | 421 | ||
422 | /* test if filesystem is not corrupted */ | ||
423 | |||
424 | i_eoff = le32_to_cpu(di->i_eoffset); | ||
425 | i_sblock = le32_to_cpu(di->i_sblock); | ||
426 | i_eblock = le32_to_cpu(di->i_eblock); | ||
427 | s_size = le32_to_cpu(bfs_sb->s_end); | ||
428 | |||
429 | if (i_sblock > info->si_blocks || | ||
430 | i_eblock > info->si_blocks || | ||
431 | i_sblock > i_eblock || | ||
432 | i_eoff > s_size || | ||
433 | i_sblock * BFS_BSIZE > i_eoff) { | ||
434 | |||
435 | printf("Inode 0x%08x corrupted\n", i); | ||
436 | |||
437 | brelse(bh); | ||
438 | s->s_root = NULL; | ||
439 | kfree(info->si_imap); | ||
440 | kfree(info); | ||
441 | s->s_fs_info = NULL; | ||
442 | return -EIO; | ||
443 | } | ||
444 | |||
400 | if (!di->i_ino) { | 445 | if (!di->i_ino) { |
401 | info->si_freei++; | 446 | info->si_freei++; |
402 | continue; | 447 | continue; |