block/rnbd-clt-sysfs: use default_groups in kobj_type
[sfrench/cifs-2.6.git] / drivers / block / rnbd / rnbd-clt-sysfs.c
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
10 #undef pr_fmt
11 #define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt
12
13 #include <linux/types.h>
14 #include <linux/ctype.h>
15 #include <linux/parser.h>
16 #include <linux/module.h>
17 #include <linux/in6.h>
18 #include <linux/fs.h>
19 #include <linux/uaccess.h>
20 #include <linux/device.h>
21 #include <rdma/ib.h>
22 #include <rdma/rdma_cm.h>
23
24 #include "rnbd-clt.h"
25
26 static struct device *rnbd_dev;
27 static struct class *rnbd_dev_class;
28 static struct kobject *rnbd_devs_kobj;
29
30 enum {
31         RNBD_OPT_ERR            = 0,
32         RNBD_OPT_DEST_PORT      = 1 << 0,
33         RNBD_OPT_PATH           = 1 << 1,
34         RNBD_OPT_DEV_PATH       = 1 << 2,
35         RNBD_OPT_ACCESS_MODE    = 1 << 3,
36         RNBD_OPT_SESSNAME       = 1 << 6,
37         RNBD_OPT_NR_POLL_QUEUES = 1 << 7,
38 };
39
40 static const unsigned int rnbd_opt_mandatory[] = {
41         RNBD_OPT_DEV_PATH,
42         RNBD_OPT_SESSNAME,
43 };
44
45 static const match_table_t rnbd_opt_tokens = {
46         {RNBD_OPT_PATH,                 "path=%s"               },
47         {RNBD_OPT_DEV_PATH,             "device_path=%s"        },
48         {RNBD_OPT_DEST_PORT,            "dest_port=%d"          },
49         {RNBD_OPT_ACCESS_MODE,          "access_mode=%s"        },
50         {RNBD_OPT_SESSNAME,             "sessname=%s"           },
51         {RNBD_OPT_NR_POLL_QUEUES,       "nr_poll_queues=%d"     },
52         {RNBD_OPT_ERR,                  NULL                    },
53 };
54
55 struct rnbd_map_options {
56         char *sessname;
57         struct rtrs_addr *paths;
58         size_t *path_cnt;
59         char *pathname;
60         u16 *dest_port;
61         enum rnbd_access_mode *access_mode;
62         u32 *nr_poll_queues;
63 };
64
65 static int rnbd_clt_parse_map_options(const char *buf, size_t max_path_cnt,
66                                        struct rnbd_map_options *opt)
67 {
68         char *options, *sep_opt;
69         char *p;
70         substring_t args[MAX_OPT_ARGS];
71         int opt_mask = 0;
72         int token;
73         int ret = -EINVAL;
74         int nr_poll_queues = 0;
75         int dest_port = 0;
76         int p_cnt = 0;
77         int i;
78
79         options = kstrdup(buf, GFP_KERNEL);
80         if (!options)
81                 return -ENOMEM;
82
83         sep_opt = strstrip(options);
84         while ((p = strsep(&sep_opt, " ")) != NULL) {
85                 if (!*p)
86                         continue;
87
88                 token = match_token(p, rnbd_opt_tokens, args);
89                 opt_mask |= token;
90
91                 switch (token) {
92                 case RNBD_OPT_SESSNAME:
93                         p = match_strdup(args);
94                         if (!p) {
95                                 ret = -ENOMEM;
96                                 goto out;
97                         }
98                         if (strlen(p) > NAME_MAX) {
99                                 pr_err("map_device: sessname too long\n");
100                                 ret = -EINVAL;
101                                 kfree(p);
102                                 goto out;
103                         }
104                         strscpy(opt->sessname, p, NAME_MAX);
105                         kfree(p);
106                         break;
107
108                 case RNBD_OPT_PATH:
109                         if (p_cnt >= max_path_cnt) {
110                                 pr_err("map_device: too many (> %zu) paths provided\n",
111                                        max_path_cnt);
112                                 ret = -ENOMEM;
113                                 goto out;
114                         }
115                         p = match_strdup(args);
116                         if (!p) {
117                                 ret = -ENOMEM;
118                                 goto out;
119                         }
120
121                         ret = rtrs_addr_to_sockaddr(p, strlen(p),
122                                                     *opt->dest_port,
123                                                     &opt->paths[p_cnt]);
124                         if (ret) {
125                                 pr_err("Can't parse path %s: %d\n", p, ret);
126                                 kfree(p);
127                                 goto out;
128                         }
129
130                         p_cnt++;
131
132                         kfree(p);
133                         break;
134
135                 case RNBD_OPT_DEV_PATH:
136                         p = match_strdup(args);
137                         if (!p) {
138                                 ret = -ENOMEM;
139                                 goto out;
140                         }
141                         if (strlen(p) > NAME_MAX) {
142                                 pr_err("map_device: Device path too long\n");
143                                 ret = -EINVAL;
144                                 kfree(p);
145                                 goto out;
146                         }
147                         strscpy(opt->pathname, p, NAME_MAX);
148                         kfree(p);
149                         break;
150
151                 case RNBD_OPT_DEST_PORT:
152                         if (match_int(args, &dest_port) || dest_port < 0 ||
153                             dest_port > 65535) {
154                                 pr_err("bad destination port number parameter '%d'\n",
155                                        dest_port);
156                                 ret = -EINVAL;
157                                 goto out;
158                         }
159                         *opt->dest_port = dest_port;
160                         break;
161
162                 case RNBD_OPT_ACCESS_MODE:
163                         p = match_strdup(args);
164                         if (!p) {
165                                 ret = -ENOMEM;
166                                 goto out;
167                         }
168
169                         if (!strcmp(p, "ro")) {
170                                 *opt->access_mode = RNBD_ACCESS_RO;
171                         } else if (!strcmp(p, "rw")) {
172                                 *opt->access_mode = RNBD_ACCESS_RW;
173                         } else if (!strcmp(p, "migration")) {
174                                 *opt->access_mode = RNBD_ACCESS_MIGRATION;
175                         } else {
176                                 pr_err("map_device: Invalid access_mode: '%s'\n",
177                                        p);
178                                 ret = -EINVAL;
179                                 kfree(p);
180                                 goto out;
181                         }
182
183                         kfree(p);
184                         break;
185
186                 case RNBD_OPT_NR_POLL_QUEUES:
187                         if (match_int(args, &nr_poll_queues) || nr_poll_queues < -1 ||
188                             nr_poll_queues > (int)nr_cpu_ids) {
189                                 pr_err("bad nr_poll_queues parameter '%d'\n",
190                                        nr_poll_queues);
191                                 ret = -EINVAL;
192                                 goto out;
193                         }
194                         if (nr_poll_queues == -1)
195                                 nr_poll_queues = nr_cpu_ids;
196                         *opt->nr_poll_queues = nr_poll_queues;
197                         break;
198
199                 default:
200                         pr_err("map_device: Unknown parameter or missing value '%s'\n",
201                                p);
202                         ret = -EINVAL;
203                         goto out;
204                 }
205         }
206
207         for (i = 0; i < ARRAY_SIZE(rnbd_opt_mandatory); i++) {
208                 if ((opt_mask & rnbd_opt_mandatory[i])) {
209                         ret = 0;
210                 } else {
211                         pr_err("map_device: Parameters missing\n");
212                         ret = -EINVAL;
213                         break;
214                 }
215         }
216
217 out:
218         *opt->path_cnt = p_cnt;
219         kfree(options);
220         return ret;
221 }
222
223 static ssize_t state_show(struct kobject *kobj,
224                           struct kobj_attribute *attr, char *page)
225 {
226         struct rnbd_clt_dev *dev;
227
228         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
229
230         switch (dev->dev_state) {
231         case DEV_STATE_INIT:
232                 return sysfs_emit(page, "init\n");
233         case DEV_STATE_MAPPED:
234                 /* TODO fix cli tool before changing to proper state */
235                 return sysfs_emit(page, "open\n");
236         case DEV_STATE_MAPPED_DISCONNECTED:
237                 /* TODO fix cli tool before changing to proper state */
238                 return sysfs_emit(page, "closed\n");
239         case DEV_STATE_UNMAPPED:
240                 return sysfs_emit(page, "unmapped\n");
241         default:
242                 return sysfs_emit(page, "unknown\n");
243         }
244 }
245
246 static struct kobj_attribute rnbd_clt_state_attr = __ATTR_RO(state);
247
248 static ssize_t nr_poll_queues_show(struct kobject *kobj,
249                                    struct kobj_attribute *attr, char *page)
250 {
251         struct rnbd_clt_dev *dev;
252
253         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
254
255         return sysfs_emit(page, "%d\n", dev->nr_poll_queues);
256 }
257
258 static struct kobj_attribute rnbd_clt_nr_poll_queues =
259         __ATTR_RO(nr_poll_queues);
260
261 static ssize_t mapping_path_show(struct kobject *kobj,
262                                  struct kobj_attribute *attr, char *page)
263 {
264         struct rnbd_clt_dev *dev;
265
266         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
267
268         return sysfs_emit(page, "%s\n", dev->pathname);
269 }
270
271 static struct kobj_attribute rnbd_clt_mapping_path_attr =
272         __ATTR_RO(mapping_path);
273
274 static ssize_t access_mode_show(struct kobject *kobj,
275                                 struct kobj_attribute *attr, char *page)
276 {
277         struct rnbd_clt_dev *dev;
278
279         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
280
281         return sysfs_emit(page, "%s\n", rnbd_access_mode_str(dev->access_mode));
282 }
283
284 static struct kobj_attribute rnbd_clt_access_mode =
285         __ATTR_RO(access_mode);
286
287 static ssize_t rnbd_clt_unmap_dev_show(struct kobject *kobj,
288                                         struct kobj_attribute *attr, char *page)
289 {
290         return sysfs_emit(page, "Usage: echo <normal|force> > %s\n",
291                           attr->attr.name);
292 }
293
294 static ssize_t rnbd_clt_unmap_dev_store(struct kobject *kobj,
295                                          struct kobj_attribute *attr,
296                                          const char *buf, size_t count)
297 {
298         struct rnbd_clt_dev *dev;
299         char *opt, *options;
300         bool force;
301         int err;
302
303         opt = kstrdup(buf, GFP_KERNEL);
304         if (!opt)
305                 return -ENOMEM;
306
307         options = strstrip(opt);
308         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
309         if (sysfs_streq(options, "normal")) {
310                 force = false;
311         } else if (sysfs_streq(options, "force")) {
312                 force = true;
313         } else {
314                 rnbd_clt_err(dev,
315                               "unmap_device: Invalid value: %s\n",
316                               options);
317                 err = -EINVAL;
318                 goto out;
319         }
320
321         rnbd_clt_info(dev, "Unmapping device, option: %s.\n",
322                        force ? "force" : "normal");
323
324         /*
325          * We take explicit module reference only for one reason: do not
326          * race with lockless rnbd_destroy_sessions().
327          */
328         if (!try_module_get(THIS_MODULE)) {
329                 err = -ENODEV;
330                 goto out;
331         }
332         err = rnbd_clt_unmap_device(dev, force, &attr->attr);
333         if (err) {
334                 if (err != -EALREADY)
335                         rnbd_clt_err(dev, "unmap_device: %d\n",  err);
336                 goto module_put;
337         }
338
339         /*
340          * Here device can be vanished!
341          */
342
343         err = count;
344
345 module_put:
346         module_put(THIS_MODULE);
347 out:
348         kfree(opt);
349
350         return err;
351 }
352
353 static struct kobj_attribute rnbd_clt_unmap_device_attr =
354         __ATTR(unmap_device, 0644, rnbd_clt_unmap_dev_show,
355                rnbd_clt_unmap_dev_store);
356
357 static ssize_t rnbd_clt_resize_dev_show(struct kobject *kobj,
358                                          struct kobj_attribute *attr,
359                                          char *page)
360 {
361         return sysfs_emit(page, "Usage: echo <new size in sectors> > %s\n",
362                           attr->attr.name);
363 }
364
365 static ssize_t rnbd_clt_resize_dev_store(struct kobject *kobj,
366                                           struct kobj_attribute *attr,
367                                           const char *buf, size_t count)
368 {
369         int ret;
370         unsigned long sectors;
371         struct rnbd_clt_dev *dev;
372
373         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
374
375         ret = kstrtoul(buf, 0, &sectors);
376         if (ret)
377                 return ret;
378
379         ret = rnbd_clt_resize_disk(dev, (size_t)sectors);
380         if (ret)
381                 return ret;
382
383         return count;
384 }
385
386 static struct kobj_attribute rnbd_clt_resize_dev_attr =
387         __ATTR(resize, 0644, rnbd_clt_resize_dev_show,
388                rnbd_clt_resize_dev_store);
389
390 static ssize_t rnbd_clt_remap_dev_show(struct kobject *kobj,
391                                         struct kobj_attribute *attr, char *page)
392 {
393         return sysfs_emit(page, "Usage: echo <1> > %s\n", attr->attr.name);
394 }
395
396 static ssize_t rnbd_clt_remap_dev_store(struct kobject *kobj,
397                                          struct kobj_attribute *attr,
398                                          const char *buf, size_t count)
399 {
400         struct rnbd_clt_dev *dev;
401         char *opt, *options;
402         int err;
403
404         opt = kstrdup(buf, GFP_KERNEL);
405         if (!opt)
406                 return -ENOMEM;
407
408         options = strstrip(opt);
409         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
410         if (!sysfs_streq(options, "1")) {
411                 rnbd_clt_err(dev,
412                               "remap_device: Invalid value: %s\n",
413                               options);
414                 err = -EINVAL;
415                 goto out;
416         }
417         err = rnbd_clt_remap_device(dev);
418         if (likely(!err))
419                 err = count;
420
421 out:
422         kfree(opt);
423
424         return err;
425 }
426
427 static struct kobj_attribute rnbd_clt_remap_device_attr =
428         __ATTR(remap_device, 0644, rnbd_clt_remap_dev_show,
429                rnbd_clt_remap_dev_store);
430
431 static ssize_t session_show(struct kobject *kobj, struct kobj_attribute *attr,
432                             char *page)
433 {
434         struct rnbd_clt_dev *dev;
435
436         dev = container_of(kobj, struct rnbd_clt_dev, kobj);
437
438         return sysfs_emit(page, "%s\n", dev->sess->sessname);
439 }
440
441 static struct kobj_attribute rnbd_clt_session_attr =
442         __ATTR_RO(session);
443
444 static struct attribute *rnbd_dev_attrs[] = {
445         &rnbd_clt_unmap_device_attr.attr,
446         &rnbd_clt_resize_dev_attr.attr,
447         &rnbd_clt_remap_device_attr.attr,
448         &rnbd_clt_mapping_path_attr.attr,
449         &rnbd_clt_state_attr.attr,
450         &rnbd_clt_session_attr.attr,
451         &rnbd_clt_access_mode.attr,
452         &rnbd_clt_nr_poll_queues.attr,
453         NULL,
454 };
455 ATTRIBUTE_GROUPS(rnbd_dev);
456
457 void rnbd_clt_remove_dev_symlink(struct rnbd_clt_dev *dev)
458 {
459         /*
460          * The module unload rnbd_client_exit path is racing with unmapping of
461          * the last single device from the sysfs manually
462          * i.e. rnbd_clt_unmap_dev_store() leading to a sysfs warning because
463          * of sysfs link already was removed already.
464          */
465         if (dev->blk_symlink_name) {
466                 if (try_module_get(THIS_MODULE)) {
467                         sysfs_remove_link(rnbd_devs_kobj, dev->blk_symlink_name);
468                         module_put(THIS_MODULE);
469                 }
470                 /* It should be freed always. */
471                 kfree(dev->blk_symlink_name);
472                 dev->blk_symlink_name = NULL;
473         }
474 }
475
476 static struct kobj_type rnbd_dev_ktype = {
477         .sysfs_ops      = &kobj_sysfs_ops,
478         .default_groups = rnbd_dev_groups,
479 };
480
481 static int rnbd_clt_add_dev_kobj(struct rnbd_clt_dev *dev)
482 {
483         int ret;
484         struct kobject *gd_kobj = &disk_to_dev(dev->gd)->kobj;
485
486         ret = kobject_init_and_add(&dev->kobj, &rnbd_dev_ktype, gd_kobj, "%s",
487                                    "rnbd");
488         if (ret) {
489                 rnbd_clt_err(dev, "Failed to create device sysfs dir, err: %d\n",
490                               ret);
491                 kobject_put(&dev->kobj);
492         }
493         kobject_uevent(gd_kobj, KOBJ_ONLINE);
494
495         return ret;
496 }
497
498 static ssize_t rnbd_clt_map_device_show(struct kobject *kobj,
499                                          struct kobj_attribute *attr,
500                                          char *page)
501 {
502         return sysfs_emit(page,
503                           "Usage: echo \"[dest_port=server port number] sessname=<name of the rtrs session> path=<[srcaddr@]dstaddr> [path=<[srcaddr@]dstaddr>] device_path=<full path on remote side> [access_mode=<ro|rw|migration>] [nr_poll_queues=<number of queues>]\" > %s\n\naddr ::= [ ip:<ipv4> | ip:<ipv6> | gid:<gid> ]\n",
504                          attr->attr.name);
505 }
506
507 static int rnbd_clt_get_path_name(struct rnbd_clt_dev *dev, char *buf,
508                                    size_t len)
509 {
510         int ret;
511         char pathname[NAME_MAX], *s;
512
513         strscpy(pathname, dev->pathname, sizeof(pathname));
514         while ((s = strchr(pathname, '/')))
515                 s[0] = '!';
516
517         ret = snprintf(buf, len, "%s@%s", pathname, dev->sess->sessname);
518         if (ret >= len)
519                 return -ENAMETOOLONG;
520
521         return 0;
522 }
523
524 static int rnbd_clt_add_dev_symlink(struct rnbd_clt_dev *dev)
525 {
526         struct kobject *gd_kobj = &disk_to_dev(dev->gd)->kobj;
527         int ret, len;
528
529         len = strlen(dev->pathname) + strlen(dev->sess->sessname) + 2;
530         dev->blk_symlink_name = kzalloc(len, GFP_KERNEL);
531         if (!dev->blk_symlink_name) {
532                 rnbd_clt_err(dev, "Failed to allocate memory for blk_symlink_name\n");
533                 return -ENOMEM;
534         }
535
536         ret = rnbd_clt_get_path_name(dev, dev->blk_symlink_name,
537                                       len);
538         if (ret) {
539                 rnbd_clt_err(dev, "Failed to get /sys/block symlink path, err: %d\n",
540                               ret);
541                 goto out_err;
542         }
543
544         ret = sysfs_create_link(rnbd_devs_kobj, gd_kobj,
545                                 dev->blk_symlink_name);
546         if (ret) {
547                 rnbd_clt_err(dev, "Creating /sys/block symlink failed, err: %d\n",
548                               ret);
549                 goto out_err;
550         }
551
552         return 0;
553
554 out_err:
555         kfree(dev->blk_symlink_name);
556         dev->blk_symlink_name = NULL ;
557         return ret;
558 }
559
560 static ssize_t rnbd_clt_map_device_store(struct kobject *kobj,
561                                           struct kobj_attribute *attr,
562                                           const char *buf, size_t count)
563 {
564         struct rnbd_clt_dev *dev;
565         struct rnbd_map_options opt;
566         int ret;
567         char pathname[NAME_MAX];
568         char sessname[NAME_MAX];
569         enum rnbd_access_mode access_mode = RNBD_ACCESS_RW;
570         u16 port_nr = RTRS_PORT;
571         u32 nr_poll_queues = 0;
572
573         struct sockaddr_storage *addrs;
574         struct rtrs_addr paths[6];
575         size_t path_cnt;
576
577         opt.sessname = sessname;
578         opt.paths = paths;
579         opt.path_cnt = &path_cnt;
580         opt.pathname = pathname;
581         opt.dest_port = &port_nr;
582         opt.access_mode = &access_mode;
583         opt.nr_poll_queues = &nr_poll_queues;
584         addrs = kcalloc(ARRAY_SIZE(paths) * 2, sizeof(*addrs), GFP_KERNEL);
585         if (!addrs)
586                 return -ENOMEM;
587
588         for (path_cnt = 0; path_cnt < ARRAY_SIZE(paths); path_cnt++) {
589                 paths[path_cnt].src = &addrs[path_cnt * 2];
590                 paths[path_cnt].dst = &addrs[path_cnt * 2 + 1];
591         }
592
593         ret = rnbd_clt_parse_map_options(buf, ARRAY_SIZE(paths), &opt);
594         if (ret)
595                 goto out;
596
597         pr_info("Mapping device %s on session %s, (access_mode: %s, nr_poll_queues: %d)\n",
598                 pathname, sessname,
599                 rnbd_access_mode_str(access_mode),
600                 nr_poll_queues);
601
602         dev = rnbd_clt_map_device(sessname, paths, path_cnt, port_nr, pathname,
603                                   access_mode, nr_poll_queues);
604         if (IS_ERR(dev)) {
605                 ret = PTR_ERR(dev);
606                 goto out;
607         }
608
609         ret = rnbd_clt_add_dev_kobj(dev);
610         if (ret)
611                 goto unmap_dev;
612
613         ret = rnbd_clt_add_dev_symlink(dev);
614         if (ret)
615                 goto unmap_dev;
616
617         kfree(addrs);
618         return count;
619
620 unmap_dev:
621         rnbd_clt_unmap_device(dev, true, NULL);
622 out:
623         kfree(addrs);
624         return ret;
625 }
626
627 static struct kobj_attribute rnbd_clt_map_device_attr =
628         __ATTR(map_device, 0644,
629                rnbd_clt_map_device_show, rnbd_clt_map_device_store);
630
631 static struct attribute *default_attrs[] = {
632         &rnbd_clt_map_device_attr.attr,
633         NULL,
634 };
635
636 static struct attribute_group default_attr_group = {
637         .attrs = default_attrs,
638 };
639
640 static const struct attribute_group *default_attr_groups[] = {
641         &default_attr_group,
642         NULL,
643 };
644
645 int rnbd_clt_create_sysfs_files(void)
646 {
647         int err;
648
649         rnbd_dev_class = class_create(THIS_MODULE, "rnbd-client");
650         if (IS_ERR(rnbd_dev_class))
651                 return PTR_ERR(rnbd_dev_class);
652
653         rnbd_dev = device_create_with_groups(rnbd_dev_class, NULL,
654                                               MKDEV(0, 0), NULL,
655                                               default_attr_groups, "ctl");
656         if (IS_ERR(rnbd_dev)) {
657                 err = PTR_ERR(rnbd_dev);
658                 goto cls_destroy;
659         }
660         rnbd_devs_kobj = kobject_create_and_add("devices", &rnbd_dev->kobj);
661         if (!rnbd_devs_kobj) {
662                 err = -ENOMEM;
663                 goto dev_destroy;
664         }
665
666         return 0;
667
668 dev_destroy:
669         device_destroy(rnbd_dev_class, MKDEV(0, 0));
670 cls_destroy:
671         class_destroy(rnbd_dev_class);
672
673         return err;
674 }
675
676 void rnbd_clt_destroy_sysfs_files(void)
677 {
678         sysfs_remove_group(&rnbd_dev->kobj, &default_attr_group);
679         kobject_del(rnbd_devs_kobj);
680         kobject_put(rnbd_devs_kobj);
681         device_destroy(rnbd_dev_class, MKDEV(0, 0));
682         class_destroy(rnbd_dev_class);
683 }