aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-09-18 08:53:59 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2008-09-18 08:53:59 -0400
commit719ee344675c2efed9115934f19aa66a526b6e5b (patch)
tree7f9502d696a09eaf5eba0a0d3fa35557ffd3c503 /fs/gfs2/inode.c
parent37ec89e83c4ca98323fe74f139301ff3949cfdb6 (diff)
GFS2: high time to take some time over atime
Until now, we've used the same scheme as GFS1 for atime. This has failed since atime is a per vfsmnt flag, not a per fs flag and as such the "noatime" flag was not getting passed down to the filesystems. This patch removes all the "special casing" around atime updates and we simply use the VFS's atime code. The net result is that GFS2 will now support all the same atime related mount options of any other filesystem on a per-vfsmnt basis. We do lose the "lazy atime" updates, but we gain "relatime". We could add lazy atime to the VFS at a later date, if there is a requirement for that variant still - I suspect relatime will be enough. Also we lose about 100 lines of code after this patch has been applied, and I have a suspicion that it will speed things up a bit, even when atime is "on". So it seems like a nice clean up as well. From a user perspective, everything stays the same except the loss of the per-fs atime quantum tweekable (ought to be per-vfsmnt at the very least, and to be honest I don't think anybody ever used it) and that a number of options which were ignored before now work correctly. Please let me know if you've got any comments. I'm pushing this out early so that you can all see what my plans are. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r--fs/gfs2/inode.c107
1 files changed, 8 insertions, 99 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index c8a959c09f1e..7cee695fa441 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -18,6 +18,7 @@
18#include <linux/crc32.h> 18#include <linux/crc32.h>
19#include <linux/lm_interface.h> 19#include <linux/lm_interface.h>
20#include <linux/security.h> 20#include <linux/security.h>
21#include <linux/time.h>
21 22
22#include "gfs2.h" 23#include "gfs2.h"
23#include "incore.h" 24#include "incore.h"
@@ -249,6 +250,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
249{ 250{
250 struct gfs2_dinode_host *di = &ip->i_di; 251 struct gfs2_dinode_host *di = &ip->i_di;
251 const struct gfs2_dinode *str = buf; 252 const struct gfs2_dinode *str = buf;
253 struct timespec atime;
252 u16 height, depth; 254 u16 height, depth;
253 255
254 if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) 256 if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
@@ -275,8 +277,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
275 di->di_size = be64_to_cpu(str->di_size); 277 di->di_size = be64_to_cpu(str->di_size);
276 i_size_write(&ip->i_inode, di->di_size); 278 i_size_write(&ip->i_inode, di->di_size);
277 gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); 279 gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
278 ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime); 280 atime.tv_sec = be64_to_cpu(str->di_atime);
279 ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); 281 atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
282 if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0)
283 ip->i_inode.i_atime = atime;
280 ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); 284 ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
281 ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); 285 ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
282 ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); 286 ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
@@ -1157,8 +1161,8 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
1157 unsigned int x; 1161 unsigned int x;
1158 int error; 1162 int error;
1159 1163
1160 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh); 1164 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
1161 error = gfs2_glock_nq_atime(&i_gh); 1165 error = gfs2_glock_nq(&i_gh);
1162 if (error) { 1166 if (error) {
1163 gfs2_holder_uninit(&i_gh); 1167 gfs2_holder_uninit(&i_gh);
1164 return error; 1168 return error;
@@ -1193,101 +1197,6 @@ out:
1193 return error; 1197 return error;
1194} 1198}
1195 1199
1196/**
1197 * gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and
1198 * conditionally update the inode's atime
1199 * @gh: the holder to acquire
1200 *
1201 * Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap
1202 * Update if the difference between the current time and the inode's current
1203 * atime is greater than an interval specified at mount.
1204 *
1205 * Returns: errno
1206 */
1207
1208int gfs2_glock_nq_atime(struct gfs2_holder *gh)
1209{
1210 struct gfs2_glock *gl = gh->gh_gl;
1211 struct gfs2_sbd *sdp = gl->gl_sbd;
1212 struct gfs2_inode *ip = gl->gl_object;
1213 s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
1214 unsigned int state;
1215 int flags;
1216 int error;
1217 struct timespec tv = CURRENT_TIME;
1218
1219 if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
1220 gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
1221 gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops))
1222 return -EINVAL;
1223
1224 state = gh->gh_state;
1225 flags = gh->gh_flags;
1226
1227 error = gfs2_glock_nq(gh);
1228 if (error)
1229 return error;
1230
1231 if (test_bit(SDF_NOATIME, &sdp->sd_flags) ||
1232 (sdp->sd_vfs->s_flags & MS_RDONLY))
1233 return 0;
1234
1235 if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
1236 gfs2_glock_dq(gh);
1237 gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
1238 gh);
1239 error = gfs2_glock_nq(gh);
1240 if (error)
1241 return error;
1242
1243 /* Verify that atime hasn't been updated while we were
1244 trying to get exclusive lock. */
1245
1246 tv = CURRENT_TIME;
1247 if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
1248 struct buffer_head *dibh;
1249 struct gfs2_dinode *di;
1250
1251 error = gfs2_trans_begin(sdp, RES_DINODE, 0);
1252 if (error == -EROFS)
1253 return 0;
1254 if (error)
1255 goto fail;
1256
1257 error = gfs2_meta_inode_buffer(ip, &dibh);
1258 if (error)
1259 goto fail_end_trans;
1260
1261 ip->i_inode.i_atime = tv;
1262
1263 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
1264 di = (struct gfs2_dinode *)dibh->b_data;
1265 di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
1266 di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
1267 brelse(dibh);
1268
1269 gfs2_trans_end(sdp);
1270 }
1271
1272 /* If someone else has asked for the glock,
1273 unlock and let them have it. Then reacquire
1274 in the original state. */
1275 if (gfs2_glock_is_blocking(gl)) {
1276 gfs2_glock_dq(gh);
1277 gfs2_holder_reinit(state, flags, gh);
1278 return gfs2_glock_nq(gh);
1279 }
1280 }
1281
1282 return 0;
1283
1284fail_end_trans:
1285 gfs2_trans_end(sdp);
1286fail:
1287 gfs2_glock_dq(gh);
1288 return error;
1289}
1290
1291static int 1200static int
1292__gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) 1201__gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
1293{ 1202{