aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-06-22 18:53:18 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-07-20 01:43:46 -0400
commitf7c85868fcacc331dd3454a4f08f006d7942521f (patch)
tree03e01b3f96684911c353ce22c1cc757a36616977 /fs/nfs/dir.c
parent511415980ace0ceecd71088dbe1c7ce4ca7c79fe (diff)
fix mknod() on nfs4 (hopefully)
a) check the right flags in ->create() (LOOKUP_OPEN, not LOOKUP_CREATE) b) default (!LOOKUP_OPEN) open_flags is O_CREAT|O_EXCL|FMODE_READ, not 0 c) lookup_instantiate_filp() should be done only with LOOKUP_OPEN; otherwise we need to issue CLOSE, lest we leak stateid on server. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index cc613c354bb8..1f4625749038 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1567,7 +1567,7 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
1567 struct nfs_open_context *ctx = NULL; 1567 struct nfs_open_context *ctx = NULL;
1568 struct iattr attr; 1568 struct iattr attr;
1569 int error; 1569 int error;
1570 int open_flags = 0; 1570 int open_flags = O_CREAT|O_EXCL|FMODE_READ;
1571 1571
1572 dfprintk(VFS, "NFS: create(%s/%ld), %s\n", 1572 dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
1573 dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); 1573 dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1575,27 +1575,27 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
1575 attr.ia_mode = mode; 1575 attr.ia_mode = mode;
1576 attr.ia_valid = ATTR_MODE; 1576 attr.ia_valid = ATTR_MODE;
1577 1577
1578 if ((nd->flags & LOOKUP_CREATE) != 0) { 1578 if (nd && (nd->flags & LOOKUP_OPEN) != 0)
1579 open_flags = nd->intent.open.flags; 1579 open_flags = nd->intent.open.flags;
1580 1580
1581 ctx = create_nfs_open_context(dentry, open_flags); 1581 ctx = create_nfs_open_context(dentry, open_flags);
1582 error = PTR_ERR(ctx); 1582 error = PTR_ERR(ctx);
1583 if (IS_ERR(ctx)) 1583 if (IS_ERR(ctx))
1584 goto out_err_drop; 1584 goto out_err_drop;
1585 }
1586 1585
1587 error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx); 1586 error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
1588 if (error != 0) 1587 if (error != 0)
1589 goto out_put_ctx; 1588 goto out_put_ctx;
1590 if (ctx != NULL) { 1589 if (nd && (nd->flags & LOOKUP_OPEN) != 0) {
1591 error = nfs_intent_set_file(nd, ctx); 1590 error = nfs_intent_set_file(nd, ctx);
1592 if (error < 0) 1591 if (error < 0)
1593 goto out_err; 1592 goto out_err;
1593 } else {
1594 put_nfs_open_context(ctx);
1594 } 1595 }
1595 return 0; 1596 return 0;
1596out_put_ctx: 1597out_put_ctx:
1597 if (ctx != NULL) 1598 put_nfs_open_context(ctx);
1598 put_nfs_open_context(ctx);
1599out_err_drop: 1599out_err_drop:
1600 d_drop(dentry); 1600 d_drop(dentry);
1601out_err: 1601out_err:
@@ -1657,7 +1657,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
1657{ 1657{
1658 struct iattr attr; 1658 struct iattr attr;
1659 int error; 1659 int error;
1660 int open_flags = 0; 1660 int open_flags = O_CREAT|O_EXCL|FMODE_READ;
1661 1661
1662 dfprintk(VFS, "NFS: create(%s/%ld), %s\n", 1662 dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
1663 dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); 1663 dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1665,7 +1665,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
1665 attr.ia_mode = mode; 1665 attr.ia_mode = mode;
1666 attr.ia_valid = ATTR_MODE; 1666 attr.ia_valid = ATTR_MODE;
1667 1667
1668 if ((nd->flags & LOOKUP_CREATE) != 0) 1668 if (nd && (nd->flags & LOOKUP_OPEN) != 0)
1669 open_flags = nd->intent.open.flags; 1669 open_flags = nd->intent.open.flags;
1670 1670
1671 error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL); 1671 error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL);