On Fri, 2020-07-17 at 07:26 -0400, Jeff Layton wrote: > On Thu, 2020-07-16 at 10:05 -0400, xiubli@xxxxxxxxxx wrote: > > From: Xiubo Li <xiubli@xxxxxxxxxx> > > > > Will send the metric flags to MDS, currently it supports the cap, > > read latency, write latency and metadata latency. > > > > URL: https://tracker.ceph.com/issues/43435 > > Signed-off-by: Xiubo Li <xiubli@xxxxxxxxxx> > > --- > > fs/ceph/mds_client.c | 60 ++++++++++++++++++++++++++++++++++++++++++-- > > fs/ceph/metric.h | 13 ++++++++++ > > 2 files changed, 71 insertions(+), 2 deletions(-) > > > > diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c > > index cf4c2ba2311f..929778625ea5 100644 > > --- a/fs/ceph/mds_client.c > > +++ b/fs/ceph/mds_client.c > > @@ -1194,6 +1194,48 @@ static int encode_supported_features(void **p, void *end) > > return 0; > > } > > > > +static const unsigned char metric_bits[] = CEPHFS_METRIC_SPEC_CLIENT_SUPPORTED; > > +#define METRIC_BYTES(cnt) (DIV_ROUND_UP((size_t)metric_bits[cnt - 1] + 1, 64) * 8) > > +static int encode_metric_spec(void **p, void *end) > > +{ > > + static const size_t count = ARRAY_SIZE(metric_bits); > > + > > + /* header */ > > + if (WARN_ON_ONCE(*p + 2 > end)) > > + return -ERANGE; > > + > > + ceph_encode_8(p, 1); /* version */ > > + ceph_encode_8(p, 1); /* compat */ > > + > > + if (count > 0) { > > + size_t i; > > + size_t size = METRIC_BYTES(count); > > + > > + if (WARN_ON_ONCE(*p + 4 + 4 + size > end)) > > + return -ERANGE; > > + > > + /* metric spec info length */ > > + ceph_encode_32(p, 4 + size); > > + > > + /* metric spec */ > > + ceph_encode_32(p, size); > > + memset(*p, 0, size); > > + for (i = 0; i < count; i++) > > + ((unsigned char *)(*p))[i / 8] |= BIT(metric_bits[i] % 8); > > + *p += size; > > + } else { > > + if (WARN_ON_ONCE(*p + 4 + 4 > end)) > > + return -ERANGE; > > + > > + /* metric spec info length */ > > + ceph_encode_32(p, 4); > > + /* metric spec */ > > + ceph_encode_32(p, 0); > > + } > > + > > + return 0; > > +} > > + > > /* > > * session message, specialization for CEPH_SESSION_REQUEST_OPEN > > * to include additional client metadata fields. > > @@ -1234,6 +1276,13 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6 > > size = FEATURE_BYTES(count); > > extra_bytes += 4 + size; > > > > + /* metric spec */ > > + size = 0; > > + count = ARRAY_SIZE(metric_bits); > > + if (count > 0) > > + size = METRIC_BYTES(count); > > + extra_bytes += 2 + 4 + 4 + size; > > + > > /* Allocate the message */ > > msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes, > > GFP_NOFS, false); > > @@ -1252,9 +1301,9 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6 > > * Serialize client metadata into waiting buffer space, using > > * the format that userspace expects for map<string, string> > > * > > - * ClientSession messages with metadata are v3 > > + * ClientSession messages with metadata are v4 > > */ > > - msg->hdr.version = cpu_to_le16(3); > > + msg->hdr.version = cpu_to_le16(4); > > msg->hdr.compat_version = cpu_to_le16(1); > > > > /* 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 > > return ERR_PTR(ret); > > } > > > > + ret = encode_metric_spec(&p, end); > > + if (ret) { > > + pr_err("encode_metric_spec failed!\n"); > > + ceph_msg_put(msg); > > + return ERR_PTR(ret); > > + } > > + > > msg->front.iov_len = p - msg->front.iov_base; > > msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); > > > > diff --git a/fs/ceph/metric.h b/fs/ceph/metric.h > > index fe5d07d2e63a..1d0959d669d7 100644 > > --- a/fs/ceph/metric.h > > +++ b/fs/ceph/metric.h > > @@ -18,6 +18,19 @@ enum ceph_metric_type { > > CLIENT_METRIC_TYPE_MAX = CLIENT_METRIC_TYPE_DENTRY_LEASE, > > }; > > > > +/* > > + * This will always have the highest metric bit value > > + * as the last element of the array. > > + */ > > +#define CEPHFS_METRIC_SPEC_CLIENT_SUPPORTED { \ > > + CLIENT_METRIC_TYPE_CAP_INFO, \ > > + CLIENT_METRIC_TYPE_READ_LATENCY, \ > > + CLIENT_METRIC_TYPE_WRITE_LATENCY, \ > > + CLIENT_METRIC_TYPE_METADATA_LATENCY, \ > > + \ > > + CLIENT_METRIC_TYPE_MAX, \ > > Not a huge problem now, but shouldn't this last line be? > > CLIENT_METRIC_TYPE_MAX = CLIENT_METRIC_TYPE_METADATA_LATENCY, > > Disregard my earlier mail here. I read this as if you were adding another enum. This patch looks fine. > > +} > > + > > /* metric caps header */ > > struct ceph_metric_cap { > > __le32 type; /* ceph metric type */ -- Jeff Layton <jlayton@xxxxxxxxxx>