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 cc55cecf9fbc..5e0faf4cda79 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1166,9 +1166,25 @@ static int walk_page_buffers( handle_t *handle,
1166static int do_journal_get_write_access(handle_t *handle, 1166static int do_journal_get_write_access(handle_t *handle,
1167 struct buffer_head *bh) 1167 struct buffer_head *bh)
1168{ 1168{
1169 int dirty = buffer_dirty(bh);
1170 int ret;
1171
1169 if (!buffer_mapped(bh) || buffer_freed(bh)) 1172 if (!buffer_mapped(bh) || buffer_freed(bh))
1170 return 0; 1173 return 0;
1171 return ext3_journal_get_write_access(handle, bh); 1174 /*
1175 * __block_prepare_write() could have dirtied some buffers. Clean
1176 * the dirty bit as jbd2_journal_get_write_access() could complain
1177 * otherwise about fs integrity issues. Setting of the dirty bit
1178 * by __block_prepare_write() isn't a real problem here as we clear
1179 * the bit before releasing a page lock and thus writeback cannot
1180 * ever write the buffer.
1181 */
1182 if (dirty)
1183 clear_buffer_dirty(bh);
1184 ret = ext3_journal_get_write_access(handle, bh);
1185 if (!ret && dirty)
1186 ret = ext3_journal_dirty_metadata(handle, bh);
1187 return ret;
1172} 1188}
1173 1189
1174/* 1190/*
@@ -1641,10 +1657,7 @@ static int ext3_writeback_writepage(struct page *page,
1641 goto out_fail; 1657 goto out_fail;
1642 } 1658 }
1643 1659
1644 if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) 1660 ret = block_write_full_page(page, ext3_get_block, wbc);
1645 ret = nobh_writepage(page, ext3_get_block, wbc);
1646 else
1647 ret = block_write_full_page(page, ext3_get_block, wbc);
1648 1661
1649 err = ext3_journal_stop(handle); 1662 err = ext3_journal_stop(handle);
1650 if (!ret) 1663 if (!ret)
@@ -1949,17 +1962,6 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
1949 length = blocksize - (offset & (blocksize - 1)); 1962 length = blocksize - (offset & (blocksize - 1));
1950 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); 1963 iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
1951 1964
1952 /*
1953 * For "nobh" option, we can only work if we don't need to
1954 * read-in the page - otherwise we create buffers to do the IO.
1955 */
1956 if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) &&
1957 ext3_should_writeback_data(inode) && PageUptodate(page)) {
1958 zero_user(page, offset, length);
1959 set_page_dirty(page);
1960 goto unlock;
1961 }
1962
1963 if (!page_has_buffers(page)) 1965 if (!page_has_buffers(page))
1964 create_empty_buffers(page, blocksize, 0); 1966 create_empty_buffers(page, blocksize, 0);
1965 1967
@@ -2311,27 +2313,6 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
2311 depth); 2313 depth);
2312 2314
2313 /* 2315 /*
2314 * We've probably journalled the indirect block several
2315 * times during the truncate. But it's no longer
2316 * needed and we now drop it from the transaction via
2317 * journal_revoke().
2318 *
2319 * That's easy if it's exclusively part of this
2320 * transaction. But if it's part of the committing
2321 * transaction then journal_forget() will simply
2322 * brelse() it. That means that if the underlying
2323 * block is reallocated in ext3_get_block(),
2324 * unmap_underlying_metadata() will find this block
2325 * and will try to get rid of it. damn, damn.
2326 *
2327 * If this block has already been committed to the
2328 * journal, a revoke record will be written. And
2329 * revoke records must be emitted *before* clearing
2330 * this block's bit in the bitmaps.
2331 */
2332 ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
2333
2334 /*
2335 * Everything below this this pointer has been 2316 * Everything below this this pointer has been
2336 * released. Now let this top-of-subtree go. 2317 * released. Now let this top-of-subtree go.
2337 * 2318 *
@@ -2354,6 +2335,31 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
2354 truncate_restart_transaction(handle, inode); 2335 truncate_restart_transaction(handle, inode);
2355 } 2336 }
2356 2337
2338 /*
2339 * We've probably journalled the indirect block several
2340 * times during the truncate. But it's no longer
2341 * needed and we now drop it from the transaction via
2342 * journal_revoke().
2343 *
2344 * That's easy if it's exclusively part of this
2345 * transaction. But if it's part of the committing
2346 * transaction then journal_forget() will simply
2347 * brelse() it. That means that if the underlying
2348 * block is reallocated in ext3_get_block(),
2349 * unmap_underlying_metadata() will find this block
2350 * and will try to get rid of it. damn, damn. Thus
2351 * we don't allow a block to be reallocated until
2352 * a transaction freeing it has fully committed.
2353 *
2354 * We also have to make sure journal replay after a
2355 * crash does not overwrite non-journaled data blocks
2356 * with old metadata when the block got reallocated for
2357 * data. Thus we have to store a revoke record for a
2358 * block in the same transaction in which we free the
2359 * block.
2360 */
2361 ext3_forget(handle, 1, inode, bh, bh->b_blocknr);
2362
2357 ext3_free_blocks(handle, inode, nr, 1); 2363 ext3_free_blocks(handle, inode, nr, 1);
2358 2364
2359 if (parent_bh) { 2365 if (parent_bh) {