aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2005-11-01 19:43:58 -0500
committerNathan Scott <nathans@sgi.com>2005-11-01 19:43:58 -0500
commit4aeb664c2561c0bae18d7a3a141d7d2acf126da1 (patch)
tree832e72237a69b76bf4c965d7383cdbb9fc3f8939 /fs/xfs
parent0fdfb3757f27b6d802f85e962d9b0f875df17113 (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.c131
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c15
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h7
-rw-r--r--fs/xfs/xfs_inode.c67
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 */
83void
84xfs_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 */
147void
148xfs_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);
48extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, 48extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
49 int, unsigned int, void __user *); 49 int, unsigned int, void __user *);
50 50
51struct xfs_inode;
52extern void xfs_ichgtime(struct xfs_inode *, int);
53extern 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
307unlock_isem: 307unlock_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 */
579static inline void vn_mark_bad(struct vnode *vp) 572static 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 */
3702void
3703xfs_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
3759ktrace_t *xfs_ilock_trace_buf; 3692ktrace_t *xfs_ilock_trace_buf;
3760 3693