diff options
Diffstat (limited to 'drivers/s390/block/dcssblk.c')
-rw-r--r-- | drivers/s390/block/dcssblk.c | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 63f26a135fe5..26ffc6ab441d 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -4,6 +4,9 @@ | |||
4 | * Authors: Carsten Otte, Stefan Weinhuber, Gerald Schaefer | 4 | * Authors: Carsten Otte, Stefan Weinhuber, Gerald Schaefer |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #define KMSG_COMPONENT "dcssblk" | ||
8 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
9 | |||
7 | #include <linux/module.h> | 10 | #include <linux/module.h> |
8 | #include <linux/moduleparam.h> | 11 | #include <linux/moduleparam.h> |
9 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
@@ -17,19 +20,10 @@ | |||
17 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
18 | #include <asm/s390_rdev.h> | 21 | #include <asm/s390_rdev.h> |
19 | 22 | ||
20 | //#define DCSSBLK_DEBUG /* Debug messages on/off */ | ||
21 | #define DCSSBLK_NAME "dcssblk" | 23 | #define DCSSBLK_NAME "dcssblk" |
22 | #define DCSSBLK_MINORS_PER_DISK 1 | 24 | #define DCSSBLK_MINORS_PER_DISK 1 |
23 | #define DCSSBLK_PARM_LEN 400 | 25 | #define DCSSBLK_PARM_LEN 400 |
24 | 26 | #define DCSS_BUS_ID_SIZE 20 | |
25 | #ifdef DCSSBLK_DEBUG | ||
26 | #define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSSBLK_NAME " debug: " x) | ||
27 | #else | ||
28 | #define PRINT_DEBUG(x...) do {} while (0) | ||
29 | #endif | ||
30 | #define PRINT_INFO(x...) printk(KERN_INFO DCSSBLK_NAME " info: " x) | ||
31 | #define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x) | ||
32 | #define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x) | ||
33 | 27 | ||
34 | static int dcssblk_open(struct block_device *bdev, fmode_t mode); | 28 | static int dcssblk_open(struct block_device *bdev, fmode_t mode); |
35 | static int dcssblk_release(struct gendisk *disk, fmode_t mode); | 29 | static int dcssblk_release(struct gendisk *disk, fmode_t mode); |
@@ -50,7 +44,7 @@ static struct block_device_operations dcssblk_devops = { | |||
50 | struct dcssblk_dev_info { | 44 | struct dcssblk_dev_info { |
51 | struct list_head lh; | 45 | struct list_head lh; |
52 | struct device dev; | 46 | struct device dev; |
53 | char segment_name[BUS_ID_SIZE]; | 47 | char segment_name[DCSS_BUS_ID_SIZE]; |
54 | atomic_t use_count; | 48 | atomic_t use_count; |
55 | struct gendisk *gd; | 49 | struct gendisk *gd; |
56 | unsigned long start; | 50 | unsigned long start; |
@@ -65,7 +59,7 @@ struct dcssblk_dev_info { | |||
65 | 59 | ||
66 | struct segment_info { | 60 | struct segment_info { |
67 | struct list_head lh; | 61 | struct list_head lh; |
68 | char segment_name[BUS_ID_SIZE]; | 62 | char segment_name[DCSS_BUS_ID_SIZE]; |
69 | unsigned long start; | 63 | unsigned long start; |
70 | unsigned long end; | 64 | unsigned long end; |
71 | int segment_type; | 65 | int segment_type; |
@@ -261,10 +255,9 @@ dcssblk_is_continuous(struct dcssblk_dev_info *dev_info) | |||
261 | /* check continuity */ | 255 | /* check continuity */ |
262 | for (i = 0; i < dev_info->num_of_segments - 1; i++) { | 256 | for (i = 0; i < dev_info->num_of_segments - 1; i++) { |
263 | if ((sort_list[i].end + 1) != sort_list[i+1].start) { | 257 | if ((sort_list[i].end + 1) != sort_list[i+1].start) { |
264 | PRINT_ERR("Segment %s is not contiguous with " | 258 | pr_err("Adjacent DCSSs %s and %s are not " |
265 | "segment %s\n", | 259 | "contiguous\n", sort_list[i].segment_name, |
266 | sort_list[i].segment_name, | 260 | sort_list[i+1].segment_name); |
267 | sort_list[i+1].segment_name); | ||
268 | rc = -EINVAL; | 261 | rc = -EINVAL; |
269 | goto out; | 262 | goto out; |
270 | } | 263 | } |
@@ -275,10 +268,10 @@ dcssblk_is_continuous(struct dcssblk_dev_info *dev_info) | |||
275 | !(sort_list[i+1].segment_type & | 268 | !(sort_list[i+1].segment_type & |
276 | SEGMENT_EXCLUSIVE) || | 269 | SEGMENT_EXCLUSIVE) || |
277 | (sort_list[i+1].segment_type == SEG_TYPE_ER)) { | 270 | (sort_list[i+1].segment_type == SEG_TYPE_ER)) { |
278 | PRINT_ERR("Segment %s has different type from " | 271 | pr_err("DCSS %s and DCSS %s have " |
279 | "segment %s\n", | 272 | "incompatible types\n", |
280 | sort_list[i].segment_name, | 273 | sort_list[i].segment_name, |
281 | sort_list[i+1].segment_name); | 274 | sort_list[i+1].segment_name); |
282 | rc = -EINVAL; | 275 | rc = -EINVAL; |
283 | goto out; | 276 | goto out; |
284 | } | 277 | } |
@@ -380,8 +373,9 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch | |||
380 | } else if (inbuf[0] == '0') { | 373 | } else if (inbuf[0] == '0') { |
381 | /* reload segments in exclusive mode */ | 374 | /* reload segments in exclusive mode */ |
382 | if (dev_info->segment_type == SEG_TYPE_SC) { | 375 | if (dev_info->segment_type == SEG_TYPE_SC) { |
383 | PRINT_ERR("Segment type SC (%s) cannot be loaded in " | 376 | pr_err("DCSS %s is of type SC and cannot be " |
384 | "non-shared mode\n", dev_info->segment_name); | 377 | "loaded as exclusive-writable\n", |
378 | dev_info->segment_name); | ||
385 | rc = -EINVAL; | 379 | rc = -EINVAL; |
386 | goto out; | 380 | goto out; |
387 | } | 381 | } |
@@ -404,9 +398,8 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch | |||
404 | goto out; | 398 | goto out; |
405 | 399 | ||
406 | removeseg: | 400 | removeseg: |
407 | PRINT_ERR("Could not reload segment(s) of the device %s, removing " | 401 | pr_err("DCSS device %s is removed after a failed access mode " |
408 | "segment(s) now!\n", | 402 | "change\n", dev_info->segment_name); |
409 | dev_info->segment_name); | ||
410 | temp = entry; | 403 | temp = entry; |
411 | list_for_each_entry(entry, &dev_info->seg_list, lh) { | 404 | list_for_each_entry(entry, &dev_info->seg_list, lh) { |
412 | if (entry != temp) | 405 | if (entry != temp) |
@@ -454,17 +447,17 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char | |||
454 | if (inbuf[0] == '1') { | 447 | if (inbuf[0] == '1') { |
455 | if (atomic_read(&dev_info->use_count) == 0) { | 448 | if (atomic_read(&dev_info->use_count) == 0) { |
456 | // device is idle => we save immediately | 449 | // device is idle => we save immediately |
457 | PRINT_INFO("Saving segment(s) of the device %s\n", | 450 | pr_info("All DCSSs that map to device %s are " |
458 | dev_info->segment_name); | 451 | "saved\n", dev_info->segment_name); |
459 | list_for_each_entry(entry, &dev_info->seg_list, lh) { | 452 | list_for_each_entry(entry, &dev_info->seg_list, lh) { |
460 | segment_save(entry->segment_name); | 453 | segment_save(entry->segment_name); |
461 | } | 454 | } |
462 | } else { | 455 | } else { |
463 | // device is busy => we save it when it becomes | 456 | // device is busy => we save it when it becomes |
464 | // idle in dcssblk_release | 457 | // idle in dcssblk_release |
465 | PRINT_INFO("Device %s is currently busy, segment(s) " | 458 | pr_info("Device %s is in use, its DCSSs will be " |
466 | "will be saved when it becomes idle...\n", | 459 | "saved when it becomes idle\n", |
467 | dev_info->segment_name); | 460 | dev_info->segment_name); |
468 | dev_info->save_pending = 1; | 461 | dev_info->save_pending = 1; |
469 | } | 462 | } |
470 | } else if (inbuf[0] == '0') { | 463 | } else if (inbuf[0] == '0') { |
@@ -472,9 +465,9 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char | |||
472 | // device is busy & the user wants to undo his save | 465 | // device is busy & the user wants to undo his save |
473 | // request | 466 | // request |
474 | dev_info->save_pending = 0; | 467 | dev_info->save_pending = 0; |
475 | PRINT_INFO("Pending save for segment(s) of the device " | 468 | pr_info("A pending save request for device %s " |
476 | "%s deactivated\n", | 469 | "has been canceled\n", |
477 | dev_info->segment_name); | 470 | dev_info->segment_name); |
478 | } | 471 | } |
479 | } else { | 472 | } else { |
480 | up_write(&dcssblk_devices_sem); | 473 | up_write(&dcssblk_devices_sem); |
@@ -614,9 +607,8 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char | |||
614 | 607 | ||
615 | seg_byte_size = (dev_info->end - dev_info->start + 1); | 608 | seg_byte_size = (dev_info->end - dev_info->start + 1); |
616 | set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors | 609 | set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors |
617 | PRINT_INFO("Loaded segment(s) %s, size = %lu Byte, " | 610 | pr_info("Loaded %s with total size %lu bytes and capacity %lu " |
618 | "capacity = %lu (512 Byte) sectors\n", local_buf, | 611 | "sectors\n", local_buf, seg_byte_size, seg_byte_size >> 9); |
619 | seg_byte_size, seg_byte_size >> 9); | ||
620 | 612 | ||
621 | dev_info->save_pending = 0; | 613 | dev_info->save_pending = 0; |
622 | dev_info->is_shared = 1; | 614 | dev_info->is_shared = 1; |
@@ -744,13 +736,15 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch | |||
744 | dev_info = dcssblk_get_device_by_name(local_buf); | 736 | dev_info = dcssblk_get_device_by_name(local_buf); |
745 | if (dev_info == NULL) { | 737 | if (dev_info == NULL) { |
746 | up_write(&dcssblk_devices_sem); | 738 | up_write(&dcssblk_devices_sem); |
747 | PRINT_WARN("Device %s is not loaded!\n", local_buf); | 739 | pr_warning("Device %s cannot be removed because it is not a " |
740 | "known device\n", local_buf); | ||
748 | rc = -ENODEV; | 741 | rc = -ENODEV; |
749 | goto out_buf; | 742 | goto out_buf; |
750 | } | 743 | } |
751 | if (atomic_read(&dev_info->use_count) != 0) { | 744 | if (atomic_read(&dev_info->use_count) != 0) { |
752 | up_write(&dcssblk_devices_sem); | 745 | up_write(&dcssblk_devices_sem); |
753 | PRINT_WARN("Device %s is in use!\n", local_buf); | 746 | pr_warning("Device %s cannot be removed while it is in " |
747 | "use\n", local_buf); | ||
754 | rc = -EBUSY; | 748 | rc = -EBUSY; |
755 | goto out_buf; | 749 | goto out_buf; |
756 | } | 750 | } |
@@ -807,8 +801,8 @@ dcssblk_release(struct gendisk *disk, fmode_t mode) | |||
807 | down_write(&dcssblk_devices_sem); | 801 | down_write(&dcssblk_devices_sem); |
808 | if (atomic_dec_and_test(&dev_info->use_count) | 802 | if (atomic_dec_and_test(&dev_info->use_count) |
809 | && (dev_info->save_pending)) { | 803 | && (dev_info->save_pending)) { |
810 | PRINT_INFO("Device %s became idle and is being saved now\n", | 804 | pr_info("Device %s has become idle and is being saved " |
811 | dev_info->segment_name); | 805 | "now\n", dev_info->segment_name); |
812 | list_for_each_entry(entry, &dev_info->seg_list, lh) { | 806 | list_for_each_entry(entry, &dev_info->seg_list, lh) { |
813 | segment_save(entry->segment_name); | 807 | segment_save(entry->segment_name); |
814 | } | 808 | } |
@@ -851,7 +845,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) | |||
851 | case SEG_TYPE_SC: | 845 | case SEG_TYPE_SC: |
852 | /* cannot write to these segments */ | 846 | /* cannot write to these segments */ |
853 | if (bio_data_dir(bio) == WRITE) { | 847 | if (bio_data_dir(bio) == WRITE) { |
854 | PRINT_WARN("rejecting write to ro device %s\n", | 848 | pr_warning("Writing to %s failed because it " |
849 | "is a read-only device\n", | ||
855 | dev_name(&dev_info->dev)); | 850 | dev_name(&dev_info->dev)); |
856 | goto fail; | 851 | goto fail; |
857 | } | 852 | } |