diff options
Diffstat (limited to 'fs/ext4')
| -rw-r--r-- | fs/ext4/balloc.c | 2 | ||||
| -rw-r--r-- | fs/ext4/namei.c | 10 | ||||
| -rw-r--r-- | fs/ext4/super.c | 49 |
3 files changed, 48 insertions, 13 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 3b64bb16c727..9de54ae48dee 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -1585,7 +1585,7 @@ allocated: | |||
| 1585 | ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no); | 1585 | ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no); |
| 1586 | 1586 | ||
| 1587 | if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) || | 1587 | if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) || |
| 1588 | in_range(ext4_block_bitmap(sb, gdp), ret_block, num) || | 1588 | in_range(ext4_inode_bitmap(sb, gdp), ret_block, num) || |
| 1589 | in_range(ret_block, ext4_inode_table(sb, gdp), | 1589 | in_range(ret_block, ext4_inode_table(sb, gdp), |
| 1590 | EXT4_SB(sb)->s_itb_per_group) || | 1590 | EXT4_SB(sb)->s_itb_per_group) || |
| 1591 | in_range(ret_block + num - 1, ext4_inode_table(sb, gdp), | 1591 | in_range(ret_block + num - 1, ext4_inode_table(sb, gdp), |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 2811e5720ad0..2de339dd7554 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -1017,6 +1017,11 @@ static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, str | |||
| 1017 | 1017 | ||
| 1018 | if (!inode) | 1018 | if (!inode) |
| 1019 | return ERR_PTR(-EACCES); | 1019 | return ERR_PTR(-EACCES); |
| 1020 | |||
| 1021 | if (is_bad_inode(inode)) { | ||
| 1022 | iput(inode); | ||
| 1023 | return ERR_PTR(-ENOENT); | ||
| 1024 | } | ||
| 1020 | } | 1025 | } |
| 1021 | return d_splice_alias(inode, dentry); | 1026 | return d_splice_alias(inode, dentry); |
| 1022 | } | 1027 | } |
| @@ -1052,6 +1057,11 @@ struct dentry *ext4_get_parent(struct dentry *child) | |||
| 1052 | if (!inode) | 1057 | if (!inode) |
| 1053 | return ERR_PTR(-EACCES); | 1058 | return ERR_PTR(-EACCES); |
| 1054 | 1059 | ||
| 1060 | if (is_bad_inode(inode)) { | ||
| 1061 | iput(inode); | ||
| 1062 | return ERR_PTR(-ENOENT); | ||
| 1063 | } | ||
| 1064 | |||
| 1055 | parent = d_alloc_anon(inode); | 1065 | parent = d_alloc_anon(inode); |
| 1056 | if (!parent) { | 1066 | if (!parent) { |
| 1057 | iput(inode); | 1067 | iput(inode); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 175b68c60968..b806e689c4aa 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/parser.h> | 29 | #include <linux/parser.h> |
| 30 | #include <linux/smp_lock.h> | 30 | #include <linux/smp_lock.h> |
| 31 | #include <linux/buffer_head.h> | 31 | #include <linux/buffer_head.h> |
| 32 | #include <linux/exportfs.h> | ||
| 32 | #include <linux/vfs.h> | 33 | #include <linux/vfs.h> |
| 33 | #include <linux/random.h> | 34 | #include <linux/random.h> |
| 34 | #include <linux/mount.h> | 35 | #include <linux/mount.h> |
| @@ -510,6 +511,14 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
| 510 | 511 | ||
| 511 | static void ext4_destroy_inode(struct inode *inode) | 512 | static void ext4_destroy_inode(struct inode *inode) |
| 512 | { | 513 | { |
| 514 | if (!list_empty(&(EXT4_I(inode)->i_orphan))) { | ||
| 515 | printk("EXT4 Inode %p: orphan list check failed!\n", | ||
| 516 | EXT4_I(inode)); | ||
| 517 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4, | ||
| 518 | EXT4_I(inode), sizeof(struct ext4_inode_info), | ||
| 519 | true); | ||
| 520 | dump_stack(); | ||
| 521 | } | ||
| 513 | kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); | 522 | kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); |
| 514 | } | 523 | } |
| 515 | 524 | ||
| @@ -2150,6 +2159,7 @@ static int ext4_create_journal(struct super_block * sb, | |||
| 2150 | unsigned int journal_inum) | 2159 | unsigned int journal_inum) |
| 2151 | { | 2160 | { |
| 2152 | journal_t *journal; | 2161 | journal_t *journal; |
| 2162 | int err; | ||
| 2153 | 2163 | ||
| 2154 | if (sb->s_flags & MS_RDONLY) { | 2164 | if (sb->s_flags & MS_RDONLY) { |
| 2155 | printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to " | 2165 | printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to " |
| @@ -2157,13 +2167,15 @@ static int ext4_create_journal(struct super_block * sb, | |||
| 2157 | return -EROFS; | 2167 | return -EROFS; |
| 2158 | } | 2168 | } |
| 2159 | 2169 | ||
| 2160 | if (!(journal = ext4_get_journal(sb, journal_inum))) | 2170 | journal = ext4_get_journal(sb, journal_inum); |
| 2171 | if (!journal) | ||
| 2161 | return -EINVAL; | 2172 | return -EINVAL; |
| 2162 | 2173 | ||
| 2163 | printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n", | 2174 | printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n", |
| 2164 | journal_inum); | 2175 | journal_inum); |
| 2165 | 2176 | ||
| 2166 | if (jbd2_journal_create(journal)) { | 2177 | err = jbd2_journal_create(journal); |
| 2178 | if (err) { | ||
| 2167 | printk(KERN_ERR "EXT4-fs: error creating journal.\n"); | 2179 | printk(KERN_ERR "EXT4-fs: error creating journal.\n"); |
| 2168 | jbd2_journal_destroy(journal); | 2180 | jbd2_journal_destroy(journal); |
| 2169 | return -EIO; | 2181 | return -EIO; |
| @@ -2214,12 +2226,14 @@ static void ext4_mark_recovery_complete(struct super_block * sb, | |||
| 2214 | 2226 | ||
| 2215 | jbd2_journal_lock_updates(journal); | 2227 | jbd2_journal_lock_updates(journal); |
| 2216 | jbd2_journal_flush(journal); | 2228 | jbd2_journal_flush(journal); |
| 2229 | lock_super(sb); | ||
| 2217 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && | 2230 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && |
| 2218 | sb->s_flags & MS_RDONLY) { | 2231 | sb->s_flags & MS_RDONLY) { |
| 2219 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 2232 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
| 2220 | sb->s_dirt = 0; | 2233 | sb->s_dirt = 0; |
| 2221 | ext4_commit_super(sb, es, 1); | 2234 | ext4_commit_super(sb, es, 1); |
| 2222 | } | 2235 | } |
| 2236 | unlock_super(sb); | ||
| 2223 | jbd2_journal_unlock_updates(journal); | 2237 | jbd2_journal_unlock_updates(journal); |
| 2224 | } | 2238 | } |
| 2225 | 2239 | ||
| @@ -2408,7 +2422,13 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data) | |||
| 2408 | (sbi->s_mount_state & EXT4_VALID_FS)) | 2422 | (sbi->s_mount_state & EXT4_VALID_FS)) |
| 2409 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 2423 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| 2410 | 2424 | ||
| 2425 | /* | ||
| 2426 | * We have to unlock super so that we can wait for | ||
| 2427 | * transactions. | ||
| 2428 | */ | ||
| 2429 | unlock_super(sb); | ||
| 2411 | ext4_mark_recovery_complete(sb, es); | 2430 | ext4_mark_recovery_complete(sb, es); |
| 2431 | lock_super(sb); | ||
| 2412 | } else { | 2432 | } else { |
| 2413 | __le32 ret; | 2433 | __le32 ret; |
| 2414 | if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb, | 2434 | if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb, |
| @@ -2481,19 +2501,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 2481 | struct super_block *sb = dentry->d_sb; | 2501 | struct super_block *sb = dentry->d_sb; |
| 2482 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 2502 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 2483 | struct ext4_super_block *es = sbi->s_es; | 2503 | struct ext4_super_block *es = sbi->s_es; |
| 2484 | ext4_fsblk_t overhead; | ||
| 2485 | int i; | ||
| 2486 | u64 fsid; | 2504 | u64 fsid; |
| 2487 | 2505 | ||
| 2488 | if (test_opt (sb, MINIX_DF)) | 2506 | if (test_opt(sb, MINIX_DF)) { |
| 2489 | overhead = 0; | 2507 | sbi->s_overhead_last = 0; |
| 2490 | else { | 2508 | } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) { |
| 2491 | unsigned long ngroups; | 2509 | unsigned long ngroups = sbi->s_groups_count, i; |
| 2492 | ngroups = EXT4_SB(sb)->s_groups_count; | 2510 | ext4_fsblk_t overhead = 0; |
| 2493 | smp_rmb(); | 2511 | smp_rmb(); |
| 2494 | 2512 | ||
| 2495 | /* | 2513 | /* |
| 2496 | * Compute the overhead (FS structures) | 2514 | * Compute the overhead (FS structures). This is constant |
| 2515 | * for a given filesystem unless the number of block groups | ||
| 2516 | * changes so we cache the previous value until it does. | ||
| 2497 | */ | 2517 | */ |
| 2498 | 2518 | ||
| 2499 | /* | 2519 | /* |
| @@ -2517,18 +2537,23 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 2517 | * Every block group has an inode bitmap, a block | 2537 | * Every block group has an inode bitmap, a block |
| 2518 | * bitmap, and an inode table. | 2538 | * bitmap, and an inode table. |
| 2519 | */ | 2539 | */ |
| 2520 | overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group)); | 2540 | overhead += ngroups * (2 + sbi->s_itb_per_group); |
| 2541 | sbi->s_overhead_last = overhead; | ||
| 2542 | smp_wmb(); | ||
| 2543 | sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); | ||
| 2521 | } | 2544 | } |
| 2522 | 2545 | ||
| 2523 | buf->f_type = EXT4_SUPER_MAGIC; | 2546 | buf->f_type = EXT4_SUPER_MAGIC; |
| 2524 | buf->f_bsize = sb->s_blocksize; | 2547 | buf->f_bsize = sb->s_blocksize; |
| 2525 | buf->f_blocks = ext4_blocks_count(es) - overhead; | 2548 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; |
| 2526 | buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); | 2549 | buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); |
| 2550 | es->s_free_blocks_count = cpu_to_le32(buf->f_bfree); | ||
| 2527 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); | 2551 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); |
| 2528 | if (buf->f_bfree < ext4_r_blocks_count(es)) | 2552 | if (buf->f_bfree < ext4_r_blocks_count(es)) |
| 2529 | buf->f_bavail = 0; | 2553 | buf->f_bavail = 0; |
| 2530 | buf->f_files = le32_to_cpu(es->s_inodes_count); | 2554 | buf->f_files = le32_to_cpu(es->s_inodes_count); |
| 2531 | buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); | 2555 | buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); |
| 2556 | es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); | ||
| 2532 | buf->f_namelen = EXT4_NAME_LEN; | 2557 | buf->f_namelen = EXT4_NAME_LEN; |
| 2533 | fsid = le64_to_cpup((void *)es->s_uuid) ^ | 2558 | fsid = le64_to_cpup((void *)es->s_uuid) ^ |
| 2534 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); | 2559 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); |
