1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * dcssblk.c -- the S/390 block driver for dcss memory 4 * 5 * Authors: Carsten Otte, Stefan Weinhuber, Gerald Schaefer 6 */ 7 8 #define KMSG_COMPONENT "dcssblk" 9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 10 11 #include <linux/module.h> 12 #include <linux/moduleparam.h> 13 #include <linux/ctype.h> 14 #include <linux/errno.h> 15 #include <linux/init.h> 16 #include <linux/slab.h> 17 #include <linux/blkdev.h> 18 #include <linux/completion.h> 19 #include <linux/interrupt.h> 20 #include <linux/pfn_t.h> 21 #include <linux/uio.h> 22 #include <linux/dax.h> 23 #include <asm/extmem.h> 24 #include <asm/io.h> 25 26 #define DCSSBLK_NAME "dcssblk" 27 #define DCSSBLK_MINORS_PER_DISK 1 28 #define DCSSBLK_PARM_LEN 400 29 #define DCSS_BUS_ID_SIZE 20 30 31 static int dcssblk_open(struct block_device *bdev, fmode_t mode); 32 static void dcssblk_release(struct gendisk *disk, fmode_t mode); 33 static void dcssblk_submit_bio(struct bio *bio); 34 static long dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, 35 long nr_pages, void **kaddr, pfn_t *pfn); 36 37 static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0"; 38 39 static int dcssblk_major; 40 static const struct block_device_operations dcssblk_devops = { 41 .owner = THIS_MODULE, 42 .submit_bio = dcssblk_submit_bio, 43 .open = dcssblk_open, 44 .release = dcssblk_release, 45 }; 46 47 static size_t dcssblk_dax_copy_from_iter(struct dax_device *dax_dev, 48 pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i) 49 { 50 return copy_from_iter(addr, bytes, i); 51 } 52 53 static size_t dcssblk_dax_copy_to_iter(struct dax_device *dax_dev, 54 pgoff_t pgoff, void *addr, size_t bytes, struct iov_iter *i) 55 { 56 return copy_to_iter(addr, bytes, i); 57 } 58 59 static int dcssblk_dax_zero_page_range(struct dax_device *dax_dev, 60 pgoff_t pgoff, size_t nr_pages) 61 { 62 long rc; 63 void *kaddr; 64 65 rc = dax_direct_access(dax_dev, pgoff, nr_pages, &kaddr, NULL); 66 if (rc < 0) 67 return rc; 68 memset(kaddr, 0, nr_pages << PAGE_SHIFT); 69 dax_flush(dax_dev, kaddr, nr_pages << PAGE_SHIFT); 70 return 0; 71 } 72 73 static const struct dax_operations dcssblk_dax_ops = { 74 .direct_access = dcssblk_dax_direct_access, 75 .dax_supported = generic_fsdax_supported, 76 .copy_from_iter = dcssblk_dax_copy_from_iter, 77 .copy_to_iter = dcssblk_dax_copy_to_iter, 78 .zero_page_range = dcssblk_dax_zero_page_range, 79 }; 80 81 struct dcssblk_dev_info { 82 struct list_head lh; 83 struct device dev; 84 char segment_name[DCSS_BUS_ID_SIZE]; 85 atomic_t use_count; 86 struct gendisk *gd; 87 unsigned long start; 88 unsigned long end; 89 int segment_type; 90 unsigned char save_pending; 91 unsigned char is_shared; 92 int num_of_segments; 93 struct list_head seg_list; 94 struct dax_device *dax_dev; 95 }; 96 97 struct segment_info { 98 struct list_head lh; 99 char segment_name[DCSS_BUS_ID_SIZE]; 100 unsigned long start; 101 unsigned long end; 102 int segment_type; 103 }; 104 105 static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf, 106 size_t count); 107 static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf, 108 size_t count); 109 110 static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store); 111 static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store); 112 113 static struct device *dcssblk_root_dev; 114 115 static LIST_HEAD(dcssblk_devices); 116 static struct rw_semaphore dcssblk_devices_sem; 117 118 /* 119 * release function for segment device. 120 */ 121 static void 122 dcssblk_release_segment(struct device *dev) 123 { 124 struct dcssblk_dev_info *dev_info; 125 struct segment_info *entry, *temp; 126 127 dev_info = container_of(dev, struct dcssblk_dev_info, dev); 128 list_for_each_entry_safe(entry, temp, &dev_info->seg_list, lh) { 129 list_del(&entry->lh); 130 kfree(entry); 131 } 132 kfree(dev_info); 133 module_put(THIS_MODULE); 134 } 135 136 /* 137 * get a minor number. needs to be called with 138 * down_write(&dcssblk_devices_sem) and the 139 * device needs to be enqueued before the semaphore is 140 * freed. 141 */ 142 static int 143 dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) 144 { 145 int minor, found; 146 struct dcssblk_dev_info *entry; 147 148 if (dev_info == NULL) 149 return -EINVAL; 150 for (minor = 0; minor < (1<<MINORBITS); minor++) { 151 found = 0; 152 // test if minor available 153 list_for_each_entry(entry, &dcssblk_devices, lh) 154 if (minor == entry->gd->first_minor) 155 found++; 156 if (!found) break; // got unused minor 157 } 158 if (found) 159 return -EBUSY; 160 dev_info->gd->first_minor = minor; 161 return 0; 162 } 163 164 /* 165 * get the struct dcssblk_dev_info from dcssblk_devices 166 * for the given name. 167 * down_read(&dcssblk_devices_sem) must be held. 168 */ 169 static struct dcssblk_dev_info * 170 dcssblk_get_device_by_name(char *name) 171 { 172 struct dcssblk_dev_info *entry; 173 174 list_for_each_entry(entry, &dcssblk_devices, lh) { 175 if (!strcmp(name, entry->segment_name)) { 176 return entry; 177 } 178 } 179 return NULL; 180 } 181 182 /* 183 * get the struct segment_info from seg_list 184 * for the given name. 185 * down_read(&dcssblk_devices_sem) must be held. 186 */ 187 static struct segment_info * 188 dcssblk_get_segment_by_name(char *name) 189 { 190 struct dcssblk_dev_info *dev_info; 191 struct segment_info *entry; 192 193 list_for_each_entry(dev_info, &dcssblk_devices, lh) { 194 list_for_each_entry(entry, &dev_info->seg_list, lh) { 195 if (!strcmp(name, entry->segment_name)) 196 return entry; 197 } 198 } 199 return NULL; 200 } 201 202 /* 203 * get the highest address of the multi-segment block. 204 */ 205 static unsigned long 206 dcssblk_find_highest_addr(struct dcssblk_dev_info *dev_info) 207 { 208 unsigned long highest_addr; 209 struct segment_info *entry; 210 211 highest_addr = 0; 212 list_for_each_entry(entry, &dev_info->seg_list, lh) { 213 if (highest_addr < entry->end) 214 highest_addr = entry->end; 215 } 216 return highest_addr; 217 } 218 219 /* 220 * get the lowest address of the multi-segment block. 221 */ 222 static unsigned long 223 dcssblk_find_lowest_addr(struct dcssblk_dev_info *dev_info) 224 { 225 int set_first; 226 unsigned long lowest_addr; 227 struct segment_info *entry; 228 229 set_first = 0; 230 lowest_addr = 0; 231 list_for_each_entry(entry, &dev_info->seg_list, lh) { 232 if (set_first == 0) { 233 lowest_addr = entry->start; 234 set_first = 1; 235 } else { 236 if (lowest_addr > entry->start) 237 lowest_addr = entry->start; 238 } 239 } 240 return lowest_addr; 241 } 242 243 /* 244 * Check continuity of segments. 245 */ 246 static int 247 dcssblk_is_continuous(struct dcssblk_dev_info *dev_info) 248 { 249 int i, j, rc; 250 struct segment_info *sort_list, *entry, temp; 251 252 if (dev_info->num_of_segments <= 1) 253 return 0; 254 255 sort_list = kcalloc(dev_info->num_of_segments, 256 sizeof(struct segment_info), 257 GFP_KERNEL); 258 if (sort_list == NULL) 259 return -ENOMEM; 260 i = 0; 261 list_for_each_entry(entry, &dev_info->seg_list, lh) { 262 memcpy(&sort_list[i], entry, sizeof(struct segment_info)); 263 i++; 264 } 265 266 /* sort segments */ 267 for (i = 0; i < dev_info->num_of_segments; i++) 268 for (j = 0; j < dev_info->num_of_segments; j++) 269 if (sort_list[j].start > sort_list[i].start) { 270 memcpy(&temp, &sort_list[i], 271 sizeof(struct segment_info)); 272 memcpy(&sort_list[i], &sort_list[j], 273 sizeof(struct segment_info)); 274 memcpy(&sort_list[j], &temp, 275 sizeof(struct segment_info)); 276 } 277 278 /* check continuity */ 279 for (i = 0; i < dev_info->num_of_segments - 1; i++) { 280 if ((sort_list[i].end + 1) != sort_list[i+1].start) { 281 pr_err("Adjacent DCSSs %s and %s are not " 282 "contiguous\n", sort_list[i].segment_name, 283 sort_list[i+1].segment_name); 284 rc = -EINVAL; 285 goto out; 286 } 287 /* EN and EW are allowed in a block device */ 288 if (sort_list[i].segment_type != sort_list[i+1].segment_type) { 289 if (!(sort_list[i].segment_type & SEGMENT_EXCLUSIVE) || 290 (sort_list[i].segment_type == SEG_TYPE_ER) || 291 !(sort_list[i+1].segment_type & 292 SEGMENT_EXCLUSIVE) || 293 (sort_list[i+1].segment_type == SEG_TYPE_ER)) { 294 pr_err("DCSS %s and DCSS %s have " 295 "incompatible types\n", 296 sort_list[i].segment_name, 297 sort_list[i+1].segment_name); 298 rc = -EINVAL; 299 goto out; 300 } 301 } 302 } 303 rc = 0; 304 out: 305 kfree(sort_list); 306 return rc; 307 } 308 309 /* 310 * Load a segment 311 */ 312 static int 313 dcssblk_load_segment(char *name, struct segment_info **seg_info) 314 { 315 int rc; 316 317 /* already loaded? */ 318 down_read(&dcssblk_devices_sem); 319 *seg_info = dcssblk_get_segment_by_name(name); 320 up_read(&dcssblk_devices_sem); 321 if (*seg_info != NULL) 322 return -EEXIST; 323 324 /* get a struct segment_info */ 325 *seg_info = kzalloc(sizeof(struct segment_info), GFP_KERNEL); 326 if (*seg_info == NULL) 327 return -ENOMEM; 328 329 strcpy((*seg_info)->segment_name, name); 330 331 /* load the segment */ 332 rc = segment_load(name, SEGMENT_SHARED, 333 &(*seg_info)->start, &(*seg_info)->end); 334 if (rc < 0) { 335 segment_warning(rc, (*seg_info)->segment_name); 336 kfree(*seg_info); 337 } else { 338 INIT_LIST_HEAD(&(*seg_info)->lh); 339 (*seg_info)->segment_type = rc; 340 } 341 return rc; 342 } 343 344 /* 345 * device attribute for switching shared/nonshared (exclusive) 346 * operation (show + store) 347 */ 348 static ssize_t 349 dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf) 350 { 351 struct dcssblk_dev_info *dev_info; 352 353 dev_info = container_of(dev, struct dcssblk_dev_info, dev); 354 return sprintf(buf, dev_info->is_shared ? "1\n" : "0\n"); 355 } 356 357 static ssize_t 358 dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count) 359 { 360 struct dcssblk_dev_info *dev_info; 361 struct segment_info *entry, *temp; 362 int rc; 363 364 if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) 365 return -EINVAL; 366 down_write(&dcssblk_devices_sem); 367 dev_info = container_of(dev, struct dcssblk_dev_info, dev); 368 if (atomic_read(&dev_info->use_count)) { 369 rc = -EBUSY; 370 goto out; 371 } 372 if (inbuf[0] == '1') { 373 /* reload segments in shared mode */ 374 list_for_each_entry(entry, &dev_info->seg_list, lh) { 375 rc = segment_modify_shared(entry->segment_name, 376 SEGMENT_SHARED); 377 if (rc < 0) { 378 BUG_ON(rc == -EINVAL); 379 if (rc != -EAGAIN) 380 goto removeseg; 381 } 382 } 383 dev_info->is_shared = 1; 384 switch (dev_info->segment_type) { 385 case SEG_TYPE_SR: 386 case SEG_TYPE_ER: 387 case SEG_TYPE_SC: 388 set_disk_ro(dev_info->gd, 1); 389 } 390 } else if (inbuf[0] == '0') { 391 /* reload segments in exclusive mode */ 392 if (dev_info->segment_type == SEG_TYPE_SC) { 393 pr_err("DCSS %s is of type SC and cannot be " 394 "loaded as exclusive-writable\n", 395 dev_info->segment_name); 396 rc = -EINVAL; 397 goto out; 398 } 399 list_for_each_entry(entry, &dev_info->seg_list, lh) { 400 rc = segment_modify_shared(entry->segment_name, 401 SEGMENT_EXCLUSIVE); 402 if (rc < 0) { 403 BUG_ON(rc == -EINVAL); 404 if (rc != -EAGAIN) 405 goto removeseg; 406 } 407 } 408 dev_info->is_shared = 0; 409 set_disk_ro(dev_info->gd, 0); 410 } else { 411 rc = -EINVAL; 412 goto out; 413 } 414 rc = count; 415 goto out; 416 417 removeseg: 418 pr_err("DCSS device %s is removed after a failed access mode " 419 "change\n", dev_info->segment_name); 420 temp = entry; 421 list_for_each_entry(entry, &dev_info->seg_list, lh) { 422 if (entry != temp) 423 segment_unload(entry->segment_name); 424 } 425 list_del(&dev_info->lh); 426 427 kill_dax(dev_info->dax_dev); 428 put_dax(dev_info->dax_dev); 429 del_gendisk(dev_info->gd); 430 blk_cleanup_disk(dev_info->gd); 431 up_write(&dcssblk_devices_sem); 432 433 if (device_remove_file_self(dev, attr)) { 434 device_unregister(dev); 435 put_device(dev); 436 } 437 return rc; 438 out: 439 up_write(&dcssblk_devices_sem); 440 return rc; 441 } 442 static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show, 443 dcssblk_shared_store); 444 445 /* 446 * device attribute for save operation on current copy 447 * of the segment. If the segment is busy, saving will 448 * become pending until it gets released, which can be 449 * undone by storing a non-true value to this entry. 450 * (show + store) 451 */ 452 static ssize_t 453 dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf) 454 { 455 struct dcssblk_dev_info *dev_info; 456 457 dev_info = container_of(dev, struct dcssblk_dev_info, dev); 458 return sprintf(buf, dev_info->save_pending ? "1\n" : "0\n"); 459 } 460 461 static ssize_t 462 dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count) 463 { 464 struct dcssblk_dev_info *dev_info; 465 struct segment_info *entry; 466 467 if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) 468 return -EINVAL; 469 dev_info = container_of(dev, struct dcssblk_dev_info, dev); 470 471 down_write(&dcssblk_devices_sem); 472 if (inbuf[0] == '1') { 473 if (atomic_read(&dev_info->use_count) == 0) { 474 // device is idle => we save immediately 475 pr_info("All DCSSs that map to device %s are " 476 "saved\n", dev_info->segment_name); 477 list_for_each_entry(entry, &dev_info->seg_list, lh) { 478 if (entry->segment_type == SEG_TYPE_EN || 479 entry->segment_type == SEG_TYPE_SN) 480 pr_warn("DCSS %s is of type SN or EN" 481 " and cannot be saved\n", 482 entry->segment_name); 483 else 484 segment_save(entry->segment_name); 485 } 486 } else { 487 // device is busy => we save it when it becomes 488 // idle in dcssblk_release 489 pr_info("Device %s is in use, its DCSSs will be " 490 "saved when it becomes idle\n", 491 dev_info->segment_name); 492 dev_info->save_pending = 1; 493 } 494 } else if (inbuf[0] == '0') { 495 if (dev_info->save_pending) { 496 // device is busy & the user wants to undo his save 497 // request 498 dev_info->save_pending = 0; 499 pr_info("A pending save request for device %s " 500 "has been canceled\n", 501 dev_info->segment_name); 502 } 503 } else { 504 up_write(&dcssblk_devices_sem); 505 return -EINVAL; 506 } 507 up_write(&dcssblk_devices_sem); 508 return count; 509 } 510 static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show, 511 dcssblk_save_store); 512 513 /* 514 * device attribute for showing all segments in a device 515 */ 516 static ssize_t 517 dcssblk_seglist_show(struct device *dev, struct device_attribute *attr, 518 char *buf) 519 { 520 int i; 521 522 struct dcssblk_dev_info *dev_info; 523 struct segment_info *entry; 524 525 down_read(&dcssblk_devices_sem); 526 dev_info = container_of(dev, struct dcssblk_dev_info, dev); 527 i = 0; 528 buf[0] = '\0'; 529 list_for_each_entry(entry, &dev_info->seg_list, lh) { 530 strcpy(&buf[i], entry->segment_name); 531 i += strlen(entry->segment_name); 532 buf[i] = '\n'; 533 i++; 534 } 535 up_read(&dcssblk_devices_sem); 536 return i; 537 } 538 static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL); 539 540 static struct attribute *dcssblk_dev_attrs[] = { 541 &dev_attr_shared.attr, 542 &dev_attr_save.attr, 543 &dev_attr_seglist.attr, 544 NULL, 545 }; 546 static struct attribute_group dcssblk_dev_attr_group = { 547 .attrs = dcssblk_dev_attrs, 548 }; 549 static const struct attribute_group *dcssblk_dev_attr_groups[] = { 550 &dcssblk_dev_attr_group, 551 NULL, 552 }; 553 554 /* 555 * device attribute for adding devices 556 */ 557 static ssize_t 558 dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 559 { 560 int rc, i, j, num_of_segments; 561 struct dcssblk_dev_info *dev_info; 562 struct segment_info *seg_info, *temp; 563 char *local_buf; 564 unsigned long seg_byte_size; 565 566 dev_info = NULL; 567 seg_info = NULL; 568 if (dev != dcssblk_root_dev) { 569 rc = -EINVAL; 570 goto out_nobuf; 571 } 572 if ((count < 1) || (buf[0] == '\0') || (buf[0] == '\n')) { 573 rc = -ENAMETOOLONG; 574 goto out_nobuf; 575 } 576 577 local_buf = kmalloc(count + 1, GFP_KERNEL); 578 if (local_buf == NULL) { 579 rc = -ENOMEM; 580 goto out_nobuf; 581 } 582 583 /* 584 * parse input 585 */ 586 num_of_segments = 0; 587 for (i = 0; (i < count && (buf[i] != '\0') && (buf[i] != '\n')); i++) { 588 for (j = i; j < count && 589 (buf[j] != ':') && 590 (buf[j] != '\0') && 591 (buf[j] != '\n'); j++) { 592 local_buf[j-i] = toupper(buf[j]); 593 } 594 local_buf[j-i] = '\0'; 595 if (((j - i) == 0) || ((j - i) > 8)) { 596 rc = -ENAMETOOLONG; 597 goto seg_list_del; 598 } 599 600 rc = dcssblk_load_segment(local_buf, &seg_info); 601 if (rc < 0) 602 goto seg_list_del; 603 /* 604 * get a struct dcssblk_dev_info 605 */ 606 if (num_of_segments == 0) { 607 dev_info = kzalloc(sizeof(struct dcssblk_dev_info), 608 GFP_KERNEL); 609 if (dev_info == NULL) { 610 rc = -ENOMEM; 611 goto out; 612 } 613 strcpy(dev_info->segment_name, local_buf); 614 dev_info->segment_type = seg_info->segment_type; 615 INIT_LIST_HEAD(&dev_info->seg_list); 616 } 617 list_add_tail(&seg_info->lh, &dev_info->seg_list); 618 num_of_segments++; 619 i = j; 620 621 if ((buf[j] == '\0') || (buf[j] == '\n')) 622 break; 623 } 624 625 /* no trailing colon at the end of the input */ 626 if ((i > 0) && (buf[i-1] == ':')) { 627 rc = -ENAMETOOLONG; 628 goto seg_list_del; 629 } 630 strlcpy(local_buf, buf, i + 1); 631 dev_info->num_of_segments = num_of_segments; 632 rc = dcssblk_is_continuous(dev_info); 633 if (rc < 0) 634 goto seg_list_del; 635 636 dev_info->start = dcssblk_find_lowest_addr(dev_info); 637 dev_info->end = dcssblk_find_highest_addr(dev_info); 638 639 dev_set_name(&dev_info->dev, "%s", dev_info->segment_name); 640 dev_info->dev.release = dcssblk_release_segment; 641 dev_info->dev.groups = dcssblk_dev_attr_groups; 642 INIT_LIST_HEAD(&dev_info->lh); 643 dev_info->gd = blk_alloc_disk(NUMA_NO_NODE); 644 if (dev_info->gd == NULL) { 645 rc = -ENOMEM; 646 goto seg_list_del; 647 } 648 dev_info->gd->major = dcssblk_major; 649 dev_info->gd->minors = DCSSBLK_MINORS_PER_DISK; 650 dev_info->gd->fops = &dcssblk_devops; 651 dev_info->gd->private_data = dev_info; 652 blk_queue_logical_block_size(dev_info->gd->queue, 4096); 653 blk_queue_flag_set(QUEUE_FLAG_DAX, dev_info->gd->queue); 654 655 seg_byte_size = (dev_info->end - dev_info->start + 1); 656 set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors 657 pr_info("Loaded %s with total size %lu bytes and capacity %lu " 658 "sectors\n", local_buf, seg_byte_size, seg_byte_size >> 9); 659 660 dev_info->save_pending = 0; 661 dev_info->is_shared = 1; 662 dev_info->dev.parent = dcssblk_root_dev; 663 664 /* 665 *get minor, add to list 666 */ 667 down_write(&dcssblk_devices_sem); 668 if (dcssblk_get_segment_by_name(local_buf)) { 669 rc = -EEXIST; 670 goto release_gd; 671 } 672 rc = dcssblk_assign_free_minor(dev_info); 673 if (rc) 674 goto release_gd; 675 sprintf(dev_info->gd->disk_name, "dcssblk%d", 676 dev_info->gd->first_minor); 677 list_add_tail(&dev_info->lh, &dcssblk_devices); 678 679 if (!try_module_get(THIS_MODULE)) { 680 rc = -ENODEV; 681 goto dev_list_del; 682 } 683 /* 684 * register the device 685 */ 686 rc = device_register(&dev_info->dev); 687 if (rc) 688 goto put_dev; 689 690 dev_info->dax_dev = alloc_dax(dev_info, dev_info->gd->disk_name, 691 &dcssblk_dax_ops, DAXDEV_F_SYNC); 692 if (IS_ERR(dev_info->dax_dev)) { 693 rc = PTR_ERR(dev_info->dax_dev); 694 dev_info->dax_dev = NULL; 695 goto put_dev; 696 } 697 698 get_device(&dev_info->dev); 699 rc = device_add_disk(&dev_info->dev, dev_info->gd, NULL); 700 if (rc) 701 goto out_dax; 702 703 switch (dev_info->segment_type) { 704 case SEG_TYPE_SR: 705 case SEG_TYPE_ER: 706 case SEG_TYPE_SC: 707 set_disk_ro(dev_info->gd,1); 708 break; 709 default: 710 set_disk_ro(dev_info->gd,0); 711 break; 712 } 713 up_write(&dcssblk_devices_sem); 714 rc = count; 715 goto out; 716 717 out_dax: 718 put_device(&dev_info->dev); 719 kill_dax(dev_info->dax_dev); 720 put_dax(dev_info->dax_dev); 721 put_dev: 722 list_del(&dev_info->lh); 723 blk_cleanup_disk(dev_info->gd); 724 list_for_each_entry(seg_info, &dev_info->seg_list, lh) { 725 segment_unload(seg_info->segment_name); 726 } 727 put_device(&dev_info->dev); 728 up_write(&dcssblk_devices_sem); 729 goto out; 730 dev_list_del: 731 list_del(&dev_info->lh); 732 release_gd: 733 blk_cleanup_disk(dev_info->gd); 734 up_write(&dcssblk_devices_sem); 735 seg_list_del: 736 if (dev_info == NULL) 737 goto out; 738 list_for_each_entry_safe(seg_info, temp, &dev_info->seg_list, lh) { 739 list_del(&seg_info->lh); 740 segment_unload(seg_info->segment_name); 741 kfree(seg_info); 742 } 743 kfree(dev_info); 744 out: 745 kfree(local_buf); 746 out_nobuf: 747 return rc; 748 } 749 750 /* 751 * device attribute for removing devices 752 */ 753 static ssize_t 754 dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 755 { 756 struct dcssblk_dev_info *dev_info; 757 struct segment_info *entry; 758 int rc, i; 759 char *local_buf; 760 761 if (dev != dcssblk_root_dev) { 762 return -EINVAL; 763 } 764 local_buf = kmalloc(count + 1, GFP_KERNEL); 765 if (local_buf == NULL) { 766 return -ENOMEM; 767 } 768 /* 769 * parse input 770 */ 771 for (i = 0; (i < count && (*(buf+i)!='\0') && (*(buf+i)!='\n')); i++) { 772 local_buf[i] = toupper(buf[i]); 773 } 774 local_buf[i] = '\0'; 775 if ((i == 0) || (i > 8)) { 776 rc = -ENAMETOOLONG; 777 goto out_buf; 778 } 779 780 down_write(&dcssblk_devices_sem); 781 dev_info = dcssblk_get_device_by_name(local_buf); 782 if (dev_info == NULL) { 783 up_write(&dcssblk_devices_sem); 784 pr_warn("Device %s cannot be removed because it is not a known device\n", 785 local_buf); 786 rc = -ENODEV; 787 goto out_buf; 788 } 789 if (atomic_read(&dev_info->use_count) != 0) { 790 up_write(&dcssblk_devices_sem); 791 pr_warn("Device %s cannot be removed while it is in use\n", 792 local_buf); 793 rc = -EBUSY; 794 goto out_buf; 795 } 796 797 list_del(&dev_info->lh); 798 kill_dax(dev_info->dax_dev); 799 put_dax(dev_info->dax_dev); 800 del_gendisk(dev_info->gd); 801 blk_cleanup_disk(dev_info->gd); 802 803 /* unload all related segments */ 804 list_for_each_entry(entry, &dev_info->seg_list, lh) 805 segment_unload(entry->segment_name); 806 807 up_write(&dcssblk_devices_sem); 808 809 device_unregister(&dev_info->dev); 810 put_device(&dev_info->dev); 811 812 rc = count; 813 out_buf: 814 kfree(local_buf); 815 return rc; 816 } 817 818 static int 819 dcssblk_open(struct block_device *bdev, fmode_t mode) 820 { 821 struct dcssblk_dev_info *dev_info; 822 int rc; 823 824 dev_info = bdev->bd_disk->private_data; 825 if (NULL == dev_info) { 826 rc = -ENODEV; 827 goto out; 828 } 829 atomic_inc(&dev_info->use_count); 830 rc = 0; 831 out: 832 return rc; 833 } 834 835 static void 836 dcssblk_release(struct gendisk *disk, fmode_t mode) 837 { 838 struct dcssblk_dev_info *dev_info = disk->private_data; 839 struct segment_info *entry; 840 841 if (!dev_info) { 842 WARN_ON(1); 843 return; 844 } 845 down_write(&dcssblk_devices_sem); 846 if (atomic_dec_and_test(&dev_info->use_count) 847 && (dev_info->save_pending)) { 848 pr_info("Device %s has become idle and is being saved " 849 "now\n", dev_info->segment_name); 850 list_for_each_entry(entry, &dev_info->seg_list, lh) { 851 if (entry->segment_type == SEG_TYPE_EN || 852 entry->segment_type == SEG_TYPE_SN) 853 pr_warn("DCSS %s is of type SN or EN and cannot" 854 " be saved\n", entry->segment_name); 855 else 856 segment_save(entry->segment_name); 857 } 858 dev_info->save_pending = 0; 859 } 860 up_write(&dcssblk_devices_sem); 861 } 862 863 static void 864 dcssblk_submit_bio(struct bio *bio) 865 { 866 struct dcssblk_dev_info *dev_info; 867 struct bio_vec bvec; 868 struct bvec_iter iter; 869 unsigned long index; 870 unsigned long page_addr; 871 unsigned long source_addr; 872 unsigned long bytes_done; 873 874 blk_queue_split(&bio); 875 876 bytes_done = 0; 877 dev_info = bio->bi_bdev->bd_disk->private_data; 878 if (dev_info == NULL) 879 goto fail; 880 if ((bio->bi_iter.bi_sector & 7) != 0 || 881 (bio->bi_iter.bi_size & 4095) != 0) 882 /* Request is not page-aligned. */ 883 goto fail; 884 /* verify data transfer direction */ 885 if (dev_info->is_shared) { 886 switch (dev_info->segment_type) { 887 case SEG_TYPE_SR: 888 case SEG_TYPE_ER: 889 case SEG_TYPE_SC: 890 /* cannot write to these segments */ 891 if (bio_data_dir(bio) == WRITE) { 892 pr_warn("Writing to %s failed because it is a read-only device\n", 893 dev_name(&dev_info->dev)); 894 goto fail; 895 } 896 } 897 } 898 899 index = (bio->bi_iter.bi_sector >> 3); 900 bio_for_each_segment(bvec, bio, iter) { 901 page_addr = (unsigned long)bvec_virt(&bvec); 902 source_addr = dev_info->start + (index<<12) + bytes_done; 903 if (unlikely((page_addr & 4095) != 0) || (bvec.bv_len & 4095) != 0) 904 // More paranoia. 905 goto fail; 906 if (bio_data_dir(bio) == READ) { 907 memcpy((void*)page_addr, (void*)source_addr, 908 bvec.bv_len); 909 } else { 910 memcpy((void*)source_addr, (void*)page_addr, 911 bvec.bv_len); 912 } 913 bytes_done += bvec.bv_len; 914 } 915 bio_endio(bio); 916 return; 917 fail: 918 bio_io_error(bio); 919 } 920 921 static long 922 __dcssblk_direct_access(struct dcssblk_dev_info *dev_info, pgoff_t pgoff, 923 long nr_pages, void **kaddr, pfn_t *pfn) 924 { 925 resource_size_t offset = pgoff * PAGE_SIZE; 926 unsigned long dev_sz; 927 928 dev_sz = dev_info->end - dev_info->start + 1; 929 if (kaddr) 930 *kaddr = (void *) dev_info->start + offset; 931 if (pfn) 932 *pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset), 933 PFN_DEV|PFN_SPECIAL); 934 935 return (dev_sz - offset) / PAGE_SIZE; 936 } 937 938 static long 939 dcssblk_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, 940 long nr_pages, void **kaddr, pfn_t *pfn) 941 { 942 struct dcssblk_dev_info *dev_info = dax_get_private(dax_dev); 943 944 return __dcssblk_direct_access(dev_info, pgoff, nr_pages, kaddr, pfn); 945 } 946 947 static void 948 dcssblk_check_params(void) 949 { 950 int rc, i, j, k; 951 char buf[DCSSBLK_PARM_LEN + 1]; 952 struct dcssblk_dev_info *dev_info; 953 954 for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0'); 955 i++) { 956 for (j = i; (j < DCSSBLK_PARM_LEN) && 957 (dcssblk_segments[j] != ',') && 958 (dcssblk_segments[j] != '\0') && 959 (dcssblk_segments[j] != '('); j++) 960 { 961 buf[j-i] = dcssblk_segments[j]; 962 } 963 buf[j-i] = '\0'; 964 rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i); 965 if ((rc >= 0) && (dcssblk_segments[j] == '(')) { 966 for (k = 0; (buf[k] != ':') && (buf[k] != '\0'); k++) 967 buf[k] = toupper(buf[k]); 968 buf[k] = '\0'; 969 if (!strncmp(&dcssblk_segments[j], "(local)", 7)) { 970 down_read(&dcssblk_devices_sem); 971 dev_info = dcssblk_get_device_by_name(buf); 972 up_read(&dcssblk_devices_sem); 973 if (dev_info) 974 dcssblk_shared_store(&dev_info->dev, 975 NULL, "0\n", 2); 976 } 977 } 978 while ((dcssblk_segments[j] != ',') && 979 (dcssblk_segments[j] != '\0')) 980 { 981 j++; 982 } 983 if (dcssblk_segments[j] == '\0') 984 break; 985 i = j; 986 } 987 } 988 989 /* 990 * The init/exit functions. 991 */ 992 static void __exit 993 dcssblk_exit(void) 994 { 995 root_device_unregister(dcssblk_root_dev); 996 unregister_blkdev(dcssblk_major, DCSSBLK_NAME); 997 } 998 999 static int __init 1000 dcssblk_init(void) 1001 { 1002 int rc; 1003 1004 dcssblk_root_dev = root_device_register("dcssblk"); 1005 if (IS_ERR(dcssblk_root_dev)) 1006 return PTR_ERR(dcssblk_root_dev); 1007 rc = device_create_file(dcssblk_root_dev, &dev_attr_add); 1008 if (rc) 1009 goto out_root; 1010 rc = device_create_file(dcssblk_root_dev, &dev_attr_remove); 1011 if (rc) 1012 goto out_root; 1013 rc = register_blkdev(0, DCSSBLK_NAME); 1014 if (rc < 0) 1015 goto out_root; 1016 dcssblk_major = rc; 1017 init_rwsem(&dcssblk_devices_sem); 1018 1019 dcssblk_check_params(); 1020 return 0; 1021 1022 out_root: 1023 root_device_unregister(dcssblk_root_dev); 1024 1025 return rc; 1026 } 1027 1028 module_init(dcssblk_init); 1029 module_exit(dcssblk_exit); 1030 1031 module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444); 1032 MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, " 1033 "comma-separated list, names in each set separated " 1034 "by commas are separated by colons, each set contains " 1035 "names of contiguous segments and each name max. 8 chars.\n" 1036 "Adding \"(local)\" to the end of each set equals echoing 0 " 1037 "to /sys/devices/dcssblk/<device name>/shared after loading " 1038 "the contiguous segments - \n" 1039 "e.g. segments=\"mydcss1,mydcss2:mydcss3,mydcss4(local)\""); 1040 1041 MODULE_LICENSE("GPL"); 1042