diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-26 12:53:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-26 12:53:20 -0400 |
| commit | 35806b4f7c5620b547f183e9d53f7cfaeabb582b (patch) | |
| tree | dc966f5edd9e482fdc85b8fb886ae39ce5c5ec80 /fs/ext4/super.c | |
| parent | 32e51f141fd8d880f57b6a2eb53ce72856254d4a (diff) | |
| parent | d183e11a4a66d80e10d60b0918a47cf073135379 (diff) | |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (61 commits)
jbd2: Add MAINTAINERS entry
jbd2: fix a potential leak of a journal_head on an error path
ext4: teach ext4_ext_split to calculate extents efficiently
ext4: Convert ext4 to new truncate calling convention
ext4: do not normalize block requests from fallocate()
ext4: enable "punch hole" functionality
ext4: add "punch hole" flag to ext4_map_blocks()
ext4: punch out extents
ext4: add new function ext4_block_zero_page_range()
ext4: add flag to ext4_has_free_blocks
ext4: reserve inodes and feature code for 'quota' feature
ext4: add support for multiple mount protection
ext4: ensure f_bfree returned by ext4_statfs() is non-negative
ext4: protect bb_first_free in ext4_trim_all_free() with group lock
ext4: only load buddy bitmap in ext4_trim_fs() when it is needed
jbd2: Fix comment to match the code in jbd2__journal_start()
ext4: fix waiting and sending of a barrier in ext4_sync_file()
jbd2: Add function jbd2_trans_will_send_data_barrier()
jbd2: fix sending of data flush on journal commit
ext4: fix ext4_ext_fiemap_cb() to handle blocks before request range correctly
...
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 204 |
1 files changed, 135 insertions, 69 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8553dfb310af..d9937df7f5cf 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -75,11 +75,27 @@ static void ext4_write_super(struct super_block *sb); | |||
| 75 | static int ext4_freeze(struct super_block *sb); | 75 | static int ext4_freeze(struct super_block *sb); |
| 76 | static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, | 76 | static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, |
| 77 | const char *dev_name, void *data); | 77 | const char *dev_name, void *data); |
| 78 | static inline int ext2_feature_set_ok(struct super_block *sb); | ||
| 79 | static inline int ext3_feature_set_ok(struct super_block *sb); | ||
| 78 | static int ext4_feature_set_ok(struct super_block *sb, int readonly); | 80 | static int ext4_feature_set_ok(struct super_block *sb, int readonly); |
| 79 | static void ext4_destroy_lazyinit_thread(void); | 81 | static void ext4_destroy_lazyinit_thread(void); |
| 80 | static void ext4_unregister_li_request(struct super_block *sb); | 82 | static void ext4_unregister_li_request(struct super_block *sb); |
| 81 | static void ext4_clear_request_list(void); | 83 | static void ext4_clear_request_list(void); |
| 82 | 84 | ||
| 85 | #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) | ||
| 86 | static struct file_system_type ext2_fs_type = { | ||
| 87 | .owner = THIS_MODULE, | ||
| 88 | .name = "ext2", | ||
| 89 | .mount = ext4_mount, | ||
| 90 | .kill_sb = kill_block_super, | ||
| 91 | .fs_flags = FS_REQUIRES_DEV, | ||
| 92 | }; | ||
| 93 | #define IS_EXT2_SB(sb) ((sb)->s_bdev->bd_holder == &ext2_fs_type) | ||
| 94 | #else | ||
| 95 | #define IS_EXT2_SB(sb) (0) | ||
| 96 | #endif | ||
| 97 | |||
| 98 | |||
| 83 | #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) | 99 | #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) |
| 84 | static struct file_system_type ext3_fs_type = { | 100 | static struct file_system_type ext3_fs_type = { |
| 85 | .owner = THIS_MODULE, | 101 | .owner = THIS_MODULE, |
| @@ -806,6 +822,8 @@ static void ext4_put_super(struct super_block *sb) | |||
| 806 | invalidate_bdev(sbi->journal_bdev); | 822 | invalidate_bdev(sbi->journal_bdev); |
| 807 | ext4_blkdev_remove(sbi); | 823 | ext4_blkdev_remove(sbi); |
| 808 | } | 824 | } |
| 825 | if (sbi->s_mmp_tsk) | ||
| 826 | kthread_stop(sbi->s_mmp_tsk); | ||
| 809 | sb->s_fs_info = NULL; | 827 | sb->s_fs_info = NULL; |
| 810 | /* | 828 | /* |
| 811 | * Now that we are completely done shutting down the | 829 | * Now that we are completely done shutting down the |
| @@ -1096,7 +1114,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 1096 | 1114 | ||
| 1097 | if (!test_opt(sb, INIT_INODE_TABLE)) | 1115 | if (!test_opt(sb, INIT_INODE_TABLE)) |
| 1098 | seq_puts(seq, ",noinit_inode_table"); | 1116 | seq_puts(seq, ",noinit_inode_table"); |
| 1099 | else if (sbi->s_li_wait_mult) | 1117 | else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT) |
| 1100 | seq_printf(seq, ",init_inode_table=%u", | 1118 | seq_printf(seq, ",init_inode_table=%u", |
| 1101 | (unsigned) sbi->s_li_wait_mult); | 1119 | (unsigned) sbi->s_li_wait_mult); |
| 1102 | 1120 | ||
| @@ -1187,9 +1205,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, | |||
| 1187 | const char *data, size_t len, loff_t off); | 1205 | const char *data, size_t len, loff_t off); |
| 1188 | 1206 | ||
| 1189 | static const struct dquot_operations ext4_quota_operations = { | 1207 | static const struct dquot_operations ext4_quota_operations = { |
| 1190 | #ifdef CONFIG_QUOTA | ||
| 1191 | .get_reserved_space = ext4_get_reserved_space, | 1208 | .get_reserved_space = ext4_get_reserved_space, |
| 1192 | #endif | ||
| 1193 | .write_dquot = ext4_write_dquot, | 1209 | .write_dquot = ext4_write_dquot, |
| 1194 | .acquire_dquot = ext4_acquire_dquot, | 1210 | .acquire_dquot = ext4_acquire_dquot, |
| 1195 | .release_dquot = ext4_release_dquot, | 1211 | .release_dquot = ext4_release_dquot, |
| @@ -1900,7 +1916,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, | |||
| 1900 | ext4_msg(sb, KERN_WARNING, | 1916 | ext4_msg(sb, KERN_WARNING, |
| 1901 | "warning: mounting fs with errors, " | 1917 | "warning: mounting fs with errors, " |
| 1902 | "running e2fsck is recommended"); | 1918 | "running e2fsck is recommended"); |
| 1903 | else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 && | 1919 | else if ((__s16) le16_to_cpu(es->s_max_mnt_count) > 0 && |
| 1904 | le16_to_cpu(es->s_mnt_count) >= | 1920 | le16_to_cpu(es->s_mnt_count) >= |
| 1905 | (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) | 1921 | (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count)) |
| 1906 | ext4_msg(sb, KERN_WARNING, | 1922 | ext4_msg(sb, KERN_WARNING, |
| @@ -2425,6 +2441,18 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, | |||
| 2425 | EXT4_SB(sb)->s_sectors_written_start) >> 1))); | 2441 | EXT4_SB(sb)->s_sectors_written_start) >> 1))); |
| 2426 | } | 2442 | } |
| 2427 | 2443 | ||
| 2444 | static ssize_t extent_cache_hits_show(struct ext4_attr *a, | ||
| 2445 | struct ext4_sb_info *sbi, char *buf) | ||
| 2446 | { | ||
| 2447 | return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits); | ||
| 2448 | } | ||
| 2449 | |||
| 2450 | static ssize_t extent_cache_misses_show(struct ext4_attr *a, | ||
| 2451 | struct ext4_sb_info *sbi, char *buf) | ||
| 2452 | { | ||
| 2453 | return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses); | ||
| 2454 | } | ||
| 2455 | |||
| 2428 | static ssize_t inode_readahead_blks_store(struct ext4_attr *a, | 2456 | static ssize_t inode_readahead_blks_store(struct ext4_attr *a, |
| 2429 | struct ext4_sb_info *sbi, | 2457 | struct ext4_sb_info *sbi, |
| 2430 | const char *buf, size_t count) | 2458 | const char *buf, size_t count) |
| @@ -2482,6 +2510,8 @@ static struct ext4_attr ext4_attr_##name = __ATTR(name, mode, show, store) | |||
| 2482 | EXT4_RO_ATTR(delayed_allocation_blocks); | 2510 | EXT4_RO_ATTR(delayed_allocation_blocks); |
| 2483 | EXT4_RO_ATTR(session_write_kbytes); | 2511 | EXT4_RO_ATTR(session_write_kbytes); |
| 2484 | EXT4_RO_ATTR(lifetime_write_kbytes); | 2512 | EXT4_RO_ATTR(lifetime_write_kbytes); |
| 2513 | EXT4_RO_ATTR(extent_cache_hits); | ||
| 2514 | EXT4_RO_ATTR(extent_cache_misses); | ||
| 2485 | EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, | 2515 | EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show, |
| 2486 | inode_readahead_blks_store, s_inode_readahead_blks); | 2516 | inode_readahead_blks_store, s_inode_readahead_blks); |
| 2487 | EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); | 2517 | EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal); |
| @@ -2497,6 +2527,8 @@ static struct attribute *ext4_attrs[] = { | |||
| 2497 | ATTR_LIST(delayed_allocation_blocks), | 2527 | ATTR_LIST(delayed_allocation_blocks), |
| 2498 | ATTR_LIST(session_write_kbytes), | 2528 | ATTR_LIST(session_write_kbytes), |
| 2499 | ATTR_LIST(lifetime_write_kbytes), | 2529 | ATTR_LIST(lifetime_write_kbytes), |
| 2530 | ATTR_LIST(extent_cache_hits), | ||
| 2531 | ATTR_LIST(extent_cache_misses), | ||
| 2500 | ATTR_LIST(inode_readahead_blks), | 2532 | ATTR_LIST(inode_readahead_blks), |
| 2501 | ATTR_LIST(inode_goal), | 2533 | ATTR_LIST(inode_goal), |
| 2502 | ATTR_LIST(mb_stats), | 2534 | ATTR_LIST(mb_stats), |
| @@ -2659,12 +2691,6 @@ static void print_daily_error_info(unsigned long arg) | |||
| 2659 | mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ | 2691 | mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ |
| 2660 | } | 2692 | } |
| 2661 | 2693 | ||
| 2662 | static void ext4_lazyinode_timeout(unsigned long data) | ||
| 2663 | { | ||
| 2664 | struct task_struct *p = (struct task_struct *)data; | ||
| 2665 | wake_up_process(p); | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | /* Find next suitable group and run ext4_init_inode_table */ | 2694 | /* Find next suitable group and run ext4_init_inode_table */ |
| 2669 | static int ext4_run_li_request(struct ext4_li_request *elr) | 2695 | static int ext4_run_li_request(struct ext4_li_request *elr) |
| 2670 | { | 2696 | { |
| @@ -2696,11 +2722,8 @@ static int ext4_run_li_request(struct ext4_li_request *elr) | |||
| 2696 | ret = ext4_init_inode_table(sb, group, | 2722 | ret = ext4_init_inode_table(sb, group, |
| 2697 | elr->lr_timeout ? 0 : 1); | 2723 | elr->lr_timeout ? 0 : 1); |
| 2698 | if (elr->lr_timeout == 0) { | 2724 | if (elr->lr_timeout == 0) { |
| 2699 | timeout = jiffies - timeout; | 2725 | timeout = (jiffies - timeout) * |
| 2700 | if (elr->lr_sbi->s_li_wait_mult) | 2726 | elr->lr_sbi->s_li_wait_mult; |
| 2701 | timeout *= elr->lr_sbi->s_li_wait_mult; | ||
| 2702 | else | ||
| 2703 | timeout *= 20; | ||
| 2704 | elr->lr_timeout = timeout; | 2727 | elr->lr_timeout = timeout; |
| 2705 | } | 2728 | } |
| 2706 | elr->lr_next_sched = jiffies + elr->lr_timeout; | 2729 | elr->lr_next_sched = jiffies + elr->lr_timeout; |
| @@ -2712,7 +2735,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr) | |||
| 2712 | 2735 | ||
| 2713 | /* | 2736 | /* |
| 2714 | * Remove lr_request from the list_request and free the | 2737 | * Remove lr_request from the list_request and free the |
| 2715 | * request tructure. Should be called with li_list_mtx held | 2738 | * request structure. Should be called with li_list_mtx held |
| 2716 | */ | 2739 | */ |
| 2717 | static void ext4_remove_li_request(struct ext4_li_request *elr) | 2740 | static void ext4_remove_li_request(struct ext4_li_request *elr) |
| 2718 | { | 2741 | { |
| @@ -2730,14 +2753,16 @@ static void ext4_remove_li_request(struct ext4_li_request *elr) | |||
| 2730 | 2753 | ||
| 2731 | static void ext4_unregister_li_request(struct super_block *sb) | 2754 | static void ext4_unregister_li_request(struct super_block *sb) |
| 2732 | { | 2755 | { |
| 2733 | struct ext4_li_request *elr = EXT4_SB(sb)->s_li_request; | 2756 | mutex_lock(&ext4_li_mtx); |
| 2734 | 2757 | if (!ext4_li_info) { | |
| 2735 | if (!ext4_li_info) | 2758 | mutex_unlock(&ext4_li_mtx); |
| 2736 | return; | 2759 | return; |
| 2760 | } | ||
| 2737 | 2761 | ||
| 2738 | mutex_lock(&ext4_li_info->li_list_mtx); | 2762 | mutex_lock(&ext4_li_info->li_list_mtx); |
| 2739 | ext4_remove_li_request(elr); | 2763 | ext4_remove_li_request(EXT4_SB(sb)->s_li_request); |
| 2740 | mutex_unlock(&ext4_li_info->li_list_mtx); | 2764 | mutex_unlock(&ext4_li_info->li_list_mtx); |
| 2765 | mutex_unlock(&ext4_li_mtx); | ||
| 2741 | } | 2766 | } |
| 2742 | 2767 | ||
| 2743 | static struct task_struct *ext4_lazyinit_task; | 2768 | static struct task_struct *ext4_lazyinit_task; |
| @@ -2756,17 +2781,10 @@ static int ext4_lazyinit_thread(void *arg) | |||
| 2756 | struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg; | 2781 | struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg; |
| 2757 | struct list_head *pos, *n; | 2782 | struct list_head *pos, *n; |
| 2758 | struct ext4_li_request *elr; | 2783 | struct ext4_li_request *elr; |
| 2759 | unsigned long next_wakeup; | 2784 | unsigned long next_wakeup, cur; |
| 2760 | DEFINE_WAIT(wait); | ||
| 2761 | 2785 | ||
| 2762 | BUG_ON(NULL == eli); | 2786 | BUG_ON(NULL == eli); |
| 2763 | 2787 | ||
| 2764 | eli->li_timer.data = (unsigned long)current; | ||
| 2765 | eli->li_timer.function = ext4_lazyinode_timeout; | ||
| 2766 | |||
| 2767 | eli->li_task = current; | ||
| 2768 | wake_up(&eli->li_wait_task); | ||
| 2769 | |||
| 2770 | cont_thread: | 2788 | cont_thread: |
| 2771 | while (true) { | 2789 | while (true) { |
| 2772 | next_wakeup = MAX_JIFFY_OFFSET; | 2790 | next_wakeup = MAX_JIFFY_OFFSET; |
| @@ -2797,19 +2815,15 @@ cont_thread: | |||
| 2797 | if (freezing(current)) | 2815 | if (freezing(current)) |
| 2798 | refrigerator(); | 2816 | refrigerator(); |
| 2799 | 2817 | ||
| 2800 | if ((time_after_eq(jiffies, next_wakeup)) || | 2818 | cur = jiffies; |
| 2819 | if ((time_after_eq(cur, next_wakeup)) || | ||
| 2801 | (MAX_JIFFY_OFFSET == next_wakeup)) { | 2820 | (MAX_JIFFY_OFFSET == next_wakeup)) { |
| 2802 | cond_resched(); | 2821 | cond_resched(); |
| 2803 | continue; | 2822 | continue; |
| 2804 | } | 2823 | } |
| 2805 | 2824 | ||
| 2806 | eli->li_timer.expires = next_wakeup; | 2825 | schedule_timeout_interruptible(next_wakeup - cur); |
| 2807 | add_timer(&eli->li_timer); | 2826 | |
| 2808 | prepare_to_wait(&eli->li_wait_daemon, &wait, | ||
| 2809 | TASK_INTERRUPTIBLE); | ||
| 2810 | if (time_before(jiffies, next_wakeup)) | ||
| 2811 | schedule(); | ||
| 2812 | finish_wait(&eli->li_wait_daemon, &wait); | ||
| 2813 | if (kthread_should_stop()) { | 2827 | if (kthread_should_stop()) { |
| 2814 | ext4_clear_request_list(); | 2828 | ext4_clear_request_list(); |
| 2815 | goto exit_thread; | 2829 | goto exit_thread; |
| @@ -2833,12 +2847,7 @@ exit_thread: | |||
| 2833 | goto cont_thread; | 2847 | goto cont_thread; |
| 2834 | } | 2848 | } |
| 2835 | mutex_unlock(&eli->li_list_mtx); | 2849 | mutex_unlock(&eli->li_list_mtx); |
| 2836 | del_timer_sync(&ext4_li_info->li_timer); | ||
| 2837 | eli->li_task = NULL; | ||
| 2838 | wake_up(&eli->li_wait_task); | ||
| 2839 | |||
| 2840 | kfree(ext4_li_info); | 2850 | kfree(ext4_li_info); |
| 2841 | ext4_lazyinit_task = NULL; | ||
| 2842 | ext4_li_info = NULL; | 2851 | ext4_li_info = NULL; |
| 2843 | mutex_unlock(&ext4_li_mtx); | 2852 | mutex_unlock(&ext4_li_mtx); |
| 2844 | 2853 | ||
| @@ -2866,7 +2875,6 @@ static int ext4_run_lazyinit_thread(void) | |||
| 2866 | if (IS_ERR(ext4_lazyinit_task)) { | 2875 | if (IS_ERR(ext4_lazyinit_task)) { |
| 2867 | int err = PTR_ERR(ext4_lazyinit_task); | 2876 | int err = PTR_ERR(ext4_lazyinit_task); |
| 2868 | ext4_clear_request_list(); | 2877 | ext4_clear_request_list(); |
| 2869 | del_timer_sync(&ext4_li_info->li_timer); | ||
| 2870 | kfree(ext4_li_info); | 2878 | kfree(ext4_li_info); |
| 2871 | ext4_li_info = NULL; | 2879 | ext4_li_info = NULL; |
| 2872 | printk(KERN_CRIT "EXT4: error %d creating inode table " | 2880 | printk(KERN_CRIT "EXT4: error %d creating inode table " |
| @@ -2875,8 +2883,6 @@ static int ext4_run_lazyinit_thread(void) | |||
| 2875 | return err; | 2883 | return err; |
| 2876 | } | 2884 | } |
| 2877 | ext4_li_info->li_state |= EXT4_LAZYINIT_RUNNING; | 2885 | ext4_li_info->li_state |= EXT4_LAZYINIT_RUNNING; |
| 2878 | |||
| 2879 | wait_event(ext4_li_info->li_wait_task, ext4_li_info->li_task != NULL); | ||
| 2880 | return 0; | 2886 | return 0; |
| 2881 | } | 2887 | } |
| 2882 | 2888 | ||
| @@ -2911,13 +2917,9 @@ static int ext4_li_info_new(void) | |||
| 2911 | if (!eli) | 2917 | if (!eli) |
| 2912 | return -ENOMEM; | 2918 | return -ENOMEM; |
| 2913 | 2919 | ||
| 2914 | eli->li_task = NULL; | ||
| 2915 | INIT_LIST_HEAD(&eli->li_request_list); | 2920 | INIT_LIST_HEAD(&eli->li_request_list); |
| 2916 | mutex_init(&eli->li_list_mtx); | 2921 | mutex_init(&eli->li_list_mtx); |
| 2917 | 2922 | ||
| 2918 | init_waitqueue_head(&eli->li_wait_daemon); | ||
| 2919 | init_waitqueue_head(&eli->li_wait_task); | ||
| 2920 | init_timer(&eli->li_timer); | ||
| 2921 | eli->li_state |= EXT4_LAZYINIT_QUIT; | 2923 | eli->li_state |= EXT4_LAZYINIT_QUIT; |
| 2922 | 2924 | ||
| 2923 | ext4_li_info = eli; | 2925 | ext4_li_info = eli; |
| @@ -2960,20 +2962,19 @@ static int ext4_register_li_request(struct super_block *sb, | |||
| 2960 | ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; | 2962 | ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; |
| 2961 | int ret = 0; | 2963 | int ret = 0; |
| 2962 | 2964 | ||
| 2963 | if (sbi->s_li_request != NULL) | 2965 | if (sbi->s_li_request != NULL) { |
| 2966 | /* | ||
| 2967 | * Reset timeout so it can be computed again, because | ||
| 2968 | * s_li_wait_mult might have changed. | ||
| 2969 | */ | ||
| 2970 | sbi->s_li_request->lr_timeout = 0; | ||
| 2964 | return 0; | 2971 | return 0; |
| 2972 | } | ||
| 2965 | 2973 | ||
| 2966 | if (first_not_zeroed == ngroups || | 2974 | if (first_not_zeroed == ngroups || |
| 2967 | (sb->s_flags & MS_RDONLY) || | 2975 | (sb->s_flags & MS_RDONLY) || |
| 2968 | !test_opt(sb, INIT_INODE_TABLE)) { | 2976 | !test_opt(sb, INIT_INODE_TABLE)) |
| 2969 | sbi->s_li_request = NULL; | ||
| 2970 | return 0; | 2977 | return 0; |
| 2971 | } | ||
| 2972 | |||
| 2973 | if (first_not_zeroed == ngroups) { | ||
| 2974 | sbi->s_li_request = NULL; | ||
| 2975 | return 0; | ||
| 2976 | } | ||
| 2977 | 2978 | ||
| 2978 | elr = ext4_li_request_new(sb, first_not_zeroed); | 2979 | elr = ext4_li_request_new(sb, first_not_zeroed); |
| 2979 | if (!elr) | 2980 | if (!elr) |
| @@ -3166,6 +3167,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3166 | ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0)) | 3167 | ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0)) |
| 3167 | set_opt(sb, DELALLOC); | 3168 | set_opt(sb, DELALLOC); |
| 3168 | 3169 | ||
| 3170 | /* | ||
| 3171 | * set default s_li_wait_mult for lazyinit, for the case there is | ||
| 3172 | * no mount option specified. | ||
| 3173 | */ | ||
| 3174 | sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT; | ||
| 3175 | |||
| 3169 | if (!parse_options((char *) sbi->s_es->s_mount_opts, sb, | 3176 | if (!parse_options((char *) sbi->s_es->s_mount_opts, sb, |
| 3170 | &journal_devnum, &journal_ioprio, NULL, 0)) { | 3177 | &journal_devnum, &journal_ioprio, NULL, 0)) { |
| 3171 | ext4_msg(sb, KERN_WARNING, | 3178 | ext4_msg(sb, KERN_WARNING, |
| @@ -3187,6 +3194,28 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3187 | "feature flags set on rev 0 fs, " | 3194 | "feature flags set on rev 0 fs, " |
| 3188 | "running e2fsck is recommended"); | 3195 | "running e2fsck is recommended"); |
| 3189 | 3196 | ||
| 3197 | if (IS_EXT2_SB(sb)) { | ||
| 3198 | if (ext2_feature_set_ok(sb)) | ||
| 3199 | ext4_msg(sb, KERN_INFO, "mounting ext2 file system " | ||
| 3200 | "using the ext4 subsystem"); | ||
| 3201 | else { | ||
| 3202 | ext4_msg(sb, KERN_ERR, "couldn't mount as ext2 due " | ||
| 3203 | "to feature incompatibilities"); | ||
| 3204 | goto failed_mount; | ||
| 3205 | } | ||
| 3206 | } | ||
| 3207 | |||
| 3208 | if (IS_EXT3_SB(sb)) { | ||
| 3209 | if (ext3_feature_set_ok(sb)) | ||
| 3210 | ext4_msg(sb, KERN_INFO, "mounting ext3 file system " | ||
| 3211 | "using the ext4 subsystem"); | ||
| 3212 | else { | ||
| 3213 | ext4_msg(sb, KERN_ERR, "couldn't mount as ext3 due " | ||
| 3214 | "to feature incompatibilities"); | ||
| 3215 | goto failed_mount; | ||
| 3216 | } | ||
| 3217 | } | ||
| 3218 | |||
| 3190 | /* | 3219 | /* |
| 3191 | * Check feature flags regardless of the revision level, since we | 3220 | * Check feature flags regardless of the revision level, since we |
| 3192 | * previously didn't change the revision level when setting the flags, | 3221 | * previously didn't change the revision level when setting the flags, |
| @@ -3459,6 +3488,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3459 | EXT4_HAS_INCOMPAT_FEATURE(sb, | 3488 | EXT4_HAS_INCOMPAT_FEATURE(sb, |
| 3460 | EXT4_FEATURE_INCOMPAT_RECOVER)); | 3489 | EXT4_FEATURE_INCOMPAT_RECOVER)); |
| 3461 | 3490 | ||
| 3491 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_MMP) && | ||
| 3492 | !(sb->s_flags & MS_RDONLY)) | ||
| 3493 | if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block))) | ||
| 3494 | goto failed_mount3; | ||
| 3495 | |||
| 3462 | /* | 3496 | /* |
| 3463 | * The first inode we look at is the journal inode. Don't try | 3497 | * The first inode we look at is the journal inode. Don't try |
| 3464 | * root first: it may be modified in the journal! | 3498 | * root first: it may be modified in the journal! |
| @@ -3474,7 +3508,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 3474 | goto failed_mount_wq; | 3508 | goto failed_mount_wq; |
| 3475 | } else { | 3509 | } else { |
| 3476 | clear_opt(sb, DATA_FLAGS); | 3510 | clear_opt(sb, DATA_FLAGS); |
| 3477 | set_opt(sb, WRITEBACK_DATA); | ||
| 3478 | sbi->s_journal = NULL; | 3511 | sbi->s_journal = NULL; |
| 3479 | needs_recovery = 0; | 3512 | needs_recovery = 0; |
| 3480 | goto no_journal; | 3513 | goto no_journal; |
| @@ -3707,6 +3740,8 @@ failed_mount3: | |||
| 3707 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 3740 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
| 3708 | percpu_counter_destroy(&sbi->s_dirs_counter); | 3741 | percpu_counter_destroy(&sbi->s_dirs_counter); |
| 3709 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); | 3742 | percpu_counter_destroy(&sbi->s_dirtyblocks_counter); |
| 3743 | if (sbi->s_mmp_tsk) | ||
| 3744 | kthread_stop(sbi->s_mmp_tsk); | ||
| 3710 | failed_mount2: | 3745 | failed_mount2: |
| 3711 | for (i = 0; i < db_count; i++) | 3746 | for (i = 0; i < db_count; i++) |
| 3712 | brelse(sbi->s_group_desc[i]); | 3747 | brelse(sbi->s_group_desc[i]); |
| @@ -4242,7 +4277,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 4242 | int enable_quota = 0; | 4277 | int enable_quota = 0; |
| 4243 | ext4_group_t g; | 4278 | ext4_group_t g; |
| 4244 | unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; | 4279 | unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; |
| 4245 | int err; | 4280 | int err = 0; |
| 4246 | #ifdef CONFIG_QUOTA | 4281 | #ifdef CONFIG_QUOTA |
| 4247 | int i; | 4282 | int i; |
| 4248 | #endif | 4283 | #endif |
| @@ -4368,6 +4403,13 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
| 4368 | goto restore_opts; | 4403 | goto restore_opts; |
| 4369 | if (!ext4_setup_super(sb, es, 0)) | 4404 | if (!ext4_setup_super(sb, es, 0)) |
| 4370 | sb->s_flags &= ~MS_RDONLY; | 4405 | sb->s_flags &= ~MS_RDONLY; |
| 4406 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, | ||
| 4407 | EXT4_FEATURE_INCOMPAT_MMP)) | ||
| 4408 | if (ext4_multi_mount_protect(sb, | ||
| 4409 | le64_to_cpu(es->s_mmp_block))) { | ||
| 4410 | err = -EROFS; | ||
| 4411 | goto restore_opts; | ||
| 4412 | } | ||
| 4371 | enable_quota = 1; | 4413 | enable_quota = 1; |
| 4372 | } | 4414 | } |
| 4373 | } | 4415 | } |
| @@ -4432,6 +4474,7 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 4432 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 4474 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 4433 | struct ext4_super_block *es = sbi->s_es; | 4475 | struct ext4_super_block *es = sbi->s_es; |
| 4434 | u64 fsid; | 4476 | u64 fsid; |
| 4477 | s64 bfree; | ||
| 4435 | 4478 | ||
| 4436 | if (test_opt(sb, MINIX_DF)) { | 4479 | if (test_opt(sb, MINIX_DF)) { |
| 4437 | sbi->s_overhead_last = 0; | 4480 | sbi->s_overhead_last = 0; |
| @@ -4475,8 +4518,10 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 4475 | buf->f_type = EXT4_SUPER_MAGIC; | 4518 | buf->f_type = EXT4_SUPER_MAGIC; |
| 4476 | buf->f_bsize = sb->s_blocksize; | 4519 | buf->f_bsize = sb->s_blocksize; |
| 4477 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; | 4520 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; |
| 4478 | buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - | 4521 | bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) - |
| 4479 | percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); | 4522 | percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter); |
| 4523 | /* prevent underflow in case that few free space is available */ | ||
| 4524 | buf->f_bfree = max_t(s64, bfree, 0); | ||
| 4480 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); | 4525 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); |
| 4481 | if (buf->f_bfree < ext4_r_blocks_count(es)) | 4526 | if (buf->f_bfree < ext4_r_blocks_count(es)) |
| 4482 | buf->f_bavail = 0; | 4527 | buf->f_bavail = 0; |
| @@ -4652,6 +4697,9 @@ static int ext4_quota_off(struct super_block *sb, int type) | |||
| 4652 | if (test_opt(sb, DELALLOC)) | 4697 | if (test_opt(sb, DELALLOC)) |
| 4653 | sync_filesystem(sb); | 4698 | sync_filesystem(sb); |
| 4654 | 4699 | ||
| 4700 | if (!inode) | ||
| 4701 | goto out; | ||
| 4702 | |||
| 4655 | /* Update modification times of quota files when userspace can | 4703 | /* Update modification times of quota files when userspace can |
| 4656 | * start looking at them */ | 4704 | * start looking at them */ |
| 4657 | handle = ext4_journal_start(inode, 1); | 4705 | handle = ext4_journal_start(inode, 1); |
| @@ -4772,14 +4820,6 @@ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, | |||
| 4772 | } | 4820 | } |
| 4773 | 4821 | ||
| 4774 | #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) | 4822 | #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) |
| 4775 | static struct file_system_type ext2_fs_type = { | ||
| 4776 | .owner = THIS_MODULE, | ||
| 4777 | .name = "ext2", | ||
| 4778 | .mount = ext4_mount, | ||
| 4779 | .kill_sb = kill_block_super, | ||
| 4780 | .fs_flags = FS_REQUIRES_DEV, | ||
| 4781 | }; | ||
| 4782 | |||
| 4783 | static inline void register_as_ext2(void) | 4823 | static inline void register_as_ext2(void) |
| 4784 | { | 4824 | { |
| 4785 | int err = register_filesystem(&ext2_fs_type); | 4825 | int err = register_filesystem(&ext2_fs_type); |
| @@ -4792,10 +4832,22 @@ static inline void unregister_as_ext2(void) | |||
| 4792 | { | 4832 | { |
| 4793 | unregister_filesystem(&ext2_fs_type); | 4833 | unregister_filesystem(&ext2_fs_type); |
| 4794 | } | 4834 | } |
| 4835 | |||
| 4836 | static inline int ext2_feature_set_ok(struct super_block *sb) | ||
| 4837 | { | ||
| 4838 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP)) | ||
| 4839 | return 0; | ||
| 4840 | if (sb->s_flags & MS_RDONLY) | ||
| 4841 | return 1; | ||
| 4842 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP)) | ||
| 4843 | return 0; | ||
| 4844 | return 1; | ||
| 4845 | } | ||
| 4795 | MODULE_ALIAS("ext2"); | 4846 | MODULE_ALIAS("ext2"); |
| 4796 | #else | 4847 | #else |
| 4797 | static inline void register_as_ext2(void) { } | 4848 | static inline void register_as_ext2(void) { } |
| 4798 | static inline void unregister_as_ext2(void) { } | 4849 | static inline void unregister_as_ext2(void) { } |
| 4850 | static inline int ext2_feature_set_ok(struct super_block *sb) { return 0; } | ||
| 4799 | #endif | 4851 | #endif |
| 4800 | 4852 | ||
| 4801 | #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) | 4853 | #if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) |
| @@ -4811,10 +4863,24 @@ static inline void unregister_as_ext3(void) | |||
| 4811 | { | 4863 | { |
| 4812 | unregister_filesystem(&ext3_fs_type); | 4864 | unregister_filesystem(&ext3_fs_type); |
| 4813 | } | 4865 | } |
| 4866 | |||
| 4867 | static inline int ext3_feature_set_ok(struct super_block *sb) | ||
| 4868 | { | ||
| 4869 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP)) | ||
| 4870 | return 0; | ||
| 4871 | if (!EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) | ||
| 4872 | return 0; | ||
| 4873 | if (sb->s_flags & MS_RDONLY) | ||
| 4874 | return 1; | ||
| 4875 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) | ||
| 4876 | return 0; | ||
| 4877 | return 1; | ||
| 4878 | } | ||
| 4814 | MODULE_ALIAS("ext3"); | 4879 | MODULE_ALIAS("ext3"); |
| 4815 | #else | 4880 | #else |
| 4816 | static inline void register_as_ext3(void) { } | 4881 | static inline void register_as_ext3(void) { } |
| 4817 | static inline void unregister_as_ext3(void) { } | 4882 | static inline void unregister_as_ext3(void) { } |
| 4883 | static inline int ext3_feature_set_ok(struct super_block *sb) { return 0; } | ||
| 4818 | #endif | 4884 | #endif |
| 4819 | 4885 | ||
| 4820 | static struct file_system_type ext4_fs_type = { | 4886 | static struct file_system_type ext4_fs_type = { |
| @@ -4898,8 +4964,8 @@ static int __init ext4_init_fs(void) | |||
| 4898 | err = init_inodecache(); | 4964 | err = init_inodecache(); |
| 4899 | if (err) | 4965 | if (err) |
| 4900 | goto out1; | 4966 | goto out1; |
| 4901 | register_as_ext2(); | ||
| 4902 | register_as_ext3(); | 4967 | register_as_ext3(); |
| 4968 | register_as_ext2(); | ||
| 4903 | err = register_filesystem(&ext4_fs_type); | 4969 | err = register_filesystem(&ext4_fs_type); |
| 4904 | if (err) | 4970 | if (err) |
| 4905 | goto out; | 4971 | goto out; |
