diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 317 |
1 files changed, 230 insertions, 87 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 566344b926b7..dea8f13c2fd9 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,14 +910,16 @@ 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 const match_table_t tokens = { |
913 | {Opt_bsd_df, "bsddf"}, | 923 | {Opt_bsd_df, "bsddf"}, |
914 | {Opt_minix_df, "minixdf"}, | 924 | {Opt_minix_df, "minixdf"}, |
915 | {Opt_grpid, "grpid"}, | 925 | {Opt_grpid, "grpid"}, |
@@ -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"); |