Commit c063d8a6 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: flush any pending end_io requests before DIO reads w/dioread_nolock
  ext4: fix nomblk_io_submit option so it correctly converts uninit blocks
  ext4: Resolve the hang of direct i/o read in handling EXT4_IO_END_UNWRITTEN.
  ext4: call ext4_ioend_wait and ext4_flush_completed_IO in ext4_evict_inode
  ext4: Fix ext4_should_writeback_data() for no-journal mode
parents 79058c4b dccaf33f
...@@ -289,10 +289,10 @@ static inline int ext4_should_order_data(struct inode *inode) ...@@ -289,10 +289,10 @@ static inline int ext4_should_order_data(struct inode *inode)
static inline int ext4_should_writeback_data(struct inode *inode) static inline int ext4_should_writeback_data(struct inode *inode)
{ {
if (!S_ISREG(inode->i_mode))
return 0;
if (EXT4_JOURNAL(inode) == NULL) if (EXT4_JOURNAL(inode) == NULL)
return 1; return 1;
if (!S_ISREG(inode->i_mode))
return 0;
if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
return 0; return 0;
if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
......
...@@ -800,12 +800,17 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, ...@@ -800,12 +800,17 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
} }
retry: retry:
if (rw == READ && ext4_should_dioread_nolock(inode)) if (rw == READ && ext4_should_dioread_nolock(inode)) {
if (unlikely(!list_empty(&ei->i_completed_io_list))) {
mutex_lock(&inode->i_mutex);
ext4_flush_completed_IO(inode);
mutex_unlock(&inode->i_mutex);
}
ret = __blockdev_direct_IO(rw, iocb, inode, ret = __blockdev_direct_IO(rw, iocb, inode,
inode->i_sb->s_bdev, iov, inode->i_sb->s_bdev, iov,
offset, nr_segs, offset, nr_segs,
ext4_get_block, NULL, NULL, 0); ext4_get_block, NULL, NULL, 0);
else { } else {
ret = blockdev_direct_IO(rw, iocb, inode, iov, ret = blockdev_direct_IO(rw, iocb, inode, iov,
offset, nr_segs, ext4_get_block); offset, nr_segs, ext4_get_block);
......
...@@ -120,6 +120,12 @@ void ext4_evict_inode(struct inode *inode) ...@@ -120,6 +120,12 @@ void ext4_evict_inode(struct inode *inode)
int err; int err;
trace_ext4_evict_inode(inode); trace_ext4_evict_inode(inode);
mutex_lock(&inode->i_mutex);
ext4_flush_completed_IO(inode);
mutex_unlock(&inode->i_mutex);
ext4_ioend_wait(inode);
if (inode->i_nlink) { if (inode->i_nlink) {
/* /*
* When journalling data dirty buffers are tracked only in the * When journalling data dirty buffers are tracked only in the
...@@ -983,6 +989,8 @@ static int ext4_journalled_write_end(struct file *file, ...@@ -983,6 +989,8 @@ static int ext4_journalled_write_end(struct file *file,
from = pos & (PAGE_CACHE_SIZE - 1); from = pos & (PAGE_CACHE_SIZE - 1);
to = from + len; to = from + len;
BUG_ON(!ext4_handle_valid(handle));
if (copied < len) { if (copied < len) {
if (!PageUptodate(page)) if (!PageUptodate(page))
copied = 0; copied = 0;
...@@ -1283,7 +1291,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, ...@@ -1283,7 +1291,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT)) else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
err = ext4_bio_write_page(&io_submit, page, err = ext4_bio_write_page(&io_submit, page,
len, mpd->wbc); len, mpd->wbc);
else else if (buffer_uninit(page_bufs)) {
ext4_set_bh_endio(page_bufs, inode);
err = block_write_full_page_endio(page,
noalloc_get_block_write,
mpd->wbc, ext4_end_io_buffer_write);
} else
err = block_write_full_page(page, err = block_write_full_page(page,
noalloc_get_block_write, mpd->wbc); noalloc_get_block_write, mpd->wbc);
...@@ -1699,6 +1712,8 @@ static int __ext4_journalled_writepage(struct page *page, ...@@ -1699,6 +1712,8 @@ static int __ext4_journalled_writepage(struct page *page,
goto out; goto out;
} }
BUG_ON(!ext4_handle_valid(handle));
ret = walk_page_buffers(handle, page_bufs, 0, len, NULL, ret = walk_page_buffers(handle, page_bufs, 0, len, NULL,
do_journal_get_write_access); do_journal_get_write_access);
...@@ -2668,8 +2683,15 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) ...@@ -2668,8 +2683,15 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
goto out; 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; 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*/ /* Add the io_end to per-inode completed io list*/
spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
......
...@@ -334,8 +334,10 @@ static int io_submit_add_bh(struct ext4_io_submit *io, ...@@ -334,8 +334,10 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
if ((io_end->num_io_pages >= MAX_IO_PAGES) && if ((io_end->num_io_pages >= MAX_IO_PAGES) &&
(io_end->pages[io_end->num_io_pages-1] != io_page)) (io_end->pages[io_end->num_io_pages-1] != io_page))
goto submit_and_retry; goto submit_and_retry;
if (buffer_uninit(bh)) if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
io->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_end->size += bh->b_size;
io->io_next_block++; io->io_next_block++;
ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh));
......
...@@ -919,7 +919,6 @@ static void ext4_i_callback(struct rcu_head *head) ...@@ -919,7 +919,6 @@ static void ext4_i_callback(struct rcu_head *head)
static void ext4_destroy_inode(struct inode *inode) static void ext4_destroy_inode(struct inode *inode)
{ {
ext4_ioend_wait(inode);
if (!list_empty(&(EXT4_I(inode)->i_orphan))) { if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
ext4_msg(inode->i_sb, KERN_ERR, ext4_msg(inode->i_sb, KERN_ERR,
"Inode %lu (%p): orphan list check failed!", "Inode %lu (%p): orphan list check failed!",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment