RDMA/cm: Use an attribute_group on the ib_port_attribute intead of kobj's

This code is trying to attach a list of counters grouped into 4 groups to
the ib_port sysfs. Instead of creating a bunch of kobjects simply express
everything naturally as an ib_port_attribute and add a single
attribute_groups list.

Remove all the naked kobject manipulations.

Link: https://lore.kernel.org/r/0d5a7241ee0fe66622de04fcbaafaf6a791d5c7c.1623427137.git.leonro@nvidia.com
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Jason Gunthorpe 2021-06-11 19:00:29 +03:00
parent 054239f45c
commit 526a12c8c5
3 changed files with 118 additions and 165 deletions

View File

@ -25,6 +25,7 @@
#include <rdma/ib_cache.h>
#include <rdma/ib_cm.h>
#include <rdma/ib_sysfs.h>
#include "cm_msgs.h"
#include "core_priv.h"
#include "cm_trace.h"
@ -148,60 +149,17 @@ enum {
CM_COUNTER_GROUPS
};
static char const counter_group_names[CM_COUNTER_GROUPS]
[sizeof("cm_rx_duplicates")] = {
"cm_tx_msgs", "cm_tx_retries",
"cm_rx_msgs", "cm_rx_duplicates"
};
struct cm_counter_group {
struct kobject obj;
atomic_long_t counter[CM_ATTR_COUNT];
};
struct cm_counter_attribute {
struct attribute attr;
int index;
};
#define CM_COUNTER_ATTR(_name, _index) \
struct cm_counter_attribute cm_##_name##_counter_attr = { \
.attr = { .name = __stringify(_name), .mode = 0444 }, \
.index = _index \
}
static CM_COUNTER_ATTR(req, CM_REQ_COUNTER);
static CM_COUNTER_ATTR(mra, CM_MRA_COUNTER);
static CM_COUNTER_ATTR(rej, CM_REJ_COUNTER);
static CM_COUNTER_ATTR(rep, CM_REP_COUNTER);
static CM_COUNTER_ATTR(rtu, CM_RTU_COUNTER);
static CM_COUNTER_ATTR(dreq, CM_DREQ_COUNTER);
static CM_COUNTER_ATTR(drep, CM_DREP_COUNTER);
static CM_COUNTER_ATTR(sidr_req, CM_SIDR_REQ_COUNTER);
static CM_COUNTER_ATTR(sidr_rep, CM_SIDR_REP_COUNTER);
static CM_COUNTER_ATTR(lap, CM_LAP_COUNTER);
static CM_COUNTER_ATTR(apr, CM_APR_COUNTER);
static struct attribute *cm_counter_default_attrs[] = {
&cm_req_counter_attr.attr,
&cm_mra_counter_attr.attr,
&cm_rej_counter_attr.attr,
&cm_rep_counter_attr.attr,
&cm_rtu_counter_attr.attr,
&cm_dreq_counter_attr.attr,
&cm_drep_counter_attr.attr,
&cm_sidr_req_counter_attr.attr,
&cm_sidr_rep_counter_attr.attr,
&cm_lap_counter_attr.attr,
&cm_apr_counter_attr.attr,
NULL
struct ib_port_attribute attr;
unsigned short group;
unsigned short index;
};
struct cm_port {
struct cm_device *cm_dev;
struct ib_mad_agent *mad_agent;
u32 port_num;
struct cm_counter_group counter_group[CM_COUNTER_GROUPS];
atomic_long_t counters[CM_COUNTER_GROUPS][CM_ATTR_COUNT];
};
struct cm_device {
@ -1964,8 +1922,8 @@ static void cm_dup_req_handler(struct cm_work *work,
struct ib_mad_send_buf *msg = NULL;
int ret;
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_REQ_COUNTER]);
atomic_long_inc(
&work->port->counters[CM_RECV_DUPLICATES][CM_REQ_COUNTER]);
/* Quick state check to discard duplicate REQs. */
spin_lock_irq(&cm_id_priv->lock);
@ -2463,8 +2421,8 @@ static void cm_dup_rep_handler(struct cm_work *work)
if (!cm_id_priv)
return;
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_REP_COUNTER]);
atomic_long_inc(
&work->port->counters[CM_RECV_DUPLICATES][CM_REP_COUNTER]);
ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
if (ret)
goto deref;
@ -2641,8 +2599,8 @@ static int cm_rtu_handler(struct cm_work *work)
if (cm_id_priv->id.state != IB_CM_REP_SENT &&
cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
spin_unlock_irq(&cm_id_priv->lock);
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_RTU_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_RTU_COUNTER]);
goto out;
}
cm_id_priv->id.state = IB_CM_ESTABLISHED;
@ -2846,8 +2804,8 @@ static int cm_dreq_handler(struct cm_work *work)
cpu_to_be32(IBA_GET(CM_DREQ_REMOTE_COMM_ID, dreq_msg)),
cpu_to_be32(IBA_GET(CM_DREQ_LOCAL_COMM_ID, dreq_msg)));
if (!cm_id_priv) {
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_DREQ_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_DREQ_COUNTER]);
cm_issue_drep(work->port, work->mad_recv_wc);
trace_icm_no_priv_err(
IBA_GET(CM_DREQ_LOCAL_COMM_ID, dreq_msg),
@ -2876,8 +2834,8 @@ static int cm_dreq_handler(struct cm_work *work)
case IB_CM_MRA_REP_RCVD:
break;
case IB_CM_TIMEWAIT:
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_DREQ_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_DREQ_COUNTER]);
msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc);
if (IS_ERR(msg))
goto unlock;
@ -2892,8 +2850,8 @@ static int cm_dreq_handler(struct cm_work *work)
cm_free_response_msg(msg);
goto deref;
case IB_CM_DREQ_RCVD:
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_DREQ_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_DREQ_COUNTER]);
goto unlock;
default:
trace_icm_dreq_unknown_err(&cm_id_priv->id);
@ -3244,17 +3202,17 @@ static int cm_mra_handler(struct cm_work *work)
cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
ib_modify_mad(cm_id_priv->msg, timeout)) {
if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
atomic_long_inc(&work->port->
counter_group[CM_RECV_DUPLICATES].
counter[CM_MRA_COUNTER]);
atomic_long_inc(
&work->port->counters[CM_RECV_DUPLICATES]
[CM_MRA_COUNTER]);
goto out;
}
cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
break;
case IB_CM_MRA_REQ_RCVD:
case IB_CM_MRA_REP_RCVD:
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_MRA_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_MRA_COUNTER]);
fallthrough;
default:
trace_icm_mra_unknown_err(&cm_id_priv->id);
@ -3380,8 +3338,8 @@ static int cm_lap_handler(struct cm_work *work)
case IB_CM_LAP_IDLE:
break;
case IB_CM_MRA_LAP_SENT:
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_LAP_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_LAP_COUNTER]);
msg = cm_alloc_response_msg_no_ah(work->port, work->mad_recv_wc);
if (IS_ERR(msg))
goto unlock;
@ -3398,8 +3356,8 @@ static int cm_lap_handler(struct cm_work *work)
cm_free_response_msg(msg);
goto deref;
case IB_CM_LAP_RCVD:
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_LAP_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_LAP_COUNTER]);
goto unlock;
default:
goto unlock;
@ -3617,8 +3575,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
listen_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
if (listen_cm_id_priv) {
spin_unlock_irq(&cm.lock);
atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
counter[CM_SIDR_REQ_COUNTER]);
atomic_long_inc(&work->port->counters[CM_RECV_DUPLICATES]
[CM_SIDR_REQ_COUNTER]);
goto out; /* Duplicate message. */
}
cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
@ -3867,12 +3825,10 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
if (!cm_id_priv && (attr_index != CM_REJ_COUNTER))
msg->retries = 1;
atomic_long_add(1 + msg->retries,
&port->counter_group[CM_XMIT].counter[attr_index]);
atomic_long_add(1 + msg->retries, &port->counters[CM_XMIT][attr_index]);
if (msg->retries)
atomic_long_add(msg->retries,
&port->counter_group[CM_XMIT_RETRIES].
counter[attr_index]);
&port->counters[CM_XMIT_RETRIES][attr_index]);
if (cm_id_priv)
cm_process_send_error(cm_id_priv, msg, state,
@ -4093,8 +4049,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
}
attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id);
atomic_long_inc(&port->counter_group[CM_RECV].
counter[attr_id - CM_ATTR_ID_OFFSET]);
atomic_long_inc(&port->counters[CM_RECV][attr_id - CM_ATTR_ID_OFFSET]);
work = kmalloc(struct_size(work, path, paths), GFP_KERNEL);
if (!work) {
@ -4296,60 +4251,75 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_init_qp_attr);
static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,
char *buf)
static ssize_t cm_show_counter(struct ib_device *ibdev, u32 port_num,
struct ib_port_attribute *attr, char *buf)
{
struct cm_counter_group *group;
struct cm_counter_attribute *cm_attr;
struct cm_counter_attribute *cm_attr =
container_of(attr, struct cm_counter_attribute, attr);
struct cm_device *cm_dev = ib_get_client_data(ibdev, &cm_client);
group = container_of(obj, struct cm_counter_group, obj);
cm_attr = container_of(attr, struct cm_counter_attribute, attr);
if (WARN_ON(!cm_dev))
return -EINVAL;
return sysfs_emit(buf, "%ld\n",
atomic_long_read(&group->counter[cm_attr->index]));
return sysfs_emit(
buf, "%ld\n",
atomic_long_read(
&cm_dev->port[port_num - 1]
->counters[cm_attr->group][cm_attr->index]));
}
static const struct sysfs_ops cm_counter_ops = {
.show = cm_show_counter
#define CM_COUNTER_ATTR(_name, _group, _index) \
{ \
.attr = __ATTR(_name, 0444, cm_show_counter, NULL), \
.group = _group, .index = _index \
}
#define CM_COUNTER_GROUP(_group, _name) \
static struct cm_counter_attribute cm_counter_attr_##_group[] = { \
CM_COUNTER_ATTR(req, _group, CM_REQ_COUNTER), \
CM_COUNTER_ATTR(mra, _group, CM_MRA_COUNTER), \
CM_COUNTER_ATTR(rej, _group, CM_REJ_COUNTER), \
CM_COUNTER_ATTR(rep, _group, CM_REP_COUNTER), \
CM_COUNTER_ATTR(rtu, _group, CM_RTU_COUNTER), \
CM_COUNTER_ATTR(dreq, _group, CM_DREQ_COUNTER), \
CM_COUNTER_ATTR(drep, _group, CM_DREP_COUNTER), \
CM_COUNTER_ATTR(sidr_req, _group, CM_SIDR_REQ_COUNTER), \
CM_COUNTER_ATTR(sidr_rep, _group, CM_SIDR_REP_COUNTER), \
CM_COUNTER_ATTR(lap, _group, CM_LAP_COUNTER), \
CM_COUNTER_ATTR(apr, _group, CM_APR_COUNTER), \
}; \
static struct attribute *cm_counter_attrs_##_group[] = { \
&cm_counter_attr_##_group[0].attr.attr, \
&cm_counter_attr_##_group[1].attr.attr, \
&cm_counter_attr_##_group[2].attr.attr, \
&cm_counter_attr_##_group[3].attr.attr, \
&cm_counter_attr_##_group[4].attr.attr, \
&cm_counter_attr_##_group[5].attr.attr, \
&cm_counter_attr_##_group[6].attr.attr, \
&cm_counter_attr_##_group[7].attr.attr, \
&cm_counter_attr_##_group[8].attr.attr, \
&cm_counter_attr_##_group[9].attr.attr, \
&cm_counter_attr_##_group[10].attr.attr, \
NULL, \
}; \
static const struct attribute_group cm_counter_group_##_group = { \
.name = _name, \
.attrs = cm_counter_attrs_##_group, \
};
static struct kobj_type cm_counter_obj_type = {
.sysfs_ops = &cm_counter_ops,
.default_attrs = cm_counter_default_attrs
CM_COUNTER_GROUP(CM_XMIT, "cm_tx_msgs")
CM_COUNTER_GROUP(CM_XMIT_RETRIES, "cm_tx_retries")
CM_COUNTER_GROUP(CM_RECV, "cm_rx_msgs")
CM_COUNTER_GROUP(CM_RECV_DUPLICATES, "cm_rx_duplicates")
static const struct attribute_group *cm_counter_groups[] = {
&cm_counter_group_CM_XMIT,
&cm_counter_group_CM_XMIT_RETRIES,
&cm_counter_group_CM_RECV,
&cm_counter_group_CM_RECV_DUPLICATES,
NULL,
};
static int cm_create_port_fs(struct cm_port *port)
{
int i, ret;
for (i = 0; i < CM_COUNTER_GROUPS; i++) {
ret = ib_port_register_module_stat(port->cm_dev->ib_device,
port->port_num,
&port->counter_group[i].obj,
&cm_counter_obj_type,
counter_group_names[i]);
if (ret)
goto error;
}
return 0;
error:
while (i--)
ib_port_unregister_module_stat(&port->counter_group[i].obj);
return ret;
}
static void cm_remove_port_fs(struct cm_port *port)
{
int i;
for (i = 0; i < CM_COUNTER_GROUPS; i++)
ib_port_unregister_module_stat(&port->counter_group[i].obj);
}
static int cm_add_one(struct ib_device *ib_device)
{
struct cm_device *cm_dev;
@ -4377,6 +4347,8 @@ static int cm_add_one(struct ib_device *ib_device)
cm_dev->ack_delay = ib_device->attrs.local_ca_ack_delay;
cm_dev->going_down = 0;
ib_set_client_data(ib_device, &cm_client, cm_dev);
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
rdma_for_each_port (ib_device, i) {
if (!rdma_cap_ib_cm(ib_device, i))
@ -4392,7 +4364,8 @@ static int cm_add_one(struct ib_device *ib_device)
port->cm_dev = cm_dev;
port->port_num = i;
ret = cm_create_port_fs(port);
ret = ib_port_register_client_groups(ib_device, i,
cm_counter_groups);
if (ret)
goto error1;
@ -4421,8 +4394,6 @@ static int cm_add_one(struct ib_device *ib_device)
goto free;
}
ib_set_client_data(ib_device, &cm_client, cm_dev);
write_lock_irqsave(&cm.device_lock, flags);
list_add_tail(&cm_dev->list, &cm.device_list);
write_unlock_irqrestore(&cm.device_lock, flags);
@ -4431,7 +4402,7 @@ static int cm_add_one(struct ib_device *ib_device)
error3:
ib_unregister_mad_agent(port->mad_agent);
error2:
cm_remove_port_fs(port);
ib_port_unregister_client_groups(ib_device, i, cm_counter_groups);
error1:
port_modify.set_port_cap_mask = 0;
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
@ -4442,7 +4413,8 @@ error1:
port = cm_dev->port[i-1];
ib_modify_port(ib_device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
cm_remove_port_fs(port);
ib_port_unregister_client_groups(ib_device, i,
cm_counter_groups);
}
free:
cm_device_put(cm_dev);
@ -4490,7 +4462,8 @@ static void cm_remove_one(struct ib_device *ib_device, void *client_data)
port->mad_agent = NULL;
spin_unlock(&cm_dev->mad_agent_lock);
ib_unregister_mad_agent(mad_agent);
cm_remove_port_fs(port);
ib_port_unregister_client_groups(ib_device, i,
cm_counter_groups);
}
cm_device_put(cm_dev);

View File

@ -382,10 +382,10 @@ int ib_setup_device_attrs(struct ib_device *ibdev);
int rdma_compatdev_set(u8 enable);
int ib_port_register_module_stat(struct ib_device *device, u32 port_num,
struct kobject *kobj, struct kobj_type *ktype,
const char *name);
void ib_port_unregister_module_stat(struct kobject *kobj);
int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
int ib_device_set_netns_put(struct sk_buff *skb,
struct ib_device *dev, u32 ns_fd);

View File

@ -1448,46 +1448,26 @@ err_put:
}
/**
* ib_port_register_module_stat - add module counters under relevant port
* of IB device.
* ib_port_register_client_groups - Add an ib_client's attributes to the port
*
* @device: IB device to add counters
* @ibdev: IB device to add counters
* @port_num: valid port number
* @kobj: pointer to the kobject to initialize
* @ktype: pointer to the ktype for this kobject.
* @name: the name of the kobject
* @groups: Group list of attributes
*
* Do not use. Only for legacy sysfs compatibility.
*/
int ib_port_register_module_stat(struct ib_device *device, u32 port_num,
struct kobject *kobj, struct kobj_type *ktype,
const char *name)
int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups)
{
struct kobject *p, *t;
int ret;
list_for_each_entry_safe(p, t, &device->coredev.port_list, entry) {
struct ib_port *port = container_of(p, struct ib_port, kobj);
if (port->port_num != port_num)
continue;
ret = kobject_init_and_add(kobj, ktype, &port->kobj, "%s",
name);
if (ret) {
kobject_put(kobj);
return ret;
}
return sysfs_create_groups(&ibdev->port_data[port_num].sysfs->kobj,
groups);
}
EXPORT_SYMBOL(ib_port_register_client_groups);
return 0;
}
EXPORT_SYMBOL(ib_port_register_module_stat);
/**
* ib_port_unregister_module_stat - release module counters
* @kobj: pointer to the kobject to release
*/
void ib_port_unregister_module_stat(struct kobject *kobj)
void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups)
{
kobject_put(kobj);
return sysfs_remove_groups(&ibdev->port_data[port_num].sysfs->kobj,
groups);
}
EXPORT_SYMBOL(ib_port_unregister_module_stat);
EXPORT_SYMBOL(ib_port_unregister_client_groups);