|
@@ -172,10 +172,21 @@ static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
|
|
* so before we call here everything must be consistently dirtied against
|
|
* so before we call here everything must be consistently dirtied against
|
|
* this transaction.
|
|
* this transaction.
|
|
*/
|
|
*/
|
|
-static int ext3_journal_test_restart(handle_t *handle, struct inode *inode)
|
|
|
|
|
|
+static int truncate_restart_transaction(handle_t *handle, struct inode *inode)
|
|
{
|
|
{
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
jbd_debug(2, "restarting handle %p\n", handle);
|
|
jbd_debug(2, "restarting handle %p\n", handle);
|
|
- return ext3_journal_restart(handle, blocks_for_truncate(inode));
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Drop truncate_mutex to avoid deadlock with ext3_get_blocks_handle
|
|
|
|
+ * At this moment, get_block can be called only for blocks inside
|
|
|
|
+ * i_size since page cache has been already dropped and writes are
|
|
|
|
+ * blocked by i_mutex. So we can safely drop the truncate_mutex.
|
|
|
|
+ */
|
|
|
|
+ mutex_unlock(&EXT3_I(inode)->truncate_mutex);
|
|
|
|
+ ret = ext3_journal_restart(handle, blocks_for_truncate(inode));
|
|
|
|
+ mutex_lock(&EXT3_I(inode)->truncate_mutex);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2072,7 +2083,7 @@ static void ext3_clear_blocks(handle_t *handle, struct inode *inode,
|
|
ext3_journal_dirty_metadata(handle, bh);
|
|
ext3_journal_dirty_metadata(handle, bh);
|
|
}
|
|
}
|
|
ext3_mark_inode_dirty(handle, inode);
|
|
ext3_mark_inode_dirty(handle, inode);
|
|
- ext3_journal_test_restart(handle, inode);
|
|
|
|
|
|
+ truncate_restart_transaction(handle, inode);
|
|
if (bh) {
|
|
if (bh) {
|
|
BUFFER_TRACE(bh, "retaking write access");
|
|
BUFFER_TRACE(bh, "retaking write access");
|
|
ext3_journal_get_write_access(handle, bh);
|
|
ext3_journal_get_write_access(handle, bh);
|
|
@@ -2282,7 +2293,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
|
|
return;
|
|
return;
|
|
if (try_to_extend_transaction(handle, inode)) {
|
|
if (try_to_extend_transaction(handle, inode)) {
|
|
ext3_mark_inode_dirty(handle, inode);
|
|
ext3_mark_inode_dirty(handle, inode);
|
|
- ext3_journal_test_restart(handle, inode);
|
|
|
|
|
|
+ truncate_restart_transaction(handle, inode);
|
|
}
|
|
}
|
|
|
|
|
|
ext3_free_blocks(handle, inode, nr, 1);
|
|
ext3_free_blocks(handle, inode, nr, 1);
|