diff options
Diffstat (limited to 'fs/inode.c')
| -rw-r--r-- | fs/inode.c | 71 |
1 files changed, 55 insertions, 16 deletions
diff --git a/fs/inode.c b/fs/inode.c index 826fb0b9d1c3..643ac43e5a5c 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/hash.h> | 17 | #include <linux/hash.h> |
| 18 | #include <linux/swap.h> | 18 | #include <linux/swap.h> |
| 19 | #include <linux/security.h> | 19 | #include <linux/security.h> |
| 20 | #include <linux/ima.h> | ||
| 20 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
| 21 | #include <linux/cdev.h> | 22 | #include <linux/cdev.h> |
| 22 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
| @@ -147,13 +148,13 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | |||
| 147 | inode->i_cdev = NULL; | 148 | inode->i_cdev = NULL; |
| 148 | inode->i_rdev = 0; | 149 | inode->i_rdev = 0; |
| 149 | inode->dirtied_when = 0; | 150 | inode->dirtied_when = 0; |
| 150 | if (security_inode_alloc(inode)) { | 151 | |
| 151 | if (inode->i_sb->s_op->destroy_inode) | 152 | if (security_inode_alloc(inode)) |
| 152 | inode->i_sb->s_op->destroy_inode(inode); | 153 | goto out_free_inode; |
| 153 | else | 154 | |
| 154 | kmem_cache_free(inode_cachep, (inode)); | 155 | /* allocate and initialize an i_integrity */ |
| 155 | return NULL; | 156 | if (ima_inode_alloc(inode)) |
| 156 | } | 157 | goto out_free_security; |
| 157 | 158 | ||
| 158 | spin_lock_init(&inode->i_lock); | 159 | spin_lock_init(&inode->i_lock); |
| 159 | lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); | 160 | lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); |
| @@ -189,6 +190,15 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) | |||
| 189 | inode->i_mapping = mapping; | 190 | inode->i_mapping = mapping; |
| 190 | 191 | ||
| 191 | return inode; | 192 | return inode; |
| 193 | |||
| 194 | out_free_security: | ||
| 195 | security_inode_free(inode); | ||
| 196 | out_free_inode: | ||
| 197 | if (inode->i_sb->s_op->destroy_inode) | ||
| 198 | inode->i_sb->s_op->destroy_inode(inode); | ||
| 199 | else | ||
| 200 | kmem_cache_free(inode_cachep, (inode)); | ||
| 201 | return NULL; | ||
| 192 | } | 202 | } |
| 193 | EXPORT_SYMBOL(inode_init_always); | 203 | EXPORT_SYMBOL(inode_init_always); |
| 194 | 204 | ||
| @@ -1290,6 +1300,40 @@ sector_t bmap(struct inode * inode, sector_t block) | |||
| 1290 | } | 1300 | } |
| 1291 | EXPORT_SYMBOL(bmap); | 1301 | EXPORT_SYMBOL(bmap); |
| 1292 | 1302 | ||
| 1303 | /* | ||
| 1304 | * With relative atime, only update atime if the previous atime is | ||
| 1305 | * earlier than either the ctime or mtime or if at least a day has | ||
| 1306 | * passed since the last atime update. | ||
| 1307 | */ | ||
| 1308 | static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, | ||
| 1309 | struct timespec now) | ||
| 1310 | { | ||
| 1311 | |||
| 1312 | if (!(mnt->mnt_flags & MNT_RELATIME)) | ||
| 1313 | return 1; | ||
| 1314 | /* | ||
| 1315 | * Is mtime younger than atime? If yes, update atime: | ||
| 1316 | */ | ||
| 1317 | if (timespec_compare(&inode->i_mtime, &inode->i_atime) >= 0) | ||
| 1318 | return 1; | ||
| 1319 | /* | ||
| 1320 | * Is ctime younger than atime? If yes, update atime: | ||
| 1321 | */ | ||
| 1322 | if (timespec_compare(&inode->i_ctime, &inode->i_atime) >= 0) | ||
| 1323 | return 1; | ||
| 1324 | |||
| 1325 | /* | ||
| 1326 | * Is the previous atime value older than a day? If yes, | ||
| 1327 | * update atime: | ||
| 1328 | */ | ||
| 1329 | if ((long)(now.tv_sec - inode->i_atime.tv_sec) >= 24*60*60) | ||
| 1330 | return 1; | ||
| 1331 | /* | ||
| 1332 | * Good, we can skip the atime update: | ||
| 1333 | */ | ||
| 1334 | return 0; | ||
| 1335 | } | ||
| 1336 | |||
| 1293 | /** | 1337 | /** |
| 1294 | * touch_atime - update the access time | 1338 | * touch_atime - update the access time |
| 1295 | * @mnt: mount the inode is accessed on | 1339 | * @mnt: mount the inode is accessed on |
| @@ -1317,17 +1361,12 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry) | |||
| 1317 | goto out; | 1361 | goto out; |
| 1318 | if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) | 1362 | if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) |
| 1319 | goto out; | 1363 | goto out; |
| 1320 | if (mnt->mnt_flags & MNT_RELATIME) { | ||
| 1321 | /* | ||
| 1322 | * With relative atime, only update atime if the previous | ||
| 1323 | * atime is earlier than either the ctime or mtime. | ||
| 1324 | */ | ||
| 1325 | if (timespec_compare(&inode->i_mtime, &inode->i_atime) < 0 && | ||
| 1326 | timespec_compare(&inode->i_ctime, &inode->i_atime) < 0) | ||
| 1327 | goto out; | ||
| 1328 | } | ||
| 1329 | 1364 | ||
| 1330 | now = current_fs_time(inode->i_sb); | 1365 | now = current_fs_time(inode->i_sb); |
| 1366 | |||
| 1367 | if (!relatime_need_update(mnt, inode, now)) | ||
| 1368 | goto out; | ||
| 1369 | |||
| 1331 | if (timespec_equal(&inode->i_atime, &now)) | 1370 | if (timespec_equal(&inode->i_atime, &now)) |
| 1332 | goto out; | 1371 | goto out; |
| 1333 | 1372 | ||
