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