Add a new helper to write out the inode using the writeback code, that is including the correct dirty bit and list manipulation. A few of filesystems already opencode this, and a lot of others should be using it instead of using write_inode_now which also writes out the data. Signed-off-by: Christoph Hellwig <hch@xxxxxx> Index: linux-2.6/drivers/staging/pohmelfs/inode.c =================================================================== --- linux-2.6.orig/drivers/staging/pohmelfs/inode.c 2010-10-05 10:51:24.565005008 +0200 +++ linux-2.6/drivers/staging/pohmelfs/inode.c 2010-10-05 10:52:12.866254065 +0200 @@ -882,12 +882,8 @@ static struct inode *pohmelfs_alloc_inod static int pohmelfs_fsync(struct file *file, int datasync) { struct inode *inode = file->f_mapping->host; - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, /* sys_fsync did this */ - }; - return sync_inode(inode, &wbc); + return sync_inode_metadata(inode, 1); } ssize_t pohmelfs_write(struct file *file, const char __user *buf, Index: linux-2.6/fs/ext2/dir.c =================================================================== --- linux-2.6.orig/fs/ext2/dir.c 2010-10-05 10:51:24.574004450 +0200 +++ linux-2.6/fs/ext2/dir.c 2010-10-05 10:52:12.867253925 +0200 @@ -98,7 +98,7 @@ static int ext2_commit_chunk(struct page if (IS_DIRSYNC(dir)) { err = write_one_page(page, 1); if (!err) - err = ext2_sync_inode(dir); + err = sync_inode_metadata(dir, 1); } else { unlock_page(page); } Index: linux-2.6/fs/ext2/ext2.h =================================================================== --- linux-2.6.orig/fs/ext2/ext2.h 2010-10-05 10:51:24.581003472 +0200 +++ linux-2.6/fs/ext2/ext2.h 2010-10-05 10:52:12.871253995 +0200 @@ -120,7 +120,6 @@ extern unsigned long ext2_count_free (st extern struct inode *ext2_iget (struct super_block *, unsigned long); extern int ext2_write_inode (struct inode *, struct writeback_control *); extern void ext2_evict_inode(struct inode *); -extern int ext2_sync_inode (struct inode *); extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int); extern int ext2_setattr (struct dentry *, struct iattr *); extern void ext2_set_inode_flags(struct inode *inode); Index: linux-2.6/fs/ext2/inode.c =================================================================== --- linux-2.6.orig/fs/ext2/inode.c 2010-10-05 10:51:24.588253716 +0200 +++ linux-2.6/fs/ext2/inode.c 2010-10-05 10:52:12.874253996 +0200 @@ -1203,7 +1203,7 @@ static int ext2_setsize(struct inode *in inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; if (inode_needs_sync(inode)) { sync_mapping_buffers(inode->i_mapping); - ext2_sync_inode (inode); + sync_inode_metadata(inode, 1); } else { mark_inode_dirty(inode); } @@ -1523,15 +1523,6 @@ int ext2_write_inode(struct inode *inode return __ext2_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL); } -int ext2_sync_inode(struct inode *inode) -{ - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, /* sys_fsync did this */ - }; - return sync_inode(inode, &wbc); -} - int ext2_setattr(struct dentry *dentry, struct iattr *iattr) { struct inode *inode = dentry->d_inode; Index: linux-2.6/fs/ext2/xattr.c =================================================================== --- linux-2.6.orig/fs/ext2/xattr.c 2010-10-05 10:51:24.595254275 +0200 +++ linux-2.6/fs/ext2/xattr.c 2010-10-05 10:52:12.878253995 +0200 @@ -699,7 +699,7 @@ ext2_xattr_set2(struct inode *inode, str EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0; inode->i_ctime = CURRENT_TIME_SEC; if (IS_SYNC(inode)) { - error = ext2_sync_inode (inode); + error = sync_inode_metadata(inode, 1); /* In case sync failed due to ENOSPC the inode was actually * written (only some dirty data were not) so we just proceed * as if nothing happened and cleanup the unused block */ Index: linux-2.6/fs/fs-writeback.c =================================================================== --- linux-2.6.orig/fs/fs-writeback.c 2010-10-05 10:51:24.611023726 +0200 +++ linux-2.6/fs/fs-writeback.c 2010-10-05 10:53:24.684255876 +0200 @@ -1209,3 +1209,23 @@ int sync_inode(struct inode *inode, stru return ret; } EXPORT_SYMBOL(sync_inode); + +/** + * sync_inode - write an inode to disk + * @inode: the inode to sync + * @wait: wait for I/O to complete. + * + * Write an inode to disk and adjust it's dirty state after completion. + * + * Note: only writes the actual inode, no associated data or other metadata. + */ +int sync_inode_metadata(struct inode *inode, int wait) +{ + struct writeback_control wbc = { + .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_NONE, + .nr_to_write = 0, /* metadata-only */ + }; + + return sync_inode(inode, &wbc); +} +EXPORT_SYMBOL(sync_inode_metadata); Index: linux-2.6/fs/libfs.c =================================================================== --- linux-2.6.orig/fs/libfs.c 2010-10-05 10:51:24.618004031 +0200 +++ linux-2.6/fs/libfs.c 2010-10-05 10:52:12.887255532 +0200 @@ -892,10 +892,6 @@ EXPORT_SYMBOL_GPL(generic_fh_to_parent); */ int generic_file_fsync(struct file *file, int datasync) { - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, /* metadata-only; caller takes care of data */ - }; struct inode *inode = file->f_mapping->host; int err; int ret; @@ -906,7 +902,7 @@ int generic_file_fsync(struct file *file if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) return ret; - err = sync_inode(inode, &wbc); + err = sync_inode_metadata(inode, 1); if (ret == 0) ret = err; return ret; Index: linux-2.6/fs/nfsd/vfs.c =================================================================== --- linux-2.6.orig/fs/nfsd/vfs.c 2010-10-05 10:51:24.625004031 +0200 +++ linux-2.6/fs/nfsd/vfs.c 2010-10-05 10:52:12.892255391 +0200 @@ -286,18 +286,9 @@ commit_metadata(struct svc_fh *fhp) if (!EX_ISSYNC(fhp->fh_export)) return 0; - if (export_ops->commit_metadata) { - error = export_ops->commit_metadata(inode); - } else { - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, /* metadata only */ - }; - - error = sync_inode(inode, &wbc); - } - - return error; + if (export_ops->commit_metadata) + return export_ops->commit_metadata(inode); + return sync_inode_metadata(inode, 1); } /* Index: linux-2.6/include/linux/fs.h =================================================================== --- linux-2.6.orig/include/linux/fs.h 2010-10-05 10:51:24.641010386 +0200 +++ linux-2.6/include/linux/fs.h 2010-10-05 10:52:12.897255881 +0200 @@ -1732,6 +1732,7 @@ static inline void file_accessed(struct } int sync_inode(struct inode *inode, struct writeback_control *wbc); +int sync_inode_metadata(struct inode *inode, int wait); struct file_system_type { const char *name; Index: linux-2.6/fs/exofs/file.c =================================================================== --- linux-2.6.orig/fs/exofs/file.c 2010-10-05 10:51:24.633010177 +0200 +++ linux-2.6/fs/exofs/file.c 2010-10-05 10:52:12.899255253 +0200 @@ -46,10 +46,6 @@ static int exofs_file_fsync(struct file { int ret; struct inode *inode = filp->f_mapping->host; - struct writeback_control wbc = { - .sync_mode = WB_SYNC_ALL, - .nr_to_write = 0, /* metadata-only; caller takes care of data */ - }; struct super_block *sb; if (!(inode->i_state & I_DIRTY)) @@ -57,7 +53,7 @@ static int exofs_file_fsync(struct file if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) return 0; - ret = sync_inode(inode, &wbc); + ret = sync_inode_metadata(inode, 1); /* This is a good place to write the sb */ /* TODO: Sechedule an sb-sync on create */ -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html