aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3/inode.c')
-rw-r--r--fs/ext3/inode.c80
1 files changed, 43 insertions, 37 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 735f0190ec2a..001eb0e2d48e 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1149,9 +1149,25 @@ static int walk_page_buffers( handle_t *handle,
1149static int do_journal_get_write_access(handle_t *handle, 1149static int do_journal_get_write_access(handle_t *handle,
1150 struct buffer_head *bh) 1150 struct buffer_head *bh)
1151{ 1151{
1152 int dirty = buffer_dirty(bh);
1153 int ret;
1154
1152 if (!buffer_mapped(bh) || buffer_freed(bh)) 1155 if (!buffer_mapped(bh) || buffer_freed(bh))
1153 return 0; 1156 return 0;
1154 return ext3_journal_get_write_access(handle, bh); 1157 /*
1158 * __block_prepare_write() could have dirtied some buffers. Clean
1159 * the dirty bit as jbd2_journal_get_write_access() could complain
1160 * otherwise about fs integrity issues. Setting of the dirty bit
1161 * by __block_prepare_write() isn't a real problem here as we clear
1162 * the bit before releasing a page lock and thus writeback cannot
1163 * ever write the buffer.
1164 */
1165 if (dirty)
1166 clear_buffer_dirty(bh);
1167 ret = ext3_journal_get_write_access(handle, bh);
1168 if (!ret && dirty)
1169 ret = ext3_journal_dirty_metadata(handle, bh);
1170 return ret;
1155} 1171}
1156 1172
1157/* 1173/*
@@ -1625,10 +1641,7 @@ static int ext3_writeback_writepage(struct page *page,
1625 goto out_fail; 1641 goto out_fail;
1626 } 1642 }
1627 1643
1628 if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) 1644 ret = block_write_full_page(page, ext3_get_block, wbc);
1629 ret = nobh_writepage(page, ext3_get_block, wbc);
1630 else
1631 ret = block_write_full_page(page, ext3_get_block, wbc);
1632 1645
1633 err = ext3_journal_stop(handle); 1646 err = ext3_journal_stop(handle);
1634 if (!ret) 1647 if (!ret)
@@ -1922,17 +1935,6 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
1922 length = blocksize - (offset & (blocksize - 1)); 1935 length = blocksize - (offset & (blocksize - 1));
1923 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); 1936 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
1924 1937
1925 /*
1926 * For "nobh" option, we can only work if we don't need to
1927 * read-in the page - otherwise we create buffers to do the IO.
1928 */
1929 if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) &&
1930 ext3_should_writeback_data(inode) && PageUptodate(page)) {
1931 zero_user(page, offset, length);
1932 set_page_dirty(page);
1933 goto unlock;
1934 }
1935
1936 if (!page_has_buffers(page)) 1938 if (!page_has_buffers(page))
1937 create_empty_buffers(page, blocksize, 0); 1939 create_empty_buffers(page, blocksize, 0);
1938 1940
@@ -2284,27 +2286,6 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
2284 depth); 2286 depth);
2285 2287
2286 /* 2288 /*
2287 * We've probably journalled the indirect block several
2288 * times during the truncate. But it's no longer
2289 * needed and we now drop it from the transaction via
2290 * journal_revoke().
2291 *
2292 * That's easy if it's exclusively part of this
2293 * transaction. But if it's part of the committing
2294 * transaction then journal_forget() will simply
2295 * brelse() it. That means that if the underlying
2296 * block is reallocated in ext3_get_block(),
2297 * unmap_underlying_metadata() will find this block
2298 * and will try to get rid of it. damn, damn.
2299 *
2300 * If this block has already been committed to the
2301 * journal, a revoke record will be written. And
2302 * revoke records must be emitted *before* clearing
2303 * this block's bit in the bitmaps.
2304 */
2305 ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
2306
2307 /*
2308 * Everything below this this pointer has been 2289 * Everything below this this pointer has been
2309 * released. Now let this top-of-subtree go. 2290 * released. Now let this top-of-subtree go.
2310 * 2291 *
@@ -2327,6 +2308,31 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
2327 truncate_restart_transaction(handle, inode); 2308 truncate_restart_transaction(handle, inode);
2328 } 2309 }
2329 2310
2311 /*
2312 * We've probably journalled the indirect block several
2313 * times during the truncate. But it's no longer
2314 * needed and we now drop it from the transaction via
2315 * journal_revoke().
2316 *
2317 * That's easy if it's exclusively part of this
2318 * transaction. But if it's part of the committing
2319 * transaction then journal_forget() will simply
2320 * brelse() it. That means that if the underlying
2321 * block is reallocated in ext3_get_block(),
2322 * unmap_underlying_metadata() will find this block
2323 * and will try to get rid of it. damn, damn. Thus
2324 * we don't allow a block to be reallocated until
2325 * a transaction freeing it has fully committed.
2326 *
2327 * We also have to make sure journal replay after a
2328 * crash does not overwrite non-journaled data blocks
2329 * with old metadata when the block got reallocated for
2330 * data. Thus we have to store a revoke record for a
2331 * block in the same transaction in which we free the
2332 * block.
2333 */
2334 ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
2335
2330 ext3_free_blocks(handle, inode, nr, 1); 2336 ext3_free_blocks(handle, inode, nr, 1);
2331 2337
2332 if (parent_bh) { 2338 if (parent_bh) {