NFS: cleanup create() Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 20 +++++++++----------- fs/nfs/nfs3proc.c | 33 ++++++++------------------------- fs/nfs/nfs4proc.c | 21 ++++++++++----------- fs/nfs/proc.c | 13 ++++--------- include/linux/nfs_xdr.h | 2 +- 5 files changed, 32 insertions(+), 57 deletions(-) Index: linux-2.6.11/fs/nfs/nfs3proc.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs3proc.c +++ linux-2.6.11/fs/nfs/nfs3proc.c @@ -295,7 +295,7 @@ static int nfs3_proc_commit(struct nfs_w * Create a regular file. * For now, we don't implement O_EXCL. */ -static struct inode * +static int nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, int flags) { @@ -342,29 +342,19 @@ again: break; case NFS3_CREATE_UNCHECKED: - goto exit; + goto out; } goto again; } -exit: - dprintk("NFS reply create: %d\n", status); - + if (status == 0) + status = nfs_instantiate(dentry, &fhandle, &fattr); if (status != 0) goto out; - if (fhandle.size == 0 || !(fattr.valid & NFS_ATTR_FATTR)) { - status = nfs3_proc_lookup(dir, &dentry->d_name, &fhandle, &fattr); - if (status != 0) - goto out; - } /* When we created the file with exclusive semantics, make * sure we set the attributes afterwards. */ if (arg.createmode == NFS3_CREATE_EXCLUSIVE) { - struct nfs3_sattrargs arg = { - .fh = &fhandle, - .sattr = sattr, - }; dprintk("NFS call setattr (post-create)\n"); if (!(sattr->ia_valid & ATTR_ATIME_SET)) @@ -375,20 +365,13 @@ exit: /* Note: we could use a guarded setattr here, but I'm * not sure this buys us anything (and I'd have * to revamp the NFSv3 XDR code) */ - fattr.valid = 0; - status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR, - &arg, &fattr, 0); + status = nfs3_proc_setattr(dentry, &fattr, sattr); + nfs_refresh_inode(dentry->d_inode, &fattr); dprintk("NFS reply setattr (post-create): %d\n", status); } - if (status == 0) { - struct inode *inode; - inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); - if (inode) - return inode; - status = -ENOMEM; - } out: - return ERR_PTR(status); + dprintk("NFS reply create: %d\n", status); + return status; } static int Index: linux-2.6.11/fs/nfs/nfs4proc.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs4proc.c +++ linux-2.6.11/fs/nfs/nfs4proc.c @@ -1434,38 +1434,37 @@ static int nfs4_proc_commit(struct nfs_w * opens the file O_RDONLY. This will all be resolved with the VFS changes. */ -static struct inode * +static int nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, int flags) { - struct inode *inode; struct nfs4_state *state; struct rpc_cred *cred; + int status = 0; cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); - if (IS_ERR(cred)) - return (struct inode *)cred; + if (IS_ERR(cred)) { + status = PTR_ERR(cred); + goto out; + } state = nfs4_do_open(dir, dentry, flags, sattr, cred); put_rpccred(cred); if (IS_ERR(state)) { - inode = (struct inode *)state; + status = PTR_ERR(state); goto out; } - inode = state->inode; + d_instantiate(dentry, state->inode); if (flags & O_EXCL) { struct nfs_fattr fattr; - int status; status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, - NFS_FH(inode), sattr, state); + NFS_FH(state->inode), sattr, state); if (status == 0) goto out; - iput(inode); - inode = ERR_PTR(status); } else if (flags != 0) goto out; nfs4_close_state(state, flags); out: - return inode; + return status; } static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) Index: linux-2.6.11/fs/nfs/proc.c =================================================================== --- linux-2.6.11.orig/fs/nfs/proc.c +++ linux-2.6.11/fs/nfs/proc.c @@ -212,7 +212,7 @@ static int nfs_proc_write(struct nfs_wri return status < 0? status : wdata->res.count; } -static struct inode * +static int nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, int flags) { @@ -233,15 +233,10 @@ nfs_proc_create(struct inode *dir, struc fattr.valid = 0; dprintk("NFS call create %s\n", dentry->d_name.name); status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); + if (status == 0) + status = nfs_instantiate(dentry, &fhandle, &fattr); dprintk("NFS reply create: %d\n", status); - if (status == 0) { - struct inode *inode; - inode = nfs_fhget(dir->i_sb, &fhandle, &fattr); - if (inode) - return inode; - status = -ENOMEM; - } - return ERR_PTR(status); + return status; } /* Index: linux-2.6.11/fs/nfs/dir.c =================================================================== --- linux-2.6.11.orig/fs/nfs/dir.c +++ linux-2.6.11/fs/nfs/dir.c @@ -997,7 +997,6 @@ static int nfs_create(struct inode *dir, struct nameidata *nd) { struct iattr attr; - struct inode *inode; int error; int open_flags = 0; @@ -1012,18 +1011,17 @@ static int nfs_create(struct inode *dir, lock_kernel(); nfs_begin_data_update(dir); - inode = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); + error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); nfs_end_data_update(dir); - if (!IS_ERR(inode)) { - d_instantiate(dentry, inode); - nfs_renew_times(dentry); - nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); - error = 0; - } else { - error = PTR_ERR(inode); - d_drop(dentry); - } + if (error != 0) + goto out_err; + nfs_renew_times(dentry); + nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); unlock_kernel(); + return 0; +out_err: + unlock_kernel(); + d_drop(dentry); return error; } Index: linux-2.6.11/include/linux/nfs_xdr.h =================================================================== --- linux-2.6.11.orig/include/linux/nfs_xdr.h +++ linux-2.6.11/include/linux/nfs_xdr.h @@ -682,7 +682,7 @@ struct nfs_rpc_ops { int (*read) (struct nfs_read_data *); int (*write) (struct nfs_write_data *); int (*commit) (struct nfs_write_data *); - struct inode * (*create) (struct inode *, struct dentry *, + int (*create) (struct inode *, struct dentry *, struct iattr *, int); int (*remove) (struct inode *, struct qstr *); int (*unlink_setup) (struct rpc_message *,