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, ...@@ -982,12 +982,18 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
/* We may have been initialized further down */ /* We may have been initialized further down */
if (dentry->d_inode) if (dentry->d_inode)
return 0; return 0;
if (fhandle->size == 0 || !(fattr->valid & NFS_ATTR_FATTR)) { if (fhandle->size == 0) {
struct inode *dir = dentry->d_parent->d_inode; struct inode *dir = dentry->d_parent->d_inode;
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error) if (error)
goto out_err; 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); inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
if (inode) { if (inode) {
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
......
...@@ -961,7 +961,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) ...@@ -961,7 +961,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
/* Protect against RPC races by saving the change attribute */ /* Protect against RPC races by saving the change attribute */
verifier = nfs_save_change_attribute(inode); 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) { if (status) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
inode->i_sb->s_id, inode->i_sb->s_id,
......
...@@ -92,14 +92,15 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -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. * One function for each procedure in the NFS protocol.
*/ */
static int 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; int status;
dprintk("NFS call getattr\n"); dprintk("NFS call getattr\n");
fattr->valid = 0; fattr->valid = 0;
status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR, status = rpc_call(server->client, NFS3PROC_GETATTR,
NFS_FH(inode), fattr, 0); fhandle, fattr, 0);
dprintk("NFS reply getattr\n"); dprintk("NFS reply getattr\n");
return status; return status;
} }
......
...@@ -305,6 +305,11 @@ static int _nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct ...@@ -305,6 +305,11 @@ static int _nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct
if (status) if (status)
goto out_err; goto out_err;
update_changeattr(dir, &o_res.cinfo); 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; status = -ENOMEM;
inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr); 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, ...@@ -734,11 +739,10 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
return status; 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 = { struct nfs4_getattr_arg args = {
.fh = NFS_FH(inode), .fh = fhandle,
.bitmask = server->attr_bitmask, .bitmask = server->attr_bitmask,
}; };
struct nfs4_getattr_res res = { struct nfs4_getattr_res res = {
...@@ -752,16 +756,16 @@ static int _nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr) ...@@ -752,16 +756,16 @@ static int _nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
}; };
fattr->valid = 0; 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 = { }; struct nfs4_exception exception = { };
int err; int err;
do { do {
err = nfs4_handle_exception(NFS_SERVER(inode), err = nfs4_handle_exception(server,
_nfs4_proc_getattr(inode, fattr), _nfs4_proc_getattr(server, fhandle, fattr),
&exception); &exception);
} while (exception.retry); } while (exception.retry);
return err; return err;
......
...@@ -87,14 +87,15 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, ...@@ -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. * One function for each procedure in the NFS protocol.
*/ */
static int 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; int status;
dprintk("NFS call getattr\n"); dprintk("NFS call getattr\n");
fattr->valid = 0; fattr->valid = 0;
status = rpc_call(NFS_CLIENT(inode), NFSPROC_GETATTR, status = rpc_call(server->client, NFSPROC_GETATTR,
NFS_FH(inode), fattr, 0); fhandle, fattr, 0);
dprintk("NFS reply getattr\n"); dprintk("NFS reply getattr\n");
return status; return status;
} }
......
...@@ -669,7 +669,8 @@ struct nfs_rpc_ops { ...@@ -669,7 +669,8 @@ struct nfs_rpc_ops {
int (*getroot) (struct nfs_server *, struct nfs_fh *, int (*getroot) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *); 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 *, int (*setattr) (struct dentry *, struct nfs_fattr *,
struct iattr *); struct iattr *);
int (*lookup) (struct inode *, struct qstr *, 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