Commit d572f1a5 authored by Alexander Viro's avatar Alexander Viro Committed by Andy Grover

[PATCH] per-disk gendisks in ataraid

parent 59a00f8c
......@@ -28,6 +28,7 @@
#include <linux/ioctl.h>
#include <linux/kdev_t.h>
#include <linux/swap.h>
#include <linux/buffer_head.h>
#include <linux/ide.h>
#include <asm/uaccess.h>
......@@ -44,7 +45,9 @@ static void ataraid_split_request(request_queue_t * q, int rw,
struct buffer_head *bh);
struct gendisk ataraid_gendisk;
static struct gendisk ataraid_gendisk[16];
static struct hd_struct *ataraid_part;
static char *ataraid_names;
static int ataraid_readahead[256];
static struct block_device_operations ataraid_fops = {
......@@ -229,9 +232,28 @@ void ataraid_release_device(int device)
void ataraid_register_disk(int device, long size)
{
register_disk(&ataraid_gendisk, mk_kdev(ATAMAJOR, 16 * device), 16,
&ataraid_fops, size);
struct gendisk *disk = ataraid_gendisk + device;
char *name = ataraid_names + 12 * device;
sprintf(name, "ataraid/d%d", device);
disk->part = ataraid_part + 16 * device;
disk->major = ATAMAJOR;
disk->first_minor = 16 * device;
disk->major_name = name;
disk->minor_shift = 4;
disk->nr_real = 1;
disk->fops = &ataraid_fops;
add_gendisk(disk);
register_disk(disk,
mk_kdev(disk->major, disk->first_minor),
1 << disk->minor_shift,
disk->fops, size);
}
void ataraid_unregister_disk(int device)
{
del_gendisk(&ataraid_gendisk[device]);
}
static __init int ataraid_init(void)
......@@ -241,61 +263,44 @@ static __init int ataraid_init(void)
ataraid_readahead[i] = 1023;
/* setup the gendisk structure */
ataraid_gendisk.part =
kmalloc(256 * sizeof(struct hd_struct), GFP_KERNEL);
if (ataraid_gendisk.part == NULL) {
ataraid_part = kmalloc(256 * sizeof(struct hd_struct), GFP_KERNEL);
ataraid_names = kmalloc(16 * 12, GFP_KERNEL);
if (!ataraid_part || !ataraid_names) {
kfree(ataraid_part);
kfree(ataraid_names);
printk(KERN_ERR
"ataraid: Couldn't allocate memory, aborting \n");
return -1;
}
memset(&ataraid_gendisk.part[0], 0,
256 * sizeof(struct hd_struct));
ataraid_gendisk.major = ATAMAJOR;
ataraid_gendisk.major_name = "ataraid";
ataraid_gendisk.minor_shift = 4;
ataraid_gendisk.nr_real = 16;
ataraid_gendisk.fops = &ataraid_fops;
add_gendisk(&ataraid_gendisk);
memset(ataraid_part, 0, 256 * sizeof(struct hd_struct));
if (register_blkdev(ATAMAJOR, "ataraid", &ataraid_fops)) {
kfree(ataraid_part);
kfree(ataraid_names);
printk(KERN_ERR "ataraid: Could not get major %d \n",
ATAMAJOR);
return -1;
}
blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR),
ataraid_make_request);
return 0;
}
static void __exit ataraid_exit(void)
{
unregister_blkdev(ATAMAJOR, "ataraid");
del_gendisk(&ataraid_gendisk);
if (ataraid_gendisk.part) {
kfree(ataraid_gendisk.part);
ataraid_gendisk.part = NULL;
}
kfree(ataraid_part);
kfree(ataraid_names);
}
module_init(ataraid_init);
module_exit(ataraid_exit);
EXPORT_SYMBOL(ataraid_get_device);
EXPORT_SYMBOL(ataraid_release_device);
EXPORT_SYMBOL(ataraid_gendisk);
EXPORT_SYMBOL(ataraid_register_disk);
EXPORT_SYMBOL(ataraid_unregister_disk);
MODULE_LICENSE("GPL");
......@@ -56,17 +56,10 @@ struct ataraid_bh_private {
atomic_t count;
};
extern struct gendisk ataraid_gendisk;
extern int ataraid_get_device(struct raid_device_operations *fops);
extern void ataraid_release_device(int device);
extern int get_blocksize(kdev_t dev);
extern void ataraid_register_disk(int device,long size);
extern void ataraid_unregister_disk(int device);
extern struct buffer_head *ataraid_get_bhead(void);
extern struct ataraid_bh_private *ataraid_get_private(void);
extern void ataraid_end_request(struct buffer_head *bh, int uptodate);
......@@ -74,62 +74,20 @@ static struct hptraid raid[16];
static int hptraid_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned int minor;
unsigned char val;
unsigned long sectors;
if (!inode || kdev_none(inode->i_rdev))
return -EINVAL;
minor = minor(inode->i_rdev) >> SHIFT;
switch (cmd) {
case BLKGETSIZE: /* Return device size */
if (!arg)
return -EINVAL;
sectors =
ataraid_gendisk.part[minor(inode->i_rdev)].nr_sects;
if (minor(inode->i_rdev) & 15)
return put_user(sectors, (unsigned long *) arg);
return put_user(raid[minor].sectors,
(unsigned long *) arg);
break;
case HDIO_GETGEO:
{
struct hd_geometry *loc =
(struct hd_geometry *) arg;
unsigned short bios_cyl;
if (!loc)
return -EINVAL;
val = 255;
if (put_user(val, (u8 *) & loc->heads))
return -EFAULT;
val = 63;
if (put_user(val, (u8 *) & loc->sectors))
return -EFAULT;
bios_cyl = raid[minor].sectors / 63 / 255;
if (put_user
(bios_cyl, (unsigned short *) &loc->cylinders))
return -EFAULT;
if (put_user
((unsigned) ataraid_gendisk.
part[minor(inode->i_rdev)].start_sect,
(unsigned long *) &loc->start))
return -EFAULT;
return 0;
}
unsigned int minor = minor(inode->i_rdev) >> SHIFT;
struct hd_geometry *geometry = (struct hd_geometry *) arg;
struct hd_geometry g;
default:
if (cmd != HDIO_GETGEO)
return -EINVAL;
};
return 0;
g.heads = 255;
g.sectors = 63;
g.cylinders = raid[minor].sectors / 63 / 255;
g.start = get_start_sect(inode->i_bdev);
return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
}
static int hptraid_make_request(request_queue_t * q, int rw,
struct buffer_head *bh)
{
......@@ -160,10 +118,6 @@ static int hptraid_make_request(request_queue_t * q, int rw,
if (thisraid->stride == 0)
thisraid->stride = 1;
/* Partitions need adding of the start sector of the partition to the requested sector */
rsect += ataraid_gendisk.part[minor(bh->b_rdev)].start_sect;
/* Woops we need to split the request to avoid crossing a stride barrier */
if ((rsect / thisraid->stride) !=
((rsect + (bh->b_size / 512) - 1) / thisraid->stride)) {
......@@ -273,7 +227,6 @@ static void __init probedisk(int major, int minor, int device)
{
int i;
struct block_device *bdev = bdget(mk_kdev(major, minor));
struct gendisk *gd;
if (!bdev)
return;
......@@ -301,19 +254,9 @@ static void __init probedisk(int major, int minor, int device)
if (i > 8)
goto out;
if (bd_claim(bdev, &raid[device].disk[i]) < 0)
goto out;
raid[device].disk[i].bdev = bdev;
/* This is supposed to prevent others from stealing our underlying disks */
/* now blank the /proc/partitions table for the wrong partition table,
so that scripts don't accidentally mount it and crash the kernel */
/* XXX: the 0 is an utter hack --hch */
gd = get_gendisk(mk_kdev(major, 0));
if (gd != NULL) {
int j;
for (j = 1 + (minor << gd->minor_shift);
j < ((minor + 1) << gd->minor_shift); j++)
gd->part[j].nr_sects = 0;
}
raid[device].disk[i].device = mk_kdev(major, minor);
raid[device].disk[i].sectors = maxsectors(major, minor);
raid[device].stride = (1 << prom.raid0_shift);
......@@ -367,10 +310,6 @@ static __init int hptraid_init_one(int device)
fill_cutoff(device);
/* Initialize the gendisk structure */
ataraid_register_disk(device, raid[device].sectors);
count = 0;
printk(KERN_INFO
"Highpoint HPT370 Softwareraid driver for linux version 0.01\n");
......@@ -383,6 +322,7 @@ static __init int hptraid_init_one(int device)
}
}
if (count) {
ataraid_register_disk(device, raid[device].sectors);
printk(KERN_INFO "Raid array consists of %i drives. \n",
count);
return 0;
......@@ -414,11 +354,15 @@ static void __exit hptraid_exit(void)
struct block_device *bdev =
raid[device].disk[i].bdev;
raid[device].disk[i].bdev = NULL;
if (bdev)
if (bdev) {
bd_release(bdev);
blkdev_put(bdev, BDEV_RAW);
}
}
if (raid[device].sectors)
if (raid[device].sectors) {
ataraid_unregister_disk(device);
ataraid_release_device(device);
}
}
}
......
......@@ -103,118 +103,18 @@ static struct pdcraid raid[16];
static int pdcraid_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned int minor;
unsigned long sectors;
if (!inode || kdev_none(inode->i_rdev))
unsigned int minor = minor(inode->i_rdev) >> SHIFT;
struct hd_geometry *geometry = (struct hd_geometry *) arg;
struct hd_geometry g;
if (cmd != HDIO_GETGEO)
return -EINVAL;
minor = minor(inode->i_rdev) >> SHIFT;
switch (cmd) {
case BLKGETSIZE: /* Return device size */
if (!arg)
return -EINVAL;
sectors =
ataraid_gendisk.part[minor(inode->i_rdev)].nr_sects;
if (minor(inode->i_rdev) & 15)
return put_user(sectors, (unsigned long *) arg);
return put_user(raid[minor].sectors,
(unsigned long *) arg);
break;
case HDIO_GETGEO:
{
struct hd_geometry *loc =
(struct hd_geometry *) arg;
unsigned short bios_cyl = raid[minor].geom.cylinders; /* truncate */
if (!loc)
return -EINVAL;
if (put_user
(raid[minor].geom.heads,
(u8 *) & loc->heads))
return -EFAULT;
if (put_user
(raid[minor].geom.sectors,
(u8 *) & loc->sectors))
return -EFAULT;
if (put_user
(bios_cyl, (unsigned short *) &loc->cylinders))
return -EFAULT;
if (put_user
((unsigned) ataraid_gendisk.
part[minor(inode->i_rdev)].start_sect,
(unsigned long *) &loc->start))
return -EFAULT;
return 0;
}
default:
printk("Invalid ioctl \n");
return -EINVAL;
};
return 0;
}
unsigned long partition_map_normal(unsigned long block,
unsigned long partition_off,
unsigned long partition_size,
int stride)
{
return block + partition_off;
}
unsigned long partition_map_linux(unsigned long block,
unsigned long partition_off,
unsigned long partition_size, int stride)
{
unsigned long newblock;
newblock = stride - (partition_off % stride);
if (newblock == stride)
newblock = 0;
newblock += block;
newblock = newblock % partition_size;
newblock += partition_off;
return newblock;
}
static int funky_remap[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
unsigned long partition_map_linux_raid0_4disk(unsigned long block,
unsigned long partition_off,
unsigned long partition_size,
int stride)
{
unsigned long newblock, temp, temp2;
newblock = stride - (partition_off % stride);
if (newblock == stride)
newblock = 0;
if (block < (partition_size / (8 * stride)) * 8 * stride) {
temp = block % stride;
temp2 = block / stride;
temp2 = ((temp2 >> 3) << 3) | (funky_remap[temp2 & 7]);
block = temp2 * stride + temp;
}
newblock += block;
newblock = newblock % partition_size;
newblock += partition_off;
return newblock;
g.heads = raid[minor].geom.heads;
g.sectors = raid[minor].geom.sectors;
g.cylinders = raid[minor].geom.cylinders;
g.start = get_start_sect(inode->i_bdev);
return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
}
static int pdcraid0_make_request(request_queue_t * q, int rw,
struct buffer_head *bh)
{
......@@ -240,20 +140,11 @@ static int pdcraid0_make_request(request_queue_t * q, int rw,
* point, we have to divide by one less.
*/
device = (bh->b_rdev >> SHIFT) & MAJOR_MASK;
device = minor(bh->b_rdev) >> SHIFT;
thisraid = &raid[device];
if (thisraid->stride == 0)
thisraid->stride = 1;
/* Partitions need adding of the start sector of the partition to the requested sector */
rsect =
partition_map_normal(rsect,
ataraid_gendisk.part[MINOR(bh->b_rdev)].
start_sect,
ataraid_gendisk.part[MINOR(bh->b_rdev)].
nr_sects, thisraid->stride);
/* Woops we need to split the request to avoid crossing a stride barrier */
if ((rsect / thisraid->stride) !=
((rsect + (bh->b_size / 512) - 1) / thisraid->stride)) {
......@@ -320,7 +211,7 @@ static int pdcraid1_write_request(request_queue_t * q, int rw,
int device;
int i;
device = (bh->b_rdev >> SHIFT) & MAJOR_MASK;
device = minor(bh->b_rdev) >> SHIFT;
private = ataraid_get_private();
if (private == NULL)
BUG();
......@@ -341,7 +232,6 @@ static int pdcraid1_write_request(request_queue_t * q, int rw,
bh1->b_end_io = ataraid_end_request;
bh1->b_private = private;
bh1->b_rsector += ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect; /* partition offset */
bh1->b_rdev = raid[device].disk[i].device;
/* update the last known head position for the drive */
......@@ -361,15 +251,13 @@ static int pdcraid1_read_request(request_queue_t * q, int rw,
int bestsofar, bestdist, i;
static int previous;
device = minor(bh->b_rdev) >> SHIFT;
/* Reads are simple in principle. Pick a disk and go.
Initially I cheat by just picking the one which the last known
head position is closest by.
Later on, online/offline checking and performance needs adding */
device = (bh->b_rdev >> SHIFT) & MAJOR_MASK;
bh->b_rsector +=
ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect;
bestsofar = 0;
bestdist = raid[device].disk[0].last_pos - bh->b_rsector;
if (bestdist < 0)
......@@ -575,6 +463,7 @@ static void __init fill_cutoff(int device)
static __init int pdcraid_init_one(int device, int raidlevel)
{
int i, count;
struct pdcraid *p = raid + device;
for (i = 0; i < 14; i++)
probedisk(i, device, raidlevel);
......@@ -582,22 +471,19 @@ static __init int pdcraid_init_one(int device, int raidlevel)
if (raidlevel == 0)
fill_cutoff(device);
/* Initialize the gendisk structure */
ataraid_register_disk(device, raid[device].sectors);
count = 0;
for (i = 0; i < 8; i++) {
if (raid[device].disk[i].device != 0) {
if (p->disk[i].device != 0) {
printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n",
i, raid[device].disk[i].sectors / 2048,
major(raid[device].disk[i].device),
minor(raid[device].disk[i].device));
i, p->disk[i].sectors / 2048,
major(p->disk[i].device),
minor(p->disk[i].device));
count++;
}
}
if (count) {
ataraid_register_disk(device, p->sectors);
printk(KERN_INFO "Raid%i array consists of %i drives. \n",
raidlevel, count);
return 0;
......@@ -660,8 +546,10 @@ static void __exit pdcraid_exit(void)
if (bdev)
blkdev_put(bdev, BDEV_RAW);
}
if (raid[device].sectors)
if (raid[device].sectors) {
ataraid_unregister_disk(device);
ataraid_release_device(device);
}
}
}
......
......@@ -137,10 +137,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
sprintf(s, "%s%d", "md", unit);
maj = s;
break;
case ATARAID_MAJOR:
sprintf(s, "ataraid/d%d", unit);
maj = s;
break;
case ACSI_MAJOR:
case I2O_MAJOR:
case DASD_MAJOR:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment