diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2012-06-05 09:10:19 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-14 08:33:08 -0400 |
commit | 8867fe5899010a0c0ac36dadfdacf1072b1c990c (patch) | |
tree | 3af6bb8d50fb06a46a451ba23bde8dac98361c25 | |
parent | 0dd2b474d0b69d58859399b1df7fdc699ea005d4 (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.c | 42 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 37 | ||||
-rw-r--r-- | fs/nfs/proc.c | 2 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 |
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 = { | |||
114 | static struct file *nfs_atomic_open(struct inode *, struct dentry *, | 114 | static 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 *); |
117 | static int nfs4_create(struct inode *dir, struct dentry *dentry, | ||
118 | umode_t mode, struct nameidata *nd); | ||
119 | const struct inode_operations nfs4_dir_inode_operations = { | 117 | const 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 | ||
1585 | static 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; | ||
1614 | out_put_ctx: | ||
1615 | put_nfs_open_context(ctx); | ||
1616 | out_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 | */ |
315 | static int | 315 | static int |
316 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 316 | nfs3_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 | |||
2823 | static int | 2811 | static int |
2824 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 2812 | nfs4_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); | ||
2851 | out: | 2833 | out: |
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 | ||
260 | static int | 260 | static int |
261 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 261 | nfs_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 *); |