diff options
-rw-r--r-- | fs/ext4/ext4.h | 4 | ||||
-rw-r--r-- | fs/ext4/extents.c | 15 | ||||
-rw-r--r-- | fs/ext4/inode.c | 292 |
3 files changed, 155 insertions, 156 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 98760d14e2cd..f65829bbe7aa 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1066,7 +1066,7 @@ extern void ext4_set_inode_flags(struct inode *); | |||
1066 | extern void ext4_get_inode_flags(struct ext4_inode_info *); | 1066 | extern void ext4_get_inode_flags(struct ext4_inode_info *); |
1067 | extern void ext4_set_aops(struct inode *inode); | 1067 | extern void ext4_set_aops(struct inode *inode); |
1068 | extern int ext4_writepage_trans_blocks(struct inode *); | 1068 | extern int ext4_writepage_trans_blocks(struct inode *); |
1069 | extern int ext4_block_truncate_page(handle_t *handle, struct page *page, | 1069 | extern int ext4_block_truncate_page(handle_t *handle, |
1070 | struct address_space *mapping, loff_t from); | 1070 | struct address_space *mapping, loff_t from); |
1071 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); | 1071 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); |
1072 | 1072 | ||
@@ -1225,7 +1225,7 @@ extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
1225 | ext4_lblk_t iblock, | 1225 | ext4_lblk_t iblock, |
1226 | unsigned long max_blocks, struct buffer_head *bh_result, | 1226 | unsigned long max_blocks, struct buffer_head *bh_result, |
1227 | int create, int extend_disksize); | 1227 | int create, int extend_disksize); |
1228 | extern void ext4_ext_truncate(struct inode *, struct page *); | 1228 | extern void ext4_ext_truncate(struct inode *); |
1229 | extern void ext4_ext_init(struct super_block *); | 1229 | extern void ext4_ext_init(struct super_block *); |
1230 | extern void ext4_ext_release(struct super_block *); | 1230 | extern void ext4_ext_release(struct super_block *); |
1231 | extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset, | 1231 | extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset, |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index bb36a28f8ff3..b722bce7d662 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -2749,7 +2749,7 @@ out2: | |||
2749 | return err ? err : allocated; | 2749 | return err ? err : allocated; |
2750 | } | 2750 | } |
2751 | 2751 | ||
2752 | void ext4_ext_truncate(struct inode * inode, struct page *page) | 2752 | void ext4_ext_truncate(struct inode *inode) |
2753 | { | 2753 | { |
2754 | struct address_space *mapping = inode->i_mapping; | 2754 | struct address_space *mapping = inode->i_mapping; |
2755 | struct super_block *sb = inode->i_sb; | 2755 | struct super_block *sb = inode->i_sb; |
@@ -2762,18 +2762,11 @@ void ext4_ext_truncate(struct inode * inode, struct page *page) | |||
2762 | */ | 2762 | */ |
2763 | err = ext4_writepage_trans_blocks(inode) + 3; | 2763 | err = ext4_writepage_trans_blocks(inode) + 3; |
2764 | handle = ext4_journal_start(inode, err); | 2764 | handle = ext4_journal_start(inode, err); |
2765 | if (IS_ERR(handle)) { | 2765 | if (IS_ERR(handle)) |
2766 | if (page) { | ||
2767 | clear_highpage(page); | ||
2768 | flush_dcache_page(page); | ||
2769 | unlock_page(page); | ||
2770 | page_cache_release(page); | ||
2771 | } | ||
2772 | return; | 2766 | return; |
2773 | } | ||
2774 | 2767 | ||
2775 | if (page) | 2768 | if (inode->i_size & (sb->s_blocksize - 1)) |
2776 | ext4_block_truncate_page(handle, page, mapping, inode->i_size); | 2769 | ext4_block_truncate_page(handle, mapping, inode->i_size); |
2777 | 2770 | ||
2778 | down_write(&EXT4_I(inode)->i_data_sem); | 2771 | down_write(&EXT4_I(inode)->i_data_sem); |
2779 | ext4_ext_invalidate_cache(inode); | 2772 | ext4_ext_invalidate_cache(inode); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 034fc544aa66..320acb6c35bf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1239,19 +1239,20 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, | |||
1239 | to = from + len; | 1239 | to = from + len; |
1240 | 1240 | ||
1241 | retry: | 1241 | retry: |
1242 | page = __grab_cache_page(mapping, index); | ||
1243 | if (!page) | ||
1244 | return -ENOMEM; | ||
1245 | *pagep = page; | ||
1246 | |||
1247 | handle = ext4_journal_start(inode, needed_blocks); | 1242 | handle = ext4_journal_start(inode, needed_blocks); |
1248 | if (IS_ERR(handle)) { | 1243 | if (IS_ERR(handle)) { |
1249 | unlock_page(page); | ||
1250 | page_cache_release(page); | ||
1251 | ret = PTR_ERR(handle); | 1244 | ret = PTR_ERR(handle); |
1252 | goto out; | 1245 | goto out; |
1253 | } | 1246 | } |
1254 | 1247 | ||
1248 | page = __grab_cache_page(mapping, index); | ||
1249 | if (!page) { | ||
1250 | ext4_journal_stop(handle); | ||
1251 | ret = -ENOMEM; | ||
1252 | goto out; | ||
1253 | } | ||
1254 | *pagep = page; | ||
1255 | |||
1255 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 1256 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
1256 | ext4_get_block); | 1257 | ext4_get_block); |
1257 | 1258 | ||
@@ -1261,8 +1262,8 @@ retry: | |||
1261 | } | 1262 | } |
1262 | 1263 | ||
1263 | if (ret) { | 1264 | if (ret) { |
1264 | ext4_journal_stop(handle); | ||
1265 | unlock_page(page); | 1265 | unlock_page(page); |
1266 | ext4_journal_stop(handle); | ||
1266 | page_cache_release(page); | 1267 | page_cache_release(page); |
1267 | } | 1268 | } |
1268 | 1269 | ||
@@ -1291,29 +1292,6 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh) | |||
1291 | } | 1292 | } |
1292 | 1293 | ||
1293 | /* | 1294 | /* |
1294 | * Generic write_end handler for ordered and writeback ext4 journal modes. | ||
1295 | * We can't use generic_write_end, because that unlocks the page and we need to | ||
1296 | * unlock the page after ext4_journal_stop, but ext4_journal_stop must run | ||
1297 | * after block_write_end. | ||
1298 | */ | ||
1299 | static int ext4_generic_write_end(struct file *file, | ||
1300 | struct address_space *mapping, | ||
1301 | loff_t pos, unsigned len, unsigned copied, | ||
1302 | struct page *page, void *fsdata) | ||
1303 | { | ||
1304 | struct inode *inode = file->f_mapping->host; | ||
1305 | |||
1306 | copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); | ||
1307 | |||
1308 | if (pos+copied > inode->i_size) { | ||
1309 | i_size_write(inode, pos+copied); | ||
1310 | mark_inode_dirty(inode); | ||
1311 | } | ||
1312 | |||
1313 | return copied; | ||
1314 | } | ||
1315 | |||
1316 | /* | ||
1317 | * We need to pick up the new inode size which generic_commit_write gave us | 1295 | * We need to pick up the new inode size which generic_commit_write gave us |
1318 | * `file' can be NULL - eg, when called from page_symlink(). | 1296 | * `file' can be NULL - eg, when called from page_symlink(). |
1319 | * | 1297 | * |
@@ -1326,7 +1304,7 @@ static int ext4_ordered_write_end(struct file *file, | |||
1326 | struct page *page, void *fsdata) | 1304 | struct page *page, void *fsdata) |
1327 | { | 1305 | { |
1328 | handle_t *handle = ext4_journal_current_handle(); | 1306 | handle_t *handle = ext4_journal_current_handle(); |
1329 | struct inode *inode = file->f_mapping->host; | 1307 | struct inode *inode = mapping->host; |
1330 | unsigned from, to; | 1308 | unsigned from, to; |
1331 | int ret = 0, ret2; | 1309 | int ret = 0, ret2; |
1332 | 1310 | ||
@@ -1347,7 +1325,7 @@ static int ext4_ordered_write_end(struct file *file, | |||
1347 | new_i_size = pos + copied; | 1325 | new_i_size = pos + copied; |
1348 | if (new_i_size > EXT4_I(inode)->i_disksize) | 1326 | if (new_i_size > EXT4_I(inode)->i_disksize) |
1349 | EXT4_I(inode)->i_disksize = new_i_size; | 1327 | EXT4_I(inode)->i_disksize = new_i_size; |
1350 | ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, | 1328 | ret2 = generic_write_end(file, mapping, pos, len, copied, |
1351 | page, fsdata); | 1329 | page, fsdata); |
1352 | copied = ret2; | 1330 | copied = ret2; |
1353 | if (ret2 < 0) | 1331 | if (ret2 < 0) |
@@ -1356,8 +1334,6 @@ static int ext4_ordered_write_end(struct file *file, | |||
1356 | ret2 = ext4_journal_stop(handle); | 1334 | ret2 = ext4_journal_stop(handle); |
1357 | if (!ret) | 1335 | if (!ret) |
1358 | ret = ret2; | 1336 | ret = ret2; |
1359 | unlock_page(page); | ||
1360 | page_cache_release(page); | ||
1361 | 1337 | ||
1362 | return ret ? ret : copied; | 1338 | return ret ? ret : copied; |
1363 | } | 1339 | } |
@@ -1368,7 +1344,7 @@ static int ext4_writeback_write_end(struct file *file, | |||
1368 | struct page *page, void *fsdata) | 1344 | struct page *page, void *fsdata) |
1369 | { | 1345 | { |
1370 | handle_t *handle = ext4_journal_current_handle(); | 1346 | handle_t *handle = ext4_journal_current_handle(); |
1371 | struct inode *inode = file->f_mapping->host; | 1347 | struct inode *inode = mapping->host; |
1372 | int ret = 0, ret2; | 1348 | int ret = 0, ret2; |
1373 | loff_t new_i_size; | 1349 | loff_t new_i_size; |
1374 | 1350 | ||
@@ -1376,7 +1352,7 @@ static int ext4_writeback_write_end(struct file *file, | |||
1376 | if (new_i_size > EXT4_I(inode)->i_disksize) | 1352 | if (new_i_size > EXT4_I(inode)->i_disksize) |
1377 | EXT4_I(inode)->i_disksize = new_i_size; | 1353 | EXT4_I(inode)->i_disksize = new_i_size; |
1378 | 1354 | ||
1379 | ret2 = ext4_generic_write_end(file, mapping, pos, len, copied, | 1355 | ret2 = generic_write_end(file, mapping, pos, len, copied, |
1380 | page, fsdata); | 1356 | page, fsdata); |
1381 | copied = ret2; | 1357 | copied = ret2; |
1382 | if (ret2 < 0) | 1358 | if (ret2 < 0) |
@@ -1385,8 +1361,6 @@ static int ext4_writeback_write_end(struct file *file, | |||
1385 | ret2 = ext4_journal_stop(handle); | 1361 | ret2 = ext4_journal_stop(handle); |
1386 | if (!ret) | 1362 | if (!ret) |
1387 | ret = ret2; | 1363 | ret = ret2; |
1388 | unlock_page(page); | ||
1389 | page_cache_release(page); | ||
1390 | 1364 | ||
1391 | return ret ? ret : copied; | 1365 | return ret ? ret : copied; |
1392 | } | 1366 | } |
@@ -1425,10 +1399,10 @@ static int ext4_journalled_write_end(struct file *file, | |||
1425 | ret = ret2; | 1399 | ret = ret2; |
1426 | } | 1400 | } |
1427 | 1401 | ||
1402 | unlock_page(page); | ||
1428 | ret2 = ext4_journal_stop(handle); | 1403 | ret2 = ext4_journal_stop(handle); |
1429 | if (!ret) | 1404 | if (!ret) |
1430 | ret = ret2; | 1405 | ret = ret2; |
1431 | unlock_page(page); | ||
1432 | page_cache_release(page); | 1406 | page_cache_release(page); |
1433 | 1407 | ||
1434 | return ret ? ret : copied; | 1408 | return ret ? ret : copied; |
@@ -1505,12 +1479,16 @@ static int jbd2_journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) | |||
1505 | return 0; | 1479 | return 0; |
1506 | } | 1480 | } |
1507 | 1481 | ||
1482 | static int ext4_bh_unmapped_or_delay(handle_t *handle, struct buffer_head *bh) | ||
1483 | { | ||
1484 | return !buffer_mapped(bh) || buffer_delay(bh); | ||
1485 | } | ||
1486 | |||
1508 | /* | 1487 | /* |
1509 | * Note that we always start a transaction even if we're not journalling | 1488 | * Note that we don't need to start a transaction unless we're journaling |
1510 | * data. This is to preserve ordering: any hole instantiation within | 1489 | * data because we should have holes filled from ext4_page_mkwrite(). If |
1511 | * __block_write_full_page -> ext4_get_block() should be journalled | 1490 | * we are journaling data, we cannot start transaction directly because |
1512 | * along with the data so we don't crash and then get metadata which | 1491 | * transaction start ranks above page lock so we have to do some magic... |
1513 | * refers to old data. | ||
1514 | * | 1492 | * |
1515 | * In all journalling modes block_write_full_page() will start the I/O. | 1493 | * In all journalling modes block_write_full_page() will start the I/O. |
1516 | * | 1494 | * |
@@ -1554,10 +1532,8 @@ static int jbd2_journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) | |||
1554 | * disastrous. Any write() or metadata operation will sync the fs for | 1532 | * disastrous. Any write() or metadata operation will sync the fs for |
1555 | * us. | 1533 | * us. |
1556 | * | 1534 | * |
1557 | * AKPM2: if all the page's buffers are mapped to disk and !data=journal, | ||
1558 | * we don't need to open a transaction here. | ||
1559 | */ | 1535 | */ |
1560 | static int ext4_ordered_writepage(struct page *page, | 1536 | static int __ext4_ordered_writepage(struct page *page, |
1561 | struct writeback_control *wbc) | 1537 | struct writeback_control *wbc) |
1562 | { | 1538 | { |
1563 | struct inode *inode = page->mapping->host; | 1539 | struct inode *inode = page->mapping->host; |
@@ -1566,22 +1542,6 @@ static int ext4_ordered_writepage(struct page *page, | |||
1566 | int ret = 0; | 1542 | int ret = 0; |
1567 | int err; | 1543 | int err; |
1568 | 1544 | ||
1569 | J_ASSERT(PageLocked(page)); | ||
1570 | |||
1571 | /* | ||
1572 | * We give up here if we're reentered, because it might be for a | ||
1573 | * different filesystem. | ||
1574 | */ | ||
1575 | if (ext4_journal_current_handle()) | ||
1576 | goto out_fail; | ||
1577 | |||
1578 | handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode)); | ||
1579 | |||
1580 | if (IS_ERR(handle)) { | ||
1581 | ret = PTR_ERR(handle); | ||
1582 | goto out_fail; | ||
1583 | } | ||
1584 | |||
1585 | if (!page_has_buffers(page)) { | 1545 | if (!page_has_buffers(page)) { |
1586 | create_empty_buffers(page, inode->i_sb->s_blocksize, | 1546 | create_empty_buffers(page, inode->i_sb->s_blocksize, |
1587 | (1 << BH_Dirty)|(1 << BH_Uptodate)); | 1547 | (1 << BH_Dirty)|(1 << BH_Uptodate)); |
@@ -1605,54 +1565,135 @@ static int ext4_ordered_writepage(struct page *page, | |||
1605 | * and generally junk. | 1565 | * and generally junk. |
1606 | */ | 1566 | */ |
1607 | if (ret == 0) { | 1567 | if (ret == 0) { |
1608 | err = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, | 1568 | handle = ext4_journal_start(inode, |
1569 | ext4_writepage_trans_blocks(inode)); | ||
1570 | if (IS_ERR(handle)) { | ||
1571 | ret = PTR_ERR(handle); | ||
1572 | goto out_put; | ||
1573 | } | ||
1574 | |||
1575 | ret = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, | ||
1609 | NULL, jbd2_journal_dirty_data_fn); | 1576 | NULL, jbd2_journal_dirty_data_fn); |
1577 | err = ext4_journal_stop(handle); | ||
1610 | if (!ret) | 1578 | if (!ret) |
1611 | ret = err; | 1579 | ret = err; |
1612 | } | 1580 | } |
1613 | walk_page_buffers(handle, page_bufs, 0, | 1581 | out_put: |
1614 | PAGE_CACHE_SIZE, NULL, bput_one); | 1582 | walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, NULL, |
1615 | err = ext4_journal_stop(handle); | 1583 | bput_one); |
1616 | if (!ret) | ||
1617 | ret = err; | ||
1618 | return ret; | 1584 | return ret; |
1585 | } | ||
1586 | |||
1587 | static int ext4_ordered_writepage(struct page *page, | ||
1588 | struct writeback_control *wbc) | ||
1589 | { | ||
1590 | struct inode *inode = page->mapping->host; | ||
1591 | loff_t size = i_size_read(inode); | ||
1592 | loff_t len; | ||
1593 | |||
1594 | J_ASSERT(PageLocked(page)); | ||
1595 | J_ASSERT(page_has_buffers(page)); | ||
1596 | if (page->index == size >> PAGE_CACHE_SHIFT) | ||
1597 | len = size & ~PAGE_CACHE_MASK; | ||
1598 | else | ||
1599 | len = PAGE_CACHE_SIZE; | ||
1600 | BUG_ON(walk_page_buffers(NULL, page_buffers(page), 0, len, NULL, | ||
1601 | ext4_bh_unmapped_or_delay)); | ||
1602 | |||
1603 | /* | ||
1604 | * We give up here if we're reentered, because it might be for a | ||
1605 | * different filesystem. | ||
1606 | */ | ||
1607 | if (!ext4_journal_current_handle()) | ||
1608 | return __ext4_ordered_writepage(page, wbc); | ||
1619 | 1609 | ||
1620 | out_fail: | ||
1621 | redirty_page_for_writepage(wbc, page); | 1610 | redirty_page_for_writepage(wbc, page); |
1622 | unlock_page(page); | 1611 | unlock_page(page); |
1623 | return ret; | 1612 | return 0; |
1624 | } | 1613 | } |
1625 | 1614 | ||
1615 | static int __ext4_writeback_writepage(struct page *page, | ||
1616 | struct writeback_control *wbc) | ||
1617 | { | ||
1618 | struct inode *inode = page->mapping->host; | ||
1619 | |||
1620 | if (test_opt(inode->i_sb, NOBH)) | ||
1621 | return nobh_writepage(page, ext4_get_block, wbc); | ||
1622 | else | ||
1623 | return block_write_full_page(page, ext4_get_block, wbc); | ||
1624 | } | ||
1625 | |||
1626 | |||
1626 | static int ext4_writeback_writepage(struct page *page, | 1627 | static int ext4_writeback_writepage(struct page *page, |
1627 | struct writeback_control *wbc) | 1628 | struct writeback_control *wbc) |
1628 | { | 1629 | { |
1629 | struct inode *inode = page->mapping->host; | 1630 | struct inode *inode = page->mapping->host; |
1631 | loff_t size = i_size_read(inode); | ||
1632 | loff_t len; | ||
1633 | |||
1634 | J_ASSERT(PageLocked(page)); | ||
1635 | J_ASSERT(page_has_buffers(page)); | ||
1636 | if (page->index == size >> PAGE_CACHE_SHIFT) | ||
1637 | len = size & ~PAGE_CACHE_MASK; | ||
1638 | else | ||
1639 | len = PAGE_CACHE_SIZE; | ||
1640 | BUG_ON(walk_page_buffers(NULL, page_buffers(page), 0, len, NULL, | ||
1641 | ext4_bh_unmapped_or_delay)); | ||
1642 | |||
1643 | if (!ext4_journal_current_handle()) | ||
1644 | return __ext4_writeback_writepage(page, wbc); | ||
1645 | |||
1646 | redirty_page_for_writepage(wbc, page); | ||
1647 | unlock_page(page); | ||
1648 | return 0; | ||
1649 | } | ||
1650 | |||
1651 | static int __ext4_journalled_writepage(struct page *page, | ||
1652 | struct writeback_control *wbc) | ||
1653 | { | ||
1654 | struct address_space *mapping = page->mapping; | ||
1655 | struct inode *inode = mapping->host; | ||
1656 | struct buffer_head *page_bufs; | ||
1630 | handle_t *handle = NULL; | 1657 | handle_t *handle = NULL; |
1631 | int ret = 0; | 1658 | int ret = 0; |
1632 | int err; | 1659 | int err; |
1633 | 1660 | ||
1634 | if (ext4_journal_current_handle()) | 1661 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, ext4_get_block); |
1635 | goto out_fail; | 1662 | if (ret != 0) |
1663 | goto out_unlock; | ||
1664 | |||
1665 | page_bufs = page_buffers(page); | ||
1666 | walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, NULL, | ||
1667 | bget_one); | ||
1668 | /* As soon as we unlock the page, it can go away, but we have | ||
1669 | * references to buffers so we are safe */ | ||
1670 | unlock_page(page); | ||
1636 | 1671 | ||
1637 | handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode)); | 1672 | handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode)); |
1638 | if (IS_ERR(handle)) { | 1673 | if (IS_ERR(handle)) { |
1639 | ret = PTR_ERR(handle); | 1674 | ret = PTR_ERR(handle); |
1640 | goto out_fail; | 1675 | goto out; |
1641 | } | 1676 | } |
1642 | 1677 | ||
1643 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) | 1678 | ret = walk_page_buffers(handle, page_bufs, 0, |
1644 | ret = nobh_writepage(page, ext4_get_block, wbc); | 1679 | PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); |
1645 | else | ||
1646 | ret = block_write_full_page(page, ext4_get_block, wbc); | ||
1647 | 1680 | ||
1681 | err = walk_page_buffers(handle, page_bufs, 0, | ||
1682 | PAGE_CACHE_SIZE, NULL, write_end_fn); | ||
1683 | if (ret == 0) | ||
1684 | ret = err; | ||
1648 | err = ext4_journal_stop(handle); | 1685 | err = ext4_journal_stop(handle); |
1649 | if (!ret) | 1686 | if (!ret) |
1650 | ret = err; | 1687 | ret = err; |
1651 | return ret; | ||
1652 | 1688 | ||
1653 | out_fail: | 1689 | walk_page_buffers(handle, page_bufs, 0, |
1654 | redirty_page_for_writepage(wbc, page); | 1690 | PAGE_CACHE_SIZE, NULL, bput_one); |
1691 | EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; | ||
1692 | goto out; | ||
1693 | |||
1694 | out_unlock: | ||
1655 | unlock_page(page); | 1695 | unlock_page(page); |
1696 | out: | ||
1656 | return ret; | 1697 | return ret; |
1657 | } | 1698 | } |
1658 | 1699 | ||
@@ -1660,59 +1701,40 @@ static int ext4_journalled_writepage(struct page *page, | |||
1660 | struct writeback_control *wbc) | 1701 | struct writeback_control *wbc) |
1661 | { | 1702 | { |
1662 | struct inode *inode = page->mapping->host; | 1703 | struct inode *inode = page->mapping->host; |
1663 | handle_t *handle = NULL; | 1704 | loff_t size = i_size_read(inode); |
1664 | int ret = 0; | 1705 | loff_t len; |
1665 | int err; | ||
1666 | 1706 | ||
1667 | if (ext4_journal_current_handle()) | 1707 | J_ASSERT(PageLocked(page)); |
1668 | goto no_write; | 1708 | J_ASSERT(page_has_buffers(page)); |
1709 | if (page->index == size >> PAGE_CACHE_SHIFT) | ||
1710 | len = size & ~PAGE_CACHE_MASK; | ||
1711 | else | ||
1712 | len = PAGE_CACHE_SIZE; | ||
1713 | BUG_ON(walk_page_buffers(NULL, page_buffers(page), 0, len, NULL, | ||
1714 | ext4_bh_unmapped_or_delay)); | ||
1669 | 1715 | ||
1670 | handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode)); | 1716 | if (ext4_journal_current_handle()) |
1671 | if (IS_ERR(handle)) { | ||
1672 | ret = PTR_ERR(handle); | ||
1673 | goto no_write; | 1717 | goto no_write; |
1674 | } | ||
1675 | 1718 | ||
1676 | if (!page_has_buffers(page) || PageChecked(page)) { | 1719 | if (PageChecked(page)) { |
1677 | /* | 1720 | /* |
1678 | * It's mmapped pagecache. Add buffers and journal it. There | 1721 | * It's mmapped pagecache. Add buffers and journal it. There |
1679 | * doesn't seem much point in redirtying the page here. | 1722 | * doesn't seem much point in redirtying the page here. |
1680 | */ | 1723 | */ |
1681 | ClearPageChecked(page); | 1724 | ClearPageChecked(page); |
1682 | ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE, | 1725 | return __ext4_journalled_writepage(page, wbc); |
1683 | ext4_get_block); | ||
1684 | if (ret != 0) { | ||
1685 | ext4_journal_stop(handle); | ||
1686 | goto out_unlock; | ||
1687 | } | ||
1688 | ret = walk_page_buffers(handle, page_buffers(page), 0, | ||
1689 | PAGE_CACHE_SIZE, NULL, do_journal_get_write_access); | ||
1690 | |||
1691 | err = walk_page_buffers(handle, page_buffers(page), 0, | ||
1692 | PAGE_CACHE_SIZE, NULL, write_end_fn); | ||
1693 | if (ret == 0) | ||
1694 | ret = err; | ||
1695 | EXT4_I(inode)->i_state |= EXT4_STATE_JDATA; | ||
1696 | unlock_page(page); | ||
1697 | } else { | 1726 | } else { |
1698 | /* | 1727 | /* |
1699 | * It may be a page full of checkpoint-mode buffers. We don't | 1728 | * It may be a page full of checkpoint-mode buffers. We don't |
1700 | * really know unless we go poke around in the buffer_heads. | 1729 | * really know unless we go poke around in the buffer_heads. |
1701 | * But block_write_full_page will do the right thing. | 1730 | * But block_write_full_page will do the right thing. |
1702 | */ | 1731 | */ |
1703 | ret = block_write_full_page(page, ext4_get_block, wbc); | 1732 | return block_write_full_page(page, ext4_get_block, wbc); |
1704 | } | 1733 | } |
1705 | err = ext4_journal_stop(handle); | ||
1706 | if (!ret) | ||
1707 | ret = err; | ||
1708 | out: | ||
1709 | return ret; | ||
1710 | |||
1711 | no_write: | 1734 | no_write: |
1712 | redirty_page_for_writepage(wbc, page); | 1735 | redirty_page_for_writepage(wbc, page); |
1713 | out_unlock: | ||
1714 | unlock_page(page); | 1736 | unlock_page(page); |
1715 | goto out; | 1737 | return 0; |
1716 | } | 1738 | } |
1717 | 1739 | ||
1718 | static int ext4_readpage(struct file *file, struct page *page) | 1740 | static int ext4_readpage(struct file *file, struct page *page) |
@@ -1909,7 +1931,7 @@ void ext4_set_aops(struct inode *inode) | |||
1909 | * This required during truncate. We need to physically zero the tail end | 1931 | * This required during truncate. We need to physically zero the tail end |
1910 | * of that block so it doesn't yield old data if the file is later grown. | 1932 | * of that block so it doesn't yield old data if the file is later grown. |
1911 | */ | 1933 | */ |
1912 | int ext4_block_truncate_page(handle_t *handle, struct page *page, | 1934 | int ext4_block_truncate_page(handle_t *handle, |
1913 | struct address_space *mapping, loff_t from) | 1935 | struct address_space *mapping, loff_t from) |
1914 | { | 1936 | { |
1915 | ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT; | 1937 | ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT; |
@@ -1918,8 +1940,13 @@ int ext4_block_truncate_page(handle_t *handle, struct page *page, | |||
1918 | ext4_lblk_t iblock; | 1940 | ext4_lblk_t iblock; |
1919 | struct inode *inode = mapping->host; | 1941 | struct inode *inode = mapping->host; |
1920 | struct buffer_head *bh; | 1942 | struct buffer_head *bh; |
1943 | struct page *page; | ||
1921 | int err = 0; | 1944 | int err = 0; |
1922 | 1945 | ||
1946 | page = grab_cache_page(mapping, from >> PAGE_CACHE_SHIFT); | ||
1947 | if (!page) | ||
1948 | return -EINVAL; | ||
1949 | |||
1923 | blocksize = inode->i_sb->s_blocksize; | 1950 | blocksize = inode->i_sb->s_blocksize; |
1924 | length = blocksize - (offset & (blocksize - 1)); | 1951 | length = blocksize - (offset & (blocksize - 1)); |
1925 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); | 1952 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); |
@@ -2410,46 +2437,25 @@ void ext4_truncate(struct inode *inode) | |||
2410 | int n; | 2437 | int n; |
2411 | ext4_lblk_t last_block; | 2438 | ext4_lblk_t last_block; |
2412 | unsigned blocksize = inode->i_sb->s_blocksize; | 2439 | unsigned blocksize = inode->i_sb->s_blocksize; |
2413 | struct page *page; | ||
2414 | 2440 | ||
2415 | if (!ext4_can_truncate(inode)) | 2441 | if (!ext4_can_truncate(inode)) |
2416 | return; | 2442 | return; |
2417 | 2443 | ||
2418 | /* | ||
2419 | * We have to lock the EOF page here, because lock_page() nests | ||
2420 | * outside jbd2_journal_start(). | ||
2421 | */ | ||
2422 | if ((inode->i_size & (blocksize - 1)) == 0) { | ||
2423 | /* Block boundary? Nothing to do */ | ||
2424 | page = NULL; | ||
2425 | } else { | ||
2426 | page = grab_cache_page(mapping, | ||
2427 | inode->i_size >> PAGE_CACHE_SHIFT); | ||
2428 | if (!page) | ||
2429 | return; | ||
2430 | } | ||
2431 | |||
2432 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 2444 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { |
2433 | ext4_ext_truncate(inode, page); | 2445 | ext4_ext_truncate(inode); |
2434 | return; | 2446 | return; |
2435 | } | 2447 | } |
2436 | 2448 | ||
2437 | handle = start_transaction(inode); | 2449 | handle = start_transaction(inode); |
2438 | if (IS_ERR(handle)) { | 2450 | if (IS_ERR(handle)) |
2439 | if (page) { | ||
2440 | clear_highpage(page); | ||
2441 | flush_dcache_page(page); | ||
2442 | unlock_page(page); | ||
2443 | page_cache_release(page); | ||
2444 | } | ||
2445 | return; /* AKPM: return what? */ | 2451 | return; /* AKPM: return what? */ |
2446 | } | ||
2447 | 2452 | ||
2448 | last_block = (inode->i_size + blocksize-1) | 2453 | last_block = (inode->i_size + blocksize-1) |
2449 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); | 2454 | >> EXT4_BLOCK_SIZE_BITS(inode->i_sb); |
2450 | 2455 | ||
2451 | if (page) | 2456 | if (inode->i_size & (blocksize - 1)) |
2452 | ext4_block_truncate_page(handle, page, mapping, inode->i_size); | 2457 | if (ext4_block_truncate_page(handle, mapping, inode->i_size)) |
2458 | goto out_stop; | ||
2453 | 2459 | ||
2454 | n = ext4_block_to_path(inode, last_block, offsets, NULL); | 2460 | n = ext4_block_to_path(inode, last_block, offsets, NULL); |
2455 | if (n == 0) | 2461 | if (n == 0) |