aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-07-17 17:09:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-07-23 18:18:53 -0400
commitd7067b2db78aab1a76f9c443b1fcf81c3e35dd50 (patch)
tree8fe1427b57d4d605e812d30c6ebb052cdaeb6185 /fs/nfs/nfs4xdr.c
parent7c6d4dca777d6423cb9ccdc019cad94c75adcbe4 (diff)
NFSv4: encode_attrs should not backfill the bitmap and attribute length
The attribute length is already calculated in advance. There is no reason why we cannot calculate the bitmap in advance too so that we don't have to play pointer games. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c125
1 files changed, 53 insertions, 72 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 3850b018815f..1a4a3bd415ed 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -997,12 +997,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
997 int owner_namelen = 0; 997 int owner_namelen = 0;
998 int owner_grouplen = 0; 998 int owner_grouplen = 0;
999 __be32 *p; 999 __be32 *p;
1000 __be32 *q; 1000 unsigned i;
1001 int len; 1001 uint32_t len = 0;
1002 uint32_t bmval_len = 2; 1002 uint32_t bmval_len;
1003 uint32_t bmval0 = 0; 1003 uint32_t bmval[3] = { 0 };
1004 uint32_t bmval1 = 0;
1005 uint32_t bmval2 = 0;
1006 1004
1007 /* 1005 /*
1008 * We reserve enough space to write the entire attribute buffer at once. 1006 * We reserve enough space to write the entire attribute buffer at once.
@@ -1011,13 +1009,14 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1011 * = 40 bytes, plus any contribution from variable-length fields 1009 * = 40 bytes, plus any contribution from variable-length fields
1012 * such as owner/group. 1010 * such as owner/group.
1013 */ 1011 */
1014 len = 8; 1012 if (iap->ia_valid & ATTR_SIZE) {
1015 1013 bmval[0] |= FATTR4_WORD0_SIZE;
1016 /* Sigh */
1017 if (iap->ia_valid & ATTR_SIZE)
1018 len += 8; 1014 len += 8;
1019 if (iap->ia_valid & ATTR_MODE) 1015 }
1016 if (iap->ia_valid & ATTR_MODE) {
1017 bmval[1] |= FATTR4_WORD1_MODE;
1020 len += 4; 1018 len += 4;
1019 }
1021 if (iap->ia_valid & ATTR_UID) { 1020 if (iap->ia_valid & ATTR_UID) {
1022 owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ); 1021 owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
1023 if (owner_namelen < 0) { 1022 if (owner_namelen < 0) {
@@ -1028,6 +1027,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1028 owner_namelen = sizeof("nobody") - 1; 1027 owner_namelen = sizeof("nobody") - 1;
1029 /* goto out; */ 1028 /* goto out; */
1030 } 1029 }
1030 bmval[1] |= FATTR4_WORD1_OWNER;
1031 len += 4 + (XDR_QUADLEN(owner_namelen) << 2); 1031 len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
1032 } 1032 }
1033 if (iap->ia_valid & ATTR_GID) { 1033 if (iap->ia_valid & ATTR_GID) {
@@ -1039,92 +1039,73 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1039 owner_grouplen = sizeof("nobody") - 1; 1039 owner_grouplen = sizeof("nobody") - 1;
1040 /* goto out; */ 1040 /* goto out; */
1041 } 1041 }
1042 bmval[1] |= FATTR4_WORD1_OWNER_GROUP;
1042 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); 1043 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
1043 } 1044 }
1044 if (iap->ia_valid & ATTR_ATIME_SET) 1045 if (iap->ia_valid & ATTR_ATIME_SET) {
1046 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1045 len += 16; 1047 len += 16;
1046 else if (iap->ia_valid & ATTR_ATIME) 1048 } else if (iap->ia_valid & ATTR_ATIME) {
1049 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1047 len += 4; 1050 len += 4;
1048 if (iap->ia_valid & ATTR_MTIME_SET) 1051 }
1052 if (iap->ia_valid & ATTR_MTIME_SET) {
1053 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1049 len += 16; 1054 len += 16;
1050 else if (iap->ia_valid & ATTR_MTIME) 1055 } else if (iap->ia_valid & ATTR_MTIME) {
1056 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1051 len += 4; 1057 len += 4;
1058 }
1052 if (label) { 1059 if (label) {
1053 len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); 1060 len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
1054 bmval_len = 3; 1061 bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
1055 } 1062 }
1056 1063
1057 len += bmval_len << 2; 1064 if (bmval[2] != 0)
1058 p = reserve_space(xdr, len); 1065 bmval_len = 3;
1066 else if (bmval[1] != 0)
1067 bmval_len = 2;
1068 else
1069 bmval_len = 1;
1070
1071 p = reserve_space(xdr, 4 + (bmval_len << 2) + 4 + len);
1059 1072
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); 1073 *p++ = cpu_to_be32(bmval_len);
1065 q = p; 1074 for (i = 0; i < bmval_len; i++)
1066 /* Skip bitmap entries + attrlen */ 1075 *p++ = cpu_to_be32(bmval[i]);
1067 p += bmval_len + 1; 1076 *p++ = cpu_to_be32(len);
1068 1077
1069 if (iap->ia_valid & ATTR_SIZE) { 1078 if (bmval[0] & FATTR4_WORD0_SIZE)
1070 bmval0 |= FATTR4_WORD0_SIZE;
1071 p = xdr_encode_hyper(p, iap->ia_size); 1079 p = xdr_encode_hyper(p, iap->ia_size);
1072 } 1080 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); 1081 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
1076 } 1082 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); 1083 p = xdr_encode_opaque(p, owner_name, owner_namelen);
1080 } 1084 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); 1085 p = xdr_encode_opaque(p, owner_group, owner_grouplen);
1086 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
1087 if (iap->ia_valid & ATTR_ATIME_SET) {
1088 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1089 p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec);
1090 *p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
1091 } else
1092 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1084 } 1093 }
1085 if (iap->ia_valid & ATTR_ATIME_SET) { 1094 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
1086 bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; 1095 if (iap->ia_valid & ATTR_MTIME_SET) {
1087 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME); 1096 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1088 p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec); 1097 p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
1089 *p++ = cpu_to_be32(iap->ia_atime.tv_nsec); 1098 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
1090 } 1099 } else
1091 else if (iap->ia_valid & ATTR_ATIME) { 1100 *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 } 1101 }
1105 if (label) { 1102 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
1106 bmval2 |= FATTR4_WORD2_SECURITY_LABEL;
1107 *p++ = cpu_to_be32(label->lfs); 1103 *p++ = cpu_to_be32(label->lfs);
1108 *p++ = cpu_to_be32(label->pi); 1104 *p++ = cpu_to_be32(label->pi);
1109 *p++ = cpu_to_be32(label->len); 1105 *p++ = cpu_to_be32(label->len);
1110 p = xdr_encode_opaque_fixed(p, label->label, label->len); 1106 p = xdr_encode_opaque_fixed(p, label->label, label->len);
1111 } 1107 }
1112 1108
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: */ 1109/* out: */
1129} 1110}
1130 1111