lkml.org 
[lkml]   [2019]   [Apr]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.0 080/117] block: fix the return errno for direct IO
    Date
    From: Jason Yan <yanaijie@huawei.com>

    commit a89afe58f1a74aac768a5eb77af95ef4ee15beaa upstream.

    If the last bio returned is not dio->bio, the status of the bio will
    not assigned to dio->bio if it is error. This will cause the whole IO
    status wrong.

    ksoftirqd/21-117 [021] ..s. 4017.966090: 8,0 C N 4883648 [0]
    <idle>-0 [018] ..s. 4017.970888: 8,0 C WS 4924800 + 1024 [0]
    <idle>-0 [018] ..s. 4017.970909: 8,0 D WS 4935424 + 1024 [<idle>]
    <idle>-0 [018] ..s. 4017.970924: 8,0 D WS 4936448 + 321 [<idle>]
    ksoftirqd/21-117 [021] ..s. 4017.995033: 8,0 C R 4883648 + 336 [65475]
    ksoftirqd/21-117 [021] d.s. 4018.001988: myprobe1: (blkdev_bio_end_io+0x0/0x168) bi_status=7
    ksoftirqd/21-117 [021] d.s. 4018.001992: myprobe: (aio_complete_rw+0x0/0x148) x0=0xffff802f2595ad80 res=0x12a000 res2=0x0

    We always have to assign bio->bi_status to dio->bio.bi_status because we
    will only check dio->bio.bi_status when we return the whole IO to
    the upper layer.

    Fixes: 542ff7bf18c6 ("block: new direct I/O implementation")
    Cc: stable@vger.kernel.org
    Cc: Christoph Hellwig <hch@lst.de>
    Cc: Jens Axboe <axboe@kernel.dk>
    Reviewed-by: Ming Lei <ming.lei@redhat.com>
    Signed-off-by: Jason Yan <yanaijie@huawei.com>
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/block_dev.c | 8 ++++----
    1 file changed, 4 insertions(+), 4 deletions(-)

    --- a/fs/block_dev.c
    +++ b/fs/block_dev.c
    @@ -298,10 +298,10 @@ static void blkdev_bio_end_io(struct bio
    struct blkdev_dio *dio = bio->bi_private;
    bool should_dirty = dio->should_dirty;

    - if (dio->multi_bio && !atomic_dec_and_test(&dio->ref)) {
    - if (bio->bi_status && !dio->bio.bi_status)
    - dio->bio.bi_status = bio->bi_status;
    - } else {
    + if (bio->bi_status && !dio->bio.bi_status)
    + dio->bio.bi_status = bio->bi_status;
    +
    + if (!dio->multi_bio || atomic_dec_and_test(&dio->ref)) {
    if (!dio->is_sync) {
    struct kiocb *iocb = dio->iocb;
    ssize_t ret;

    \
     
     \ /
      Last update: 2019-04-15 21:17    [W:2.910 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site