diff options
-rw-r--r-- | fs/jbd2/commit.c | 16 | ||||
-rw-r--r-- | include/linux/fs.h | 2 | ||||
-rw-r--r-- | mm/filemap.c | 16 |
3 files changed, 19 insertions, 15 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index b6b194ec1b4f..3c1c31321d9b 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -263,18 +263,10 @@ static int journal_finish_inode_data_buffers(journal_t *journal, | |||
263 | continue; | 263 | continue; |
264 | jinode->i_flags |= JI_COMMIT_RUNNING; | 264 | jinode->i_flags |= JI_COMMIT_RUNNING; |
265 | spin_unlock(&journal->j_list_lock); | 265 | spin_unlock(&journal->j_list_lock); |
266 | err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping); | 266 | err = filemap_fdatawait_keep_errors( |
267 | if (err) { | 267 | jinode->i_vfs_inode->i_mapping); |
268 | /* | 268 | if (!ret) |
269 | * Because AS_EIO is cleared by | 269 | ret = err; |
270 | * filemap_fdatawait_range(), set it again so | ||
271 | * that user process can get -EIO from fsync(). | ||
272 | */ | ||
273 | mapping_set_error(jinode->i_vfs_inode->i_mapping, -EIO); | ||
274 | |||
275 | if (!ret) | ||
276 | ret = err; | ||
277 | } | ||
278 | spin_lock(&journal->j_list_lock); | 270 | spin_lock(&journal->j_list_lock); |
279 | jinode->i_flags &= ~JI_COMMIT_RUNNING; | 271 | jinode->i_flags &= ~JI_COMMIT_RUNNING; |
280 | smp_mb(); | 272 | smp_mb(); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 803e5a9b2654..8ac8df1b3550 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2514,7 +2514,7 @@ extern int write_inode_now(struct inode *, int); | |||
2514 | extern int filemap_fdatawrite(struct address_space *); | 2514 | extern int filemap_fdatawrite(struct address_space *); |
2515 | extern int filemap_flush(struct address_space *); | 2515 | extern int filemap_flush(struct address_space *); |
2516 | extern int filemap_fdatawait(struct address_space *); | 2516 | extern int filemap_fdatawait(struct address_space *); |
2517 | extern void filemap_fdatawait_keep_errors(struct address_space *); | 2517 | extern int filemap_fdatawait_keep_errors(struct address_space *mapping); |
2518 | extern int filemap_fdatawait_range(struct address_space *, loff_t lstart, | 2518 | extern int filemap_fdatawait_range(struct address_space *, loff_t lstart, |
2519 | loff_t lend); | 2519 | loff_t lend); |
2520 | extern int filemap_write_and_wait(struct address_space *mapping); | 2520 | extern int filemap_write_and_wait(struct address_space *mapping); |
diff --git a/mm/filemap.c b/mm/filemap.c index 6f1be573a5e6..e5711b2728f4 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -309,6 +309,16 @@ int filemap_check_errors(struct address_space *mapping) | |||
309 | } | 309 | } |
310 | EXPORT_SYMBOL(filemap_check_errors); | 310 | EXPORT_SYMBOL(filemap_check_errors); |
311 | 311 | ||
312 | static int filemap_check_and_keep_errors(struct address_space *mapping) | ||
313 | { | ||
314 | /* Check for outstanding write errors */ | ||
315 | if (test_bit(AS_EIO, &mapping->flags)) | ||
316 | return -EIO; | ||
317 | if (test_bit(AS_ENOSPC, &mapping->flags)) | ||
318 | return -ENOSPC; | ||
319 | return 0; | ||
320 | } | ||
321 | |||
312 | /** | 322 | /** |
313 | * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range | 323 | * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range |
314 | * @mapping: address space structure to write | 324 | * @mapping: address space structure to write |
@@ -453,15 +463,17 @@ EXPORT_SYMBOL(filemap_fdatawait_range); | |||
453 | * call sites are system-wide / filesystem-wide data flushers: e.g. sync(2), | 463 | * call sites are system-wide / filesystem-wide data flushers: e.g. sync(2), |
454 | * fsfreeze(8) | 464 | * fsfreeze(8) |
455 | */ | 465 | */ |
456 | void filemap_fdatawait_keep_errors(struct address_space *mapping) | 466 | int filemap_fdatawait_keep_errors(struct address_space *mapping) |
457 | { | 467 | { |
458 | loff_t i_size = i_size_read(mapping->host); | 468 | loff_t i_size = i_size_read(mapping->host); |
459 | 469 | ||
460 | if (i_size == 0) | 470 | if (i_size == 0) |
461 | return; | 471 | return 0; |
462 | 472 | ||
463 | __filemap_fdatawait_range(mapping, 0, i_size - 1); | 473 | __filemap_fdatawait_range(mapping, 0, i_size - 1); |
474 | return filemap_check_and_keep_errors(mapping); | ||
464 | } | 475 | } |
476 | EXPORT_SYMBOL(filemap_fdatawait_keep_errors); | ||
465 | 477 | ||
466 | /** | 478 | /** |
467 | * filemap_fdatawait - wait for all under-writeback pages to complete | 479 | * filemap_fdatawait - wait for all under-writeback pages to complete |