diff options
Diffstat (limited to 'fs/ext3/inode.c')
-rw-r--r-- | fs/ext3/inode.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 6ae4ecf3ce40..3bf07d70b914 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -2127,7 +2127,21 @@ static void ext3_free_data(handle_t *handle, struct inode *inode, | |||
2127 | 2127 | ||
2128 | if (this_bh) { | 2128 | if (this_bh) { |
2129 | BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata"); | 2129 | BUFFER_TRACE(this_bh, "call ext3_journal_dirty_metadata"); |
2130 | ext3_journal_dirty_metadata(handle, this_bh); | 2130 | |
2131 | /* | ||
2132 | * The buffer head should have an attached journal head at this | ||
2133 | * point. However, if the data is corrupted and an indirect | ||
2134 | * block pointed to itself, it would have been detached when | ||
2135 | * the block was cleared. Check for this instead of OOPSing. | ||
2136 | */ | ||
2137 | if (bh2jh(this_bh)) | ||
2138 | ext3_journal_dirty_metadata(handle, this_bh); | ||
2139 | else | ||
2140 | ext3_error(inode->i_sb, "ext3_free_data", | ||
2141 | "circular indirect block detected, " | ||
2142 | "inode=%lu, block=%llu", | ||
2143 | inode->i_ino, | ||
2144 | (unsigned long long)this_bh->b_blocknr); | ||
2131 | } | 2145 | } |
2132 | } | 2146 | } |
2133 | 2147 | ||
@@ -2253,6 +2267,19 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode, | |||
2253 | } | 2267 | } |
2254 | } | 2268 | } |
2255 | 2269 | ||
2270 | int ext3_can_truncate(struct inode *inode) | ||
2271 | { | ||
2272 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
2273 | return 0; | ||
2274 | if (S_ISREG(inode->i_mode)) | ||
2275 | return 1; | ||
2276 | if (S_ISDIR(inode->i_mode)) | ||
2277 | return 1; | ||
2278 | if (S_ISLNK(inode->i_mode)) | ||
2279 | return !ext3_inode_is_fast_symlink(inode); | ||
2280 | return 0; | ||
2281 | } | ||
2282 | |||
2256 | /* | 2283 | /* |
2257 | * ext3_truncate() | 2284 | * ext3_truncate() |
2258 | * | 2285 | * |
@@ -2297,12 +2324,7 @@ void ext3_truncate(struct inode *inode) | |||
2297 | unsigned blocksize = inode->i_sb->s_blocksize; | 2324 | unsigned blocksize = inode->i_sb->s_blocksize; |
2298 | struct page *page; | 2325 | struct page *page; |
2299 | 2326 | ||
2300 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 2327 | 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; | 2328 | return; |
2307 | 2329 | ||
2308 | /* | 2330 | /* |
@@ -2513,6 +2535,16 @@ static int __ext3_get_inode_loc(struct inode *inode, | |||
2513 | } | 2535 | } |
2514 | if (!buffer_uptodate(bh)) { | 2536 | if (!buffer_uptodate(bh)) { |
2515 | lock_buffer(bh); | 2537 | lock_buffer(bh); |
2538 | |||
2539 | /* | ||
2540 | * If the buffer has the write error flag, we have failed | ||
2541 | * to write out another inode in the same block. In this | ||
2542 | * case, we don't have to read the block because we may | ||
2543 | * read the old inode data successfully. | ||
2544 | */ | ||
2545 | if (buffer_write_io_error(bh) && !buffer_uptodate(bh)) | ||
2546 | set_buffer_uptodate(bh); | ||
2547 | |||
2516 | if (buffer_uptodate(bh)) { | 2548 | if (buffer_uptodate(bh)) { |
2517 | /* someone brought it uptodate while we waited */ | 2549 | /* someone brought it uptodate while we waited */ |
2518 | unlock_buffer(bh); | 2550 | unlock_buffer(bh); |