Skip to content

Commit

Permalink
ext4: Resolve the hang of direct i/o read in handling EXT4_IO_END_UNW…
Browse files Browse the repository at this point in the history
…RITTEN.

EXT4_IO_END_UNWRITTEN flag set and the increase of i_aiodio_unwritten
should be done simultaneously since ext4_end_io_nolock always clear
the flag and decrease the counter in the same time.

We don't increase i_aiodio_unwritten when setting
EXT4_IO_END_UNWRITTEN so it will go nagative and causes some process
to wait forever.

Part of the patch came from Eric in his e-mail, but it doesn't fix the
problem met by Michael actually.

http://marc.info/?l=linux-ext4&m=131316851417460&w=2

Reported-and-Tested-by: Michael Tokarev<mjt@tls.msk.ru>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@kernel.org
  • Loading branch information
Tao Ma authored and Theodore Ts'o committed Aug 13, 2011
1 parent 2581fdc commit 32c80b3
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 3 deletions.
9 changes: 8 additions & 1 deletion fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2678,8 +2678,15 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
goto out;
}

io_end->flag = EXT4_IO_END_UNWRITTEN;
/*
* It may be over-defensive here to check EXT4_IO_END_UNWRITTEN now,
* but being more careful is always safe for the future change.
*/
inode = io_end->inode;
if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
io_end->flag |= EXT4_IO_END_UNWRITTEN;
atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
}

/* Add the io_end to per-inode completed io list*/
spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
Expand Down
6 changes: 4 additions & 2 deletions fs/ext4/page-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,10 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
if ((io_end->num_io_pages >= MAX_IO_PAGES) &&
(io_end->pages[io_end->num_io_pages-1] != io_page))
goto submit_and_retry;
if (buffer_uninit(bh))
io->io_end->flag |= EXT4_IO_END_UNWRITTEN;
if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
io_end->flag |= EXT4_IO_END_UNWRITTEN;
atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten);
}
io->io_end->size += bh->b_size;
io->io_next_block++;
ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
Expand Down

0 comments on commit 32c80b3

Please sign in to comment.