nfs_readdir_descriptor_t my_desc,
*desc = &my_desc;
struct nfs_entry my_entry;
- struct nfs_fh fh;
- struct nfs_fattr fattr;
- long res;
+ int res = -ENOMEM;
dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
my_entry.cookie = my_entry.prev_cookie = 0;
my_entry.eof = 0;
- my_entry.fh = &fh;
- my_entry.fattr = &fattr;
- nfs_fattr_init(&fattr);
+ my_entry.fh = nfs_alloc_fhandle();
+ my_entry.fattr = nfs_alloc_fattr();
+ if (my_entry.fh == NULL || my_entry.fattr == NULL)
+ goto out_alloc_failed;
+
desc->entry = &my_entry;
nfs_block_sillyrename(dentry);
nfs_unblock_sillyrename(dentry);
if (res > 0)
res = 0;
- dfprintk(FILE, "NFS: readdir(%s/%s) returns %ld\n",
+out_alloc_failed:
+ nfs_free_fattr(my_entry.fattr);
+ nfs_free_fhandle(my_entry.fh);
+ dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
res);
return res;
struct inode *dir;
struct inode *inode;
struct dentry *parent;
+ struct nfs_fh *fhandle = NULL;
+ struct nfs_fattr *fattr = NULL;
int error;
- struct nfs_fh fhandle;
- struct nfs_fattr fattr;
parent = dget_parent(dentry);
dir = parent->d_inode;
if (NFS_STALE(inode))
goto out_bad;
- error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+ error = -ENOMEM;
+ fhandle = nfs_alloc_fhandle();
+ fattr = nfs_alloc_fattr();
+ if (fhandle == NULL || fattr == NULL)
+ goto out_error;
+
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error)
goto out_bad;
- if (nfs_compare_fh(NFS_FH(inode), &fhandle))
+ if (nfs_compare_fh(NFS_FH(inode), fhandle))
goto out_bad;
- if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
+ if ((error = nfs_refresh_inode(inode, fattr)) != 0)
goto out_bad;
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
out_set_verifier:
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
out_valid:
/* If we have submounts, don't unhash ! */
if (have_submounts(dentry))
goto out_valid;
+ if (dentry->d_flags & DCACHE_DISCONNECTED)
+ goto out_valid;
shrink_dcache_parent(dentry);
}
d_drop(dentry);
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
dput(parent);
dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
__func__, dentry->d_parent->d_name.name,
dentry->d_name.name);
return 0;
+out_error:
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
+ dput(parent);
+ dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
+ __func__, dentry->d_parent->d_name.name,
+ dentry->d_name.name, error);
+ return error;
}
/*
struct dentry *res;
struct dentry *parent;
struct inode *inode = NULL;
+ struct nfs_fh *fhandle = NULL;
+ struct nfs_fattr *fattr = NULL;
int error;
- struct nfs_fh fhandle;
- struct nfs_fattr fattr;
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
goto out;
- res = ERR_PTR(-ENOMEM);
dentry->d_op = NFS_PROTO(dir)->dentry_ops;
/*
goto out;
}
+ res = ERR_PTR(-ENOMEM);
+ fhandle = nfs_alloc_fhandle();
+ fattr = nfs_alloc_fattr();
+ if (fhandle == NULL || fattr == NULL)
+ goto out;
+
parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent);
- error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error == -ENOENT)
goto no_entry;
if (error < 0) {
res = ERR_PTR(error);
goto out_unblock_sillyrename;
}
- inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
+ inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
res = (struct dentry *)inode;
if (IS_ERR(res))
goto out_unblock_sillyrename;
out_unblock_sillyrename:
nfs_unblock_sillyrename(parent);
out:
+ nfs_free_fattr(fattr);
+ nfs_free_fhandle(fhandle);
return res;
}
res = NULL;
goto out;
/* This turned out not to be a regular file */
+ case -EISDIR:
case -ENOTDIR:
goto no_open;
case -ELOOP:
if (!(nd->intent.open.flags & O_NOFOLLOW))
goto no_open;
- /* case -EISDIR: */
/* case -EINVAL: */
default:
goto out;
struct inode *dir;
int openflags, ret = 0;
- if (!is_atomic_open(nd))
+ if (!is_atomic_open(nd) || d_mountpoint(dentry))
goto no_open;
parent = dget_parent(dentry);
dir = parent->d_inode;