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; |
