Commit 42fe2b1f7fe788ed5304a7bfa0a0b0db81bc03a8
Committed by
Nathan Scott
1 parent
dd954c69d1
[XFS] fix, speedup and simplify atime handling let the VFS handle atime
updates and only sync back to the xfs inode when nessecary SGI-PV: 946679 SGI-Modid: xfs-linux-melb:xfs-kern:203362a Signed-off-by: Christoph Hellwig <hch@sgi.com> Signed-off-by: Nathan Scott <nathans@sgi.com>
Showing 8 changed files with 49 additions and 54 deletions Side-by-side Diff
fs/xfs/linux-2.6/xfs_iops.c
... | ... | @@ -58,6 +58,24 @@ |
58 | 58 | (S_ISDIR(inode->i_mode) && inode->i_sb->s_flags & MS_NODIRATIME)) |
59 | 59 | |
60 | 60 | /* |
61 | + * Bring the atime in the XFS inode uptodate. | |
62 | + * Used before logging the inode to disk or when the Linux inode goes away. | |
63 | + */ | |
64 | +void | |
65 | +xfs_synchronize_atime( | |
66 | + xfs_inode_t *ip) | |
67 | +{ | |
68 | + vnode_t *vp; | |
69 | + | |
70 | + vp = XFS_ITOV_NULL(ip); | |
71 | + if (vp) { | |
72 | + struct inode *inode = &vp->v_inode; | |
73 | + ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; | |
74 | + ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; | |
75 | + } | |
76 | +} | |
77 | + | |
78 | +/* | |
61 | 79 | * Change the requested timestamp in the given inode. |
62 | 80 | * We don't lock across timestamp updates, and we don't log them but |
63 | 81 | * we do record the fact that there is dirty information in core. |
... | ... | @@ -76,23 +94,6 @@ |
76 | 94 | struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); |
77 | 95 | timespec_t tv; |
78 | 96 | |
79 | - /* | |
80 | - * We're not supposed to change timestamps in readonly-mounted | |
81 | - * filesystems. Throw it away if anyone asks us. | |
82 | - */ | |
83 | - if (unlikely(IS_RDONLY(inode))) | |
84 | - return; | |
85 | - | |
86 | - /* | |
87 | - * Don't update access timestamps on reads if mounted "noatime". | |
88 | - * Throw it away if anyone asks us. | |
89 | - */ | |
90 | - if (unlikely( | |
91 | - (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) && | |
92 | - (flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) == | |
93 | - XFS_ICHGTIME_ACC)) | |
94 | - return; | |
95 | - | |
96 | 97 | nanotime(&tv); |
97 | 98 | if (flags & XFS_ICHGTIME_MOD) { |
98 | 99 | inode->i_mtime = tv; |
... | ... | @@ -129,8 +130,6 @@ |
129 | 130 | * Variant on the above which avoids querying the system clock |
130 | 131 | * in situations where we know the Linux inode timestamps have |
131 | 132 | * just been updated (and so we can update our inode cheaply). |
132 | - * We also skip the readonly and noatime checks here, they are | |
133 | - * also catered for already. | |
134 | 133 | */ |
135 | 134 | void |
136 | 135 | xfs_ichgtime_fast( |
137 | 136 | |
138 | 137 | |
... | ... | @@ -141,31 +140,22 @@ |
141 | 140 | timespec_t *tvp; |
142 | 141 | |
143 | 142 | /* |
143 | + * Atime updates for read() & friends are handled lazily now, and | |
144 | + * explicit updates must go through xfs_ichgtime() | |
145 | + */ | |
146 | + ASSERT((flags & XFS_ICHGTIME_ACC) == 0); | |
147 | + | |
148 | + /* | |
144 | 149 | * We're not supposed to change timestamps in readonly-mounted |
145 | 150 | * filesystems. Throw it away if anyone asks us. |
146 | 151 | */ |
147 | 152 | if (unlikely(IS_RDONLY(inode))) |
148 | 153 | return; |
149 | 154 | |
150 | - /* | |
151 | - * Don't update access timestamps on reads if mounted "noatime". | |
152 | - * Throw it away if anyone asks us. | |
153 | - */ | |
154 | - if (unlikely( | |
155 | - (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) && | |
156 | - ((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) == | |
157 | - XFS_ICHGTIME_ACC))) | |
158 | - return; | |
159 | - | |
160 | 155 | if (flags & XFS_ICHGTIME_MOD) { |
161 | 156 | tvp = &inode->i_mtime; |
162 | 157 | ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; |
163 | 158 | ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec; |
164 | - } | |
165 | - if (flags & XFS_ICHGTIME_ACC) { | |
166 | - tvp = &inode->i_atime; | |
167 | - ip->i_d.di_atime.t_sec = (__int32_t)tvp->tv_sec; | |
168 | - ip->i_d.di_atime.t_nsec = (__int32_t)tvp->tv_nsec; | |
169 | 159 | } |
170 | 160 | if (flags & XFS_ICHGTIME_CHG) { |
171 | 161 | tvp = &inode->i_ctime; |
fs/xfs/linux-2.6/xfs_lrw.c
... | ... | @@ -281,9 +281,6 @@ |
281 | 281 | |
282 | 282 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
283 | 283 | |
284 | - if (likely(!(ioflags & IO_INVIS))) | |
285 | - xfs_ichgtime_fast(ip, inode, XFS_ICHGTIME_ACC); | |
286 | - | |
287 | 284 | unlock_isem: |
288 | 285 | if (unlikely(ioflags & IO_ISDIRECT)) |
289 | 286 | mutex_unlock(&inode->i_mutex); |
... | ... | @@ -345,9 +342,6 @@ |
345 | 342 | |
346 | 343 | if (ret > 0) |
347 | 344 | XFS_STATS_ADD(xs_read_bytes, ret); |
348 | - | |
349 | - if (likely(!(ioflags & IO_INVIS))) | |
350 | - xfs_ichgtime_fast(ip, LINVFS_GET_IP(vp), XFS_ICHGTIME_ACC); | |
351 | 345 | |
352 | 346 | return ret; |
353 | 347 | } |
fs/xfs/linux-2.6/xfs_vnode.c
... | ... | @@ -106,7 +106,6 @@ |
106 | 106 | inode->i_blocks = vap->va_nblocks; |
107 | 107 | inode->i_mtime = vap->va_mtime; |
108 | 108 | inode->i_ctime = vap->va_ctime; |
109 | - inode->i_atime = vap->va_atime; | |
110 | 109 | inode->i_blksize = vap->va_blocksize; |
111 | 110 | if (vap->va_xflags & XFS_XFLAG_IMMUTABLE) |
112 | 111 | inode->i_flags |= S_IMMUTABLE; |
fs/xfs/xfs_inode.c
... | ... | @@ -3364,6 +3364,11 @@ |
3364 | 3364 | ip->i_update_core = 0; |
3365 | 3365 | SYNCHRONIZE(); |
3366 | 3366 | |
3367 | + /* | |
3368 | + * Make sure to get the latest atime from the Linux inode. | |
3369 | + */ | |
3370 | + xfs_synchronize_atime(ip); | |
3371 | + | |
3367 | 3372 | if (XFS_TEST_ERROR(INT_GET(dip->di_core.di_magic,ARCH_CONVERT) != XFS_DINODE_MAGIC, |
3368 | 3373 | mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { |
3369 | 3374 | xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, |
fs/xfs/xfs_inode.h
... | ... | @@ -436,6 +436,8 @@ |
436 | 436 | xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); |
437 | 437 | void xfs_lock_inodes(xfs_inode_t **, int, int, uint); |
438 | 438 | |
439 | +void xfs_synchronize_atime(xfs_inode_t *); | |
440 | + | |
439 | 441 | #define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount)) |
440 | 442 | |
441 | 443 | #ifdef DEBUG |
fs/xfs/xfs_inode_item.c
... | ... | @@ -271,6 +271,11 @@ |
271 | 271 | if (ip->i_update_size) |
272 | 272 | ip->i_update_size = 0; |
273 | 273 | |
274 | + /* | |
275 | + * Make sure to get the latest atime from the Linux inode. | |
276 | + */ | |
277 | + xfs_synchronize_atime(ip); | |
278 | + | |
274 | 279 | vecp->i_addr = (xfs_caddr_t)&ip->i_d; |
275 | 280 | vecp->i_len = sizeof(xfs_dinode_core_t); |
276 | 281 | XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE); |
fs/xfs/xfs_itable.c
... | ... | @@ -56,6 +56,7 @@ |
56 | 56 | { |
57 | 57 | xfs_dinode_core_t *dic; /* dinode core info pointer */ |
58 | 58 | xfs_inode_t *ip; /* incore inode pointer */ |
59 | + vnode_t *vp; | |
59 | 60 | int error; |
60 | 61 | |
61 | 62 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno); |
... | ... | @@ -72,6 +73,7 @@ |
72 | 73 | goto out_iput; |
73 | 74 | } |
74 | 75 | |
76 | + vp = XFS_ITOV(ip); | |
75 | 77 | dic = &ip->i_d; |
76 | 78 | |
77 | 79 | /* xfs_iget returns the following without needing |
... | ... | @@ -84,8 +86,9 @@ |
84 | 86 | buf->bs_uid = dic->di_uid; |
85 | 87 | buf->bs_gid = dic->di_gid; |
86 | 88 | buf->bs_size = dic->di_size; |
87 | - buf->bs_atime.tv_sec = dic->di_atime.t_sec; | |
88 | - buf->bs_atime.tv_nsec = dic->di_atime.t_nsec; | |
89 | + /* atime is only kept uptodate in the Linux inode */ | |
90 | + buf->bs_atime.tv_sec = vp->v_inode.i_atime.tv_sec; | |
91 | + buf->bs_atime.tv_nsec = vp->v_inode.i_atime.tv_nsec; | |
89 | 92 | buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; |
90 | 93 | buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; |
91 | 94 | buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; |
fs/xfs/xfs_vnodeops.c
... | ... | @@ -182,8 +182,8 @@ |
182 | 182 | break; |
183 | 183 | } |
184 | 184 | |
185 | - vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec; | |
186 | - vap->va_atime.tv_nsec = ip->i_d.di_atime.t_nsec; | |
185 | + /* atime is only kept uptodate in the Linux inode */ | |
186 | + vap->va_atime = vp->v_inode.i_atime; | |
187 | 187 | vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec; |
188 | 188 | vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; |
189 | 189 | vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec; |
... | ... | @@ -982,10 +982,6 @@ |
982 | 982 | goto error_return; |
983 | 983 | } |
984 | 984 | |
985 | - if (!(ioflags & IO_INVIS)) { | |
986 | - xfs_ichgtime(ip, XFS_ICHGTIME_ACC); | |
987 | - } | |
988 | - | |
989 | 985 | /* |
990 | 986 | * See if the symlink is stored inline. |
991 | 987 | */ |
... | ... | @@ -3226,7 +3222,6 @@ |
3226 | 3222 | xfs_trans_t *tp = NULL; |
3227 | 3223 | int error = 0; |
3228 | 3224 | uint lock_mode; |
3229 | - xfs_off_t start_offset; | |
3230 | 3225 | |
3231 | 3226 | vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__, |
3232 | 3227 | (inst_t *)__return_address); |
3233 | 3228 | |
... | ... | @@ -3237,11 +3232,7 @@ |
3237 | 3232 | } |
3238 | 3233 | |
3239 | 3234 | lock_mode = xfs_ilock_map_shared(dp); |
3240 | - start_offset = uiop->uio_offset; | |
3241 | 3235 | error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); |
3242 | - if (start_offset != uiop->uio_offset) { | |
3243 | - xfs_ichgtime(dp, XFS_ICHGTIME_ACC); | |
3244 | - } | |
3245 | 3236 | xfs_iunlock_map_shared(dp, lock_mode); |
3246 | 3237 | return error; |
3247 | 3238 | } |
... | ... | @@ -3818,6 +3809,12 @@ |
3818 | 3809 | vn_iowait(vp); |
3819 | 3810 | |
3820 | 3811 | ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); |
3812 | + | |
3813 | + /* | |
3814 | + * Make sure the atime in the XFS inode is correct before freeing the | |
3815 | + * Linux inode. | |
3816 | + */ | |
3817 | + xfs_synchronize_atime(ip); | |
3821 | 3818 | |
3822 | 3819 | /* If we have nothing to flush with this inode then complete the |
3823 | 3820 | * teardown now, otherwise break the link between the xfs inode |