aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2010-12-07 16:19:50 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-01-12 20:06:59 -0500
commite1181ee6575d7970bad15aaa852784b4972d2af8 (patch)
treecf1010ee6361e8bcd98ea2f29fa899fa52bf801d /fs/namei.c
parentcccb5a1e698535fa5a734ffe21c7061c97f8d8c5 (diff)
vfs: pass struct file to do_truncate on O_TRUNC opens (try #2)
When a file is opened with O_TRUNC, the truncate processing is handled by handle_truncate(). This function however doesn't receive any info about the newly instantiated filp, and therefore can't pass that info along so that the setattr can use it. This makes NFSv4 misbehave. The client does an open and gets a valid stateid, and then doesn't use that stateid on the subsequent truncate. It uses the zero-stateid instead. Most servers ignore this fact and just do the truncate anyway, but some don't like it (notably, RHEL4). It seems more correct that since we have a fully instantiated file at the time that handle_truncate is called, that we pass that along so that the truncate operation can properly use it. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 24ece10470b6..0b14f6910fc6 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1950,8 +1950,9 @@ int may_open(struct path *path, int acc_mode, int flag)
1950 return break_lease(inode, flag); 1950 return break_lease(inode, flag);
1951} 1951}
1952 1952
1953static int handle_truncate(struct path *path) 1953static int handle_truncate(struct file *filp)
1954{ 1954{
1955 struct path *path = &filp->f_path;
1955 struct inode *inode = path->dentry->d_inode; 1956 struct inode *inode = path->dentry->d_inode;
1956 int error = get_write_access(inode); 1957 int error = get_write_access(inode);
1957 if (error) 1958 if (error)
@@ -1965,7 +1966,7 @@ static int handle_truncate(struct path *path)
1965 if (!error) { 1966 if (!error) {
1966 error = do_truncate(path->dentry, 0, 1967 error = do_truncate(path->dentry, 0,
1967 ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, 1968 ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
1968 NULL); 1969 filp);
1969 } 1970 }
1970 put_write_access(inode); 1971 put_write_access(inode);
1971 return error; 1972 return error;
@@ -2063,7 +2064,7 @@ static struct file *finish_open(struct nameidata *nd,
2063 } 2064 }
2064 if (!IS_ERR(filp)) { 2065 if (!IS_ERR(filp)) {
2065 if (will_truncate) { 2066 if (will_truncate) {
2066 error = handle_truncate(&nd->path); 2067 error = handle_truncate(filp);
2067 if (error) { 2068 if (error) {
2068 fput(filp); 2069 fput(filp);
2069 filp = ERR_PTR(error); 2070 filp = ERR_PTR(error);