diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index c007607..be804b4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -58,7 +58,10 @@ void __mark_inode_dirty(struct inode *inode, int flags) /* * Don't do this for I_DIRTY_PAGES - that doesn't actually - * dirty the inode itself + * dirty the inode itself. Do not call dirty_inode() for + * atime-only updates, as dirty_inode() can be expensive and + * we want atime updates to occur as asynchronously as + * possible. */ if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { if (sb->s_op->dirty_inode) @@ -245,8 +248,11 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) ret = do_writepages(mapping, wbc); + if ((dirty & I_DIRTY_ATIME) && inode->i_sb->s_op->dirty_inode) + inode->i_sb->s_op->dirty_inode(inode); + /* Don't write the inode if only I_DIRTY_PAGES was set */ - if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { + if (dirty & (I_DIRTY_ATIME | I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { int err = write_inode(inode, wait); if (ret == 0) ret = err; diff --git a/fs/inode.c b/fs/inode.c index 53245ff..2354f9f 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1234,7 +1234,7 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry) return; inode->i_atime = now; - mark_inode_dirty_sync(inode); + __mark_inode_dirty(inode, I_DIRTY_ATIME); } EXPORT_SYMBOL(touch_atime); diff --git a/include/linux/fs.h b/include/linux/fs.h index 98ffb6e..d2b2185 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1282,6 +1282,7 @@ struct super_operations { * * Two bits are used for locking and completion notification, I_LOCK and I_SYNC. * + * I_DIRTY_ATIME Inode's atime is dirty -- writeback can be deferred. * I_DIRTY_SYNC Inode is dirty, but doesn't have to be written on * fdatasync(). i_atime is the usual cause. * I_DIRTY_DATASYNC Data-related inode changes pending. We keep track of @@ -1334,8 +1335,10 @@ struct super_operations { #define I_LOCK (1 << __I_LOCK) #define __I_SYNC 8 #define I_SYNC (1 << __I_SYNC) +#define __I_DIRTY_ATIME 9 +#define I_DIRTY_ATIME (1 << __I_DIRTY_ATIME) -#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) +#define I_DIRTY (I_DIRTY_ATIME | I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) extern void __mark_inode_dirty(struct inode *, int); static inline void mark_inode_dirty(struct inode *inode)