summaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2008-07-11 19:27:31 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-07-11 19:27:31 -0400
commitcd1aac32923a9c8adcc0ae85e33c1ca0c5855838 (patch)
tree3d55d9249ef960a7e345969404d537e36dbd9609 /fs/ext4
parent61628a3f3a37af2bf25daf8e26fd6b76a78c4f76 (diff)
downloadlinux-stable-cd1aac32923a9c8adcc0ae85e33c1ca0c5855838.tar.gz
linux-stable-cd1aac32923a9c8adcc0ae85e33c1ca0c5855838.tar.bz2
linux-stable-cd1aac32923a9c8adcc0ae85e33c1ca0c5855838.zip
ext4: Add ordered mode support for delalloc
This provides a new ordered mode implementation which gets rid of using buffer heads to enforce the ordering between metadata change with the related data chage. Instead, in the new ordering mode, it keeps track of all of the inodes touched by each transaction on a list, and when that transaction is committed, it flushes all of the dirty pages for those inodes. In addition, the new ordered mode reverses the lock ordering of the page lock and transaction lock, which provides easier support for delayed allocation. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Mingming Cao <cmm@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/inode.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 7923336ecf94..24518b57733e 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2043,11 +2043,12 @@ static int ext4_bh_unmapped_or_delay(handle_t *handle, struct buffer_head *bh)
return !buffer_mapped(bh) || buffer_delay(bh);
}
-/* FIXME!! only support data=writeback mode */
/*
* get called vi ext4_da_writepages after taking page lock
* We may end up doing block allocation here in case
* mpage_da_map_blocks failed to allocate blocks.
+ *
+ * We also get called via journal_submit_inode_data_buffers
*/
static int ext4_da_writepage(struct page *page,
struct writeback_control *wbc)
@@ -2066,6 +2067,7 @@ static int ext4_da_writepage(struct page *page,
* ext4_da_writepages() but directly (shrink_page_list).
* We cannot easily start a transaction here so we just skip
* writing the page in case we would have to do so.
+ * We reach here also via journal_submit_inode_data_buffers
*/
size = i_size_read(inode);
@@ -2081,8 +2083,11 @@ static int ext4_da_writepage(struct page *page,
* We can't do block allocation under
* page lock without a handle . So redirty
* the page and return
+ * We may reach here when we do a journal commit
+ * via journal_submit_inode_data_buffers.
+ * If we don't have mapping block we just ignore
+ * them
*/
- BUG_ON(wbc->sync_mode != WB_SYNC_NONE);
redirty_page_for_writepage(wbc, page);
unlock_page(page);
return 0;
@@ -2097,7 +2102,6 @@ static int ext4_da_writepage(struct page *page,
return ret;
}
-
/*
* For now just follow the DIO way to estimate the max credits
* needed to write out EXT4_MAX_WRITEBACK_PAGES.
@@ -2130,7 +2134,7 @@ static int ext4_da_writepages(struct address_space *mapping,
return 0;
/*
- * Estimate the worse case needed credits to write out
+ * Estimate the worse case needed credits to write out
* EXT4_MAX_BUF_BLOCKS pages
*/
needed_blocks = EXT4_MAX_WRITEBACK_CREDITS;
@@ -2152,6 +2156,19 @@ static int ext4_da_writepages(struct address_space *mapping,
ret = PTR_ERR(handle);
goto out_writepages;
}
+ if (ext4_should_order_data(inode)) {
+ /*
+ * With ordered mode we need to add
+ * the inode to the journal handle
+ * when we do block allocation.
+ */
+ ret = ext4_jbd2_file_inode(handle, inode);
+ if (ret) {
+ ext4_journal_stop(handle);
+ goto out_writepages;
+ }
+
+ }
/*
* set the max dirty pages could be write at a time
* to fit into the reserved transaction credits
@@ -2735,7 +2752,10 @@ static const struct address_space_operations ext4_da_aops = {
void ext4_set_aops(struct inode *inode)
{
- if (ext4_should_order_data(inode))
+ if (ext4_should_order_data(inode) &&
+ test_opt(inode->i_sb, DELALLOC))
+ inode->i_mapping->a_ops = &ext4_da_aops;
+ else if (ext4_should_order_data(inode))
inode->i_mapping->a_ops = &ext4_ordered_aops;
else if (ext4_should_writeback_data(inode) &&
test_opt(inode->i_sb, DELALLOC))