a53c8fab3f
Remove the file name from the comment at top of many files. In most cases the file name was wrong anyway, so it's rather pointless. Also unify the IBM copyright statement. We did have a lot of sightly different statements and wanted to change them one after another whenever a file gets touched. However that never happened. Instead people start to take the old/"wrong" statements to use as a template for new files. So unify all of them in one go. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
180 lines
4.7 KiB
C
180 lines
4.7 KiB
C
/*
|
|
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
|
|
* Horst Hummel <Horst.Hummel@de.ibm.com>
|
|
* Carsten Otte <Cotte@de.ibm.com>
|
|
* Martin Schwidefsky <schwidefsky@de.ibm.com>
|
|
* Bugreports.to..: <Linux390@de.ibm.com>
|
|
* Copyright IBM Corp. 1999, 2001
|
|
*
|
|
* gendisk related functions for the dasd driver.
|
|
*
|
|
*/
|
|
|
|
#define KMSG_COMPONENT "dasd"
|
|
|
|
#include <linux/interrupt.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/blkpg.h>
|
|
|
|
#include <asm/uaccess.h>
|
|
|
|
/* This is ugly... */
|
|
#define PRINTK_HEADER "dasd_gendisk:"
|
|
|
|
#include "dasd_int.h"
|
|
|
|
/*
|
|
* Allocate and register gendisk structure for device.
|
|
*/
|
|
int dasd_gendisk_alloc(struct dasd_block *block)
|
|
{
|
|
struct gendisk *gdp;
|
|
struct dasd_device *base;
|
|
int len;
|
|
|
|
/* Make sure the minor for this device exists. */
|
|
base = block->base;
|
|
if (base->devindex >= DASD_PER_MAJOR)
|
|
return -EBUSY;
|
|
|
|
gdp = alloc_disk(1 << DASD_PARTN_BITS);
|
|
if (!gdp)
|
|
return -ENOMEM;
|
|
|
|
/* Initialize gendisk structure. */
|
|
gdp->major = DASD_MAJOR;
|
|
gdp->first_minor = base->devindex << DASD_PARTN_BITS;
|
|
gdp->fops = &dasd_device_operations;
|
|
gdp->driverfs_dev = &base->cdev->dev;
|
|
|
|
/*
|
|
* Set device name.
|
|
* dasda - dasdz : 26 devices
|
|
* dasdaa - dasdzz : 676 devices, added up = 702
|
|
* dasdaaa - dasdzzz : 17576 devices, added up = 18278
|
|
* dasdaaaa - dasdzzzz : 456976 devices, added up = 475252
|
|
*/
|
|
len = sprintf(gdp->disk_name, "dasd");
|
|
if (base->devindex > 25) {
|
|
if (base->devindex > 701) {
|
|
if (base->devindex > 18277)
|
|
len += sprintf(gdp->disk_name + len, "%c",
|
|
'a'+(((base->devindex-18278)
|
|
/17576)%26));
|
|
len += sprintf(gdp->disk_name + len, "%c",
|
|
'a'+(((base->devindex-702)/676)%26));
|
|
}
|
|
len += sprintf(gdp->disk_name + len, "%c",
|
|
'a'+(((base->devindex-26)/26)%26));
|
|
}
|
|
len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26));
|
|
|
|
if (base->features & DASD_FEATURE_READONLY ||
|
|
test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
|
|
set_disk_ro(gdp, 1);
|
|
dasd_add_link_to_gendisk(gdp, base);
|
|
gdp->queue = block->request_queue;
|
|
block->gdp = gdp;
|
|
set_capacity(block->gdp, 0);
|
|
add_disk(block->gdp);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Unregister and free gendisk structure for device.
|
|
*/
|
|
void dasd_gendisk_free(struct dasd_block *block)
|
|
{
|
|
if (block->gdp) {
|
|
del_gendisk(block->gdp);
|
|
block->gdp->queue = NULL;
|
|
block->gdp->private_data = NULL;
|
|
put_disk(block->gdp);
|
|
block->gdp = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Trigger a partition detection.
|
|
*/
|
|
int dasd_scan_partitions(struct dasd_block *block)
|
|
{
|
|
struct block_device *bdev;
|
|
|
|
bdev = bdget_disk(block->gdp, 0);
|
|
if (!bdev || blkdev_get(bdev, FMODE_READ, NULL) < 0)
|
|
return -ENODEV;
|
|
/*
|
|
* See fs/partition/check.c:register_disk,rescan_partitions
|
|
* Can't call rescan_partitions directly. Use ioctl.
|
|
*/
|
|
ioctl_by_bdev(bdev, BLKRRPART, 0);
|
|
/*
|
|
* Since the matching blkdev_put call to the blkdev_get in
|
|
* this function is not called before dasd_destroy_partitions
|
|
* the offline open_count limit needs to be increased from
|
|
* 0 to 1. This is done by setting device->bdev (see
|
|
* dasd_generic_set_offline). As long as the partition
|
|
* detection is running no offline should be allowed. That
|
|
* is why the assignment to device->bdev is done AFTER
|
|
* the BLKRRPART ioctl.
|
|
*/
|
|
block->bdev = bdev;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Remove all inodes in the system for a device, delete the
|
|
* partitions and make device unusable by setting its size to zero.
|
|
*/
|
|
void dasd_destroy_partitions(struct dasd_block *block)
|
|
{
|
|
/* The two structs have 168/176 byte on 31/64 bit. */
|
|
struct blkpg_partition bpart;
|
|
struct blkpg_ioctl_arg barg;
|
|
struct block_device *bdev;
|
|
|
|
/*
|
|
* Get the bdev pointer from the device structure and clear
|
|
* device->bdev to lower the offline open_count limit again.
|
|
*/
|
|
bdev = block->bdev;
|
|
block->bdev = NULL;
|
|
|
|
/*
|
|
* See fs/partition/check.c:delete_partition
|
|
* Can't call delete_partitions directly. Use ioctl.
|
|
* The ioctl also does locking and invalidation.
|
|
*/
|
|
memset(&bpart, 0, sizeof(struct blkpg_partition));
|
|
memset(&barg, 0, sizeof(struct blkpg_ioctl_arg));
|
|
barg.data = (void __force __user *) &bpart;
|
|
barg.op = BLKPG_DEL_PARTITION;
|
|
for (bpart.pno = block->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
|
|
ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
|
|
|
|
invalidate_partition(block->gdp, 0);
|
|
/* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
|
|
blkdev_put(bdev, FMODE_READ);
|
|
set_capacity(block->gdp, 0);
|
|
}
|
|
|
|
int dasd_gendisk_init(void)
|
|
{
|
|
int rc;
|
|
|
|
/* Register to static dasd major 94 */
|
|
rc = register_blkdev(DASD_MAJOR, "dasd");
|
|
if (rc != 0) {
|
|
pr_warning("Registering the device driver with major number "
|
|
"%d failed\n", DASD_MAJOR);
|
|
return rc;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void dasd_gendisk_exit(void)
|
|
{
|
|
unregister_blkdev(DASD_MAJOR, "dasd");
|
|
}
|