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