]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From e7432675f8ca868a4af365759a8d4c3779a3d922 Mon Sep 17 00:00:00 2001 |
2 | From: Sunil Mushran <sunil.mushran@oracle.com> | |
3 | Date: Thu, 6 Aug 2009 16:12:58 -0700 | |
4 | Subject: ocfs2: Initialize the cluster we're writing to in a non-sparse extend | |
5 | References: bnc#501563 | |
6 | ||
7 | In a non-sparse extend, we correctly allocate (and zero) the clusters between | |
8 | the old_i_size and pos, but we don't zero the portions of the cluster we're | |
9 | writing to outside of pos<->len. | |
10 | ||
11 | It handles clustersize > pagesize and blocksize < pagesize. | |
12 | ||
13 | [Cleaned up by Joel Becker.] | |
14 | ||
15 | Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com> | |
16 | Signed-off-by: Joel Becker <joel.becker@oracle.com> | |
17 | Signed-off-by: Mark Fasheh <mfasheh@suse.com> | |
18 | --- | |
19 | fs/ocfs2/aops.c | 66 +++++++++++++++++++++++++++++++++++++++--------------- | |
20 | 1 files changed, 47 insertions(+), 19 deletions(-) | |
21 | ||
22 | Index: linux-2.6.27-ocfs2-update-sle11/fs/ocfs2/aops.c | |
23 | =================================================================== | |
24 | --- linux-2.6.27-ocfs2-update-sle11.orig/fs/ocfs2/aops.c | |
25 | +++ linux-2.6.27-ocfs2-update-sle11/fs/ocfs2/aops.c | |
26 | @@ -909,18 +909,17 @@ struct ocfs2_write_cluster_desc { | |
27 | */ | |
28 | unsigned c_new; | |
29 | unsigned c_unwritten; | |
30 | + unsigned c_needs_zero; | |
31 | }; | |
32 | ||
33 | -static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d) | |
34 | -{ | |
35 | - return d->c_new || d->c_unwritten; | |
36 | -} | |
37 | - | |
38 | struct ocfs2_write_ctxt { | |
39 | /* Logical cluster position / len of write */ | |
40 | u32 w_cpos; | |
41 | u32 w_clen; | |
42 | ||
43 | + /* First cluster allocated in a nonsparse extend */ | |
44 | + u32 w_first_new_cpos; | |
45 | + | |
46 | struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE]; | |
47 | ||
48 | /* | |
49 | @@ -998,6 +997,7 @@ static int ocfs2_alloc_write_ctxt(struct | |
50 | return -ENOMEM; | |
51 | ||
52 | wc->w_cpos = pos >> osb->s_clustersize_bits; | |
53 | + wc->w_first_new_cpos = UINT_MAX; | |
54 | cend = (pos + len - 1) >> osb->s_clustersize_bits; | |
55 | wc->w_clen = cend - wc->w_cpos + 1; | |
56 | get_bh(di_bh); | |
57 | @@ -1239,20 +1239,18 @@ out: | |
58 | */ | |
59 | static int ocfs2_write_cluster(struct address_space *mapping, | |
60 | u32 phys, unsigned int unwritten, | |
61 | + unsigned int should_zero, | |
62 | struct ocfs2_alloc_context *data_ac, | |
63 | struct ocfs2_alloc_context *meta_ac, | |
64 | struct ocfs2_write_ctxt *wc, u32 cpos, | |
65 | loff_t user_pos, unsigned user_len) | |
66 | { | |
67 | - int ret, i, new, should_zero = 0; | |
68 | + int ret, i, new; | |
69 | u64 v_blkno, p_blkno; | |
70 | struct inode *inode = mapping->host; | |
71 | struct ocfs2_extent_tree et; | |
72 | ||
73 | new = phys == 0 ? 1 : 0; | |
74 | - if (new || unwritten) | |
75 | - should_zero = 1; | |
76 | - | |
77 | if (new) { | |
78 | u32 tmp_pos; | |
79 | ||
80 | @@ -1363,7 +1361,9 @@ static int ocfs2_write_cluster_by_desc(s | |
81 | local_len = osb->s_clustersize - cluster_off; | |
82 | ||
83 | ret = ocfs2_write_cluster(mapping, desc->c_phys, | |
84 | - desc->c_unwritten, data_ac, meta_ac, | |
85 | + desc->c_unwritten, | |
86 | + desc->c_needs_zero, | |
87 | + data_ac, meta_ac, | |
88 | wc, desc->c_cpos, pos, local_len); | |
89 | if (ret) { | |
90 | mlog_errno(ret); | |
91 | @@ -1413,14 +1413,14 @@ static void ocfs2_set_target_boundaries( | |
92 | * newly allocated cluster. | |
93 | */ | |
94 | desc = &wc->w_desc[0]; | |
95 | - if (ocfs2_should_zero_cluster(desc)) | |
96 | + if (desc->c_needs_zero) | |
97 | ocfs2_figure_cluster_boundaries(osb, | |
98 | desc->c_cpos, | |
99 | &wc->w_target_from, | |
100 | NULL); | |
101 | ||
102 | desc = &wc->w_desc[wc->w_clen - 1]; | |
103 | - if (ocfs2_should_zero_cluster(desc)) | |
104 | + if (desc->c_needs_zero) | |
105 | ocfs2_figure_cluster_boundaries(osb, | |
106 | desc->c_cpos, | |
107 | NULL, | |
108 | @@ -1488,13 +1488,28 @@ static int ocfs2_populate_write_desc(str | |
109 | phys++; | |
110 | } | |
111 | ||
112 | + /* | |
113 | + * If w_first_new_cpos is < UINT_MAX, we have a non-sparse | |
114 | + * file that got extended. w_first_new_cpos tells us | |
115 | + * where the newly allocated clusters are so we can | |
116 | + * zero them. | |
117 | + */ | |
118 | + if (desc->c_cpos >= wc->w_first_new_cpos) { | |
119 | + BUG_ON(phys == 0); | |
120 | + desc->c_needs_zero = 1; | |
121 | + } | |
122 | + | |
123 | desc->c_phys = phys; | |
124 | if (phys == 0) { | |
125 | desc->c_new = 1; | |
126 | + desc->c_needs_zero = 1; | |
127 | *clusters_to_alloc = *clusters_to_alloc + 1; | |
128 | } | |
129 | - if (ext_flags & OCFS2_EXT_UNWRITTEN) | |
130 | + | |
131 | + if (ext_flags & OCFS2_EXT_UNWRITTEN) { | |
132 | desc->c_unwritten = 1; | |
133 | + desc->c_needs_zero = 1; | |
134 | + } | |
135 | ||
136 | num_clusters--; | |
137 | } | |
138 | @@ -1654,10 +1669,13 @@ static int ocfs2_expand_nonsparse_inode( | |
139 | if (newsize <= i_size_read(inode)) | |
140 | return 0; | |
141 | ||
142 | - ret = ocfs2_extend_no_holes(inode, newsize, newsize - len); | |
143 | + ret = ocfs2_extend_no_holes(inode, newsize, pos); | |
144 | if (ret) | |
145 | mlog_errno(ret); | |
146 | ||
147 | + wc->w_first_new_cpos = | |
148 | + ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode)); | |
149 | + | |
150 | return ret; | |
151 | } | |
152 | ||
153 | @@ -1666,7 +1684,7 @@ int ocfs2_write_begin_nolock(struct addr | |
154 | struct page **pagep, void **fsdata, | |
155 | struct buffer_head *di_bh, struct page *mmap_page) | |
156 | { | |
157 | - int ret, credits = OCFS2_INODE_UPDATE_CREDITS; | |
158 | + int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; | |
159 | unsigned int clusters_to_alloc, extents_to_split; | |
160 | struct ocfs2_write_ctxt *wc; | |
161 | struct inode *inode = mapping->host; | |
162 | @@ -1744,8 +1762,19 @@ int ocfs2_write_begin_nolock(struct addr | |
163 | ||
164 | } | |
165 | ||
166 | - ocfs2_set_target_boundaries(osb, wc, pos, len, | |
167 | - clusters_to_alloc + extents_to_split); | |
168 | + /* | |
169 | + * We have to zero sparse allocated clusters, unwritten extent clusters, | |
170 | + * and non-sparse clusters we just extended. For non-sparse writes, | |
171 | + * we know zeros will only be needed in the first and/or last cluster. | |
172 | + */ | |
173 | + if (clusters_to_alloc || extents_to_split || | |
174 | + wc->w_desc[0].c_needs_zero || | |
175 | + wc->w_desc[wc->w_clen - 1].c_needs_zero) | |
176 | + cluster_of_pages = 1; | |
177 | + else | |
178 | + cluster_of_pages = 0; | |
179 | + | |
180 | + ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages); | |
181 | ||
182 | handle = ocfs2_start_trans(osb, credits); | |
183 | if (IS_ERR(handle)) { | |
184 | @@ -1778,8 +1807,7 @@ int ocfs2_write_begin_nolock(struct addr | |
185 | * extent. | |
186 | */ | |
187 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, | |
188 | - clusters_to_alloc + extents_to_split, | |
189 | - mmap_page); | |
190 | + cluster_of_pages, mmap_page); | |
191 | if (ret) { | |
192 | mlog_errno(ret); | |
193 | goto out_quota; |