diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 274 |
1 files changed, 192 insertions, 82 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 566344b926b..0e661c56966 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 *, |
@@ -508,10 +512,12 @@ static void ext4_put_super(struct super_block *sb) | |||
508 | if (!(sb->s_flags & MS_RDONLY)) { | 512 | if (!(sb->s_flags & MS_RDONLY)) { |
509 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 513 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
510 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 514 | 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); | 515 | ext4_commit_super(sb, es, 1); |
514 | } | 516 | } |
517 | if (sbi->s_proc) { | ||
518 | remove_proc_entry("inode_readahead_blks", sbi->s_proc); | ||
519 | remove_proc_entry(sb->s_id, ext4_proc_root); | ||
520 | } | ||
515 | 521 | ||
516 | for (i = 0; i < sbi->s_gdb_count; i++) | 522 | for (i = 0; i < sbi->s_gdb_count; i++) |
517 | brelse(sbi->s_group_desc[i]); | 523 | brelse(sbi->s_group_desc[i]); |
@@ -520,6 +526,7 @@ static void ext4_put_super(struct super_block *sb) | |||
520 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | 526 | percpu_counter_destroy(&sbi->s_freeblocks_counter); |
521 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 527 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
522 | percpu_counter_destroy(&sbi->s_dirs_counter); | 528 | percpu_counter_destroy(&sbi->s_dirs_counter); |
529 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
523 | brelse(sbi->s_sbh); | 530 | brelse(sbi->s_sbh); |
524 | #ifdef CONFIG_QUOTA | 531 | #ifdef CONFIG_QUOTA |
525 | for (i = 0; i < MAXQUOTAS; i++) | 532 | for (i = 0; i < MAXQUOTAS; i++) |
@@ -562,11 +569,10 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
562 | ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS); | 569 | ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS); |
563 | if (!ei) | 570 | if (!ei) |
564 | return NULL; | 571 | return NULL; |
565 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 572 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
566 | ei->i_acl = EXT4_ACL_NOT_CACHED; | 573 | ei->i_acl = EXT4_ACL_NOT_CACHED; |
567 | ei->i_default_acl = EXT4_ACL_NOT_CACHED; | 574 | ei->i_default_acl = EXT4_ACL_NOT_CACHED; |
568 | #endif | 575 | #endif |
569 | ei->i_block_alloc_info = NULL; | ||
570 | ei->vfs_inode.i_version = 1; | 576 | ei->vfs_inode.i_version = 1; |
571 | ei->vfs_inode.i_data.writeback_index = 0; | 577 | ei->vfs_inode.i_data.writeback_index = 0; |
572 | memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); | 578 | memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); |
@@ -599,7 +605,7 @@ static void init_once(void *foo) | |||
599 | struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; | 605 | struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; |
600 | 606 | ||
601 | INIT_LIST_HEAD(&ei->i_orphan); | 607 | INIT_LIST_HEAD(&ei->i_orphan); |
602 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 608 | #ifdef CONFIG_EXT4_FS_XATTR |
603 | init_rwsem(&ei->xattr_sem); | 609 | init_rwsem(&ei->xattr_sem); |
604 | #endif | 610 | #endif |
605 | init_rwsem(&ei->i_data_sem); | 611 | init_rwsem(&ei->i_data_sem); |
@@ -625,8 +631,7 @@ static void destroy_inodecache(void) | |||
625 | 631 | ||
626 | static void ext4_clear_inode(struct inode *inode) | 632 | static void ext4_clear_inode(struct inode *inode) |
627 | { | 633 | { |
628 | struct ext4_block_alloc_info *rsv = EXT4_I(inode)->i_block_alloc_info; | 634 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
629 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | ||
630 | if (EXT4_I(inode)->i_acl && | 635 | if (EXT4_I(inode)->i_acl && |
631 | EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) { | 636 | EXT4_I(inode)->i_acl != EXT4_ACL_NOT_CACHED) { |
632 | posix_acl_release(EXT4_I(inode)->i_acl); | 637 | posix_acl_release(EXT4_I(inode)->i_acl); |
@@ -638,10 +643,7 @@ static void ext4_clear_inode(struct inode *inode) | |||
638 | EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED; | 643 | EXT4_I(inode)->i_default_acl = EXT4_ACL_NOT_CACHED; |
639 | } | 644 | } |
640 | #endif | 645 | #endif |
641 | ext4_discard_reservation(inode); | 646 | 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, | 647 | jbd2_journal_release_jbd_inode(EXT4_SB(inode->i_sb)->s_journal, |
646 | &EXT4_I(inode)->jinode); | 648 | &EXT4_I(inode)->jinode); |
647 | } | 649 | } |
@@ -654,7 +656,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq, | |||
654 | 656 | ||
655 | if (sbi->s_jquota_fmt) | 657 | if (sbi->s_jquota_fmt) |
656 | seq_printf(seq, ",jqfmt=%s", | 658 | seq_printf(seq, ",jqfmt=%s", |
657 | (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0"); | 659 | (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0"); |
658 | 660 | ||
659 | if (sbi->s_qf_names[USRQUOTA]) | 661 | if (sbi->s_qf_names[USRQUOTA]) |
660 | seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); | 662 | seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]); |
@@ -718,7 +720,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
718 | seq_puts(seq, ",debug"); | 720 | seq_puts(seq, ",debug"); |
719 | if (test_opt(sb, OLDALLOC)) | 721 | if (test_opt(sb, OLDALLOC)) |
720 | seq_puts(seq, ",oldalloc"); | 722 | seq_puts(seq, ",oldalloc"); |
721 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 723 | #ifdef CONFIG_EXT4_FS_XATTR |
722 | if (test_opt(sb, XATTR_USER) && | 724 | if (test_opt(sb, XATTR_USER) && |
723 | !(def_mount_opts & EXT4_DEFM_XATTR_USER)) | 725 | !(def_mount_opts & EXT4_DEFM_XATTR_USER)) |
724 | seq_puts(seq, ",user_xattr"); | 726 | seq_puts(seq, ",user_xattr"); |
@@ -727,7 +729,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
727 | seq_puts(seq, ",nouser_xattr"); | 729 | seq_puts(seq, ",nouser_xattr"); |
728 | } | 730 | } |
729 | #endif | 731 | #endif |
730 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 732 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
731 | if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) | 733 | if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) |
732 | seq_puts(seq, ",acl"); | 734 | seq_puts(seq, ",acl"); |
733 | if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) | 735 | if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) |
@@ -752,8 +754,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
752 | seq_puts(seq, ",nobh"); | 754 | seq_puts(seq, ",nobh"); |
753 | if (!test_opt(sb, EXTENTS)) | 755 | if (!test_opt(sb, EXTENTS)) |
754 | seq_puts(seq, ",noextents"); | 756 | seq_puts(seq, ",noextents"); |
755 | if (!test_opt(sb, MBALLOC)) | ||
756 | seq_puts(seq, ",nomballoc"); | ||
757 | if (test_opt(sb, I_VERSION)) | 757 | if (test_opt(sb, I_VERSION)) |
758 | seq_puts(seq, ",i_version"); | 758 | seq_puts(seq, ",i_version"); |
759 | if (!test_opt(sb, DELALLOC)) | 759 | if (!test_opt(sb, DELALLOC)) |
@@ -773,6 +773,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
773 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) | 773 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
774 | seq_puts(seq, ",data=writeback"); | 774 | seq_puts(seq, ",data=writeback"); |
775 | 775 | ||
776 | if (sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS) | ||
777 | seq_printf(seq, ",inode_readahead_blks=%u", | ||
778 | sbi->s_inode_readahead_blks); | ||
779 | |||
776 | ext4_show_quota_options(seq, sb); | 780 | ext4_show_quota_options(seq, sb); |
777 | return 0; | 781 | return 0; |
778 | } | 782 | } |
@@ -822,7 +826,7 @@ static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, | |||
822 | } | 826 | } |
823 | 827 | ||
824 | #ifdef CONFIG_QUOTA | 828 | #ifdef CONFIG_QUOTA |
825 | #define QTYPE2NAME(t) ((t) == USRQUOTA?"user":"group") | 829 | #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group") |
826 | #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) | 830 | #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) |
827 | 831 | ||
828 | static int ext4_dquot_initialize(struct inode *inode, int type); | 832 | static int ext4_dquot_initialize(struct inode *inode, int type); |
@@ -907,6 +911,7 @@ enum { | |||
907 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, | 911 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, |
908 | Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version, | 912 | Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version, |
909 | Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc, | 913 | Opt_mballoc, Opt_nomballoc, Opt_stripe, Opt_delalloc, Opt_nodelalloc, |
914 | Opt_inode_readahead_blks | ||
910 | }; | 915 | }; |
911 | 916 | ||
912 | static match_table_t tokens = { | 917 | static match_table_t tokens = { |
@@ -967,6 +972,7 @@ static match_table_t tokens = { | |||
967 | {Opt_resize, "resize"}, | 972 | {Opt_resize, "resize"}, |
968 | {Opt_delalloc, "delalloc"}, | 973 | {Opt_delalloc, "delalloc"}, |
969 | {Opt_nodelalloc, "nodelalloc"}, | 974 | {Opt_nodelalloc, "nodelalloc"}, |
975 | {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, | ||
970 | {Opt_err, NULL}, | 976 | {Opt_err, NULL}, |
971 | }; | 977 | }; |
972 | 978 | ||
@@ -981,7 +987,7 @@ static ext4_fsblk_t get_sb_block(void **data) | |||
981 | /*todo: use simple_strtoll with >32bit ext4 */ | 987 | /*todo: use simple_strtoll with >32bit ext4 */ |
982 | sb_block = simple_strtoul(options, &options, 0); | 988 | sb_block = simple_strtoul(options, &options, 0); |
983 | if (*options && *options != ',') { | 989 | if (*options && *options != ',') { |
984 | printk("EXT4-fs: Invalid sb specification: %s\n", | 990 | printk(KERN_ERR "EXT4-fs: Invalid sb specification: %s\n", |
985 | (char *) *data); | 991 | (char *) *data); |
986 | return 1; | 992 | return 1; |
987 | } | 993 | } |
@@ -1072,7 +1078,7 @@ static int parse_options(char *options, struct super_block *sb, | |||
1072 | case Opt_orlov: | 1078 | case Opt_orlov: |
1073 | clear_opt(sbi->s_mount_opt, OLDALLOC); | 1079 | clear_opt(sbi->s_mount_opt, OLDALLOC); |
1074 | break; | 1080 | break; |
1075 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 1081 | #ifdef CONFIG_EXT4_FS_XATTR |
1076 | case Opt_user_xattr: | 1082 | case Opt_user_xattr: |
1077 | set_opt(sbi->s_mount_opt, XATTR_USER); | 1083 | set_opt(sbi->s_mount_opt, XATTR_USER); |
1078 | break; | 1084 | break; |
@@ -1082,10 +1088,11 @@ static int parse_options(char *options, struct super_block *sb, | |||
1082 | #else | 1088 | #else |
1083 | case Opt_user_xattr: | 1089 | case Opt_user_xattr: |
1084 | case Opt_nouser_xattr: | 1090 | case Opt_nouser_xattr: |
1085 | printk("EXT4 (no)user_xattr options not supported\n"); | 1091 | printk(KERN_ERR "EXT4 (no)user_xattr options " |
1092 | "not supported\n"); | ||
1086 | break; | 1093 | break; |
1087 | #endif | 1094 | #endif |
1088 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 1095 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
1089 | case Opt_acl: | 1096 | case Opt_acl: |
1090 | set_opt(sbi->s_mount_opt, POSIX_ACL); | 1097 | set_opt(sbi->s_mount_opt, POSIX_ACL); |
1091 | break; | 1098 | break; |
@@ -1095,7 +1102,8 @@ static int parse_options(char *options, struct super_block *sb, | |||
1095 | #else | 1102 | #else |
1096 | case Opt_acl: | 1103 | case Opt_acl: |
1097 | case Opt_noacl: | 1104 | case Opt_noacl: |
1098 | printk("EXT4 (no)acl options not supported\n"); | 1105 | printk(KERN_ERR "EXT4 (no)acl options " |
1106 | "not supported\n"); | ||
1099 | break; | 1107 | break; |
1100 | #endif | 1108 | #endif |
1101 | case Opt_reservation: | 1109 | case Opt_reservation: |
@@ -1189,8 +1197,8 @@ set_qf_name: | |||
1189 | sb_any_quota_suspended(sb)) && | 1197 | sb_any_quota_suspended(sb)) && |
1190 | !sbi->s_qf_names[qtype]) { | 1198 | !sbi->s_qf_names[qtype]) { |
1191 | printk(KERN_ERR | 1199 | printk(KERN_ERR |
1192 | "EXT4-fs: Cannot change journaled " | 1200 | "EXT4-fs: Cannot change journaled " |
1193 | "quota options when quota turned on.\n"); | 1201 | "quota options when quota turned on.\n"); |
1194 | return 0; | 1202 | return 0; |
1195 | } | 1203 | } |
1196 | qname = match_strdup(&args[0]); | 1204 | qname = match_strdup(&args[0]); |
@@ -1357,12 +1365,6 @@ set_qf_format: | |||
1357 | case Opt_nodelalloc: | 1365 | case Opt_nodelalloc: |
1358 | clear_opt(sbi->s_mount_opt, DELALLOC); | 1366 | clear_opt(sbi->s_mount_opt, DELALLOC); |
1359 | break; | 1367 | 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: | 1368 | case Opt_stripe: |
1367 | if (match_int(&args[0], &option)) | 1369 | if (match_int(&args[0], &option)) |
1368 | return 0; | 1370 | return 0; |
@@ -1373,6 +1375,13 @@ set_qf_format: | |||
1373 | case Opt_delalloc: | 1375 | case Opt_delalloc: |
1374 | set_opt(sbi->s_mount_opt, DELALLOC); | 1376 | set_opt(sbi->s_mount_opt, DELALLOC); |
1375 | break; | 1377 | break; |
1378 | case Opt_inode_readahead_blks: | ||
1379 | if (match_int(&args[0], &option)) | ||
1380 | return 0; | ||
1381 | if (option < 0 || option > (1 << 30)) | ||
1382 | return 0; | ||
1383 | sbi->s_inode_readahead_blks = option; | ||
1384 | break; | ||
1376 | default: | 1385 | default: |
1377 | printk(KERN_ERR | 1386 | printk(KERN_ERR |
1378 | "EXT4-fs: Unrecognized mount option \"%s\" " | 1387 | "EXT4-fs: Unrecognized mount option \"%s\" " |
@@ -1473,15 +1482,9 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, | |||
1473 | EXT4_INODES_PER_GROUP(sb), | 1482 | EXT4_INODES_PER_GROUP(sb), |
1474 | sbi->s_mount_opt); | 1483 | sbi->s_mount_opt); |
1475 | 1484 | ||
1476 | printk(KERN_INFO "EXT4 FS on %s, ", sb->s_id); | 1485 | printk(KERN_INFO "EXT4 FS on %s, %s journal on %s\n", |
1477 | if (EXT4_SB(sb)->s_journal->j_inode == NULL) { | 1486 | sb->s_id, EXT4_SB(sb)->s_journal->j_inode ? "internal" : |
1478 | char b[BDEVNAME_SIZE]; | 1487 | "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; | 1488 | return res; |
1486 | } | 1489 | } |
1487 | 1490 | ||
@@ -1504,8 +1507,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; | 1507 | 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; | 1508 | groups_per_flex = 1 << sbi->s_log_groups_per_flex; |
1506 | 1509 | ||
1507 | flex_group_count = (sbi->s_groups_count + groups_per_flex - 1) / | 1510 | /* We allocate both existing and potentially added groups */ |
1508 | groups_per_flex; | 1511 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + |
1512 | ((sbi->s_es->s_reserved_gdt_blocks +1 ) << | ||
1513 | EXT4_DESC_PER_BLOCK_BITS(sb))) / | ||
1514 | groups_per_flex; | ||
1509 | sbi->s_flex_groups = kzalloc(flex_group_count * | 1515 | sbi->s_flex_groups = kzalloc(flex_group_count * |
1510 | sizeof(struct flex_groups), GFP_KERNEL); | 1516 | sizeof(struct flex_groups), GFP_KERNEL); |
1511 | if (sbi->s_flex_groups == NULL) { | 1517 | if (sbi->s_flex_groups == NULL) { |
@@ -1584,7 +1590,7 @@ static int ext4_check_descriptors(struct super_block *sb) | |||
1584 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | 1590 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) |
1585 | flexbg_flag = 1; | 1591 | flexbg_flag = 1; |
1586 | 1592 | ||
1587 | ext4_debug ("Checking group descriptors"); | 1593 | ext4_debug("Checking group descriptors"); |
1588 | 1594 | ||
1589 | for (i = 0; i < sbi->s_groups_count; i++) { | 1595 | for (i = 0; i < sbi->s_groups_count; i++) { |
1590 | struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL); | 1596 | struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL); |
@@ -1623,8 +1629,10 @@ static int ext4_check_descriptors(struct super_block *sb) | |||
1623 | "Checksum for group %lu failed (%u!=%u)\n", | 1629 | "Checksum for group %lu failed (%u!=%u)\n", |
1624 | i, le16_to_cpu(ext4_group_desc_csum(sbi, i, | 1630 | i, le16_to_cpu(ext4_group_desc_csum(sbi, i, |
1625 | gdp)), le16_to_cpu(gdp->bg_checksum)); | 1631 | gdp)), le16_to_cpu(gdp->bg_checksum)); |
1626 | if (!(sb->s_flags & MS_RDONLY)) | 1632 | if (!(sb->s_flags & MS_RDONLY)) { |
1633 | spin_unlock(sb_bgl_lock(sbi, i)); | ||
1627 | return 0; | 1634 | return 0; |
1635 | } | ||
1628 | } | 1636 | } |
1629 | spin_unlock(sb_bgl_lock(sbi, i)); | 1637 | spin_unlock(sb_bgl_lock(sbi, i)); |
1630 | if (!flexbg_flag) | 1638 | if (!flexbg_flag) |
@@ -1714,9 +1722,9 @@ static void ext4_orphan_cleanup(struct super_block *sb, | |||
1714 | DQUOT_INIT(inode); | 1722 | DQUOT_INIT(inode); |
1715 | if (inode->i_nlink) { | 1723 | if (inode->i_nlink) { |
1716 | printk(KERN_DEBUG | 1724 | printk(KERN_DEBUG |
1717 | "%s: truncating inode %lu to %Ld bytes\n", | 1725 | "%s: truncating inode %lu to %lld bytes\n", |
1718 | __func__, inode->i_ino, inode->i_size); | 1726 | __func__, inode->i_ino, inode->i_size); |
1719 | jbd_debug(2, "truncating inode %lu to %Ld bytes\n", | 1727 | jbd_debug(2, "truncating inode %lu to %lld bytes\n", |
1720 | inode->i_ino, inode->i_size); | 1728 | inode->i_ino, inode->i_size); |
1721 | ext4_truncate(inode); | 1729 | ext4_truncate(inode); |
1722 | nr_truncates++; | 1730 | nr_truncates++; |
@@ -1914,6 +1922,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
1914 | unsigned long journal_devnum = 0; | 1922 | unsigned long journal_devnum = 0; |
1915 | unsigned long def_mount_opts; | 1923 | unsigned long def_mount_opts; |
1916 | struct inode *root; | 1924 | struct inode *root; |
1925 | char *cp; | ||
1917 | int ret = -EINVAL; | 1926 | int ret = -EINVAL; |
1918 | int blocksize; | 1927 | int blocksize; |
1919 | int db_count; | 1928 | int db_count; |
@@ -1930,10 +1939,15 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
1930 | sbi->s_mount_opt = 0; | 1939 | sbi->s_mount_opt = 0; |
1931 | sbi->s_resuid = EXT4_DEF_RESUID; | 1940 | sbi->s_resuid = EXT4_DEF_RESUID; |
1932 | sbi->s_resgid = EXT4_DEF_RESGID; | 1941 | sbi->s_resgid = EXT4_DEF_RESGID; |
1942 | sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; | ||
1933 | sbi->s_sb_block = sb_block; | 1943 | sbi->s_sb_block = sb_block; |
1934 | 1944 | ||
1935 | unlock_kernel(); | 1945 | unlock_kernel(); |
1936 | 1946 | ||
1947 | /* Cleanup superblock name */ | ||
1948 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) | ||
1949 | *cp = '!'; | ||
1950 | |||
1937 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); | 1951 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); |
1938 | if (!blocksize) { | 1952 | if (!blocksize) { |
1939 | printk(KERN_ERR "EXT4-fs: unable to set blocksize\n"); | 1953 | printk(KERN_ERR "EXT4-fs: unable to set blocksize\n"); |
@@ -1973,11 +1987,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
1973 | set_opt(sbi->s_mount_opt, GRPID); | 1987 | set_opt(sbi->s_mount_opt, GRPID); |
1974 | if (def_mount_opts & EXT4_DEFM_UID16) | 1988 | if (def_mount_opts & EXT4_DEFM_UID16) |
1975 | set_opt(sbi->s_mount_opt, NO_UID32); | 1989 | set_opt(sbi->s_mount_opt, NO_UID32); |
1976 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 1990 | #ifdef CONFIG_EXT4_FS_XATTR |
1977 | if (def_mount_opts & EXT4_DEFM_XATTR_USER) | 1991 | if (def_mount_opts & EXT4_DEFM_XATTR_USER) |
1978 | set_opt(sbi->s_mount_opt, XATTR_USER); | 1992 | set_opt(sbi->s_mount_opt, XATTR_USER); |
1979 | #endif | 1993 | #endif |
1980 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL | 1994 | #ifdef CONFIG_EXT4_FS_POSIX_ACL |
1981 | if (def_mount_opts & EXT4_DEFM_ACL) | 1995 | if (def_mount_opts & EXT4_DEFM_ACL) |
1982 | set_opt(sbi->s_mount_opt, POSIX_ACL); | 1996 | set_opt(sbi->s_mount_opt, POSIX_ACL); |
1983 | #endif | 1997 | #endif |
@@ -2012,11 +2026,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2012 | ext4_warning(sb, __func__, | 2026 | ext4_warning(sb, __func__, |
2013 | "extents feature not enabled on this filesystem, " | 2027 | "extents feature not enabled on this filesystem, " |
2014 | "use tune2fs.\n"); | 2028 | "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 | 2029 | ||
2021 | /* | 2030 | /* |
2022 | * enable delayed allocation by default | 2031 | * enable delayed allocation by default |
@@ -2041,16 +2050,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2041 | "running e2fsck is recommended\n"); | 2050 | "running e2fsck is recommended\n"); |
2042 | 2051 | ||
2043 | /* | 2052 | /* |
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 | 2053 | * Check feature flags regardless of the revision level, since we |
2055 | * previously didn't change the revision level when setting the flags, | 2054 | * 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. | 2055 | * so there is a chance incompat flags are set on a rev 0 filesystem. |
@@ -2219,6 +2218,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2219 | goto failed_mount; | 2218 | goto failed_mount; |
2220 | } | 2219 | } |
2221 | 2220 | ||
2221 | if (ext4_proc_root) | ||
2222 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); | ||
2223 | |||
2224 | if (sbi->s_proc) | ||
2225 | proc_create_data("inode_readahead_blks", 0644, sbi->s_proc, | ||
2226 | &ext4_ui_proc_fops, | ||
2227 | &sbi->s_inode_readahead_blks); | ||
2228 | |||
2222 | bgl_lock_init(&sbi->s_blockgroup_lock); | 2229 | bgl_lock_init(&sbi->s_blockgroup_lock); |
2223 | 2230 | ||
2224 | for (i = 0; i < db_count; i++) { | 2231 | for (i = 0; i < db_count; i++) { |
@@ -2257,24 +2264,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2257 | err = percpu_counter_init(&sbi->s_dirs_counter, | 2264 | err = percpu_counter_init(&sbi->s_dirs_counter, |
2258 | ext4_count_dirs(sb)); | 2265 | ext4_count_dirs(sb)); |
2259 | } | 2266 | } |
2267 | if (!err) { | ||
2268 | err = percpu_counter_init(&sbi->s_dirtyblocks_counter, 0); | ||
2269 | } | ||
2260 | if (err) { | 2270 | if (err) { |
2261 | printk(KERN_ERR "EXT4-fs: insufficient memory\n"); | 2271 | printk(KERN_ERR "EXT4-fs: insufficient memory\n"); |
2262 | goto failed_mount3; | 2272 | goto failed_mount3; |
2263 | } | 2273 | } |
2264 | 2274 | ||
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); | 2275 | sbi->s_stripe = ext4_get_stripe_size(sbi); |
2279 | 2276 | ||
2280 | /* | 2277 | /* |
@@ -2471,7 +2468,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2471 | printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n"); | 2468 | printk(KERN_INFO "EXT4-fs: delayed allocation enabled\n"); |
2472 | 2469 | ||
2473 | ext4_ext_init(sb); | 2470 | ext4_ext_init(sb); |
2474 | ext4_mb_init(sb, needs_recovery); | 2471 | err = ext4_mb_init(sb, needs_recovery); |
2472 | if (err) { | ||
2473 | printk(KERN_ERR "EXT4-fs: failed to initalize mballoc (%d)\n", | ||
2474 | err); | ||
2475 | goto failed_mount4; | ||
2476 | } | ||
2475 | 2477 | ||
2476 | lock_kernel(); | 2478 | lock_kernel(); |
2477 | return 0; | 2479 | return 0; |
@@ -2489,11 +2491,16 @@ failed_mount3: | |||
2489 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | 2491 | percpu_counter_destroy(&sbi->s_freeblocks_counter); |
2490 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 2492 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
2491 | percpu_counter_destroy(&sbi->s_dirs_counter); | 2493 | percpu_counter_destroy(&sbi->s_dirs_counter); |
2494 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | ||
2492 | failed_mount2: | 2495 | failed_mount2: |
2493 | for (i = 0; i < db_count; i++) | 2496 | for (i = 0; i < db_count; i++) |
2494 | brelse(sbi->s_group_desc[i]); | 2497 | brelse(sbi->s_group_desc[i]); |
2495 | kfree(sbi->s_group_desc); | 2498 | kfree(sbi->s_group_desc); |
2496 | failed_mount: | 2499 | failed_mount: |
2500 | if (sbi->s_proc) { | ||
2501 | remove_proc_entry("inode_readahead_blks", sbi->s_proc); | ||
2502 | remove_proc_entry(sb->s_id, ext4_proc_root); | ||
2503 | } | ||
2497 | #ifdef CONFIG_QUOTA | 2504 | #ifdef CONFIG_QUOTA |
2498 | for (i = 0; i < MAXQUOTAS; i++) | 2505 | for (i = 0; i < MAXQUOTAS; i++) |
2499 | kfree(sbi->s_qf_names[i]); | 2506 | kfree(sbi->s_qf_names[i]); |
@@ -2552,7 +2559,7 @@ static journal_t *ext4_get_journal(struct super_block *sb, | |||
2552 | return NULL; | 2559 | return NULL; |
2553 | } | 2560 | } |
2554 | 2561 | ||
2555 | jbd_debug(2, "Journal inode found at %p: %Ld bytes\n", | 2562 | jbd_debug(2, "Journal inode found at %p: %lld bytes\n", |
2556 | journal_inode, journal_inode->i_size); | 2563 | journal_inode, journal_inode->i_size); |
2557 | if (!S_ISREG(journal_inode->i_mode)) { | 2564 | if (!S_ISREG(journal_inode->i_mode)) { |
2558 | printk(KERN_ERR "EXT4-fs: invalid journal inode.\n"); | 2565 | printk(KERN_ERR "EXT4-fs: invalid journal inode.\n"); |
@@ -2715,6 +2722,11 @@ static int ext4_load_journal(struct super_block *sb, | |||
2715 | return -EINVAL; | 2722 | return -EINVAL; |
2716 | } | 2723 | } |
2717 | 2724 | ||
2725 | if (journal->j_flags & JBD2_BARRIER) | ||
2726 | printk(KERN_INFO "EXT4-fs: barriers enabled\n"); | ||
2727 | else | ||
2728 | printk(KERN_INFO "EXT4-fs: barriers disabled\n"); | ||
2729 | |||
2718 | if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { | 2730 | if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { |
2719 | err = jbd2_journal_update_format(journal); | 2731 | err = jbd2_journal_update_format(journal); |
2720 | if (err) { | 2732 | if (err) { |
@@ -2799,13 +2811,34 @@ static void ext4_commit_super(struct super_block *sb, | |||
2799 | 2811 | ||
2800 | if (!sbh) | 2812 | if (!sbh) |
2801 | return; | 2813 | return; |
2814 | if (buffer_write_io_error(sbh)) { | ||
2815 | /* | ||
2816 | * Oh, dear. A previous attempt to write the | ||
2817 | * superblock failed. This could happen because the | ||
2818 | * USB device was yanked out. Or it could happen to | ||
2819 | * be a transient write error and maybe the block will | ||
2820 | * be remapped. Nothing we can do but to retry the | ||
2821 | * write and hope for the best. | ||
2822 | */ | ||
2823 | printk(KERN_ERR "ext4: previous I/O error to " | ||
2824 | "superblock detected for %s.\n", sb->s_id); | ||
2825 | clear_buffer_write_io_error(sbh); | ||
2826 | set_buffer_uptodate(sbh); | ||
2827 | } | ||
2802 | es->s_wtime = cpu_to_le32(get_seconds()); | 2828 | es->s_wtime = cpu_to_le32(get_seconds()); |
2803 | ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb)); | 2829 | 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)); | 2830 | es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb)); |
2805 | BUFFER_TRACE(sbh, "marking dirty"); | 2831 | BUFFER_TRACE(sbh, "marking dirty"); |
2806 | mark_buffer_dirty(sbh); | 2832 | mark_buffer_dirty(sbh); |
2807 | if (sync) | 2833 | if (sync) { |
2808 | sync_dirty_buffer(sbh); | 2834 | sync_dirty_buffer(sbh); |
2835 | if (buffer_write_io_error(sbh)) { | ||
2836 | printk(KERN_ERR "ext4: I/O error while writing " | ||
2837 | "superblock for %s.\n", sb->s_id); | ||
2838 | clear_buffer_write_io_error(sbh); | ||
2839 | set_buffer_uptodate(sbh); | ||
2840 | } | ||
2841 | } | ||
2809 | } | 2842 | } |
2810 | 2843 | ||
2811 | 2844 | ||
@@ -2907,6 +2940,7 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
2907 | { | 2940 | { |
2908 | tid_t target; | 2941 | tid_t target; |
2909 | 2942 | ||
2943 | trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); | ||
2910 | sb->s_dirt = 0; | 2944 | sb->s_dirt = 0; |
2911 | if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { | 2945 | if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { |
2912 | if (wait) | 2946 | if (wait) |
@@ -3162,7 +3196,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
3162 | buf->f_type = EXT4_SUPER_MAGIC; | 3196 | buf->f_type = EXT4_SUPER_MAGIC; |
3163 | buf->f_bsize = sb->s_blocksize; | 3197 | buf->f_bsize = sb->s_blocksize; |
3164 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; | 3198 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; |
3165 | buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter); | 3199 | buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - |
3200 | percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); | ||
3166 | ext4_free_blocks_count_set(es, buf->f_bfree); | 3201 | ext4_free_blocks_count_set(es, buf->f_bfree); |
3167 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); | 3202 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); |
3168 | if (buf->f_bfree < ext4_r_blocks_count(es)) | 3203 | if (buf->f_bfree < ext4_r_blocks_count(es)) |
@@ -3432,7 +3467,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, | |||
3432 | handle_t *handle = journal_current_handle(); | 3467 | handle_t *handle = journal_current_handle(); |
3433 | 3468 | ||
3434 | if (!handle) { | 3469 | if (!handle) { |
3435 | printk(KERN_WARNING "EXT4-fs: Quota write (off=%Lu, len=%Lu)" | 3470 | printk(KERN_WARNING "EXT4-fs: Quota write (off=%llu, len=%llu)" |
3436 | " cancelled because transaction is not started.\n", | 3471 | " cancelled because transaction is not started.\n", |
3437 | (unsigned long long)off, (unsigned long long)len); | 3472 | (unsigned long long)off, (unsigned long long)len); |
3438 | return -EIO; | 3473 | return -EIO; |
@@ -3493,18 +3528,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); | 3528 | return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt); |
3494 | } | 3529 | } |
3495 | 3530 | ||
3531 | #ifdef CONFIG_PROC_FS | ||
3532 | static int ext4_ui_proc_show(struct seq_file *m, void *v) | ||
3533 | { | ||
3534 | unsigned int *p = m->private; | ||
3535 | |||
3536 | seq_printf(m, "%u\n", *p); | ||
3537 | return 0; | ||
3538 | } | ||
3539 | |||
3540 | static int ext4_ui_proc_open(struct inode *inode, struct file *file) | ||
3541 | { | ||
3542 | return single_open(file, ext4_ui_proc_show, PDE(inode)->data); | ||
3543 | } | ||
3544 | |||
3545 | static ssize_t ext4_ui_proc_write(struct file *file, const char __user *buf, | ||
3546 | size_t cnt, loff_t *ppos) | ||
3547 | { | ||
3548 | unsigned int *p = PDE(file->f_path.dentry->d_inode)->data; | ||
3549 | char str[32]; | ||
3550 | unsigned long value; | ||
3551 | |||
3552 | if (cnt >= sizeof(str)) | ||
3553 | return -EINVAL; | ||
3554 | if (copy_from_user(str, buf, cnt)) | ||
3555 | return -EFAULT; | ||
3556 | value = simple_strtol(str, NULL, 0); | ||
3557 | if (value < 0) | ||
3558 | return -ERANGE; | ||
3559 | *p = value; | ||
3560 | return cnt; | ||
3561 | } | ||
3562 | |||
3563 | const struct file_operations ext4_ui_proc_fops = { | ||
3564 | .owner = THIS_MODULE, | ||
3565 | .open = ext4_ui_proc_open, | ||
3566 | .read = seq_read, | ||
3567 | .llseek = seq_lseek, | ||
3568 | .release = single_release, | ||
3569 | .write = ext4_ui_proc_write, | ||
3570 | }; | ||
3571 | #endif | ||
3572 | |||
3573 | static struct file_system_type ext4_fs_type = { | ||
3574 | .owner = THIS_MODULE, | ||
3575 | .name = "ext4", | ||
3576 | .get_sb = ext4_get_sb, | ||
3577 | .kill_sb = kill_block_super, | ||
3578 | .fs_flags = FS_REQUIRES_DEV, | ||
3579 | }; | ||
3580 | |||
3581 | #ifdef CONFIG_EXT4DEV_COMPAT | ||
3582 | static int ext4dev_get_sb(struct file_system_type *fs_type, | ||
3583 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | ||
3584 | { | ||
3585 | printk(KERN_WARNING "EXT4-fs: Update your userspace programs " | ||
3586 | "to mount using ext4\n"); | ||
3587 | printk(KERN_WARNING "EXT4-fs: ext4dev backwards compatibility " | ||
3588 | "will go away by 2.6.31\n"); | ||
3589 | return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super, mnt); | ||
3590 | } | ||
3591 | |||
3496 | static struct file_system_type ext4dev_fs_type = { | 3592 | static struct file_system_type ext4dev_fs_type = { |
3497 | .owner = THIS_MODULE, | 3593 | .owner = THIS_MODULE, |
3498 | .name = "ext4dev", | 3594 | .name = "ext4dev", |
3499 | .get_sb = ext4_get_sb, | 3595 | .get_sb = ext4dev_get_sb, |
3500 | .kill_sb = kill_block_super, | 3596 | .kill_sb = kill_block_super, |
3501 | .fs_flags = FS_REQUIRES_DEV, | 3597 | .fs_flags = FS_REQUIRES_DEV, |
3502 | }; | 3598 | }; |
3599 | MODULE_ALIAS("ext4dev"); | ||
3600 | #endif | ||
3503 | 3601 | ||
3504 | static int __init init_ext4_fs(void) | 3602 | static int __init init_ext4_fs(void) |
3505 | { | 3603 | { |
3506 | int err; | 3604 | int err; |
3507 | 3605 | ||
3606 | ext4_proc_root = proc_mkdir("fs/ext4", NULL); | ||
3508 | err = init_ext4_mballoc(); | 3607 | err = init_ext4_mballoc(); |
3509 | if (err) | 3608 | if (err) |
3510 | return err; | 3609 | return err; |
@@ -3515,9 +3614,16 @@ static int __init init_ext4_fs(void) | |||
3515 | err = init_inodecache(); | 3614 | err = init_inodecache(); |
3516 | if (err) | 3615 | if (err) |
3517 | goto out1; | 3616 | goto out1; |
3518 | err = register_filesystem(&ext4dev_fs_type); | 3617 | err = register_filesystem(&ext4_fs_type); |
3519 | if (err) | 3618 | if (err) |
3520 | goto out; | 3619 | goto out; |
3620 | #ifdef CONFIG_EXT4DEV_COMPAT | ||
3621 | err = register_filesystem(&ext4dev_fs_type); | ||
3622 | if (err) { | ||
3623 | unregister_filesystem(&ext4_fs_type); | ||
3624 | goto out; | ||
3625 | } | ||
3626 | #endif | ||
3521 | return 0; | 3627 | return 0; |
3522 | out: | 3628 | out: |
3523 | destroy_inodecache(); | 3629 | destroy_inodecache(); |
@@ -3530,10 +3636,14 @@ out2: | |||
3530 | 3636 | ||
3531 | static void __exit exit_ext4_fs(void) | 3637 | static void __exit exit_ext4_fs(void) |
3532 | { | 3638 | { |
3639 | unregister_filesystem(&ext4_fs_type); | ||
3640 | #ifdef CONFIG_EXT4DEV_COMPAT | ||
3533 | unregister_filesystem(&ext4dev_fs_type); | 3641 | unregister_filesystem(&ext4dev_fs_type); |
3642 | #endif | ||
3534 | destroy_inodecache(); | 3643 | destroy_inodecache(); |
3535 | exit_ext4_xattr(); | 3644 | exit_ext4_xattr(); |
3536 | exit_ext4_mballoc(); | 3645 | exit_ext4_mballoc(); |
3646 | remove_proc_entry("fs/ext4", NULL); | ||
3537 | } | 3647 | } |
3538 | 3648 | ||
3539 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); | 3649 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); |