aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/page-io.c
diff options
context:
space:
mode:
authorDmitry Monakhov <dmonakhov@openvz.org>2012-09-28 23:36:25 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-09-28 23:36:25 -0400
commit82e54229118785badffb4ef5ba4803df25fe007f (patch)
tree270d0afb27dce342b7508cd05bb0db45cdad089d /fs/ext4/page-io.c
parente27f41e1b789e60e7d8cc9c81fd93ca49ef31f13 (diff)
ext4: fix unwritten counter leakage
ext4_set_io_unwritten_flag() will increment i_unwritten counter, so once we mark end_io with EXT4_END_IO_UNWRITTEN we have to revert it back on error path. - add missed error checks to prevent counter leakage - ext4_end_io_nolock() will clear EXT4_END_IO_UNWRITTEN flag to signal that conversion finished. - add BUG_ON to ext4_free_end_io() to prevent similar leakage in future. Visible effect of this bug is that unaligned aio_stress may deadlock Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/page-io.c')
-rw-r--r--fs/ext4/page-io.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index de77e31cc11..99700221822 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -71,6 +71,8 @@ void ext4_free_io_end(ext4_io_end_t *io)
71 int i; 71 int i;
72 72
73 BUG_ON(!io); 73 BUG_ON(!io);
74 BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN);
75
74 if (io->page) 76 if (io->page)
75 put_page(io->page); 77 put_page(io->page);
76 for (i = 0; i < io->num_io_pages; i++) 78 for (i = 0; i < io->num_io_pages; i++)
@@ -94,6 +96,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io)
94 ssize_t size = io->size; 96 ssize_t size = io->size;
95 int ret = 0; 97 int ret = 0;
96 98
99 BUG_ON(!(io->flag & EXT4_IO_END_UNWRITTEN));
100
97 ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," 101 ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p,"
98 "list->prev 0x%p\n", 102 "list->prev 0x%p\n",
99 io, inode->i_ino, io->list.next, io->list.prev); 103 io, inode->i_ino, io->list.next, io->list.prev);
@@ -106,7 +110,7 @@ int ext4_end_io_nolock(ext4_io_end_t *io)
106 "(inode %lu, offset %llu, size %zd, error %d)", 110 "(inode %lu, offset %llu, size %zd, error %d)",
107 inode->i_ino, offset, size, ret); 111 inode->i_ino, offset, size, ret);
108 } 112 }
109 113 io->flag &= ~EXT4_IO_END_UNWRITTEN;
110 if (io->iocb) 114 if (io->iocb)
111 aio_complete(io->iocb, io->result, 0); 115 aio_complete(io->iocb, io->result, 0);
112 116