summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c56
-rw-r--r--fs/nfs/nfs4xdr.c74
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_xdr.h13
4 files changed, 80 insertions, 64 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 149d430aff57..6203634f598a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -82,19 +82,6 @@ nfs4_setup_compound(struct nfs4_compound *cp, struct nfs4_op *ops,
}
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);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 742958ee2f9e..b28f70e3f264 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -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 @@ out_bad_bitmap:
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;
@@ -2729,6 +2740,24 @@ out:
}
/*
+ * 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
*/
static int
@@ -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 = {
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 644cd1c27c47..5165192d15e7 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -303,6 +303,7 @@ enum {
NFSPROC4_CLNT_LOCK,
NFSPROC4_CLNT_LOCKT,
NFSPROC4_CLNT_LOCKU,
+ NFSPROC4_CLNT_ACCESS,
};
#endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 5c171dd6d818..94ac6db11699 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -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;