diff options
author | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
commit | ee3e542fec6e69bc9fb668698889a37d93950ddf (patch) | |
tree | e74ee766a4764769ef1d3d45d266b4dea64101d3 /fs/nfs/nfs4xdr.c | |
parent | fe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff) | |
parent | f1d6e17f540af37bb1891480143669ba7636c4cf (diff) |
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 189 |
1 files changed, 151 insertions, 38 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 4be8d135ed61..3850b018815f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -102,12 +102,23 @@ static int nfs4_stat_to_errno(int); | |||
102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
105 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
106 | /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */ | ||
107 | #define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN)) | ||
108 | #define encode_readdir_space 24 | ||
109 | #define encode_readdir_bitmask_sz 3 | ||
110 | #else | ||
111 | #define nfs4_label_maxsz 0 | ||
112 | #define encode_readdir_space 20 | ||
113 | #define encode_readdir_bitmask_sz 2 | ||
114 | #endif | ||
105 | /* We support only one layout type per file system */ | 115 | /* We support only one layout type per file system */ |
106 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) | 116 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) |
107 | /* This is based on getfattr, which uses the most attributes: */ | 117 | /* This is based on getfattr, which uses the most attributes: */ |
108 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ | 118 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
109 | 3 + 3 + 3 + nfs4_owner_maxsz + \ | 119 | 3 + 3 + 3 + nfs4_owner_maxsz + \ |
110 | nfs4_group_maxsz + decode_mdsthreshold_maxsz)) | 120 | nfs4_group_maxsz + nfs4_label_maxsz + \ |
121 | decode_mdsthreshold_maxsz)) | ||
111 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ | 122 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ |
112 | nfs4_fattr_value_maxsz) | 123 | nfs4_fattr_value_maxsz) |
113 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 124 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
@@ -115,6 +126,7 @@ static int nfs4_stat_to_errno(int); | |||
115 | 1 + 2 + 1 + \ | 126 | 1 + 2 + 1 + \ |
116 | nfs4_owner_maxsz + \ | 127 | nfs4_owner_maxsz + \ |
117 | nfs4_group_maxsz + \ | 128 | nfs4_group_maxsz + \ |
129 | nfs4_label_maxsz + \ | ||
118 | 4 + 4) | 130 | 4 + 4) |
119 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 131 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
120 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 132 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
@@ -192,9 +204,11 @@ static int nfs4_stat_to_errno(int); | |||
192 | encode_stateid_maxsz + 3) | 204 | encode_stateid_maxsz + 3) |
193 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) | 205 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) |
194 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ | 206 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ |
195 | 2 + encode_verifier_maxsz + 5) | 207 | 2 + encode_verifier_maxsz + 5 + \ |
208 | nfs4_label_maxsz) | ||
196 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ | 209 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ |
197 | decode_verifier_maxsz) | 210 | decode_verifier_maxsz + \ |
211 | nfs4_label_maxsz + nfs4_fattr_maxsz) | ||
198 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) | 212 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) |
199 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) | 213 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) |
200 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ | 214 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ |
@@ -853,6 +867,12 @@ const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH + | |||
853 | decode_sequence_maxsz + | 867 | decode_sequence_maxsz + |
854 | decode_putfh_maxsz) * | 868 | decode_putfh_maxsz) * |
855 | XDR_UNIT); | 869 | XDR_UNIT); |
870 | |||
871 | const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH + | ||
872 | compound_decode_hdr_maxsz + | ||
873 | decode_sequence_maxsz) * | ||
874 | XDR_UNIT); | ||
875 | EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead); | ||
856 | #endif /* CONFIG_NFS_V4_1 */ | 876 | #endif /* CONFIG_NFS_V4_1 */ |
857 | 877 | ||
858 | static const umode_t nfs_type2fmt[] = { | 878 | static const umode_t nfs_type2fmt[] = { |
@@ -968,7 +988,9 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve | |||
968 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); | 988 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); |
969 | } | 989 | } |
970 | 990 | ||
971 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) | 991 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, |
992 | const struct nfs4_label *label, | ||
993 | const struct nfs_server *server) | ||
972 | { | 994 | { |
973 | char owner_name[IDMAP_NAMESZ]; | 995 | char owner_name[IDMAP_NAMESZ]; |
974 | char owner_group[IDMAP_NAMESZ]; | 996 | char owner_group[IDMAP_NAMESZ]; |
@@ -977,17 +999,19 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
977 | __be32 *p; | 999 | __be32 *p; |
978 | __be32 *q; | 1000 | __be32 *q; |
979 | int len; | 1001 | int len; |
1002 | uint32_t bmval_len = 2; | ||
980 | uint32_t bmval0 = 0; | 1003 | uint32_t bmval0 = 0; |
981 | uint32_t bmval1 = 0; | 1004 | uint32_t bmval1 = 0; |
1005 | uint32_t bmval2 = 0; | ||
982 | 1006 | ||
983 | /* | 1007 | /* |
984 | * We reserve enough space to write the entire attribute buffer at once. | 1008 | * We reserve enough space to write the entire attribute buffer at once. |
985 | * In the worst-case, this would be | 1009 | * In the worst-case, this would be |
986 | * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) | 1010 | * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime) |
987 | * = 36 bytes, plus any contribution from variable-length fields | 1011 | * = 40 bytes, plus any contribution from variable-length fields |
988 | * such as owner/group. | 1012 | * such as owner/group. |
989 | */ | 1013 | */ |
990 | len = 16; | 1014 | len = 8; |
991 | 1015 | ||
992 | /* Sigh */ | 1016 | /* Sigh */ |
993 | if (iap->ia_valid & ATTR_SIZE) | 1017 | if (iap->ia_valid & ATTR_SIZE) |
@@ -1025,15 +1049,22 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1025 | len += 16; | 1049 | len += 16; |
1026 | else if (iap->ia_valid & ATTR_MTIME) | 1050 | else if (iap->ia_valid & ATTR_MTIME) |
1027 | len += 4; | 1051 | len += 4; |
1052 | if (label) { | ||
1053 | len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); | ||
1054 | bmval_len = 3; | ||
1055 | } | ||
1056 | |||
1057 | len += bmval_len << 2; | ||
1028 | p = reserve_space(xdr, len); | 1058 | p = reserve_space(xdr, len); |
1029 | 1059 | ||
1030 | /* | 1060 | /* |
1031 | * We write the bitmap length now, but leave the bitmap and the attribute | 1061 | * We write the bitmap length now, but leave the bitmap and the attribute |
1032 | * buffer length to be backfilled at the end of this routine. | 1062 | * buffer length to be backfilled at the end of this routine. |
1033 | */ | 1063 | */ |
1034 | *p++ = cpu_to_be32(2); | 1064 | *p++ = cpu_to_be32(bmval_len); |
1035 | q = p; | 1065 | q = p; |
1036 | p += 3; | 1066 | /* Skip bitmap entries + attrlen */ |
1067 | p += bmval_len + 1; | ||
1037 | 1068 | ||
1038 | if (iap->ia_valid & ATTR_SIZE) { | 1069 | if (iap->ia_valid & ATTR_SIZE) { |
1039 | bmval0 |= FATTR4_WORD0_SIZE; | 1070 | bmval0 |= FATTR4_WORD0_SIZE; |
@@ -1071,6 +1102,13 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1071 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | 1102 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; |
1072 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | 1103 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
1073 | } | 1104 | } |
1105 | if (label) { | ||
1106 | bmval2 |= FATTR4_WORD2_SECURITY_LABEL; | ||
1107 | *p++ = cpu_to_be32(label->lfs); | ||
1108 | *p++ = cpu_to_be32(label->pi); | ||
1109 | *p++ = cpu_to_be32(label->len); | ||
1110 | p = xdr_encode_opaque_fixed(p, label->label, label->len); | ||
1111 | } | ||
1074 | 1112 | ||
1075 | /* | 1113 | /* |
1076 | * Now we backfill the bitmap and the attribute buffer length. | 1114 | * Now we backfill the bitmap and the attribute buffer length. |
@@ -1080,9 +1118,11 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1080 | len, ((char *)p - (char *)q) + 4); | 1118 | len, ((char *)p - (char *)q) + 4); |
1081 | BUG(); | 1119 | BUG(); |
1082 | } | 1120 | } |
1083 | len = (char *)p - (char *)q - 12; | ||
1084 | *q++ = htonl(bmval0); | 1121 | *q++ = htonl(bmval0); |
1085 | *q++ = htonl(bmval1); | 1122 | *q++ = htonl(bmval1); |
1123 | if (bmval_len == 3) | ||
1124 | *q++ = htonl(bmval2); | ||
1125 | len = (char *)p - (char *)(q + 1); | ||
1086 | *q = htonl(len); | 1126 | *q = htonl(len); |
1087 | 1127 | ||
1088 | /* out: */ | 1128 | /* out: */ |
@@ -1136,7 +1176,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg * | |||
1136 | } | 1176 | } |
1137 | 1177 | ||
1138 | encode_string(xdr, create->name->len, create->name->name); | 1178 | encode_string(xdr, create->name->len, create->name->name); |
1139 | encode_attrs(xdr, create->attrs, create->server); | 1179 | encode_attrs(xdr, create->attrs, create->label, create->server); |
1140 | } | 1180 | } |
1141 | 1181 | ||
1142 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) | 1182 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) |
@@ -1188,8 +1228,10 @@ encode_getattr_three(struct xdr_stream *xdr, | |||
1188 | 1228 | ||
1189 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) | 1229 | static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr) |
1190 | { | 1230 | { |
1191 | encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0], | 1231 | encode_getattr_three(xdr, bitmask[0] & nfs4_fattr_bitmap[0], |
1192 | bitmask[1] & nfs4_fattr_bitmap[1], hdr); | 1232 | bitmask[1] & nfs4_fattr_bitmap[1], |
1233 | bitmask[2] & nfs4_fattr_bitmap[2], | ||
1234 | hdr); | ||
1193 | } | 1235 | } |
1194 | 1236 | ||
1195 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, | 1237 | static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask, |
@@ -1367,11 +1409,11 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
1367 | switch(arg->createmode) { | 1409 | switch(arg->createmode) { |
1368 | case NFS4_CREATE_UNCHECKED: | 1410 | case NFS4_CREATE_UNCHECKED: |
1369 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); | 1411 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); |
1370 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1412 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
1371 | break; | 1413 | break; |
1372 | case NFS4_CREATE_GUARDED: | 1414 | case NFS4_CREATE_GUARDED: |
1373 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); | 1415 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); |
1374 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1416 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
1375 | break; | 1417 | break; |
1376 | case NFS4_CREATE_EXCLUSIVE: | 1418 | case NFS4_CREATE_EXCLUSIVE: |
1377 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); | 1419 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); |
@@ -1381,7 +1423,7 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
1381 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); | 1423 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); |
1382 | encode_nfs4_verifier(xdr, &arg->u.verifier); | 1424 | encode_nfs4_verifier(xdr, &arg->u.verifier); |
1383 | dummy.ia_valid = 0; | 1425 | dummy.ia_valid = 0; |
1384 | encode_attrs(xdr, &dummy, arg->server); | 1426 | encode_attrs(xdr, &dummy, arg->label, arg->server); |
1385 | } | 1427 | } |
1386 | } | 1428 | } |
1387 | 1429 | ||
@@ -1532,7 +1574,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
1532 | 1574 | ||
1533 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1575 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
1534 | { | 1576 | { |
1535 | uint32_t attrs[2] = { | 1577 | uint32_t attrs[3] = { |
1536 | FATTR4_WORD0_RDATTR_ERROR, | 1578 | FATTR4_WORD0_RDATTR_ERROR, |
1537 | FATTR4_WORD1_MOUNTED_ON_FILEID, | 1579 | FATTR4_WORD1_MOUNTED_ON_FILEID, |
1538 | }; | 1580 | }; |
@@ -1555,20 +1597,26 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg | |||
1555 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); | 1597 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); |
1556 | encode_uint64(xdr, readdir->cookie); | 1598 | encode_uint64(xdr, readdir->cookie); |
1557 | encode_nfs4_verifier(xdr, &readdir->verifier); | 1599 | encode_nfs4_verifier(xdr, &readdir->verifier); |
1558 | p = reserve_space(xdr, 20); | 1600 | p = reserve_space(xdr, encode_readdir_space); |
1559 | *p++ = cpu_to_be32(dircount); | 1601 | *p++ = cpu_to_be32(dircount); |
1560 | *p++ = cpu_to_be32(readdir->count); | 1602 | *p++ = cpu_to_be32(readdir->count); |
1561 | *p++ = cpu_to_be32(2); | 1603 | *p++ = cpu_to_be32(encode_readdir_bitmask_sz); |
1562 | |||
1563 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); | 1604 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); |
1564 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); | 1605 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); |
1606 | if (encode_readdir_bitmask_sz > 2) { | ||
1607 | if (hdr->minorversion > 1) | ||
1608 | attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; | ||
1609 | p++, *p++ = cpu_to_be32(attrs[2] & readdir->bitmask[2]); | ||
1610 | } | ||
1565 | memcpy(verf, readdir->verifier.data, sizeof(verf)); | 1611 | memcpy(verf, readdir->verifier.data, sizeof(verf)); |
1566 | dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", | 1612 | |
1613 | dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", | ||
1567 | __func__, | 1614 | __func__, |
1568 | (unsigned long long)readdir->cookie, | 1615 | (unsigned long long)readdir->cookie, |
1569 | verf[0], verf[1], | 1616 | verf[0], verf[1], |
1570 | attrs[0] & readdir->bitmask[0], | 1617 | attrs[0] & readdir->bitmask[0], |
1571 | attrs[1] & readdir->bitmask[1]); | 1618 | attrs[1] & readdir->bitmask[1], |
1619 | attrs[2] & readdir->bitmask[2]); | ||
1572 | } | 1620 | } |
1573 | 1621 | ||
1574 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) | 1622 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) |
@@ -1627,7 +1675,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs | |||
1627 | { | 1675 | { |
1628 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); | 1676 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); |
1629 | encode_nfs4_stateid(xdr, &arg->stateid); | 1677 | encode_nfs4_stateid(xdr, &arg->stateid); |
1630 | encode_attrs(xdr, arg->iap, server); | 1678 | encode_attrs(xdr, arg->iap, arg->label, server); |
1631 | } | 1679 | } |
1632 | 1680 | ||
1633 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) | 1681 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) |
@@ -1889,7 +1937,7 @@ encode_getdeviceinfo(struct xdr_stream *xdr, | |||
1889 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, | 1937 | p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data, |
1890 | NFS4_DEVICEID4_SIZE); | 1938 | NFS4_DEVICEID4_SIZE); |
1891 | *p++ = cpu_to_be32(args->pdev->layout_type); | 1939 | *p++ = cpu_to_be32(args->pdev->layout_type); |
1892 | *p++ = cpu_to_be32(args->pdev->pglen); /* gdia_maxcount */ | 1940 | *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */ |
1893 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ | 1941 | *p++ = cpu_to_be32(0); /* bitmap length 0 */ |
1894 | } | 1942 | } |
1895 | 1943 | ||
@@ -4038,6 +4086,56 @@ static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4038 | return status; | 4086 | return status; |
4039 | } | 4087 | } |
4040 | 4088 | ||
4089 | static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, | ||
4090 | struct nfs4_label *label) | ||
4091 | { | ||
4092 | uint32_t pi = 0; | ||
4093 | uint32_t lfs = 0; | ||
4094 | __u32 len; | ||
4095 | __be32 *p; | ||
4096 | int status = 0; | ||
4097 | |||
4098 | if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U))) | ||
4099 | return -EIO; | ||
4100 | if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { | ||
4101 | p = xdr_inline_decode(xdr, 4); | ||
4102 | if (unlikely(!p)) | ||
4103 | goto out_overflow; | ||
4104 | lfs = be32_to_cpup(p++); | ||
4105 | p = xdr_inline_decode(xdr, 4); | ||
4106 | if (unlikely(!p)) | ||
4107 | goto out_overflow; | ||
4108 | pi = be32_to_cpup(p++); | ||
4109 | p = xdr_inline_decode(xdr, 4); | ||
4110 | if (unlikely(!p)) | ||
4111 | goto out_overflow; | ||
4112 | len = be32_to_cpup(p++); | ||
4113 | p = xdr_inline_decode(xdr, len); | ||
4114 | if (unlikely(!p)) | ||
4115 | goto out_overflow; | ||
4116 | if (len < NFS4_MAXLABELLEN) { | ||
4117 | if (label) { | ||
4118 | memcpy(label->label, p, len); | ||
4119 | label->len = len; | ||
4120 | label->pi = pi; | ||
4121 | label->lfs = lfs; | ||
4122 | status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; | ||
4123 | } | ||
4124 | bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
4125 | } else | ||
4126 | printk(KERN_WARNING "%s: label too long (%u)!\n", | ||
4127 | __func__, len); | ||
4128 | } | ||
4129 | if (label && label->label) | ||
4130 | dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, | ||
4131 | (char *)label->label, label->len, label->pi, label->lfs); | ||
4132 | return status; | ||
4133 | |||
4134 | out_overflow: | ||
4135 | print_overflow_msg(__func__, xdr); | ||
4136 | return -EIO; | ||
4137 | } | ||
4138 | |||
4041 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4139 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
4042 | { | 4140 | { |
4043 | int status = 0; | 4141 | int status = 0; |
@@ -4380,7 +4478,7 @@ out_overflow: | |||
4380 | 4478 | ||
4381 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4479 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
4382 | struct nfs_fattr *fattr, struct nfs_fh *fh, | 4480 | struct nfs_fattr *fattr, struct nfs_fh *fh, |
4383 | struct nfs4_fs_locations *fs_loc, | 4481 | struct nfs4_fs_locations *fs_loc, struct nfs4_label *label, |
4384 | const struct nfs_server *server) | 4482 | const struct nfs_server *server) |
4385 | { | 4483 | { |
4386 | int status; | 4484 | int status; |
@@ -4488,6 +4586,13 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4488 | if (status < 0) | 4586 | if (status < 0) |
4489 | goto xdr_error; | 4587 | goto xdr_error; |
4490 | 4588 | ||
4589 | if (label) { | ||
4590 | status = decode_attr_security_label(xdr, bitmap, label); | ||
4591 | if (status < 0) | ||
4592 | goto xdr_error; | ||
4593 | fattr->valid |= status; | ||
4594 | } | ||
4595 | |||
4491 | xdr_error: | 4596 | xdr_error: |
4492 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4597 | dprintk("%s: xdr returned %d\n", __func__, -status); |
4493 | return status; | 4598 | return status; |
@@ -4495,7 +4600,7 @@ xdr_error: | |||
4495 | 4600 | ||
4496 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4601 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4497 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, | 4602 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, |
4498 | const struct nfs_server *server) | 4603 | struct nfs4_label *label, const struct nfs_server *server) |
4499 | { | 4604 | { |
4500 | unsigned int savep; | 4605 | unsigned int savep; |
4501 | uint32_t attrlen, | 4606 | uint32_t attrlen, |
@@ -4514,7 +4619,8 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat | |||
4514 | if (status < 0) | 4619 | if (status < 0) |
4515 | goto xdr_error; | 4620 | goto xdr_error; |
4516 | 4621 | ||
4517 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server); | 4622 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, |
4623 | label, server); | ||
4518 | if (status < 0) | 4624 | if (status < 0) |
4519 | goto xdr_error; | 4625 | goto xdr_error; |
4520 | 4626 | ||
@@ -4524,10 +4630,16 @@ xdr_error: | |||
4524 | return status; | 4630 | return status; |
4525 | } | 4631 | } |
4526 | 4632 | ||
4633 | static int decode_getfattr_label(struct xdr_stream *xdr, struct nfs_fattr *fattr, | ||
4634 | struct nfs4_label *label, const struct nfs_server *server) | ||
4635 | { | ||
4636 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server); | ||
4637 | } | ||
4638 | |||
4527 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4639 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4528 | const struct nfs_server *server) | 4640 | const struct nfs_server *server) |
4529 | { | 4641 | { |
4530 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, server); | 4642 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, NULL, server); |
4531 | } | 4643 | } |
4532 | 4644 | ||
4533 | /* | 4645 | /* |
@@ -5919,7 +6031,7 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5919 | status = decode_getfh(xdr, res->fh); | 6031 | status = decode_getfh(xdr, res->fh); |
5920 | if (status) | 6032 | if (status) |
5921 | goto out; | 6033 | goto out; |
5922 | status = decode_getfattr(xdr, res->fattr, res->server); | 6034 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
5923 | out: | 6035 | out: |
5924 | return status; | 6036 | return status; |
5925 | } | 6037 | } |
@@ -5945,7 +6057,8 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, | |||
5945 | goto out; | 6057 | goto out; |
5946 | status = decode_getfh(xdr, res->fh); | 6058 | status = decode_getfh(xdr, res->fh); |
5947 | if (status == 0) | 6059 | if (status == 0) |
5948 | status = decode_getfattr(xdr, res->fattr, res->server); | 6060 | status = decode_getfattr_label(xdr, res->fattr, |
6061 | res->label, res->server); | ||
5949 | out: | 6062 | out: |
5950 | return status; | 6063 | return status; |
5951 | } | 6064 | } |
@@ -6036,7 +6149,7 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6036 | status = decode_restorefh(xdr); | 6149 | status = decode_restorefh(xdr); |
6037 | if (status) | 6150 | if (status) |
6038 | goto out; | 6151 | goto out; |
6039 | decode_getfattr(xdr, res->fattr, res->server); | 6152 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6040 | out: | 6153 | out: |
6041 | return status; | 6154 | return status; |
6042 | } | 6155 | } |
@@ -6065,7 +6178,7 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6065 | status = decode_getfh(xdr, res->fh); | 6178 | status = decode_getfh(xdr, res->fh); |
6066 | if (status) | 6179 | if (status) |
6067 | goto out; | 6180 | goto out; |
6068 | decode_getfattr(xdr, res->fattr, res->server); | 6181 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6069 | out: | 6182 | out: |
6070 | return status; | 6183 | return status; |
6071 | } | 6184 | } |
@@ -6097,7 +6210,7 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6097 | status = decode_putfh(xdr); | 6210 | status = decode_putfh(xdr); |
6098 | if (status) | 6211 | if (status) |
6099 | goto out; | 6212 | goto out; |
6100 | status = decode_getfattr(xdr, res->fattr, res->server); | 6213 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6101 | out: | 6214 | out: |
6102 | return status; | 6215 | return status; |
6103 | } | 6216 | } |
@@ -6230,7 +6343,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6230 | goto out; | 6343 | goto out; |
6231 | if (res->access_request) | 6344 | if (res->access_request) |
6232 | decode_access(xdr, &res->access_supported, &res->access_result); | 6345 | decode_access(xdr, &res->access_supported, &res->access_result); |
6233 | decode_getfattr(xdr, res->f_attr, res->server); | 6346 | decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server); |
6234 | out: | 6347 | out: |
6235 | return status; | 6348 | return status; |
6236 | } | 6349 | } |
@@ -6307,7 +6420,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, | |||
6307 | status = decode_setattr(xdr); | 6420 | status = decode_setattr(xdr); |
6308 | if (status) | 6421 | if (status) |
6309 | goto out; | 6422 | goto out; |
6310 | decode_getfattr(xdr, res->fattr, res->server); | 6423 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6311 | out: | 6424 | out: |
6312 | return status; | 6425 | return status; |
6313 | } | 6426 | } |
@@ -6696,7 +6809,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, | |||
6696 | xdr_enter_page(xdr, PAGE_SIZE); | 6809 | xdr_enter_page(xdr, PAGE_SIZE); |
6697 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, | 6810 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, |
6698 | NULL, res->fs_locations, | 6811 | NULL, res->fs_locations, |
6699 | res->fs_locations->server); | 6812 | NULL, res->fs_locations->server); |
6700 | out: | 6813 | out: |
6701 | return status; | 6814 | return status; |
6702 | } | 6815 | } |
@@ -7109,7 +7222,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7109 | goto out_overflow; | 7222 | goto out_overflow; |
7110 | 7223 | ||
7111 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 7224 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
7112 | NULL, entry->server) < 0) | 7225 | NULL, entry->label, entry->server) < 0) |
7113 | goto out_overflow; | 7226 | goto out_overflow; |
7114 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | 7227 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
7115 | entry->ino = entry->fattr->mounted_on_fileid; | 7228 | entry->ino = entry->fattr->mounted_on_fileid; |