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