aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2012-03-26 09:59:21 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-06-01 12:07:25 -0400
commitc3b2da314834499f34cba94f7053e55f6d6f92d8 (patch)
tree7012b569ee9e0781761a8eb388190979441583c7 /fs/inode.c
parent033369d1af1264abc23bea2e174aa47cdd212f6f (diff)
fs: introduce inode operation ->update_time
Btrfs has to make sure we have space to allocate new blocks in order to modify the inode, so updating time can fail. We've gotten around this by having our own file_update_time but this is kind of a pain, and Christoph has indicated he would like to make xfs do something different with atime updates. So introduce ->update_time, where we will deal with i_version an a/m/c time updates and indicate which changes need to be made. The normal version just does what it has always done, updates the time and marks the inode dirty, and then filesystems can choose to do something different. I've gone through all of the users of file_update_time and made them check for errors with the exception of the fault code since it's complicated and I wasn't quite sure what to do there, also Jan is going to be pushing the file time updates into page_mkwrite for those who have it so that should satisfy btrfs and make it not a big deal to check the file_update_time() return code in the generic fault path. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c56
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 */
1494static 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}
1531EXPORT_SYMBOL(touch_atime); 1558EXPORT_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
1610void file_update_time(struct file *file) 1638int 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}
1647EXPORT_SYMBOL(file_update_time); 1671EXPORT_SYMBOL(file_update_time);
1648 1672