aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-09-29 17:41:33 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-10-09 17:19:22 -0400
commitfab728e156b3cbfe31f05d6e7cdebe3d5eaff878 (patch)
tree4a0a9ab57867e33342119e61d52c16d0c9eb7a32 /fs/nfs/dir.c
parent4b841736bc16b320bcdb1e8ece585b3ced9a8811 (diff)
NFS: Ensure nfs_instantiate() invalidates the parent dir on error
Also ensure that it drops the dentry in this case. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index e275a6eb0a7c..82395c511710 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1174,32 +1174,39 @@ out_renew:
1174int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, 1174int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
1175 struct nfs_fattr *fattr) 1175 struct nfs_fattr *fattr)
1176{ 1176{
1177 struct dentry *parent = dget_parent(dentry);
1178 struct inode *dir = parent->d_inode;
1177 struct inode *inode; 1179 struct inode *inode;
1178 int error = -EACCES; 1180 int error = -EACCES;
1179 1181
1182 d_drop(dentry);
1183
1180 /* We may have been initialized further down */ 1184 /* We may have been initialized further down */
1181 if (dentry->d_inode) 1185 if (dentry->d_inode)
1182 return 0; 1186 goto out;
1183 if (fhandle->size == 0) { 1187 if (fhandle->size == 0) {
1184 struct inode *dir = dentry->d_parent->d_inode;
1185 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); 1188 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
1186 if (error) 1189 if (error)
1187 return error; 1190 goto out_error;
1188 } 1191 }
1189 if (!(fattr->valid & NFS_ATTR_FATTR)) { 1192 if (!(fattr->valid & NFS_ATTR_FATTR)) {
1190 struct nfs_server *server = NFS_SB(dentry->d_sb); 1193 struct nfs_server *server = NFS_SB(dentry->d_sb);
1191 error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); 1194 error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr);
1192 if (error < 0) 1195 if (error < 0)
1193 return error; 1196 goto out_error;
1194 } 1197 }
1195 inode = nfs_fhget(dentry->d_sb, fhandle, fattr); 1198 inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
1196 error = PTR_ERR(inode); 1199 error = PTR_ERR(inode);
1197 if (IS_ERR(inode)) 1200 if (IS_ERR(inode))
1198 return error; 1201 goto out_error;
1199 d_instantiate(dentry, inode); 1202 d_add(dentry, inode);
1200 if (d_unhashed(dentry)) 1203out:
1201 d_rehash(dentry); 1204 dput(parent);
1202 return 0; 1205 return 0;
1206out_error:
1207 nfs_mark_for_revalidate(dir);
1208 dput(parent);
1209 return error;
1203} 1210}
1204 1211
1205/* 1212/*