Skip to content

Commit d928755

Browse files
author
Herton R. Krzesinski
committed
Merge: fs: replace ll_rw_block()
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/1885 Bugzilla: https://bugzilla.redhat.com/2160719 Tested: xfstests ll_rw_block() is not safe for the sync read path because it cannot guarantee that submitting read IO if the buffer has been locked. We could get false positive EIO after wait_on_buffer() if the buffer has been locked by others. ll_rw_block() is being used by multiple file systems (gfs2, isofs, jbd2, ntfs3, ocfs2, reiserfs, udf, ufs) not all of which are shipped by Red Hat so we only backport changes for gfs2, isofs, jbd2, and udf. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Approved-by: Pavel Reichl <preichl@redhat.com> Approved-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
2 parents 5cbb96e + dcb28bf commit d928755

File tree

11 files changed

+129
-140
lines changed

11 files changed

+129
-140
lines changed

fs/buffer.c

Lines changed: 63 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ static void __end_buffer_read_notouch(struct buffer_head *bh, int uptodate)
152152

153153
/*
154154
* Default synchronous end-of-IO handler.. Just mark it up-to-date and
155-
* unlock the buffer. This is what ll_rw_block uses too.
155+
* unlock the buffer.
156156
*/
157157
void end_buffer_read_sync(struct buffer_head *bh, int uptodate)
158158
{
@@ -491,8 +491,8 @@ int inode_has_buffers(struct inode *inode)
491491
* all already-submitted IO to complete, but does not queue any new
492492
* writes to the disk.
493493
*
494-
* To do O_SYNC writes, just queue the buffer writes with ll_rw_block as
495-
* you dirty the buffers, and then use osync_inode_buffers to wait for
494+
* To do O_SYNC writes, just queue the buffer writes with write_dirty_buffer
495+
* as you dirty the buffers, and then use osync_inode_buffers to wait for
496496
* completion. Any other dirty buffers which are not yet queued for
497497
* write will not be flushed to disk by the osync.
498498
*/
@@ -562,7 +562,7 @@ void write_boundary_block(struct block_device *bdev,
562562
struct buffer_head *bh = __find_get_block(bdev, bblock + 1, blocksize);
563563
if (bh) {
564564
if (buffer_dirty(bh))
565-
ll_rw_block(REQ_OP_WRITE, 1, &bh);
565+
write_dirty_buffer(bh, 0);
566566
put_bh(bh);
567567
}
568568
}
@@ -1342,23 +1342,12 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size)
13421342
{
13431343
struct buffer_head *bh = __getblk(bdev, block, size);
13441344
if (likely(bh)) {
1345-
ll_rw_block(REQ_OP_READ | REQ_RAHEAD, 1, &bh);
1345+
bh_readahead(bh, REQ_RAHEAD);
13461346
brelse(bh);
13471347
}
13481348
}
13491349
EXPORT_SYMBOL(__breadahead);
13501350

1351-
void __breadahead_gfp(struct block_device *bdev, sector_t block, unsigned size,
1352-
gfp_t gfp)
1353-
{
1354-
struct buffer_head *bh = __getblk_gfp(bdev, block, size, gfp);
1355-
if (likely(bh)) {
1356-
ll_rw_block(REQ_OP_READ | REQ_RAHEAD, 1, &bh);
1357-
brelse(bh);
1358-
}
1359-
}
1360-
EXPORT_SYMBOL(__breadahead_gfp);
1361-
13621351
/**
13631352
* __bread_gfp() - reads a specified block and returns the bh
13641353
* @bdev: the block_device to read from
@@ -1817,7 +1806,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
18171806
/*
18181807
* The page was marked dirty, but the buffers were
18191808
* clean. Someone wrote them back by hand with
1820-
* ll_rw_block/submit_bh. A rare case.
1809+
* write_dirty_buffer/submit_bh. A rare case.
18211810
*/
18221811
end_page_writeback(page);
18231812

@@ -2033,7 +2022,7 @@ int __block_write_begin_int(struct page *page, loff_t pos, unsigned len,
20332022
if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
20342023
!buffer_unwritten(bh) &&
20352024
(block_start < from || block_end > to)) {
2036-
ll_rw_block(REQ_OP_READ, 1, &bh);
2025+
bh_read_nowait(bh, 0);
20372026
*wait_bh++=bh;
20382027
}
20392028
}
@@ -2920,11 +2909,9 @@ int block_truncate_page(struct address_space *mapping,
29202909
set_buffer_uptodate(bh);
29212910

29222911
if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) {
2923-
err = -EIO;
2924-
ll_rw_block(REQ_OP_READ, 1, &bh);
2925-
wait_on_buffer(bh);
2912+
err = bh_read(bh, 0);
29262913
/* Uhhuh. Read error. Complain and punt. */
2927-
if (!buffer_uptodate(bh))
2914+
if (err < 0)
29282915
goto unlock;
29292916
}
29302917

@@ -3053,61 +3040,6 @@ int submit_bh(blk_opf_t opf, struct buffer_head *bh)
30533040
}
30543041
EXPORT_SYMBOL(submit_bh);
30553042

3056-
/**
3057-
* ll_rw_block: low-level access to block devices (DEPRECATED)
3058-
* @opf: block layer request operation and flags.
3059-
* @nr: number of &struct buffer_heads in the array
3060-
* @bhs: array of pointers to &struct buffer_head
3061-
*
3062-
* ll_rw_block() takes an array of pointers to &struct buffer_heads, and
3063-
* requests an I/O operation on them, either a %REQ_OP_READ or a %REQ_OP_WRITE.
3064-
* @opf contains flags modifying the detailed I/O behavior, most notably
3065-
* %REQ_RAHEAD.
3066-
*
3067-
* This function drops any buffer that it cannot get a lock on (with the
3068-
* BH_Lock state bit), any buffer that appears to be clean when doing a write
3069-
* request, and any buffer that appears to be up-to-date when doing read
3070-
* request. Further it marks as clean buffers that are processed for
3071-
* writing (the buffer cache won't assume that they are actually clean
3072-
* until the buffer gets unlocked).
3073-
*
3074-
* ll_rw_block sets b_end_io to simple completion handler that marks
3075-
* the buffer up-to-date (if appropriate), unlocks the buffer and wakes
3076-
* any waiters.
3077-
*
3078-
* All of the buffers must be for the same device, and must also be a
3079-
* multiple of the current approved size for the device.
3080-
*/
3081-
void ll_rw_block(const blk_opf_t opf, int nr, struct buffer_head *bhs[])
3082-
{
3083-
const enum req_op op = opf & REQ_OP_MASK;
3084-
int i;
3085-
3086-
for (i = 0; i < nr; i++) {
3087-
struct buffer_head *bh = bhs[i];
3088-
3089-
if (!trylock_buffer(bh))
3090-
continue;
3091-
if (op == REQ_OP_WRITE) {
3092-
if (test_clear_buffer_dirty(bh)) {
3093-
bh->b_end_io = end_buffer_write_sync;
3094-
get_bh(bh);
3095-
submit_bh(opf, bh);
3096-
continue;
3097-
}
3098-
} else {
3099-
if (!buffer_uptodate(bh)) {
3100-
bh->b_end_io = end_buffer_read_sync;
3101-
get_bh(bh);
3102-
submit_bh(opf, bh);
3103-
continue;
3104-
}
3105-
}
3106-
unlock_buffer(bh);
3107-
}
3108-
}
3109-
EXPORT_SYMBOL(ll_rw_block);
3110-
31113043
void write_dirty_buffer(struct buffer_head *bh, blk_opf_t op_flags)
31123044
{
31133045
lock_buffer(bh);
@@ -3356,29 +3288,69 @@ int bh_uptodate_or_lock(struct buffer_head *bh)
33563288
EXPORT_SYMBOL(bh_uptodate_or_lock);
33573289

33583290
/**
3359-
* bh_submit_read - Submit a locked buffer for reading
3291+
* __bh_read - Submit read for a locked buffer
33603292
* @bh: struct buffer_head
3293+
* @op_flags: appending REQ_OP_* flags besides REQ_OP_READ
3294+
* @wait: wait until reading finish
33613295
*
3362-
* Returns zero on success and -EIO on error.
3296+
* Returns zero on success or don't wait, and -EIO on error.
33633297
*/
3364-
int bh_submit_read(struct buffer_head *bh)
3298+
int __bh_read(struct buffer_head *bh, blk_opf_t op_flags, bool wait)
33653299
{
3366-
BUG_ON(!buffer_locked(bh));
3300+
int ret = 0;
33673301

3368-
if (buffer_uptodate(bh)) {
3369-
unlock_buffer(bh);
3370-
return 0;
3371-
}
3302+
BUG_ON(!buffer_locked(bh));
33723303

33733304
get_bh(bh);
33743305
bh->b_end_io = end_buffer_read_sync;
3375-
submit_bh(REQ_OP_READ, bh);
3376-
wait_on_buffer(bh);
3377-
if (buffer_uptodate(bh))
3378-
return 0;
3379-
return -EIO;
3306+
submit_bh(REQ_OP_READ | op_flags, bh);
3307+
if (wait) {
3308+
wait_on_buffer(bh);
3309+
if (!buffer_uptodate(bh))
3310+
ret = -EIO;
3311+
}
3312+
return ret;
3313+
}
3314+
EXPORT_SYMBOL(__bh_read);
3315+
3316+
/**
3317+
* __bh_read_batch - Submit read for a batch of unlocked buffers
3318+
* @nr: entry number of the buffer batch
3319+
* @bhs: a batch of struct buffer_head
3320+
* @op_flags: appending REQ_OP_* flags besides REQ_OP_READ
3321+
* @force_lock: force to get a lock on the buffer if set, otherwise drops any
3322+
* buffer that cannot lock.
3323+
*
3324+
* Returns zero on success or don't wait, and -EIO on error.
3325+
*/
3326+
void __bh_read_batch(int nr, struct buffer_head *bhs[],
3327+
blk_opf_t op_flags, bool force_lock)
3328+
{
3329+
int i;
3330+
3331+
for (i = 0; i < nr; i++) {
3332+
struct buffer_head *bh = bhs[i];
3333+
3334+
if (buffer_uptodate(bh))
3335+
continue;
3336+
3337+
if (force_lock)
3338+
lock_buffer(bh);
3339+
else
3340+
if (!trylock_buffer(bh))
3341+
continue;
3342+
3343+
if (buffer_uptodate(bh)) {
3344+
unlock_buffer(bh);
3345+
continue;
3346+
}
3347+
3348+
bh->b_end_io = end_buffer_read_sync;
3349+
get_bh(bh);
3350+
submit_bh(REQ_OP_READ | op_flags, bh);
3351+
}
33803352
}
3381-
EXPORT_SYMBOL(bh_submit_read);
3353+
EXPORT_SYMBOL(__bh_read_batch);
33823354

33833355
void __init buffer_init(void)
33843356
{

fs/ext2/balloc.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
128128
struct ext2_group_desc * desc;
129129
struct buffer_head * bh = NULL;
130130
ext2_fsblk_t bitmap_blk;
131+
int ret;
131132

132133
desc = ext2_get_group_desc(sb, block_group, NULL);
133134
if (!desc)
@@ -141,10 +142,10 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
141142
block_group, le32_to_cpu(desc->bg_block_bitmap));
142143
return NULL;
143144
}
144-
if (likely(bh_uptodate_or_lock(bh)))
145+
ret = bh_read(bh, 0);
146+
if (ret > 0)
145147
return bh;
146-
147-
if (bh_submit_read(bh) < 0) {
148+
if (ret < 0) {
148149
brelse(bh);
149150
ext2_error(sb, __func__,
150151
"Cannot read block bitmap - "

fs/gfs2/meta_io.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -525,18 +525,15 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
525525

526526
if (buffer_uptodate(first_bh))
527527
goto out;
528-
if (!buffer_locked(first_bh))
529-
ll_rw_block(REQ_OP_READ | REQ_META | REQ_PRIO, 1, &first_bh);
528+
bh_read_nowait(first_bh, REQ_META | REQ_PRIO);
530529

531530
dblock++;
532531
extlen--;
533532

534533
while (extlen) {
535534
bh = gfs2_getbuf(gl, dblock, CREATE);
536535

537-
if (!buffer_uptodate(bh) && !buffer_locked(bh))
538-
ll_rw_block(REQ_OP_READ | REQ_RAHEAD | REQ_META |
539-
REQ_PRIO, 1, &bh);
536+
bh_readahead(bh, REQ_RAHEAD | REQ_META | REQ_PRIO);
540537
brelse(bh);
541538
dblock++;
542539
extlen--;

fs/gfs2/quota.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -733,12 +733,8 @@ static int gfs2_write_buf_to_page(struct gfs2_inode *ip, unsigned long index,
733733
}
734734
if (PageUptodate(page))
735735
set_buffer_uptodate(bh);
736-
if (!buffer_uptodate(bh)) {
737-
ll_rw_block(REQ_OP_READ | REQ_META | REQ_PRIO, 1, &bh);
738-
wait_on_buffer(bh);
739-
if (!buffer_uptodate(bh))
740-
goto unlock_out;
741-
}
736+
if (bh_read(bh, REQ_META | REQ_PRIO) < 0)
737+
goto unlock_out;
742738
if (gfs2_is_jdata(ip))
743739
gfs2_trans_add_data(ip->i_gl, bh);
744740
else

fs/isofs/compress.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
8282
return 0;
8383
}
8484
haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks);
85-
ll_rw_block(REQ_OP_READ, haveblocks, bhs);
85+
bh_read_batch(haveblocks, bhs);
8686

8787
curbh = 0;
8888
curpage = 0;

fs/jbd2/journal.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,19 +1897,16 @@ static int journal_get_superblock(journal_t *journal)
18971897
{
18981898
struct buffer_head *bh;
18991899
journal_superblock_t *sb;
1900-
int err = -EIO;
1900+
int err;
19011901

19021902
bh = journal->j_sb_buffer;
19031903

19041904
J_ASSERT(bh != NULL);
1905-
if (!buffer_uptodate(bh)) {
1906-
ll_rw_block(REQ_OP_READ, 1, &bh);
1907-
wait_on_buffer(bh);
1908-
if (!buffer_uptodate(bh)) {
1909-
printk(KERN_ERR
1910-
"JBD2: IO error reading journal superblock\n");
1911-
goto out;
1912-
}
1905+
err = bh_read(bh, 0);
1906+
if (err < 0) {
1907+
printk(KERN_ERR
1908+
"JBD2: IO error reading journal superblock\n");
1909+
goto out;
19131910
}
19141911

19151912
if (buffer_verified(bh))

fs/jbd2/recovery.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
100100
if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
101101
bufs[nbufs++] = bh;
102102
if (nbufs == MAXBUF) {
103-
ll_rw_block(REQ_OP_READ, nbufs, bufs);
103+
bh_readahead_batch(nbufs, bufs, 0);
104104
journal_brelse_array(bufs, nbufs);
105105
nbufs = 0;
106106
}
@@ -109,7 +109,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
109109
}
110110

111111
if (nbufs)
112-
ll_rw_block(REQ_OP_READ, nbufs, bufs);
112+
bh_readahead_batch(nbufs, bufs, 0);
113113
err = 0;
114114

115115
failed:
@@ -152,9 +152,14 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
152152
return -ENOMEM;
153153

154154
if (!buffer_uptodate(bh)) {
155-
/* If this is a brand new buffer, start readahead.
156-
Otherwise, we assume we are already reading it. */
157-
if (!buffer_req(bh))
155+
/*
156+
* If this is a brand new buffer, start readahead.
157+
* Otherwise, we assume we are already reading it.
158+
*/
159+
bool need_readahead = !buffer_req(bh);
160+
161+
bh_read_nowait(bh, 0);
162+
if (need_readahead)
158163
do_readahead(journal, offset);
159164
wait_on_buffer(bh);
160165
}
@@ -688,7 +693,6 @@ static int do_one_pass(journal_t *journal,
688693
mark_buffer_dirty(nbh);
689694
BUFFER_TRACE(nbh, "marking uptodate");
690695
++info->nr_replays;
691-
/* ll_rw_block(WRITE, 1, &nbh); */
692696
unlock_buffer(nbh);
693697
brelse(obh);
694698
brelse(nbh);

fs/udf/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx)
114114
brelse(tmp);
115115
}
116116
if (num) {
117-
ll_rw_block(REQ_OP_READ | REQ_RAHEAD, num, bha);
117+
bh_readahead_batch(num, bha, REQ_RAHEAD);
118118
for (i = 0; i < num; i++)
119119
brelse(bha[i]);
120120
}

fs/udf/directory.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
8989
brelse(tmp);
9090
}
9191
if (num) {
92-
ll_rw_block(REQ_OP_READ | REQ_RAHEAD, num, bha);
92+
bh_readahead_batch(num, bha, REQ_RAHEAD);
9393
for (i = 0; i < num; i++)
9494
brelse(bha[i]);
9595
}

0 commit comments

Comments
 (0)