diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-21 09:59:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-21 09:59:41 -0400 |
commit | c063d8a60fc912ae198f054608ad461a69dc9a19 (patch) | |
tree | fb7804322f0fa7880b073a5b2a4f2bd1a01ee5c0 | |
parent | 79058c4b9ed82415d0690ce6d520252741653486 (diff) | |
parent | dccaf33fa37a1bc5d651baeb3bfeb6becb86597b (diff) |
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
-rw-r--r-- | fs/ext4/ext4_jbd2.h | 4 | ||||
-rw-r--r-- | fs/ext4/indirect.c | 9 | ||||
-rw-r--r-- | fs/ext4/inode.c | 26 | ||||
-rw-r--r-- | fs/ext4/page-io.c | 6 | ||||
-rw-r--r-- | fs/ext4/super.c | 1 |
5 files changed, 37 insertions, 9 deletions
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index bb85757689b6..5802fa1dab18 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
@@ -289,10 +289,10 @@ static inline int ext4_should_order_data(struct inode *inode) | |||
289 | 289 | ||
290 | static inline int ext4_should_writeback_data(struct inode *inode) | 290 | static inline int ext4_should_writeback_data(struct inode *inode) |
291 | { | 291 | { |
292 | if (!S_ISREG(inode->i_mode)) | ||
293 | return 0; | ||
294 | if (EXT4_JOURNAL(inode) == NULL) | 292 | if (EXT4_JOURNAL(inode) == NULL) |
295 | return 1; | 293 | return 1; |
294 | if (!S_ISREG(inode->i_mode)) | ||
295 | return 0; | ||
296 | if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) | 296 | if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) |
297 | return 0; | 297 | return 0; |
298 | if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) | 298 | if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index b8602cde5b5a..0962642119c0 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c | |||
@@ -800,12 +800,17 @@ ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, | |||
800 | } | 800 | } |
801 | 801 | ||
802 | retry: | 802 | retry: |
803 | if (rw == READ && ext4_should_dioread_nolock(inode)) | 803 | if (rw == READ && ext4_should_dioread_nolock(inode)) { |
804 | if (unlikely(!list_empty(&ei->i_completed_io_list))) { | ||
805 | mutex_lock(&inode->i_mutex); | ||
806 | ext4_flush_completed_IO(inode); | ||
807 | mutex_unlock(&inode->i_mutex); | ||
808 | } | ||
804 | ret = __blockdev_direct_IO(rw, iocb, inode, | 809 | ret = __blockdev_direct_IO(rw, iocb, inode, |
805 | inode->i_sb->s_bdev, iov, | 810 | inode->i_sb->s_bdev, iov, |
806 | offset, nr_segs, | 811 | offset, nr_segs, |
807 | ext4_get_block, NULL, NULL, 0); | 812 | ext4_get_block, NULL, NULL, 0); |
808 | else { | 813 | } else { |
809 | ret = blockdev_direct_IO(rw, iocb, inode, iov, | 814 | ret = blockdev_direct_IO(rw, iocb, inode, iov, |
810 | offset, nr_segs, ext4_get_block); | 815 | offset, nr_segs, ext4_get_block); |
811 | 816 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index d47264cafee0..c4da98a959ae 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -120,6 +120,12 @@ void ext4_evict_inode(struct inode *inode) | |||
120 | int err; | 120 | int err; |
121 | 121 | ||
122 | trace_ext4_evict_inode(inode); | 122 | trace_ext4_evict_inode(inode); |
123 | |||
124 | mutex_lock(&inode->i_mutex); | ||
125 | ext4_flush_completed_IO(inode); | ||
126 | mutex_unlock(&inode->i_mutex); | ||
127 | ext4_ioend_wait(inode); | ||
128 | |||
123 | if (inode->i_nlink) { | 129 | if (inode->i_nlink) { |
124 | /* | 130 | /* |
125 | * When journalling data dirty buffers are tracked only in the | 131 | * When journalling data dirty buffers are tracked only in the |
@@ -983,6 +989,8 @@ static int ext4_journalled_write_end(struct file *file, | |||
983 | from = pos & (PAGE_CACHE_SIZE - 1); | 989 | from = pos & (PAGE_CACHE_SIZE - 1); |
984 | to = from + len; | 990 | to = from + len; |
985 | 991 | ||
992 | BUG_ON(!ext4_handle_valid(handle)); | ||
993 | |||
986 | if (copied < len) { | 994 | if (copied < len) { |
987 | if (!PageUptodate(page)) | 995 | if (!PageUptodate(page)) |
988 | copied = 0; | 996 | copied = 0; |
@@ -1283,7 +1291,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, | |||
1283 | else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT)) | 1291 | else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT)) |
1284 | err = ext4_bio_write_page(&io_submit, page, | 1292 | err = ext4_bio_write_page(&io_submit, page, |
1285 | len, mpd->wbc); | 1293 | len, mpd->wbc); |
1286 | else | 1294 | else if (buffer_uninit(page_bufs)) { |
1295 | ext4_set_bh_endio(page_bufs, inode); | ||
1296 | err = block_write_full_page_endio(page, | ||
1297 | noalloc_get_block_write, | ||
1298 | mpd->wbc, ext4_end_io_buffer_write); | ||
1299 | } else | ||
1287 | err = block_write_full_page(page, | 1300 | err = block_write_full_page(page, |
1288 | noalloc_get_block_write, mpd->wbc); | 1301 | noalloc_get_block_write, mpd->wbc); |
1289 | 1302 | ||
@@ -1699,6 +1712,8 @@ static int __ext4_journalled_writepage(struct page *page, | |||
1699 | goto out; | 1712 | goto out; |
1700 | } | 1713 | } |
1701 | 1714 | ||
1715 | BUG_ON(!ext4_handle_valid(handle)); | ||
1716 | |||
1702 | ret = walk_page_buffers(handle, page_bufs, 0, len, NULL, | 1717 | ret = walk_page_buffers(handle, page_bufs, 0, len, NULL, |
1703 | do_journal_get_write_access); | 1718 | do_journal_get_write_access); |
1704 | 1719 | ||
@@ -2668,8 +2683,15 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) | |||
2668 | goto out; | 2683 | goto out; |
2669 | } | 2684 | } |
2670 | 2685 | ||
2671 | io_end->flag = EXT4_IO_END_UNWRITTEN; | 2686 | /* |
2687 | * It may be over-defensive here to check EXT4_IO_END_UNWRITTEN now, | ||
2688 | * but being more careful is always safe for the future change. | ||
2689 | */ | ||
2672 | inode = io_end->inode; | 2690 | inode = io_end->inode; |
2691 | if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { | ||
2692 | io_end->flag |= EXT4_IO_END_UNWRITTEN; | ||
2693 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); | ||
2694 | } | ||
2673 | 2695 | ||
2674 | /* Add the io_end to per-inode completed io list*/ | 2696 | /* Add the io_end to per-inode completed io list*/ |
2675 | spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); | 2697 | spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); |
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 430c401d0895..78839af7ce29 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -334,8 +334,10 @@ submit_and_retry: | |||
334 | if ((io_end->num_io_pages >= MAX_IO_PAGES) && | 334 | if ((io_end->num_io_pages >= MAX_IO_PAGES) && |
335 | (io_end->pages[io_end->num_io_pages-1] != io_page)) | 335 | (io_end->pages[io_end->num_io_pages-1] != io_page)) |
336 | goto submit_and_retry; | 336 | goto submit_and_retry; |
337 | if (buffer_uninit(bh)) | 337 | if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) { |
338 | io->io_end->flag |= EXT4_IO_END_UNWRITTEN; | 338 | io_end->flag |= EXT4_IO_END_UNWRITTEN; |
339 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); | ||
340 | } | ||
339 | io->io_end->size += bh->b_size; | 341 | io->io_end->size += bh->b_size; |
340 | io->io_next_block++; | 342 | io->io_next_block++; |
341 | ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); | 343 | ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 4687fea0c00f..44d0c8db2239 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -919,7 +919,6 @@ static void ext4_i_callback(struct rcu_head *head) | |||
919 | 919 | ||
920 | static void ext4_destroy_inode(struct inode *inode) | 920 | static void ext4_destroy_inode(struct inode *inode) |
921 | { | 921 | { |
922 | ext4_ioend_wait(inode); | ||
923 | if (!list_empty(&(EXT4_I(inode)->i_orphan))) { | 922 | if (!list_empty(&(EXT4_I(inode)->i_orphan))) { |
924 | ext4_msg(inode->i_sb, KERN_ERR, | 923 | ext4_msg(inode->i_sb, KERN_ERR, |
925 | "Inode %lu (%p): orphan list check failed!", | 924 | "Inode %lu (%p): orphan list check failed!", |