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.c113
1 files changed, 74 insertions, 39 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 6ae4ecf3ce40..507d8689b111 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1767,44 +1767,47 @@ static int ext3_journalled_set_page_dirty(struct page *page)
1767} 1767}
1768 1768
1769static const struct address_space_operations ext3_ordered_aops = { 1769static const struct address_space_operations ext3_ordered_aops = {
1770 .readpage = ext3_readpage, 1770 .readpage = ext3_readpage,
1771 .readpages = ext3_readpages, 1771 .readpages = ext3_readpages,
1772 .writepage = ext3_ordered_writepage, 1772 .writepage = ext3_ordered_writepage,
1773 .sync_page = block_sync_page, 1773 .sync_page = block_sync_page,
1774 .write_begin = ext3_write_begin, 1774 .write_begin = ext3_write_begin,
1775 .write_end = ext3_ordered_write_end, 1775 .write_end = ext3_ordered_write_end,
1776 .bmap = ext3_bmap, 1776 .bmap = ext3_bmap,
1777 .invalidatepage = ext3_invalidatepage, 1777 .invalidatepage = ext3_invalidatepage,
1778 .releasepage = ext3_releasepage, 1778 .releasepage = ext3_releasepage,
1779 .direct_IO = ext3_direct_IO, 1779 .direct_IO = ext3_direct_IO,
1780 .migratepage = buffer_migrate_page, 1780 .migratepage = buffer_migrate_page,
1781 .is_partially_uptodate = block_is_partially_uptodate,
1781}; 1782};
1782 1783
1783static const struct address_space_operations ext3_writeback_aops = { 1784static const struct address_space_operations ext3_writeback_aops = {
1784 .readpage = ext3_readpage, 1785 .readpage = ext3_readpage,
1785 .readpages = ext3_readpages, 1786 .readpages = ext3_readpages,
1786 .writepage = ext3_writeback_writepage, 1787 .writepage = ext3_writeback_writepage,
1787 .sync_page = block_sync_page, 1788 .sync_page = block_sync_page,
1788 .write_begin = ext3_write_begin, 1789 .write_begin = ext3_write_begin,
1789 .write_end = ext3_writeback_write_end, 1790 .write_end = ext3_writeback_write_end,
1790 .bmap = ext3_bmap, 1791 .bmap = ext3_bmap,
1791 .invalidatepage = ext3_invalidatepage, 1792 .invalidatepage = ext3_invalidatepage,
1792 .releasepage = ext3_releasepage, 1793 .releasepage = ext3_releasepage,
1793 .direct_IO = ext3_direct_IO, 1794 .direct_IO = ext3_direct_IO,
1794 .migratepage = buffer_migrate_page, 1795 .migratepage = buffer_migrate_page,
1796 .is_partially_uptodate = block_is_partially_uptodate,
1795}; 1797};
1796 1798
1797static const struct address_space_operations ext3_journalled_aops = { 1799static const struct address_space_operations ext3_journalled_aops = {
1798 .readpage = ext3_readpage, 1800 .readpage = ext3_readpage,
1799 .readpages = ext3_readpages, 1801 .readpages = ext3_readpages,
1800 .writepage = ext3_journalled_writepage, 1802 .writepage = ext3_journalled_writepage,
1801 .sync_page = block_sync_page, 1803 .sync_page = block_sync_page,
1802 .write_begin = ext3_write_begin, 1804 .write_begin = ext3_write_begin,
1803 .write_end = ext3_journalled_write_end, 1805 .write_end = ext3_journalled_write_end,
1804 .set_page_dirty = ext3_journalled_set_page_dirty, 1806 .set_page_dirty = ext3_journalled_set_page_dirty,
1805 .bmap = ext3_bmap, 1807 .bmap = ext3_bmap,
1806 .invalidatepage = ext3_invalidatepage, 1808 .invalidatepage = ext3_invalidatepage,
1807 .releasepage = ext3_releasepage, 1809 .releasepage = ext3_releasepage,
1810 .is_partially_uptodate = block_is_partially_uptodate,
1808}; 1811};
1809 1812
1810void ext3_set_aops(struct inode *inode) 1813void ext3_set_aops(struct inode *inode)
@@ -2127,7 +2130,21 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
2127 2130
2128 if (this_bh) { 2131 if (this_bh) {
2129 BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata"); 2132 BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata");
2130 ext3_journal_dirty_metadata(handle, this_bh); 2133
2134 /*
2135 * The buffer head should have an attached journal head at this
2136 * point. However, if the data is corrupted and an indirect
2137 * block pointed to itself, it would have been detached when
2138 * the block was cleared. Check for this instead of OOPSing.
2139 */
2140 if (bh2jh(this_bh))
2141 ext3_journal_dirty_metadata(handle, this_bh);
2142 else
2143 ext3_error(inode->i_sb, "ext3_free_data",
2144 "circular indirect block detected, "
2145 "inode=%lu, block=%llu",
2146 inode->i_ino,
2147 (unsigned long long)this_bh->b_blocknr);
2131 } 2148 }
2132} 2149}
2133 2150
@@ -2253,6 +2270,19 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
2253 } 2270 }
2254} 2271}
2255 2272
2273int ext3_can_truncate(struct inode *inode)
2274{
2275 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2276 return 0;
2277 if (S_ISREG(inode->i_mode))
2278 return 1;
2279 if (S_ISDIR(inode->i_mode))
2280 return 1;
2281 if (S_ISLNK(inode->i_mode))
2282 return !ext3_inode_is_fast_symlink(inode);
2283 return 0;
2284}
2285
2256/* 2286/*
2257 * ext3_truncate() 2287 * ext3_truncate()
2258 * 2288 *
@@ -2297,12 +2327,7 @@ void ext3_truncate(struct inode *inode)
2297 unsigned blocksize = inode->i_sb->s_blocksize; 2327 unsigned blocksize = inode->i_sb->s_blocksize;
2298 struct page *page; 2328 struct page *page;
2299 2329
2300 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || 2330 if (!ext3_can_truncate(inode))
2301 S_ISLNK(inode->i_mode)))
2302 return;
2303 if (ext3_inode_is_fast_symlink(inode))
2304 return;
2305 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
2306 return; 2331 return;
2307 2332
2308 /* 2333 /*
@@ -2513,6 +2538,16 @@ static int __ext3_get_inode_loc(struct inode *inode,
2513 } 2538 }
2514 if (!buffer_uptodate(bh)) { 2539 if (!buffer_uptodate(bh)) {
2515 lock_buffer(bh); 2540 lock_buffer(bh);
2541
2542 /*
2543 * If the buffer has the write error flag, we have failed
2544 * to write out another inode in the same block. In this
2545 * case, we don't have to read the block because we may
2546 * read the old inode data successfully.
2547 */
2548 if (buffer_write_io_error(bh) && !buffer_uptodate(bh))
2549 set_buffer_uptodate(bh);
2550
2516 if (buffer_uptodate(bh)) { 2551 if (buffer_uptodate(bh)) {
2517 /* someone brought it uptodate while we waited */ 2552 /* someone brought it uptodate while we waited */
2518 unlock_buffer(bh); 2553 unlock_buffer(bh);