diff options
Diffstat (limited to 'fs/gfs2/inode.c')
| -rw-r--r-- | fs/gfs2/inode.c | 159 |
1 files changed, 9 insertions, 150 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 8b0806a32948..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); |
| @@ -1033,13 +1037,11 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, | |||
| 1033 | 1037 | ||
| 1034 | if (bh) | 1038 | if (bh) |
| 1035 | brelse(bh); | 1039 | brelse(bh); |
| 1036 | if (!inode) | ||
| 1037 | return ERR_PTR(-ENOMEM); | ||
| 1038 | return inode; | 1040 | return inode; |
| 1039 | 1041 | ||
| 1040 | fail_gunlock2: | 1042 | fail_gunlock2: |
| 1041 | gfs2_glock_dq_uninit(ghs + 1); | 1043 | gfs2_glock_dq_uninit(ghs + 1); |
| 1042 | if (inode) | 1044 | if (inode && !IS_ERR(inode)) |
| 1043 | iput(inode); | 1045 | iput(inode); |
| 1044 | fail_gunlock: | 1046 | fail_gunlock: |
| 1045 | gfs2_glock_dq(ghs); | 1047 | gfs2_glock_dq(ghs); |
| @@ -1140,54 +1142,6 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, | |||
| 1140 | return 0; | 1142 | return 0; |
| 1141 | } | 1143 | } |
| 1142 | 1144 | ||
| 1143 | /* | ||
| 1144 | * gfs2_ok_to_move - check if it's ok to move a directory to another directory | ||
| 1145 | * @this: move this | ||
| 1146 | * @to: to here | ||
| 1147 | * | ||
| 1148 | * Follow @to back to the root and make sure we don't encounter @this | ||
| 1149 | * Assumes we already hold the rename lock. | ||
| 1150 | * | ||
| 1151 | * Returns: errno | ||
| 1152 | */ | ||
| 1153 | |||
| 1154 | int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to) | ||
| 1155 | { | ||
| 1156 | struct inode *dir = &to->i_inode; | ||
| 1157 | struct super_block *sb = dir->i_sb; | ||
| 1158 | struct inode *tmp; | ||
| 1159 | struct qstr dotdot; | ||
| 1160 | int error = 0; | ||
| 1161 | |||
| 1162 | gfs2_str2qstr(&dotdot, ".."); | ||
| 1163 | |||
| 1164 | igrab(dir); | ||
| 1165 | |||
| 1166 | for (;;) { | ||
| 1167 | if (dir == &this->i_inode) { | ||
| 1168 | error = -EINVAL; | ||
| 1169 | break; | ||
| 1170 | } | ||
| 1171 | if (dir == sb->s_root->d_inode) { | ||
| 1172 | error = 0; | ||
| 1173 | break; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | tmp = gfs2_lookupi(dir, &dotdot, 1); | ||
| 1177 | if (IS_ERR(tmp)) { | ||
| 1178 | error = PTR_ERR(tmp); | ||
| 1179 | break; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | iput(dir); | ||
| 1183 | dir = tmp; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | iput(dir); | ||
| 1187 | |||
| 1188 | return error; | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | /** | 1145 | /** |
| 1192 | * gfs2_readlinki - return the contents of a symlink | 1146 | * gfs2_readlinki - return the contents of a symlink |
| 1193 | * @ip: the symlink's inode | 1147 | * @ip: the symlink's inode |
| @@ -1207,8 +1161,8 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len) | |||
| 1207 | unsigned int x; | 1161 | unsigned int x; |
| 1208 | int error; | 1162 | int error; |
| 1209 | 1163 | ||
| 1210 | 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); |
| 1211 | error = gfs2_glock_nq_atime(&i_gh); | 1165 | error = gfs2_glock_nq(&i_gh); |
| 1212 | if (error) { | 1166 | if (error) { |
| 1213 | gfs2_holder_uninit(&i_gh); | 1167 | gfs2_holder_uninit(&i_gh); |
| 1214 | return error; | 1168 | return error; |
| @@ -1243,101 +1197,6 @@ out: | |||
| 1243 | return error; | 1197 | return error; |
| 1244 | } | 1198 | } |
| 1245 | 1199 | ||
| 1246 | /** | ||
| 1247 | * gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and | ||
| 1248 | * conditionally update the inode's atime | ||
| 1249 | * @gh: the holder to acquire | ||
| 1250 | * | ||
| 1251 | * Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap | ||
| 1252 | * Update if the difference between the current time and the inode's current | ||
| 1253 | * atime is greater than an interval specified at mount. | ||
| 1254 | * | ||
| 1255 | * Returns: errno | ||
| 1256 | */ | ||
| 1257 | |||
| 1258 | int gfs2_glock_nq_atime(struct gfs2_holder *gh) | ||
| 1259 | { | ||
| 1260 | struct gfs2_glock *gl = gh->gh_gl; | ||
| 1261 | struct gfs2_sbd *sdp = gl->gl_sbd; | ||
| 1262 | struct gfs2_inode *ip = gl->gl_object; | ||
| 1263 | s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum); | ||
| 1264 | unsigned int state; | ||
| 1265 | int flags; | ||
| 1266 | int error; | ||
| 1267 | struct timespec tv = CURRENT_TIME; | ||
| 1268 | |||
| 1269 | if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) || | ||
| 1270 | gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) || | ||
| 1271 | gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops)) | ||
| 1272 | return -EINVAL; | ||
| 1273 | |||
| 1274 | state = gh->gh_state; | ||
| 1275 | flags = gh->gh_flags; | ||
| 1276 | |||
| 1277 | error = gfs2_glock_nq(gh); | ||
| 1278 | if (error) | ||
| 1279 | return error; | ||
| 1280 | |||
| 1281 | if (test_bit(SDF_NOATIME, &sdp->sd_flags) || | ||
| 1282 | (sdp->sd_vfs->s_flags & MS_RDONLY)) | ||
| 1283 | return 0; | ||
| 1284 | |||
| 1285 | if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { | ||
| 1286 | gfs2_glock_dq(gh); | ||
| 1287 | gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY, | ||
| 1288 | gh); | ||
| 1289 | error = gfs2_glock_nq(gh); | ||
| 1290 | if (error) | ||
| 1291 | return error; | ||
| 1292 | |||
| 1293 | /* Verify that atime hasn't been updated while we were | ||
| 1294 | trying to get exclusive lock. */ | ||
| 1295 | |||
| 1296 | tv = CURRENT_TIME; | ||
| 1297 | if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { | ||
| 1298 | struct buffer_head *dibh; | ||
| 1299 | struct gfs2_dinode *di; | ||
| 1300 | |||
| 1301 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | ||
| 1302 | if (error == -EROFS) | ||
| 1303 | return 0; | ||
| 1304 | if (error) | ||
| 1305 | goto fail; | ||
| 1306 | |||
| 1307 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
| 1308 | if (error) | ||
| 1309 | goto fail_end_trans; | ||
| 1310 | |||
| 1311 | ip->i_inode.i_atime = tv; | ||
| 1312 | |||
| 1313 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | ||
| 1314 | di = (struct gfs2_dinode *)dibh->b_data; | ||
| 1315 | di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); | ||
| 1316 | di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); | ||
| 1317 | brelse(dibh); | ||
| 1318 | |||
| 1319 | gfs2_trans_end(sdp); | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | /* If someone else has asked for the glock, | ||
| 1323 | unlock and let them have it. Then reacquire | ||
| 1324 | in the original state. */ | ||
| 1325 | if (gfs2_glock_is_blocking(gl)) { | ||
| 1326 | gfs2_glock_dq(gh); | ||
| 1327 | gfs2_holder_reinit(state, flags, gh); | ||
| 1328 | return gfs2_glock_nq(gh); | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | return 0; | ||
| 1333 | |||
| 1334 | fail_end_trans: | ||
| 1335 | gfs2_trans_end(sdp); | ||
| 1336 | fail: | ||
| 1337 | gfs2_glock_dq(gh); | ||
| 1338 | return error; | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | static int | 1200 | static int |
| 1342 | __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) | 1201 | __gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr) |
| 1343 | { | 1202 | { |
