1 vfs: split update_time() into update_time() and write_time()
3 In preparation for adding support for the lazytime mount option, we
4 need to be able to separate out the update_time() and write_time()
5 inode operations. Previously, only btrfs and xfs uses update_time().
7 With this patch, btrfs only needs write_time(), and xfs uses
8 update_time() to synchronize its on-disk and in-memory timestamps.
10 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
12 Cc: linux-btrfs@vger.kernel.org
13 Acked-by: David Sterba <dsterba@suse.cz>
15 Documentation/filesystems/Locking | 4 +++-
16 fs/btrfs/inode.c | 30 ++++++------------------------
17 fs/inode.c | 7 ++++---
18 fs/xfs/xfs_iops.c | 48 ++++++++++++++++++++++++++----------------------
19 fs/xfs/xfs_trace.h | 1 +
20 include/linux/fs.h | 3 ++-
21 6 files changed, 42 insertions(+), 51 deletions(-)
23 diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
24 index b30753c..ee94a66 100644
25 --- a/Documentation/filesystems/Locking
26 +++ b/Documentation/filesystems/Locking
27 @@ -62,7 +62,8 @@ prototypes:
28 ssize_t (*listxattr) (struct dentry *, char *, size_t);
29 int (*removexattr) (struct dentry *, const char *);
30 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
31 - void (*update_time)(struct inode *, struct timespec *, int);
32 + void (*update_time)(struct inode *);
33 + void (*write_time)(struct inode *);
34 int (*atomic_open)(struct inode *, struct dentry *,
35 struct file *, unsigned open_flag,
36 umode_t create_mode, int *opened);
37 @@ -95,6 +96,7 @@ listxattr: no
45 diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
46 index bd46a22..a81a0652 100644
47 --- a/fs/btrfs/inode.c
48 +++ b/fs/btrfs/inode.c
49 @@ -5563,26 +5563,8 @@ static int btrfs_is_readonly(struct inode *inode)
54 - * This is a copy of file_update_time. We need this so we can return error on
55 - * ENOSPC for updating the inode in the case of file write and mmap writes.
57 -static int btrfs_update_time(struct inode *inode, struct timespec *now,
59 +static int btrfs_write_time(struct inode *inode)
61 - struct btrfs_root *root = BTRFS_I(inode)->root;
63 - if (btrfs_root_readonly(root))
66 - if (flags & S_VERSION)
67 - inode_inc_iversion(inode);
68 - if (flags & S_CTIME)
69 - inode->i_ctime = *now;
70 - if (flags & S_MTIME)
71 - inode->i_mtime = *now;
72 - if (flags & S_ATIME)
73 - inode->i_atime = *now;
74 return btrfs_dirty_inode(inode);
77 @@ -9471,7 +9453,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
78 .get_acl = btrfs_get_acl,
79 .set_acl = btrfs_set_acl,
80 .is_readonly = btrfs_is_readonly,
81 - .update_time = btrfs_update_time,
82 + .write_time = btrfs_write_time,
83 .tmpfile = btrfs_tmpfile,
85 static const struct inode_operations btrfs_dir_ro_inode_operations = {
86 @@ -9480,7 +9462,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = {
87 .get_acl = btrfs_get_acl,
88 .set_acl = btrfs_set_acl,
89 .is_readonly = btrfs_is_readonly,
90 - .update_time = btrfs_update_time,
91 + .write_time = btrfs_write_time,
94 static const struct file_operations btrfs_dir_file_operations = {
95 @@ -9551,7 +9533,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
96 .get_acl = btrfs_get_acl,
97 .set_acl = btrfs_set_acl,
98 .is_readonly = btrfs_is_readonly,
99 - .update_time = btrfs_update_time,
100 + .write_time = btrfs_write_time,
102 static const struct inode_operations btrfs_special_inode_operations = {
103 .getattr = btrfs_getattr,
104 @@ -9564,7 +9546,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
105 .get_acl = btrfs_get_acl,
106 .set_acl = btrfs_set_acl,
107 .is_readonly = btrfs_is_readonly,
108 - .update_time = btrfs_update_time,
109 + .write_time = btrfs_write_time,
111 static const struct inode_operations btrfs_symlink_inode_operations = {
112 .readlink = generic_readlink,
113 @@ -9578,7 +9560,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
114 .listxattr = btrfs_listxattr,
115 .removexattr = btrfs_removexattr,
116 .is_readonly = btrfs_is_readonly,
117 - .update_time = btrfs_update_time,
118 + .write_time = btrfs_write_time,
121 const struct dentry_operations btrfs_dentry_operations = {
122 diff --git a/fs/inode.c b/fs/inode.c
123 index 53f0173..94bc908 100644
126 @@ -1506,9 +1506,6 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
130 - if (inode->i_op->update_time)
131 - return inode->i_op->update_time(inode, time, flags);
134 inode->i_atime = *time;
135 if (flags & S_VERSION)
136 @@ -1517,6 +1514,10 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
137 inode->i_ctime = *time;
139 inode->i_mtime = *time;
140 + if (inode->i_op->update_time)
141 + inode->i_op->update_time(inode);
142 + if (inode->i_op->write_time)
143 + return inode->i_op->write_time(inode);
144 mark_inode_dirty_sync(inode);
147 diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
148 index ec6dcdc..b69493d 100644
149 --- a/fs/xfs/xfs_iops.c
150 +++ b/fs/xfs/xfs_iops.c
151 @@ -983,42 +983,42 @@ xfs_vn_setattr(
158 - struct inode *inode,
159 - struct timespec *now,
161 + struct inode *inode)
163 + struct xfs_inode *ip = XFS_I(inode);
165 + trace_xfs_update_time(ip);
166 + xfs_ilock(ip, XFS_ILOCK_EXCL);
167 + ip->i_d.di_ctime.t_sec = (__int32_t) inode->i_ctime.tv_sec;
168 + ip->i_d.di_ctime.t_nsec = (__int32_t) inode->i_ctime.tv_nsec;
170 + ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec;
171 + ip->i_d.di_mtime.t_nsec = (__int32_t) inode->i_mtime.tv_nsec;
173 + ip->i_d.di_atime.t_sec = (__int32_t) inode->i_atime.tv_sec;
174 + ip->i_d.di_atime.t_nsec = (__int32_t) inode->i_atime.tv_nsec;
175 + xfs_iunlock(ip, XFS_ILOCK_EXCL);
180 + struct inode *inode)
182 struct xfs_inode *ip = XFS_I(inode);
183 struct xfs_mount *mp = ip->i_mount;
184 struct xfs_trans *tp;
187 - trace_xfs_update_time(ip);
189 + trace_xfs_write_time(ip);
190 tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
191 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_fsyncts, 0, 0);
193 xfs_trans_cancel(tp, 0);
197 xfs_ilock(ip, XFS_ILOCK_EXCL);
198 - if (flags & S_CTIME) {
199 - inode->i_ctime = *now;
200 - ip->i_d.di_ctime.t_sec = (__int32_t)now->tv_sec;
201 - ip->i_d.di_ctime.t_nsec = (__int32_t)now->tv_nsec;
203 - if (flags & S_MTIME) {
204 - inode->i_mtime = *now;
205 - ip->i_d.di_mtime.t_sec = (__int32_t)now->tv_sec;
206 - ip->i_d.di_mtime.t_nsec = (__int32_t)now->tv_nsec;
208 - if (flags & S_ATIME) {
209 - inode->i_atime = *now;
210 - ip->i_d.di_atime.t_sec = (__int32_t)now->tv_sec;
211 - ip->i_d.di_atime.t_nsec = (__int32_t)now->tv_nsec;
213 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
214 xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP);
215 return xfs_trans_commit(tp, 0);
216 @@ -1130,6 +1130,7 @@ static const struct inode_operations xfs_inode_operations = {
217 .listxattr = xfs_vn_listxattr,
218 .fiemap = xfs_vn_fiemap,
219 .update_time = xfs_vn_update_time,
220 + .write_time = xfs_vn_write_time,
223 static const struct inode_operations xfs_dir_inode_operations = {
224 @@ -1157,6 +1158,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
225 .removexattr = generic_removexattr,
226 .listxattr = xfs_vn_listxattr,
227 .update_time = xfs_vn_update_time,
228 + .write_time = xfs_vn_write_time,
229 .tmpfile = xfs_vn_tmpfile,
232 @@ -1185,6 +1187,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
233 .removexattr = generic_removexattr,
234 .listxattr = xfs_vn_listxattr,
235 .update_time = xfs_vn_update_time,
236 + .write_time = xfs_vn_write_time,
237 .tmpfile = xfs_vn_tmpfile,
240 @@ -1199,6 +1202,7 @@ static const struct inode_operations xfs_symlink_inode_operations = {
241 .removexattr = generic_removexattr,
242 .listxattr = xfs_vn_listxattr,
243 .update_time = xfs_vn_update_time,
244 + .write_time = xfs_vn_write_time,
248 diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
249 index 51372e3..09d261c 100644
250 --- a/fs/xfs/xfs_trace.h
251 +++ b/fs/xfs/xfs_trace.h
252 @@ -677,6 +677,7 @@ DEFINE_INODE_EVENT(xfs_file_fsync);
253 DEFINE_INODE_EVENT(xfs_destroy_inode);
254 DEFINE_INODE_EVENT(xfs_evict_inode);
255 DEFINE_INODE_EVENT(xfs_update_time);
256 +DEFINE_INODE_EVENT(xfs_write_time);
258 DEFINE_INODE_EVENT(xfs_dquot_dqalloc);
259 DEFINE_INODE_EVENT(xfs_dquot_dqdetach);
260 diff --git a/include/linux/fs.h b/include/linux/fs.h
261 index f4b0ecd..befd5d2 100644
262 --- a/include/linux/fs.h
263 +++ b/include/linux/fs.h
264 @@ -1545,7 +1545,8 @@ struct inode_operations {
265 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
267 int (*is_readonly)(struct inode *);
268 - int (*update_time)(struct inode *, struct timespec *, int);
269 + void (*update_time)(struct inode *);
270 + int (*write_time)(struct inode *);
271 int (*atomic_open)(struct inode *, struct dentry *,
272 struct file *, unsigned open_flag,
273 umode_t create_mode, int *opened);