Skip to content

Commit

Permalink
exofs: simple fsync race fix
Browse files Browse the repository at this point in the history
It is incorrect to test inode dirty bits without participating in the inode
writeback protocol. Inode writeback sets I_SYNC and clears I_DIRTY_?, then
writes out the particular bits, then clears I_SYNC when it is done. BTW. it
may not completely write all pages out, so I_DIRTY_PAGES would get set
again.

This is a standard pattern used throughout the kernel's writeback caches
(I_SYNC ~= I_WRITEBACK, if that makes it clearer).

And so it is not possible to determine an inode's dirty status just by
checking I_DIRTY bits. Especially not for the purpose of data integrity
syncs.

Missing the check for these bits means that fsync can complete while
writeback to the inode is underway. Inode writeback functions get this
right, so call into them rather than try to shortcut things by testing
dirty state improperly.

Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
  • Loading branch information
Nick Piggin authored and Boaz Harrosh committed Mar 15, 2011
1 parent a8f1418 commit 97178b7
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 6 deletions.
5 changes: 0 additions & 5 deletions fs/exofs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ static int exofs_file_fsync(struct file *filp, int datasync)
struct inode *inode = filp->f_mapping->host;
struct super_block *sb;

if (!(inode->i_state & I_DIRTY))
return 0;
if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
return 0;

ret = sync_inode_metadata(inode, 1);

/* This is a good place to write the sb */
Expand Down
3 changes: 2 additions & 1 deletion fs/exofs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1290,7 +1290,8 @@ static int exofs_update_inode(struct inode *inode, int do_sync)

int exofs_write_inode(struct inode *inode, struct writeback_control *wbc)
{
return exofs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
/* FIXME: fix fsync and use wbc->sync_mode == WB_SYNC_ALL */
return exofs_update_inode(inode, 1);
}

/*
Expand Down

0 comments on commit 97178b7

Please sign in to comment.