Commit 9c0c8d90 authored by Trond Myklebust's avatar Trond Myklebust

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

ACCESS RPC calls.
parent 677da9bf
......@@ -81,19 +81,6 @@ nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops,
cp->server = server;
}
static void
nfs4_setup_access(struct nfs4_compound *cp, u32 req_access, u32 *resp_supported, u32 *resp_access)
{
struct nfs4_access *access = GET_OP(cp, access);
access->ac_req_access = req_access;
access->ac_resp_supported = resp_supported;
access->ac_resp_access = resp_access;
OPNUM(cp) = OP_ACCESS;
cp->req_nops++;
}
static void
nfs4_setup_create_dir(struct nfs4_compound *cp, struct qstr *name,
struct iattr *sattr, struct nfs4_change_info *info)
......@@ -989,48 +976,43 @@ nfs4_proc_lookup(struct inode *dir, struct qstr *name,
return nfs4_map_errors(status);
}
static int
nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
{
struct nfs4_compound compound;
struct nfs4_op ops[3];
struct nfs_fattr fattr;
u32 req_access = 0, resp_supported, resp_access;
int status;
fattr.valid = 0;
struct nfs4_accessargs args = {
.fh = NFS_FH(inode),
};
struct nfs4_accessres res = { 0 };
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
.rpc_argp = &args,
.rpc_resp = &res,
.rpc_cred = cred,
};
/*
* Determine which access bits we want to ask for...
*/
if (mode & MAY_READ)
req_access |= NFS4_ACCESS_READ;
args.access |= NFS4_ACCESS_READ;
if (S_ISDIR(inode->i_mode)) {
if (mode & MAY_WRITE)
req_access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE;
args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE;
if (mode & MAY_EXEC)
req_access |= NFS4_ACCESS_LOOKUP;
args.access |= NFS4_ACCESS_LOOKUP;
}
else {
if (mode & MAY_WRITE)
req_access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND;
args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND;
if (mode & MAY_EXEC)
req_access |= NFS4_ACCESS_EXECUTE;
args.access |= NFS4_ACCESS_EXECUTE;
}
nfs4_setup_compound(&compound, ops, NFS_SERVER(inode), "access");
nfs4_setup_putfh(&compound, NFS_FH(inode));
nfs4_setup_getattr(&compound, &fattr);
nfs4_setup_access(&compound, req_access, &resp_supported, &resp_access);
status = nfs4_call_compound(&compound, cred, 0);
nfs_refresh_inode(inode, &fattr);
status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
if (!status) {
if (req_access != resp_supported) {
if (args.access != res.supported) {
printk(KERN_NOTICE "NFS: server didn't support all access bits!\n");
status = -ENOTSUPP;
}
else if (req_access != resp_access)
} else if ((args.access & res.access) != args.access)
status = -EACCES;
}
return nfs4_map_errors(status);
......
......@@ -255,7 +255,13 @@ static int nfs_stat_to_errno(int);
decode_putfh_maxsz + \
decode_getattr_maxsz + \
op_decode_hdr_maxsz + 4)
#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 1)
#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 2)
static struct {
......@@ -450,14 +456,13 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap,
return status;
}
static int
encode_access(struct xdr_stream *xdr, struct nfs4_access *access)
static int encode_access(struct xdr_stream *xdr, u32 access)
{
uint32_t *p;
RESERVE_SPACE(8);
WRITE32(OP_ACCESS);
WRITE32(access->ac_req_access);
WRITE32(access);
return 0;
}
......@@ -832,8 +837,7 @@ encode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeargs *arg)
return 0;
}
static int
encode_putfh(struct xdr_stream *xdr, struct nfs_fh *fh)
static int encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)
{
int len = fh->size;
uint32_t *p;
......@@ -1094,9 +1098,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
for (i = 0; i < cp->req_nops; i++) {
switch (cp->ops[i].opnum) {
case OP_ACCESS:
status = encode_access(xdr, &cp->ops[i].u.access);
break;
case OP_CREATE:
status = encode_create(xdr, &cp->ops[i].u.create, cp->server);
break;
......@@ -1149,7 +1150,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
* END OF "GENERIC" ENCODE ROUTINES.
*/
/*
* Encode COMPOUND argument
*/
......@@ -1164,6 +1164,26 @@ nfs4_xdr_enc_compound(struct rpc_rqst *req, uint32_t *p, struct nfs4_compound *c
cp->timestamp = jiffies;
return status;
}
/*
* Encode an ACCESS request
*/
static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct nfs4_accessargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
};
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
if ((status = encode_putfh(&xdr, args->fh)) == 0)
status = encode_access(&xdr, args->access);
return status;
}
/*
* Encode a CLOSE request
*/
......@@ -1645,8 +1665,7 @@ decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
return 0;
}
static int
decode_access(struct xdr_stream *xdr, struct nfs4_access *access)
static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
{
uint32_t *p;
uint32_t supp, acc;
......@@ -1658,12 +1677,8 @@ decode_access(struct xdr_stream *xdr, struct nfs4_access *access)
READ_BUF(8);
READ32(supp);
READ32(acc);
if ((supp & ~access->ac_req_access) || (acc & ~supp)) {
printk(KERN_NOTICE "NFS: server returned bad bits in access call!\n");
return -EIO;
}
*access->ac_resp_supported = supp;
*access->ac_resp_access = acc;
access->supported = supp;
access->access = acc;
return 0;
}
......@@ -2077,7 +2092,6 @@ decode_post_write_getattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
return -EIO;
}
static int
decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
{
......@@ -2628,9 +2642,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
op = &cp->ops[0];
for (cp->nops = 0; cp->nops < cp->resp_nops; cp->nops++, op++) {
switch (op->opnum) {
case OP_ACCESS:
status = decode_access(xdr, &op->u.access);
break;
case OP_CREATE:
status = decode_create(xdr, &op->u.create);
break;
......@@ -2728,6 +2739,24 @@ nfs4_xdr_dec_compound(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_compound
return status;
}
/*
* Decode ACCESS response
*/
static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_accessres *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)
status = decode_access(&xdr, res);
out:
return status;
}
/*
* Decode CLOSE response
*/
......@@ -3236,6 +3265,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(LOCK, enc_lock, dec_lock),
PROC(LOCKT, enc_lockt, dec_lockt),
PROC(LOCKU, enc_locku, dec_locku),
PROC(ACCESS, enc_access, dec_access),
};
struct rpc_version nfs_version4 = {
......
......@@ -303,6 +303,7 @@ enum {
NFSPROC4_CLNT_LOCK,
NFSPROC4_CLNT_LOCKT,
NFSPROC4_CLNT_LOCKU,
NFSPROC4_CLNT_ACCESS,
};
#endif
......
......@@ -484,10 +484,14 @@ struct nfs4_change_info {
u64 after;
};
struct nfs4_access {
u32 ac_req_access; /* request */
u32 * ac_resp_supported; /* response */
u32 * ac_resp_access; /* response */
struct nfs4_accessargs {
const struct nfs_fh * fh;
u32 access;
};
struct nfs4_accessres {
u32 supported;
u32 access;
};
struct nfs4_close {
......@@ -611,7 +615,6 @@ struct nfs4_setclientid {
struct nfs4_op {
u32 opnum;
union {
struct nfs4_access access;
struct nfs4_close close;
struct nfs4_create create;
struct nfs4_getattr getattr;
......
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