aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-02-22 21:09:59 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-02-22 21:09:59 -0500
commitebd3610b110bbb18ea6f9f2aeed1e1068c537227 (patch)
treea7ecd4c6ef1d05619abeefea831e8f73ffadda11 /fs
parent05bf9e839d9de4e8a094274a0a2fd07beb47eaf1 (diff)
ext4: Fix deadlock in ext4_write_begin() and ext4_da_write_begin()
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/inode.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index cbd2ca99d113..51cdd13e1c31 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1368,6 +1368,10 @@ retry:
1368 goto out; 1368 goto out;
1369 } 1369 }
1370 1370
1371 /* We cannot recurse into the filesystem as the transaction is already
1372 * started */
1373 flags |= AOP_FLAG_NOFS;
1374
1371 page = grab_cache_page_write_begin(mapping, index, flags); 1375 page = grab_cache_page_write_begin(mapping, index, flags);
1372 if (!page) { 1376 if (!page) {
1373 ext4_journal_stop(handle); 1377 ext4_journal_stop(handle);
@@ -1377,7 +1381,7 @@ retry:
1377 *pagep = page; 1381 *pagep = page;
1378 1382
1379 ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, 1383 ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
1380 ext4_get_block); 1384 ext4_get_block);
1381 1385
1382 if (!ret && ext4_should_journal_data(inode)) { 1386 if (!ret && ext4_should_journal_data(inode)) {
1383 ret = walk_page_buffers(handle, page_buffers(page), 1387 ret = walk_page_buffers(handle, page_buffers(page),
@@ -2667,6 +2671,9 @@ retry:
2667 ret = PTR_ERR(handle); 2671 ret = PTR_ERR(handle);
2668 goto out; 2672 goto out;
2669 } 2673 }
2674 /* We cannot recurse into the filesystem as the transaction is already
2675 * started */
2676 flags |= AOP_FLAG_NOFS;
2670 2677
2671 page = grab_cache_page_write_begin(mapping, index, flags); 2678 page = grab_cache_page_write_begin(mapping, index, flags);
2672 if (!page) { 2679 if (!page) {