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