- i_size is 64 bit, ssize_t is 32-bit - whitespace tweaks. - i_size_read() in interrupt context is a no-no. Signed-off-by: Andrew Morton --- 25-akpm/fs/direct-io.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff -puN fs/direct-io.c~direct-io-async-short-read-fix-fix fs/direct-io.c --- 25/fs/direct-io.c~direct-io-async-short-read-fix-fix 2005-03-07 22:28:52.000000000 -0800 +++ 25-akpm/fs/direct-io.c 2005-03-07 22:37:18.000000000 -0800 @@ -231,7 +231,7 @@ static void finished_one_bio(struct dio if (dio->bio_count == 1) { if (dio->is_async) { ssize_t transferred; - ssize_t i_size; + loff_t i_size; loff_t offset; /* @@ -241,11 +241,19 @@ static void finished_one_bio(struct dio spin_unlock_irqrestore(&dio->bio_lock, flags); /* Check for short read case */ + + /* + * We should use i_size_read() here. But we're called + * in interrupt context. If this CPU happened to be + * in the middle of i_size_write() when the interrupt + * occurred, i_size_read() would lock up. + * So we just risk getting a wrong result instead :( + */ + i_size = dio->inode->i_size; transferred = dio->result; - i_size = i_size_read (dio->inode); offset = dio->iocb->ki_pos; - if ((dio->rw == READ) && ((offset + transferred) > i_size)) + if ((dio->rw == READ) && (offset+transferred > i_size)) transferred = i_size - offset; dio_complete(dio, offset, transferred); _