aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c214
1 files changed, 124 insertions, 90 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 3850b018815f..fbdad9e1719f 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -294,7 +294,9 @@ static int nfs4_stat_to_errno(int);
294 XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \ 294 XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \
295 1 /* flags */ + \ 295 1 /* flags */ + \
296 1 /* spa_how */ + \ 296 1 /* spa_how */ + \
297 0 /* SP4_NONE (for now) */ + \ 297 /* max is SP4_MACH_CRED (for now) */ + \
298 1 + NFS4_OP_MAP_NUM_WORDS + \
299 1 + NFS4_OP_MAP_NUM_WORDS + \
298 1 /* implementation id array of size 1 */ + \ 300 1 /* implementation id array of size 1 */ + \
299 1 /* nii_domain */ + \ 301 1 /* nii_domain */ + \
300 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \ 302 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
@@ -306,7 +308,9 @@ static int nfs4_stat_to_errno(int);
306 1 /* eir_sequenceid */ + \ 308 1 /* eir_sequenceid */ + \
307 1 /* eir_flags */ + \ 309 1 /* eir_flags */ + \
308 1 /* spr_how */ + \ 310 1 /* spr_how */ + \
309 0 /* SP4_NONE (for now) */ + \ 311 /* max is SP4_MACH_CRED (for now) */ + \
312 1 + NFS4_OP_MAP_NUM_WORDS + \
313 1 + NFS4_OP_MAP_NUM_WORDS + \
310 2 /* eir_server_owner.so_minor_id */ + \ 314 2 /* eir_server_owner.so_minor_id */ + \
311 /* eir_server_owner.so_major_id<> */ \ 315 /* eir_server_owner.so_major_id<> */ \
312 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \ 316 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
@@ -997,12 +1001,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
997 int owner_namelen = 0; 1001 int owner_namelen = 0;
998 int owner_grouplen = 0; 1002 int owner_grouplen = 0;
999 __be32 *p; 1003 __be32 *p;
1000 __be32 *q; 1004 unsigned i;
1001 int len; 1005 uint32_t len = 0;
1002 uint32_t bmval_len = 2; 1006 uint32_t bmval_len;
1003 uint32_t bmval0 = 0; 1007 uint32_t bmval[3] = { 0 };
1004 uint32_t bmval1 = 0;
1005 uint32_t bmval2 = 0;
1006 1008
1007 /* 1009 /*
1008 * We reserve enough space to write the entire attribute buffer at once. 1010 * We reserve enough space to write the entire attribute buffer at once.
@@ -1011,13 +1013,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1011 * = 40 bytes, plus any contribution from variable-length fields 1013 * = 40 bytes, plus any contribution from variable-length fields
1012 * such as owner/group. 1014 * such as owner/group.
1013 */ 1015 */
1014 len = 8; 1016 if (iap->ia_valid & ATTR_SIZE) {
1015 1017 bmval[0] |= FATTR4_WORD0_SIZE;
1016 /* Sigh */
1017 if (iap->ia_valid & ATTR_SIZE)
1018 len += 8; 1018 len += 8;
1019 if (iap->ia_valid & ATTR_MODE) 1019 }
1020 if (iap->ia_valid & ATTR_MODE) {
1021 bmval[1] |= FATTR4_WORD1_MODE;
1020 len += 4; 1022 len += 4;
1023 }
1021 if (iap->ia_valid & ATTR_UID) { 1024 if (iap->ia_valid & ATTR_UID) {
1022 owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); 1025 owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
1023 if (owner_namelen < 0) { 1026 if (owner_namelen < 0) {
@@ -1028,6 +1031,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1028 owner_namelen = sizeof("nobody") - 1; 1031 owner_namelen = sizeof("nobody") - 1;
1029 /* goto out; */ 1032 /* goto out; */
1030 } 1033 }
1034 bmval[1] |= FATTR4_WORD1_OWNER;
1031 len += 4 + (XDR_QUADLEN(owner_namelen) << 2); 1035 len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
1032 } 1036 }
1033 if (iap->ia_valid & ATTR_GID) { 1037 if (iap->ia_valid & ATTR_GID) {
@@ -1039,92 +1043,73 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1039 owner_grouplen = sizeof("nobody") - 1; 1043 owner_grouplen = sizeof("nobody") - 1;
1040 /* goto out; */ 1044 /* goto out; */
1041 } 1045 }
1046 bmval[1] |= FATTR4_WORD1_OWNER_GROUP;
1042 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); 1047 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
1043 } 1048 }
1044 if (iap->ia_valid & ATTR_ATIME_SET) 1049 if (iap->ia_valid & ATTR_ATIME_SET) {
1050 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1045 len += 16; 1051 len += 16;
1046 else if (iap->ia_valid & ATTR_ATIME) 1052 } else if (iap->ia_valid & ATTR_ATIME) {
1053 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1047 len += 4; 1054 len += 4;
1048 if (iap->ia_valid & ATTR_MTIME_SET) 1055 }
1056 if (iap->ia_valid & ATTR_MTIME_SET) {
1057 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1049 len += 16; 1058 len += 16;
1050 else if (iap->ia_valid & ATTR_MTIME) 1059 } else if (iap->ia_valid & ATTR_MTIME) {
1060 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1051 len += 4; 1061 len += 4;
1062 }
1052 if (label) { 1063 if (label) {
1053 len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); 1064 len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
1054 bmval_len = 3; 1065 bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
1055 } 1066 }
1056 1067
1057 len += bmval_len << 2; 1068 if (bmval[2] != 0)
1058 p = reserve_space(xdr, len); 1069 bmval_len = 3;
1070 else if (bmval[1] != 0)
1071 bmval_len = 2;
1072 else
1073 bmval_len = 1;
1074
1075 p = reserve_space(xdr, 4 + (bmval_len << 2) + 4 + len);
1059 1076
1060 /*
1061 * We write the bitmap length now, but leave the bitmap and the attribute
1062 * buffer length to be backfilled at the end of this routine.
1063 */
1064 *p++ = cpu_to_be32(bmval_len); 1077 *p++ = cpu_to_be32(bmval_len);
1065 q = p; 1078 for (i = 0; i < bmval_len; i++)
1066 /* Skip bitmap entries + attrlen */ 1079 *p++ = cpu_to_be32(bmval[i]);
1067 p += bmval_len + 1; 1080 *p++ = cpu_to_be32(len);
1068 1081
1069 if (iap->ia_valid & ATTR_SIZE) { 1082 if (bmval[0] & FATTR4_WORD0_SIZE)
1070 bmval0 |= FATTR4_WORD0_SIZE;
1071 p = xdr_encode_hyper(p, iap->ia_size); 1083 p = xdr_encode_hyper(p, iap->ia_size);
1072 } 1084 if (bmval[1] & FATTR4_WORD1_MODE)
1073 if (iap->ia_valid & ATTR_MODE) {
1074 bmval1 |= FATTR4_WORD1_MODE;
1075 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO); 1085 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
1076 } 1086 if (bmval[1] & FATTR4_WORD1_OWNER)
1077 if (iap->ia_valid & ATTR_UID) {
1078 bmval1 |= FATTR4_WORD1_OWNER;
1079 p = xdr_encode_opaque(p, owner_name, owner_namelen); 1087 p = xdr_encode_opaque(p, owner_name, owner_namelen);
1080 } 1088 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP)
1081 if (iap->ia_valid & ATTR_GID) {
1082 bmval1 |= FATTR4_WORD1_OWNER_GROUP;
1083 p = xdr_encode_opaque(p, owner_group, owner_grouplen); 1089 p = xdr_encode_opaque(p, owner_group, owner_grouplen);
1090 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
1091 if (iap->ia_valid & ATTR_ATIME_SET) {
1092 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1093 p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec);
1094 *p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
1095 } else
1096 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1084 } 1097 }
1085 if (iap->ia_valid & ATTR_ATIME_SET) { 1098 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
1086 bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; 1099 if (iap->ia_valid & ATTR_MTIME_SET) {
1087 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1100 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1088 p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec); 1101 p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
1089 *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); 1102 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
1090 } 1103 } else
1091 else if (iap->ia_valid & ATTR_ATIME) { 1104 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1092 bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
1093 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1094 }
1095 if (iap->ia_valid & ATTR_MTIME_SET) {
1096 bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
1097 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1098 p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
1099 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
1100 }
1101 else if (iap->ia_valid & ATTR_MTIME) {
1102 bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
1103 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1104 } 1105 }
1105 if (label) { 1106 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
1106 bmval2 |= FATTR4_WORD2_SECURITY_LABEL;
1107 *p++ = cpu_to_be32(label->lfs); 1107 *p++ = cpu_to_be32(label->lfs);
1108 *p++ = cpu_to_be32(label->pi); 1108 *p++ = cpu_to_be32(label->pi);
1109 *p++ = cpu_to_be32(label->len); 1109 *p++ = cpu_to_be32(label->len);
1110 p = xdr_encode_opaque_fixed(p, label->label, label->len); 1110 p = xdr_encode_opaque_fixed(p, label->label, label->len);
1111 } 1111 }
1112 1112
1113 /*
1114 * Now we backfill the bitmap and the attribute buffer length.
1115 */
1116 if (len != ((char *)p - (char *)q) + 4) {
1117 printk(KERN_ERR "NFS: Attr length error, %u != %Zu\n",
1118 len, ((char *)p - (char *)q) + 4);
1119 BUG();
1120 }
1121 *q++ = htonl(bmval0);
1122 *q++ = htonl(bmval1);
1123 if (bmval_len == 3)
1124 *q++ = htonl(bmval2);
1125 len = (char *)p - (char *)(q + 1);
1126 *q = htonl(len);
1127
1128/* out: */ 1113/* out: */
1129} 1114}
1130 1115
@@ -1745,6 +1730,14 @@ static void encode_bind_conn_to_session(struct xdr_stream *xdr,
1745 *p = 0; /* use_conn_in_rdma_mode = False */ 1730 *p = 0; /* use_conn_in_rdma_mode = False */
1746} 1731}
1747 1732
1733static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
1734{
1735 unsigned int i;
1736 encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS);
1737 for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++)
1738 encode_uint32(xdr, op_map->u.words[i]);
1739}
1740
1748static void encode_exchange_id(struct xdr_stream *xdr, 1741static void encode_exchange_id(struct xdr_stream *xdr,
1749 struct nfs41_exchange_id_args *args, 1742 struct nfs41_exchange_id_args *args,
1750 struct compound_hdr *hdr) 1743 struct compound_hdr *hdr)
@@ -1758,9 +1751,20 @@ static void encode_exchange_id(struct xdr_stream *xdr,
1758 1751
1759 encode_string(xdr, args->id_len, args->id); 1752 encode_string(xdr, args->id_len, args->id);
1760 1753
1761 p = reserve_space(xdr, 12); 1754 encode_uint32(xdr, args->flags);
1762 *p++ = cpu_to_be32(args->flags); 1755 encode_uint32(xdr, args->state_protect.how);
1763 *p++ = cpu_to_be32(0); /* zero length state_protect4_a */ 1756
1757 switch (args->state_protect.how) {
1758 case SP4_NONE:
1759 break;
1760 case SP4_MACH_CRED:
1761 encode_op_map(xdr, &args->state_protect.enforce);
1762 encode_op_map(xdr, &args->state_protect.allow);
1763 break;
1764 default:
1765 WARN_ON_ONCE(1);
1766 break;
1767 }
1764 1768
1765 if (send_implementation_id && 1769 if (send_implementation_id &&
1766 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 && 1770 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
@@ -1771,7 +1775,7 @@ static void encode_exchange_id(struct xdr_stream *xdr,
1771 utsname()->version, utsname()->machine); 1775 utsname()->version, utsname()->machine);
1772 1776
1773 if (len > 0) { 1777 if (len > 0) {
1774 *p = cpu_to_be32(1); /* implementation id array length=1 */ 1778 encode_uint32(xdr, 1); /* implementation id array length=1 */
1775 1779
1776 encode_string(xdr, 1780 encode_string(xdr,
1777 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1, 1781 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1,
@@ -1782,7 +1786,7 @@ static void encode_exchange_id(struct xdr_stream *xdr,
1782 p = xdr_encode_hyper(p, 0); 1786 p = xdr_encode_hyper(p, 0);
1783 *p = cpu_to_be32(0); 1787 *p = cpu_to_be32(0);
1784 } else 1788 } else
1785 *p = cpu_to_be32(0); /* implementation id array length=0 */ 1789 encode_uint32(xdr, 0); /* implementation id array length=0 */
1786} 1790}
1787 1791
1788static void encode_create_session(struct xdr_stream *xdr, 1792static void encode_create_session(struct xdr_stream *xdr,
@@ -1835,7 +1839,7 @@ static void encode_create_session(struct xdr_stream *xdr,
1835 *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */ 1839 *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */
1836 1840
1837 /* authsys_parms rfc1831 */ 1841 /* authsys_parms rfc1831 */
1838 *p++ = (__be32)nn->boot_time.tv_nsec; /* stamp */ 1842 *p++ = cpu_to_be32(nn->boot_time.tv_nsec); /* stamp */
1839 p = xdr_encode_opaque(p, machine_name, len); 1843 p = xdr_encode_opaque(p, machine_name, len);
1840 *p++ = cpu_to_be32(0); /* UID */ 1844 *p++ = cpu_to_be32(0); /* UID */
1841 *p++ = cpu_to_be32(0); /* GID */ 1845 *p++ = cpu_to_be32(0); /* GID */
@@ -1877,11 +1881,10 @@ static void encode_sequence(struct xdr_stream *xdr,
1877 struct nfs4_slot *slot = args->sa_slot; 1881 struct nfs4_slot *slot = args->sa_slot;
1878 __be32 *p; 1882 __be32 *p;
1879 1883
1880 if (slot == NULL)
1881 return;
1882
1883 tp = slot->table; 1884 tp = slot->table;
1884 session = tp->session; 1885 session = tp->session;
1886 if (!session)
1887 return;
1885 1888
1886 encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr); 1889 encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr);
1887 1890
@@ -2062,9 +2065,9 @@ static void encode_free_stateid(struct xdr_stream *xdr,
2062static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) 2065static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
2063{ 2066{
2064#if defined(CONFIG_NFS_V4_1) 2067#if defined(CONFIG_NFS_V4_1)
2065 2068 struct nfs4_session *session = args->sa_slot->table->session;
2066 if (args->sa_slot) 2069 if (session)
2067 return args->sa_slot->table->session->clp->cl_mvops->minor_version; 2070 return session->clp->cl_mvops->minor_version;
2068#endif /* CONFIG_NFS_V4_1 */ 2071#endif /* CONFIG_NFS_V4_1 */
2069 return 0; 2072 return 0;
2070} 2073}
@@ -4649,7 +4652,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
4649static int decode_first_pnfs_layout_type(struct xdr_stream *xdr, 4652static int decode_first_pnfs_layout_type(struct xdr_stream *xdr,
4650 uint32_t *layouttype) 4653 uint32_t *layouttype)
4651{ 4654{
4652 uint32_t *p; 4655 __be32 *p;
4653 int num; 4656 int num;
4654 4657
4655 p = xdr_inline_decode(xdr, 4); 4658 p = xdr_inline_decode(xdr, 4);
@@ -5394,6 +5397,23 @@ static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_re
5394 return decode_secinfo_common(xdr, res); 5397 return decode_secinfo_common(xdr, res);
5395} 5398}
5396 5399
5400static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
5401{
5402 __be32 *p;
5403 uint32_t bitmap_words;
5404 unsigned int i;
5405
5406 p = xdr_inline_decode(xdr, 4);
5407 bitmap_words = be32_to_cpup(p++);
5408 if (bitmap_words > NFS4_OP_MAP_NUM_WORDS)
5409 return -EIO;
5410 p = xdr_inline_decode(xdr, 4 * bitmap_words);
5411 for (i = 0; i < bitmap_words; i++)
5412 op_map->u.words[i] = be32_to_cpup(p++);
5413
5414 return 0;
5415}
5416
5397static int decode_exchange_id(struct xdr_stream *xdr, 5417static int decode_exchange_id(struct xdr_stream *xdr,
5398 struct nfs41_exchange_id_res *res) 5418 struct nfs41_exchange_id_res *res)
5399{ 5419{
@@ -5417,10 +5437,22 @@ static int decode_exchange_id(struct xdr_stream *xdr,
5417 res->seqid = be32_to_cpup(p++); 5437 res->seqid = be32_to_cpup(p++);
5418 res->flags = be32_to_cpup(p++); 5438 res->flags = be32_to_cpup(p++);
5419 5439
5420 /* We ask for SP4_NONE */ 5440 res->state_protect.how = be32_to_cpup(p);
5421 dummy = be32_to_cpup(p); 5441 switch (res->state_protect.how) {
5422 if (dummy != SP4_NONE) 5442 case SP4_NONE:
5443 break;
5444 case SP4_MACH_CRED:
5445 status = decode_op_map(xdr, &res->state_protect.enforce);
5446 if (status)
5447 return status;
5448 status = decode_op_map(xdr, &res->state_protect.allow);
5449 if (status)
5450 return status;
5451 break;
5452 default:
5453 WARN_ON_ONCE(1);
5423 return -EIO; 5454 return -EIO;
5455 }
5424 5456
5425 /* server_owner4.so_minor_id */ 5457 /* server_owner4.so_minor_id */
5426 p = xdr_inline_decode(xdr, 8); 5458 p = xdr_inline_decode(xdr, 8);
@@ -5614,6 +5646,8 @@ static int decode_sequence(struct xdr_stream *xdr,
5614 5646
5615 if (res->sr_slot == NULL) 5647 if (res->sr_slot == NULL)
5616 return 0; 5648 return 0;
5649 if (!res->sr_slot->table->session)
5650 return 0;
5617 5651
5618 status = decode_op_hdr(xdr, OP_SEQUENCE); 5652 status = decode_op_hdr(xdr, OP_SEQUENCE);
5619 if (!status) 5653 if (!status)