Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 584482ac authored by Haggai Eran's avatar Haggai Eran Committed by Roland Dreier
Browse files

IB/core: Fix kobject leak on device register error flow



The ports kobject isn't being released during error flow in device
registration.  This patch refactors the ports kobject cleanup into a
single function called from both the error flow in device registration
and from the unregistration function.

A couple of attributes aren't being deleted (iw_stats_group, and
ib_class_attributes).  While this may be handled implicitly by the
destruction of their kobjects, it seems better to handle all the
attributes the same way.

Signed-off-by: default avatarHaggai Eran <haggaie@mellanox.com>

[ Make free_port_list_attributes() static.  - Roland ]

Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent cad6d02a
Loading
Loading
Loading
Loading
+26 −26
Original line number Diff line number Diff line
@@ -816,6 +816,22 @@ static struct attribute_group iw_stats_group = {
	.attrs	= iw_proto_stats_attrs,
};

static void free_port_list_attributes(struct ib_device *device)
{
	struct kobject *p, *t;

	list_for_each_entry_safe(p, t, &device->port_list, entry) {
		struct ib_port *port = container_of(p, struct ib_port, kobj);
		list_del(&p->entry);
		sysfs_remove_group(p, &pma_group);
		sysfs_remove_group(p, &port->pkey_group);
		sysfs_remove_group(p, &port->gid_group);
		kobject_put(p);
	}

	kobject_put(device->ports_parent);
}

int ib_device_register_sysfs(struct ib_device *device,
			     int (*port_callback)(struct ib_device *,
						  u8, struct kobject *))
@@ -869,19 +885,7 @@ int ib_device_register_sysfs(struct ib_device *device,
	return 0;

err_put:
	{
		struct kobject *p, *t;
		struct ib_port *port;

		list_for_each_entry_safe(p, t, &device->port_list, entry) {
			list_del(&p->entry);
			port = container_of(p, struct ib_port, kobj);
			sysfs_remove_group(p, &pma_group);
			sysfs_remove_group(p, &port->pkey_group);
			sysfs_remove_group(p, &port->gid_group);
			kobject_put(p);
		}
	}
	free_port_list_attributes(device);

err_unregister:
	device_unregister(class_dev);
@@ -892,22 +896,18 @@ err:

void ib_device_unregister_sysfs(struct ib_device *device)
{
	struct kobject *p, *t;
	struct ib_port *port;

	/* Hold kobject until ib_dealloc_device() */
	kobject_get(&device->dev.kobj);
	struct kobject *kobj_dev = kobject_get(&device->dev.kobj);
	int i;

	list_for_each_entry_safe(p, t, &device->port_list, entry) {
		list_del(&p->entry);
		port = container_of(p, struct ib_port, kobj);
		sysfs_remove_group(p, &pma_group);
		sysfs_remove_group(p, &port->pkey_group);
		sysfs_remove_group(p, &port->gid_group);
		kobject_put(p);
	}
	if (device->node_type == RDMA_NODE_RNIC && device->get_protocol_stats)
		sysfs_remove_group(kobj_dev, &iw_stats_group);

	free_port_list_attributes(device);

	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i)
		device_remove_file(&device->dev, ib_class_attributes[i]);

	kobject_put(device->ports_parent);
	device_unregister(&device->dev);
}