diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 99 |
1 files changed, 57 insertions, 42 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index df539ba27779..12e726a7073f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -50,13 +50,6 @@ | |||
| 50 | #define CREATE_TRACE_POINTS | 50 | #define CREATE_TRACE_POINTS |
| 51 | #include <trace/events/ext4.h> | 51 | #include <trace/events/ext4.h> |
| 52 | 52 | ||
| 53 | static int default_mb_history_length = 1000; | ||
| 54 | |||
| 55 | module_param_named(default_mb_history_length, default_mb_history_length, | ||
| 56 | int, 0644); | ||
| 57 | MODULE_PARM_DESC(default_mb_history_length, | ||
| 58 | "Default number of entries saved for mb_history"); | ||
| 59 | |||
| 60 | struct proc_dir_entry *ext4_proc_root; | 53 | struct proc_dir_entry *ext4_proc_root; |
| 61 | static struct kset *ext4_kset; | 54 | static struct kset *ext4_kset; |
| 62 | 55 | ||
| @@ -189,6 +182,36 @@ void ext4_itable_unused_set(struct super_block *sb, | |||
| 189 | bg->bg_itable_unused_hi = cpu_to_le16(count >> 16); | 182 | bg->bg_itable_unused_hi = cpu_to_le16(count >> 16); |
| 190 | } | 183 | } |
| 191 | 184 | ||
| 185 | |||
| 186 | /* Just increment the non-pointer handle value */ | ||
| 187 | static handle_t *ext4_get_nojournal(void) | ||
| 188 | { | ||
| 189 | handle_t *handle = current->journal_info; | ||
| 190 | unsigned long ref_cnt = (unsigned long)handle; | ||
| 191 | |||
| 192 | BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT); | ||
| 193 | |||
| 194 | ref_cnt++; | ||
| 195 | handle = (handle_t *)ref_cnt; | ||
| 196 | |||
| 197 | current->journal_info = handle; | ||
| 198 | return handle; | ||
| 199 | } | ||
| 200 | |||
| 201 | |||
| 202 | /* Decrement the non-pointer handle value */ | ||
| 203 | static void ext4_put_nojournal(handle_t *handle) | ||
| 204 | { | ||
| 205 | unsigned long ref_cnt = (unsigned long)handle; | ||
| 206 | |||
| 207 | BUG_ON(ref_cnt == 0); | ||
| 208 | |||
| 209 | ref_cnt--; | ||
| 210 | handle = (handle_t *)ref_cnt; | ||
| 211 | |||
| 212 | current->journal_info = handle; | ||
| 213 | } | ||
| 214 | |||
| 192 | /* | 215 | /* |
| 193 | * Wrappers for jbd2_journal_start/end. | 216 | * Wrappers for jbd2_journal_start/end. |
| 194 | * | 217 | * |
| @@ -215,11 +238,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | |||
| 215 | } | 238 | } |
| 216 | return jbd2_journal_start(journal, nblocks); | 239 | return jbd2_journal_start(journal, nblocks); |
| 217 | } | 240 | } |
| 218 | /* | 241 | return ext4_get_nojournal(); |
| 219 | * We're not journaling, return the appropriate indication. | ||
| 220 | */ | ||
| 221 | current->journal_info = EXT4_NOJOURNAL_HANDLE; | ||
| 222 | return current->journal_info; | ||
| 223 | } | 242 | } |
| 224 | 243 | ||
| 225 | /* | 244 | /* |
| @@ -235,11 +254,7 @@ int __ext4_journal_stop(const char *where, handle_t *handle) | |||
| 235 | int rc; | 254 | int rc; |
| 236 | 255 | ||
| 237 | if (!ext4_handle_valid(handle)) { | 256 | if (!ext4_handle_valid(handle)) { |
| 238 | /* | 257 | ext4_put_nojournal(handle); |
| 239 | * Do this here since we don't call jbd2_journal_stop() in | ||
| 240 | * no-journal mode. | ||
| 241 | */ | ||
| 242 | current->journal_info = NULL; | ||
| 243 | return 0; | 258 | return 0; |
| 244 | } | 259 | } |
| 245 | sb = handle->h_transaction->t_journal->j_private; | 260 | sb = handle->h_transaction->t_journal->j_private; |
| @@ -580,6 +595,9 @@ static void ext4_put_super(struct super_block *sb) | |||
| 580 | struct ext4_super_block *es = sbi->s_es; | 595 | struct ext4_super_block *es = sbi->s_es; |
| 581 | int i, err; | 596 | int i, err; |
| 582 | 597 | ||
| 598 | flush_workqueue(sbi->dio_unwritten_wq); | ||
| 599 | destroy_workqueue(sbi->dio_unwritten_wq); | ||
| 600 | |||
| 583 | lock_super(sb); | 601 | lock_super(sb); |
| 584 | lock_kernel(); | 602 | lock_kernel(); |
| 585 | if (sb->s_dirt) | 603 | if (sb->s_dirt) |
| @@ -684,6 +702,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
| 684 | ei->i_allocated_meta_blocks = 0; | 702 | ei->i_allocated_meta_blocks = 0; |
| 685 | ei->i_delalloc_reserved_flag = 0; | 703 | ei->i_delalloc_reserved_flag = 0; |
| 686 | spin_lock_init(&(ei->i_block_reservation_lock)); | 704 | spin_lock_init(&(ei->i_block_reservation_lock)); |
| 705 | INIT_LIST_HEAD(&ei->i_aio_dio_complete_list); | ||
| 706 | ei->cur_aio_dio = NULL; | ||
| 687 | 707 | ||
| 688 | return &ei->vfs_inode; | 708 | return &ei->vfs_inode; |
| 689 | } | 709 | } |
| @@ -1052,7 +1072,7 @@ enum { | |||
| 1052 | Opt_journal_update, Opt_journal_dev, | 1072 | Opt_journal_update, Opt_journal_dev, |
| 1053 | Opt_journal_checksum, Opt_journal_async_commit, | 1073 | Opt_journal_checksum, Opt_journal_async_commit, |
| 1054 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 1074 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
| 1055 | Opt_data_err_abort, Opt_data_err_ignore, Opt_mb_history_length, | 1075 | Opt_data_err_abort, Opt_data_err_ignore, |
| 1056 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 1076 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
| 1057 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, | 1077 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
| 1058 | Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize, | 1078 | Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize, |
| @@ -1099,7 +1119,6 @@ static const match_table_t tokens = { | |||
| 1099 | {Opt_data_writeback, "data=writeback"}, | 1119 | {Opt_data_writeback, "data=writeback"}, |
| 1100 | {Opt_data_err_abort, "data_err=abort"}, | 1120 | {Opt_data_err_abort, "data_err=abort"}, |
| 1101 | {Opt_data_err_ignore, "data_err=ignore"}, | 1121 | {Opt_data_err_ignore, "data_err=ignore"}, |
| 1102 | {Opt_mb_history_length, "mb_history_length=%u"}, | ||
| 1103 | {Opt_offusrjquota, "usrjquota="}, | 1122 | {Opt_offusrjquota, "usrjquota="}, |
| 1104 | {Opt_usrjquota, "usrjquota=%s"}, | 1123 | {Opt_usrjquota, "usrjquota=%s"}, |
| 1105 | {Opt_offgrpjquota, "grpjquota="}, | 1124 | {Opt_offgrpjquota, "grpjquota="}, |
| @@ -1340,13 +1359,6 @@ static int parse_options(char *options, struct super_block *sb, | |||
| 1340 | case Opt_data_err_ignore: | 1359 | case Opt_data_err_ignore: |
| 1341 | clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT); | 1360 | clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT); |
| 1342 | break; | 1361 | break; |
| 1343 | case Opt_mb_history_length: | ||
| 1344 | if (match_int(&args[0], &option)) | ||
| 1345 | return 0; | ||
| 1346 | if (option < 0) | ||
| 1347 | return 0; | ||
| 1348 | sbi->s_mb_history_max = option; | ||
| 1349 | break; | ||
| 1350 | #ifdef CONFIG_QUOTA | 1362 | #ifdef CONFIG_QUOTA |
| 1351 | case Opt_usrjquota: | 1363 | case Opt_usrjquota: |
| 1352 | qtype = USRQUOTA; | 1364 | qtype = USRQUOTA; |
| @@ -1646,13 +1658,6 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, | |||
| 1646 | EXT4_INODES_PER_GROUP(sb), | 1658 | EXT4_INODES_PER_GROUP(sb), |
| 1647 | sbi->s_mount_opt); | 1659 | sbi->s_mount_opt); |
| 1648 | 1660 | ||
| 1649 | if (EXT4_SB(sb)->s_journal) { | ||
| 1650 | ext4_msg(sb, KERN_INFO, "%s journal on %s", | ||
| 1651 | EXT4_SB(sb)->s_journal->j_inode ? "internal" : | ||
| 1652 | "external", EXT4_SB(sb)->s_journal->j_devname); | ||
| 1653 | } else { | ||
| 1654 | ext4_msg(sb, KERN_INFO, "no journal"); | ||
| 1655 | } | ||
| 1656 | return res; | 1661 | return res; |
| 1657 | } | 1662 | } |
| 1658 | 1663 | ||
| @@ -2197,6 +2202,7 @@ EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan); | |||
| 2197 | EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); | 2202 | EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs); |
| 2198 | EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); | 2203 | EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request); |
| 2199 | EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); | 2204 | EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc); |
| 2205 | EXT4_RW_ATTR_SBI_UI(max_writeback_mb_bump, s_max_writeback_mb_bump); | ||
| 2200 | 2206 | ||
| 2201 | static struct attribute *ext4_attrs[] = { | 2207 | static struct attribute *ext4_attrs[] = { |
| 2202 | ATTR_LIST(delayed_allocation_blocks), | 2208 | ATTR_LIST(delayed_allocation_blocks), |
| @@ -2210,6 +2216,7 @@ static struct attribute *ext4_attrs[] = { | |||
| 2210 | ATTR_LIST(mb_order2_req), | 2216 | ATTR_LIST(mb_order2_req), |
| 2211 | ATTR_LIST(mb_stream_req), | 2217 | ATTR_LIST(mb_stream_req), |
| 2212 | ATTR_LIST(mb_group_prealloc), | 2218 | ATTR_LIST(mb_group_prealloc), |
| 2219 | ATTR_LIST(max_writeback_mb_bump), | ||
| 2213 | NULL, | 2220 | NULL, |
| 2214 | }; | 2221 | }; |
| 2215 | 2222 | ||
| @@ -2413,7 +2420,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2413 | sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ; | 2420 | sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ; |
| 2414 | sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME; | 2421 | sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME; |
| 2415 | sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME; | 2422 | sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME; |
| 2416 | sbi->s_mb_history_max = default_mb_history_length; | ||
| 2417 | 2423 | ||
| 2418 | set_opt(sbi->s_mount_opt, BARRIER); | 2424 | set_opt(sbi->s_mount_opt, BARRIER); |
| 2419 | 2425 | ||
| @@ -2679,6 +2685,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2679 | } | 2685 | } |
| 2680 | 2686 | ||
| 2681 | sbi->s_stripe = ext4_get_stripe_size(sbi); | 2687 | sbi->s_stripe = ext4_get_stripe_size(sbi); |
| 2688 | sbi->s_max_writeback_mb_bump = 128; | ||
| 2682 | 2689 | ||
| 2683 | /* | 2690 | /* |
| 2684 | * set up enough so that it can read an inode | 2691 | * set up enough so that it can read an inode |
| @@ -2798,6 +2805,12 @@ no_journal: | |||
| 2798 | clear_opt(sbi->s_mount_opt, NOBH); | 2805 | clear_opt(sbi->s_mount_opt, NOBH); |
| 2799 | } | 2806 | } |
| 2800 | } | 2807 | } |
| 2808 | EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten"); | ||
| 2809 | if (!EXT4_SB(sb)->dio_unwritten_wq) { | ||
| 2810 | printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); | ||
| 2811 | goto failed_mount_wq; | ||
| 2812 | } | ||
| 2813 | |||
| 2801 | /* | 2814 | /* |
| 2802 | * The jbd2_journal_load will have done any necessary log recovery, | 2815 | * The jbd2_journal_load will have done any necessary log recovery, |
| 2803 | * so we can safely mount the rest of the filesystem now. | 2816 | * so we can safely mount the rest of the filesystem now. |
| @@ -2849,12 +2862,12 @@ no_journal: | |||
| 2849 | "available"); | 2862 | "available"); |
| 2850 | } | 2863 | } |
| 2851 | 2864 | ||
| 2852 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) { | 2865 | if (test_opt(sb, DELALLOC) && |
| 2866 | (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) { | ||
| 2853 | ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - " | 2867 | ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - " |
| 2854 | "requested data journaling mode"); | 2868 | "requested data journaling mode"); |
| 2855 | clear_opt(sbi->s_mount_opt, DELALLOC); | 2869 | clear_opt(sbi->s_mount_opt, DELALLOC); |
| 2856 | } else if (test_opt(sb, DELALLOC)) | 2870 | } |
| 2857 | ext4_msg(sb, KERN_INFO, "delayed allocation enabled"); | ||
| 2858 | 2871 | ||
| 2859 | err = ext4_setup_system_zone(sb); | 2872 | err = ext4_setup_system_zone(sb); |
| 2860 | if (err) { | 2873 | if (err) { |
| @@ -2910,6 +2923,8 @@ cantfind_ext4: | |||
| 2910 | 2923 | ||
| 2911 | failed_mount4: | 2924 | failed_mount4: |
| 2912 | ext4_msg(sb, KERN_ERR, "mount failed"); | 2925 | ext4_msg(sb, KERN_ERR, "mount failed"); |
| 2926 | destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq); | ||
| 2927 | failed_mount_wq: | ||
| 2913 | ext4_release_system_zone(sb); | 2928 | ext4_release_system_zone(sb); |
| 2914 | if (sbi->s_journal) { | 2929 | if (sbi->s_journal) { |
| 2915 | jbd2_journal_destroy(sbi->s_journal); | 2930 | jbd2_journal_destroy(sbi->s_journal); |
| @@ -3164,9 +3179,7 @@ static int ext4_load_journal(struct super_block *sb, | |||
| 3164 | return -EINVAL; | 3179 | return -EINVAL; |
| 3165 | } | 3180 | } |
| 3166 | 3181 | ||
| 3167 | if (journal->j_flags & JBD2_BARRIER) | 3182 | if (!(journal->j_flags & JBD2_BARRIER)) |
| 3168 | ext4_msg(sb, KERN_INFO, "barriers enabled"); | ||
| 3169 | else | ||
| 3170 | ext4_msg(sb, KERN_INFO, "barriers disabled"); | 3183 | ext4_msg(sb, KERN_INFO, "barriers disabled"); |
| 3171 | 3184 | ||
| 3172 | if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { | 3185 | if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) { |
| @@ -3361,11 +3374,13 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
| 3361 | { | 3374 | { |
| 3362 | int ret = 0; | 3375 | int ret = 0; |
| 3363 | tid_t target; | 3376 | tid_t target; |
| 3377 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
| 3364 | 3378 | ||
| 3365 | trace_ext4_sync_fs(sb, wait); | 3379 | trace_ext4_sync_fs(sb, wait); |
| 3366 | if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { | 3380 | flush_workqueue(sbi->dio_unwritten_wq); |
| 3381 | if (jbd2_journal_start_commit(sbi->s_journal, &target)) { | ||
| 3367 | if (wait) | 3382 | if (wait) |
| 3368 | jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target); | 3383 | jbd2_log_wait_commit(sbi->s_journal, target); |
| 3369 | } | 3384 | } |
| 3370 | return ret; | 3385 | return ret; |
| 3371 | } | 3386 | } |
