aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-06-05 09:10:19 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-14 08:33:08 -0400
commit8867fe5899010a0c0ac36dadfdacf1072b1c990c (patch)
tree3af6bb8d50fb06a46a451ba23bde8dac98361c25
parent0dd2b474d0b69d58859399b1df7fdc699ea005d4 (diff)
nfs: clean up ->create in nfs_rpc_ops
Don't pass nfs_open_context() to ->create(). Only the NFS4 implementation needed that and only because it wanted to return an open file using open intents. That task has been replaced by ->atomic_open so it is not necessary anymore to pass the context to the create rpc operation. Despite nfs4_proc_create apparently being okay with a NULL context it Oopses somewhere down the call chain. So allocate a context here. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> CC: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/nfs/dir.c42
-rw-r--r--fs/nfs/nfs3proc.c2
-rw-r--r--fs/nfs/nfs4proc.c37
-rw-r--r--fs/nfs/proc.c2
-rw-r--r--include/linux/nfs_xdr.h2
5 files changed, 15 insertions, 70 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 0d8c71271d1a..45015d32a865 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -114,10 +114,8 @@ const struct inode_operations nfs3_dir_inode_operations = {
114static struct file *nfs_atomic_open(struct inode *, struct dentry *, 114static struct file *nfs_atomic_open(struct inode *, struct dentry *,
115 struct opendata *, unsigned, umode_t, 115 struct opendata *, unsigned, umode_t,
116 bool *); 116 bool *);
117static int nfs4_create(struct inode *dir, struct dentry *dentry,
118 umode_t mode, struct nameidata *nd);
119const struct inode_operations nfs4_dir_inode_operations = { 117const struct inode_operations nfs4_dir_inode_operations = {
120 .create = nfs4_create, 118 .create = nfs_create,
121 .lookup = nfs_lookup, 119 .lookup = nfs_lookup,
122 .atomic_open = nfs_atomic_open, 120 .atomic_open = nfs_atomic_open,
123 .link = nfs_link, 121 .link = nfs_link,
@@ -1582,42 +1580,6 @@ no_open:
1582 return nfs_lookup_revalidate(dentry, nd); 1580 return nfs_lookup_revalidate(dentry, nd);
1583} 1581}
1584 1582
1585static int nfs4_create(struct inode *dir, struct dentry *dentry,
1586 umode_t mode, struct nameidata *nd)
1587{
1588 struct nfs_open_context *ctx = NULL;
1589 struct iattr attr;
1590 int error;
1591 int open_flags = O_CREAT|O_EXCL;
1592
1593 dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
1594 dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
1595
1596 attr.ia_mode = mode;
1597 attr.ia_valid = ATTR_MODE;
1598
1599 if (nd)
1600 open_flags = nd->intent.open.flags;
1601
1602 ctx = create_nfs_open_context(dentry, open_flags);
1603 error = PTR_ERR(ctx);
1604 if (IS_ERR(ctx))
1605 goto out_err_drop;
1606
1607 error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
1608 if (error != 0)
1609 goto out_put_ctx;
1610
1611 put_nfs_open_context(ctx);
1612
1613 return 0;
1614out_put_ctx:
1615 put_nfs_open_context(ctx);
1616out_err_drop:
1617 d_drop(dentry);
1618 return error;
1619}
1620
1621#endif /* CONFIG_NFSV4 */ 1583#endif /* CONFIG_NFSV4 */
1622 1584
1623/* 1585/*
@@ -1684,7 +1646,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry,
1684 if (nd) 1646 if (nd)
1685 open_flags = nd->intent.open.flags; 1647 open_flags = nd->intent.open.flags;
1686 1648
1687 error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL); 1649 error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
1688 if (error != 0) 1650 if (error != 0)
1689 goto out_err; 1651 goto out_err;
1690 return 0; 1652 return 0;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 2292a0fd2bff..3187e24e8f78 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -314,7 +314,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
314 */ 314 */
315static int 315static int
316nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 316nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
317 int flags, struct nfs_open_context *ctx) 317 int flags)
318{ 318{
319 struct nfs3_createdata *data; 319 struct nfs3_createdata *data;
320 umode_t mode = sattr->ia_mode; 320 umode_t mode = sattr->ia_mode;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 15fc7e4664ed..c157b2089b47 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2806,37 +2806,22 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
2806} 2806}
2807 2807
2808/* 2808/*
2809 * Got race? 2809 * This is just for mknod. open(O_CREAT) will always do ->open_context().
2810 * We will need to arrange for the VFS layer to provide an atomic open.
2811 * Until then, this create/open method is prone to inefficiency and race
2812 * conditions due to the lookup, create, and open VFS calls from sys_open()
2813 * placed on the wire.
2814 *
2815 * Given the above sorry state of affairs, I'm simply sending an OPEN.
2816 * The file will be opened again in the subsequent VFS open call
2817 * (nfs4_proc_file_open).
2818 *
2819 * The open for read will just hang around to be used by any process that
2820 * opens the file O_RDONLY. This will all be resolved with the VFS changes.
2821 */ 2810 */
2822
2823static int 2811static int
2824nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 2812nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
2825 int flags, struct nfs_open_context *ctx) 2813 int flags)
2826{ 2814{
2827 struct dentry *de = dentry; 2815 struct nfs_open_context *ctx;
2828 struct nfs4_state *state; 2816 struct nfs4_state *state;
2829 struct rpc_cred *cred = NULL;
2830 fmode_t fmode = 0;
2831 int status = 0; 2817 int status = 0;
2832 2818
2833 if (ctx != NULL) { 2819 ctx = alloc_nfs_open_context(dentry, FMODE_READ);
2834 cred = ctx->cred; 2820 if (IS_ERR(ctx))
2835 de = ctx->dentry; 2821 return PTR_ERR(ctx);
2836 fmode = ctx->mode; 2822
2837 }
2838 sattr->ia_mode &= ~current_umask(); 2823 sattr->ia_mode &= ~current_umask();
2839 state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL); 2824 state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL);
2840 d_drop(dentry); 2825 d_drop(dentry);
2841 if (IS_ERR(state)) { 2826 if (IS_ERR(state)) {
2842 status = PTR_ERR(state); 2827 status = PTR_ERR(state);
@@ -2844,11 +2829,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
2844 } 2829 }
2845 d_add(dentry, igrab(state->inode)); 2830 d_add(dentry, igrab(state->inode));
2846 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 2831 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
2847 if (ctx != NULL) 2832 ctx->state = state;
2848 ctx->state = state;
2849 else
2850 nfs4_close_sync(state, fmode);
2851out: 2833out:
2834 put_nfs_open_context(ctx);
2852 return status; 2835 return status;
2853} 2836}
2854 2837
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 617c7419a08e..4433806e116f 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -259,7 +259,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
259 259
260static int 260static int
261nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, 261nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
262 int flags, struct nfs_open_context *ctx) 262 int flags)
263{ 263{
264 struct nfs_createdata *data; 264 struct nfs_createdata *data;
265 struct rpc_message msg = { 265 struct rpc_message msg = {
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 8aadd90b808a..d3b7c18b18f4 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1374,7 +1374,7 @@ struct nfs_rpc_ops {
1374 int (*readlink)(struct inode *, struct page *, unsigned int, 1374 int (*readlink)(struct inode *, struct page *, unsigned int,
1375 unsigned int); 1375 unsigned int);
1376 int (*create) (struct inode *, struct dentry *, 1376 int (*create) (struct inode *, struct dentry *,
1377 struct iattr *, int, struct nfs_open_context *); 1377 struct iattr *, int);
1378 int (*remove) (struct inode *, struct qstr *); 1378 int (*remove) (struct inode *, struct qstr *);
1379 void (*unlink_setup) (struct rpc_message *, struct inode *dir); 1379 void (*unlink_setup) (struct rpc_message *, struct inode *dir);
1380 void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *); 1380 void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);