Tell the filesystem if we just updated timestamp (I_DIRTY_SYNC) or anything else, so that the filesystem can track internally if it needs to push out a transaction for fdatasync or not. This is just the prototype change with no user for it yet. I plan to push large XFS changes for the next merge window, and getting this trivial infrastructure in this window would help a lot to avoid tree interdependencies. Also remove incorrect comments that ->dirty_inode can't block. That has been changed a long time ago, and many implementations rely on it. Signed-off-by: Christoph Hellwig <hch@xxxxxx> Index: linux-2.6/fs/fs-writeback.c =================================================================== --- linux-2.6.orig/fs/fs-writeback.c 2011-05-27 11:27:24.095999307 +0200 +++ linux-2.6/fs/fs-writeback.c 2011-05-27 11:29:12.331995479 +0200 @@ -1007,9 +1007,6 @@ static noinline void block_dump___mark_i * In short, make sure you hash any inodes _before_ you start marking * them dirty. * - * This function *must* be atomic for the I_DIRTY_PAGES case - - * set_page_dirty() is called under spinlock in several places. - * * Note that for blockdevs, inode->dirtied_when represents the dirtying time of * the block-special inode (/dev/hda1) itself. And the ->dirtied_when field of * the kernel-internal blockdev inode represents the dirtying time of the @@ -1028,7 +1025,7 @@ void __mark_inode_dirty(struct inode *in */ if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { if (sb->s_op->dirty_inode) - sb->s_op->dirty_inode(inode); + sb->s_op->dirty_inode(inode, flags); } /* Index: linux-2.6/Documentation/filesystems/Locking =================================================================== --- linux-2.6.orig/Documentation/filesystems/Locking 2011-05-27 11:27:59.741542855 +0200 +++ linux-2.6/Documentation/filesystems/Locking 2011-05-27 11:28:58.928496469 +0200 @@ -104,7 +104,7 @@ of the locking scheme for directory oper prototypes: struct inode *(*alloc_inode)(struct super_block *sb); void (*destroy_inode)(struct inode *); - void (*dirty_inode) (struct inode *); + void (*dirty_inode) (struct inode *, int flags); int (*write_inode) (struct inode *, struct writeback_control *wbc); int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); @@ -126,7 +126,7 @@ locking rules: s_umount alloc_inode: destroy_inode: -dirty_inode: (must not sleep) +dirty_inode: write_inode: drop_inode: !!!inode->i_lock!!! evict_inode: Index: linux-2.6/Documentation/filesystems/vfs.txt =================================================================== --- linux-2.6.orig/Documentation/filesystems/vfs.txt 2011-05-27 11:27:59.761496958 +0200 +++ linux-2.6/Documentation/filesystems/vfs.txt 2011-05-27 11:29:09.092496019 +0200 @@ -211,7 +211,7 @@ struct super_operations { struct inode *(*alloc_inode)(struct super_block *sb); void (*destroy_inode)(struct inode *); - void (*dirty_inode) (struct inode *); + void (*dirty_inode) (struct inode *, int flags); int (*write_inode) (struct inode *, int); void (*drop_inode) (struct inode *); void (*delete_inode) (struct inode *); Index: linux-2.6/include/linux/fs.h =================================================================== --- linux-2.6.orig/include/linux/fs.h 2011-05-27 11:27:59.721495799 +0200 +++ linux-2.6/include/linux/fs.h 2011-05-27 11:28:44.479995912 +0200 @@ -1618,7 +1618,7 @@ struct super_operations { struct inode *(*alloc_inode)(struct super_block *sb); void (*destroy_inode)(struct inode *); - void (*dirty_inode) (struct inode *); + void (*dirty_inode) (struct inode *, int flags); int (*write_inode) (struct inode *, struct writeback_control *wbc); int (*drop_inode) (struct inode *); void (*evict_inode) (struct inode *); Index: linux-2.6/fs/nilfs2/inode.c =================================================================== --- linux-2.6.orig/fs/nilfs2/inode.c 2011-05-27 11:31:32.520496715 +0200 +++ linux-2.6/fs/nilfs2/inode.c 2011-05-27 11:31:46.960009779 +0200 @@ -917,7 +917,7 @@ int nilfs_mark_inode_dirty(struct inode * construction. This function can be called both as a single operation * and as a part of indivisible file operations. */ -void nilfs_dirty_inode(struct inode *inode) +void nilfs_dirty_inode(struct inode *inode, int flags) { struct nilfs_transaction_info ti; struct nilfs_mdt_info *mdi = NILFS_MDT(inode); Index: linux-2.6/fs/nilfs2/nilfs.h =================================================================== --- linux-2.6.orig/fs/nilfs2/nilfs.h 2011-05-27 11:31:32.508495838 +0200 +++ linux-2.6/fs/nilfs2/nilfs.h 2011-05-27 11:31:35.907997780 +0200 @@ -269,7 +269,7 @@ int nilfs_load_inode_block(struct inode extern int nilfs_inode_dirty(struct inode *); int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty); extern int nilfs_mark_inode_dirty(struct inode *); -extern void nilfs_dirty_inode(struct inode *); +extern void nilfs_dirty_inode(struct inode *, int flags); int nilfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, __u64 start, __u64 len); Index: linux-2.6/fs/reiserfs/super.c =================================================================== --- linux-2.6.orig/fs/reiserfs/super.c 2011-05-27 11:31:02.676498799 +0200 +++ linux-2.6/fs/reiserfs/super.c 2011-05-27 11:31:10.868005094 +0200 @@ -568,7 +568,7 @@ static void destroy_inodecache(void) } /* we don't mark inodes dirty, we just log them */ -static void reiserfs_dirty_inode(struct inode *inode) +static void reiserfs_dirty_inode(struct inode *inode, int flags) { struct reiserfs_transaction_handle th; Index: linux-2.6/fs/ubifs/super.c =================================================================== --- linux-2.6.orig/fs/ubifs/super.c 2011-05-27 11:30:07.577495742 +0200 +++ linux-2.6/fs/ubifs/super.c 2011-05-27 11:30:59.915995795 +0200 @@ -382,7 +382,7 @@ done: end_writeback(inode); } -static void ubifs_dirty_inode(struct inode *inode) +static void ubifs_dirty_inode(struct inode *inode, int flags) { struct ubifs_inode *ui = ubifs_inode(inode); Index: linux-2.6/fs/xfs/linux-2.6/xfs_super.c =================================================================== --- linux-2.6.orig/fs/xfs/linux-2.6/xfs_super.c 2011-05-27 11:29:57.717495573 +0200 +++ linux-2.6/fs/xfs/linux-2.6/xfs_super.c 2011-05-27 11:30:04.340520267 +0200 @@ -925,7 +925,8 @@ xfs_fs_inode_init_once( */ STATIC void xfs_fs_dirty_inode( - struct inode *inode) + struct inode *inode, + int flags) { barrier(); XFS_I(inode)->i_update_core = 1; Index: linux-2.6/fs/btrfs/ctree.h =================================================================== --- linux-2.6.orig/fs/btrfs/ctree.h 2011-05-27 11:33:40.740496200 +0200 +++ linux-2.6/fs/btrfs/ctree.h 2011-05-27 11:33:44.203996210 +0200 @@ -2522,7 +2522,7 @@ int btrfs_readpage(struct file *file, st void btrfs_evict_inode(struct inode *inode); void btrfs_put_inode(struct inode *inode); int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); -void btrfs_dirty_inode(struct inode *inode); +void btrfs_dirty_inode(struct inode *inode, int flags); struct inode *btrfs_alloc_inode(struct super_block *sb); void btrfs_destroy_inode(struct inode *inode); int btrfs_drop_inode(struct inode *inode); Index: linux-2.6/fs/btrfs/inode.c =================================================================== --- linux-2.6.orig/fs/btrfs/inode.c 2011-05-27 11:33:40.760498529 +0200 +++ linux-2.6/fs/btrfs/inode.c 2011-05-27 11:34:02.476495919 +0200 @@ -4396,7 +4396,7 @@ int btrfs_write_inode(struct inode *inod * FIXME, needs more benchmarking...there are no reasons other than performance * to keep or drop this code. */ -void btrfs_dirty_inode(struct inode *inode) +void btrfs_dirty_inode(struct inode *inode, int flags) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; Index: linux-2.6/fs/ext3/inode.c =================================================================== --- linux-2.6.orig/fs/ext3/inode.c 2011-05-27 11:34:27.528495466 +0200 +++ linux-2.6/fs/ext3/inode.c 2011-05-27 11:34:56.315996511 +0200 @@ -3392,7 +3392,7 @@ int ext3_mark_inode_dirty(handle_t *hand * so would cause a commit on atime updates, which we don't bother doing. * We handle synchronous inodes at the highest possible level. */ -void ext3_dirty_inode(struct inode *inode) +void ext3_dirty_inode(struct inode *inode, int flags) { handle_t *current_handle = ext3_journal_current_handle(); handle_t *handle; Index: linux-2.6/fs/ext4/ext4.h =================================================================== --- linux-2.6.orig/fs/ext4/ext4.h 2011-05-27 11:35:05.391995664 +0200 +++ linux-2.6/fs/ext4/ext4.h 2011-05-27 11:35:08.383998030 +0200 @@ -1813,7 +1813,7 @@ extern int ext4_getattr(struct vfsmount extern void ext4_evict_inode(struct inode *); extern void ext4_clear_inode(struct inode *); extern int ext4_sync_inode(handle_t *, struct inode *); -extern void ext4_dirty_inode(struct inode *); +extern void ext4_dirty_inode(struct inode *, int); extern int ext4_change_inode_journal_flag(struct inode *, int); extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *); extern int ext4_can_truncate(struct inode *inode); Index: linux-2.6/fs/ext4/inode.c =================================================================== --- linux-2.6.orig/fs/ext4/inode.c 2011-05-27 11:35:15.328495622 +0200 +++ linux-2.6/fs/ext4/inode.c 2011-05-27 11:35:32.827997231 +0200 @@ -5733,7 +5733,7 @@ int ext4_mark_inode_dirty(handle_t *hand * so would cause a commit on atime updates, which we don't bother doing. * We handle synchronous inodes at the highest possible level. */ -void ext4_dirty_inode(struct inode *inode) +void ext4_dirty_inode(struct inode *inode, int flags) { handle_t *handle; Index: linux-2.6/fs/jffs2/fs.c =================================================================== --- linux-2.6.orig/fs/jffs2/fs.c 2011-05-27 11:33:04.399999068 +0200 +++ linux-2.6/fs/jffs2/fs.c 2011-05-27 11:33:20.943996236 +0200 @@ -357,7 +357,7 @@ error: return ERR_PTR(ret); } -void jffs2_dirty_inode(struct inode *inode) +void jffs2_dirty_inode(struct inode *inode, int flags) { struct iattr iattr; Index: linux-2.6/fs/jffs2/os-linux.h =================================================================== --- linux-2.6.orig/fs/jffs2/os-linux.h 2011-05-27 11:33:04.381496653 +0200 +++ linux-2.6/fs/jffs2/os-linux.h 2011-05-27 11:33:08.636328827 +0200 @@ -172,7 +172,7 @@ int jffs2_setattr (struct dentry *, stru int jffs2_do_setattr (struct inode *, struct iattr *); struct inode *jffs2_iget(struct super_block *, unsigned long); void jffs2_evict_inode (struct inode *); -void jffs2_dirty_inode(struct inode *inode); +void jffs2_dirty_inode(struct inode *inode, int flags); struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_inode *ri); int jffs2_statfs (struct dentry *, struct kstatfs *); Index: linux-2.6/fs/jfs/inode.c =================================================================== --- linux-2.6.orig/fs/jfs/inode.c 2011-05-27 11:32:34.001495791 +0200 +++ linux-2.6/fs/jfs/inode.c 2011-05-27 11:32:43.200496448 +0200 @@ -173,7 +173,7 @@ void jfs_evict_inode(struct inode *inode dquot_drop(inode); } -void jfs_dirty_inode(struct inode *inode) +void jfs_dirty_inode(struct inode *inode, int flags) { static int noisy = 5; Index: linux-2.6/fs/jfs/jfs_inode.h =================================================================== --- linux-2.6.orig/fs/jfs/jfs_inode.h 2011-05-27 11:32:33.981496315 +0200 +++ linux-2.6/fs/jfs/jfs_inode.h 2011-05-27 11:32:38.368496824 +0200 @@ -28,7 +28,7 @@ extern struct inode *jfs_iget(struct sup extern int jfs_commit_inode(struct inode *, int); extern int jfs_write_inode(struct inode *, struct writeback_control *); extern void jfs_evict_inode(struct inode *); -extern void jfs_dirty_inode(struct inode *); +extern void jfs_dirty_inode(struct inode *, int); extern void jfs_truncate(struct inode *); extern void jfs_truncate_nolock(struct inode *, loff_t); extern void jfs_free_zero_link(struct inode *); Index: linux-2.6/include/linux/ext3_fs.h =================================================================== --- linux-2.6.orig/include/linux/ext3_fs.h 2011-05-27 11:34:27.512498526 +0200 +++ linux-2.6/include/linux/ext3_fs.h 2011-05-27 11:34:30.700053104 +0200 @@ -909,7 +909,7 @@ extern int ext3_setattr (struct dentry extern void ext3_evict_inode (struct inode *); extern int ext3_sync_inode (handle_t *, struct inode *); extern void ext3_discard_reservation (struct inode *); -extern void ext3_dirty_inode(struct inode *); +extern void ext3_dirty_inode(struct inode *, int); extern int ext3_change_inode_journal_flag(struct inode *, int); extern int ext3_get_inode_loc(struct inode *, struct ext3_iloc *); extern int ext3_can_truncate(struct inode *inode); -- 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