Skip to content

Commit

Permalink
make sure data is on disk before calling ->write_inode
Browse files Browse the repository at this point in the history
Similar to the fsync issue fixed a while ago in commit
2daea67 we need to write for data to
actually hit the disk before writing out the metadata to guarantee
data integrity for filesystems that modify the inode in the data I/O
completion path.  Currently XFS and NFS handle this manually, and AFS
has a write_inode method that does nothing but waiting for data, while
others are possibly missing out on this.

Fortunately this change has a lot less impact than the fsync change
as none of the write_inode methods starts data writeout of any form
by itself.

Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Christoph Hellwig authored and Al Viro committed Mar 5, 2010
1 parent 64ba992 commit 26821ed
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 38 deletions.
1 change: 0 additions & 1 deletion fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,6 @@ extern int afs_write_end(struct file *file, struct address_space *mapping,
struct page *page, void *fsdata);
extern int afs_writepage(struct page *, struct writeback_control *);
extern int afs_writepages(struct address_space *, struct writeback_control *);
extern int afs_write_inode(struct inode *, int);
extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
extern ssize_t afs_file_write(struct kiocb *, const struct iovec *,
unsigned long, loff_t);
Expand Down
1 change: 0 additions & 1 deletion fs/afs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ struct file_system_type afs_fs_type = {
static const struct super_operations afs_super_ops = {
.statfs = afs_statfs,
.alloc_inode = afs_alloc_inode,
.write_inode = afs_write_inode,
.destroy_inode = afs_destroy_inode,
.clear_inode = afs_clear_inode,
.put_super = afs_put_super,
Expand Down
21 changes: 0 additions & 21 deletions fs/afs/write.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,27 +584,6 @@ int afs_writepages(struct address_space *mapping,
return ret;
}

/*
* write an inode back
*/
int afs_write_inode(struct inode *inode, int sync)
{
struct afs_vnode *vnode = AFS_FS_I(inode);
int ret;

_enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);

ret = 0;
if (sync) {
ret = filemap_fdatawait(inode->i_mapping);
if (ret < 0)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
}

_leave(" = %d", ret);
return ret;
}

/*
* completion of write to server
*/
Expand Down
15 changes: 10 additions & 5 deletions fs/fs-writeback.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,15 +461,20 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)

ret = do_writepages(mapping, wbc);

/* Don't write the inode if only I_DIRTY_PAGES was set */
if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
int err = write_inode(inode, wait);
/*
* Make sure to wait on the data before writing out the metadata.
* This is important for filesystems that modify metadata on data
* I/O completion.
*/
if (wait) {
int err = filemap_fdatawait(mapping);
if (ret == 0)
ret = err;
}

if (wait) {
int err = filemap_fdatawait(mapping);
/* Don't write the inode if only I_DIRTY_PAGES was set */
if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
int err = write_inode(inode, wait);
if (ret == 0)
ret = err;
}
Expand Down
7 changes: 1 addition & 6 deletions fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,7 @@ int nfs_write_inode(struct inode *inode, int sync)
{
int ret;

if (sync) {
ret = filemap_fdatawait(inode->i_mapping);
if (ret == 0)
ret = nfs_commit_inode(inode, FLUSH_SYNC);
} else
ret = nfs_commit_inode(inode, 0);
ret = nfs_commit_inode(inode, sync ? FLUSH_SYNC : 0);
if (ret >= 0)
return 0;
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
Expand Down
4 changes: 0 additions & 4 deletions fs/xfs/linux-2.6/xfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1075,10 +1075,6 @@ xfs_fs_write_inode(
return XFS_ERROR(EIO);

if (sync) {
error = xfs_wait_on_pages(ip, 0, -1);
if (error)
goto out;

/*
* Make sure the inode has hit stable storage. By using the
* log and the fsync transactions we reduce the IOs we have
Expand Down

0 comments on commit 26821ed

Please sign in to comment.