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 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 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 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 close_sess(sess); 57 58 return count; 59 } 60 61 static struct kobj_attribute rtrs_srv_disconnect_attr = 62 __ATTR(disconnect, 0644, 63 rtrs_srv_disconnect_show, rtrs_srv_disconnect_store); 64 65 static ssize_t rtrs_srv_hca_port_show(struct kobject *kobj, 66 struct kobj_attribute *attr, 67 char *page) 68 { 69 struct rtrs_srv_sess *sess; 70 struct rtrs_con *usr_con; 71 72 sess = container_of(kobj, typeof(*sess), kobj); 73 usr_con = sess->s.con[0]; 74 75 return scnprintf(page, PAGE_SIZE, "%u\n", 76 usr_con->cm_id->port_num); 77 } 78 79 static struct kobj_attribute rtrs_srv_hca_port_attr = 80 __ATTR(hca_port, 0444, rtrs_srv_hca_port_show, NULL); 81 82 static ssize_t rtrs_srv_hca_name_show(struct kobject *kobj, 83 struct kobj_attribute *attr, 84 char *page) 85 { 86 struct rtrs_srv_sess *sess; 87 88 sess = container_of(kobj, struct rtrs_srv_sess, kobj); 89 90 return scnprintf(page, PAGE_SIZE, "%s\n", 91 sess->s.dev->ib_dev->name); 92 } 93 94 static struct kobj_attribute rtrs_srv_hca_name_attr = 95 __ATTR(hca_name, 0444, rtrs_srv_hca_name_show, NULL); 96 97 static ssize_t rtrs_srv_src_addr_show(struct kobject *kobj, 98 struct kobj_attribute *attr, 99 char *page) 100 { 101 struct rtrs_srv_sess *sess; 102 int cnt; 103 104 sess = container_of(kobj, struct rtrs_srv_sess, kobj); 105 cnt = sockaddr_to_str((struct sockaddr *)&sess->s.dst_addr, 106 page, PAGE_SIZE); 107 return cnt + scnprintf(page + cnt, PAGE_SIZE - cnt, "\n"); 108 } 109 110 static struct kobj_attribute rtrs_srv_src_addr_attr = 111 __ATTR(src_addr, 0444, rtrs_srv_src_addr_show, NULL); 112 113 static ssize_t rtrs_srv_dst_addr_show(struct kobject *kobj, 114 struct kobj_attribute *attr, 115 char *page) 116 { 117 struct rtrs_srv_sess *sess; 118 int cnt; 119 120 sess = container_of(kobj, struct rtrs_srv_sess, kobj); 121 cnt = sockaddr_to_str((struct sockaddr *)&sess->s.src_addr, 122 page, PAGE_SIZE); 123 return cnt + scnprintf(page + cnt, PAGE_SIZE - cnt, "\n"); 124 } 125 126 static struct kobj_attribute rtrs_srv_dst_addr_attr = 127 __ATTR(dst_addr, 0444, rtrs_srv_dst_addr_show, NULL); 128 129 static struct attribute *rtrs_srv_sess_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 138 static struct attribute_group rtrs_srv_sess_attr_group = { 139 .attrs = rtrs_srv_sess_attrs, 140 }; 141 142 STAT_ATTR(struct rtrs_srv_stats, rdma, 143 rtrs_srv_stats_rdma_to_str, 144 rtrs_srv_reset_rdma_stats); 145 146 static struct attribute *rtrs_srv_stats_attrs[] = { 147 &rdma_attr.attr, 148 NULL, 149 }; 150 151 static struct attribute_group rtrs_srv_stats_attr_group = { 152 .attrs = rtrs_srv_stats_attrs, 153 }; 154 155 static int rtrs_srv_create_once_sysfs_root_folders(struct rtrs_srv_sess *sess) 156 { 157 struct rtrs_srv *srv = sess->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 session 164 */ 165 goto unlock; 166 } 167 srv->dev.class = rtrs_dev_class; 168 err = dev_set_name(&srv->dev, "%s", sess->s.sessname); 169 if (err) 170 goto unlock; 171 172 /* 173 * Suppress user space notification until 174 * sysfs files are created 175 */ 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 goto put; 181 } 182 srv->kobj_paths = kobject_create_and_add("paths", &srv->dev.kobj); 183 if (!srv->kobj_paths) { 184 err = -ENOMEM; 185 pr_err("kobject_create_and_add(): %d\n", err); 186 device_del(&srv->dev); 187 goto unlock; 188 } 189 dev_set_uevent_suppress(&srv->dev, false); 190 kobject_uevent(&srv->dev.kobj, KOBJ_ADD); 191 goto unlock; 192 193 put: 194 put_device(&srv->dev); 195 unlock: 196 mutex_unlock(&srv->paths_mutex); 197 198 return err; 199 } 200 201 static void 202 rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess *sess) 203 { 204 struct rtrs_srv *srv = sess->srv; 205 206 mutex_lock(&srv->paths_mutex); 207 if (!--srv->dev_ref) { 208 kobject_del(srv->kobj_paths); 209 kobject_put(srv->kobj_paths); 210 mutex_unlock(&srv->paths_mutex); 211 device_del(&srv->dev); 212 } else { 213 mutex_unlock(&srv->paths_mutex); 214 } 215 } 216 217 static void rtrs_srv_sess_stats_release(struct kobject *kobj) 218 { 219 struct rtrs_srv_stats *stats; 220 221 stats = container_of(kobj, struct rtrs_srv_stats, kobj_stats); 222 223 kfree(stats); 224 } 225 226 static struct kobj_type ktype_stats = { 227 .sysfs_ops = &kobj_sysfs_ops, 228 .release = rtrs_srv_sess_stats_release, 229 }; 230 231 static int rtrs_srv_create_stats_files(struct rtrs_srv_sess *sess) 232 { 233 int err; 234 struct rtrs_sess *s = &sess->s; 235 236 err = kobject_init_and_add(&sess->stats->kobj_stats, &ktype_stats, 237 &sess->kobj, "stats"); 238 if (err) { 239 rtrs_err(s, "kobject_init_and_add(): %d\n", err); 240 return err; 241 } 242 err = sysfs_create_group(&sess->stats->kobj_stats, 243 &rtrs_srv_stats_attr_group); 244 if (err) { 245 rtrs_err(s, "sysfs_create_group(): %d\n", err); 246 goto err; 247 } 248 249 return 0; 250 251 err: 252 kobject_del(&sess->stats->kobj_stats); 253 kobject_put(&sess->stats->kobj_stats); 254 255 return err; 256 } 257 258 int rtrs_srv_create_sess_files(struct rtrs_srv_sess *sess) 259 { 260 struct rtrs_srv *srv = sess->srv; 261 struct rtrs_sess *s = &sess->s; 262 char str[NAME_MAX]; 263 int err, cnt; 264 265 cnt = sockaddr_to_str((struct sockaddr *)&sess->s.dst_addr, 266 str, sizeof(str)); 267 cnt += scnprintf(str + cnt, sizeof(str) - cnt, "@"); 268 sockaddr_to_str((struct sockaddr *)&sess->s.src_addr, 269 str + cnt, sizeof(str) - cnt); 270 271 err = rtrs_srv_create_once_sysfs_root_folders(sess); 272 if (err) 273 return err; 274 275 err = kobject_init_and_add(&sess->kobj, &ktype, srv->kobj_paths, 276 "%s", str); 277 if (err) { 278 rtrs_err(s, "kobject_init_and_add(): %d\n", err); 279 goto destroy_root; 280 } 281 err = sysfs_create_group(&sess->kobj, &rtrs_srv_sess_attr_group); 282 if (err) { 283 rtrs_err(s, "sysfs_create_group(): %d\n", err); 284 goto put_kobj; 285 } 286 err = rtrs_srv_create_stats_files(sess); 287 if (err) 288 goto remove_group; 289 290 return 0; 291 292 remove_group: 293 sysfs_remove_group(&sess->kobj, &rtrs_srv_sess_attr_group); 294 put_kobj: 295 kobject_del(&sess->kobj); 296 kobject_put(&sess->kobj); 297 destroy_root: 298 rtrs_srv_destroy_once_sysfs_root_folders(sess); 299 300 return err; 301 } 302 303 void rtrs_srv_destroy_sess_files(struct rtrs_srv_sess *sess) 304 { 305 if (sess->kobj.state_in_sysfs) { 306 kobject_del(&sess->stats->kobj_stats); 307 kobject_put(&sess->stats->kobj_stats); 308 kobject_del(&sess->kobj); 309 kobject_put(&sess->kobj); 310 311 rtrs_srv_destroy_once_sysfs_root_folders(sess); 312 } 313 } 314