aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 4fca82e5276..d5a269a51a9 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 0d049202808..b2aa722e5ea 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 504e61b7fd7..9562109d3a8 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 a79555e492e..f0335fc315e 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 3ff5fcc1528..122e260247f 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 8639169221c..7389d2d5e51 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 95ebb56de49..49c1065256f 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 f8476841eb0..47c4c1ad0c0 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 8d214b87f6b..9f7ec15a652 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 cdc1a963094..57fc70574d2 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 21e5abfbcdf..51070f1f1b5 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 a4eb3113222..213ca1f5340 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