lkml.org 
[lkml]   [2005]   [Mar]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH] 2.6.10 - direct-io async short read bug
    From
    Date
     Hi,

    When reading a file in async mode (using kernel AIO), and the file
    size is lower than the requested size (short read), the direct IO
    layer reports an incorrect number of bytes read (transferred).

    That case is handled for the sync path in 'direct_io_worker'
    (fs/direct-io.c) where a check is made against the file size.

    This patch does the same thing for the async path. It applies to
    a vanilla 2.6.10 kernel.

    Please CC: me any comments and/or suggestions.

    Sébastien.

    ------------------------------------------------------

    Sébastien Dugué BULL/FREC:B1-247
    phone: (+33) 476 29 77 70 Bullcom: 229-7770

    mailto:sebastien.dugue@bull.net

    Linux POSIX AIO: http://www.bullopensource.org/posix

    ------------------------------------------------------
    --- linux-2.6.10/fs/direct-io.c.orig 2005-03-03 12:41:05.541074051 +0100
    +++ linux-2.6.10/fs/direct-io.c 2005-03-03 12:01:46.206210808 +0100
    @@ -230,17 +230,30 @@ static void finished_one_bio(struct dio
    spin_lock_irqsave(&dio->bio_lock, flags);
    if (dio->bio_count == 1) {
    if (dio->is_async) {
    + ssize_t transferred;
    + ssize_t i_size;
    + loff_t offset;
    +
    /*
    * Last reference to the dio is going away.
    * Drop spinlock and complete the DIO.
    */
    spin_unlock_irqrestore(&dio->bio_lock, flags);
    - dio_complete(dio, dio->block_in_file << dio->blkbits,
    - dio->result);
    +
    + /* Check for short read case */
    + transferred = dio->result;
    + i_size = i_size_read (dio->inode);
    + offset = dio->iocb->ki_pos;
    +
    + if ((dio->rw == READ) && ((offset + transferred) > i_size))
    + transferred = i_size - offset;
    +
    + dio_complete(dio, offset, transferred);
    +
    /* Complete AIO later if falling back to buffered i/o */
    if (dio->result == dio->size ||
    ((dio->rw == READ) && dio->result)) {
    - aio_complete(dio->iocb, dio->result, 0);
    + aio_complete(dio->iocb, transferred, 0);
    kfree(dio);
    return;
    } else {
    \
     
     \ /
      Last update: 2005-03-22 14:10    [W:4.583 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site