diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-06-22 18:53:18 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-07-20 01:43:46 -0400 |
commit | f7c85868fcacc331dd3454a4f08f006d7942521f (patch) | |
tree | 03e01b3f96684911c353ce22c1cc757a36616977 /fs/nfs/dir.c | |
parent | 511415980ace0ceecd71088dbe1c7ce4ca7c79fe (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.c | 24 |
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; |
1596 | out_put_ctx: | 1597 | out_put_ctx: |
1597 | if (ctx != NULL) | 1598 | put_nfs_open_context(ctx); |
1598 | put_nfs_open_context(ctx); | ||
1599 | out_err_drop: | 1599 | out_err_drop: |
1600 | d_drop(dentry); | 1600 | d_drop(dentry); |
1601 | out_err: | 1601 | out_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); |