linux/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c
<<
>>
Prefs
   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
  16static 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
  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_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
  59static struct kobj_attribute rtrs_srv_disconnect_attr =
  60        __ATTR(disconnect, 0644,
  61               rtrs_srv_disconnect_show, rtrs_srv_disconnect_store);
  62
  63static 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
  76static struct kobj_attribute rtrs_srv_hca_port_attr =
  77        __ATTR(hca_port, 0444, rtrs_srv_hca_port_show, NULL);
  78
  79static 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
  90static struct kobj_attribute rtrs_srv_hca_name_attr =
  91        __ATTR(hca_name, 0444, rtrs_srv_hca_name_show, NULL);
  92
  93static 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
 106static struct kobj_attribute rtrs_srv_src_addr_attr =
 107        __ATTR(src_addr, 0444, rtrs_srv_src_addr_show, NULL);
 108
 109static 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
 123static struct kobj_attribute rtrs_srv_dst_addr_attr =
 124        __ATTR(dst_addr, 0444, rtrs_srv_dst_addr_show, NULL);
 125
 126static 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
 135static const struct attribute_group rtrs_srv_sess_attr_group = {
 136        .attrs = rtrs_srv_sess_attrs,
 137};
 138
 139STAT_ATTR(struct rtrs_srv_stats, rdma,
 140          rtrs_srv_stats_rdma_to_str,
 141          rtrs_srv_reset_rdma_stats);
 142
 143static struct attribute *rtrs_srv_stats_attrs[] = {
 144        &rdma_attr.attr,
 145        NULL,
 146};
 147
 148static const struct attribute_group rtrs_srv_stats_attr_group = {
 149        .attrs = rtrs_srv_stats_attrs,
 150};
 151
 152static 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
 190put:
 191        put_device(&srv->dev);
 192unlock:
 193        mutex_unlock(&srv->paths_mutex);
 194
 195        return err;
 196}
 197
 198static void
 199rtrs_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
 214static 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
 223static struct kobj_type ktype_stats = {
 224        .sysfs_ops = &kobj_sysfs_ops,
 225        .release = rtrs_srv_sess_stats_release,
 226};
 227
 228static 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
 248err:
 249        kobject_del(&sess->stats->kobj_stats);
 250        kobject_put(&sess->stats->kobj_stats);
 251
 252        return err;
 253}
 254
 255int 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
 289remove_group:
 290        sysfs_remove_group(&sess->kobj, &rtrs_srv_sess_attr_group);
 291put_kobj:
 292        kobject_del(&sess->kobj);
 293        kobject_put(&sess->kobj);
 294destroy_root:
 295        rtrs_srv_destroy_once_sysfs_root_folders(sess);
 296
 297        return err;
 298}
 299
 300void 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