diff options
Diffstat (limited to 'fs/gfs2/meta_io.c')
-rw-r--r-- | fs/gfs2/meta_io.c | 105 |
1 files changed, 84 insertions, 21 deletions
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 8d6f13256b26..cb8d7a93d5ec 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -31,19 +31,66 @@ | |||
31 | #include "rgrp.h" | 31 | #include "rgrp.h" |
32 | #include "trans.h" | 32 | #include "trans.h" |
33 | #include "util.h" | 33 | #include "util.h" |
34 | #include "ops_address.h" | ||
35 | 34 | ||
36 | static int aspace_get_block(struct inode *inode, sector_t lblock, | 35 | static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc) |
37 | struct buffer_head *bh_result, int create) | ||
38 | { | 36 | { |
39 | gfs2_assert_warn(inode->i_sb->s_fs_info, 0); | 37 | int err; |
40 | return -EOPNOTSUPP; | 38 | struct buffer_head *bh, *head; |
41 | } | 39 | int nr_underway = 0; |
40 | int write_op = (1 << BIO_RW_META) | ((wbc->sync_mode == WB_SYNC_ALL ? | ||
41 | WRITE_SYNC_PLUG : WRITE)); | ||
42 | |||
43 | BUG_ON(!PageLocked(page)); | ||
44 | BUG_ON(!page_has_buffers(page)); | ||
45 | |||
46 | head = page_buffers(page); | ||
47 | bh = head; | ||
48 | |||
49 | do { | ||
50 | if (!buffer_mapped(bh)) | ||
51 | continue; | ||
52 | /* | ||
53 | * If it's a fully non-blocking write attempt and we cannot | ||
54 | * lock the buffer then redirty the page. Note that this can | ||
55 | * potentially cause a busy-wait loop from pdflush and kswapd | ||
56 | * activity, but those code paths have their own higher-level | ||
57 | * throttling. | ||
58 | */ | ||
59 | if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) { | ||
60 | lock_buffer(bh); | ||
61 | } else if (!trylock_buffer(bh)) { | ||
62 | redirty_page_for_writepage(wbc, page); | ||
63 | continue; | ||
64 | } | ||
65 | if (test_clear_buffer_dirty(bh)) { | ||
66 | mark_buffer_async_write(bh); | ||
67 | } else { | ||
68 | unlock_buffer(bh); | ||
69 | } | ||
70 | } while ((bh = bh->b_this_page) != head); | ||
71 | |||
72 | /* | ||
73 | * The page and its buffers are protected by PageWriteback(), so we can | ||
74 | * drop the bh refcounts early. | ||
75 | */ | ||
76 | BUG_ON(PageWriteback(page)); | ||
77 | set_page_writeback(page); | ||
78 | |||
79 | do { | ||
80 | struct buffer_head *next = bh->b_this_page; | ||
81 | if (buffer_async_write(bh)) { | ||
82 | submit_bh(write_op, bh); | ||
83 | nr_underway++; | ||
84 | } | ||
85 | bh = next; | ||
86 | } while (bh != head); | ||
87 | unlock_page(page); | ||
42 | 88 | ||
43 | static int gfs2_aspace_writepage(struct page *page, | 89 | err = 0; |
44 | struct writeback_control *wbc) | 90 | if (nr_underway == 0) |
45 | { | 91 | end_page_writeback(page); |
46 | return block_write_full_page(page, aspace_get_block, wbc); | 92 | |
93 | return err; | ||
47 | } | 94 | } |
48 | 95 | ||
49 | static const struct address_space_operations aspace_aops = { | 96 | static const struct address_space_operations aspace_aops = { |
@@ -201,16 +248,32 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno) | |||
201 | int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, | 248 | int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, |
202 | struct buffer_head **bhp) | 249 | struct buffer_head **bhp) |
203 | { | 250 | { |
204 | *bhp = gfs2_getbuf(gl, blkno, CREATE); | 251 | struct gfs2_sbd *sdp = gl->gl_sbd; |
205 | if (!buffer_uptodate(*bhp)) { | 252 | struct buffer_head *bh; |
206 | ll_rw_block(READ_META, 1, bhp); | 253 | |
207 | if (flags & DIO_WAIT) { | 254 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
208 | int error = gfs2_meta_wait(gl->gl_sbd, *bhp); | 255 | return -EIO; |
209 | if (error) { | 256 | |
210 | brelse(*bhp); | 257 | *bhp = bh = gfs2_getbuf(gl, blkno, CREATE); |
211 | return error; | 258 | |
212 | } | 259 | lock_buffer(bh); |
213 | } | 260 | if (buffer_uptodate(bh)) { |
261 | unlock_buffer(bh); | ||
262 | return 0; | ||
263 | } | ||
264 | bh->b_end_io = end_buffer_read_sync; | ||
265 | get_bh(bh); | ||
266 | submit_bh(READ_SYNC | (1 << BIO_RW_META), bh); | ||
267 | if (!(flags & DIO_WAIT)) | ||
268 | return 0; | ||
269 | |||
270 | wait_on_buffer(bh); | ||
271 | if (unlikely(!buffer_uptodate(bh))) { | ||
272 | struct gfs2_trans *tr = current->journal_info; | ||
273 | if (tr && tr->tr_touched) | ||
274 | gfs2_io_error_bh(sdp, bh); | ||
275 | brelse(bh); | ||
276 | return -EIO; | ||
214 | } | 277 | } |
215 | 278 | ||
216 | return 0; | 279 | return 0; |
@@ -404,7 +467,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) | |||
404 | if (buffer_uptodate(first_bh)) | 467 | if (buffer_uptodate(first_bh)) |
405 | goto out; | 468 | goto out; |
406 | if (!buffer_locked(first_bh)) | 469 | if (!buffer_locked(first_bh)) |
407 | ll_rw_block(READ_META, 1, &first_bh); | 470 | ll_rw_block(READ_SYNC | (1 << BIO_RW_META), 1, &first_bh); |
408 | 471 | ||
409 | dblock++; | 472 | dblock++; |
410 | extlen--; | 473 | extlen--; |