@@ -1194,6 +1194,48 @@ static int encode_supported_features(void **p, void *end)
11941194 return 0 ;
11951195}
11961196
1197+ static const unsigned char metric_bits [] = CEPHFS_METRIC_SPEC_CLIENT_SUPPORTED ;
1198+ #define METRIC_BYTES (cnt ) (DIV_ROUND_UP((size_t)metric_bits[cnt - 1] + 1, 64) * 8)
1199+ static int encode_metric_spec (void * * p , void * end )
1200+ {
1201+ static const size_t count = ARRAY_SIZE (metric_bits );
1202+
1203+ /* header */
1204+ if (WARN_ON_ONCE (* p + 2 > end ))
1205+ return - ERANGE ;
1206+
1207+ ceph_encode_8 (p , 1 ); /* version */
1208+ ceph_encode_8 (p , 1 ); /* compat */
1209+
1210+ if (count > 0 ) {
1211+ size_t i ;
1212+ size_t size = METRIC_BYTES (count );
1213+
1214+ if (WARN_ON_ONCE (* p + 4 + 4 + size > end ))
1215+ return - ERANGE ;
1216+
1217+ /* metric spec info length */
1218+ ceph_encode_32 (p , 4 + size );
1219+
1220+ /* metric spec */
1221+ ceph_encode_32 (p , size );
1222+ memset (* p , 0 , size );
1223+ for (i = 0 ; i < count ; i ++ )
1224+ ((unsigned char * )(* p ))[i / 8 ] |= BIT (metric_bits [i ] % 8 );
1225+ * p += size ;
1226+ } else {
1227+ if (WARN_ON_ONCE (* p + 4 + 4 > end ))
1228+ return - ERANGE ;
1229+
1230+ /* metric spec info length */
1231+ ceph_encode_32 (p , 4 );
1232+ /* metric spec */
1233+ ceph_encode_32 (p , 0 );
1234+ }
1235+
1236+ return 0 ;
1237+ }
1238+
11971239/*
11981240 * session message, specialization for CEPH_SESSION_REQUEST_OPEN
11991241 * to include additional client metadata fields.
@@ -1234,6 +1276,13 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
12341276 size = FEATURE_BYTES (count );
12351277 extra_bytes += 4 + size ;
12361278
1279+ /* metric spec */
1280+ size = 0 ;
1281+ count = ARRAY_SIZE (metric_bits );
1282+ if (count > 0 )
1283+ size = METRIC_BYTES (count );
1284+ extra_bytes += 2 + 4 + 4 + size ;
1285+
12371286 /* Allocate the message */
12381287 msg = ceph_msg_new (CEPH_MSG_CLIENT_SESSION , sizeof (* h ) + extra_bytes ,
12391288 GFP_NOFS , false);
@@ -1252,9 +1301,9 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
12521301 * Serialize client metadata into waiting buffer space, using
12531302 * the format that userspace expects for map<string, string>
12541303 *
1255- * ClientSession messages with metadata are v3
1304+ * ClientSession messages with metadata are v4
12561305 */
1257- msg -> hdr .version = cpu_to_le16 (3 );
1306+ msg -> hdr .version = cpu_to_le16 (4 );
12581307 msg -> hdr .compat_version = cpu_to_le16 (1 );
12591308
12601309 /* The write pointer, following the session_head structure */
@@ -1283,6 +1332,13 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
12831332 return ERR_PTR (ret );
12841333 }
12851334
1335+ ret = encode_metric_spec (& p , end );
1336+ if (ret ) {
1337+ pr_err ("encode_metric_spec failed!\n" );
1338+ ceph_msg_put (msg );
1339+ return ERR_PTR (ret );
1340+ }
1341+
12861342 msg -> front .iov_len = p - msg -> front .iov_base ;
12871343 msg -> hdr .front_len = cpu_to_le32 (msg -> front .iov_len );
12881344
0 commit comments