diff options
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 89 |
1 files changed, 55 insertions, 34 deletions
diff --git a/fs/inode.c b/fs/inode.c index 76582b06ab97..4d8e3be55976 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1241,7 +1241,16 @@ void generic_delete_inode(struct inode *inode) | |||
1241 | } | 1241 | } |
1242 | EXPORT_SYMBOL(generic_delete_inode); | 1242 | EXPORT_SYMBOL(generic_delete_inode); |
1243 | 1243 | ||
1244 | static void generic_forget_inode(struct inode *inode) | 1244 | /** |
1245 | * generic_detach_inode - remove inode from inode lists | ||
1246 | * @inode: inode to remove | ||
1247 | * | ||
1248 | * Remove inode from inode lists, write it if it's dirty. This is just an | ||
1249 | * internal VFS helper exported for hugetlbfs. Do not use! | ||
1250 | * | ||
1251 | * Returns 1 if inode should be completely destroyed. | ||
1252 | */ | ||
1253 | int generic_detach_inode(struct inode *inode) | ||
1245 | { | 1254 | { |
1246 | struct super_block *sb = inode->i_sb; | 1255 | struct super_block *sb = inode->i_sb; |
1247 | 1256 | ||
@@ -1251,7 +1260,7 @@ static void generic_forget_inode(struct inode *inode) | |||
1251 | inodes_stat.nr_unused++; | 1260 | inodes_stat.nr_unused++; |
1252 | if (sb->s_flags & MS_ACTIVE) { | 1261 | if (sb->s_flags & MS_ACTIVE) { |
1253 | spin_unlock(&inode_lock); | 1262 | spin_unlock(&inode_lock); |
1254 | return; | 1263 | return 0; |
1255 | } | 1264 | } |
1256 | WARN_ON(inode->i_state & I_NEW); | 1265 | WARN_ON(inode->i_state & I_NEW); |
1257 | inode->i_state |= I_WILL_FREE; | 1266 | inode->i_state |= I_WILL_FREE; |
@@ -1269,6 +1278,14 @@ static void generic_forget_inode(struct inode *inode) | |||
1269 | inode->i_state |= I_FREEING; | 1278 | inode->i_state |= I_FREEING; |
1270 | inodes_stat.nr_inodes--; | 1279 | inodes_stat.nr_inodes--; |
1271 | spin_unlock(&inode_lock); | 1280 | spin_unlock(&inode_lock); |
1281 | return 1; | ||
1282 | } | ||
1283 | EXPORT_SYMBOL_GPL(generic_detach_inode); | ||
1284 | |||
1285 | static void generic_forget_inode(struct inode *inode) | ||
1286 | { | ||
1287 | if (!generic_detach_inode(inode)) | ||
1288 | return; | ||
1272 | if (inode->i_data.nrpages) | 1289 | if (inode->i_data.nrpages) |
1273 | truncate_inode_pages(&inode->i_data, 0); | 1290 | truncate_inode_pages(&inode->i_data, 0); |
1274 | clear_inode(inode); | 1291 | clear_inode(inode); |
@@ -1399,31 +1416,31 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry) | |||
1399 | struct inode *inode = dentry->d_inode; | 1416 | struct inode *inode = dentry->d_inode; |
1400 | struct timespec now; | 1417 | struct timespec now; |
1401 | 1418 | ||
1402 | if (mnt_want_write(mnt)) | ||
1403 | return; | ||
1404 | if (inode->i_flags & S_NOATIME) | 1419 | if (inode->i_flags & S_NOATIME) |
1405 | goto out; | 1420 | return; |
1406 | if (IS_NOATIME(inode)) | 1421 | if (IS_NOATIME(inode)) |
1407 | goto out; | 1422 | return; |
1408 | if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) | 1423 | if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)) |
1409 | goto out; | 1424 | return; |
1410 | 1425 | ||
1411 | if (mnt->mnt_flags & MNT_NOATIME) | 1426 | if (mnt->mnt_flags & MNT_NOATIME) |
1412 | goto out; | 1427 | return; |
1413 | if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) | 1428 | if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)) |
1414 | goto out; | 1429 | return; |
1415 | 1430 | ||
1416 | now = current_fs_time(inode->i_sb); | 1431 | now = current_fs_time(inode->i_sb); |
1417 | 1432 | ||
1418 | if (!relatime_need_update(mnt, inode, now)) | 1433 | if (!relatime_need_update(mnt, inode, now)) |
1419 | goto out; | 1434 | return; |
1420 | 1435 | ||
1421 | if (timespec_equal(&inode->i_atime, &now)) | 1436 | if (timespec_equal(&inode->i_atime, &now)) |
1422 | goto out; | 1437 | return; |
1438 | |||
1439 | if (mnt_want_write(mnt)) | ||
1440 | return; | ||
1423 | 1441 | ||
1424 | inode->i_atime = now; | 1442 | inode->i_atime = now; |
1425 | mark_inode_dirty_sync(inode); | 1443 | mark_inode_dirty_sync(inode); |
1426 | out: | ||
1427 | mnt_drop_write(mnt); | 1444 | mnt_drop_write(mnt); |
1428 | } | 1445 | } |
1429 | EXPORT_SYMBOL(touch_atime); | 1446 | EXPORT_SYMBOL(touch_atime); |
@@ -1444,34 +1461,37 @@ void file_update_time(struct file *file) | |||
1444 | { | 1461 | { |
1445 | struct inode *inode = file->f_path.dentry->d_inode; | 1462 | struct inode *inode = file->f_path.dentry->d_inode; |
1446 | struct timespec now; | 1463 | struct timespec now; |
1447 | int sync_it = 0; | 1464 | enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; |
1448 | int err; | ||
1449 | 1465 | ||
1466 | /* First try to exhaust all avenues to not sync */ | ||
1450 | if (IS_NOCMTIME(inode)) | 1467 | if (IS_NOCMTIME(inode)) |
1451 | return; | 1468 | return; |
1452 | 1469 | ||
1453 | err = mnt_want_write_file(file); | ||
1454 | if (err) | ||
1455 | return; | ||
1456 | |||
1457 | now = current_fs_time(inode->i_sb); | 1470 | now = current_fs_time(inode->i_sb); |
1458 | if (!timespec_equal(&inode->i_mtime, &now)) { | 1471 | if (!timespec_equal(&inode->i_mtime, &now)) |
1459 | inode->i_mtime = now; | 1472 | sync_it = S_MTIME; |
1460 | sync_it = 1; | ||
1461 | } | ||
1462 | 1473 | ||
1463 | if (!timespec_equal(&inode->i_ctime, &now)) { | 1474 | if (!timespec_equal(&inode->i_ctime, &now)) |
1464 | inode->i_ctime = now; | 1475 | sync_it |= S_CTIME; |
1465 | sync_it = 1; | ||
1466 | } | ||
1467 | 1476 | ||
1468 | if (IS_I_VERSION(inode)) { | 1477 | if (IS_I_VERSION(inode)) |
1469 | inode_inc_iversion(inode); | 1478 | sync_it |= S_VERSION; |
1470 | sync_it = 1; | 1479 | |
1471 | } | 1480 | if (!sync_it) |
1481 | return; | ||
1472 | 1482 | ||
1473 | if (sync_it) | 1483 | /* Finally allowed to write? Takes lock. */ |
1474 | mark_inode_dirty_sync(inode); | 1484 | if (mnt_want_write_file(file)) |
1485 | return; | ||
1486 | |||
1487 | /* Only change inode inside the lock region */ | ||
1488 | if (sync_it & S_VERSION) | ||
1489 | inode_inc_iversion(inode); | ||
1490 | if (sync_it & S_CTIME) | ||
1491 | inode->i_ctime = now; | ||
1492 | if (sync_it & S_MTIME) | ||
1493 | inode->i_mtime = now; | ||
1494 | mark_inode_dirty_sync(inode); | ||
1475 | mnt_drop_write(file->f_path.mnt); | 1495 | mnt_drop_write(file->f_path.mnt); |
1476 | } | 1496 | } |
1477 | EXPORT_SYMBOL(file_update_time); | 1497 | EXPORT_SYMBOL(file_update_time); |
@@ -1599,7 +1619,8 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) | |||
1599 | else if (S_ISSOCK(mode)) | 1619 | else if (S_ISSOCK(mode)) |
1600 | inode->i_fop = &bad_sock_fops; | 1620 | inode->i_fop = &bad_sock_fops; |
1601 | else | 1621 | else |
1602 | printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o)\n", | 1622 | printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for" |
1603 | mode); | 1623 | " inode %s:%lu\n", mode, inode->i_sb->s_id, |
1624 | inode->i_ino); | ||
1604 | } | 1625 | } |
1605 | EXPORT_SYMBOL(init_special_inode); | 1626 | EXPORT_SYMBOL(init_special_inode); |