0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #define KMSG_COMPONENT "dasd"
0015
0016 #include <linux/interrupt.h>
0017 #include <linux/major.h>
0018 #include <linux/fs.h>
0019 #include <linux/blkpg.h>
0020
0021 #include <linux/uaccess.h>
0022
0023
0024 #define PRINTK_HEADER "dasd_gendisk:"
0025
0026 #include "dasd_int.h"
0027
0028 static struct lock_class_key dasd_bio_compl_lkclass;
0029
0030
0031
0032
0033 int dasd_gendisk_alloc(struct dasd_block *block)
0034 {
0035 struct gendisk *gdp;
0036 struct dasd_device *base;
0037 int len, rc;
0038
0039
0040 base = block->base;
0041 if (base->devindex >= DASD_PER_MAJOR)
0042 return -EBUSY;
0043
0044 gdp = blk_mq_alloc_disk_for_queue(block->request_queue,
0045 &dasd_bio_compl_lkclass);
0046 if (!gdp)
0047 return -ENOMEM;
0048
0049
0050 gdp->major = DASD_MAJOR;
0051 gdp->first_minor = base->devindex << DASD_PARTN_BITS;
0052 gdp->minors = 1 << DASD_PARTN_BITS;
0053 gdp->fops = &dasd_device_operations;
0054
0055
0056
0057
0058
0059
0060
0061
0062 len = sprintf(gdp->disk_name, "dasd");
0063 if (base->devindex > 25) {
0064 if (base->devindex > 701) {
0065 if (base->devindex > 18277)
0066 len += sprintf(gdp->disk_name + len, "%c",
0067 'a'+(((base->devindex-18278)
0068 /17576)%26));
0069 len += sprintf(gdp->disk_name + len, "%c",
0070 'a'+(((base->devindex-702)/676)%26));
0071 }
0072 len += sprintf(gdp->disk_name + len, "%c",
0073 'a'+(((base->devindex-26)/26)%26));
0074 }
0075 len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26));
0076
0077 if (base->features & DASD_FEATURE_READONLY ||
0078 test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
0079 set_disk_ro(gdp, 1);
0080 dasd_add_link_to_gendisk(gdp, base);
0081 block->gdp = gdp;
0082 set_capacity(block->gdp, 0);
0083
0084 rc = device_add_disk(&base->cdev->dev, block->gdp, NULL);
0085 if (rc) {
0086 dasd_gendisk_free(block);
0087 return rc;
0088 }
0089
0090 return 0;
0091 }
0092
0093
0094
0095
0096 void dasd_gendisk_free(struct dasd_block *block)
0097 {
0098 if (block->gdp) {
0099 del_gendisk(block->gdp);
0100 block->gdp->private_data = NULL;
0101 put_disk(block->gdp);
0102 block->gdp = NULL;
0103 }
0104 }
0105
0106
0107
0108
0109 int dasd_scan_partitions(struct dasd_block *block)
0110 {
0111 struct block_device *bdev;
0112 int rc;
0113
0114 bdev = blkdev_get_by_dev(disk_devt(block->gdp), FMODE_READ, NULL);
0115 if (IS_ERR(bdev)) {
0116 DBF_DEV_EVENT(DBF_ERR, block->base,
0117 "scan partitions error, blkdev_get returned %ld",
0118 PTR_ERR(bdev));
0119 return -ENODEV;
0120 }
0121
0122 mutex_lock(&block->gdp->open_mutex);
0123 rc = bdev_disk_changed(block->gdp, false);
0124 mutex_unlock(&block->gdp->open_mutex);
0125 if (rc)
0126 DBF_DEV_EVENT(DBF_ERR, block->base,
0127 "scan partitions error, rc %d", rc);
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 block->bdev = bdev;
0140 return 0;
0141 }
0142
0143
0144
0145
0146
0147 void dasd_destroy_partitions(struct dasd_block *block)
0148 {
0149 struct block_device *bdev;
0150
0151
0152
0153
0154
0155 bdev = block->bdev;
0156 block->bdev = NULL;
0157
0158 mutex_lock(&bdev->bd_disk->open_mutex);
0159 bdev_disk_changed(bdev->bd_disk, true);
0160 mutex_unlock(&bdev->bd_disk->open_mutex);
0161
0162
0163 blkdev_put(bdev, FMODE_READ);
0164 }
0165
0166 int dasd_gendisk_init(void)
0167 {
0168 int rc;
0169
0170
0171 rc = register_blkdev(DASD_MAJOR, "dasd");
0172 if (rc != 0) {
0173 pr_warn("Registering the device driver with major number %d failed\n",
0174 DASD_MAJOR);
0175 return rc;
0176 }
0177 return 0;
0178 }
0179
0180 void dasd_gendisk_exit(void)
0181 {
0182 unregister_blkdev(DASD_MAJOR, "dasd");
0183 }