diff options
author | Nathan Scott <nathans@sgi.com> | 2005-11-01 19:43:58 -0500 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2005-11-01 19:43:58 -0500 |
commit | 4aeb664c2561c0bae18d7a3a141d7d2acf126da1 (patch) | |
tree | 832e72237a69b76bf4c965d7383cdbb9fc3f8939 /fs/xfs | |
parent | 0fdfb3757f27b6d802f85e962d9b0f875df17113 (diff) |
[XFS] Improve buffered read throughput by removing unnecessary timer calls
that showed in ´kernel profiles.
SGI-PV: 925163
SGI-Modid: xfs-linux:xfs-kern:23861a
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 131 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.h | 4 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 15 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 7 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 67 |
5 files changed, 140 insertions, 84 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 77708a8c9f87..68c83ec31143 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -69,6 +69,137 @@ | |||
69 | #include <linux/xattr.h> | 69 | #include <linux/xattr.h> |
70 | #include <linux/namei.h> | 70 | #include <linux/namei.h> |
71 | 71 | ||
72 | /* | ||
73 | * Change the requested timestamp in the given inode. | ||
74 | * We don't lock across timestamp updates, and we don't log them but | ||
75 | * we do record the fact that there is dirty information in core. | ||
76 | * | ||
77 | * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG | ||
78 | * with XFS_ICHGTIME_ACC to be sure that access time | ||
79 | * update will take. Calling first with XFS_ICHGTIME_ACC | ||
80 | * and then XFS_ICHGTIME_MOD may fail to modify the access | ||
81 | * timestamp if the filesystem is mounted noacctm. | ||
82 | */ | ||
83 | void | ||
84 | xfs_ichgtime( | ||
85 | xfs_inode_t *ip, | ||
86 | int flags) | ||
87 | { | ||
88 | struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip)); | ||
89 | timespec_t tv; | ||
90 | |||
91 | /* | ||
92 | * We're not supposed to change timestamps in readonly-mounted | ||
93 | * filesystems. Throw it away if anyone asks us. | ||
94 | */ | ||
95 | if (unlikely(IS_RDONLY(inode))) | ||
96 | return; | ||
97 | |||
98 | /* | ||
99 | * Don't update access timestamps on reads if mounted "noatime". | ||
100 | * Throw it away if anyone asks us. | ||
101 | */ | ||
102 | if (unlikely( | ||
103 | (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) && | ||
104 | (flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) == | ||
105 | XFS_ICHGTIME_ACC)) | ||
106 | return; | ||
107 | |||
108 | nanotime(&tv); | ||
109 | if (flags & XFS_ICHGTIME_MOD) { | ||
110 | inode->i_mtime = tv; | ||
111 | ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; | ||
112 | ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; | ||
113 | } | ||
114 | if (flags & XFS_ICHGTIME_ACC) { | ||
115 | inode->i_atime = tv; | ||
116 | ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec; | ||
117 | ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec; | ||
118 | } | ||
119 | if (flags & XFS_ICHGTIME_CHG) { | ||
120 | inode->i_ctime = tv; | ||
121 | ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; | ||
122 | ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * We update the i_update_core field _after_ changing | ||
127 | * the timestamps in order to coordinate properly with | ||
128 | * xfs_iflush() so that we don't lose timestamp updates. | ||
129 | * This keeps us from having to hold the inode lock | ||
130 | * while doing this. We use the SYNCHRONIZE macro to | ||
131 | * ensure that the compiler does not reorder the update | ||
132 | * of i_update_core above the timestamp updates above. | ||
133 | */ | ||
134 | SYNCHRONIZE(); | ||
135 | ip->i_update_core = 1; | ||
136 | if (!(inode->i_state & I_LOCK)) | ||
137 | mark_inode_dirty_sync(inode); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Variant on the above which avoids querying the system clock | ||
142 | * in situations where we know the Linux inode timestamps have | ||
143 | * just been updated (and so we can update our inode cheaply). | ||
144 | * We also skip the readonly and noatime checks here, they are | ||
145 | * also catered for already. | ||
146 | */ | ||
147 | void | ||
148 | xfs_ichgtime_fast( | ||
149 | xfs_inode_t *ip, | ||
150 | struct inode *inode, | ||
151 | int flags) | ||
152 | { | ||
153 | timespec_t *tvp; | ||
154 | |||
155 | /* | ||
156 | * We're not supposed to change timestamps in readonly-mounted | ||
157 | * filesystems. Throw it away if anyone asks us. | ||
158 | */ | ||
159 | if (unlikely(IS_RDONLY(inode))) | ||
160 | return; | ||
161 | |||
162 | /* | ||
163 | * Don't update access timestamps on reads if mounted "noatime". | ||
164 | * Throw it away if anyone asks us. | ||
165 | */ | ||
166 | if (unlikely( | ||
167 | (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) && | ||
168 | ((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) == | ||
169 | XFS_ICHGTIME_ACC))) | ||
170 | return; | ||
171 | |||
172 | if (flags & XFS_ICHGTIME_MOD) { | ||
173 | tvp = &inode->i_mtime; | ||
174 | ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; | ||
175 | ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec; | ||
176 | } | ||
177 | if (flags & XFS_ICHGTIME_ACC) { | ||
178 | tvp = &inode->i_atime; | ||
179 | ip->i_d.di_atime.t_sec = (__int32_t)tvp->tv_sec; | ||
180 | ip->i_d.di_atime.t_nsec = (__int32_t)tvp->tv_nsec; | ||
181 | } | ||
182 | if (flags & XFS_ICHGTIME_CHG) { | ||
183 | tvp = &inode->i_ctime; | ||
184 | ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; | ||
185 | ip->i_d.di_ctime.t_nsec = (__int32_t)tvp->tv_nsec; | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * We update the i_update_core field _after_ changing | ||
190 | * the timestamps in order to coordinate properly with | ||
191 | * xfs_iflush() so that we don't lose timestamp updates. | ||
192 | * This keeps us from having to hold the inode lock | ||
193 | * while doing this. We use the SYNCHRONIZE macro to | ||
194 | * ensure that the compiler does not reorder the update | ||
195 | * of i_update_core above the timestamp updates above. | ||
196 | */ | ||
197 | SYNCHRONIZE(); | ||
198 | ip->i_update_core = 1; | ||
199 | if (!(inode->i_state & I_LOCK)) | ||
200 | mark_inode_dirty_sync(inode); | ||
201 | } | ||
202 | |||
72 | 203 | ||
73 | /* | 204 | /* |
74 | * Pull the link count and size up from the xfs inode to the linux inode | 205 | * Pull the link count and size up from the xfs inode to the linux inode |
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index 6a69a62c36b0..415de44b6aed 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h | |||
@@ -48,4 +48,8 @@ extern void linvfs_unwritten_done(struct buffer_head *, int); | |||
48 | extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, | 48 | extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, |
49 | int, unsigned int, void __user *); | 49 | int, unsigned int, void __user *); |
50 | 50 | ||
51 | struct xfs_inode; | ||
52 | extern void xfs_ichgtime(struct xfs_inode *, int); | ||
53 | extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int); | ||
54 | |||
51 | #endif /* __XFS_IOPS_H__ */ | 55 | #endif /* __XFS_IOPS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 3b5fabe8dae9..c04f0c063c58 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -302,7 +302,7 @@ xfs_read( | |||
302 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 302 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
303 | 303 | ||
304 | if (likely(!(ioflags & IO_INVIS))) | 304 | if (likely(!(ioflags & IO_INVIS))) |
305 | xfs_ichgtime(ip, XFS_ICHGTIME_ACC); | 305 | xfs_ichgtime_fast(ip, inode, XFS_ICHGTIME_ACC); |
306 | 306 | ||
307 | unlock_isem: | 307 | unlock_isem: |
308 | if (unlikely(ioflags & IO_ISDIRECT)) | 308 | if (unlikely(ioflags & IO_ISDIRECT)) |
@@ -367,7 +367,7 @@ xfs_sendfile( | |||
367 | XFS_STATS_ADD(xs_read_bytes, ret); | 367 | XFS_STATS_ADD(xs_read_bytes, ret); |
368 | 368 | ||
369 | if (likely(!(ioflags & IO_INVIS))) | 369 | if (likely(!(ioflags & IO_INVIS))) |
370 | xfs_ichgtime(ip, XFS_ICHGTIME_ACC); | 370 | xfs_ichgtime_fast(ip, LINVFS_GET_IP(vp), XFS_ICHGTIME_ACC); |
371 | 371 | ||
372 | return ret; | 372 | return ret; |
373 | } | 373 | } |
@@ -732,15 +732,10 @@ start: | |||
732 | } | 732 | } |
733 | } | 733 | } |
734 | 734 | ||
735 | /* | 735 | if (likely(!(ioflags & IO_INVIS))) { |
736 | * On Linux, generic_file_write updates the times even if | ||
737 | * no data is copied in so long as the write had a size. | ||
738 | * | ||
739 | * We must update xfs' times since revalidate will overcopy xfs. | ||
740 | */ | ||
741 | if (!(ioflags & IO_INVIS)) { | ||
742 | xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
743 | inode_update_time(inode, 1); | 736 | inode_update_time(inode, 1); |
737 | xfs_ichgtime_fast(xip, inode, | ||
738 | XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
744 | } | 739 | } |
745 | 740 | ||
746 | /* | 741 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 76a8dddb437a..ef1c65f42fe0 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -567,13 +567,6 @@ static __inline__ void vn_flagclr(struct vnode *vp, uint flag) | |||
567 | } | 567 | } |
568 | 568 | ||
569 | /* | 569 | /* |
570 | * Update modify/access/change times on the vnode | ||
571 | */ | ||
572 | #define VN_MTIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_mtime = *(tvp)) | ||
573 | #define VN_ATIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_atime = *(tvp)) | ||
574 | #define VN_CTIMESET(vp, tvp) (LINVFS_GET_IP(vp)->i_ctime = *(tvp)) | ||
575 | |||
576 | /* | ||
577 | * Dealing with bad inodes | 570 | * Dealing with bad inodes |
578 | */ | 571 | */ |
579 | static inline void vn_mark_bad(struct vnode *vp) | 572 | static inline void vn_mark_bad(struct vnode *vp) |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5bf7b709f91a..a648cc8ce96b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -3688,73 +3688,6 @@ xfs_iroundup( | |||
3688 | return( 0 ); | 3688 | return( 0 ); |
3689 | } | 3689 | } |
3690 | 3690 | ||
3691 | /* | ||
3692 | * Change the requested timestamp in the given inode. | ||
3693 | * We don't lock across timestamp updates, and we don't log them but | ||
3694 | * we do record the fact that there is dirty information in core. | ||
3695 | * | ||
3696 | * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG | ||
3697 | * with XFS_ICHGTIME_ACC to be sure that access time | ||
3698 | * update will take. Calling first with XFS_ICHGTIME_ACC | ||
3699 | * and then XFS_ICHGTIME_MOD may fail to modify the access | ||
3700 | * timestamp if the filesystem is mounted noacctm. | ||
3701 | */ | ||
3702 | void | ||
3703 | xfs_ichgtime(xfs_inode_t *ip, | ||
3704 | int flags) | ||
3705 | { | ||
3706 | timespec_t tv; | ||
3707 | vnode_t *vp = XFS_ITOV(ip); | ||
3708 | struct inode *inode = LINVFS_GET_IP(vp); | ||
3709 | |||
3710 | /* | ||
3711 | * We're not supposed to change timestamps in readonly-mounted | ||
3712 | * filesystems. Throw it away if anyone asks us. | ||
3713 | */ | ||
3714 | if (unlikely(vp->v_vfsp->vfs_flag & VFS_RDONLY)) | ||
3715 | return; | ||
3716 | |||
3717 | /* | ||
3718 | * Don't update access timestamps on reads if mounted "noatime" | ||
3719 | * Throw it away if anyone asks us. | ||
3720 | */ | ||
3721 | if ((ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) && | ||
3722 | ((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) | ||
3723 | == XFS_ICHGTIME_ACC)) | ||
3724 | return; | ||
3725 | |||
3726 | nanotime(&tv); | ||
3727 | if (flags & XFS_ICHGTIME_MOD) { | ||
3728 | VN_MTIMESET(vp, &tv); | ||
3729 | ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; | ||
3730 | ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; | ||
3731 | } | ||
3732 | if (flags & XFS_ICHGTIME_ACC) { | ||
3733 | VN_ATIMESET(vp, &tv); | ||
3734 | ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec; | ||
3735 | ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec; | ||
3736 | } | ||
3737 | if (flags & XFS_ICHGTIME_CHG) { | ||
3738 | VN_CTIMESET(vp, &tv); | ||
3739 | ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; | ||
3740 | ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; | ||
3741 | } | ||
3742 | |||
3743 | /* | ||
3744 | * We update the i_update_core field _after_ changing | ||
3745 | * the timestamps in order to coordinate properly with | ||
3746 | * xfs_iflush() so that we don't lose timestamp updates. | ||
3747 | * This keeps us from having to hold the inode lock | ||
3748 | * while doing this. We use the SYNCHRONIZE macro to | ||
3749 | * ensure that the compiler does not reorder the update | ||
3750 | * of i_update_core above the timestamp updates above. | ||
3751 | */ | ||
3752 | SYNCHRONIZE(); | ||
3753 | ip->i_update_core = 1; | ||
3754 | if (!(inode->i_state & I_LOCK)) | ||
3755 | mark_inode_dirty_sync(inode); | ||
3756 | } | ||
3757 | |||
3758 | #ifdef XFS_ILOCK_TRACE | 3691 | #ifdef XFS_ILOCK_TRACE |
3759 | ktrace_t *xfs_ilock_trace_buf; | 3692 | ktrace_t *xfs_ilock_trace_buf; |
3760 | 3693 | ||