diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2016-08-16 07:25:22 -0400 |
---|---|---|
committer | Bob Peterson <rpeterso@redhat.com> | 2016-08-18 12:36:41 -0400 |
commit | 23e5671a79be00b2f1c895aa93ff40fb75a4647e (patch) | |
tree | 46772f1b850c86f7b7a3914137e6c78548dbc9b3 | |
parent | 1c185c02f454c47d573a17e3e7d8befb06f0d64d (diff) |
gfs2: Fix extended attribute readahead optimization
Commit 39b0555f didn't check for a failing bio_add_page in
gfs2_submit_bhs. This could cause I/O requests to get lost, and the
affected buffer heads to stay locked forever. Fix that by submitting
the current bio and allocating another one when bio_add_page fails. (It
is guaranteed that we can at least add one page to a bio.)
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
-rw-r--r-- | fs/gfs2/meta_io.c | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 950b8be68e41..373639a59782 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -216,23 +216,26 @@ static void gfs2_meta_read_endio(struct bio *bio) | |||
216 | static void gfs2_submit_bhs(int op, int op_flags, struct buffer_head *bhs[], | 216 | static void gfs2_submit_bhs(int op, int op_flags, struct buffer_head *bhs[], |
217 | int num) | 217 | int num) |
218 | { | 218 | { |
219 | struct buffer_head *bh = bhs[0]; | 219 | while (num > 0) { |
220 | struct bio *bio; | 220 | struct buffer_head *bh = *bhs; |
221 | int i; | 221 | struct bio *bio; |
222 | 222 | ||
223 | if (!num) | 223 | bio = bio_alloc(GFP_NOIO, num); |
224 | return; | 224 | bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); |
225 | 225 | bio->bi_bdev = bh->b_bdev; | |
226 | bio = bio_alloc(GFP_NOIO, num); | 226 | while (num > 0) { |
227 | bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); | 227 | bh = *bhs; |
228 | bio->bi_bdev = bh->b_bdev; | 228 | if (!bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh))) { |
229 | for (i = 0; i < num; i++) { | 229 | BUG_ON(bio->bi_iter.bi_size == 0); |
230 | bh = bhs[i]; | 230 | break; |
231 | bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); | 231 | } |
232 | bhs++; | ||
233 | num--; | ||
234 | } | ||
235 | bio->bi_end_io = gfs2_meta_read_endio; | ||
236 | bio_set_op_attrs(bio, op, op_flags); | ||
237 | submit_bio(bio); | ||
232 | } | 238 | } |
233 | bio->bi_end_io = gfs2_meta_read_endio; | ||
234 | bio_set_op_attrs(bio, op, op_flags); | ||
235 | submit_bio(bio); | ||
236 | } | 239 | } |
237 | 240 | ||
238 | /** | 241 | /** |