diff options
Diffstat (limited to 'fs/gfs2/inode.c')
-rw-r--r-- | fs/gfs2/inode.c | 107 |
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 | |||
1208 | int 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 | |||
1284 | fail_end_trans: | ||
1285 | gfs2_trans_end(sdp); | ||
1286 | fail: | ||
1287 | gfs2_glock_dq(gh); | ||
1288 | return error; | ||
1289 | } | ||
1290 | |||
1291 | static int | 1200 | static 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 | { |