diff options
-rw-r--r-- | Documentation/filesystems/ext4.txt | 6 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
-rw-r--r-- | fs/ext4/mballoc.c | 21 | ||||
-rw-r--r-- | fs/ext4/super.c | 14 |
4 files changed, 33 insertions, 9 deletions
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 6d94e0696f8c..26904ff6d61b 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt | |||
@@ -353,6 +353,12 @@ noauto_da_alloc replacing existing files via patterns such as | |||
353 | system crashes before the delayed allocation | 353 | system crashes before the delayed allocation |
354 | blocks are forced to disk. | 354 | blocks are forced to disk. |
355 | 355 | ||
356 | discard Controls whether ext4 should issue discard/TRIM | ||
357 | nodiscard(*) commands to the underlying block device when | ||
358 | blocks are freed. This is useful for SSD devices | ||
359 | and sparse/thinly-provisioned LUNs, but it is off | ||
360 | by default until sufficient testing has been done. | ||
361 | |||
356 | Data Mode | 362 | Data Mode |
357 | ========= | 363 | ========= |
358 | There are 3 different data modes: | 364 | There are 3 different data modes: |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 8825515eeddd..05ce38b981cb 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -750,6 +750,7 @@ struct ext4_inode_info { | |||
750 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ | 750 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ |
751 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ | 751 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ |
752 | #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ | 752 | #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ |
753 | #define EXT4_MOUNT_DISCARD 0x40000000 /* Issue DISCARD requests */ | ||
753 | 754 | ||
754 | #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt | 755 | #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt |
755 | #define set_opt(o, opt) o |= EXT4_MOUNT_##opt | 756 | #define set_opt(o, opt) o |= EXT4_MOUNT_##opt |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index bba12824defa..6e5a23a2cc25 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2529,7 +2529,6 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
2529 | struct ext4_group_info *db; | 2529 | struct ext4_group_info *db; |
2530 | int err, count = 0, count2 = 0; | 2530 | int err, count = 0, count2 = 0; |
2531 | struct ext4_free_data *entry; | 2531 | struct ext4_free_data *entry; |
2532 | ext4_fsblk_t discard_block; | ||
2533 | struct list_head *l, *ltmp; | 2532 | struct list_head *l, *ltmp; |
2534 | 2533 | ||
2535 | list_for_each_safe(l, ltmp, &txn->t_private_list) { | 2534 | list_for_each_safe(l, ltmp, &txn->t_private_list) { |
@@ -2559,13 +2558,19 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
2559 | page_cache_release(e4b.bd_bitmap_page); | 2558 | page_cache_release(e4b.bd_bitmap_page); |
2560 | } | 2559 | } |
2561 | ext4_unlock_group(sb, entry->group); | 2560 | ext4_unlock_group(sb, entry->group); |
2562 | discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb) | 2561 | if (test_opt(sb, DISCARD)) { |
2563 | + entry->start_blk | 2562 | ext4_fsblk_t discard_block; |
2564 | + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); | 2563 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
2565 | trace_ext4_discard_blocks(sb, (unsigned long long)discard_block, | 2564 | |
2566 | entry->count); | 2565 | discard_block = (ext4_fsblk_t)entry->group * |
2567 | sb_issue_discard(sb, discard_block, entry->count); | 2566 | EXT4_BLOCKS_PER_GROUP(sb) |
2568 | 2567 | + entry->start_blk | |
2568 | + le32_to_cpu(es->s_first_data_block); | ||
2569 | trace_ext4_discard_blocks(sb, | ||
2570 | (unsigned long long)discard_block, | ||
2571 | entry->count); | ||
2572 | sb_issue_discard(sb, discard_block, entry->count); | ||
2573 | } | ||
2569 | kmem_cache_free(ext4_free_ext_cachep, entry); | 2574 | kmem_cache_free(ext4_free_ext_cachep, entry); |
2570 | ext4_mb_release_desc(&e4b); | 2575 | ext4_mb_release_desc(&e4b); |
2571 | } | 2576 | } |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f2d5ec77c1e9..2b382f6f80c1 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -899,6 +899,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
899 | if (test_opt(sb, NO_AUTO_DA_ALLOC)) | 899 | if (test_opt(sb, NO_AUTO_DA_ALLOC)) |
900 | seq_puts(seq, ",noauto_da_alloc"); | 900 | seq_puts(seq, ",noauto_da_alloc"); |
901 | 901 | ||
902 | if (test_opt(sb, DISCARD)) | ||
903 | seq_puts(seq, ",discard"); | ||
904 | |||
902 | ext4_show_quota_options(seq, sb); | 905 | ext4_show_quota_options(seq, sb); |
903 | 906 | ||
904 | return 0; | 907 | return 0; |
@@ -1079,7 +1082,8 @@ enum { | |||
1079 | Opt_usrquota, Opt_grpquota, Opt_i_version, | 1082 | Opt_usrquota, Opt_grpquota, Opt_i_version, |
1080 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, | 1083 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, |
1081 | Opt_block_validity, Opt_noblock_validity, | 1084 | Opt_block_validity, Opt_noblock_validity, |
1082 | Opt_inode_readahead_blks, Opt_journal_ioprio | 1085 | Opt_inode_readahead_blks, Opt_journal_ioprio, |
1086 | Opt_discard, Opt_nodiscard, | ||
1083 | }; | 1087 | }; |
1084 | 1088 | ||
1085 | static const match_table_t tokens = { | 1089 | static const match_table_t tokens = { |
@@ -1144,6 +1148,8 @@ static const match_table_t tokens = { | |||
1144 | {Opt_auto_da_alloc, "auto_da_alloc=%u"}, | 1148 | {Opt_auto_da_alloc, "auto_da_alloc=%u"}, |
1145 | {Opt_auto_da_alloc, "auto_da_alloc"}, | 1149 | {Opt_auto_da_alloc, "auto_da_alloc"}, |
1146 | {Opt_noauto_da_alloc, "noauto_da_alloc"}, | 1150 | {Opt_noauto_da_alloc, "noauto_da_alloc"}, |
1151 | {Opt_discard, "discard"}, | ||
1152 | {Opt_nodiscard, "nodiscard"}, | ||
1147 | {Opt_err, NULL}, | 1153 | {Opt_err, NULL}, |
1148 | }; | 1154 | }; |
1149 | 1155 | ||
@@ -1565,6 +1571,12 @@ set_qf_format: | |||
1565 | else | 1571 | else |
1566 | set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); | 1572 | set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); |
1567 | break; | 1573 | break; |
1574 | case Opt_discard: | ||
1575 | set_opt(sbi->s_mount_opt, DISCARD); | ||
1576 | break; | ||
1577 | case Opt_nodiscard: | ||
1578 | clear_opt(sbi->s_mount_opt, DISCARD); | ||
1579 | break; | ||
1568 | default: | 1580 | default: |
1569 | ext4_msg(sb, KERN_ERR, | 1581 | ext4_msg(sb, KERN_ERR, |
1570 | "Unrecognized mount option \"%s\" " | 1582 | "Unrecognized mount option \"%s\" " |