summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/commit.c16
-rw-r--r--include/linux/fs.h2
-rw-r--r--mm/filemap.c16
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);
2514extern int filemap_fdatawrite(struct address_space *); 2514extern int filemap_fdatawrite(struct address_space *);
2515extern int filemap_flush(struct address_space *); 2515extern int filemap_flush(struct address_space *);
2516extern int filemap_fdatawait(struct address_space *); 2516extern int filemap_fdatawait(struct address_space *);
2517extern void filemap_fdatawait_keep_errors(struct address_space *); 2517extern int filemap_fdatawait_keep_errors(struct address_space *mapping);
2518extern int filemap_fdatawait_range(struct address_space *, loff_t lstart, 2518extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
2519 loff_t lend); 2519 loff_t lend);
2520extern int filemap_write_and_wait(struct address_space *mapping); 2520extern 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}
310EXPORT_SYMBOL(filemap_check_errors); 310EXPORT_SYMBOL(filemap_check_errors);
311 311
312static 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 */
456void filemap_fdatawait_keep_errors(struct address_space *mapping) 466int 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}
476EXPORT_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