aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/ext4.txt6
-rw-r--r--fs/ext4/ext4.h1
-rw-r--r--fs/ext4/mballoc.c21
-rw-r--r--fs/ext4/super.c14
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
356discard Controls whether ext4 should issue discard/TRIM
357nodiscard(*) 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
356Data Mode 362Data Mode
357========= 363=========
358There are 3 different data modes: 364There 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
1085static const match_table_t tokens = { 1089static 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\" "