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