summaryrefslogtreecommitdiff
path: root/drivers/block/rnbd/rnbd-srv-sysfs.c
diff options
context:
space:
mode:
authorLutz Pogrell <lutz.pogrell@cloud.ionos.com>2020-11-26 13:47:20 +0300
committerJens Axboe <axboe@kernel.dk>2020-12-04 19:41:10 +0300
commit786998050cbc8ead32e6e9fcda2facb3bf3d198d (patch)
tree794842b6774a8bfa6276f92091bee67e3e0ac123 /drivers/block/rnbd/rnbd-srv-sysfs.c
parent7578d5cd1e0fe71736970372fcf96341d69f2234 (diff)
downloadlinux-786998050cbc8ead32e6e9fcda2facb3bf3d198d.tar.xz
block/rnbd-srv: close a mapped device from server side.
The forceful close of an exported device is required for the use case, when the client side hangs, is crashed, or is not accessible. There have been cases observed, where only some of the devices are to be cleaned up, but the session shall remain. When the device is to be exported to a different client host, server side cleanup is required. Signed-off-by: Lutz Pogrell <lutz.pogrell@cloud.ionos.com> Signed-off-by: Jack Wang <jinpu.wang@cloud.ionos.com> Reviewed-by: Gioh Kim <gi-oh.kim@cloud.ionos.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/rnbd/rnbd-srv-sysfs.c')
-rw-r--r--drivers/block/rnbd/rnbd-srv-sysfs.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/block/rnbd/rnbd-srv-sysfs.c b/drivers/block/rnbd/rnbd-srv-sysfs.c
index 106775c074d1..08ffb492ebfa 100644
--- a/drivers/block/rnbd/rnbd-srv-sysfs.c
+++ b/drivers/block/rnbd/rnbd-srv-sysfs.c
@@ -120,10 +120,46 @@ static ssize_t mapping_path_show(struct kobject *kobj,
static struct kobj_attribute rnbd_srv_dev_session_mapping_path_attr =
__ATTR_RO(mapping_path);
+static ssize_t rnbd_srv_dev_session_force_close_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *page)
+{
+ return scnprintf(page, PAGE_SIZE, "Usage: echo 1 > %s\n",
+ attr->attr.name);
+}
+
+static ssize_t rnbd_srv_dev_session_force_close_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rnbd_srv_sess_dev *sess_dev;
+
+ sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
+
+ if (!sysfs_streq(buf, "1")) {
+ rnbd_srv_err(sess_dev, "%s: invalid value: '%s'\n",
+ attr->attr.name, buf);
+ return -EINVAL;
+ }
+
+ rnbd_srv_info(sess_dev, "force close requested\n");
+
+ /* first remove sysfs itself to avoid deadlock */
+ sysfs_remove_file_self(&sess_dev->kobj, &attr->attr);
+ rnbd_srv_sess_dev_force_close(sess_dev);
+
+ return count;
+}
+
+static struct kobj_attribute rnbd_srv_dev_session_force_close_attr =
+ __ATTR(force_close, 0644,
+ rnbd_srv_dev_session_force_close_show,
+ rnbd_srv_dev_session_force_close_store);
+
static struct attribute *rnbd_srv_default_dev_sessions_attrs[] = {
&rnbd_srv_dev_session_access_mode_attr.attr,
&rnbd_srv_dev_session_ro_attr.attr,
&rnbd_srv_dev_session_mapping_path_attr.attr,
+ &rnbd_srv_dev_session_force_close_attr.attr,
NULL,
};
@@ -145,7 +181,7 @@ static void rnbd_srv_sess_dev_release(struct kobject *kobj)
struct rnbd_srv_sess_dev *sess_dev;
sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
- rnbd_destroy_sess_dev(sess_dev);
+ rnbd_destroy_sess_dev(sess_dev, sess_dev->keep_id);
}
static struct kobj_type rnbd_srv_sess_dev_ktype = {