aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/filesystems/Locking3
-rw-r--r--Documentation/filesystems/vfs.txt4
-rw-r--r--fs/fuse/file.c4
-rw-r--r--fs/inode.c56
-rw-r--r--fs/ncpfs/file.c6
-rw-r--r--fs/ntfs/file.c4
-rw-r--r--fs/pipe.c7
-rw-r--r--fs/splice.c6
-rw-r--r--fs/xfs/xfs_file.c7
-rw-r--r--include/linux/fs.h10
-rw-r--r--mm/filemap.c4
-rw-r--r--mm/filemap_xip.c4
12 files changed, 86 insertions, 29 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 4fca82e5276e..d5a269a51a9e 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -62,6 +62,7 @@ ata *);
62 int (*removexattr) (struct dentry *, const char *); 62 int (*removexattr) (struct dentry *, const char *);
63 void (*truncate_range)(struct inode *, loff_t, loff_t); 63 void (*truncate_range)(struct inode *, loff_t, loff_t);
64 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); 64 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
65 void (*update_time)(struct inode *, struct timespec *, int);
65 66
66locking rules: 67locking rules:
67 all may block 68 all may block
@@ -89,6 +90,8 @@ listxattr: no
89removexattr: yes 90removexattr: yes
90truncate_range: yes 91truncate_range: yes
91fiemap: no 92fiemap: no
93update_time: no
94
92 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on 95 Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
93victim. 96victim.
94 cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem. 97 cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 0d0492028082..b2aa722e5ea2 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -364,6 +364,7 @@ struct inode_operations {
364 ssize_t (*listxattr) (struct dentry *, char *, size_t); 364 ssize_t (*listxattr) (struct dentry *, char *, size_t);
365 int (*removexattr) (struct dentry *, const char *); 365 int (*removexattr) (struct dentry *, const char *);
366 void (*truncate_range)(struct inode *, loff_t, loff_t); 366 void (*truncate_range)(struct inode *, loff_t, loff_t);
367 void (*update_time)(struct inode *, struct timespec *, int);
367}; 368};
368 369
369Again, all methods are called without any locks being held, unless 370Again, all methods are called without any locks being held, unless
@@ -475,6 +476,9 @@ otherwise noted.
475 truncate_range: a method provided by the underlying filesystem to truncate a 476 truncate_range: a method provided by the underlying filesystem to truncate a
476 range of blocks , i.e. punch a hole somewhere in a file. 477 range of blocks , i.e. punch a hole somewhere in a file.
477 478
479 update_time: called by the VFS to update a specific time or the i_version of
480 an inode. If this is not defined the VFS will update the inode itself
481 and call mark_inode_dirty_sync.
478 482
479The Address Space Object 483The Address Space Object
480======================== 484========================
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 504e61b7fd75..9562109d3a87 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -962,7 +962,9 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
962 if (err) 962 if (err)
963 goto out; 963 goto out;
964 964
965 file_update_time(file); 965 err = file_update_time(file);
966 if (err)
967 goto out;
966 968
967 if (file->f_flags & O_DIRECT) { 969 if (file->f_flags & O_DIRECT) {
968 written = generic_file_direct_write(iocb, iov, &nr_segs, 970 written = generic_file_direct_write(iocb, iov, &nr_segs,
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
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 3ff5fcc1528f..122e260247f5 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -221,6 +221,10 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
221 221
222 already_written = 0; 222 already_written = 0;
223 223
224 errno = file_update_time(file);
225 if (errno)
226 goto outrel;
227
224 bouncebuffer = vmalloc(bufsize); 228 bouncebuffer = vmalloc(bufsize);
225 if (!bouncebuffer) { 229 if (!bouncebuffer) {
226 errno = -EIO; /* -ENOMEM */ 230 errno = -EIO; /* -ENOMEM */
@@ -252,8 +256,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
252 } 256 }
253 vfree(bouncebuffer); 257 vfree(bouncebuffer);
254 258
255 file_update_time(file);
256
257 *ppos = pos; 259 *ppos = pos;
258 260
259 if (pos > i_size_read(inode)) { 261 if (pos > i_size_read(inode)) {
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 8639169221c7..7389d2d5e51d 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2096,7 +2096,9 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
2096 err = file_remove_suid(file); 2096 err = file_remove_suid(file);
2097 if (err) 2097 if (err)
2098 goto out; 2098 goto out;
2099 file_update_time(file); 2099 err = file_update_time(file);
2100 if (err)
2101 goto out;
2100 written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos, 2102 written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
2101 count); 2103 count);
2102out: 2104out:
diff --git a/fs/pipe.c b/fs/pipe.c
index 95ebb56de494..49c1065256fd 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -654,8 +654,11 @@ out:
654 wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM); 654 wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
655 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); 655 kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
656 } 656 }
657 if (ret > 0) 657 if (ret > 0) {
658 file_update_time(filp); 658 int err = file_update_time(filp);
659 if (err)
660 ret = err;
661 }
659 return ret; 662 return ret;
660} 663}
661 664
diff --git a/fs/splice.c b/fs/splice.c
index f8476841eb04..47c4c1ad0c04 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1003,8 +1003,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
1003 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD); 1003 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
1004 ret = file_remove_suid(out); 1004 ret = file_remove_suid(out);
1005 if (!ret) { 1005 if (!ret) {
1006 file_update_time(out); 1006 ret = file_update_time(out);
1007 ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file); 1007 if (!ret)
1008 ret = splice_from_pipe_feed(pipe, &sd,
1009 pipe_to_file);
1008 } 1010 }
1009 mutex_unlock(&inode->i_mutex); 1011 mutex_unlock(&inode->i_mutex);
1010 } while (ret > 0); 1012 } while (ret > 0);
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 8d214b87f6bb..9f7ec15a6522 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -586,8 +586,11 @@ restart:
586 * lock above. Eventually we should look into a way to avoid 586 * lock above. Eventually we should look into a way to avoid
587 * the pointless lock roundtrip. 587 * the pointless lock roundtrip.
588 */ 588 */
589 if (likely(!(file->f_mode & FMODE_NOCMTIME))) 589 if (likely(!(file->f_mode & FMODE_NOCMTIME))) {
590 file_update_time(file); 590 error = file_update_time(file);
591 if (error)
592 return error;
593 }
591 594
592 /* 595 /*
593 * If we're writing the file then make sure to clear the setuid and 596 * If we're writing the file then make sure to clear the setuid and
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cdc1a9630948..57fc70574d20 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1684,6 +1684,7 @@ struct inode_operations {
1684 void (*truncate_range)(struct inode *, loff_t, loff_t); 1684 void (*truncate_range)(struct inode *, loff_t, loff_t);
1685 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, 1685 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1686 u64 len); 1686 u64 len);
1687 int (*update_time)(struct inode *, struct timespec *, int);
1687} ____cacheline_aligned; 1688} ____cacheline_aligned;
1688 1689
1689struct seq_file; 1690struct seq_file;
@@ -1843,6 +1844,13 @@ static inline void inode_inc_iversion(struct inode *inode)
1843 spin_unlock(&inode->i_lock); 1844 spin_unlock(&inode->i_lock);
1844} 1845}
1845 1846
1847enum file_time_flags {
1848 S_ATIME = 1,
1849 S_MTIME = 2,
1850 S_CTIME = 4,
1851 S_VERSION = 8,
1852};
1853
1846extern void touch_atime(struct path *); 1854extern void touch_atime(struct path *);
1847static inline void file_accessed(struct file *file) 1855static inline void file_accessed(struct file *file)
1848{ 1856{
@@ -2579,7 +2587,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *);
2579extern int inode_newsize_ok(const struct inode *, loff_t offset); 2587extern int inode_newsize_ok(const struct inode *, loff_t offset);
2580extern void setattr_copy(struct inode *inode, const struct iattr *attr); 2588extern void setattr_copy(struct inode *inode, const struct iattr *attr);
2581 2589
2582extern void file_update_time(struct file *file); 2590extern int file_update_time(struct file *file);
2583 2591
2584extern int generic_show_options(struct seq_file *m, struct dentry *root); 2592extern int generic_show_options(struct seq_file *m, struct dentry *root);
2585extern void save_mount_options(struct super_block *sb, char *options); 2593extern void save_mount_options(struct super_block *sb, char *options);
diff --git a/mm/filemap.c b/mm/filemap.c
index 21e5abfbcdf6..51070f1f1b52 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2463,7 +2463,9 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
2463 if (err) 2463 if (err)
2464 goto out; 2464 goto out;
2465 2465
2466 file_update_time(file); 2466 err = file_update_time(file);
2467 if (err)
2468 goto out;
2467 2469
2468 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */ 2470 /* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
2469 if (unlikely(file->f_flags & O_DIRECT)) { 2471 if (unlikely(file->f_flags & O_DIRECT)) {
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index a4eb31132229..213ca1f53409 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -426,7 +426,9 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
426 if (ret) 426 if (ret)
427 goto out_backing; 427 goto out_backing;
428 428
429 file_update_time(filp); 429 ret = file_update_time(filp);
430 if (ret)
431 goto out_backing;
430 432
431 ret = __xip_file_write (filp, buf, count, pos, ppos); 433 ret = __xip_file_write (filp, buf, count, pos, ppos);
432 434