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>
This commit is contained in:
42
fs/nfs/dir.c
42
fs/nfs/dir.c
@@ -114,10 +114,8 @@ const struct inode_operations nfs3_dir_inode_operations = {
|
|||||||
static struct file *nfs_atomic_open(struct inode *, struct dentry *,
|
static struct file *nfs_atomic_open(struct inode *, struct dentry *,
|
||||||
struct opendata *, unsigned, umode_t,
|
struct opendata *, unsigned, umode_t,
|
||||||
bool *);
|
bool *);
|
||||||
static int nfs4_create(struct inode *dir, struct dentry *dentry,
|
|
||||||
umode_t mode, struct nameidata *nd);
|
|
||||||
const struct inode_operations nfs4_dir_inode_operations = {
|
const struct inode_operations nfs4_dir_inode_operations = {
|
||||||
.create = nfs4_create,
|
.create = nfs_create,
|
||||||
.lookup = nfs_lookup,
|
.lookup = nfs_lookup,
|
||||||
.atomic_open = nfs_atomic_open,
|
.atomic_open = nfs_atomic_open,
|
||||||
.link = nfs_link,
|
.link = nfs_link,
|
||||||
@@ -1582,42 +1580,6 @@ no_open:
|
|||||||
return nfs_lookup_revalidate(dentry, nd);
|
return nfs_lookup_revalidate(dentry, nd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfs4_create(struct inode *dir, struct dentry *dentry,
|
|
||||||
umode_t mode, struct nameidata *nd)
|
|
||||||
{
|
|
||||||
struct nfs_open_context *ctx = NULL;
|
|
||||||
struct iattr attr;
|
|
||||||
int error;
|
|
||||||
int open_flags = O_CREAT|O_EXCL;
|
|
||||||
|
|
||||||
dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
|
|
||||||
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
|
|
||||||
|
|
||||||
attr.ia_mode = mode;
|
|
||||||
attr.ia_valid = ATTR_MODE;
|
|
||||||
|
|
||||||
if (nd)
|
|
||||||
open_flags = nd->intent.open.flags;
|
|
||||||
|
|
||||||
ctx = create_nfs_open_context(dentry, open_flags);
|
|
||||||
error = PTR_ERR(ctx);
|
|
||||||
if (IS_ERR(ctx))
|
|
||||||
goto out_err_drop;
|
|
||||||
|
|
||||||
error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
|
|
||||||
if (error != 0)
|
|
||||||
goto out_put_ctx;
|
|
||||||
|
|
||||||
put_nfs_open_context(ctx);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
out_put_ctx:
|
|
||||||
put_nfs_open_context(ctx);
|
|
||||||
out_err_drop:
|
|
||||||
d_drop(dentry);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_NFSV4 */
|
#endif /* CONFIG_NFSV4 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1684,7 +1646,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry,
|
|||||||
if (nd)
|
if (nd)
|
||||||
open_flags = nd->intent.open.flags;
|
open_flags = nd->intent.open.flags;
|
||||||
|
|
||||||
error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL);
|
error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -314,7 +314,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
||||||
int flags, struct nfs_open_context *ctx)
|
int flags)
|
||||||
{
|
{
|
||||||
struct nfs3_createdata *data;
|
struct nfs3_createdata *data;
|
||||||
umode_t mode = sattr->ia_mode;
|
umode_t mode = sattr->ia_mode;
|
||||||
|
@@ -2806,37 +2806,22 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Got race?
|
* This is just for mknod. open(O_CREAT) will always do ->open_context().
|
||||||
* We will need to arrange for the VFS layer to provide an atomic open.
|
|
||||||
* Until then, this create/open method is prone to inefficiency and race
|
|
||||||
* conditions due to the lookup, create, and open VFS calls from sys_open()
|
|
||||||
* placed on the wire.
|
|
||||||
*
|
|
||||||
* Given the above sorry state of affairs, I'm simply sending an OPEN.
|
|
||||||
* The file will be opened again in the subsequent VFS open call
|
|
||||||
* (nfs4_proc_file_open).
|
|
||||||
*
|
|
||||||
* The open for read will just hang around to be used by any process that
|
|
||||||
* opens the file O_RDONLY. This will all be resolved with the VFS changes.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
||||||
int flags, struct nfs_open_context *ctx)
|
int flags)
|
||||||
{
|
{
|
||||||
struct dentry *de = dentry;
|
struct nfs_open_context *ctx;
|
||||||
struct nfs4_state *state;
|
struct nfs4_state *state;
|
||||||
struct rpc_cred *cred = NULL;
|
|
||||||
fmode_t fmode = 0;
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if (ctx != NULL) {
|
ctx = alloc_nfs_open_context(dentry, FMODE_READ);
|
||||||
cred = ctx->cred;
|
if (IS_ERR(ctx))
|
||||||
de = ctx->dentry;
|
return PTR_ERR(ctx);
|
||||||
fmode = ctx->mode;
|
|
||||||
}
|
|
||||||
sattr->ia_mode &= ~current_umask();
|
sattr->ia_mode &= ~current_umask();
|
||||||
state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL);
|
state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL);
|
||||||
d_drop(dentry);
|
d_drop(dentry);
|
||||||
if (IS_ERR(state)) {
|
if (IS_ERR(state)) {
|
||||||
status = PTR_ERR(state);
|
status = PTR_ERR(state);
|
||||||
@@ -2844,11 +2829,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|||||||
}
|
}
|
||||||
d_add(dentry, igrab(state->inode));
|
d_add(dentry, igrab(state->inode));
|
||||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||||
if (ctx != NULL)
|
ctx->state = state;
|
||||||
ctx->state = state;
|
|
||||||
else
|
|
||||||
nfs4_close_sync(state, fmode);
|
|
||||||
out:
|
out:
|
||||||
|
put_nfs_open_context(ctx);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -259,7 +259,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
||||||
int flags, struct nfs_open_context *ctx)
|
int flags)
|
||||||
{
|
{
|
||||||
struct nfs_createdata *data;
|
struct nfs_createdata *data;
|
||||||
struct rpc_message msg = {
|
struct rpc_message msg = {
|
||||||
|
@@ -1374,7 +1374,7 @@ struct nfs_rpc_ops {
|
|||||||
int (*readlink)(struct inode *, struct page *, unsigned int,
|
int (*readlink)(struct inode *, struct page *, unsigned int,
|
||||||
unsigned int);
|
unsigned int);
|
||||||
int (*create) (struct inode *, struct dentry *,
|
int (*create) (struct inode *, struct dentry *,
|
||||||
struct iattr *, int, struct nfs_open_context *);
|
struct iattr *, int);
|
||||||
int (*remove) (struct inode *, struct qstr *);
|
int (*remove) (struct inode *, struct qstr *);
|
||||||
void (*unlink_setup) (struct rpc_message *, struct inode *dir);
|
void (*unlink_setup) (struct rpc_message *, struct inode *dir);
|
||||||
void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
|
void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
|
||||||
|
Reference in New Issue
Block a user