]>
Commit | Line | Data |
---|---|---|
7f041dd7 GKH |
1 | From 1cc420c479f028e811b68b3e67a0695c26642223 Mon Sep 17 00:00:00 2001 |
2 | From: Eric Sandeen <sandeen@redhat.com> | |
3 | Date: Thu, 19 Nov 2009 14:25:42 -0500 | |
4 | Subject: [PATCH 71/85] ext4: make trim/discard optional (and off by default) | |
5 | ||
6 | (cherry picked from commit 5328e635315734d42080de9a5a1ee87bf4cae0a4) | |
7 | ||
8 | It is anticipated that when sb_issue_discard starts doing | |
9 | real work on trim-capable devices, we may see issues. Make | |
10 | this mount-time optional, and default it to off until we know | |
11 | that things are working out OK. | |
12 | ||
13 | Signed-off-by: Eric Sandeen <sandeen@redhat.com> | |
14 | Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> | |
15 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
16 | --- | |
17 | Documentation/filesystems/ext4.txt | 6 ++++++ | |
18 | fs/ext4/ext4.h | 1 + | |
19 | fs/ext4/mballoc.c | 21 +++++++++++++-------- | |
20 | fs/ext4/super.c | 14 +++++++++++++- | |
21 | 4 files changed, 33 insertions(+), 9 deletions(-) | |
22 | ||
23 | --- a/Documentation/filesystems/ext4.txt | |
24 | +++ b/Documentation/filesystems/ext4.txt | |
25 | @@ -338,6 +338,12 @@ noauto_da_alloc replacing existing file | |
26 | system crashes before the delayed allocation | |
27 | blocks are forced to disk. | |
28 | ||
29 | +discard Controls whether ext4 should issue discard/TRIM | |
30 | +nodiscard(*) commands to the underlying block device when | |
31 | + blocks are freed. This is useful for SSD devices | |
32 | + and sparse/thinly-provisioned LUNs, but it is off | |
33 | + by default until sufficient testing has been done. | |
34 | + | |
35 | Data Mode | |
36 | ========= | |
37 | There are 3 different data modes: | |
38 | --- a/fs/ext4/ext4.h | |
39 | +++ b/fs/ext4/ext4.h | |
40 | @@ -747,6 +747,7 @@ struct ext4_inode_info { | |
41 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ | |
42 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ | |
43 | #define EXT4_MOUNT_BLOCK_VALIDITY 0x20000000 /* Block validity checking */ | |
44 | +#define EXT4_MOUNT_DISCARD 0x40000000 /* Issue DISCARD requests */ | |
45 | ||
46 | #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt | |
47 | #define set_opt(o, opt) o |= EXT4_MOUNT_##opt | |
48 | --- a/fs/ext4/mballoc.c | |
49 | +++ b/fs/ext4/mballoc.c | |
50 | @@ -2810,7 +2810,6 @@ static void release_blocks_on_commit(jou | |
51 | struct ext4_group_info *db; | |
52 | int err, count = 0, count2 = 0; | |
53 | struct ext4_free_data *entry; | |
54 | - ext4_fsblk_t discard_block; | |
55 | struct list_head *l, *ltmp; | |
56 | ||
57 | list_for_each_safe(l, ltmp, &txn->t_private_list) { | |
58 | @@ -2840,13 +2839,19 @@ static void release_blocks_on_commit(jou | |
59 | page_cache_release(e4b.bd_bitmap_page); | |
60 | } | |
61 | ext4_unlock_group(sb, entry->group); | |
62 | - discard_block = (ext4_fsblk_t) entry->group * EXT4_BLOCKS_PER_GROUP(sb) | |
63 | - + entry->start_blk | |
64 | - + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); | |
65 | - trace_ext4_discard_blocks(sb, (unsigned long long)discard_block, | |
66 | - entry->count); | |
67 | - sb_issue_discard(sb, discard_block, entry->count); | |
68 | - | |
69 | + if (test_opt(sb, DISCARD)) { | |
70 | + ext4_fsblk_t discard_block; | |
71 | + struct ext4_super_block *es = EXT4_SB(sb)->s_es; | |
72 | + | |
73 | + discard_block = (ext4_fsblk_t)entry->group * | |
74 | + EXT4_BLOCKS_PER_GROUP(sb) | |
75 | + + entry->start_blk | |
76 | + + le32_to_cpu(es->s_first_data_block); | |
77 | + trace_ext4_discard_blocks(sb, | |
78 | + (unsigned long long)discard_block, | |
79 | + entry->count); | |
80 | + sb_issue_discard(sb, discard_block, entry->count); | |
81 | + } | |
82 | kmem_cache_free(ext4_free_ext_cachep, entry); | |
83 | ext4_mb_release_desc(&e4b); | |
84 | } | |
85 | --- a/fs/ext4/super.c | |
86 | +++ b/fs/ext4/super.c | |
87 | @@ -906,6 +906,9 @@ static int ext4_show_options(struct seq_ | |
88 | if (test_opt(sb, NO_AUTO_DA_ALLOC)) | |
89 | seq_puts(seq, ",noauto_da_alloc"); | |
90 | ||
91 | + if (test_opt(sb, DISCARD)) | |
92 | + seq_puts(seq, ",discard"); | |
93 | + | |
94 | ext4_show_quota_options(seq, sb); | |
95 | ||
96 | return 0; | |
97 | @@ -1086,7 +1089,8 @@ enum { | |
98 | Opt_usrquota, Opt_grpquota, Opt_i_version, | |
99 | Opt_stripe, Opt_delalloc, Opt_nodelalloc, | |
100 | Opt_block_validity, Opt_noblock_validity, | |
101 | - Opt_inode_readahead_blks, Opt_journal_ioprio | |
102 | + Opt_inode_readahead_blks, Opt_journal_ioprio, | |
103 | + Opt_discard, Opt_nodiscard, | |
104 | }; | |
105 | ||
106 | static const match_table_t tokens = { | |
107 | @@ -1152,6 +1156,8 @@ static const match_table_t tokens = { | |
108 | {Opt_auto_da_alloc, "auto_da_alloc=%u"}, | |
109 | {Opt_auto_da_alloc, "auto_da_alloc"}, | |
110 | {Opt_noauto_da_alloc, "noauto_da_alloc"}, | |
111 | + {Opt_discard, "discard"}, | |
112 | + {Opt_nodiscard, "nodiscard"}, | |
113 | {Opt_err, NULL}, | |
114 | }; | |
115 | ||
116 | @@ -1580,6 +1586,12 @@ set_qf_format: | |
117 | else | |
118 | set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); | |
119 | break; | |
120 | + case Opt_discard: | |
121 | + set_opt(sbi->s_mount_opt, DISCARD); | |
122 | + break; | |
123 | + case Opt_nodiscard: | |
124 | + clear_opt(sbi->s_mount_opt, DISCARD); | |
125 | + break; | |
126 | default: | |
127 | ext4_msg(sb, KERN_ERR, | |
128 | "Unrecognized mount option \"%s\" " |