aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-06-29 15:14:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-06-29 15:14:37 -0400
commit4f46accee45d74a408e417c04c0ed1543a7c51e9 (patch)
treed7bf042ab27280c9f45c1ab3959e65a3db131f59 /fs
parent543cf4cb3fe6f6cae3651ba918b9c56200b257d0 (diff)
parentcdd16d0265c9234228fd37fbbad844d7e894b278 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: [patch 2/3] vfs: dcache cleanups [patch 1/3] vfs: dcache sparse fixes [patch 3/3] vfs: make d_path() consistent across mount operations [patch 4/4] flock: remove unused fields from file_lock_operations [patch 3/4] vfs: fix ERR_PTR abuse in generic_readlink [patch 2/4] fs: make struct file arg to d_path const [patch 1/4] vfs: path_{get,put}() cleanups [patch for 2.6.26 4/4] vfs: utimensat(): fix write access check for futimens() [patch for 2.6.26 3/4] vfs: utimensat(): fix error checking for {UTIME_NOW,UTIME_OMIT} case [patch for 2.6.26 1/4] vfs: utimensat(): ignore tv_sec if tv_nsec == UTIME_OMIT or UTIME_NOW [patch for 2.6.26 2/4] vfs: utimensat(): be consistent with utime() for immutable and append-only files [PATCH] fix cgroup-inflicted breakage in block_dev.c
Diffstat (limited to 'fs')
-rw-r--r--fs/block_dev.c10
-rw-r--r--fs/dcache.c68
-rw-r--r--fs/locks.c6
-rw-r--r--fs/namei.c26
-rw-r--r--fs/pipe.c10
-rw-r--r--fs/utimes.c59
6 files changed, 88 insertions, 91 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 470c10ceb0fb..10d8a0aa871a 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -931,8 +931,16 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part)
931 struct gendisk *disk; 931 struct gendisk *disk;
932 int ret; 932 int ret;
933 int part; 933 int part;
934 int perm = 0;
934 935
935 ret = devcgroup_inode_permission(bdev->bd_inode, file->f_mode); 936 if (file->f_mode & FMODE_READ)
937 perm |= MAY_READ;
938 if (file->f_mode & FMODE_WRITE)
939 perm |= MAY_WRITE;
940 /*
941 * hooks: /n/, see "layering violations".
942 */
943 ret = devcgroup_inode_permission(bdev->bd_inode, perm);
936 if (ret != 0) 944 if (ret != 0)
937 return ret; 945 return ret;
938 946
diff --git a/fs/dcache.c b/fs/dcache.c
index 3ee588d5f585..6068c25b393c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -17,6 +17,7 @@
17#include <linux/syscalls.h> 17#include <linux/syscalls.h>
18#include <linux/string.h> 18#include <linux/string.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/fdtable.h>
20#include <linux/fs.h> 21#include <linux/fs.h>
21#include <linux/fsnotify.h> 22#include <linux/fsnotify.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
@@ -106,9 +107,10 @@ static void dentry_lru_remove(struct dentry *dentry)
106/* 107/*
107 * Release the dentry's inode, using the filesystem 108 * Release the dentry's inode, using the filesystem
108 * d_iput() operation if defined. 109 * d_iput() operation if defined.
109 * Called with dcache_lock and per dentry lock held, drops both.
110 */ 110 */
111static void dentry_iput(struct dentry * dentry) 111static void dentry_iput(struct dentry * dentry)
112 __releases(dentry->d_lock)
113 __releases(dcache_lock)
112{ 114{
113 struct inode *inode = dentry->d_inode; 115 struct inode *inode = dentry->d_inode;
114 if (inode) { 116 if (inode) {
@@ -132,12 +134,13 @@ static void dentry_iput(struct dentry * dentry)
132 * d_kill - kill dentry and return parent 134 * d_kill - kill dentry and return parent
133 * @dentry: dentry to kill 135 * @dentry: dentry to kill
134 * 136 *
135 * Called with dcache_lock and d_lock, releases both. The dentry must 137 * The dentry must already be unhashed and removed from the LRU.
136 * already be unhashed and removed from the LRU.
137 * 138 *
138 * If this is the root of the dentry tree, return NULL. 139 * If this is the root of the dentry tree, return NULL.
139 */ 140 */
140static struct dentry *d_kill(struct dentry *dentry) 141static struct dentry *d_kill(struct dentry *dentry)
142 __releases(dentry->d_lock)
143 __releases(dcache_lock)
141{ 144{
142 struct dentry *parent; 145 struct dentry *parent;
143 146
@@ -383,11 +386,11 @@ restart:
383 * Try to prune ancestors as well. This is necessary to prevent 386 * Try to prune ancestors as well. This is necessary to prevent
384 * quadratic behavior of shrink_dcache_parent(), but is also expected 387 * quadratic behavior of shrink_dcache_parent(), but is also expected
385 * to be beneficial in reducing dentry cache fragmentation. 388 * to be beneficial in reducing dentry cache fragmentation.
386 *
387 * Called with dcache_lock, drops it and then regains.
388 * Called with dentry->d_lock held, drops it.
389 */ 389 */
390static void prune_one_dentry(struct dentry * dentry) 390static void prune_one_dentry(struct dentry * dentry)
391 __releases(dentry->d_lock)
392 __releases(dcache_lock)
393 __acquires(dcache_lock)
391{ 394{
392 __d_drop(dentry); 395 __d_drop(dentry);
393 dentry = d_kill(dentry); 396 dentry = d_kill(dentry);
@@ -1604,10 +1607,9 @@ static int d_isparent(struct dentry *p1, struct dentry *p2)
1604 * 1607 *
1605 * Note: If ever the locking in lock_rename() changes, then please 1608 * Note: If ever the locking in lock_rename() changes, then please
1606 * remember to update this too... 1609 * remember to update this too...
1607 *
1608 * On return, dcache_lock will have been unlocked.
1609 */ 1610 */
1610static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias) 1611static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias)
1612 __releases(dcache_lock)
1611{ 1613{
1612 struct mutex *m1 = NULL, *m2 = NULL; 1614 struct mutex *m1 = NULL, *m2 = NULL;
1613 struct dentry *ret; 1615 struct dentry *ret;
@@ -1743,11 +1745,9 @@ out_nolock:
1743shouldnt_be_hashed: 1745shouldnt_be_hashed:
1744 spin_unlock(&dcache_lock); 1746 spin_unlock(&dcache_lock);
1745 BUG(); 1747 BUG();
1746 goto shouldnt_be_hashed;
1747} 1748}
1748 1749
1749static int prepend(char **buffer, int *buflen, const char *str, 1750static int prepend(char **buffer, int *buflen, const char *str, int namelen)
1750 int namelen)
1751{ 1751{
1752 *buflen -= namelen; 1752 *buflen -= namelen;
1753 if (*buflen < 0) 1753 if (*buflen < 0)
@@ -1757,8 +1757,13 @@ static int prepend(char **buffer, int *buflen, const char *str,
1757 return 0; 1757 return 0;
1758} 1758}
1759 1759
1760static int prepend_name(char **buffer, int *buflen, struct qstr *name)
1761{
1762 return prepend(buffer, buflen, name->name, name->len);
1763}
1764
1760/** 1765/**
1761 * d_path - return the path of a dentry 1766 * __d_path - return the path of a dentry
1762 * @path: the dentry/vfsmount to report 1767 * @path: the dentry/vfsmount to report
1763 * @root: root vfsmnt/dentry (may be modified by this function) 1768 * @root: root vfsmnt/dentry (may be modified by this function)
1764 * @buffer: buffer to return value in 1769 * @buffer: buffer to return value in
@@ -1779,9 +1784,10 @@ char *__d_path(const struct path *path, struct path *root,
1779{ 1784{
1780 struct dentry *dentry = path->dentry; 1785 struct dentry *dentry = path->dentry;
1781 struct vfsmount *vfsmnt = path->mnt; 1786 struct vfsmount *vfsmnt = path->mnt;
1782 char * end = buffer+buflen; 1787 char *end = buffer + buflen;
1783 char * retval; 1788 char *retval;
1784 1789
1790 spin_lock(&vfsmount_lock);
1785 prepend(&end, &buflen, "\0", 1); 1791 prepend(&end, &buflen, "\0", 1);
1786 if (!IS_ROOT(dentry) && d_unhashed(dentry) && 1792 if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
1787 (prepend(&end, &buflen, " (deleted)", 10) != 0)) 1793 (prepend(&end, &buflen, " (deleted)", 10) != 0))
@@ -1800,38 +1806,37 @@ char *__d_path(const struct path *path, struct path *root,
1800 break; 1806 break;
1801 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { 1807 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
1802 /* Global root? */ 1808 /* Global root? */
1803 spin_lock(&vfsmount_lock);
1804 if (vfsmnt->mnt_parent == vfsmnt) { 1809 if (vfsmnt->mnt_parent == vfsmnt) {
1805 spin_unlock(&vfsmount_lock);
1806 goto global_root; 1810 goto global_root;
1807 } 1811 }
1808 dentry = vfsmnt->mnt_mountpoint; 1812 dentry = vfsmnt->mnt_mountpoint;
1809 vfsmnt = vfsmnt->mnt_parent; 1813 vfsmnt = vfsmnt->mnt_parent;
1810 spin_unlock(&vfsmount_lock);
1811 continue; 1814 continue;
1812 } 1815 }
1813 parent = dentry->d_parent; 1816 parent = dentry->d_parent;
1814 prefetch(parent); 1817 prefetch(parent);
1815 if ((prepend(&end, &buflen, dentry->d_name.name, 1818 if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
1816 dentry->d_name.len) != 0) ||
1817 (prepend(&end, &buflen, "/", 1) != 0)) 1819 (prepend(&end, &buflen, "/", 1) != 0))
1818 goto Elong; 1820 goto Elong;
1819 retval = end; 1821 retval = end;
1820 dentry = parent; 1822 dentry = parent;
1821 } 1823 }
1822 1824
1825out:
1826 spin_unlock(&vfsmount_lock);
1823 return retval; 1827 return retval;
1824 1828
1825global_root: 1829global_root:
1826 retval += 1; /* hit the slash */ 1830 retval += 1; /* hit the slash */
1827 if (prepend(&retval, &buflen, dentry->d_name.name, 1831 if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
1828 dentry->d_name.len) != 0)
1829 goto Elong; 1832 goto Elong;
1830 root->mnt = vfsmnt; 1833 root->mnt = vfsmnt;
1831 root->dentry = dentry; 1834 root->dentry = dentry;
1832 return retval; 1835 goto out;
1836
1833Elong: 1837Elong:
1834 return ERR_PTR(-ENAMETOOLONG); 1838 retval = ERR_PTR(-ENAMETOOLONG);
1839 goto out;
1835} 1840}
1836 1841
1837/** 1842/**
@@ -1845,9 +1850,9 @@ Elong:
1845 * 1850 *
1846 * Returns the buffer or an error code if the path was too long. 1851 * Returns the buffer or an error code if the path was too long.
1847 * 1852 *
1848 * "buflen" should be positive. Caller holds the dcache_lock. 1853 * "buflen" should be positive.
1849 */ 1854 */
1850char *d_path(struct path *path, char *buf, int buflen) 1855char *d_path(const struct path *path, char *buf, int buflen)
1851{ 1856{
1852 char *res; 1857 char *res;
1853 struct path root; 1858 struct path root;
@@ -1915,16 +1920,11 @@ char *dentry_path(struct dentry *dentry, char *buf, int buflen)
1915 retval = end-1; 1920 retval = end-1;
1916 *retval = '/'; 1921 *retval = '/';
1917 1922
1918 for (;;) { 1923 while (!IS_ROOT(dentry)) {
1919 struct dentry *parent; 1924 struct dentry *parent = dentry->d_parent;
1920 if (IS_ROOT(dentry))
1921 break;
1922 1925
1923 parent = dentry->d_parent;
1924 prefetch(parent); 1926 prefetch(parent);
1925 1927 if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
1926 if ((prepend(&end, &buflen, dentry->d_name.name,
1927 dentry->d_name.len) != 0) ||
1928 (prepend(&end, &buflen, "/", 1) != 0)) 1928 (prepend(&end, &buflen, "/", 1) != 0))
1929 goto Elong; 1929 goto Elong;
1930 1930
@@ -1975,7 +1975,7 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
1975 error = -ENOENT; 1975 error = -ENOENT;
1976 /* Has the current directory has been unlinked? */ 1976 /* Has the current directory has been unlinked? */
1977 spin_lock(&dcache_lock); 1977 spin_lock(&dcache_lock);
1978 if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) { 1978 if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
1979 unsigned long len; 1979 unsigned long len;
1980 struct path tmp = root; 1980 struct path tmp = root;
1981 char * cwd; 1981 char * cwd;
diff --git a/fs/locks.c b/fs/locks.c
index 11dbf08651b7..dce8c747371c 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -561,9 +561,6 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
561 /* insert into file's list */ 561 /* insert into file's list */
562 fl->fl_next = *pos; 562 fl->fl_next = *pos;
563 *pos = fl; 563 *pos = fl;
564
565 if (fl->fl_ops && fl->fl_ops->fl_insert)
566 fl->fl_ops->fl_insert(fl);
567} 564}
568 565
569/* 566/*
@@ -586,9 +583,6 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
586 fl->fl_fasync = NULL; 583 fl->fl_fasync = NULL;
587 } 584 }
588 585
589 if (fl->fl_ops && fl->fl_ops->fl_remove)
590 fl->fl_ops->fl_remove(fl);
591
592 if (fl->fl_nspid) { 586 if (fl->fl_nspid) {
593 put_pid(fl->fl_nspid); 587 put_pid(fl->fl_nspid);
594 fl->fl_nspid = NULL; 588 fl->fl_nspid = NULL;
diff --git a/fs/namei.c b/fs/namei.c
index c7e43536c49a..01e67dddcc3d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -581,15 +581,13 @@ static __always_inline int link_path_walk(const char *name, struct nameidata *nd
581 int result; 581 int result;
582 582
583 /* make sure the stuff we saved doesn't go away */ 583 /* make sure the stuff we saved doesn't go away */
584 dget(save.dentry); 584 path_get(&save);
585 mntget(save.mnt);
586 585
587 result = __link_path_walk(name, nd); 586 result = __link_path_walk(name, nd);
588 if (result == -ESTALE) { 587 if (result == -ESTALE) {
589 /* nd->path had been dropped */ 588 /* nd->path had been dropped */
590 nd->path = save; 589 nd->path = save;
591 dget(nd->path.dentry); 590 path_get(&nd->path);
592 mntget(nd->path.mnt);
593 nd->flags |= LOOKUP_REVAL; 591 nd->flags |= LOOKUP_REVAL;
594 result = __link_path_walk(name, nd); 592 result = __link_path_walk(name, nd);
595 } 593 }
@@ -1216,8 +1214,9 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
1216 nd->flags = flags; 1214 nd->flags = flags;
1217 nd->depth = 0; 1215 nd->depth = 0;
1218 1216
1219 nd->path.mnt = mntget(mnt); 1217 nd->path.dentry = dentry;
1220 nd->path.dentry = dget(dentry); 1218 nd->path.mnt = mnt;
1219 path_get(&nd->path);
1221 1220
1222 retval = path_walk(name, nd); 1221 retval = path_walk(name, nd);
1223 if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && 1222 if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
@@ -2857,16 +2856,17 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
2857{ 2856{
2858 struct nameidata nd; 2857 struct nameidata nd;
2859 void *cookie; 2858 void *cookie;
2859 int res;
2860 2860
2861 nd.depth = 0; 2861 nd.depth = 0;
2862 cookie = dentry->d_inode->i_op->follow_link(dentry, &nd); 2862 cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
2863 if (!IS_ERR(cookie)) { 2863 if (IS_ERR(cookie))
2864 int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd)); 2864 return PTR_ERR(cookie);
2865 if (dentry->d_inode->i_op->put_link) 2865
2866 dentry->d_inode->i_op->put_link(dentry, &nd, cookie); 2866 res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
2867 cookie = ERR_PTR(res); 2867 if (dentry->d_inode->i_op->put_link)
2868 } 2868 dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
2869 return PTR_ERR(cookie); 2869 return res;
2870} 2870}
2871 2871
2872int vfs_follow_link(struct nameidata *nd, const char *link) 2872int vfs_follow_link(struct nameidata *nd, const char *link)
diff --git a/fs/pipe.c b/fs/pipe.c
index ec228bc9f882..700f4e0d9572 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1003,8 +1003,7 @@ struct file *create_write_pipe(void)
1003void free_write_pipe(struct file *f) 1003void free_write_pipe(struct file *f)
1004{ 1004{
1005 free_pipe_info(f->f_dentry->d_inode); 1005 free_pipe_info(f->f_dentry->d_inode);
1006 dput(f->f_path.dentry); 1006 path_put(&f->f_path);
1007 mntput(f->f_path.mnt);
1008 put_filp(f); 1007 put_filp(f);
1009} 1008}
1010 1009
@@ -1015,8 +1014,8 @@ struct file *create_read_pipe(struct file *wrf)
1015 return ERR_PTR(-ENFILE); 1014 return ERR_PTR(-ENFILE);
1016 1015
1017 /* Grab pipe from the writer */ 1016 /* Grab pipe from the writer */
1018 f->f_path.mnt = mntget(wrf->f_path.mnt); 1017 f->f_path = wrf->f_path;
1019 f->f_path.dentry = dget(wrf->f_path.dentry); 1018 path_get(&wrf->f_path);
1020 f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping; 1019 f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
1021 1020
1022 f->f_pos = 0; 1021 f->f_pos = 0;
@@ -1068,8 +1067,7 @@ int do_pipe(int *fd)
1068 err_fdr: 1067 err_fdr:
1069 put_unused_fd(fdr); 1068 put_unused_fd(fdr);
1070 err_read_pipe: 1069 err_read_pipe:
1071 dput(fr->f_dentry); 1070 path_put(&fr->f_path);
1072 mntput(fr->f_vfsmnt);
1073 put_filp(fr); 1071 put_filp(fr);
1074 err_write_pipe: 1072 err_write_pipe:
1075 free_write_pipe(fw); 1073 free_write_pipe(fw);
diff --git a/fs/utimes.c b/fs/utimes.c
index af059d5cb485..b6b664e7145e 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -40,14 +40,9 @@ asmlinkage long sys_utime(char __user *filename, struct utimbuf __user *times)
40 40
41#endif 41#endif
42 42
43static bool nsec_special(long nsec)
44{
45 return nsec == UTIME_OMIT || nsec == UTIME_NOW;
46}
47
48static bool nsec_valid(long nsec) 43static bool nsec_valid(long nsec)
49{ 44{
50 if (nsec_special(nsec)) 45 if (nsec == UTIME_OMIT || nsec == UTIME_NOW)
51 return true; 46 return true;
52 47
53 return nsec >= 0 && nsec <= 999999999; 48 return nsec >= 0 && nsec <= 999999999;
@@ -102,7 +97,11 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
102 if (error) 97 if (error)
103 goto dput_and_out; 98 goto dput_and_out;
104 99
105 /* Don't worry, the checks are done in inode_change_ok() */ 100 if (times && times[0].tv_nsec == UTIME_NOW &&
101 times[1].tv_nsec == UTIME_NOW)
102 times = NULL;
103
104 /* In most cases, the checks are done in inode_change_ok() */
106 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; 105 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
107 if (times) { 106 if (times) {
108 error = -EPERM; 107 error = -EPERM;
@@ -124,28 +123,34 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
124 newattrs.ia_mtime.tv_nsec = times[1].tv_nsec; 123 newattrs.ia_mtime.tv_nsec = times[1].tv_nsec;
125 newattrs.ia_valid |= ATTR_MTIME_SET; 124 newattrs.ia_valid |= ATTR_MTIME_SET;
126 } 125 }
127 }
128 126
129 /* 127 /*
130 * If times is NULL or both times are either UTIME_OMIT or 128 * For the UTIME_OMIT/UTIME_NOW and UTIME_NOW/UTIME_OMIT
131 * UTIME_NOW, then need to check permissions, because 129 * cases, we need to make an extra check that is not done by
132 * inode_change_ok() won't do it. 130 * inode_change_ok().
133 */ 131 */
134 if (!times || (nsec_special(times[0].tv_nsec) && 132 if (((times[0].tv_nsec == UTIME_NOW &&
135 nsec_special(times[1].tv_nsec))) { 133 times[1].tv_nsec == UTIME_OMIT)
134 ||
135 (times[0].tv_nsec == UTIME_OMIT &&
136 times[1].tv_nsec == UTIME_NOW))
137 && !is_owner_or_cap(inode))
138 goto mnt_drop_write_and_out;
139 } else {
140
141 /*
142 * If times is NULL (or both times are UTIME_NOW),
143 * then we need to check permissions, because
144 * inode_change_ok() won't do it.
145 */
136 error = -EACCES; 146 error = -EACCES;
137 if (IS_IMMUTABLE(inode)) 147 if (IS_IMMUTABLE(inode))
138 goto mnt_drop_write_and_out; 148 goto mnt_drop_write_and_out;
139 149
140 if (!is_owner_or_cap(inode)) { 150 if (!is_owner_or_cap(inode)) {
141 if (f) { 151 error = permission(inode, MAY_WRITE, NULL);
142 if (!(f->f_mode & FMODE_WRITE)) 152 if (error)
143 goto mnt_drop_write_and_out; 153 goto mnt_drop_write_and_out;
144 } else {
145 error = vfs_permission(&nd, MAY_WRITE);
146 if (error)
147 goto mnt_drop_write_and_out;
148 }
149 } 154 }
150 } 155 }
151 mutex_lock(&inode->i_mutex); 156 mutex_lock(&inode->i_mutex);
@@ -169,14 +174,6 @@ asmlinkage long sys_utimensat(int dfd, char __user *filename, struct timespec __
169 if (utimes) { 174 if (utimes) {
170 if (copy_from_user(&tstimes, utimes, sizeof(tstimes))) 175 if (copy_from_user(&tstimes, utimes, sizeof(tstimes)))
171 return -EFAULT; 176 return -EFAULT;
172 if ((tstimes[0].tv_nsec == UTIME_OMIT ||
173 tstimes[0].tv_nsec == UTIME_NOW) &&
174 tstimes[0].tv_sec != 0)
175 return -EINVAL;
176 if ((tstimes[1].tv_nsec == UTIME_OMIT ||
177 tstimes[1].tv_nsec == UTIME_NOW) &&
178 tstimes[1].tv_sec != 0)
179 return -EINVAL;
180 177
181 /* Nothing to do, we must not even check the path. */ 178 /* Nothing to do, we must not even check the path. */
182 if (tstimes[0].tv_nsec == UTIME_OMIT && 179 if (tstimes[0].tv_nsec == UTIME_OMIT &&