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