Commit efec5fa4 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: use the (more efficient) NFSv2/v3-like XDR scheme for generating

LOOKUP RPC calls.
parent abd795e9
...@@ -956,30 +956,31 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, ...@@ -956,30 +956,31 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
return status; return status;
} }
static int static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{ {
struct nfs4_compound compound; int status;
struct nfs4_op ops[5]; struct nfs4_lookup_arg args = {
struct nfs_fattr dir_attr; .bitmask = nfs4_fattr_bitmap,
int status; .dir_fh = NFS_FH(dir),
.name = name,
dir_attr.valid = 0; };
struct nfs4_lookup_res res = {
.server = NFS_SERVER(dir),
.fattr = fattr,
.fh = fhandle,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
.rpc_argp = &args,
.rpc_resp = &res,
};
fattr->valid = 0; fattr->valid = 0;
dprintk("NFS call lookup %s\n", name->name); dprintk("NFS call lookup %s\n", name->name);
nfs4_setup_compound(&compound, ops, NFS_SERVER(dir), "lookup"); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
nfs4_setup_putfh(&compound, NFS_FH(dir));
nfs4_setup_getattr(&compound, &dir_attr);
nfs4_setup_lookup(&compound, name);
nfs4_setup_getattr(&compound, fattr);
nfs4_setup_getfh(&compound, fhandle);
status = nfs4_call_compound(&compound, NULL, 0);
dprintk("NFS reply lookup: %d\n", status); dprintk("NFS reply lookup: %d\n", status);
if (status >= 0)
status = nfs_refresh_inode(dir, &dir_attr);
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
......
...@@ -81,7 +81,7 @@ static int nfs_stat_to_errno(int); ...@@ -81,7 +81,7 @@ static int nfs_stat_to_errno(int);
#define decode_putrootfh_maxsz (op_decode_hdr_maxsz) #define decode_putrootfh_maxsz (op_decode_hdr_maxsz)
#define encode_getfh_maxsz (op_encode_hdr_maxsz) #define encode_getfh_maxsz (op_encode_hdr_maxsz)
#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
(NFS4_FHSIZE >> 2)) ((3+NFS4_FHSIZE) >> 2))
#define encode_getattr_maxsz (op_encode_hdr_maxsz + 3) #define encode_getattr_maxsz (op_encode_hdr_maxsz + 3)
#define nfs4_fattr_bitmap_maxsz (26 + 2 * ((NFS4_MAXNAMLEN +1) >> 2)) #define nfs4_fattr_bitmap_maxsz (26 + 2 * ((NFS4_MAXNAMLEN +1) >> 2))
#define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \ #define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \
...@@ -109,7 +109,8 @@ static int nfs_stat_to_errno(int); ...@@ -109,7 +109,8 @@ static int nfs_stat_to_errno(int);
3 + (NFS4_VERIFIER_SIZE >> 2)) 3 + (NFS4_VERIFIER_SIZE >> 2))
#define decode_setclientid_confirm_maxsz \ #define decode_setclientid_confirm_maxsz \
(op_decode_hdr_maxsz) (op_decode_hdr_maxsz)
#define encode_lookup_maxsz (op_encode_hdr_maxsz + \
1 + ((3 + NFS4_FHSIZE) >> 2))
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
...@@ -251,6 +252,16 @@ static int nfs_stat_to_errno(int); ...@@ -251,6 +252,16 @@ static int nfs_stat_to_errno(int);
#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \ #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
decode_getattr_maxsz) decode_getattr_maxsz)
#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_lookup_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
...@@ -665,16 +676,15 @@ encode_locku(struct xdr_stream *xdr, struct nfs_lockargs *arg) ...@@ -665,16 +676,15 @@ encode_locku(struct xdr_stream *xdr, struct nfs_lockargs *arg)
return 0; return 0;
} }
static int static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
encode_lookup(struct xdr_stream *xdr, struct nfs4_lookup *lookup)
{ {
int len = lookup->lo_name->len; int len = name->len;
uint32_t *p; uint32_t *p;
RESERVE_SPACE(8 + len); RESERVE_SPACE(8 + len);
WRITE32(OP_LOOKUP); WRITE32(OP_LOOKUP);
WRITE32(len); WRITE32(len);
WRITEMEM(lookup->lo_name->name, len); WRITEMEM(name->name, len);
return 0; return 0;
} }
...@@ -1079,7 +1089,7 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1079,7 +1089,7 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
status = encode_link(xdr, &cp->ops[i].u.link); status = encode_link(xdr, &cp->ops[i].u.link);
break; break;
case OP_LOOKUP: case OP_LOOKUP:
status = encode_lookup(xdr, &cp->ops[i].u.lookup); status = encode_lookup(xdr, cp->ops[i].u.lookup.lo_name);
break; break;
case OP_PUTFH: case OP_PUTFH:
status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle); status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle);
...@@ -1151,6 +1161,30 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct n ...@@ -1151,6 +1161,30 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct n
return status; return status;
} }
/*
* Encode LOOKUP request
*/
static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 4,
};
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
goto out;
if ((status = encode_lookup(&xdr, args->name)) != 0)
goto out;
if ((status = encode_getfh(&xdr)) != 0)
goto out;
status = encode_getfattr(&xdr, args->bitmask);
out:
return status;
}
/* /*
* Encode GETATTR request * Encode GETATTR request
*/ */
...@@ -2376,10 +2410,8 @@ decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) ...@@ -2376,10 +2410,8 @@ decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
return -EIO; return -EIO;
} }
static int static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
decode_getfh(struct xdr_stream *xdr, struct nfs4_getfh *getfh)
{ {
struct nfs_fh *fh = getfh->gf_fhandle;
uint32_t *p; uint32_t *p;
uint32_t len; uint32_t len;
int status; int status;
...@@ -2392,7 +2424,7 @@ decode_getfh(struct xdr_stream *xdr, struct nfs4_getfh *getfh) ...@@ -2392,7 +2424,7 @@ decode_getfh(struct xdr_stream *xdr, struct nfs4_getfh *getfh)
READ_BUF(4); READ_BUF(4);
READ32(len); READ32(len);
if (len > NFS_MAXFHSIZE) if (len > NFS4_FHSIZE)
return -EIO; return -EIO;
fh->size = len; fh->size = len;
READ_BUF(len); READ_BUF(len);
...@@ -2865,7 +2897,7 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -2865,7 +2897,7 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
status = decode_getattr(xdr, &op->u.getattr, cp->server); status = decode_getattr(xdr, &op->u.getattr, cp->server);
break; break;
case OP_GETFH: case OP_GETFH:
status = decode_getfh(xdr, &op->u.getfh); status = decode_getfh(xdr, op->u.getfh.gf_fhandle);
break; break;
case OP_LINK: case OP_LINK:
status = decode_link(xdr, &op->u.link); status = decode_link(xdr, &op->u.link);
...@@ -2973,6 +3005,29 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ ...@@ -2973,6 +3005,29 @@ static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
return status; return status;
} }
/*
* Decode LOOKUP response
*/
static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
if ((status = decode_lookup(&xdr)) != 0)
goto out;
if ((status = decode_getfh(&xdr, res->fh)) != 0)
goto out;
status = decode_getfattr(&xdr, res->fattr, res->server);
out:
return status;
}
/* /*
* Decode GETATTR response * Decode GETATTR response
*/ */
...@@ -3026,9 +3081,6 @@ nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res) ...@@ -3026,9 +3081,6 @@ nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
{ {
struct xdr_stream xdr; struct xdr_stream xdr;
struct compound_hdr hdr; struct compound_hdr hdr;
struct nfs4_getfh gfh = {
.gf_fhandle = &res->fh,
};
int status; int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
...@@ -3047,7 +3099,7 @@ nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res) ...@@ -3047,7 +3099,7 @@ nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
status = decode_getattr(&xdr, res->f_getattr, res->server); status = decode_getattr(&xdr, res->f_getattr, res->server);
if (status) if (status)
goto out; goto out;
status = decode_getfh(&xdr, &gfh); status = decode_getfh(&xdr, &res->fh);
if (status) if (status)
goto out; goto out;
status = decode_restorefh(&xdr); status = decode_restorefh(&xdr);
...@@ -3485,6 +3537,7 @@ struct rpc_procinfo nfs4_procedures[] = { ...@@ -3485,6 +3537,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(LOCKU, enc_locku, dec_locku), PROC(LOCKU, enc_locku, dec_locku),
PROC(ACCESS, enc_access, dec_access), PROC(ACCESS, enc_access, dec_access),
PROC(GETATTR, enc_getattr, dec_getattr), PROC(GETATTR, enc_getattr, dec_getattr),
PROC(LOOKUP, enc_lookup, dec_lookup),
}; };
struct rpc_version nfs_version4 = { struct rpc_version nfs_version4 = {
......
...@@ -305,6 +305,7 @@ enum { ...@@ -305,6 +305,7 @@ enum {
NFSPROC4_CLNT_LOCKU, NFSPROC4_CLNT_LOCKU,
NFSPROC4_CLNT_ACCESS, NFSPROC4_CLNT_ACCESS,
NFSPROC4_CLNT_GETATTR, NFSPROC4_CLNT_GETATTR,
NFSPROC4_CLNT_LOOKUP,
}; };
#endif #endif
......
...@@ -554,6 +554,18 @@ struct nfs4_lookup { ...@@ -554,6 +554,18 @@ struct nfs4_lookup {
struct qstr * lo_name; /* request */ struct qstr * lo_name; /* request */
}; };
struct nfs4_lookup_arg {
const struct nfs_fh * dir_fh;
const struct qstr * name;
const u32 * bitmask;
};
struct nfs4_lookup_res {
const struct nfs_server * server;
struct nfs_fattr * fattr;
struct nfs_fh * fh;
};
struct nfs4_open { struct nfs4_open {
struct nfs4_client * op_client_state; /* request */ struct nfs4_client * op_client_state; /* request */
u32 op_share_access; /* request */ u32 op_share_access; /* request */
......
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