diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 155 |
1 files changed, 113 insertions, 42 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d4ca92aab514..827bde1f2594 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -603,10 +603,6 @@ static void ext4_put_super(struct super_block *sb) | |||
603 | if (sb->s_dirt) | 603 | if (sb->s_dirt) |
604 | ext4_commit_super(sb, 1); | 604 | ext4_commit_super(sb, 1); |
605 | 605 | ||
606 | ext4_release_system_zone(sb); | ||
607 | ext4_mb_release(sb); | ||
608 | ext4_ext_release(sb); | ||
609 | ext4_xattr_put_super(sb); | ||
610 | if (sbi->s_journal) { | 606 | if (sbi->s_journal) { |
611 | err = jbd2_journal_destroy(sbi->s_journal); | 607 | err = jbd2_journal_destroy(sbi->s_journal); |
612 | sbi->s_journal = NULL; | 608 | sbi->s_journal = NULL; |
@@ -614,6 +610,12 @@ static void ext4_put_super(struct super_block *sb) | |||
614 | ext4_abort(sb, __func__, | 610 | ext4_abort(sb, __func__, |
615 | "Couldn't clean up the journal"); | 611 | "Couldn't clean up the journal"); |
616 | } | 612 | } |
613 | |||
614 | ext4_release_system_zone(sb); | ||
615 | ext4_mb_release(sb); | ||
616 | ext4_ext_release(sb); | ||
617 | ext4_xattr_put_super(sb); | ||
618 | |||
617 | if (!(sb->s_flags & MS_RDONLY)) { | 619 | if (!(sb->s_flags & MS_RDONLY)) { |
618 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 620 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
619 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 621 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
@@ -704,6 +706,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
704 | spin_lock_init(&(ei->i_block_reservation_lock)); | 706 | spin_lock_init(&(ei->i_block_reservation_lock)); |
705 | INIT_LIST_HEAD(&ei->i_aio_dio_complete_list); | 707 | INIT_LIST_HEAD(&ei->i_aio_dio_complete_list); |
706 | ei->cur_aio_dio = NULL; | 708 | ei->cur_aio_dio = NULL; |
709 | ei->i_sync_tid = 0; | ||
710 | ei->i_datasync_tid = 0; | ||
707 | 711 | ||
708 | return &ei->vfs_inode; | 712 | return &ei->vfs_inode; |
709 | } | 713 | } |
@@ -765,9 +769,22 @@ static inline void ext4_show_quota_options(struct seq_file *seq, | |||
765 | #if defined(CONFIG_QUOTA) | 769 | #if defined(CONFIG_QUOTA) |
766 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 770 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
767 | 771 | ||
768 | if (sbi->s_jquota_fmt) | 772 | if (sbi->s_jquota_fmt) { |
769 | seq_printf(seq, ",jqfmt=%s", | 773 | char *fmtname = ""; |
770 | (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0"); | 774 | |
775 | switch (sbi->s_jquota_fmt) { | ||
776 | case QFMT_VFS_OLD: | ||
777 | fmtname = "vfsold"; | ||
778 | break; | ||
779 | case QFMT_VFS_V0: | ||
780 | fmtname = "vfsv0"; | ||
781 | break; | ||
782 | case QFMT_VFS_V1: | ||
783 | fmtname = "vfsv1"; | ||
784 | break; | ||
785 | } | ||
786 | seq_printf(seq, ",jqfmt=%s", fmtname); | ||
787 | } | ||
771 | 788 | ||
772 | if (sbi->s_qf_names[USRQUOTA]) | 789 | if (sbi->s_qf_names[USRQUOTA]) |
773 | seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); | 790 | seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); |
@@ -899,6 +916,12 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
899 | if (test_opt(sb, NO_AUTO_DA_ALLOC)) | 916 | if (test_opt(sb, NO_AUTO_DA_ALLOC)) |
900 | seq_puts(seq, ",noauto_da_alloc"); | 917 | seq_puts(seq, ",noauto_da_alloc"); |
901 | 918 | ||
919 | if (test_opt(sb, DISCARD)) | ||
920 | seq_puts(seq, ",discard"); | ||
921 | |||
922 | if (test_opt(sb, NOLOAD)) | ||
923 | seq_puts(seq, ",norecovery"); | ||
924 | |||
902 | ext4_show_quota_options(seq, sb); | 925 | ext4_show_quota_options(seq, sb); |
903 | 926 | ||
904 | return 0; | 927 | return 0; |
@@ -1074,12 +1097,13 @@ enum { | |||
1074 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 1097 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
1075 | Opt_data_err_abort, Opt_data_err_ignore, | 1098 | Opt_data_err_abort, Opt_data_err_ignore, |
1076 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 1099 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
1077 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, | 1100 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota, |
1078 | Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize, | 1101 | Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, |
1079 | Opt_usrquota, Opt_grpquota, Opt_i_version, | 1102 | Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version, |
1080 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, | 1103 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, |
1081 | Opt_block_validity, Opt_noblock_validity, | 1104 | Opt_block_validity, Opt_noblock_validity, |
1082 | Opt_inode_readahead_blks, Opt_journal_ioprio | 1105 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
1106 | Opt_discard, Opt_nodiscard, | ||
1083 | }; | 1107 | }; |
1084 | 1108 | ||
1085 | static const match_table_t tokens = { | 1109 | static const match_table_t tokens = { |
@@ -1104,6 +1128,7 @@ static const match_table_t tokens = { | |||
1104 | {Opt_acl, "acl"}, | 1128 | {Opt_acl, "acl"}, |
1105 | {Opt_noacl, "noacl"}, | 1129 | {Opt_noacl, "noacl"}, |
1106 | {Opt_noload, "noload"}, | 1130 | {Opt_noload, "noload"}, |
1131 | {Opt_noload, "norecovery"}, | ||
1107 | {Opt_nobh, "nobh"}, | 1132 | {Opt_nobh, "nobh"}, |
1108 | {Opt_bh, "bh"}, | 1133 | {Opt_bh, "bh"}, |
1109 | {Opt_commit, "commit=%u"}, | 1134 | {Opt_commit, "commit=%u"}, |
@@ -1125,6 +1150,7 @@ static const match_table_t tokens = { | |||
1125 | {Opt_grpjquota, "grpjquota=%s"}, | 1150 | {Opt_grpjquota, "grpjquota=%s"}, |
1126 | {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, | 1151 | {Opt_jqfmt_vfsold, "jqfmt=vfsold"}, |
1127 | {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, | 1152 | {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"}, |
1153 | {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"}, | ||
1128 | {Opt_grpquota, "grpquota"}, | 1154 | {Opt_grpquota, "grpquota"}, |
1129 | {Opt_noquota, "noquota"}, | 1155 | {Opt_noquota, "noquota"}, |
1130 | {Opt_quota, "quota"}, | 1156 | {Opt_quota, "quota"}, |
@@ -1144,6 +1170,8 @@ static const match_table_t tokens = { | |||
1144 | {Opt_auto_da_alloc, "auto_da_alloc=%u"}, | 1170 | {Opt_auto_da_alloc, "auto_da_alloc=%u"}, |
1145 | {Opt_auto_da_alloc, "auto_da_alloc"}, | 1171 | {Opt_auto_da_alloc, "auto_da_alloc"}, |
1146 | {Opt_noauto_da_alloc, "noauto_da_alloc"}, | 1172 | {Opt_noauto_da_alloc, "noauto_da_alloc"}, |
1173 | {Opt_discard, "discard"}, | ||
1174 | {Opt_nodiscard, "nodiscard"}, | ||
1147 | {Opt_err, NULL}, | 1175 | {Opt_err, NULL}, |
1148 | }; | 1176 | }; |
1149 | 1177 | ||
@@ -1425,6 +1453,9 @@ clear_qf_name: | |||
1425 | goto set_qf_format; | 1453 | goto set_qf_format; |
1426 | case Opt_jqfmt_vfsv0: | 1454 | case Opt_jqfmt_vfsv0: |
1427 | qfmt = QFMT_VFS_V0; | 1455 | qfmt = QFMT_VFS_V0; |
1456 | goto set_qf_format; | ||
1457 | case Opt_jqfmt_vfsv1: | ||
1458 | qfmt = QFMT_VFS_V1; | ||
1428 | set_qf_format: | 1459 | set_qf_format: |
1429 | if (sb_any_quota_loaded(sb) && | 1460 | if (sb_any_quota_loaded(sb) && |
1430 | sbi->s_jquota_fmt != qfmt) { | 1461 | sbi->s_jquota_fmt != qfmt) { |
@@ -1467,6 +1498,7 @@ set_qf_format: | |||
1467 | case Opt_offgrpjquota: | 1498 | case Opt_offgrpjquota: |
1468 | case Opt_jqfmt_vfsold: | 1499 | case Opt_jqfmt_vfsold: |
1469 | case Opt_jqfmt_vfsv0: | 1500 | case Opt_jqfmt_vfsv0: |
1501 | case Opt_jqfmt_vfsv1: | ||
1470 | ext4_msg(sb, KERN_ERR, | 1502 | ext4_msg(sb, KERN_ERR, |
1471 | "journaled quota options not supported"); | 1503 | "journaled quota options not supported"); |
1472 | break; | 1504 | break; |
@@ -1565,6 +1597,12 @@ set_qf_format: | |||
1565 | else | 1597 | else |
1566 | set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); | 1598 | set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); |
1567 | break; | 1599 | break; |
1600 | case Opt_discard: | ||
1601 | set_opt(sbi->s_mount_opt, DISCARD); | ||
1602 | break; | ||
1603 | case Opt_nodiscard: | ||
1604 | clear_opt(sbi->s_mount_opt, DISCARD); | ||
1605 | break; | ||
1568 | default: | 1606 | default: |
1569 | ext4_msg(sb, KERN_ERR, | 1607 | ext4_msg(sb, KERN_ERR, |
1570 | "Unrecognized mount option \"%s\" " | 1608 | "Unrecognized mount option \"%s\" " |
@@ -1673,14 +1711,14 @@ static int ext4_fill_flex_info(struct super_block *sb) | |||
1673 | size_t size; | 1711 | size_t size; |
1674 | int i; | 1712 | int i; |
1675 | 1713 | ||
1676 | if (!sbi->s_es->s_log_groups_per_flex) { | 1714 | sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; |
1715 | groups_per_flex = 1 << sbi->s_log_groups_per_flex; | ||
1716 | |||
1717 | if (groups_per_flex < 2) { | ||
1677 | sbi->s_log_groups_per_flex = 0; | 1718 | sbi->s_log_groups_per_flex = 0; |
1678 | return 1; | 1719 | return 1; |
1679 | } | 1720 | } |
1680 | 1721 | ||
1681 | sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex; | ||
1682 | groups_per_flex = 1 << sbi->s_log_groups_per_flex; | ||
1683 | |||
1684 | /* We allocate both existing and potentially added groups */ | 1722 | /* We allocate both existing and potentially added groups */ |
1685 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + | 1723 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + |
1686 | ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << | 1724 | ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << |
@@ -2099,11 +2137,8 @@ static int parse_strtoul(const char *buf, | |||
2099 | { | 2137 | { |
2100 | char *endp; | 2138 | char *endp; |
2101 | 2139 | ||
2102 | while (*buf && isspace(*buf)) | 2140 | *value = simple_strtoul(skip_spaces(buf), &endp, 0); |
2103 | buf++; | 2141 | endp = skip_spaces(endp); |
2104 | *value = simple_strtoul(buf, &endp, 0); | ||
2105 | while (*endp && isspace(*endp)) | ||
2106 | endp++; | ||
2107 | if (*endp || *value > max) | 2142 | if (*endp || *value > max) |
2108 | return -EINVAL; | 2143 | return -EINVAL; |
2109 | 2144 | ||
@@ -2721,26 +2756,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2721 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { | 2756 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) { |
2722 | if (ext4_load_journal(sb, es, journal_devnum)) | 2757 | if (ext4_load_journal(sb, es, journal_devnum)) |
2723 | goto failed_mount3; | 2758 | goto failed_mount3; |
2724 | if (!(sb->s_flags & MS_RDONLY) && | ||
2725 | EXT4_SB(sb)->s_journal->j_failed_commit) { | ||
2726 | ext4_msg(sb, KERN_CRIT, "error: " | ||
2727 | "ext4_fill_super: Journal transaction " | ||
2728 | "%u is corrupt", | ||
2729 | EXT4_SB(sb)->s_journal->j_failed_commit); | ||
2730 | if (test_opt(sb, ERRORS_RO)) { | ||
2731 | ext4_msg(sb, KERN_CRIT, | ||
2732 | "Mounting filesystem read-only"); | ||
2733 | sb->s_flags |= MS_RDONLY; | ||
2734 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
2735 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); | ||
2736 | } | ||
2737 | if (test_opt(sb, ERRORS_PANIC)) { | ||
2738 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
2739 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); | ||
2740 | ext4_commit_super(sb, 1); | ||
2741 | goto failed_mount4; | ||
2742 | } | ||
2743 | } | ||
2744 | } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && | 2759 | } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && |
2745 | EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { | 2760 | EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) { |
2746 | ext4_msg(sb, KERN_ERR, "required journal recovery " | 2761 | ext4_msg(sb, KERN_ERR, "required journal recovery " |
@@ -3668,13 +3683,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
3668 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; | 3683 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; |
3669 | buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - | 3684 | buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - |
3670 | percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); | 3685 | percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); |
3671 | ext4_free_blocks_count_set(es, buf->f_bfree); | ||
3672 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); | 3686 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); |
3673 | if (buf->f_bfree < ext4_r_blocks_count(es)) | 3687 | if (buf->f_bfree < ext4_r_blocks_count(es)) |
3674 | buf->f_bavail = 0; | 3688 | buf->f_bavail = 0; |
3675 | buf->f_files = le32_to_cpu(es->s_inodes_count); | 3689 | buf->f_files = le32_to_cpu(es->s_inodes_count); |
3676 | buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter); | 3690 | buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter); |
3677 | es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); | ||
3678 | buf->f_namelen = EXT4_NAME_LEN; | 3691 | buf->f_namelen = EXT4_NAME_LEN; |
3679 | fsid = le64_to_cpup((void *)es->s_uuid) ^ | 3692 | fsid = le64_to_cpup((void *)es->s_uuid) ^ |
3680 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); | 3693 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); |
@@ -3966,6 +3979,58 @@ static int ext4_get_sb(struct file_system_type *fs_type, int flags, | |||
3966 | return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt); | 3979 | return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt); |
3967 | } | 3980 | } |
3968 | 3981 | ||
3982 | #if !defined(CONTIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) | ||
3983 | static struct file_system_type ext2_fs_type = { | ||
3984 | .owner = THIS_MODULE, | ||
3985 | .name = "ext2", | ||
3986 | .get_sb = ext4_get_sb, | ||
3987 | .kill_sb = kill_block_super, | ||
3988 | .fs_flags = FS_REQUIRES_DEV, | ||
3989 | }; | ||
3990 | |||
3991 | static inline void register_as_ext2(void) | ||
3992 | { | ||
3993 | int err = register_filesystem(&ext2_fs_type); | ||
3994 | if (err) | ||
3995 | printk(KERN_WARNING | ||
3996 | "EXT4-fs: Unable to register as ext2 (%d)\n", err); | ||
3997 | } | ||
3998 | |||
3999 | static inline void unregister_as_ext2(void) | ||
4000 | { | ||
4001 | unregister_filesystem(&ext2_fs_type); | ||
4002 | } | ||
4003 | #else | ||
4004 | static inline void register_as_ext2(void) { } | ||
4005 | static inline void unregister_as_ext2(void) { } | ||
4006 | #endif | ||
4007 | |||
4008 | #if !defined(CONTIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) | ||
4009 | static struct file_system_type ext3_fs_type = { | ||
4010 | .owner = THIS_MODULE, | ||
4011 | .name = "ext3", | ||
4012 | .get_sb = ext4_get_sb, | ||
4013 | .kill_sb = kill_block_super, | ||
4014 | .fs_flags = FS_REQUIRES_DEV, | ||
4015 | }; | ||
4016 | |||
4017 | static inline void register_as_ext3(void) | ||
4018 | { | ||
4019 | int err = register_filesystem(&ext3_fs_type); | ||
4020 | if (err) | ||
4021 | printk(KERN_WARNING | ||
4022 | "EXT4-fs: Unable to register as ext3 (%d)\n", err); | ||
4023 | } | ||
4024 | |||
4025 | static inline void unregister_as_ext3(void) | ||
4026 | { | ||
4027 | unregister_filesystem(&ext3_fs_type); | ||
4028 | } | ||
4029 | #else | ||
4030 | static inline void register_as_ext3(void) { } | ||
4031 | static inline void unregister_as_ext3(void) { } | ||
4032 | #endif | ||
4033 | |||
3969 | static struct file_system_type ext4_fs_type = { | 4034 | static struct file_system_type ext4_fs_type = { |
3970 | .owner = THIS_MODULE, | 4035 | .owner = THIS_MODULE, |
3971 | .name = "ext4", | 4036 | .name = "ext4", |
@@ -3995,11 +4060,15 @@ static int __init init_ext4_fs(void) | |||
3995 | err = init_inodecache(); | 4060 | err = init_inodecache(); |
3996 | if (err) | 4061 | if (err) |
3997 | goto out1; | 4062 | goto out1; |
4063 | register_as_ext2(); | ||
4064 | register_as_ext3(); | ||
3998 | err = register_filesystem(&ext4_fs_type); | 4065 | err = register_filesystem(&ext4_fs_type); |
3999 | if (err) | 4066 | if (err) |
4000 | goto out; | 4067 | goto out; |
4001 | return 0; | 4068 | return 0; |
4002 | out: | 4069 | out: |
4070 | unregister_as_ext2(); | ||
4071 | unregister_as_ext3(); | ||
4003 | destroy_inodecache(); | 4072 | destroy_inodecache(); |
4004 | out1: | 4073 | out1: |
4005 | exit_ext4_xattr(); | 4074 | exit_ext4_xattr(); |
@@ -4015,6 +4084,8 @@ out4: | |||
4015 | 4084 | ||
4016 | static void __exit exit_ext4_fs(void) | 4085 | static void __exit exit_ext4_fs(void) |
4017 | { | 4086 | { |
4087 | unregister_as_ext2(); | ||
4088 | unregister_as_ext3(); | ||
4018 | unregister_filesystem(&ext4_fs_type); | 4089 | unregister_filesystem(&ext4_fs_type); |
4019 | destroy_inodecache(); | 4090 | destroy_inodecache(); |
4020 | exit_ext4_xattr(); | 4091 | exit_ext4_xattr(); |