Commit 60fa4cfb authored by Trond Myklebust's avatar Trond Myklebust

NFSv2/v3/v4: Make the rpc_ops->getattr method take a filehandle

   rather than an inode argument. Fix up nfs_instantiate() and
   _nfs4_do_open to use this since doing a new lookup might be racy.
parent 26ee7f10
......@@ -982,12 +982,18 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
/* We may have been initialized further down */
if (dentry->d_inode)
return 0;
if (fhandle->size == 0 || !(fattr->valid & NFS_ATTR_FATTR)) {
if (fhandle->size == 0) {
struct inode *dir = dentry->d_parent->d_inode;
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error)
goto out_err;
}
if (!(fattr->valid & NFS_ATTR_FATTR)) {
struct nfs_server *server = NFS_SB(dentry->d_sb);
error = server->rpc_ops->getattr(server, fhandle, fattr);
if (error < 0)
goto out_err;
}
inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
if (inode) {
d_instantiate(dentry, inode);
......
......@@ -961,7 +961,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
/* Protect against RPC races by saving the change attribute */
verifier = nfs_save_change_attribute(inode);
status = NFS_PROTO(inode)->getattr(inode, &fattr);
status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
if (status) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
inode->i_sb->s_id,
......
......@@ -92,14 +92,15 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* One function for each procedure in the NFS protocol.
*/
static int
nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
int status;
dprintk("NFS call getattr\n");
fattr->valid = 0;
status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
NFS_FH(inode), fattr, 0);
status = rpc_call(server->client, NFS3PROC_GETATTR,
fhandle, fattr, 0);
dprintk("NFS reply getattr\n");
return status;
}
......
......@@ -305,6 +305,11 @@ static int _nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct
if (status)
goto out_err;
update_changeattr(dir, &o_res.cinfo);
if (!(f_attr.valid & NFS_ATTR_FATTR)) {
status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);
if (status < 0)
goto out_err;
}
status = -ENOMEM;
inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
......@@ -734,11 +739,10 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
return status;
}
static int _nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_getattr_arg args = {
.fh = NFS_FH(inode),
.fh = fhandle,
.bitmask = server->attr_bitmask,
};
struct nfs4_getattr_res res = {
......@@ -752,16 +756,16 @@ static int _nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
};
fattr->valid = 0;
return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
return rpc_call_sync(server->client, &msg, 0);
}
static int nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(inode),
_nfs4_proc_getattr(inode, fattr),
err = nfs4_handle_exception(server,
_nfs4_proc_getattr(server, fhandle, fattr),
&exception);
} while (exception.retry);
return err;
......
......@@ -87,14 +87,15 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
* One function for each procedure in the NFS protocol.
*/
static int
nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
int status;
dprintk("NFS call getattr\n");
fattr->valid = 0;
status = rpc_call(NFS_CLIENT(inode), NFSPROC_GETATTR,
NFS_FH(inode), fattr, 0);
status = rpc_call(server->client, NFSPROC_GETATTR,
fhandle, fattr, 0);
dprintk("NFS reply getattr\n");
return status;
}
......
......@@ -669,7 +669,8 @@ struct nfs_rpc_ops {
int (*getroot) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *);
int (*getattr) (struct inode *, struct nfs_fattr *);
int (*getattr) (struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *);
int (*setattr) (struct dentry *, struct nfs_fattr *,
struct iattr *);
int (*lookup) (struct inode *, struct qstr *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment