Skip to content

Commit

Permalink
ext4: Fix deadlock in ext4_write_begin() and ext4_da_write_begin()
Browse files Browse the repository at this point in the history
Functions ext4_write_begin() and ext4_da_write_begin() call
grab_cache_page_write_begin() without AOP_FLAG_NOFS. Thus it
can happen that page reclaim is triggered in that function
and it recurses back into the filesystem (or some other filesystem).
But this can lead to various problems as a transaction is already
started at that point. Add the necessary flag.

http://bugzilla.kernel.org/show_bug.cgi?id=11688

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
  • Loading branch information
Jan Kara authored and Theodore Ts'o committed Feb 23, 2009
1 parent 05bf9e8 commit ebd3610
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,10 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
goto out;
}

/* We cannot recurse into the filesystem as the transaction is already
* started */
flags |= AOP_FLAG_NOFS;

page = grab_cache_page_write_begin(mapping, index, flags);
if (!page) {
ext4_journal_stop(handle);
Expand All @@ -1377,7 +1381,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
*pagep = page;

ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
ext4_get_block);
ext4_get_block);

if (!ret && ext4_should_journal_data(inode)) {
ret = walk_page_buffers(handle, page_buffers(page),
Expand Down Expand Up @@ -2667,6 +2671,9 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
ret = PTR_ERR(handle);
goto out;
}
/* We cannot recurse into the filesystem as the transaction is already
* started */
flags |= AOP_FLAG_NOFS;

page = grab_cache_page_write_begin(mapping, index, flags);
if (!page) {
Expand Down

0 comments on commit ebd3610

Please sign in to comment.