Skip to content

Commit 4a94f05

Browse files
author
Andreas Gruenbacher
committed
gfs2: Initialize bio->bi_opf early
Pass the right blk_opf_t value to bio_alloc() so that ->bi_ops is initialized correctly and doesn't have to be changed later. Adjust the call chain to pass that value through to where it is needed (and only there). Add a separate blk_opf_t argument to gfs2_chain_bio() instead of copying the value from the previous bio. Fixes: 8a157e0 ("gfs2: Fix use of bio_chain") Reported-by: syzbot+f6539d4ce3f775aee0cc@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=f6539d4ce3f775aee0cc Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
1 parent 59d8103 commit 4a94f05

3 files changed

Lines changed: 26 additions & 22 deletions

File tree

fs/gfs2/log.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -888,8 +888,9 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
888888
sb->s_blocksize - LH_V1_SIZE - 4);
889889
lh->lh_crc = cpu_to_be32(crc);
890890

891-
gfs2_log_write(sdp, jd, page, sb->s_blocksize, 0, dblock);
892-
gfs2_log_submit_write(&jd->jd_log_bio, REQ_OP_WRITE | op_flags);
891+
gfs2_log_write(sdp, jd, page, sb->s_blocksize, 0, dblock,
892+
REQ_OP_WRITE | op_flags);
893+
gfs2_log_submit_write(&jd->jd_log_bio);
893894
}
894895

895896
/**
@@ -1096,7 +1097,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
10961097
if (gfs2_withdrawn(sdp))
10971098
goto out_withdraw;
10981099
if (sdp->sd_jdesc)
1099-
gfs2_log_submit_write(&sdp->sd_jdesc->jd_log_bio, REQ_OP_WRITE);
1100+
gfs2_log_submit_write(&sdp->sd_jdesc->jd_log_bio);
11001101
if (gfs2_withdrawn(sdp))
11011102
goto out_withdraw;
11021103

fs/gfs2/lops.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -231,19 +231,17 @@ static void gfs2_end_log_write(struct bio *bio)
231231
/**
232232
* gfs2_log_submit_write - Submit a pending log write bio
233233
* @biop: Address of the bio pointer
234-
* @opf: REQ_OP | op_flags
235234
*
236235
* Submit any pending part-built or full bio to the block device. If
237236
* there is no pending bio, then this is a no-op.
238237
*/
239238

240-
void gfs2_log_submit_write(struct bio **biop, blk_opf_t opf)
239+
void gfs2_log_submit_write(struct bio **biop)
241240
{
242241
struct bio *bio = *biop;
243242
if (bio) {
244243
struct gfs2_sbd *sdp = bio->bi_private;
245244
atomic_inc(&sdp->sd_log_in_flight);
246-
bio->bi_opf = opf;
247245
submit_bio(bio);
248246
*biop = NULL;
249247
}
@@ -254,17 +252,18 @@ void gfs2_log_submit_write(struct bio **biop, blk_opf_t opf)
254252
* @sdp: The super block
255253
* @blkno: The device block number we want to write to
256254
* @end_io: The bi_end_io callback
255+
* @opf: REQ_OP | op_flags
257256
*
258257
* Allocate a new bio, initialize it with the given parameters and return it.
259258
*
260259
* Returns: The newly allocated bio
261260
*/
262261

263262
static struct bio *gfs2_log_alloc_bio(struct gfs2_sbd *sdp, u64 blkno,
264-
bio_end_io_t *end_io)
263+
bio_end_io_t *end_io, blk_opf_t opf)
265264
{
266265
struct super_block *sb = sdp->sd_vfs;
267-
struct bio *bio = bio_alloc(sb->s_bdev, BIO_MAX_VECS, 0, GFP_NOIO);
266+
struct bio *bio = bio_alloc(sb->s_bdev, BIO_MAX_VECS, opf, GFP_NOIO);
268267

269268
bio->bi_iter.bi_sector = blkno << sdp->sd_fsb2bb_shift;
270269
bio->bi_end_io = end_io;
@@ -303,10 +302,10 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
303302
nblk >>= sdp->sd_fsb2bb_shift;
304303
if (blkno == nblk && !flush)
305304
return bio;
306-
gfs2_log_submit_write(biop, op);
305+
gfs2_log_submit_write(biop);
307306
}
308307

309-
*biop = gfs2_log_alloc_bio(sdp, blkno, end_io);
308+
*biop = gfs2_log_alloc_bio(sdp, blkno, end_io, op);
310309
return *biop;
311310
}
312311

@@ -318,6 +317,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
318317
* @size: the size of the data to write
319318
* @offset: the offset within the page
320319
* @blkno: block number of the log entry
320+
* @opf: REQ_OP | op_flags
321321
*
322322
* Try and add the page segment to the current bio. If that fails,
323323
* submit the current bio to the device and create a new one, and
@@ -326,17 +326,17 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
326326

327327
void gfs2_log_write(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
328328
struct page *page, unsigned size, unsigned offset,
329-
u64 blkno)
329+
u64 blkno, blk_opf_t opf)
330330
{
331331
struct bio *bio;
332332
int ret;
333333

334-
bio = gfs2_log_get_bio(sdp, blkno, &jd->jd_log_bio, REQ_OP_WRITE,
334+
bio = gfs2_log_get_bio(sdp, blkno, &jd->jd_log_bio, opf,
335335
gfs2_end_log_write, false);
336336
ret = bio_add_page(bio, page, size, offset);
337337
if (ret == 0) {
338338
bio = gfs2_log_get_bio(sdp, blkno, &jd->jd_log_bio,
339-
REQ_OP_WRITE, gfs2_end_log_write, true);
339+
opf, gfs2_end_log_write, true);
340340
ret = bio_add_page(bio, page, size, offset);
341341
WARN_ON(ret == 0);
342342
}
@@ -359,7 +359,7 @@ static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
359359
dblock = gfs2_log_bmap(sdp->sd_jdesc, sdp->sd_log_flush_head);
360360
gfs2_log_incr_head(sdp);
361361
gfs2_log_write(sdp, sdp->sd_jdesc, folio_page(bh->b_folio, 0),
362-
bh->b_size, bh_offset(bh), dblock);
362+
bh->b_size, bh_offset(bh), dblock, REQ_OP_WRITE);
363363
}
364364

365365
/**
@@ -380,7 +380,8 @@ static void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
380380

381381
dblock = gfs2_log_bmap(sdp->sd_jdesc, sdp->sd_log_flush_head);
382382
gfs2_log_incr_head(sdp);
383-
gfs2_log_write(sdp, sdp->sd_jdesc, page, sb->s_blocksize, 0, dblock);
383+
gfs2_log_write(sdp, sdp->sd_jdesc, page, sb->s_blocksize, 0, dblock,
384+
REQ_OP_WRITE);
384385
}
385386

386387
/**
@@ -477,11 +478,12 @@ static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index,
477478
folio_put_refs(folio, 2);
478479
}
479480

480-
static struct bio *gfs2_chain_bio(struct bio *prev, unsigned int nr_iovecs)
481+
static struct bio *gfs2_chain_bio(struct bio *prev, unsigned int nr_iovecs,
482+
blk_opf_t opf)
481483
{
482484
struct bio *new;
483485

484-
new = bio_alloc(prev->bi_bdev, nr_iovecs, prev->bi_opf, GFP_NOIO);
486+
new = bio_alloc(prev->bi_bdev, nr_iovecs, opf, GFP_NOIO);
485487
bio_clone_blkg_association(new, prev);
486488
new->bi_iter.bi_sector = bio_end_sector(prev);
487489
bio_chain(new, prev);
@@ -546,7 +548,8 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
546548
unsigned int blocks =
547549
(PAGE_SIZE - off) >> bsize_shift;
548550

549-
bio = gfs2_chain_bio(bio, blocks);
551+
bio = gfs2_chain_bio(bio, blocks,
552+
REQ_OP_READ);
550553
goto add_block_to_new_bio;
551554
}
552555
}
@@ -556,8 +559,8 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
556559
submit_bio(bio);
557560
}
558561

559-
bio = gfs2_log_alloc_bio(sdp, dblock, gfs2_end_log_read);
560-
bio->bi_opf = REQ_OP_READ;
562+
bio = gfs2_log_alloc_bio(sdp, dblock, gfs2_end_log_read,
563+
REQ_OP_READ);
561564
add_block_to_new_bio:
562565
bio_add_folio_nofail(bio, folio, bsize, off);
563566
block_added:

fs/gfs2/lops.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ void gfs2_log_incr_head(struct gfs2_sbd *sdp);
1616
u64 gfs2_log_bmap(struct gfs2_jdesc *jd, unsigned int lbn);
1717
void gfs2_log_write(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
1818
struct page *page, unsigned size, unsigned offset,
19-
u64 blkno);
20-
void gfs2_log_submit_write(struct bio **biop, blk_opf_t opf);
19+
u64 blkno, blk_opf_t opf);
20+
void gfs2_log_submit_write(struct bio **biop);
2121
void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
2222
int gfs2_find_jhead(struct gfs2_jdesc *jd,
2323
struct gfs2_log_header_host *head);

0 commit comments

Comments
 (0)