brintos

brintos / linux-shallow public Read only

0
0
Text · 7.9 KiB · 3f305e6 Raw
320 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * RDMA Transport Layer4 *5 * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved.6 * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved.7 * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved.8 */9#undef pr_fmt10#define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt11 12#include "rtrs-pri.h"13#include "rtrs-srv.h"14#include "rtrs-log.h"15 16static void rtrs_srv_release(struct kobject *kobj)17{18	struct rtrs_srv_path *srv_path;19 20	srv_path = container_of(kobj, struct rtrs_srv_path, kobj);21	kfree(srv_path);22}23 24static struct kobj_type ktype = {25	.sysfs_ops	= &kobj_sysfs_ops,26	.release	= rtrs_srv_release,27};28 29static ssize_t rtrs_srv_disconnect_show(struct kobject *kobj,30					struct kobj_attribute *attr, char *buf)31{32	return sysfs_emit(buf, "Usage: echo 1 > %s\n", attr->attr.name);33}34 35static ssize_t rtrs_srv_disconnect_store(struct kobject *kobj,36					  struct kobj_attribute *attr,37					  const char *buf, size_t count)38{39	struct rtrs_srv_path *srv_path;40	struct rtrs_path *s;41	char str[MAXHOSTNAMELEN];42 43	srv_path = container_of(kobj, struct rtrs_srv_path, kobj);44	s = &srv_path->s;45	if (!sysfs_streq(buf, "1")) {46		rtrs_err(s, "%s: invalid value: '%s'\n",47			  attr->attr.name, buf);48		return -EINVAL;49	}50 51	sockaddr_to_str((struct sockaddr *)&srv_path->s.dst_addr, str,52			sizeof(str));53 54	rtrs_info(s, "disconnect for path %s requested\n", str);55	/* first remove sysfs itself to avoid deadlock */56	sysfs_remove_file_self(&srv_path->kobj, &attr->attr);57	close_path(srv_path);58 59	return count;60}61 62static struct kobj_attribute rtrs_srv_disconnect_attr =63	__ATTR(disconnect, 0644,64	       rtrs_srv_disconnect_show, rtrs_srv_disconnect_store);65 66static ssize_t rtrs_srv_hca_port_show(struct kobject *kobj,67				       struct kobj_attribute *attr,68				       char *page)69{70	struct rtrs_srv_path *srv_path;71	struct rtrs_con *usr_con;72 73	srv_path = container_of(kobj, typeof(*srv_path), kobj);74	usr_con = srv_path->s.con[0];75 76	return sysfs_emit(page, "%u\n", usr_con->cm_id->port_num);77}78 79static struct kobj_attribute rtrs_srv_hca_port_attr =80	__ATTR(hca_port, 0444, rtrs_srv_hca_port_show, NULL);81 82static ssize_t rtrs_srv_hca_name_show(struct kobject *kobj,83				       struct kobj_attribute *attr,84				       char *page)85{86	struct rtrs_srv_path *srv_path;87 88	srv_path = container_of(kobj, struct rtrs_srv_path, kobj);89 90	return sysfs_emit(page, "%s\n", srv_path->s.dev->ib_dev->name);91}92 93static struct kobj_attribute rtrs_srv_hca_name_attr =94	__ATTR(hca_name, 0444, rtrs_srv_hca_name_show, NULL);95 96static ssize_t rtrs_srv_src_addr_show(struct kobject *kobj,97				       struct kobj_attribute *attr,98				       char *page)99{100	struct rtrs_srv_path *srv_path;101	int cnt;102 103	srv_path = container_of(kobj, struct rtrs_srv_path, kobj);104	cnt = sockaddr_to_str((struct sockaddr *)&srv_path->s.dst_addr,105			      page, PAGE_SIZE);106	return cnt + sysfs_emit_at(page, cnt, "\n");107}108 109static struct kobj_attribute rtrs_srv_src_addr_attr =110	__ATTR(src_addr, 0444, rtrs_srv_src_addr_show, NULL);111 112static ssize_t rtrs_srv_dst_addr_show(struct kobject *kobj,113				       struct kobj_attribute *attr,114				       char *page)115{116	struct rtrs_srv_path *srv_path;117	int len;118 119	srv_path = container_of(kobj, struct rtrs_srv_path, kobj);120	len = sockaddr_to_str((struct sockaddr *)&srv_path->s.src_addr, page,121			      PAGE_SIZE);122	len += sysfs_emit_at(page, len, "\n");123	return len;124}125 126static struct kobj_attribute rtrs_srv_dst_addr_attr =127	__ATTR(dst_addr, 0444, rtrs_srv_dst_addr_show, NULL);128 129static struct attribute *rtrs_srv_path_attrs[] = {130	&rtrs_srv_hca_name_attr.attr,131	&rtrs_srv_hca_port_attr.attr,132	&rtrs_srv_src_addr_attr.attr,133	&rtrs_srv_dst_addr_attr.attr,134	&rtrs_srv_disconnect_attr.attr,135	NULL,136};137 138static const struct attribute_group rtrs_srv_path_attr_group = {139	.attrs = rtrs_srv_path_attrs,140};141 142STAT_ATTR(struct rtrs_srv_stats, rdma,143	  rtrs_srv_stats_rdma_to_str,144	  rtrs_srv_reset_rdma_stats);145 146static struct attribute *rtrs_srv_stats_attrs[] = {147	&rdma_attr.attr,148	NULL,149};150 151static const struct attribute_group rtrs_srv_stats_attr_group = {152	.attrs = rtrs_srv_stats_attrs,153};154 155static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_path *srv_path)156{157	struct rtrs_srv_sess *srv = srv_path->srv;158	int err = 0;159 160	mutex_lock(&srv->paths_mutex);161	if (srv->dev_ref++) {162		/*163		 * Device needs to be registered only on the first session164		 */165		goto unlock;166	}167	srv->dev.class = &rtrs_dev_class;168	err = dev_set_name(&srv->dev, "%s", srv_path->s.sessname);169	if (err)170		goto unlock;171 172	/*173	 * Suppress user space notification until174	 * sysfs files are created175	 */176	dev_set_uevent_suppress(&srv->dev, true);177	err = device_add(&srv->dev);178	if (err) {179		pr_err("device_add(): %d\n", err);180		put_device(&srv->dev);181		goto unlock;182	}183	srv->kobj_paths = kobject_create_and_add("paths", &srv->dev.kobj);184	if (!srv->kobj_paths) {185		err = -ENOMEM;186		pr_err("kobject_create_and_add(): %d\n", err);187		device_del(&srv->dev);188		put_device(&srv->dev);189		goto unlock;190	}191	dev_set_uevent_suppress(&srv->dev, false);192	kobject_uevent(&srv->dev.kobj, KOBJ_ADD);193unlock:194	mutex_unlock(&srv->paths_mutex);195 196	return err;197}198 199static void200rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_path *srv_path)201{202	struct rtrs_srv_sess *srv = srv_path->srv;203 204	mutex_lock(&srv->paths_mutex);205	if (!--srv->dev_ref) {206		kobject_put(srv->kobj_paths);207		mutex_unlock(&srv->paths_mutex);208		device_del(&srv->dev);209		put_device(&srv->dev);210	} else {211		put_device(&srv->dev);212		mutex_unlock(&srv->paths_mutex);213	}214}215 216static void rtrs_srv_path_stats_release(struct kobject *kobj)217{218	struct rtrs_srv_stats *stats;219 220	stats = container_of(kobj, struct rtrs_srv_stats, kobj_stats);221 222	free_percpu(stats->rdma_stats);223 224	kfree(stats);225}226 227static struct kobj_type ktype_stats = {228	.sysfs_ops = &kobj_sysfs_ops,229	.release = rtrs_srv_path_stats_release,230};231 232static int rtrs_srv_create_stats_files(struct rtrs_srv_path *srv_path)233{234	int err;235	struct rtrs_path *s = &srv_path->s;236 237	err = kobject_init_and_add(&srv_path->stats->kobj_stats, &ktype_stats,238				   &srv_path->kobj, "stats");239	if (err) {240		rtrs_err(s, "kobject_init_and_add(): %d\n", err);241		kobject_put(&srv_path->stats->kobj_stats);242		return err;243	}244	err = sysfs_create_group(&srv_path->stats->kobj_stats,245				 &rtrs_srv_stats_attr_group);246	if (err) {247		rtrs_err(s, "sysfs_create_group(): %d\n", err);248		goto err;249	}250 251	return 0;252 253err:254	kobject_del(&srv_path->stats->kobj_stats);255	kobject_put(&srv_path->stats->kobj_stats);256 257	return err;258}259 260int rtrs_srv_create_path_files(struct rtrs_srv_path *srv_path)261{262	struct rtrs_srv_sess *srv = srv_path->srv;263	struct rtrs_path *s = &srv_path->s;264	char str[NAME_MAX];265	int err;266	struct rtrs_addr path = {267		.src = &srv_path->s.dst_addr,268		.dst = &srv_path->s.src_addr,269	};270 271	rtrs_addr_to_str(&path, str, sizeof(str));272	err = rtrs_srv_create_once_sysfs_root_folders(srv_path);273	if (err)274		return err;275 276	err = kobject_init_and_add(&srv_path->kobj, &ktype, srv->kobj_paths,277				   "%s", str);278	if (err) {279		rtrs_err(s, "kobject_init_and_add(): %d\n", err);280		goto destroy_root;281	}282	err = sysfs_create_group(&srv_path->kobj, &rtrs_srv_path_attr_group);283	if (err) {284		rtrs_err(s, "sysfs_create_group(): %d\n", err);285		goto put_kobj;286	}287	err = rtrs_srv_create_stats_files(srv_path);288	if (err)289		goto remove_group;290 291	return 0;292 293remove_group:294	sysfs_remove_group(&srv_path->kobj, &rtrs_srv_path_attr_group);295put_kobj:296	kobject_del(&srv_path->kobj);297destroy_root:298	kobject_put(&srv_path->kobj);299	rtrs_srv_destroy_once_sysfs_root_folders(srv_path);300 301	return err;302}303 304void rtrs_srv_destroy_path_files(struct rtrs_srv_path *srv_path)305{306	if (srv_path->stats->kobj_stats.state_in_sysfs) {307		sysfs_remove_group(&srv_path->stats->kobj_stats,308				   &rtrs_srv_stats_attr_group);309		kobject_del(&srv_path->stats->kobj_stats);310		kobject_put(&srv_path->stats->kobj_stats);311	}312 313	if (srv_path->kobj.state_in_sysfs) {314		sysfs_remove_group(&srv_path->kobj, &rtrs_srv_path_attr_group);315		kobject_put(&srv_path->kobj);316		rtrs_srv_destroy_once_sysfs_root_folders(srv_path);317	}318 319}320