diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 241 |
1 files changed, 219 insertions, 22 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5f4de05763c9..6c564ef9489e 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/nfs4.h> | 51 | #include <linux/nfs4.h> |
52 | #include <linux/nfs_fs.h> | 52 | #include <linux/nfs_fs.h> |
53 | #include <linux/nfs_idmap.h> | 53 | #include <linux/nfs_idmap.h> |
54 | #include "nfs4_fs.h" | ||
54 | 55 | ||
55 | #define NFSDBG_FACILITY NFSDBG_XDR | 56 | #define NFSDBG_FACILITY NFSDBG_XDR |
56 | 57 | ||
@@ -82,12 +83,16 @@ static int nfs_stat_to_errno(int); | |||
82 | #define encode_getfh_maxsz (op_encode_hdr_maxsz) | 83 | #define encode_getfh_maxsz (op_encode_hdr_maxsz) |
83 | #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ | 84 | #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \ |
84 | ((3+NFS4_FHSIZE) >> 2)) | 85 | ((3+NFS4_FHSIZE) >> 2)) |
85 | #define encode_getattr_maxsz (op_encode_hdr_maxsz + 3) | 86 | #define nfs4_fattr_bitmap_maxsz 3 |
87 | #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) | ||
86 | #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) | 88 | #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2)) |
87 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 89 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
88 | #define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz) | 90 | /* This is based on getfattr, which uses the most attributes: */ |
89 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \ | 91 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
90 | nfs4_fattr_bitmap_maxsz) | 92 | 3 + 3 + 3 + 2 * nfs4_name_maxsz)) |
93 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ | ||
94 | nfs4_fattr_value_maxsz) | ||
95 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | ||
91 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 96 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
92 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 97 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
93 | #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) | 98 | #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) |
@@ -122,11 +127,11 @@ static int nfs_stat_to_errno(int); | |||
122 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ | 127 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ |
123 | 1 + nfs4_name_maxsz + \ | 128 | 1 + nfs4_name_maxsz + \ |
124 | nfs4_path_maxsz + \ | 129 | nfs4_path_maxsz + \ |
125 | nfs4_fattr_bitmap_maxsz) | 130 | nfs4_fattr_maxsz) |
126 | #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) | 131 | #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) |
127 | #define encode_create_maxsz (op_encode_hdr_maxsz + \ | 132 | #define encode_create_maxsz (op_encode_hdr_maxsz + \ |
128 | 2 + nfs4_name_maxsz + \ | 133 | 2 + nfs4_name_maxsz + \ |
129 | nfs4_fattr_bitmap_maxsz) | 134 | nfs4_fattr_maxsz) |
130 | #define decode_create_maxsz (op_decode_hdr_maxsz + 8) | 135 | #define decode_create_maxsz (op_decode_hdr_maxsz + 8) |
131 | #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) | 136 | #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4) |
132 | #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) | 137 | #define decode_delegreturn_maxsz (op_decode_hdr_maxsz) |
@@ -205,7 +210,7 @@ static int nfs_stat_to_errno(int); | |||
205 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ | 210 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ |
206 | encode_putfh_maxsz + \ | 211 | encode_putfh_maxsz + \ |
207 | op_encode_hdr_maxsz + 4 + \ | 212 | op_encode_hdr_maxsz + 4 + \ |
208 | nfs4_fattr_bitmap_maxsz + \ | 213 | nfs4_fattr_maxsz + \ |
209 | encode_getattr_maxsz) | 214 | encode_getattr_maxsz) |
210 | #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ | 215 | #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \ |
211 | decode_putfh_maxsz + \ | 216 | decode_putfh_maxsz + \ |
@@ -360,6 +365,20 @@ static int nfs_stat_to_errno(int); | |||
360 | encode_delegreturn_maxsz) | 365 | encode_delegreturn_maxsz) |
361 | #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ | 366 | #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ |
362 | decode_delegreturn_maxsz) | 367 | decode_delegreturn_maxsz) |
368 | #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ | ||
369 | encode_putfh_maxsz + \ | ||
370 | encode_getattr_maxsz) | ||
371 | #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \ | ||
372 | decode_putfh_maxsz + \ | ||
373 | op_decode_hdr_maxsz + \ | ||
374 | nfs4_fattr_bitmap_maxsz + 1) | ||
375 | #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \ | ||
376 | encode_putfh_maxsz + \ | ||
377 | op_encode_hdr_maxsz + 4 + \ | ||
378 | nfs4_fattr_bitmap_maxsz + 1) | ||
379 | #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \ | ||
380 | decode_putfh_maxsz + \ | ||
381 | op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz) | ||
363 | 382 | ||
364 | static struct { | 383 | static struct { |
365 | unsigned int mode; | 384 | unsigned int mode; |
@@ -459,7 +478,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s | |||
459 | * In the worst-case, this would be | 478 | * In the worst-case, this would be |
460 | * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) | 479 | * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) |
461 | * = 36 bytes, plus any contribution from variable-length fields | 480 | * = 36 bytes, plus any contribution from variable-length fields |
462 | * such as owner/group/acl's. | 481 | * such as owner/group. |
463 | */ | 482 | */ |
464 | len = 16; | 483 | len = 16; |
465 | 484 | ||
@@ -660,8 +679,6 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1 | |||
660 | 679 | ||
661 | static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask) | 680 | static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask) |
662 | { | 681 | { |
663 | extern u32 nfs4_fattr_bitmap[]; | ||
664 | |||
665 | return encode_getattr_two(xdr, | 682 | return encode_getattr_two(xdr, |
666 | bitmask[0] & nfs4_fattr_bitmap[0], | 683 | bitmask[0] & nfs4_fattr_bitmap[0], |
667 | bitmask[1] & nfs4_fattr_bitmap[1]); | 684 | bitmask[1] & nfs4_fattr_bitmap[1]); |
@@ -669,8 +686,6 @@ static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask) | |||
669 | 686 | ||
670 | static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask) | 687 | static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask) |
671 | { | 688 | { |
672 | extern u32 nfs4_fsinfo_bitmap[]; | ||
673 | |||
674 | return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], | 689 | return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0], |
675 | bitmask[1] & nfs4_fsinfo_bitmap[1]); | 690 | bitmask[1] & nfs4_fsinfo_bitmap[1]); |
676 | } | 691 | } |
@@ -969,7 +984,6 @@ static int encode_putrootfh(struct xdr_stream *xdr) | |||
969 | 984 | ||
970 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) | 985 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) |
971 | { | 986 | { |
972 | extern nfs4_stateid zero_stateid; | ||
973 | nfs4_stateid stateid; | 987 | nfs4_stateid stateid; |
974 | uint32_t *p; | 988 | uint32_t *p; |
975 | 989 | ||
@@ -1000,6 +1014,10 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args) | |||
1000 | static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req) | 1014 | static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req) |
1001 | { | 1015 | { |
1002 | struct rpc_auth *auth = req->rq_task->tk_auth; | 1016 | struct rpc_auth *auth = req->rq_task->tk_auth; |
1017 | uint32_t attrs[2] = { | ||
1018 | FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID, | ||
1019 | FATTR4_WORD1_MOUNTED_ON_FILEID, | ||
1020 | }; | ||
1003 | int replen; | 1021 | int replen; |
1004 | uint32_t *p; | 1022 | uint32_t *p; |
1005 | 1023 | ||
@@ -1010,13 +1028,20 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg | |||
1010 | WRITE32(readdir->count >> 1); /* We're not doing readdirplus */ | 1028 | WRITE32(readdir->count >> 1); /* We're not doing readdirplus */ |
1011 | WRITE32(readdir->count); | 1029 | WRITE32(readdir->count); |
1012 | WRITE32(2); | 1030 | WRITE32(2); |
1013 | if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) { | 1031 | /* Switch to mounted_on_fileid if the server supports it */ |
1014 | WRITE32(0); | 1032 | if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) |
1015 | WRITE32(FATTR4_WORD1_MOUNTED_ON_FILEID); | 1033 | attrs[0] &= ~FATTR4_WORD0_FILEID; |
1016 | } else { | 1034 | else |
1017 | WRITE32(FATTR4_WORD0_FILEID); | 1035 | attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; |
1018 | WRITE32(0); | 1036 | WRITE32(attrs[0] & readdir->bitmask[0]); |
1019 | } | 1037 | WRITE32(attrs[1] & readdir->bitmask[1]); |
1038 | dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n", | ||
1039 | __FUNCTION__, | ||
1040 | (unsigned long long)readdir->cookie, | ||
1041 | ((u32 *)readdir->verifier.data)[0], | ||
1042 | ((u32 *)readdir->verifier.data)[1], | ||
1043 | attrs[0] & readdir->bitmask[0], | ||
1044 | attrs[1] & readdir->bitmask[1]); | ||
1020 | 1045 | ||
1021 | /* set up reply kvec | 1046 | /* set up reply kvec |
1022 | * toplevel_status + taglen + rescount + OP_PUTFH + status | 1047 | * toplevel_status + taglen + rescount + OP_PUTFH + status |
@@ -1025,6 +1050,9 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg | |||
1025 | replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2; | 1050 | replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2; |
1026 | xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages, | 1051 | xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages, |
1027 | readdir->pgbase, readdir->count); | 1052 | readdir->pgbase, readdir->count); |
1053 | dprintk("%s: inlined page args = (%u, %p, %u, %u)\n", | ||
1054 | __FUNCTION__, replen, readdir->pages, | ||
1055 | readdir->pgbase, readdir->count); | ||
1028 | 1056 | ||
1029 | return 0; | 1057 | return 0; |
1030 | } | 1058 | } |
@@ -1089,6 +1117,25 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client | |||
1089 | } | 1117 | } |
1090 | 1118 | ||
1091 | static int | 1119 | static int |
1120 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) | ||
1121 | { | ||
1122 | uint32_t *p; | ||
1123 | |||
1124 | RESERVE_SPACE(4+sizeof(zero_stateid.data)); | ||
1125 | WRITE32(OP_SETATTR); | ||
1126 | WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data)); | ||
1127 | RESERVE_SPACE(2*4); | ||
1128 | WRITE32(1); | ||
1129 | WRITE32(FATTR4_WORD0_ACL); | ||
1130 | if (arg->acl_len % 4) | ||
1131 | return -EINVAL; | ||
1132 | RESERVE_SPACE(4); | ||
1133 | WRITE32(arg->acl_len); | ||
1134 | xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len); | ||
1135 | return 0; | ||
1136 | } | ||
1137 | |||
1138 | static int | ||
1092 | encode_savefh(struct xdr_stream *xdr) | 1139 | encode_savefh(struct xdr_stream *xdr) |
1093 | { | 1140 | { |
1094 | uint32_t *p; | 1141 | uint32_t *p; |
@@ -1632,6 +1679,34 @@ out: | |||
1632 | } | 1679 | } |
1633 | 1680 | ||
1634 | /* | 1681 | /* |
1682 | * Encode a GETACL request | ||
1683 | */ | ||
1684 | static int | ||
1685 | nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p, | ||
1686 | struct nfs_getaclargs *args) | ||
1687 | { | ||
1688 | struct xdr_stream xdr; | ||
1689 | struct rpc_auth *auth = req->rq_task->tk_auth; | ||
1690 | struct compound_hdr hdr = { | ||
1691 | .nops = 2, | ||
1692 | }; | ||
1693 | int replen, status; | ||
1694 | |||
1695 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1696 | encode_compound_hdr(&xdr, &hdr); | ||
1697 | status = encode_putfh(&xdr, args->fh); | ||
1698 | if (status) | ||
1699 | goto out; | ||
1700 | status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0); | ||
1701 | /* set up reply buffer: */ | ||
1702 | replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2; | ||
1703 | xdr_inline_pages(&req->rq_rcv_buf, replen, | ||
1704 | args->acl_pages, args->acl_pgbase, args->acl_len); | ||
1705 | out: | ||
1706 | return status; | ||
1707 | } | ||
1708 | |||
1709 | /* | ||
1635 | * Encode a WRITE request | 1710 | * Encode a WRITE request |
1636 | */ | 1711 | */ |
1637 | static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args) | 1712 | static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args) |
@@ -1697,7 +1772,6 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs | |||
1697 | */ | 1772 | */ |
1698 | static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args) | 1773 | static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args) |
1699 | { | 1774 | { |
1700 | extern u32 nfs4_pathconf_bitmap[2]; | ||
1701 | struct xdr_stream xdr; | 1775 | struct xdr_stream xdr; |
1702 | struct compound_hdr hdr = { | 1776 | struct compound_hdr hdr = { |
1703 | .nops = 2, | 1777 | .nops = 2, |
@@ -1718,7 +1792,6 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct | |||
1718 | */ | 1792 | */ |
1719 | static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args) | 1793 | static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args) |
1720 | { | 1794 | { |
1721 | extern u32 nfs4_statfs_bitmap[]; | ||
1722 | struct xdr_stream xdr; | 1795 | struct xdr_stream xdr; |
1723 | struct compound_hdr hdr = { | 1796 | struct compound_hdr hdr = { |
1724 | .nops = 2, | 1797 | .nops = 2, |
@@ -3003,6 +3076,11 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
3003 | return status; | 3076 | return status; |
3004 | READ_BUF(8); | 3077 | READ_BUF(8); |
3005 | COPYMEM(readdir->verifier.data, 8); | 3078 | COPYMEM(readdir->verifier.data, 8); |
3079 | dprintk("%s: verifier = 0x%x%x\n", | ||
3080 | __FUNCTION__, | ||
3081 | ((u32 *)readdir->verifier.data)[0], | ||
3082 | ((u32 *)readdir->verifier.data)[1]); | ||
3083 | |||
3006 | 3084 | ||
3007 | hdrlen = (char *) p - (char *) iov->iov_base; | 3085 | hdrlen = (char *) p - (char *) iov->iov_base; |
3008 | recvd = rcvbuf->len - hdrlen; | 3086 | recvd = rcvbuf->len - hdrlen; |
@@ -3017,12 +3095,14 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
3017 | for (nr = 0; *p++; nr++) { | 3095 | for (nr = 0; *p++; nr++) { |
3018 | if (p + 3 > end) | 3096 | if (p + 3 > end) |
3019 | goto short_pkt; | 3097 | goto short_pkt; |
3098 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); | ||
3020 | p += 2; /* cookie */ | 3099 | p += 2; /* cookie */ |
3021 | len = ntohl(*p++); /* filename length */ | 3100 | len = ntohl(*p++); /* filename length */ |
3022 | if (len > NFS4_MAXNAMLEN) { | 3101 | if (len > NFS4_MAXNAMLEN) { |
3023 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); | 3102 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); |
3024 | goto err_unmap; | 3103 | goto err_unmap; |
3025 | } | 3104 | } |
3105 | dprintk("filename = %*s\n", len, (char *)p); | ||
3026 | p += XDR_QUADLEN(len); | 3106 | p += XDR_QUADLEN(len); |
3027 | if (p + 1 > end) | 3107 | if (p + 1 > end) |
3028 | goto short_pkt; | 3108 | goto short_pkt; |
@@ -3042,6 +3122,7 @@ out: | |||
3042 | kunmap_atomic(kaddr, KM_USER0); | 3122 | kunmap_atomic(kaddr, KM_USER0); |
3043 | return 0; | 3123 | return 0; |
3044 | short_pkt: | 3124 | short_pkt: |
3125 | dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr); | ||
3045 | entry[0] = entry[1] = 0; | 3126 | entry[0] = entry[1] = 0; |
3046 | /* truncate listing ? */ | 3127 | /* truncate listing ? */ |
3047 | if (!nr) { | 3128 | if (!nr) { |
@@ -3127,6 +3208,47 @@ static int decode_renew(struct xdr_stream *xdr) | |||
3127 | return decode_op_hdr(xdr, OP_RENEW); | 3208 | return decode_op_hdr(xdr, OP_RENEW); |
3128 | } | 3209 | } |
3129 | 3210 | ||
3211 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | ||
3212 | size_t *acl_len) | ||
3213 | { | ||
3214 | uint32_t *savep; | ||
3215 | uint32_t attrlen, | ||
3216 | bitmap[2] = {0}; | ||
3217 | struct kvec *iov = req->rq_rcv_buf.head; | ||
3218 | int status; | ||
3219 | |||
3220 | *acl_len = 0; | ||
3221 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | ||
3222 | goto out; | ||
3223 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | ||
3224 | goto out; | ||
3225 | if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0) | ||
3226 | goto out; | ||
3227 | |||
3228 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) | ||
3229 | return -EIO; | ||
3230 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { | ||
3231 | int hdrlen, recvd; | ||
3232 | |||
3233 | /* We ignore &savep and don't do consistency checks on | ||
3234 | * the attr length. Let userspace figure it out.... */ | ||
3235 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; | ||
3236 | recvd = req->rq_rcv_buf.len - hdrlen; | ||
3237 | if (attrlen > recvd) { | ||
3238 | printk(KERN_WARNING "NFS: server cheating in getattr" | ||
3239 | " acl reply: attrlen %u > recvd %u\n", | ||
3240 | attrlen, recvd); | ||
3241 | return -EINVAL; | ||
3242 | } | ||
3243 | if (attrlen <= *acl_len) | ||
3244 | xdr_read_pages(xdr, attrlen); | ||
3245 | *acl_len = attrlen; | ||
3246 | } | ||
3247 | |||
3248 | out: | ||
3249 | return status; | ||
3250 | } | ||
3251 | |||
3130 | static int | 3252 | static int |
3131 | decode_savefh(struct xdr_stream *xdr) | 3253 | decode_savefh(struct xdr_stream *xdr) |
3132 | { | 3254 | { |
@@ -3418,6 +3540,71 @@ out: | |||
3418 | 3540 | ||
3419 | } | 3541 | } |
3420 | 3542 | ||
3543 | /* | ||
3544 | * Encode an SETACL request | ||
3545 | */ | ||
3546 | static int | ||
3547 | nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args) | ||
3548 | { | ||
3549 | struct xdr_stream xdr; | ||
3550 | struct compound_hdr hdr = { | ||
3551 | .nops = 2, | ||
3552 | }; | ||
3553 | int status; | ||
3554 | |||
3555 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
3556 | encode_compound_hdr(&xdr, &hdr); | ||
3557 | status = encode_putfh(&xdr, args->fh); | ||
3558 | if (status) | ||
3559 | goto out; | ||
3560 | status = encode_setacl(&xdr, args); | ||
3561 | out: | ||
3562 | return status; | ||
3563 | } | ||
3564 | /* | ||
3565 | * Decode SETACL response | ||
3566 | */ | ||
3567 | static int | ||
3568 | nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res) | ||
3569 | { | ||
3570 | struct xdr_stream xdr; | ||
3571 | struct compound_hdr hdr; | ||
3572 | int status; | ||
3573 | |||
3574 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | ||
3575 | status = decode_compound_hdr(&xdr, &hdr); | ||
3576 | if (status) | ||
3577 | goto out; | ||
3578 | status = decode_putfh(&xdr); | ||
3579 | if (status) | ||
3580 | goto out; | ||
3581 | status = decode_setattr(&xdr, res); | ||
3582 | out: | ||
3583 | return status; | ||
3584 | } | ||
3585 | |||
3586 | /* | ||
3587 | * Decode GETACL response | ||
3588 | */ | ||
3589 | static int | ||
3590 | nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len) | ||
3591 | { | ||
3592 | struct xdr_stream xdr; | ||
3593 | struct compound_hdr hdr; | ||
3594 | int status; | ||
3595 | |||
3596 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | ||
3597 | status = decode_compound_hdr(&xdr, &hdr); | ||
3598 | if (status) | ||
3599 | goto out; | ||
3600 | status = decode_putfh(&xdr); | ||
3601 | if (status) | ||
3602 | goto out; | ||
3603 | status = decode_getacl(&xdr, rqstp, acl_len); | ||
3604 | |||
3605 | out: | ||
3606 | return status; | ||
3607 | } | ||
3421 | 3608 | ||
3422 | /* | 3609 | /* |
3423 | * Decode CLOSE response | 3610 | * Decode CLOSE response |
@@ -3895,6 +4082,12 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus) | |||
3895 | } | 4082 | } |
3896 | len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */ | 4083 | len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */ |
3897 | if (len > 0) { | 4084 | if (len > 0) { |
4085 | if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) { | ||
4086 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | ||
4087 | /* Ignore the return value of rdattr_error for now */ | ||
4088 | p++; | ||
4089 | len--; | ||
4090 | } | ||
3898 | if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID) | 4091 | if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID) |
3899 | xdr_decode_hyper(p, &entry->ino); | 4092 | xdr_decode_hyper(p, &entry->ino); |
3900 | else if (bitmap[0] == FATTR4_WORD0_FILEID) | 4093 | else if (bitmap[0] == FATTR4_WORD0_FILEID) |
@@ -3934,6 +4127,8 @@ static struct { | |||
3934 | { NFS4ERR_DQUOT, EDQUOT }, | 4127 | { NFS4ERR_DQUOT, EDQUOT }, |
3935 | { NFS4ERR_STALE, ESTALE }, | 4128 | { NFS4ERR_STALE, ESTALE }, |
3936 | { NFS4ERR_BADHANDLE, EBADHANDLE }, | 4129 | { NFS4ERR_BADHANDLE, EBADHANDLE }, |
4130 | { NFS4ERR_BADOWNER, EINVAL }, | ||
4131 | { NFS4ERR_BADNAME, EINVAL }, | ||
3937 | { NFS4ERR_BAD_COOKIE, EBADCOOKIE }, | 4132 | { NFS4ERR_BAD_COOKIE, EBADCOOKIE }, |
3938 | { NFS4ERR_NOTSUPP, ENOTSUPP }, | 4133 | { NFS4ERR_NOTSUPP, ENOTSUPP }, |
3939 | { NFS4ERR_TOOSMALL, ETOOSMALL }, | 4134 | { NFS4ERR_TOOSMALL, ETOOSMALL }, |
@@ -4019,6 +4214,8 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
4019 | PROC(READDIR, enc_readdir, dec_readdir), | 4214 | PROC(READDIR, enc_readdir, dec_readdir), |
4020 | PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), | 4215 | PROC(SERVER_CAPS, enc_server_caps, dec_server_caps), |
4021 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), | 4216 | PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn), |
4217 | PROC(GETACL, enc_getacl, dec_getacl), | ||
4218 | PROC(SETACL, enc_setacl, dec_setacl), | ||
4022 | }; | 4219 | }; |
4023 | 4220 | ||
4024 | struct rpc_version nfs_version4 = { | 4221 | struct rpc_version nfs_version4 = { |