Skip to content

Commit 7869980

Browse files
Lutz Pogrellaxboe
authored andcommitted
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 <[email protected]> Signed-off-by: Jack Wang <[email protected]> Reviewed-by: Gioh Kim <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 7578d5c commit 7869980

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

drivers/block/rnbd/rnbd-srv-sysfs.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,46 @@ static ssize_t mapping_path_show(struct kobject *kobj,
120120
static struct kobj_attribute rnbd_srv_dev_session_mapping_path_attr =
121121
__ATTR_RO(mapping_path);
122122

123+
static ssize_t rnbd_srv_dev_session_force_close_show(struct kobject *kobj,
124+
struct kobj_attribute *attr, char *page)
125+
{
126+
return scnprintf(page, PAGE_SIZE, "Usage: echo 1 > %s\n",
127+
attr->attr.name);
128+
}
129+
130+
static ssize_t rnbd_srv_dev_session_force_close_store(struct kobject *kobj,
131+
struct kobj_attribute *attr,
132+
const char *buf, size_t count)
133+
{
134+
struct rnbd_srv_sess_dev *sess_dev;
135+
136+
sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
137+
138+
if (!sysfs_streq(buf, "1")) {
139+
rnbd_srv_err(sess_dev, "%s: invalid value: '%s'\n",
140+
attr->attr.name, buf);
141+
return -EINVAL;
142+
}
143+
144+
rnbd_srv_info(sess_dev, "force close requested\n");
145+
146+
/* first remove sysfs itself to avoid deadlock */
147+
sysfs_remove_file_self(&sess_dev->kobj, &attr->attr);
148+
rnbd_srv_sess_dev_force_close(sess_dev);
149+
150+
return count;
151+
}
152+
153+
static struct kobj_attribute rnbd_srv_dev_session_force_close_attr =
154+
__ATTR(force_close, 0644,
155+
rnbd_srv_dev_session_force_close_show,
156+
rnbd_srv_dev_session_force_close_store);
157+
123158
static struct attribute *rnbd_srv_default_dev_sessions_attrs[] = {
124159
&rnbd_srv_dev_session_access_mode_attr.attr,
125160
&rnbd_srv_dev_session_ro_attr.attr,
126161
&rnbd_srv_dev_session_mapping_path_attr.attr,
162+
&rnbd_srv_dev_session_force_close_attr.attr,
127163
NULL,
128164
};
129165

@@ -145,7 +181,7 @@ static void rnbd_srv_sess_dev_release(struct kobject *kobj)
145181
struct rnbd_srv_sess_dev *sess_dev;
146182

147183
sess_dev = container_of(kobj, struct rnbd_srv_sess_dev, kobj);
148-
rnbd_destroy_sess_dev(sess_dev);
184+
rnbd_destroy_sess_dev(sess_dev, sess_dev->keep_id);
149185
}
150186

151187
static struct kobj_type rnbd_srv_sess_dev_ktype = {

drivers/block/rnbd/rnbd-srv.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,20 @@ static void rnbd_put_srv_dev(struct rnbd_srv_dev *dev)
212212
kref_put(&dev->kref, destroy_device_cb);
213213
}
214214

215-
void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev)
215+
void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev, bool keep_id)
216216
{
217217
DECLARE_COMPLETION_ONSTACK(dc);
218218

219-
xa_erase(&sess_dev->sess->index_idr, sess_dev->device_id);
219+
if (keep_id)
220+
/* free the resources for the id but don't */
221+
/* allow to re-use the id itself because it */
222+
/* is still used by the client */
223+
xa_cmpxchg(&sess_dev->sess->index_idr, sess_dev->device_id,
224+
sess_dev, NULL, 0);
225+
else
226+
xa_erase(&sess_dev->sess->index_idr, sess_dev->device_id);
220227
synchronize_rcu();
228+
221229
sess_dev->destroy_comp = &dc;
222230
rnbd_put_sess_dev(sess_dev);
223231
wait_for_completion(&dc); /* wait for inflights to drop to zero */
@@ -328,6 +336,13 @@ static int rnbd_srv_link_ev(struct rtrs_srv *rtrs,
328336
}
329337
}
330338

339+
void rnbd_srv_sess_dev_force_close(struct rnbd_srv_sess_dev *sess_dev)
340+
{
341+
rnbd_srv_destroy_dev_session_sysfs(sess_dev);
342+
sess_dev->keep_id = true;
343+
344+
}
345+
331346
static int process_msg_close(struct rtrs_srv *rtrs,
332347
struct rnbd_srv_session *srv_sess,
333348
void *data, size_t datalen, const void *usr,

drivers/block/rnbd/rnbd-srv.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,15 @@ struct rnbd_srv_sess_dev {
5656
struct rnbd_srv_dev *dev;
5757
struct kobject kobj;
5858
u32 device_id;
59+
bool keep_id;
5960
fmode_t open_flags;
6061
struct kref kref;
6162
struct completion *destroy_comp;
6263
char pathname[NAME_MAX];
6364
enum rnbd_access_mode access_mode;
6465
};
6566

67+
void rnbd_srv_sess_dev_force_close(struct rnbd_srv_sess_dev *sess_dev);
6668
/* rnbd-srv-sysfs.c */
6769

6870
int rnbd_srv_create_dev_sysfs(struct rnbd_srv_dev *dev,
@@ -73,6 +75,6 @@ int rnbd_srv_create_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev);
7375
void rnbd_srv_destroy_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev);
7476
int rnbd_srv_create_sysfs_files(void);
7577
void rnbd_srv_destroy_sysfs_files(void);
76-
void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev);
78+
void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev, bool keep_id);
7779

7880
#endif /* RNBD_SRV_H */

0 commit comments

Comments
 (0)