mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
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: 8a157e0a0a ("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>
This commit is contained in:
parent
59d81037d3
commit
4a94f052e0
3 changed files with 26 additions and 22 deletions
|
|
@ -888,8 +888,9 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
|||
sb->s_blocksize - LH_V1_SIZE - 4);
|
||||
lh->lh_crc = cpu_to_be32(crc);
|
||||
|
||||
gfs2_log_write(sdp, jd, page, sb->s_blocksize, 0, dblock);
|
||||
gfs2_log_submit_write(&jd->jd_log_bio, REQ_OP_WRITE | op_flags);
|
||||
gfs2_log_write(sdp, jd, page, sb->s_blocksize, 0, dblock,
|
||||
REQ_OP_WRITE | op_flags);
|
||||
gfs2_log_submit_write(&jd->jd_log_bio);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1096,7 +1097,7 @@ repeat:
|
|||
if (gfs2_withdrawn(sdp))
|
||||
goto out_withdraw;
|
||||
if (sdp->sd_jdesc)
|
||||
gfs2_log_submit_write(&sdp->sd_jdesc->jd_log_bio, REQ_OP_WRITE);
|
||||
gfs2_log_submit_write(&sdp->sd_jdesc->jd_log_bio);
|
||||
if (gfs2_withdrawn(sdp))
|
||||
goto out_withdraw;
|
||||
|
||||
|
|
|
|||
|
|
@ -231,19 +231,17 @@ static void gfs2_end_log_write(struct bio *bio)
|
|||
/**
|
||||
* gfs2_log_submit_write - Submit a pending log write bio
|
||||
* @biop: Address of the bio pointer
|
||||
* @opf: REQ_OP | op_flags
|
||||
*
|
||||
* Submit any pending part-built or full bio to the block device. If
|
||||
* there is no pending bio, then this is a no-op.
|
||||
*/
|
||||
|
||||
void gfs2_log_submit_write(struct bio **biop, blk_opf_t opf)
|
||||
void gfs2_log_submit_write(struct bio **biop)
|
||||
{
|
||||
struct bio *bio = *biop;
|
||||
if (bio) {
|
||||
struct gfs2_sbd *sdp = bio->bi_private;
|
||||
atomic_inc(&sdp->sd_log_in_flight);
|
||||
bio->bi_opf = opf;
|
||||
submit_bio(bio);
|
||||
*biop = NULL;
|
||||
}
|
||||
|
|
@ -254,6 +252,7 @@ void gfs2_log_submit_write(struct bio **biop, blk_opf_t opf)
|
|||
* @sdp: The super block
|
||||
* @blkno: The device block number we want to write to
|
||||
* @end_io: The bi_end_io callback
|
||||
* @opf: REQ_OP | op_flags
|
||||
*
|
||||
* Allocate a new bio, initialize it with the given parameters and return it.
|
||||
*
|
||||
|
|
@ -261,10 +260,10 @@ void gfs2_log_submit_write(struct bio **biop, blk_opf_t opf)
|
|||
*/
|
||||
|
||||
static struct bio *gfs2_log_alloc_bio(struct gfs2_sbd *sdp, u64 blkno,
|
||||
bio_end_io_t *end_io)
|
||||
bio_end_io_t *end_io, blk_opf_t opf)
|
||||
{
|
||||
struct super_block *sb = sdp->sd_vfs;
|
||||
struct bio *bio = bio_alloc(sb->s_bdev, BIO_MAX_VECS, 0, GFP_NOIO);
|
||||
struct bio *bio = bio_alloc(sb->s_bdev, BIO_MAX_VECS, opf, GFP_NOIO);
|
||||
|
||||
bio->bi_iter.bi_sector = blkno << sdp->sd_fsb2bb_shift;
|
||||
bio->bi_end_io = end_io;
|
||||
|
|
@ -303,10 +302,10 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
|
|||
nblk >>= sdp->sd_fsb2bb_shift;
|
||||
if (blkno == nblk && !flush)
|
||||
return bio;
|
||||
gfs2_log_submit_write(biop, op);
|
||||
gfs2_log_submit_write(biop);
|
||||
}
|
||||
|
||||
*biop = gfs2_log_alloc_bio(sdp, blkno, end_io);
|
||||
*biop = gfs2_log_alloc_bio(sdp, blkno, end_io, op);
|
||||
return *biop;
|
||||
}
|
||||
|
||||
|
|
@ -318,6 +317,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
|
|||
* @size: the size of the data to write
|
||||
* @offset: the offset within the page
|
||||
* @blkno: block number of the log entry
|
||||
* @opf: REQ_OP | op_flags
|
||||
*
|
||||
* Try and add the page segment to the current bio. If that fails,
|
||||
* 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,
|
|||
|
||||
void gfs2_log_write(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
struct page *page, unsigned size, unsigned offset,
|
||||
u64 blkno)
|
||||
u64 blkno, blk_opf_t opf)
|
||||
{
|
||||
struct bio *bio;
|
||||
int ret;
|
||||
|
||||
bio = gfs2_log_get_bio(sdp, blkno, &jd->jd_log_bio, REQ_OP_WRITE,
|
||||
bio = gfs2_log_get_bio(sdp, blkno, &jd->jd_log_bio, opf,
|
||||
gfs2_end_log_write, false);
|
||||
ret = bio_add_page(bio, page, size, offset);
|
||||
if (ret == 0) {
|
||||
bio = gfs2_log_get_bio(sdp, blkno, &jd->jd_log_bio,
|
||||
REQ_OP_WRITE, gfs2_end_log_write, true);
|
||||
opf, gfs2_end_log_write, true);
|
||||
ret = bio_add_page(bio, page, size, offset);
|
||||
WARN_ON(ret == 0);
|
||||
}
|
||||
|
|
@ -359,7 +359,7 @@ static void gfs2_log_write_bh(struct gfs2_sbd *sdp, struct buffer_head *bh)
|
|||
dblock = gfs2_log_bmap(sdp->sd_jdesc, sdp->sd_log_flush_head);
|
||||
gfs2_log_incr_head(sdp);
|
||||
gfs2_log_write(sdp, sdp->sd_jdesc, folio_page(bh->b_folio, 0),
|
||||
bh->b_size, bh_offset(bh), dblock);
|
||||
bh->b_size, bh_offset(bh), dblock, REQ_OP_WRITE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -380,7 +380,8 @@ static void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
|
|||
|
||||
dblock = gfs2_log_bmap(sdp->sd_jdesc, sdp->sd_log_flush_head);
|
||||
gfs2_log_incr_head(sdp);
|
||||
gfs2_log_write(sdp, sdp->sd_jdesc, page, sb->s_blocksize, 0, dblock);
|
||||
gfs2_log_write(sdp, sdp->sd_jdesc, page, sb->s_blocksize, 0, dblock,
|
||||
REQ_OP_WRITE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -477,11 +478,12 @@ static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index,
|
|||
folio_put_refs(folio, 2);
|
||||
}
|
||||
|
||||
static struct bio *gfs2_chain_bio(struct bio *prev, unsigned int nr_iovecs)
|
||||
static struct bio *gfs2_chain_bio(struct bio *prev, unsigned int nr_iovecs,
|
||||
blk_opf_t opf)
|
||||
{
|
||||
struct bio *new;
|
||||
|
||||
new = bio_alloc(prev->bi_bdev, nr_iovecs, prev->bi_opf, GFP_NOIO);
|
||||
new = bio_alloc(prev->bi_bdev, nr_iovecs, opf, GFP_NOIO);
|
||||
bio_clone_blkg_association(new, prev);
|
||||
new->bi_iter.bi_sector = bio_end_sector(prev);
|
||||
bio_chain(new, prev);
|
||||
|
|
@ -546,7 +548,8 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
|
|||
unsigned int blocks =
|
||||
(PAGE_SIZE - off) >> bsize_shift;
|
||||
|
||||
bio = gfs2_chain_bio(bio, blocks);
|
||||
bio = gfs2_chain_bio(bio, blocks,
|
||||
REQ_OP_READ);
|
||||
goto add_block_to_new_bio;
|
||||
}
|
||||
}
|
||||
|
|
@ -556,8 +559,8 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
|
|||
submit_bio(bio);
|
||||
}
|
||||
|
||||
bio = gfs2_log_alloc_bio(sdp, dblock, gfs2_end_log_read);
|
||||
bio->bi_opf = REQ_OP_READ;
|
||||
bio = gfs2_log_alloc_bio(sdp, dblock, gfs2_end_log_read,
|
||||
REQ_OP_READ);
|
||||
add_block_to_new_bio:
|
||||
bio_add_folio_nofail(bio, folio, bsize, off);
|
||||
block_added:
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ void gfs2_log_incr_head(struct gfs2_sbd *sdp);
|
|||
u64 gfs2_log_bmap(struct gfs2_jdesc *jd, unsigned int lbn);
|
||||
void gfs2_log_write(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
|
||||
struct page *page, unsigned size, unsigned offset,
|
||||
u64 blkno);
|
||||
void gfs2_log_submit_write(struct bio **biop, blk_opf_t opf);
|
||||
u64 blkno, blk_opf_t opf);
|
||||
void gfs2_log_submit_write(struct bio **biop);
|
||||
void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
|
||||
int gfs2_find_jhead(struct gfs2_jdesc *jd,
|
||||
struct gfs2_log_header_host *head);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue