aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/inode.c
diff options
context:
space:
mode:
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{