diff options
Diffstat (limited to 'fs/gfs2/glops.c')
-rw-r--r-- | fs/gfs2/glops.c | 138 |
1 files changed, 35 insertions, 103 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 41a6b6818a50..b068d10bcb6e 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -92,7 +92,7 @@ static void gfs2_pte_inval(struct gfs2_glock *gl) | |||
92 | 92 | ||
93 | ip = gl->gl_object; | 93 | ip = gl->gl_object; |
94 | inode = &ip->i_inode; | 94 | inode = &ip->i_inode; |
95 | if (!ip || !S_ISREG(ip->i_di.di_mode)) | 95 | if (!ip || !S_ISREG(inode->i_mode)) |
96 | return; | 96 | return; |
97 | 97 | ||
98 | if (!test_bit(GIF_PAGED, &ip->i_flags)) | 98 | if (!test_bit(GIF_PAGED, &ip->i_flags)) |
@@ -107,89 +107,20 @@ static void gfs2_pte_inval(struct gfs2_glock *gl) | |||
107 | } | 107 | } |
108 | 108 | ||
109 | /** | 109 | /** |
110 | * gfs2_page_inval - Invalidate all pages associated with a glock | ||
111 | * @gl: the glock | ||
112 | * | ||
113 | */ | ||
114 | |||
115 | static void gfs2_page_inval(struct gfs2_glock *gl) | ||
116 | { | ||
117 | struct gfs2_inode *ip; | ||
118 | struct inode *inode; | ||
119 | |||
120 | ip = gl->gl_object; | ||
121 | inode = &ip->i_inode; | ||
122 | if (!ip || !S_ISREG(ip->i_di.di_mode)) | ||
123 | return; | ||
124 | |||
125 | truncate_inode_pages(inode->i_mapping, 0); | ||
126 | gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !inode->i_mapping->nrpages); | ||
127 | clear_bit(GIF_PAGED, &ip->i_flags); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * gfs2_page_wait - Wait for writeback of data | ||
132 | * @gl: the glock | ||
133 | * | ||
134 | * Syncs data (not metadata) for a regular file. | ||
135 | * No-op for all other types. | ||
136 | */ | ||
137 | |||
138 | static void gfs2_page_wait(struct gfs2_glock *gl) | ||
139 | { | ||
140 | struct gfs2_inode *ip = gl->gl_object; | ||
141 | struct inode *inode = &ip->i_inode; | ||
142 | struct address_space *mapping = inode->i_mapping; | ||
143 | int error; | ||
144 | |||
145 | if (!S_ISREG(ip->i_di.di_mode)) | ||
146 | return; | ||
147 | |||
148 | error = filemap_fdatawait(mapping); | ||
149 | |||
150 | /* Put back any errors cleared by filemap_fdatawait() | ||
151 | so they can be caught by someone who can pass them | ||
152 | up to user space. */ | ||
153 | |||
154 | if (error == -ENOSPC) | ||
155 | set_bit(AS_ENOSPC, &mapping->flags); | ||
156 | else if (error) | ||
157 | set_bit(AS_EIO, &mapping->flags); | ||
158 | |||
159 | } | ||
160 | |||
161 | static void gfs2_page_writeback(struct gfs2_glock *gl) | ||
162 | { | ||
163 | struct gfs2_inode *ip = gl->gl_object; | ||
164 | struct inode *inode = &ip->i_inode; | ||
165 | struct address_space *mapping = inode->i_mapping; | ||
166 | |||
167 | if (!S_ISREG(ip->i_di.di_mode)) | ||
168 | return; | ||
169 | |||
170 | filemap_fdatawrite(mapping); | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * meta_go_sync - sync out the metadata for this glock | 110 | * meta_go_sync - sync out the metadata for this glock |
175 | * @gl: the glock | 111 | * @gl: the glock |
176 | * @flags: DIO_* | ||
177 | * | 112 | * |
178 | * Called when demoting or unlocking an EX glock. We must flush | 113 | * Called when demoting or unlocking an EX glock. We must flush |
179 | * to disk all dirty buffers/pages relating to this glock, and must not | 114 | * to disk all dirty buffers/pages relating to this glock, and must not |
180 | * not return to caller to demote/unlock the glock until I/O is complete. | 115 | * not return to caller to demote/unlock the glock until I/O is complete. |
181 | */ | 116 | */ |
182 | 117 | ||
183 | static void meta_go_sync(struct gfs2_glock *gl, int flags) | 118 | static void meta_go_sync(struct gfs2_glock *gl) |
184 | { | 119 | { |
185 | if (!(flags & DIO_METADATA)) | ||
186 | return; | ||
187 | |||
188 | if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) { | 120 | if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) { |
189 | gfs2_log_flush(gl->gl_sbd, gl); | 121 | gfs2_log_flush(gl->gl_sbd, gl); |
190 | gfs2_meta_sync(gl); | 122 | gfs2_meta_sync(gl); |
191 | if (flags & DIO_RELEASE) | 123 | gfs2_ail_empty_gl(gl); |
192 | gfs2_ail_empty_gl(gl); | ||
193 | } | 124 | } |
194 | 125 | ||
195 | } | 126 | } |
@@ -264,31 +195,31 @@ static void inode_go_drop_th(struct gfs2_glock *gl) | |||
264 | /** | 195 | /** |
265 | * inode_go_sync - Sync the dirty data and/or metadata for an inode glock | 196 | * inode_go_sync - Sync the dirty data and/or metadata for an inode glock |
266 | * @gl: the glock protecting the inode | 197 | * @gl: the glock protecting the inode |
267 | * @flags: | ||
268 | * | 198 | * |
269 | */ | 199 | */ |
270 | 200 | ||
271 | static void inode_go_sync(struct gfs2_glock *gl, int flags) | 201 | static void inode_go_sync(struct gfs2_glock *gl) |
272 | { | 202 | { |
273 | int meta = (flags & DIO_METADATA); | 203 | struct gfs2_inode *ip = gl->gl_object; |
274 | int data = (flags & DIO_DATA); | 204 | |
205 | if (ip && !S_ISREG(ip->i_inode.i_mode)) | ||
206 | ip = NULL; | ||
275 | 207 | ||
276 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { | 208 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) { |
277 | if (meta && data) { | 209 | gfs2_log_flush(gl->gl_sbd, gl); |
278 | gfs2_page_writeback(gl); | 210 | if (ip) |
279 | gfs2_log_flush(gl->gl_sbd, gl); | 211 | filemap_fdatawrite(ip->i_inode.i_mapping); |
280 | gfs2_meta_sync(gl); | 212 | gfs2_meta_sync(gl); |
281 | gfs2_page_wait(gl); | 213 | if (ip) { |
282 | clear_bit(GLF_DIRTY, &gl->gl_flags); | 214 | struct address_space *mapping = ip->i_inode.i_mapping; |
283 | } else if (meta) { | 215 | int error = filemap_fdatawait(mapping); |
284 | gfs2_log_flush(gl->gl_sbd, gl); | 216 | if (error == -ENOSPC) |
285 | gfs2_meta_sync(gl); | 217 | set_bit(AS_ENOSPC, &mapping->flags); |
286 | } else if (data) { | 218 | else if (error) |
287 | gfs2_page_writeback(gl); | 219 | set_bit(AS_EIO, &mapping->flags); |
288 | gfs2_page_wait(gl); | ||
289 | } | 220 | } |
290 | if (flags & DIO_RELEASE) | 221 | clear_bit(GLF_DIRTY, &gl->gl_flags); |
291 | gfs2_ail_empty_gl(gl); | 222 | gfs2_ail_empty_gl(gl); |
292 | } | 223 | } |
293 | } | 224 | } |
294 | 225 | ||
@@ -301,15 +232,20 @@ static void inode_go_sync(struct gfs2_glock *gl, int flags) | |||
301 | 232 | ||
302 | static void inode_go_inval(struct gfs2_glock *gl, int flags) | 233 | static void inode_go_inval(struct gfs2_glock *gl, int flags) |
303 | { | 234 | { |
235 | struct gfs2_inode *ip = gl->gl_object; | ||
304 | int meta = (flags & DIO_METADATA); | 236 | int meta = (flags & DIO_METADATA); |
305 | int data = (flags & DIO_DATA); | ||
306 | 237 | ||
307 | if (meta) { | 238 | if (meta) { |
308 | gfs2_meta_inval(gl); | 239 | gfs2_meta_inval(gl); |
309 | gl->gl_vn++; | 240 | if (ip) |
241 | set_bit(GIF_INVALID, &ip->i_flags); | ||
242 | } | ||
243 | |||
244 | if (ip && S_ISREG(ip->i_inode.i_mode)) { | ||
245 | truncate_inode_pages(ip->i_inode.i_mapping, 0); | ||
246 | gfs2_assert_withdraw(GFS2_SB(&ip->i_inode), !ip->i_inode.i_mapping->nrpages); | ||
247 | clear_bit(GIF_PAGED, &ip->i_flags); | ||
310 | } | 248 | } |
311 | if (data) | ||
312 | gfs2_page_inval(gl); | ||
313 | } | 249 | } |
314 | 250 | ||
315 | /** | 251 | /** |
@@ -351,11 +287,10 @@ static int inode_go_lock(struct gfs2_holder *gh) | |||
351 | if (!ip) | 287 | if (!ip) |
352 | return 0; | 288 | return 0; |
353 | 289 | ||
354 | if (ip->i_vn != gl->gl_vn) { | 290 | if (test_bit(GIF_INVALID, &ip->i_flags)) { |
355 | error = gfs2_inode_refresh(ip); | 291 | error = gfs2_inode_refresh(ip); |
356 | if (error) | 292 | if (error) |
357 | return error; | 293 | return error; |
358 | gfs2_inode_attr_in(ip); | ||
359 | } | 294 | } |
360 | 295 | ||
361 | if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) && | 296 | if ((ip->i_di.di_flags & GFS2_DIF_TRUNC_IN_PROG) && |
@@ -379,11 +314,8 @@ static void inode_go_unlock(struct gfs2_holder *gh) | |||
379 | struct gfs2_glock *gl = gh->gh_gl; | 314 | struct gfs2_glock *gl = gh->gh_gl; |
380 | struct gfs2_inode *ip = gl->gl_object; | 315 | struct gfs2_inode *ip = gl->gl_object; |
381 | 316 | ||
382 | if (ip == NULL) | 317 | if (ip) |
383 | return; | 318 | gfs2_meta_cache_flush(ip); |
384 | if (test_bit(GLF_DIRTY, &gl->gl_flags)) | ||
385 | gfs2_inode_attr_in(ip); | ||
386 | gfs2_meta_cache_flush(ip); | ||
387 | } | 319 | } |
388 | 320 | ||
389 | /** | 321 | /** |
@@ -491,13 +423,13 @@ static void trans_go_xmote_bh(struct gfs2_glock *gl) | |||
491 | struct gfs2_sbd *sdp = gl->gl_sbd; | 423 | struct gfs2_sbd *sdp = gl->gl_sbd; |
492 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); | 424 | struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); |
493 | struct gfs2_glock *j_gl = ip->i_gl; | 425 | struct gfs2_glock *j_gl = ip->i_gl; |
494 | struct gfs2_log_header head; | 426 | struct gfs2_log_header_host head; |
495 | int error; | 427 | int error; |
496 | 428 | ||
497 | if (gl->gl_state != LM_ST_UNLOCKED && | 429 | if (gl->gl_state != LM_ST_UNLOCKED && |
498 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { | 430 | test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) { |
499 | gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode)); | 431 | gfs2_meta_cache_flush(GFS2_I(sdp->sd_jdesc->jd_inode)); |
500 | j_gl->gl_ops->go_inval(j_gl, DIO_METADATA | DIO_DATA); | 432 | j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); |
501 | 433 | ||
502 | error = gfs2_find_jhead(sdp->sd_jdesc, &head); | 434 | error = gfs2_find_jhead(sdp->sd_jdesc, &head); |
503 | if (error) | 435 | if (error) |