From a477f9d95af90fc6bdab9e5428ba9350cc3529f6 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 27 Nov 2014 17:02:29 -0500 Subject: [PATCH] Additional changes to the patch series Move patch to add btrfs_is_readonly() to the beginning of the patch queue Update xfs's update_time() changes --- add-find-active-inode-nowait | 8 +- btrfs-drop-update_time | 260 +++++++++------------ cover-letter | 5 +- ...let-dirty-time-inodes-get-more-than-a-day-stale | 52 ++--- ext4-add-lazytime-mount-option | 25 +- series | 2 +- split-update_time-into-update_time-and-write_time | 222 ++++++++++-------- vfs-add-lazytime-mount-option | 14 +- 8 files changed, 287 insertions(+), 301 deletions(-) rewrite btrfs-drop-update_time (62%) diff --git a/add-find-active-inode-nowait b/add-find-active-inode-nowait index 17afe669..0610cf99 100644 --- a/add-find-active-inode-nowait +++ b/add-find-active-inode-nowait @@ -12,7 +12,7 @@ Signed-off-by: Theodore Ts'o 2 files changed, 55 insertions(+) diff --git a/fs/inode.c b/fs/inode.c -index b2fea60..2c160b9 100644 +index ba53582..4e5a674 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1283,6 +1283,56 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino) @@ -32,7 +32,7 @@ index b2fea60..2c160b9 100644 + * should be stopped. The @match function must be responsible for + * taking the i_lock spin_lock and checking i_state for an inode being + * freed or being initialized, and incrementing the reference count -+ * before returning 1. It must also not sleep, since it is held with ++ * before returning 1. It also must not sleep, since it is called with + * the inode_hash_lock spinlock held. + * + * This is a even more generalized version of ilookup5() when the @@ -73,10 +73,10 @@ index b2fea60..2c160b9 100644 { struct super_block *sb = inode->i_sb; diff --git a/include/linux/fs.h b/include/linux/fs.h -index d0a2181..831dbee 100644 +index 070f6c6..bd4eff8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -2419,6 +2419,11 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino); +@@ -2420,6 +2420,11 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino); extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); extern struct inode * iget_locked(struct super_block *, unsigned long); diff --git a/btrfs-drop-update_time b/btrfs-drop-update_time dissimilarity index 62% index 383ba1b2..19e66955 100644 --- a/btrfs-drop-update_time +++ b/btrfs-drop-update_time @@ -1,154 +1,106 @@ -btrfs: add an is_readonly() so btrfs can use common code for update_time() - -The only reason btrfs cloned code from the VFS layer was so it could -add a check to see if a subvolume is read-ony. Instead of doing that, -let's add a new inode operation which allows a file system to return -an error if the inode is read-only, and use that in update_time(). -There may be other places where the VFS layer may want to know that -btrfs would want to treat an inode is read-only. - -With this commit, there are no remaining users of update_time() in the -inode operations structure, so we can remove it and simply things -further. - -Signed-off-by: Theodore Ts'o -Cc: linux-btrfs@vger.kernel.org -Reviewed-by: David Sterba ---- - fs/btrfs/inode.c | 26 ++++++-------------------- - fs/inode.c | 22 +++++++++++----------- - include/linux/fs.h | 2 +- - 3 files changed, 18 insertions(+), 32 deletions(-) - -diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index a5e0d0d..0bfe3a4 100644 ---- a/fs/btrfs/inode.c -+++ b/fs/btrfs/inode.c -@@ -5554,26 +5554,12 @@ static int btrfs_dirty_inode(struct inode *inode) - return ret; - } - --/* -- * This is a copy of file_update_time. We need this so we can return error on -- * ENOSPC for updating the inode in the case of file write and mmap writes. -- */ --static int btrfs_update_time(struct inode *inode, struct timespec *now, -- int flags) -+static int btrfs_is_readonly(struct inode *inode) - { - struct btrfs_root *root = BTRFS_I(inode)->root; - - if (btrfs_root_readonly(root)) - return -EROFS; -- -- if (flags & S_VERSION) -- inode_inc_iversion(inode); -- if (flags & S_CTIME) -- inode->i_ctime = *now; -- if (flags & S_MTIME) -- inode->i_mtime = *now; -- if (flags & S_ATIME) -- inode->i_atime = *now; - return 0; - } - -@@ -9466,8 +9452,8 @@ static const struct inode_operations btrfs_dir_inode_operations = { - .permission = btrfs_permission, - .get_acl = btrfs_get_acl, - .set_acl = btrfs_set_acl, -- .update_time = btrfs_update_time, - .write_time = btrfs_write_time, -+ .is_readonly = btrfs_is_readonly, - .tmpfile = btrfs_tmpfile, - }; - static const struct inode_operations btrfs_dir_ro_inode_operations = { -@@ -9475,8 +9461,8 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = { - .permission = btrfs_permission, - .get_acl = btrfs_get_acl, - .set_acl = btrfs_set_acl, -- .update_time = btrfs_update_time, - .write_time = btrfs_write_time, -+ .is_readonly = btrfs_is_readonly, - }; - - static const struct file_operations btrfs_dir_file_operations = { -@@ -9546,8 +9532,8 @@ static const struct inode_operations btrfs_file_inode_operations = { - .fiemap = btrfs_fiemap, - .get_acl = btrfs_get_acl, - .set_acl = btrfs_set_acl, -- .update_time = btrfs_update_time, - .write_time = btrfs_write_time, -+ .is_readonly = btrfs_is_readonly, - }; - static const struct inode_operations btrfs_special_inode_operations = { - .getattr = btrfs_getattr, -@@ -9559,8 +9545,8 @@ static const struct inode_operations btrfs_special_inode_operations = { - .removexattr = btrfs_removexattr, - .get_acl = btrfs_get_acl, - .set_acl = btrfs_set_acl, -- .update_time = btrfs_update_time, - .write_time = btrfs_write_time, -+ .is_readonly = btrfs_is_readonly, - }; - static const struct inode_operations btrfs_symlink_inode_operations = { - .readlink = generic_readlink, -@@ -9573,8 +9559,8 @@ static const struct inode_operations btrfs_symlink_inode_operations = { - .getxattr = btrfs_getxattr, - .listxattr = btrfs_listxattr, - .removexattr = btrfs_removexattr, -- .update_time = btrfs_update_time, - .write_time = btrfs_write_time, -+ .is_readonly = btrfs_is_readonly, - }; - - const struct dentry_operations btrfs_dentry_operations = { -diff --git a/fs/inode.c b/fs/inode.c -index 7b5cd40..425fe4b 100644 ---- a/fs/inode.c -+++ b/fs/inode.c -@@ -1554,20 +1554,20 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) - unsigned short days_since_boot; - int ret; - -- if (inode->i_op->update_time) { -- ret = inode->i_op->update_time(inode, time, flags); -+ if (inode->i_op->is_readonly) { -+ ret = inode->i_op->is_readonly(inode); - if (ret) - return ret; -- } else { -- if (flags & S_ATIME) -- inode->i_atime = *time; -- if (flags & S_VERSION) -- inode_inc_iversion(inode); -- if (flags & S_CTIME) -- inode->i_ctime = *time; -- if (flags & S_MTIME) -- inode->i_mtime = *time; - } -+ if (flags & S_ATIME) -+ inode->i_atime = *time; -+ if (flags & S_VERSION) -+ inode_inc_iversion(inode); -+ if (flags & S_CTIME) -+ inode->i_ctime = *time; -+ if (flags & S_MTIME) -+ inode->i_mtime = *time; -+ - /* - * If i_ts_dirty_day is zero, then either we have not deferred - * timestamp updates, or the system has been up for less than -diff --git a/include/linux/fs.h b/include/linux/fs.h -index dbbd642..70711c8 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -1545,8 +1545,8 @@ struct inode_operations { - int (*removexattr) (struct dentry *, const char *); - int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, - u64 len); -- int (*update_time)(struct inode *, struct timespec *, int); - int (*write_time)(struct inode *); -+ int (*is_readonly)(struct inode *); - int (*atomic_open)(struct inode *, struct dentry *, - struct file *, unsigned open_flag, - umode_t create_mode, int *opened); +btrfs: add an is_readonly() so btrfs can use common code for update_time() + +The only reason btrfs cloned code from the VFS layer was so it could +add a check to see if a subvolume is read-only and so it could return +an error from btrfs_dirty_inode(). This takes care of the first +reason; we'll take care of the second reason in the next commit. + +Signed-off-by: Theodore Ts'o +Cc: linux-btrfs@vger.kernel.org +Reviewed-by: David Sterba +--- + fs/btrfs/inode.c | 14 ++++++++++++++ + fs/inode.c | 7 +++++++ + include/linux/fs.h | 1 + + 3 files changed, 22 insertions(+) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index d23362f..bd46a22 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5554,6 +5554,15 @@ static int btrfs_dirty_inode(struct inode *inode) + return ret; + } + ++static int btrfs_is_readonly(struct inode *inode) ++{ ++ struct btrfs_root *root = BTRFS_I(inode)->root; ++ ++ if (btrfs_root_readonly(root)) ++ return -EROFS; ++ return 0; ++} ++ + /* + * This is a copy of file_update_time. We need this so we can return error on + * ENOSPC for updating the inode in the case of file write and mmap writes. +@@ -9461,6 +9470,7 @@ static const struct inode_operations btrfs_dir_inode_operations = { + .permission = btrfs_permission, + .get_acl = btrfs_get_acl, + .set_acl = btrfs_set_acl, ++ .is_readonly = btrfs_is_readonly, + .update_time = btrfs_update_time, + .tmpfile = btrfs_tmpfile, + }; +@@ -9469,6 +9479,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = { + .permission = btrfs_permission, + .get_acl = btrfs_get_acl, + .set_acl = btrfs_set_acl, ++ .is_readonly = btrfs_is_readonly, + .update_time = btrfs_update_time, + }; + +@@ -9539,6 +9550,7 @@ static const struct inode_operations btrfs_file_inode_operations = { + .fiemap = btrfs_fiemap, + .get_acl = btrfs_get_acl, + .set_acl = btrfs_set_acl, ++ .is_readonly = btrfs_is_readonly, + .update_time = btrfs_update_time, + }; + static const struct inode_operations btrfs_special_inode_operations = { +@@ -9551,6 +9563,7 @@ static const struct inode_operations btrfs_special_inode_operations = { + .removexattr = btrfs_removexattr, + .get_acl = btrfs_get_acl, + .set_acl = btrfs_set_acl, ++ .is_readonly = btrfs_is_readonly, + .update_time = btrfs_update_time, + }; + static const struct inode_operations btrfs_symlink_inode_operations = { +@@ -9564,6 +9577,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { + .getxattr = btrfs_getxattr, + .listxattr = btrfs_listxattr, + .removexattr = btrfs_removexattr, ++ .is_readonly = btrfs_is_readonly, + .update_time = btrfs_update_time, + }; + +diff --git a/fs/inode.c b/fs/inode.c +index 26753ba..53f0173 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1499,6 +1499,13 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, + */ + static int update_time(struct inode *inode, struct timespec *time, int flags) + { ++ int ret; ++ ++ if (inode->i_op->is_readonly) { ++ ret = inode->i_op->is_readonly(inode); ++ if (ret) ++ return ret; ++ } + if (inode->i_op->update_time) + return inode->i_op->update_time(inode, time, flags); + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 9ab779e..f4b0ecd 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1544,6 +1544,7 @@ struct inode_operations { + int (*removexattr) (struct dentry *, const char *); + int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, + u64 len); ++ int (*is_readonly)(struct inode *); + int (*update_time)(struct inode *, struct timespec *, int); + int (*atomic_open)(struct inode *, struct dentry *, + struct file *, unsigned open_flag, diff --git a/cover-letter b/cover-letter index 91bfa7b8..40ecfd1e 100644 --- a/cover-letter +++ b/cover-letter @@ -26,14 +26,13 @@ xfs teams that I got things right. Thanks!! Any objections to my carrying these patches in the ext4 git tree? TODO before next version - - Improve ext4 optimization to avoid extra leakage - - Move btrfs is_readonly patch around - - Check on xfs update_time - fix up lazytime day staleness Changes since -v4: - Fix ext4 optimization so it does not need to increment (and more problematically, decrement) the inode reference count + - Move patch to add btrfs_is_readonly() to the beginning of the patch queue + - Update xfs's update_time() changes Changes since -v3: - inodes with I_DIRTY_TIME set are placed on a new bdi list, diff --git a/dont-let-dirty-time-inodes-get-more-than-a-day-stale b/dont-let-dirty-time-inodes-get-more-than-a-day-stale index 41786cde..31e8d2cb 100644 --- a/dont-let-dirty-time-inodes-get-more-than-a-day-stale +++ b/dont-let-dirty-time-inodes-get-more-than-a-day-stale @@ -6,15 +6,15 @@ stale. Signed-off-by: Theodore Ts'o --- fs/fs-writeback.c | 1 + - fs/inode.c | 18 ++++++++++++++++++ + fs/inode.c | 19 +++++++++++++++++++ include/linux/fs.h | 1 + - 3 files changed, 20 insertions(+) + 3 files changed, 21 insertions(+) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c -index 7b3ef17..8a5920c 100644 +index ef8c5d8..529480a 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c -@@ -1144,6 +1144,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) +@@ -1143,6 +1143,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) if (flags & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { trace_writeback_dirty_inode_start(inode, flags); @@ -23,40 +23,34 @@ index 7b3ef17..8a5920c 100644 sb->s_op->dirty_inode(inode, flags); diff --git a/fs/inode.c b/fs/inode.c -index 2062a14..a39e1bb 100644 +index 009d9c5..c8ad78b 100644 --- a/fs/inode.c +++ b/fs/inode.c -@@ -1515,6 +1515,8 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, +@@ -1510,6 +1510,8 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, */ static int update_time(struct inode *inode, struct timespec *time, int flags) { + struct timespec uptime; + unsigned short days_since_boot; - int ret; + int ret; - if (inode->i_op->update_time) { -@@ -1531,6 +1533,15 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) - if (flags & S_MTIME) - inode->i_mtime = *time; - } -+ /* -+ * If i_ts_dirty_day is zero, then either we have not deferred -+ * timestamp updates, or the system has been up for less than -+ * a day (so days_since_boot is zero), so we defer timestamp -+ * updates in that case and set the I_DIRTY_TIME flag. If a -+ * day or more has passed, then i_ts_dirty_day will be -+ * different from days_since_boot, and then we should update -+ * the on-disk inode and then we can clear i_ts_dirty_day. -+ */ - if ((inode->i_sb->s_flags & MS_LAZYTIME) && - !(flags & S_VERSION) && + if (inode->i_op->is_readonly) { +@@ -1532,6 +1534,22 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) !(inode->i_state & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))) { -@@ -1539,6 +1550,12 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) - if (inode->i_state & I_DIRTY_TIME) return 0; + get_monotonic_boottime(&uptime); + days_since_boot = div_u64(uptime.tv_sec, 86400); ++ /* ++ * If i_ts_dirty_day is zero, then either we have not ++ * deferred timestamp updates, or the system has been ++ * up for less than a day (so days_since_boot is ++ * zero), so we can defer timestamp updates in that ++ * case. If a day or more has passed, then ++ * i_ts_dirty_day will be different from ++ * days_since_boot, and then we should update the ++ * on-disk inode and then we can clear i_ts_dirty_day. ++ */ + if (inode->i_ts_dirty_day && + (inode->i_ts_dirty_day != days_since_boot)) + goto force_dirty; @@ -64,16 +58,16 @@ index 2062a14..a39e1bb 100644 spin_lock(&inode->i_lock); if (inode->i_state & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { spin_unlock(&inode->i_lock); -@@ -1549,6 +1566,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) +@@ -1542,6 +1560,7 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) return 0; } inode->i_state |= I_DIRTY_TIME; + inode->i_ts_dirty_day = days_since_boot; spin_unlock(&inode->i_lock); - bdi = sb_is_blkdev_sb(sb) ? inode->i_mapping->backing_dev_info : - sb->s_bdi; + inode_requeue_dirtytime(inode); + return 0; diff --git a/include/linux/fs.h b/include/linux/fs.h -index 489b2f2..e3574cd 100644 +index 6a6f56b..070f6c6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -575,6 +575,7 @@ struct inode { diff --git a/ext4-add-lazytime-mount-option b/ext4-add-lazytime-mount-option index e412ec67..67f5e4be 100644 --- a/ext4-add-lazytime-mount-option +++ b/ext4-add-lazytime-mount-option @@ -14,16 +14,16 @@ Google-Bug-Id: 18297052 Signed-off-by: Theodore Ts'o --- - fs/ext4/inode.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++--- - fs/ext4/super.c | 9 ++++++++ - include/trace/events/ext4.h | 30 ++++++++++++++++++++++++++ - 3 files changed, 98 insertions(+), 3 deletions(-) + fs/ext4/inode.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- + fs/ext4/super.c | 9 +++++++++ + include/trace/events/ext4.h | 30 +++++++++++++++++++++++++++ + 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c -index 5653fa4..1d11920 100644 +index 5653fa4..b9ef4aae 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c -@@ -4139,6 +4139,64 @@ static int ext4_inode_blocks_set(handle_t *handle, +@@ -4139,6 +4139,65 @@ static int ext4_inode_blocks_set(handle_t *handle, return 0; } @@ -37,7 +37,9 @@ index 5653fa4..1d11920 100644 +{ + struct other_inode *oi = (struct other_inode *) data; + -+ if (inode->i_ino != ino) ++ if ((inode->i_ino != ino) || ++ (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) || ++ ((inode->i_state & I_DIRTY_TIME) == 0)) + return 0; + spin_lock(&inode->i_lock); + if (((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) == 0) && @@ -84,11 +86,10 @@ index 5653fa4..1d11920 100644 + } +} + -+ /* * Post the struct inode info into an on-disk inode location in the * buffer-cache. This gobbles the caller's reference to the -@@ -4237,7 +4295,6 @@ static int ext4_do_update_inode(handle_t *handle, +@@ -4237,7 +4296,6 @@ static int ext4_do_update_inode(handle_t *handle, for (block = 0; block < EXT4_N_BLOCKS; block++) raw_inode->i_block[block] = ei->i_data[block]; } @@ -96,7 +97,7 @@ index 5653fa4..1d11920 100644 if (likely(!test_opt2(inode->i_sb, HURD_COMPAT))) { raw_inode->i_disk_version = cpu_to_le32(inode->i_version); if (ei->i_extra_isize) { -@@ -4248,10 +4305,9 @@ static int ext4_do_update_inode(handle_t *handle, +@@ -4248,10 +4306,11 @@ static int ext4_do_update_inode(handle_t *handle, cpu_to_le16(ei->i_extra_isize); } } @@ -104,7 +105,9 @@ index 5653fa4..1d11920 100644 ext4_inode_csum_set(inode, raw_inode, ei); - spin_unlock(&ei->i_raw_lock); -+ ext4_update_other_inodes_time(inode->i_sb, inode->i_ino, bh->b_data); ++ if (inode->i_sb->s_flags & MS_LAZYTIME) ++ ext4_update_other_inodes_time(inode->i_sb, inode->i_ino, ++ bh->b_data); BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); rc = ext4_handle_dirty_metadata(handle, NULL, bh); diff --git a/series b/series index b3edd522..7c8a1c14 100644 --- a/series +++ b/series @@ -32,13 +32,13 @@ deletion-of-an-unnecessary-check-before-the-function-call-iput jbd2-remove-unnecessary-NULL-check-before-iput forbid-journal_async_commit-in-data-ordered-mode +btrfs-drop-update_time split-update_time-into-update_time-and-write_time vfs-add-lazytime-mount-option dont-let-dirty-time-inodes-get-more-than-a-day-stale add-lazytime-tracepoints add-find-active-inode-nowait ext4-add-lazytime-mount-option -btrfs-drop-update_time ########################################## # unstable patches diff --git a/split-update_time-into-update_time-and-write_time b/split-update_time-into-update_time-and-write_time index a3e0ec4f..394aef6e 100644 --- a/split-update_time-into-update_time-and-write_time +++ b/split-update_time-into-update_time-and-write_time @@ -2,32 +2,34 @@ vfs: split update_time() into update_time() and write_time() In preparation for adding support for the lazytime mount option, we need to be able to separate out the update_time() and write_time() -inode operations. Currently, only btrfs and xfs uses update_time(). +inode operations. Previously, only btrfs and xfs uses update_time(). -We needed to preserve update_time() because btrfs wants to have a -special btrfs_root_readonly() check; otherwise we could drop the -update_time() inode operation entirely. +With this patch, btrfs only needs write_time(), and xfs uses +update_time() to synchronize its on-disk and in-memory timestamps. Signed-off-by: Theodore Ts'o Cc: xfs@oss.sgi.com Cc: linux-btrfs@vger.kernel.org Acked-by: David Sterba --- - Documentation/filesystems/Locking | 2 ++ - fs/btrfs/inode.c | 10 ++++++++++ - fs/inode.c | 29 ++++++++++++++++++----------- - fs/xfs/xfs_iops.c | 39 ++++++++++++++++----------------------- - include/linux/fs.h | 1 + - 5 files changed, 47 insertions(+), 34 deletions(-) + Documentation/filesystems/Locking | 4 +++- + fs/btrfs/inode.c | 30 ++++++------------------------ + fs/inode.c | 7 ++++--- + fs/xfs/xfs_iops.c | 48 ++++++++++++++++++++++++++---------------------- + fs/xfs/xfs_trace.h | 1 + + include/linux/fs.h | 3 ++- + 6 files changed, 42 insertions(+), 51 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking -index b30753c..e49861d 100644 +index b30753c..ee94a66 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking -@@ -63,6 +63,7 @@ prototypes: +@@ -62,7 +62,8 @@ prototypes: + ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); - void (*update_time)(struct inode *, struct timespec *, int); +- void (*update_time)(struct inode *, struct timespec *, int); ++ void (*update_time)(struct inode *); + void (*write_time)(struct inode *); int (*atomic_open)(struct inode *, struct dentry *, struct file *, unsigned open_flag, @@ -41,121 +43,157 @@ index b30753c..e49861d 100644 tmpfile: no dentry_open: no diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c -index d23362f..a5e0d0d 100644 +index bd46a22..a81a0652 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c -@@ -5574,6 +5574,11 @@ static int btrfs_update_time(struct inode *inode, struct timespec *now, - inode->i_mtime = *now; - if (flags & S_ATIME) - inode->i_atime = *now; -+ return 0; -+} -+ +@@ -5563,26 +5563,8 @@ static int btrfs_is_readonly(struct inode *inode) + return 0; + } + +-/* +- * This is a copy of file_update_time. We need this so we can return error on +- * ENOSPC for updating the inode in the case of file write and mmap writes. +- */ +-static int btrfs_update_time(struct inode *inode, struct timespec *now, +- int flags) +static int btrfs_write_time(struct inode *inode) -+{ + { +- struct btrfs_root *root = BTRFS_I(inode)->root; +- +- if (btrfs_root_readonly(root)) +- return -EROFS; +- +- if (flags & S_VERSION) +- inode_inc_iversion(inode); +- if (flags & S_CTIME) +- inode->i_ctime = *now; +- if (flags & S_MTIME) +- inode->i_mtime = *now; +- if (flags & S_ATIME) +- inode->i_atime = *now; return btrfs_dirty_inode(inode); } -@@ -9462,6 +9467,7 @@ static const struct inode_operations btrfs_dir_inode_operations = { +@@ -9471,7 +9453,7 @@ static const struct inode_operations btrfs_dir_inode_operations = { .get_acl = btrfs_get_acl, .set_acl = btrfs_set_acl, - .update_time = btrfs_update_time, + .is_readonly = btrfs_is_readonly, +- .update_time = btrfs_update_time, + .write_time = btrfs_write_time, .tmpfile = btrfs_tmpfile, }; static const struct inode_operations btrfs_dir_ro_inode_operations = { -@@ -9470,6 +9476,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = { +@@ -9480,7 +9462,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = { .get_acl = btrfs_get_acl, .set_acl = btrfs_set_acl, - .update_time = btrfs_update_time, + .is_readonly = btrfs_is_readonly, +- .update_time = btrfs_update_time, + .write_time = btrfs_write_time, }; static const struct file_operations btrfs_dir_file_operations = { -@@ -9540,6 +9547,7 @@ static const struct inode_operations btrfs_file_inode_operations = { +@@ -9551,7 +9533,7 @@ static const struct inode_operations btrfs_file_inode_operations = { .get_acl = btrfs_get_acl, .set_acl = btrfs_set_acl, - .update_time = btrfs_update_time, + .is_readonly = btrfs_is_readonly, +- .update_time = btrfs_update_time, + .write_time = btrfs_write_time, }; static const struct inode_operations btrfs_special_inode_operations = { .getattr = btrfs_getattr, -@@ -9552,6 +9560,7 @@ static const struct inode_operations btrfs_special_inode_operations = { +@@ -9564,7 +9546,7 @@ static const struct inode_operations btrfs_special_inode_operations = { .get_acl = btrfs_get_acl, .set_acl = btrfs_set_acl, - .update_time = btrfs_update_time, + .is_readonly = btrfs_is_readonly, +- .update_time = btrfs_update_time, + .write_time = btrfs_write_time, }; static const struct inode_operations btrfs_symlink_inode_operations = { .readlink = generic_readlink, -@@ -9565,6 +9574,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { +@@ -9578,7 +9560,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { .listxattr = btrfs_listxattr, .removexattr = btrfs_removexattr, - .update_time = btrfs_update_time, + .is_readonly = btrfs_is_readonly, +- .update_time = btrfs_update_time, + .write_time = btrfs_write_time, }; const struct dentry_operations btrfs_dentry_operations = { diff --git a/fs/inode.c b/fs/inode.c -index 26753ba..8f5c4b5 100644 +index 53f0173..94bc908 100644 --- a/fs/inode.c +++ b/fs/inode.c -@@ -1499,17 +1499,24 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, - */ - static int update_time(struct inode *inode, struct timespec *time, int flags) - { +@@ -1506,9 +1506,6 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) + if (ret) + return ret; + } - if (inode->i_op->update_time) - return inode->i_op->update_time(inode, time, flags); - -- if (flags & S_ATIME) -- inode->i_atime = *time; -- if (flags & S_VERSION) -- inode_inc_iversion(inode); -- if (flags & S_CTIME) -- inode->i_ctime = *time; -- if (flags & S_MTIME) -- inode->i_mtime = *time; -+ int ret; -+ -+ if (inode->i_op->update_time) { -+ ret = inode->i_op->update_time(inode, time, flags); -+ if (ret) -+ return ret; -+ } else { -+ if (flags & S_ATIME) -+ inode->i_atime = *time; -+ if (flags & S_VERSION) -+ inode_inc_iversion(inode); -+ if (flags & S_CTIME) -+ inode->i_ctime = *time; -+ if (flags & S_MTIME) -+ inode->i_mtime = *time; -+ } + if (flags & S_ATIME) + inode->i_atime = *time; + if (flags & S_VERSION) +@@ -1517,6 +1514,10 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) + inode->i_ctime = *time; + if (flags & S_MTIME) + inode->i_mtime = *time; ++ if (inode->i_op->update_time) ++ inode->i_op->update_time(inode); + if (inode->i_op->write_time) + return inode->i_op->write_time(inode); mark_inode_dirty_sync(inode); return 0; } diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c -index ec6dcdc..0e9653c 100644 +index ec6dcdc..b69493d 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c -@@ -984,10 +984,8 @@ xfs_vn_setattr( +@@ -983,42 +983,42 @@ xfs_vn_setattr( + return error; } - STATIC int --xfs_vn_update_time( +-STATIC int ++STATIC void + xfs_vn_update_time( - struct inode *inode, - struct timespec *now, - int flags) ++ struct inode *inode) ++{ ++ struct xfs_inode *ip = XFS_I(inode); ++ ++ trace_xfs_update_time(ip); ++ xfs_ilock(ip, XFS_ILOCK_EXCL); ++ ip->i_d.di_ctime.t_sec = (__int32_t) inode->i_ctime.tv_sec; ++ ip->i_d.di_ctime.t_nsec = (__int32_t) inode->i_ctime.tv_nsec; ++ ++ ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec; ++ ip->i_d.di_mtime.t_nsec = (__int32_t) inode->i_mtime.tv_nsec; ++ ++ ip->i_d.di_atime.t_sec = (__int32_t) inode->i_atime.tv_sec; ++ ip->i_d.di_atime.t_nsec = (__int32_t) inode->i_atime.tv_nsec; ++ xfs_iunlock(ip, XFS_ILOCK_EXCL); ++} ++ ++STATIC int +xfs_vn_write_time( + struct inode *inode) { struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; -@@ -1004,21 +1002,16 @@ xfs_vn_update_time( - } + struct xfs_trans *tp; + int error; +- trace_xfs_update_time(ip); +- ++ trace_xfs_write_time(ip); + tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0); + if (error) { + xfs_trans_cancel(tp, 0); + return error; + } +- xfs_ilock(ip, XFS_ILOCK_EXCL); - if (flags & S_CTIME) { - inode->i_ctime = *now; @@ -172,63 +210,63 @@ index ec6dcdc..0e9653c 100644 - ip->i_d.di_atime.t_sec = (__int32_t)now->tv_sec; - ip->i_d.di_atime.t_nsec = (__int32_t)now->tv_nsec; - } -+ -+ ip->i_d.di_ctime.t_sec = (__int32_t) inode->i_ctime.tv_sec; -+ ip->i_d.di_ctime.t_nsec = (__int32_t) inode->i_ctime.tv_nsec; -+ -+ ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec; -+ ip->i_d.di_mtime.t_nsec = (__int32_t) inode->i_mtime.tv_nsec; -+ -+ ip->i_d.di_atime.t_sec = (__int32_t) inode->i_atime.tv_sec; -+ ip->i_d.di_atime.t_nsec = (__int32_t) inode->i_atime.tv_nsec; -+ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP); return xfs_trans_commit(tp, 0); -@@ -1129,7 +1122,7 @@ static const struct inode_operations xfs_inode_operations = { - .removexattr = generic_removexattr, +@@ -1130,6 +1130,7 @@ static const struct inode_operations xfs_inode_operations = { .listxattr = xfs_vn_listxattr, .fiemap = xfs_vn_fiemap, -- .update_time = xfs_vn_update_time, + .update_time = xfs_vn_update_time, + .write_time = xfs_vn_write_time, }; static const struct inode_operations xfs_dir_inode_operations = { -@@ -1156,7 +1149,7 @@ static const struct inode_operations xfs_dir_inode_operations = { - .getxattr = generic_getxattr, +@@ -1157,6 +1158,7 @@ static const struct inode_operations xfs_dir_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, -- .update_time = xfs_vn_update_time, + .update_time = xfs_vn_update_time, + .write_time = xfs_vn_write_time, .tmpfile = xfs_vn_tmpfile, }; -@@ -1184,7 +1177,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { - .getxattr = generic_getxattr, +@@ -1185,6 +1187,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, -- .update_time = xfs_vn_update_time, + .update_time = xfs_vn_update_time, + .write_time = xfs_vn_write_time, .tmpfile = xfs_vn_tmpfile, }; -@@ -1198,7 +1191,7 @@ static const struct inode_operations xfs_symlink_inode_operations = { - .getxattr = generic_getxattr, +@@ -1199,6 +1202,7 @@ static const struct inode_operations xfs_symlink_inode_operations = { .removexattr = generic_removexattr, .listxattr = xfs_vn_listxattr, -- .update_time = xfs_vn_update_time, + .update_time = xfs_vn_update_time, + .write_time = xfs_vn_write_time, }; STATIC void +diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h +index 51372e3..09d261c 100644 +--- a/fs/xfs/xfs_trace.h ++++ b/fs/xfs/xfs_trace.h +@@ -677,6 +677,7 @@ DEFINE_INODE_EVENT(xfs_file_fsync); + DEFINE_INODE_EVENT(xfs_destroy_inode); + DEFINE_INODE_EVENT(xfs_evict_inode); + DEFINE_INODE_EVENT(xfs_update_time); ++DEFINE_INODE_EVENT(xfs_write_time); + + DEFINE_INODE_EVENT(xfs_dquot_dqalloc); + DEFINE_INODE_EVENT(xfs_dquot_dqdetach); diff --git a/include/linux/fs.h b/include/linux/fs.h -index 9ab779e..3633239 100644 +index f4b0ecd..befd5d2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1545,6 +1545,7 @@ struct inode_operations { +@@ -1545,7 +1545,8 @@ struct inode_operations { int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); - int (*update_time)(struct inode *, struct timespec *, int); + int (*is_readonly)(struct inode *); +- int (*update_time)(struct inode *, struct timespec *, int); ++ void (*update_time)(struct inode *); + int (*write_time)(struct inode *); int (*atomic_open)(struct inode *, struct dentry *, struct file *, unsigned open_flag, diff --git a/vfs-add-lazytime-mount-option b/vfs-add-lazytime-mount-option index 998080cf..aec47348 100644 --- a/vfs-add-lazytime-mount-option +++ b/vfs-add-lazytime-mount-option @@ -155,7 +155,7 @@ index ef9bef1..ef8c5d8 100644 wait_for_completion(&done); diff --git a/fs/inode.c b/fs/inode.c -index 8f5c4b5..9e464cc 100644 +index 94bc908..009d9c5 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -30,7 +30,7 @@ @@ -195,10 +195,10 @@ index 8f5c4b5..9e464cc 100644 } } EXPORT_SYMBOL(iput); -@@ -1515,6 +1526,26 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) - if (flags & S_MTIME) - inode->i_mtime = *time; - } +@@ -1516,6 +1527,26 @@ static int update_time(struct inode *inode, struct timespec *time, int flags) + inode->i_mtime = *time; + if (inode->i_op->update_time) + inode->i_op->update_time(inode); + if ((inode->i_sb->s_flags & MS_LAZYTIME) && + !(flags & S_VERSION) && + !(inode->i_state & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))) { @@ -333,10 +333,10 @@ index 5da6012..4cdf733 100644 }; diff --git a/include/linux/fs.h b/include/linux/fs.h -index 3633239..55cf34d 100644 +index befd5d2..6a6f56b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1721,19 +1721,26 @@ struct super_operations { +@@ -1722,19 +1722,26 @@ struct super_operations { #define __I_DIO_WAKEUP 9 #define I_DIO_WAKEUP (1 << I_DIO_WAKEUP) #define I_LINKABLE (1 << 10) -- 2.11.4.GIT