cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rnbd-srv-sysfs.c (6237B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * RDMA Network Block Driver
      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 <uapi/linux/limits.h>
     13#include <linux/kobject.h>
     14#include <linux/sysfs.h>
     15#include <linux/stat.h>
     16#include <linux/list.h>
     17#include <linux/moduleparam.h>
     18#include <linux/device.h>
     19
     20#include "rnbd-srv.h"
     21
     22static struct device *rnbd_dev;
     23static struct class *rnbd_dev_class;
     24static struct kobject *rnbd_devs_kobj;
     25
     26static void rnbd_srv_dev_release(struct kobject *kobj)
     27{
     28	struct rnbd_srv_dev *dev;
     29
     30	dev = container_of(kobj, struct rnbd_srv_dev, dev_kobj);
     31
     32	kfree(dev);
     33}
     34
     35static struct kobj_type dev_ktype = {
     36	.sysfs_ops = &kobj_sysfs_ops,
     37	.release = rnbd_srv_dev_release
     38};
     39
     40int rnbd_srv_create_dev_sysfs(struct rnbd_srv_dev *dev,
     41			       struct block_device *bdev,
     42			       const char *dev_name)
     43{
     44	struct kobject *bdev_kobj;
     45	int ret;
     46
     47	ret = kobject_init_and_add(&dev->dev_kobj, &dev_ktype,
     48				   rnbd_devs_kobj, dev_name);
     49	if (ret) {
     50		kobject_put(&dev->dev_kobj);
     51		return ret;
     52	}
     53
     54	dev->dev_sessions_kobj = kobject_create_and_add("sessions",
     55							&dev->dev_kobj);
     56	if (!dev->dev_sessions_kobj) {
     57		ret = -ENOMEM;
     58		goto free_dev_kobj;
     59	}
     60
     61	bdev_kobj = &disk_to_dev(bdev->bd_disk)->kobj;
     62	ret = sysfs_create_link(&dev->dev_kobj, bdev_kobj, "block_dev");
     63	if (ret)
     64		goto put_sess_kobj;
     65
     66	return 0;
     67
     68put_sess_kobj:
     69	kobject_put(dev->dev_sessions_kobj);
     70free_dev_kobj:
     71	kobject_del(&dev->dev_kobj);
     72	kobject_put(&dev->dev_kobj);
     73	return ret;
     74}
     75
     76void rnbd_srv_destroy_dev_sysfs(struct rnbd_srv_dev *dev)
     77{
     78	sysfs_remove_link(&dev->dev_kobj, "block_dev");
     79	kobject_del(dev->dev_sessions_kobj);
     80	kobject_put(dev->dev_sessions_kobj);
     81	kobject_del(&dev->dev_kobj);
     82	kobject_put(&dev->dev_kobj);
     83}
     84
     85static ssize_t read_only_show(struct kobject *kobj, struct kobj_attribute *attr,
     86			      char *page)
     87{
     88	struct rnbd_srv_sess_dev *sess_dev;
     89
     90	sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
     91
     92	return sysfs_emit(page, "%d\n",
     93			  !(sess_dev->open_flags & FMODE_WRITE));
     94}
     95
     96static struct kobj_attribute rnbd_srv_dev_session_ro_attr =
     97	__ATTR_RO(read_only);
     98
     99static ssize_t access_mode_show(struct kobject *kobj,
    100				struct kobj_attribute *attr,
    101				char *page)
    102{
    103	struct rnbd_srv_sess_dev *sess_dev;
    104
    105	sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
    106
    107	return sysfs_emit(page, "%s\n",
    108			  rnbd_access_mode_str(sess_dev->access_mode));
    109}
    110
    111static struct kobj_attribute rnbd_srv_dev_session_access_mode_attr =
    112	__ATTR_RO(access_mode);
    113
    114static ssize_t mapping_path_show(struct kobject *kobj,
    115				 struct kobj_attribute *attr, char *page)
    116{
    117	struct rnbd_srv_sess_dev *sess_dev;
    118
    119	sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
    120
    121	return sysfs_emit(page, "%s\n", sess_dev->pathname);
    122}
    123
    124static struct kobj_attribute rnbd_srv_dev_session_mapping_path_attr =
    125	__ATTR_RO(mapping_path);
    126
    127static ssize_t rnbd_srv_dev_session_force_close_show(struct kobject *kobj,
    128					struct kobj_attribute *attr, char *page)
    129{
    130	return sysfs_emit(page, "Usage: echo 1 > %s\n",
    131			  attr->attr.name);
    132}
    133
    134static ssize_t rnbd_srv_dev_session_force_close_store(struct kobject *kobj,
    135					struct kobj_attribute *attr,
    136					const char *buf, size_t count)
    137{
    138	struct rnbd_srv_sess_dev *sess_dev;
    139
    140	sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
    141
    142	if (!sysfs_streq(buf, "1")) {
    143		rnbd_srv_err(sess_dev, "%s: invalid value: '%s'\n",
    144			      attr->attr.name, buf);
    145		return -EINVAL;
    146	}
    147
    148	rnbd_srv_info(sess_dev, "force close requested\n");
    149	rnbd_srv_sess_dev_force_close(sess_dev, attr);
    150
    151	return count;
    152}
    153
    154static struct kobj_attribute rnbd_srv_dev_session_force_close_attr =
    155	__ATTR(force_close, 0644,
    156	       rnbd_srv_dev_session_force_close_show,
    157	       rnbd_srv_dev_session_force_close_store);
    158
    159static struct attribute *rnbd_srv_default_dev_sessions_attrs[] = {
    160	&rnbd_srv_dev_session_access_mode_attr.attr,
    161	&rnbd_srv_dev_session_ro_attr.attr,
    162	&rnbd_srv_dev_session_mapping_path_attr.attr,
    163	&rnbd_srv_dev_session_force_close_attr.attr,
    164	NULL,
    165};
    166
    167static struct attribute_group rnbd_srv_default_dev_session_attr_group = {
    168	.attrs = rnbd_srv_default_dev_sessions_attrs,
    169};
    170
    171void rnbd_srv_destroy_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev)
    172{
    173	sysfs_remove_group(&sess_dev->kobj,
    174			   &rnbd_srv_default_dev_session_attr_group);
    175
    176	kobject_del(&sess_dev->kobj);
    177	kobject_put(&sess_dev->kobj);
    178}
    179
    180static void rnbd_srv_sess_dev_release(struct kobject *kobj)
    181{
    182	struct rnbd_srv_sess_dev *sess_dev;
    183
    184	sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
    185	rnbd_destroy_sess_dev(sess_dev, sess_dev->keep_id);
    186}
    187
    188static struct kobj_type rnbd_srv_sess_dev_ktype = {
    189	.sysfs_ops	= &kobj_sysfs_ops,
    190	.release	= rnbd_srv_sess_dev_release,
    191};
    192
    193int rnbd_srv_create_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev)
    194{
    195	int ret;
    196
    197	ret = kobject_init_and_add(&sess_dev->kobj, &rnbd_srv_sess_dev_ktype,
    198				   sess_dev->dev->dev_sessions_kobj, "%s",
    199				   sess_dev->sess->sessname);
    200	if (ret) {
    201		kobject_put(&sess_dev->kobj);
    202		return ret;
    203	}
    204
    205	ret = sysfs_create_group(&sess_dev->kobj,
    206				 &rnbd_srv_default_dev_session_attr_group);
    207	if (ret) {
    208		kobject_del(&sess_dev->kobj);
    209		kobject_put(&sess_dev->kobj);
    210	}
    211
    212	return ret;
    213}
    214
    215int rnbd_srv_create_sysfs_files(void)
    216{
    217	int err;
    218
    219	rnbd_dev_class = class_create(THIS_MODULE, "rnbd-server");
    220	if (IS_ERR(rnbd_dev_class))
    221		return PTR_ERR(rnbd_dev_class);
    222
    223	rnbd_dev = device_create(rnbd_dev_class, NULL,
    224				  MKDEV(0, 0), NULL, "ctl");
    225	if (IS_ERR(rnbd_dev)) {
    226		err = PTR_ERR(rnbd_dev);
    227		goto cls_destroy;
    228	}
    229	rnbd_devs_kobj = kobject_create_and_add("devices", &rnbd_dev->kobj);
    230	if (!rnbd_devs_kobj) {
    231		err = -ENOMEM;
    232		goto dev_destroy;
    233	}
    234
    235	return 0;
    236
    237dev_destroy:
    238	device_destroy(rnbd_dev_class, MKDEV(0, 0));
    239cls_destroy:
    240	class_destroy(rnbd_dev_class);
    241
    242	return err;
    243}
    244
    245void rnbd_srv_destroy_sysfs_files(void)
    246{
    247	kobject_del(rnbd_devs_kobj);
    248	kobject_put(rnbd_devs_kobj);
    249	device_destroy(rnbd_dev_class, MKDEV(0, 0));
    250	class_destroy(rnbd_dev_class);
    251}