Skip to content

Commit

Permalink
jbd2: don't clear and reset errors after waiting on writeback
Browse files Browse the repository at this point in the history
Resetting this flag is almost certainly racy, and will be problematic
with some coming changes.

Make filemap_fdatawait_keep_errors return int, but not clear the flag(s).
Have jbd2 call it instead of filemap_fdatawait and don't attempt to
re-set the error flag if it fails.

Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
  • Loading branch information
Jeff Layton committed Jul 6, 2017
1 parent 87354e5 commit 76341ca
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 15 deletions.
16 changes: 4 additions & 12 deletions fs/jbd2/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,18 +263,10 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
continue;
jinode->i_flags |= JI_COMMIT_RUNNING;
spin_unlock(&journal->j_list_lock);
err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping);
if (err) {
/*
* Because AS_EIO is cleared by
* filemap_fdatawait_range(), set it again so
* that user process can get -EIO from fsync().
*/
mapping_set_error(jinode->i_vfs_inode->i_mapping, -EIO);

if (!ret)
ret = err;
}
err = filemap_fdatawait_keep_errors(
jinode->i_vfs_inode->i_mapping);
if (!ret)
ret = err;
spin_lock(&journal->j_list_lock);
jinode->i_flags &= ~JI_COMMIT_RUNNING;
smp_mb();
Expand Down
2 changes: 1 addition & 1 deletion include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2514,7 +2514,7 @@ extern int write_inode_now(struct inode *, int);
extern int filemap_fdatawrite(struct address_space *);
extern int filemap_flush(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
extern void filemap_fdatawait_keep_errors(struct address_space *);
extern int filemap_fdatawait_keep_errors(struct address_space *mapping);
extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
loff_t lend);
extern int filemap_write_and_wait(struct address_space *mapping);
Expand Down
16 changes: 14 additions & 2 deletions mm/filemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,16 @@ int filemap_check_errors(struct address_space *mapping)
}
EXPORT_SYMBOL(filemap_check_errors);

static int filemap_check_and_keep_errors(struct address_space *mapping)
{
/* Check for outstanding write errors */
if (test_bit(AS_EIO, &mapping->flags))
return -EIO;
if (test_bit(AS_ENOSPC, &mapping->flags))
return -ENOSPC;
return 0;
}

/**
* __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
* @mapping: address space structure to write
Expand Down Expand Up @@ -453,15 +463,17 @@ EXPORT_SYMBOL(filemap_fdatawait_range);
* call sites are system-wide / filesystem-wide data flushers: e.g. sync(2),
* fsfreeze(8)
*/
void filemap_fdatawait_keep_errors(struct address_space *mapping)
int filemap_fdatawait_keep_errors(struct address_space *mapping)
{
loff_t i_size = i_size_read(mapping->host);

if (i_size == 0)
return;
return 0;

__filemap_fdatawait_range(mapping, 0, i_size - 1);
return filemap_check_and_keep_errors(mapping);
}
EXPORT_SYMBOL(filemap_fdatawait_keep_errors);

/**
* filemap_fdatawait - wait for all under-writeback pages to complete
Expand Down

0 comments on commit 76341ca

Please sign in to comment.