diff options
Diffstat (limited to 'fs/inode.c')
-rw-r--r-- | fs/inode.c | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/fs/inode.c b/fs/inode.c index a79555e492e0..f0335fc315ed 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1487,6 +1487,27 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode, | |||
1487 | return 0; | 1487 | return 0; |
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | /* | ||
1491 | * This does the actual work of updating an inodes time or version. Must have | ||
1492 | * had called mnt_want_write() before calling this. | ||
1493 | */ | ||
1494 | static int update_time(struct inode *inode, struct timespec *time, int flags) | ||
1495 | { | ||
1496 | if (inode->i_op->update_time) | ||
1497 | return inode->i_op->update_time(inode, time, flags); | ||
1498 | |||
1499 | if (flags & S_ATIME) | ||
1500 | inode->i_atime = *time; | ||
1501 | if (flags & S_VERSION) | ||
1502 | inode_inc_iversion(inode); | ||
1503 | if (flags & S_CTIME) | ||
1504 | inode->i_ctime = *time; | ||
1505 | if (flags & S_MTIME) | ||
1506 | inode->i_mtime = *time; | ||
1507 | mark_inode_dirty_sync(inode); | ||
1508 | return 0; | ||
1509 | } | ||
1510 | |||
1490 | /** | 1511 | /** |
1491 | * touch_atime - update the access time | 1512 | * touch_atime - update the access time |
1492 | * @path: the &struct path to update | 1513 | * @path: the &struct path to update |
@@ -1524,8 +1545,14 @@ void touch_atime(struct path *path) | |||
1524 | if (mnt_want_write(mnt)) | 1545 | if (mnt_want_write(mnt)) |
1525 | return; | 1546 | return; |
1526 | 1547 | ||
1527 | inode->i_atime = now; | 1548 | /* |
1528 | mark_inode_dirty_sync(inode); | 1549 | * File systems can error out when updating inodes if they need to |
1550 | * allocate new space to modify an inode (such is the case for | ||
1551 | * Btrfs), but since we touch atime while walking down the path we | ||
1552 | * really don't care if we failed to update the atime of the file, | ||
1553 | * so just ignore the return value. | ||
1554 | */ | ||
1555 | update_time(inode, &now, S_ATIME); | ||
1529 | mnt_drop_write(mnt); | 1556 | mnt_drop_write(mnt); |
1530 | } | 1557 | } |
1531 | EXPORT_SYMBOL(touch_atime); | 1558 | EXPORT_SYMBOL(touch_atime); |
@@ -1604,18 +1631,20 @@ EXPORT_SYMBOL(file_remove_suid); | |||
1604 | * usage in the file write path of filesystems, and filesystems may | 1631 | * usage in the file write path of filesystems, and filesystems may |
1605 | * choose to explicitly ignore update via this function with the | 1632 | * choose to explicitly ignore update via this function with the |
1606 | * S_NOCMTIME inode flag, e.g. for network filesystem where these | 1633 | * S_NOCMTIME inode flag, e.g. for network filesystem where these |
1607 | * timestamps are handled by the server. | 1634 | * timestamps are handled by the server. This can return an error for |
1635 | * file systems who need to allocate space in order to update an inode. | ||
1608 | */ | 1636 | */ |
1609 | 1637 | ||
1610 | void file_update_time(struct file *file) | 1638 | int file_update_time(struct file *file) |
1611 | { | 1639 | { |
1612 | struct inode *inode = file->f_path.dentry->d_inode; | 1640 | struct inode *inode = file->f_path.dentry->d_inode; |
1613 | struct timespec now; | 1641 | struct timespec now; |
1614 | enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; | 1642 | int sync_it = 0; |
1643 | int ret; | ||
1615 | 1644 | ||
1616 | /* First try to exhaust all avenues to not sync */ | 1645 | /* First try to exhaust all avenues to not sync */ |
1617 | if (IS_NOCMTIME(inode)) | 1646 | if (IS_NOCMTIME(inode)) |
1618 | return; | 1647 | return 0; |
1619 | 1648 | ||
1620 | now = current_fs_time(inode->i_sb); | 1649 | now = current_fs_time(inode->i_sb); |
1621 | if (!timespec_equal(&inode->i_mtime, &now)) | 1650 | if (!timespec_equal(&inode->i_mtime, &now)) |
@@ -1628,21 +1657,16 @@ void file_update_time(struct file *file) | |||
1628 | sync_it |= S_VERSION; | 1657 | sync_it |= S_VERSION; |
1629 | 1658 | ||
1630 | if (!sync_it) | 1659 | if (!sync_it) |
1631 | return; | 1660 | return 0; |
1632 | 1661 | ||
1633 | /* Finally allowed to write? Takes lock. */ | 1662 | /* Finally allowed to write? Takes lock. */ |
1634 | if (mnt_want_write_file(file)) | 1663 | if (mnt_want_write_file(file)) |
1635 | return; | 1664 | return 0; |
1636 | 1665 | ||
1637 | /* Only change inode inside the lock region */ | 1666 | ret = update_time(inode, &now, sync_it); |
1638 | if (sync_it & S_VERSION) | ||
1639 | inode_inc_iversion(inode); | ||
1640 | if (sync_it & S_CTIME) | ||
1641 | inode->i_ctime = now; | ||
1642 | if (sync_it & S_MTIME) | ||
1643 | inode->i_mtime = now; | ||
1644 | mark_inode_dirty_sync(inode); | ||
1645 | mnt_drop_write_file(file); | 1667 | mnt_drop_write_file(file); |
1668 | |||
1669 | return ret; | ||
1646 | } | 1670 | } |
1647 | EXPORT_SYMBOL(file_update_time); | 1671 | EXPORT_SYMBOL(file_update_time); |
1648 | 1672 | ||