Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / fs / ocfs2 / alloc.c
index 0c335b51043dcf922e7c71d66a532f424131037d..f9baefc76cf9b682f49fba84fdb395c46399f17d 100644 (file)
@@ -5993,6 +5993,7 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
        struct buffer_head *data_alloc_bh = NULL;
        struct ocfs2_dinode *di;
        struct ocfs2_truncate_log *tl;
+       struct ocfs2_journal *journal = osb->journal;
 
        BUG_ON(inode_trylock(tl_inode));
 
@@ -6013,6 +6014,20 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
                goto out;
        }
 
+       /* Appending truncate log(TA) and and flushing truncate log(TF) are
+        * two separated transactions. They can be both committed but not
+        * checkpointed. If crash occurs then, both two transaction will be
+        * replayed with several already released to global bitmap clusters.
+        * Then truncate log will be replayed resulting in cluster double free.
+        */
+       jbd2_journal_lock_updates(journal->j_journal);
+       status = jbd2_journal_flush(journal->j_journal);
+       jbd2_journal_unlock_updates(journal->j_journal);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+
        data_alloc_inode = ocfs2_get_system_file_inode(osb,
                                                       GLOBAL_BITMAP_SYSTEM_INODE,
                                                       OCFS2_INVALID_SLOT);
@@ -6792,6 +6807,8 @@ void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
                              struct page *page, int zero, u64 *phys)
 {
        int ret, partial = 0;
+       loff_t start_byte = ((loff_t)page->index << PAGE_SHIFT) + from;
+       loff_t length = to - from;
 
        ret = ocfs2_map_page_blocks(page, phys, inode, from, to, 0);
        if (ret)
@@ -6811,7 +6828,8 @@ void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
        if (ret < 0)
                mlog_errno(ret);
        else if (ocfs2_should_order_data(inode)) {
-               ret = ocfs2_jbd2_file_inode(handle, inode);
+               ret = ocfs2_jbd2_inode_add_write(handle, inode,
+                                                start_byte, length);
                if (ret < 0)
                        mlog_errno(ret);
        }