diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 315 |
1 files changed, 229 insertions, 86 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 566344b926b7..fb940c22ab0d 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | #include <linux/namei.h> | 34 | #include <linux/namei.h> |
| 35 | #include <linux/quotaops.h> | 35 | #include <linux/quotaops.h> |
| 36 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
| 37 | #include <linux/proc_fs.h> | ||
| 38 | #include <linux/marker.h> | ||
| 37 | #include <linux/log2.h> | 39 | #include <linux/log2.h> |
| 38 | #include <linux/crc16.h> | 40 | #include <linux/crc16.h> |
| 39 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
| @@ -45,6 +47,8 @@ | |||
| 45 | #include "namei.h" | 47 | #include "namei.h" |
| 46 | #include "group.h" | 48 | #include "group.h" |
| 47 | 49 | ||
| 50 | struct proc_dir_entry *ext4_proc_root; | ||
| 51 | |||
| 48 | static int ext4_load_journal(struct super_block *, struct ext4_super_block *, | 52 | static int ext4_load_journal(struct super_block *, struct ext4_super_block *, |
| 49 | unsigned long journal_devnum); | 53 | unsigned long journal_devnum); |
| 50 | static int ext4_create_journal(struct super_block *, struct ext4_super_block *, | 54 | static int ext4_create_journal(struct super_block *, struct ext4_super_block *, |
| @@ -503,15 +507,18 @@ static void ext4_put_super(struct super_block *sb) | |||
| 503 | ext4_mb_release(sb); | 507 | ext4_mb_release(sb); |
| 504 | ext4_ext_release(sb); | 508 | ext4_ext_release(sb); |
| 505 | ext4_xattr_put_super(sb); | 509 | ext4_xattr_put_super(sb); |
| 506 | jbd2_journal_destroy(sbi->s_journal); | 510 | if (jbd2_journal_destroy(sbi->s_journal) < 0) |
| 511 | ext4_abort(sb, __func__, "Couldn't clean up the journal"); | ||
| 507 | sbi->s_journal = NULL; | 512 | sbi->s_journal = NULL; |
| 508 | if (!(sb->s_flags & MS_RDONLY)) { | 513 | if (!(sb->s_flags & MS_RDONLY)) { |
| 509 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 514 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
| 510 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 515 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| 511 | BUFFER_TRACE(sbi->s_sbh, "marking dirty"); | ||
| 512 | mark_buffer_dirty(sbi->s_sbh); | ||
| 513 | ext4_commit_super(sb, es, 1); | 516 | ext4_commit_super(sb, es, 1); |
| 514 | } | 517 | } |
| 518 | if (sbi->s_proc) { | ||
| 519 | remove_proc_entry("inode_readahead_blks", sbi->s_proc); | ||
| 520 | remove_proc_entry(sb->s_id, ext4_proc_root); | ||
| 521 | } | ||
| 515 | 522 | ||
| 516 | for (i = 0; i < sbi->s_gdb_count; i++) | 523 | for (i = 0; i < sbi->s_gdb_count; i++) |
| 517 | brelse(sbi->s_group_desc[i]); | 524 | brelse(sbi->s_group_desc[i]); |
| @@ -520,6 +527,7 @@ static void ext4_put_super(struct super_block *sb) | |||
| 520 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | 527 | percpu_counter_destroy(&sbi->s_freeblocks_counter); |
| 521 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 528 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
| 522 | percpu_counter_destroy(&sbi->s_dirs_counter); | 529 | percpu_counter_destroy(&sbi->s_dirs_counter); |
| 530 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
| 523 | brelse(sbi->s_sbh); | 531 | brelse(sbi->s_sbh); |
| 524 | #ifdef CONFIG_QUOTA | 532 | #ifdef CONFIG_QUOTA |
| 525 | for (i = 0; i < MAXQUOTAS; i++) | 533 | for (i = 0; i < MAXQUOTAS; i++) |
| @@ -562,11 +570,10 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
| 562 | ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS); | 570 | ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS); |
| 563 | if (!ei) | 571 | if (!ei) |
| 564 | return NULL; | 572 | return NULL; |
| 565 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 573 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
| 566 | ei->i_acl = EXT4_ACL_NOT_CACHED; | 574 | ei->i_acl = EXT4_ACL_NOT_CACHED; |
| 567 | ei->i_default_acl = EXT4_ACL_NOT_CACHED; | 575 | ei->i_default_acl = EXT4_ACL_NOT_CACHED; |
| 568 | #endif | 576 | #endif |
| 569 | ei->i_block_alloc_info = NULL; | ||
| 570 | ei->vfs_inode.i_version = 1; | 577 | ei->vfs_inode.i_version = 1; |
| 571 | ei->vfs_inode.i_data.writeback_index = 0; | 578 | ei->vfs_inode.i_data.writeback_index = 0; |
| 572 | memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); | 579 | memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); |
| @@ -599,7 +606,7 @@ static void init_once(void *foo) | |||
| 599 | struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; | 606 | struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; |
| 600 | 607 | ||
| 601 | INIT_LIST_HEAD(&ei->i_orphan); | 608 | INIT_LIST_HEAD(&ei->i_orphan); |
| 602 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 609 | #ifdef CONFIG_EXT4_FS_XATTR |
| 603 | init_rwsem(&ei->xattr_sem); | 610 | init_rwsem(&ei->xattr_sem); |
| 604 | #endif | 611 | #endif |
| 605 | init_rwsem(&ei->i_data_sem); | 612 | init_rwsem(&ei->i_data_sem); |
| @@ -625,8 +632,7 @@ static void destroy_inodecache(void) | |||
| 625 | 632 | ||
| 626 | static void ext4_clear_inode(struct inode *inode) | 633 | static void ext4_clear_inode(struct inode *inode) |
| 627 | { | 634 | { |
| 628 | struct ext4_block_alloc_info *rsv = EXT4_I(inode)->i_block_alloc_info; | 635 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
| 629 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | ||
| 630 | if (EXT4_I(inode)->i_acl && | 636 | if (EXT4_I(inode)->i_acl && |
| 631 | EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) { | 637 | EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) { |
| 632 | posix_acl_release(EXT4_I(inode)->i_acl); | 638 | posix_acl_release(EXT4_I(inode)->i_acl); |
| @@ -638,10 +644,7 @@ static void ext4_clear_inode(struct inode *inode) | |||
| 638 | EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED; | 644 | EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED; |
| 639 | } | 645 | } |
| 640 | #endif | 646 | #endif |
| 641 | ext4_discard_reservation(inode); | 647 | ext4_discard_preallocations(inode); |
| 642 | EXT4_I(inode)->i_block_alloc_info = NULL; | ||
| 643 | if (unlikely(rsv)) | ||
| 644 | kfree(rsv); | ||
| 645 | jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal, | 648 | jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal, |
| 646 | &EXT4_I(inode)->jinode); | 649 | &EXT4_I(inode)->jinode); |
| 647 | } | 650 | } |
| @@ -654,7 +657,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq, | |||
| 654 | 657 | ||
| 655 | if (sbi->s_jquota_fmt) | 658 | if (sbi->s_jquota_fmt) |
| 656 | seq_printf(seq, ",jqfmt=%s", | 659 | seq_printf(seq, ",jqfmt=%s", |
| 657 | (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0"); | 660 | (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0"); |
| 658 | 661 | ||
| 659 | if (sbi->s_qf_names[USRQUOTA]) | 662 | if (sbi->s_qf_names[USRQUOTA]) |
| 660 | seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); | 663 | seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); |
| @@ -718,7 +721,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 718 | seq_puts(seq, ",debug"); | 721 | seq_puts(seq, ",debug"); |
| 719 | if (test_opt(sb, OLDALLOC)) | 722 | if (test_opt(sb, OLDALLOC)) |
| 720 | seq_puts(seq, ",oldalloc"); | 723 | seq_puts(seq, ",oldalloc"); |
| 721 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 724 | #ifdef CONFIG_EXT4_FS_XATTR |
| 722 | if (test_opt(sb, XATTR_USER) && | 725 | if (test_opt(sb, XATTR_USER) && |
| 723 | !(def_mount_opts & EXT4_DEFM_XATTR_USER)) | 726 | !(def_mount_opts & EXT4_DEFM_XATTR_USER)) |
| 724 | seq_puts(seq, ",user_xattr"); | 727 | seq_puts(seq, ",user_xattr"); |
| @@ -727,7 +730,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 727 | seq_puts(seq, ",nouser_xattr"); | 730 | seq_puts(seq, ",nouser_xattr"); |
| 728 | } | 731 | } |
| 729 | #endif | 732 | #endif |
| 730 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 733 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
| 731 | if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) | 734 | if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) |
| 732 | seq_puts(seq, ",acl"); | 735 | seq_puts(seq, ",acl"); |
| 733 | if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) | 736 | if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) |
| @@ -752,8 +755,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 752 | seq_puts(seq, ",nobh"); | 755 | seq_puts(seq, ",nobh"); |
| 753 | if (!test_opt(sb, EXTENTS)) | 756 | if (!test_opt(sb, EXTENTS)) |
| 754 | seq_puts(seq, ",noextents"); | 757 | seq_puts(seq, ",noextents"); |
| 755 | if (!test_opt(sb, MBALLOC)) | ||
| 756 | seq_puts(seq, ",nomballoc"); | ||
| 757 | if (test_opt(sb, I_VERSION)) | 758 | if (test_opt(sb, I_VERSION)) |
| 758 | seq_puts(seq, ",i_version"); | 759 | seq_puts(seq, ",i_version"); |
| 759 | if (!test_opt(sb, DELALLOC)) | 760 | if (!test_opt(sb, DELALLOC)) |
| @@ -773,6 +774,13 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 773 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) | 774 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
| 774 | seq_puts(seq, ",data=writeback"); | 775 | seq_puts(seq, ",data=writeback"); |
| 775 | 776 | ||
| 777 | if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) | ||
| 778 | seq_printf(seq, ",inode_readahead_blks=%u", | ||
| 779 | sbi->s_inode_readahead_blks); | ||
| 780 | |||
| 781 | if (test_opt(sb, DATA_ERR_ABORT)) | ||
| 782 | seq_puts(seq, ",data_err=abort"); | ||
| 783 | |||
| 776 | ext4_show_quota_options(seq, sb); | 784 | ext4_show_quota_options(seq, sb); |
| 777 | return 0; | 785 | return 0; |
| 778 | } | 786 | } |
| @@ -822,7 +830,7 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, | |||
| 822 | } | 830 | } |
| 823 | 831 | ||
| 824 | #ifdef CONFIG_QUOTA | 832 | #ifdef CONFIG_QUOTA |
| 825 | #define QTYPE2NAME(t) ((t) == USRQUOTA?"user":"group") | 833 | #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group") |
| 826 | #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) | 834 | #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) |
| 827 | 835 | ||
| 828 | static int ext4_dquot_initialize(struct inode *inode, int type); | 836 | static int ext4_dquot_initialize(struct inode *inode, int type); |
| @@ -902,11 +910,13 @@ enum { | |||
| 902 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, | 910 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, |
| 903 | Opt_journal_checksum, Opt_journal_async_commit, | 911 | Opt_journal_checksum, Opt_journal_async_commit, |
| 904 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 912 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
| 913 | Opt_data_err_abort, Opt_data_err_ignore, | ||
| 905 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 914 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
| 906 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, | 915 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
| 907 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, | 916 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, |
| 908 | Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version, | 917 | Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version, |
| 909 | Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc, | 918 | Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc, |
| 919 | Opt_inode_readahead_blks | ||
| 910 | }; | 920 | }; |
| 911 | 921 | ||
| 912 | static match_table_t tokens = { | 922 | static match_table_t tokens = { |
| @@ -947,6 +957,8 @@ static match_table_t tokens = { | |||
| 947 | {Opt_data_journal, "data=journal"}, | 957 | {Opt_data_journal, "data=journal"}, |
| 948 | {Opt_data_ordered, "data=ordered"}, | 958 | {Opt_data_ordered, "data=ordered"}, |
| 949 | {Opt_data_writeback, "data=writeback"}, | 959 | {Opt_data_writeback, "data=writeback"}, |
| 960 | {Opt_data_err_abort, "data_err=abort"}, | ||
| 961 | {Opt_data_err_ignore, "data_err=ignore"}, | ||
| 950 | {Opt_offusrjquota, "usrjquota="}, | 962 | {Opt_offusrjquota, "usrjquota="}, |
| 951 | {Opt_usrjquota, "usrjquota=%s"}, | 963 | {Opt_usrjquota, "usrjquota=%s"}, |
| 952 | {Opt_offgrpjquota, "grpjquota="}, | 964 | {Opt_offgrpjquota, "grpjquota="}, |
| @@ -967,6 +979,7 @@ static match_table_t tokens = { | |||
| 967 | {Opt_resize, "resize"}, | 979 | {Opt_resize, "resize"}, |
| 968 | {Opt_delalloc, "delalloc"}, | 980 | {Opt_delalloc, "delalloc"}, |
| 969 | {Opt_nodelalloc, "nodelalloc"}, | 981 | {Opt_nodelalloc, "nodelalloc"}, |
| 982 | {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, | ||
| 970 | {Opt_err, NULL}, | 983 | {Opt_err, NULL}, |
| 971 | }; | 984 | }; |
| 972 | 985 | ||
| @@ -981,7 +994,7 @@ static ext4_fsblk_t get_sb_block(void **data) | |||
| 981 | /*todo: use simple_strtoll with >32bit ext4 */ | 994 | /*todo: use simple_strtoll with >32bit ext4 */ |
| 982 | sb_block = simple_strtoul(options, &options, 0); | 995 | sb_block = simple_strtoul(options, &options, 0); |
| 983 | if (*options && *options != ',') { | 996 | if (*options && *options != ',') { |
| 984 | printk("EXT4-fs: Invalid sb specification: %s\n", | 997 | printk(KERN_ERR "EXT4-fs: Invalid sb specification: %s\n", |
| 985 | (char *) *data); | 998 | (char *) *data); |
| 986 | return 1; | 999 | return 1; |
| 987 | } | 1000 | } |
| @@ -1072,7 +1085,7 @@ static int parse_options(char *options, struct super_block *sb, | |||
| 1072 | case Opt_orlov: | 1085 | case Opt_orlov: |
| 1073 | clear_opt(sbi->s_mount_opt, OLDALLOC); | 1086 | clear_opt(sbi->s_mount_opt, OLDALLOC); |
| 1074 | break; | 1087 | break; |
| 1075 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 1088 | #ifdef CONFIG_EXT4_FS_XATTR |
| 1076 | case Opt_user_xattr: | 1089 | case Opt_user_xattr: |
| 1077 | set_opt(sbi->s_mount_opt, XATTR_USER); | 1090 | set_opt(sbi->s_mount_opt, XATTR_USER); |
| 1078 | break; | 1091 | break; |
| @@ -1082,10 +1095,11 @@ static int parse_options(char *options, struct super_block *sb, | |||
| 1082 | #else | 1095 | #else |
| 1083 | case Opt_user_xattr: | 1096 | case Opt_user_xattr: |
| 1084 | case Opt_nouser_xattr: | 1097 | case Opt_nouser_xattr: |
| 1085 | printk("EXT4 (no)user_xattr options not supported\n"); | 1098 | printk(KERN_ERR "EXT4 (no)user_xattr options " |
| 1099 | "not supported\n"); | ||
| 1086 | break; | 1100 | break; |
| 1087 | #endif | 1101 | #endif |
| 1088 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 1102 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
| 1089 | case Opt_acl: | 1103 | case Opt_acl: |
| 1090 | set_opt(sbi->s_mount_opt, POSIX_ACL); | 1104 | set_opt(sbi->s_mount_opt, POSIX_ACL); |
| 1091 | break; | 1105 | break; |
| @@ -1095,7 +1109,8 @@ static int parse_options(char *options, struct super_block *sb, | |||
| 1095 | #else | 1109 | #else |
| 1096 | case Opt_acl: | 1110 | case Opt_acl: |
| 1097 | case Opt_noacl: | 1111 | case Opt_noacl: |
| 1098 | printk("EXT4 (no)acl options not supported\n"); | 1112 | printk(KERN_ERR "EXT4 (no)acl options " |
| 1113 | "not supported\n"); | ||
| 1099 | break; | 1114 | break; |
| 1100 | #endif | 1115 | #endif |
| 1101 | case Opt_reservation: | 1116 | case Opt_reservation: |
| @@ -1178,6 +1193,12 @@ static int parse_options(char *options, struct super_block *sb, | |||
| 1178 | sbi->s_mount_opt |= data_opt; | 1193 | sbi->s_mount_opt |= data_opt; |
| 1179 | } | 1194 | } |
| 1180 | break; | 1195 | break; |
| 1196 | case Opt_data_err_abort: | ||
| 1197 | set_opt(sbi->s_mount_opt, DATA_ERR_ABORT); | ||
| 1198 | break; | ||
| 1199 | case Opt_data_err_ignore: | ||
| 1200 | clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT); | ||
| 1201 | break; | ||
| 1181 | #ifdef CONFIG_QUOTA | 1202 | #ifdef CONFIG_QUOTA |
| 1182 | case Opt_usrjquota: | 1203 | case Opt_usrjquota: |
| 1183 | qtype = USRQUOTA; | 1204 | qtype = USRQUOTA; |
| @@ -1189,8 +1210,8 @@ set_qf_name: | |||
| 1189 | sb_any_quota_suspended(sb)) && | 1210 | sb_any_quota_suspended(sb)) && |
| 1190 | !sbi->s_qf_names[qtype]) { | 1211 | !sbi->s_qf_names[qtype]) { |
| 1191 | printk(KERN_ERR | 1212 | printk(KERN_ERR |
| 1192 | "EXT4-fs: Cannot change journaled " | 1213 | "EXT4-fs: Cannot change journaled " |
| 1193 | "quota options when quota turned on.\n"); | 1214 | "quota options when quota turned on.\n"); |
| 1194 | return 0; | 1215 | return 0; |
| 1195 | } | 1216 | } |
| 1196 | qname = match_strdup(&args[0]); | 1217 | qname = match_strdup(&args[0]); |
| @@ -1357,12 +1378,6 @@ set_qf_format: | |||
| 1357 | case Opt_nodelalloc: | 1378 | case Opt_nodelalloc: |
| 1358 | clear_opt(sbi->s_mount_opt, DELALLOC); | 1379 | clear_opt(sbi->s_mount_opt, DELALLOC); |
| 1359 | break; | 1380 | break; |
| 1360 | case Opt_mballoc: | ||
| 1361 | set_opt(sbi->s_mount_opt, MBALLOC); | ||
| 1362 | break; | ||
| 1363 | case Opt_nomballoc: | ||
| 1364 | clear_opt(sbi->s_mount_opt, MBALLOC); | ||
| 1365 | break; | ||
| 1366 | case Opt_stripe: | 1381 | case Opt_stripe: |
| 1367 | if (match_int(&args[0], &option)) | 1382 | if (match_int(&args[0], &option)) |
| 1368 | return 0; | 1383 | return 0; |
| @@ -1373,6 +1388,13 @@ set_qf_format: | |||
| 1373 | case Opt_delalloc: | 1388 | case Opt_delalloc: |
| 1374 | set_opt(sbi->s_mount_opt, DELALLOC); | 1389 | set_opt(sbi->s_mount_opt, DELALLOC); |
| 1375 | break; | 1390 | break; |
| 1391 | case Opt_inode_readahead_blks: | ||
| 1392 | if (match_int(&args[0], &option)) | ||
| 1393 | return 0; | ||
| 1394 | if (option < 0 || option > (1 << 30)) | ||
| 1395 | return 0; | ||
| 1396 | sbi->s_inode_readahead_blks = option; | ||
| 1397 | break; | ||
| 1376 | default: | 1398 | default: |
| 1377 | printk(KERN_ERR | 1399 | printk(KERN_ERR |
| 1378 | "EXT4-fs: Unrecognized mount option \"%s\" " | 1400 | "EXT4-fs: Unrecognized mount option \"%s\" " |
| @@ -1473,15 +1495,9 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, | |||
| 1473 | EXT4_INODES_PER_GROUP(sb), | 1495 | EXT4_INODES_PER_GROUP(sb), |
| 1474 | sbi->s_mount_opt); | 1496 | sbi->s_mount_opt); |
| 1475 | 1497 | ||
| 1476 | printk(KERN_INFO "EXT4 FS on %s, ", sb->s_id); | 1498 | printk(KERN_INFO "EXT4 FS on %s, %s journal on %s\n", |
| 1477 | if (EXT4_SB(sb)->s_journal->j_inode == NULL) { | 1499 | sb->s_id, EXT4_SB(sb)->s_journal->j_inode ? "internal" : |
| 1478 | char b[BDEVNAME_SIZE]; | 1500 | "external", EXT4_SB(sb)->s_journal->j_devname); |
| 1479 | |||
| 1480 | printk("external journal on %s\n", | ||
| 1481 | bdevname(EXT4_SB(sb)->s_journal->j_dev, b)); | ||
| 1482 | } else { | ||
| 1483 | printk("internal journal\n"); | ||
| 1484 | } | ||
| 1485 | return res; | 1501 | return res; |
| 1486 | } | 1502 | } |
| 1487 | 1503 | ||
| @@ -1504,8 +1520,11 @@ static int ext4_fill_flex_info(struct super_block *sb) | |||
| 1504 | sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; | 1520 | sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; |
| 1505 | groups_per_flex = 1 << sbi->s_log_groups_per_flex; | 1521 | groups_per_flex = 1 << sbi->s_log_groups_per_flex; |
| 1506 | 1522 | ||
| 1507 | flex_group_count = (sbi->s_groups_count + groups_per_flex - 1) / | 1523 | /* We allocate both existing and potentially added groups */ |
| 1508 | groups_per_flex; | 1524 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + |
| 1525 | ((sbi->s_es->s_reserved_gdt_blocks +1 ) << | ||
| 1526 | EXT4_DESC_PER_BLOCK_BITS(sb))) / | ||
| 1527 | groups_per_flex; | ||
| 1509 | sbi->s_flex_groups = kzalloc(flex_group_count * | 1528 | sbi->s_flex_groups = kzalloc(flex_group_count * |
| 1510 | sizeof(struct flex_groups), GFP_KERNEL); | 1529 | sizeof(struct flex_groups), GFP_KERNEL); |
| 1511 | if (sbi->s_flex_groups == NULL) { | 1530 | if (sbi->s_flex_groups == NULL) { |
| @@ -1584,7 +1603,7 @@ static int ext4_check_descriptors(struct super_block *sb) | |||
| 1584 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | 1603 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) |
| 1585 | flexbg_flag = 1; | 1604 | flexbg_flag = 1; |
| 1586 | 1605 | ||
| 1587 | ext4_debug ("Checking group descriptors"); | 1606 | ext4_debug("Checking group descriptors"); |
| 1588 | 1607 | ||
| 1589 | for (i = 0; i < sbi->s_groups_count; i++) { | 1608 | for (i = 0; i < sbi->s_groups_count; i++) { |
| 1590 | struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL); | 1609 | struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL); |
| @@ -1623,8 +1642,10 @@ static int ext4_check_descriptors(struct super_block *sb) | |||
| 1623 | "Checksum for group %lu failed (%u!=%u)\n", | 1642 | "Checksum for group %lu failed (%u!=%u)\n", |
| 1624 | i, le16_to_cpu(ext4_group_desc_csum(sbi, i, | 1643 | i, le16_to_cpu(ext4_group_desc_csum(sbi, i, |
| 1625 | gdp)), le16_to_cpu(gdp->bg_checksum)); | 1644 | gdp)), le16_to_cpu(gdp->bg_checksum)); |
| 1626 | if (!(sb->s_flags & MS_RDONLY)) | 1645 | if (!(sb->s_flags & MS_RDONLY)) { |
| 1646 | spin_unlock(sb_bgl_lock(sbi, i)); | ||
| 1627 | return 0; | 1647 | return 0; |
| 1648 | } | ||
| 1628 | } | 1649 | } |
| 1629 | spin_unlock(sb_bgl_lock(sbi, i)); | 1650 | spin_unlock(sb_bgl_lock(sbi, i)); |
| 1630 | if (!flexbg_flag) | 1651 | if (!flexbg_flag) |
| @@ -1714,9 +1735,9 @@ static void ext4_orphan_cleanup(struct super_block *sb, | |||
| 1714 | DQUOT_INIT(inode); | 1735 | DQUOT_INIT(inode); |
| 1715 | if (inode->i_nlink) { | 1736 | if (inode->i_nlink) { |
| 1716 | printk(KERN_DEBUG | 1737 | printk(KERN_DEBUG |
| 1717 | "%s: truncating inode %lu to %Ld bytes\n", | 1738 | "%s: truncating inode %lu to %lld bytes\n", |
| 1718 | __func__, inode->i_ino, inode->i_size); | 1739 | __func__, inode->i_ino, inode->i_size); |
| 1719 | jbd_debug(2, "truncating inode %lu to %Ld bytes\n", | 1740 | jbd_debug(2, "truncating inode %lu to %lld bytes\n", |
| 1720 | inode->i_ino, inode->i_size); | 1741 | inode->i_ino, inode->i_size); |
| 1721 | ext4_truncate(inode); | 1742 | ext4_truncate(inode); |
| 1722 | nr_truncates++; | 1743 | nr_truncates++; |
| @@ -1914,6 +1935,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1914 | unsigned long journal_devnum = 0; | 1935 | unsigned long journal_devnum = 0; |
| 1915 | unsigned long def_mount_opts; | 1936 | unsigned long def_mount_opts; |
| 1916 | struct inode *root; | 1937 | struct inode *root; |
| 1938 | char *cp; | ||
| 1917 | int ret = -EINVAL; | 1939 | int ret = -EINVAL; |
| 1918 | int blocksize; | 1940 | int blocksize; |
| 1919 | int db_count; | 1941 | int db_count; |
| @@ -1930,10 +1952,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1930 | sbi->s_mount_opt = 0; | 1952 | sbi->s_mount_opt = 0; |
| 1931 | sbi->s_resuid = EXT4_DEF_RESUID; | 1953 | sbi->s_resuid = EXT4_DEF_RESUID; |
| 1932 | sbi->s_resgid = EXT4_DEF_RESGID; | 1954 | sbi->s_resgid = EXT4_DEF_RESGID; |
| 1955 | sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; | ||
| 1933 | sbi->s_sb_block = sb_block; | 1956 | sbi->s_sb_block = sb_block; |
| 1934 | 1957 | ||
| 1935 | unlock_kernel(); | 1958 | unlock_kernel(); |
| 1936 | 1959 | ||
| 1960 | /* Cleanup superblock name */ | ||
| 1961 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) | ||
| 1962 | *cp = '!'; | ||
| 1963 | |||
| 1937 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); | 1964 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); |
| 1938 | if (!blocksize) { | 1965 | if (!blocksize) { |
| 1939 | printk(KERN_ERR "EXT4-fs: unable to set blocksize\n"); | 1966 | printk(KERN_ERR "EXT4-fs: unable to set blocksize\n"); |
| @@ -1973,11 +2000,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1973 | set_opt(sbi->s_mount_opt, GRPID); | 2000 | set_opt(sbi->s_mount_opt, GRPID); |
| 1974 | if (def_mount_opts & EXT4_DEFM_UID16) | 2001 | if (def_mount_opts & EXT4_DEFM_UID16) |
| 1975 | set_opt(sbi->s_mount_opt, NO_UID32); | 2002 | set_opt(sbi->s_mount_opt, NO_UID32); |
| 1976 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 2003 | #ifdef CONFIG_EXT4_FS_XATTR |
| 1977 | if (def_mount_opts & EXT4_DEFM_XATTR_USER) | 2004 | if (def_mount_opts & EXT4_DEFM_XATTR_USER) |
| 1978 | set_opt(sbi->s_mount_opt, XATTR_USER); | 2005 | set_opt(sbi->s_mount_opt, XATTR_USER); |
| 1979 | #endif | 2006 | #endif |
| 1980 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 2007 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
| 1981 | if (def_mount_opts & EXT4_DEFM_ACL) | 2008 | if (def_mount_opts & EXT4_DEFM_ACL) |
| 1982 | set_opt(sbi->s_mount_opt, POSIX_ACL); | 2009 | set_opt(sbi->s_mount_opt, POSIX_ACL); |
| 1983 | #endif | 2010 | #endif |
| @@ -2012,11 +2039,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2012 | ext4_warning(sb, __func__, | 2039 | ext4_warning(sb, __func__, |
| 2013 | "extents feature not enabled on this filesystem, " | 2040 | "extents feature not enabled on this filesystem, " |
| 2014 | "use tune2fs.\n"); | 2041 | "use tune2fs.\n"); |
| 2015 | /* | ||
| 2016 | * turn on mballoc code by default in ext4 filesystem | ||
| 2017 | * Use -o nomballoc to turn it off | ||
| 2018 | */ | ||
| 2019 | set_opt(sbi->s_mount_opt, MBALLOC); | ||
| 2020 | 2042 | ||
| 2021 | /* | 2043 | /* |
| 2022 | * enable delayed allocation by default | 2044 | * enable delayed allocation by default |
| @@ -2041,16 +2063,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2041 | "running e2fsck is recommended\n"); | 2063 | "running e2fsck is recommended\n"); |
| 2042 | 2064 | ||
| 2043 | /* | 2065 | /* |
| 2044 | * Since ext4 is still considered development code, we require | ||
| 2045 | * that the TEST_FILESYS flag in s->flags be set. | ||
| 2046 | */ | ||
| 2047 | if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) { | ||
| 2048 | printk(KERN_WARNING "EXT4-fs: %s: not marked " | ||
| 2049 | "OK to use with test code.\n", sb->s_id); | ||
| 2050 | goto failed_mount; | ||
| 2051 | } | ||
| 2052 | |||
| 2053 | /* | ||
| 2054 | * Check feature flags regardless of the revision level, since we | 2066 | * Check feature flags regardless of the revision level, since we |
| 2055 | * previously didn't change the revision level when setting the flags, | 2067 | * previously didn't change the revision level when setting the flags, |
| 2056 | * so there is a chance incompat flags are set on a rev 0 filesystem. | 2068 | * so there is a chance incompat flags are set on a rev 0 filesystem. |
| @@ -2219,6 +2231,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2219 | goto failed_mount; | 2231 | goto failed_mount; |
| 2220 | } | 2232 | } |
| 2221 | 2233 | ||
| 2234 | #ifdef CONFIG_PROC_FS | ||
| 2235 | if (ext4_proc_root) | ||
| 2236 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); | ||
| 2237 | |||
| 2238 | if (sbi->s_proc) | ||
| 2239 | proc_create_data("inode_readahead_blks", 0644, sbi->s_proc, | ||
| 2240 | &ext4_ui_proc_fops, | ||
| 2241 | &sbi->s_inode_readahead_blks); | ||
| 2242 | #endif | ||
| 2243 | |||
| 2222 | bgl_lock_init(&sbi->s_blockgroup_lock); | 2244 | bgl_lock_init(&sbi->s_blockgroup_lock); |
| 2223 | 2245 | ||
| 2224 | for (i = 0; i < db_count; i++) { | 2246 | for (i = 0; i < db_count; i++) { |
| @@ -2257,24 +2279,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2257 | err = percpu_counter_init(&sbi->s_dirs_counter, | 2279 | err = percpu_counter_init(&sbi->s_dirs_counter, |
| 2258 | ext4_count_dirs(sb)); | 2280 | ext4_count_dirs(sb)); |
| 2259 | } | 2281 | } |
| 2282 | if (!err) { | ||
| 2283 | err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); | ||
| 2284 | } | ||
| 2260 | if (err) { | 2285 | if (err) { |
| 2261 | printk(KERN_ERR "EXT4-fs: insufficient memory\n"); | 2286 | printk(KERN_ERR "EXT4-fs: insufficient memory\n"); |
| 2262 | goto failed_mount3; | 2287 | goto failed_mount3; |
| 2263 | } | 2288 | } |
| 2264 | 2289 | ||
| 2265 | /* per fileystem reservation list head & lock */ | ||
| 2266 | spin_lock_init(&sbi->s_rsv_window_lock); | ||
| 2267 | sbi->s_rsv_window_root = RB_ROOT; | ||
| 2268 | /* Add a single, static dummy reservation to the start of the | ||
| 2269 | * reservation window list --- it gives us a placeholder for | ||
| 2270 | * append-at-start-of-list which makes the allocation logic | ||
| 2271 | * _much_ simpler. */ | ||
| 2272 | sbi->s_rsv_window_head.rsv_start = EXT4_RESERVE_WINDOW_NOT_ALLOCATED; | ||
| 2273 | sbi->s_rsv_window_head.rsv_end = EXT4_RESERVE_WINDOW_NOT_ALLOCATED; | ||
| 2274 | sbi->s_rsv_window_head.rsv_alloc_hit = 0; | ||
| 2275 | sbi->s_rsv_window_head.rsv_goal_size = 0; | ||
| 2276 | ext4_rsv_window_add(sb, &sbi->s_rsv_window_head); | ||
| 2277 | |||
| 2278 | sbi->s_stripe = ext4_get_stripe_size(sbi); | 2290 | sbi->s_stripe = ext4_get_stripe_size(sbi); |
| 2279 | 2291 | ||
| 2280 | /* | 2292 | /* |
| @@ -2471,7 +2483,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2471 | printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n"); | 2483 | printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n"); |
| 2472 | 2484 | ||
| 2473 | ext4_ext_init(sb); | 2485 | ext4_ext_init(sb); |
| 2474 | ext4_mb_init(sb, needs_recovery); | 2486 | err = ext4_mb_init(sb, needs_recovery); |
| 2487 | if (err) { | ||
| 2488 | printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n", | ||
| 2489 | err); | ||
| 2490 | goto failed_mount4; | ||
| 2491 | } | ||
| 2475 | 2492 | ||
| 2476 | lock_kernel(); | 2493 | lock_kernel(); |
| 2477 | return 0; | 2494 | return 0; |
| @@ -2489,11 +2506,16 @@ failed_mount3: | |||
| 2489 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | 2506 | percpu_counter_destroy(&sbi->s_freeblocks_counter); |
| 2490 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 2507 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
| 2491 | percpu_counter_destroy(&sbi->s_dirs_counter); | 2508 | percpu_counter_destroy(&sbi->s_dirs_counter); |
| 2509 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
| 2492 | failed_mount2: | 2510 | failed_mount2: |
| 2493 | for (i = 0; i < db_count; i++) | 2511 | for (i = 0; i < db_count; i++) |
| 2494 | brelse(sbi->s_group_desc[i]); | 2512 | brelse(sbi->s_group_desc[i]); |
| 2495 | kfree(sbi->s_group_desc); | 2513 | kfree(sbi->s_group_desc); |
| 2496 | failed_mount: | 2514 | failed_mount: |
| 2515 | if (sbi->s_proc) { | ||
| 2516 | remove_proc_entry("inode_readahead_blks", sbi->s_proc); | ||
| 2517 | remove_proc_entry(sb->s_id, ext4_proc_root); | ||
| 2518 | } | ||
| 2497 | #ifdef CONFIG_QUOTA | 2519 | #ifdef CONFIG_QUOTA |
| 2498 | for (i = 0; i < MAXQUOTAS; i++) | 2520 | for (i = 0; i < MAXQUOTAS; i++) |
| 2499 | kfree(sbi->s_qf_names[i]); | 2521 | kfree(sbi->s_qf_names[i]); |
| @@ -2527,6 +2549,10 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal) | |||
| 2527 | journal->j_flags |= JBD2_BARRIER; | 2549 | journal->j_flags |= JBD2_BARRIER; |
| 2528 | else | 2550 | else |
| 2529 | journal->j_flags &= ~JBD2_BARRIER; | 2551 | journal->j_flags &= ~JBD2_BARRIER; |
| 2552 | if (test_opt(sb, DATA_ERR_ABORT)) | ||
| 2553 | journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR; | ||
| 2554 | else | ||
| 2555 | journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR; | ||
| 2530 | spin_unlock(&journal->j_state_lock); | 2556 | spin_unlock(&journal->j_state_lock); |
| 2531 | } | 2557 | } |
| 2532 | 2558 | ||
| @@ -2552,7 +2578,7 @@ static journal_t *ext4_get_journal(struct super_block *sb, | |||
| 2552 | return NULL; | 2578 | return NULL; |
| 2553 | } | 2579 | } |
| 2554 | 2580 | ||
| 2555 | jbd_debug(2, "Journal inode found at %p: %Ld bytes\n", | 2581 | jbd_debug(2, "Journal inode found at %p: %lld bytes\n", |
| 2556 | journal_inode, journal_inode->i_size); | 2582 | journal_inode, journal_inode->i_size); |
| 2557 | if (!S_ISREG(journal_inode->i_mode)) { | 2583 | if (!S_ISREG(journal_inode->i_mode)) { |
| 2558 | printk(KERN_ERR "EXT4-fs: invalid journal inode.\n"); | 2584 | printk(KERN_ERR "EXT4-fs: invalid journal inode.\n"); |
| @@ -2715,6 +2741,11 @@ static int ext4_load_journal(struct super_block *sb, | |||
| 2715 | return -EINVAL; | 2741 | return -EINVAL; |
| 2716 | } | 2742 | } |
| 2717 | 2743 | ||
| 2744 | if (journal->j_flags & JBD2_BARRIER) | ||
| 2745 | printk(KERN_INFO "EXT4-fs: barriers enabled\n"); | ||
| 2746 | else | ||
| 2747 | printk(KERN_INFO "EXT4-fs: barriers disabled\n"); | ||
| 2748 | |||
| 2718 | if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { | 2749 | if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { |
| 2719 | err = jbd2_journal_update_format(journal); | 2750 | err = jbd2_journal_update_format(journal); |
| 2720 | if (err) { | 2751 | if (err) { |
| @@ -2799,13 +2830,34 @@ static void ext4_commit_super(struct super_block *sb, | |||
| 2799 | 2830 | ||
| 2800 | if (!sbh) | 2831 | if (!sbh) |
| 2801 | return; | 2832 | return; |
| 2833 | if (buffer_write_io_error(sbh)) { | ||
| 2834 | /* | ||
| 2835 | * Oh, dear. A previous attempt to write the | ||
| 2836 | * superblock failed. This could happen because the | ||
| 2837 | * USB device was yanked out. Or it could happen to | ||
| 2838 | * be a transient write error and maybe the block will | ||
| 2839 | * be remapped. Nothing we can do but to retry the | ||
| 2840 | * write and hope for the best. | ||
| 2841 | */ | ||
| 2842 | printk(KERN_ERR "ext4: previous I/O error to " | ||
| 2843 | "superblock detected for %s.\n", sb->s_id); | ||
| 2844 | clear_buffer_write_io_error(sbh); | ||
| 2845 | set_buffer_uptodate(sbh); | ||
| 2846 | } | ||
| 2802 | es->s_wtime = cpu_to_le32(get_seconds()); | 2847 | es->s_wtime = cpu_to_le32(get_seconds()); |
| 2803 | ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb)); | 2848 | ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb)); |
| 2804 | es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb)); | 2849 | es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb)); |
| 2805 | BUFFER_TRACE(sbh, "marking dirty"); | 2850 | BUFFER_TRACE(sbh, "marking dirty"); |
| 2806 | mark_buffer_dirty(sbh); | 2851 | mark_buffer_dirty(sbh); |
| 2807 | if (sync) | 2852 | if (sync) { |
| 2808 | sync_dirty_buffer(sbh); | 2853 | sync_dirty_buffer(sbh); |
| 2854 | if (buffer_write_io_error(sbh)) { | ||
| 2855 | printk(KERN_ERR "ext4: I/O error while writing " | ||
| 2856 | "superblock for %s.\n", sb->s_id); | ||
| 2857 | clear_buffer_write_io_error(sbh); | ||
| 2858 | set_buffer_uptodate(sbh); | ||
| 2859 | } | ||
| 2860 | } | ||
| 2809 | } | 2861 | } |
| 2810 | 2862 | ||
| 2811 | 2863 | ||
| @@ -2820,7 +2872,9 @@ static void ext4_mark_recovery_complete(struct super_block *sb, | |||
| 2820 | journal_t *journal = EXT4_SB(sb)->s_journal; | 2872 | journal_t *journal = EXT4_SB(sb)->s_journal; |
| 2821 | 2873 | ||
| 2822 | jbd2_journal_lock_updates(journal); | 2874 | jbd2_journal_lock_updates(journal); |
| 2823 | jbd2_journal_flush(journal); | 2875 | if (jbd2_journal_flush(journal) < 0) |
| 2876 | goto out; | ||
| 2877 | |||
| 2824 | lock_super(sb); | 2878 | lock_super(sb); |
| 2825 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && | 2879 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && |
| 2826 | sb->s_flags & MS_RDONLY) { | 2880 | sb->s_flags & MS_RDONLY) { |
| @@ -2829,6 +2883,8 @@ static void ext4_mark_recovery_complete(struct super_block *sb, | |||
| 2829 | ext4_commit_super(sb, es, 1); | 2883 | ext4_commit_super(sb, es, 1); |
| 2830 | } | 2884 | } |
| 2831 | unlock_super(sb); | 2885 | unlock_super(sb); |
| 2886 | |||
| 2887 | out: | ||
| 2832 | jbd2_journal_unlock_updates(journal); | 2888 | jbd2_journal_unlock_updates(journal); |
| 2833 | } | 2889 | } |
| 2834 | 2890 | ||
| @@ -2907,6 +2963,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
| 2907 | { | 2963 | { |
| 2908 | tid_t target; | 2964 | tid_t target; |
| 2909 | 2965 | ||
| 2966 | trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); | ||
| 2910 | sb->s_dirt = 0; | 2967 | sb->s_dirt = 0; |
| 2911 | if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { | 2968 | if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { |
| 2912 | if (wait) | 2969 | if (wait) |
| @@ -2928,7 +2985,13 @@ static void ext4_write_super_lockfs(struct super_block *sb) | |||
| 2928 | 2985 | ||
| 2929 | /* Now we set up the journal barrier. */ | 2986 | /* Now we set up the journal barrier. */ |
| 2930 | jbd2_journal_lock_updates(journal); | 2987 | jbd2_journal_lock_updates(journal); |
| 2931 | jbd2_journal_flush(journal); | 2988 | |
| 2989 | /* | ||
| 2990 | * We don't want to clear needs_recovery flag when we failed | ||
| 2991 | * to flush the journal. | ||
| 2992 | */ | ||
| 2993 | if (jbd2_journal_flush(journal) < 0) | ||
| 2994 | return; | ||
| 2932 | 2995 | ||
| 2933 | /* Journal blocked and flushed, clear needs_recovery flag. */ | 2996 | /* Journal blocked and flushed, clear needs_recovery flag. */ |
| 2934 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 2997 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
| @@ -3162,7 +3225,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 3162 | buf->f_type = EXT4_SUPER_MAGIC; | 3225 | buf->f_type = EXT4_SUPER_MAGIC; |
| 3163 | buf->f_bsize = sb->s_blocksize; | 3226 | buf->f_bsize = sb->s_blocksize; |
| 3164 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; | 3227 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; |
| 3165 | buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter); | 3228 | buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - |
| 3229 | percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); | ||
| 3166 | ext4_free_blocks_count_set(es, buf->f_bfree); | 3230 | ext4_free_blocks_count_set(es, buf->f_bfree); |
| 3167 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); | 3231 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); |
| 3168 | if (buf->f_bfree < ext4_r_blocks_count(es)) | 3232 | if (buf->f_bfree < ext4_r_blocks_count(es)) |
| @@ -3367,8 +3431,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, | |||
| 3367 | * otherwise be livelocked... | 3431 | * otherwise be livelocked... |
| 3368 | */ | 3432 | */ |
| 3369 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 3433 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
| 3370 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 3434 | err = jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
| 3371 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 3435 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
| 3436 | if (err) { | ||
| 3437 | path_put(&nd.path); | ||
| 3438 | return err; | ||
| 3439 | } | ||
| 3372 | } | 3440 | } |
| 3373 | 3441 | ||
| 3374 | err = vfs_quota_on_path(sb, type, format_id, &nd.path); | 3442 | err = vfs_quota_on_path(sb, type, format_id, &nd.path); |
| @@ -3432,7 +3500,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, | |||
| 3432 | handle_t *handle = journal_current_handle(); | 3500 | handle_t *handle = journal_current_handle(); |
| 3433 | 3501 | ||
| 3434 | if (!handle) { | 3502 | if (!handle) { |
| 3435 | printk(KERN_WARNING "EXT4-fs: Quota write (off=%Lu, len=%Lu)" | 3503 | printk(KERN_WARNING "EXT4-fs: Quota write (off=%llu, len=%llu)" |
| 3436 | " cancelled because transaction is not started.\n", | 3504 | " cancelled because transaction is not started.\n", |
| 3437 | (unsigned long long)off, (unsigned long long)len); | 3505 | (unsigned long long)off, (unsigned long long)len); |
| 3438 | return -EIO; | 3506 | return -EIO; |
| @@ -3493,18 +3561,82 @@ static int ext4_get_sb(struct file_system_type *fs_type, | |||
| 3493 | return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt); | 3561 | return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt); |
| 3494 | } | 3562 | } |
| 3495 | 3563 | ||
| 3564 | #ifdef CONFIG_PROC_FS | ||
| 3565 | static int ext4_ui_proc_show(struct seq_file *m, void *v) | ||
| 3566 | { | ||
| 3567 | unsigned int *p = m->private; | ||
| 3568 | |||
| 3569 | seq_printf(m, "%u\n", *p); | ||
| 3570 | return 0; | ||
| 3571 | } | ||
| 3572 | |||
| 3573 | static int ext4_ui_proc_open(struct inode *inode, struct file *file) | ||
| 3574 | { | ||
| 3575 | return single_open(file, ext4_ui_proc_show, PDE(inode)->data); | ||
| 3576 | } | ||
| 3577 | |||
| 3578 | static ssize_t ext4_ui_proc_write(struct file *file, const char __user *buf, | ||
| 3579 | size_t cnt, loff_t *ppos) | ||
| 3580 | { | ||
| 3581 | unsigned int *p = PDE(file->f_path.dentry->d_inode)->data; | ||
| 3582 | char str[32]; | ||
| 3583 | unsigned long value; | ||
| 3584 | |||
| 3585 | if (cnt >= sizeof(str)) | ||
| 3586 | return -EINVAL; | ||
| 3587 | if (copy_from_user(str, buf, cnt)) | ||
| 3588 | return -EFAULT; | ||
| 3589 | value = simple_strtol(str, NULL, 0); | ||
| 3590 | if (value < 0) | ||
| 3591 | return -ERANGE; | ||
| 3592 | *p = value; | ||
| 3593 | return cnt; | ||
| 3594 | } | ||
| 3595 | |||
| 3596 | const struct file_operations ext4_ui_proc_fops = { | ||
| 3597 | .owner = THIS_MODULE, | ||
| 3598 | .open = ext4_ui_proc_open, | ||
| 3599 | .read = seq_read, | ||
| 3600 | .llseek = seq_lseek, | ||
| 3601 | .release = single_release, | ||
| 3602 | .write = ext4_ui_proc_write, | ||
| 3603 | }; | ||
| 3604 | #endif | ||
| 3605 | |||
| 3606 | static struct file_system_type ext4_fs_type = { | ||
| 3607 | .owner = THIS_MODULE, | ||
| 3608 | .name = "ext4", | ||
| 3609 | .get_sb = ext4_get_sb, | ||
| 3610 | .kill_sb = kill_block_super, | ||
| 3611 | .fs_flags = FS_REQUIRES_DEV, | ||
| 3612 | }; | ||
| 3613 | |||
| 3614 | #ifdef CONFIG_EXT4DEV_COMPAT | ||
| 3615 | static int ext4dev_get_sb(struct file_system_type *fs_type, | ||
| 3616 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | ||
| 3617 | { | ||
| 3618 | printk(KERN_WARNING "EXT4-fs: Update your userspace programs " | ||
| 3619 | "to mount using ext4\n"); | ||
| 3620 | printk(KERN_WARNING "EXT4-fs: ext4dev backwards compatibility " | ||
| 3621 | "will go away by 2.6.31\n"); | ||
| 3622 | return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt); | ||
| 3623 | } | ||
| 3624 | |||
| 3496 | static struct file_system_type ext4dev_fs_type = { | 3625 | static struct file_system_type ext4dev_fs_type = { |
| 3497 | .owner = THIS_MODULE, | 3626 | .owner = THIS_MODULE, |
| 3498 | .name = "ext4dev", | 3627 | .name = "ext4dev", |
| 3499 | .get_sb = ext4_get_sb, | 3628 | .get_sb = ext4dev_get_sb, |
| 3500 | .kill_sb = kill_block_super, | 3629 | .kill_sb = kill_block_super, |
| 3501 | .fs_flags = FS_REQUIRES_DEV, | 3630 | .fs_flags = FS_REQUIRES_DEV, |
| 3502 | }; | 3631 | }; |
| 3632 | MODULE_ALIAS("ext4dev"); | ||
| 3633 | #endif | ||
| 3503 | 3634 | ||
| 3504 | static int __init init_ext4_fs(void) | 3635 | static int __init init_ext4_fs(void) |
| 3505 | { | 3636 | { |
| 3506 | int err; | 3637 | int err; |
| 3507 | 3638 | ||
| 3639 | ext4_proc_root = proc_mkdir("fs/ext4", NULL); | ||
| 3508 | err = init_ext4_mballoc(); | 3640 | err = init_ext4_mballoc(); |
| 3509 | if (err) | 3641 | if (err) |
| 3510 | return err; | 3642 | return err; |
| @@ -3515,9 +3647,16 @@ static int __init init_ext4_fs(void) | |||
| 3515 | err = init_inodecache(); | 3647 | err = init_inodecache(); |
| 3516 | if (err) | 3648 | if (err) |
| 3517 | goto out1; | 3649 | goto out1; |
| 3518 | err = register_filesystem(&ext4dev_fs_type); | 3650 | err = register_filesystem(&ext4_fs_type); |
| 3519 | if (err) | 3651 | if (err) |
| 3520 | goto out; | 3652 | goto out; |
| 3653 | #ifdef CONFIG_EXT4DEV_COMPAT | ||
| 3654 | err = register_filesystem(&ext4dev_fs_type); | ||
| 3655 | if (err) { | ||
| 3656 | unregister_filesystem(&ext4_fs_type); | ||
| 3657 | goto out; | ||
| 3658 | } | ||
| 3659 | #endif | ||
| 3521 | return 0; | 3660 | return 0; |
| 3522 | out: | 3661 | out: |
| 3523 | destroy_inodecache(); | 3662 | destroy_inodecache(); |
| @@ -3530,10 +3669,14 @@ out2: | |||
| 3530 | 3669 | ||
| 3531 | static void __exit exit_ext4_fs(void) | 3670 | static void __exit exit_ext4_fs(void) |
| 3532 | { | 3671 | { |
| 3672 | unregister_filesystem(&ext4_fs_type); | ||
| 3673 | #ifdef CONFIG_EXT4DEV_COMPAT | ||
| 3533 | unregister_filesystem(&ext4dev_fs_type); | 3674 | unregister_filesystem(&ext4dev_fs_type); |
| 3675 | #endif | ||
| 3534 | destroy_inodecache(); | 3676 | destroy_inodecache(); |
| 3535 | exit_ext4_xattr(); | 3677 | exit_ext4_xattr(); |
| 3536 | exit_ext4_mballoc(); | 3678 | exit_ext4_mballoc(); |
| 3679 | remove_proc_entry("fs/ext4", NULL); | ||
| 3537 | } | 3680 | } |
| 3538 | 3681 | ||
| 3539 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); | 3682 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); |
