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 @@ ...@@ -28,6 +28,7 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/buffer_head.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -44,7 +45,9 @@ static void ataraid_split_request(request_queue_t * q, int rw, ...@@ -44,7 +45,9 @@ static void ataraid_split_request(request_queue_t * q, int rw,
struct buffer_head *bh); 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 int ataraid_readahead[256];
static struct block_device_operations ataraid_fops = { static struct block_device_operations ataraid_fops = {
...@@ -229,9 +232,28 @@ void ataraid_release_device(int device) ...@@ -229,9 +232,28 @@ void ataraid_release_device(int device)
void ataraid_register_disk(int device, long size) void ataraid_register_disk(int device, long size)
{ {
register_disk(&ataraid_gendisk, mk_kdev(ATAMAJOR, 16 * device), 16, struct gendisk *disk = ataraid_gendisk + device;
&ataraid_fops, size); 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) static __init int ataraid_init(void)
...@@ -241,61 +263,44 @@ static __init int ataraid_init(void) ...@@ -241,61 +263,44 @@ static __init int ataraid_init(void)
ataraid_readahead[i] = 1023; ataraid_readahead[i] = 1023;
/* setup the gendisk structure */ /* setup the gendisk structure */
ataraid_gendisk.part = ataraid_part = kmalloc(256 * sizeof(struct hd_struct), GFP_KERNEL);
kmalloc(256 * sizeof(struct hd_struct), GFP_KERNEL); ataraid_names = kmalloc(16 * 12, GFP_KERNEL);
if (ataraid_gendisk.part == NULL) { if (!ataraid_part || !ataraid_names) {
kfree(ataraid_part);
kfree(ataraid_names);
printk(KERN_ERR printk(KERN_ERR
"ataraid: Couldn't allocate memory, aborting \n"); "ataraid: Couldn't allocate memory, aborting \n");
return -1; return -1;
} }
memset(&ataraid_gendisk.part[0], 0, memset(ataraid_part, 0, 256 * sizeof(struct hd_struct));
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);
if (register_blkdev(ATAMAJOR, "ataraid", &ataraid_fops)) { if (register_blkdev(ATAMAJOR, "ataraid", &ataraid_fops)) {
kfree(ataraid_part);
kfree(ataraid_names);
printk(KERN_ERR "ataraid: Could not get major %d \n", printk(KERN_ERR "ataraid: Could not get major %d \n",
ATAMAJOR); ATAMAJOR);
return -1; return -1;
} }
blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR), blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR),
ataraid_make_request); ataraid_make_request);
return 0; return 0;
} }
static void __exit ataraid_exit(void) static void __exit ataraid_exit(void)
{ {
unregister_blkdev(ATAMAJOR, "ataraid"); unregister_blkdev(ATAMAJOR, "ataraid");
kfree(ataraid_part);
del_gendisk(&ataraid_gendisk); kfree(ataraid_names);
if (ataraid_gendisk.part) {
kfree(ataraid_gendisk.part);
ataraid_gendisk.part = NULL;
}
} }
module_init(ataraid_init); module_init(ataraid_init);
module_exit(ataraid_exit); module_exit(ataraid_exit);
EXPORT_SYMBOL(ataraid_get_device); EXPORT_SYMBOL(ataraid_get_device);
EXPORT_SYMBOL(ataraid_release_device); EXPORT_SYMBOL(ataraid_release_device);
EXPORT_SYMBOL(ataraid_gendisk);
EXPORT_SYMBOL(ataraid_register_disk); EXPORT_SYMBOL(ataraid_register_disk);
EXPORT_SYMBOL(ataraid_unregister_disk);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -56,17 +56,10 @@ struct ataraid_bh_private { ...@@ -56,17 +56,10 @@ struct ataraid_bh_private {
atomic_t count; atomic_t count;
}; };
extern struct gendisk ataraid_gendisk;
extern int ataraid_get_device(struct raid_device_operations *fops); extern int ataraid_get_device(struct raid_device_operations *fops);
extern void ataraid_release_device(int device); 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_register_disk(int device,long size);
extern void ataraid_unregister_disk(int device);
extern struct buffer_head *ataraid_get_bhead(void); extern struct buffer_head *ataraid_get_bhead(void);
extern struct ataraid_bh_private *ataraid_get_private(void); extern struct ataraid_bh_private *ataraid_get_private(void);
extern void ataraid_end_request(struct buffer_head *bh, int uptodate); extern void ataraid_end_request(struct buffer_head *bh, int uptodate);
...@@ -74,62 +74,20 @@ static struct hptraid raid[16]; ...@@ -74,62 +74,20 @@ static struct hptraid raid[16];
static int hptraid_ioctl(struct inode *inode, struct file *file, static int hptraid_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
unsigned int minor; unsigned int minor = minor(inode->i_rdev) >> SHIFT;
unsigned char val; struct hd_geometry *geometry = (struct hd_geometry *) arg;
unsigned long sectors; struct hd_geometry g;
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;
}
default: if (cmd != HDIO_GETGEO)
return -EINVAL; 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, static int hptraid_make_request(request_queue_t * q, int rw,
struct buffer_head *bh) struct buffer_head *bh)
{ {
...@@ -160,10 +118,6 @@ static int hptraid_make_request(request_queue_t * q, int rw, ...@@ -160,10 +118,6 @@ static int hptraid_make_request(request_queue_t * q, int rw,
if (thisraid->stride == 0) if (thisraid->stride == 0)
thisraid->stride = 1; 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 */ /* Woops we need to split the request to avoid crossing a stride barrier */
if ((rsect / thisraid->stride) != if ((rsect / thisraid->stride) !=
((rsect + (bh->b_size / 512) - 1) / thisraid->stride)) { ((rsect + (bh->b_size / 512) - 1) / thisraid->stride)) {
...@@ -273,7 +227,6 @@ static void __init probedisk(int major, int minor, int device) ...@@ -273,7 +227,6 @@ static void __init probedisk(int major, int minor, int device)
{ {
int i; int i;
struct block_device *bdev = bdget(mk_kdev(major, minor)); struct block_device *bdev = bdget(mk_kdev(major, minor));
struct gendisk *gd;
if (!bdev) if (!bdev)
return; return;
...@@ -301,19 +254,9 @@ static void __init probedisk(int major, int minor, int device) ...@@ -301,19 +254,9 @@ static void __init probedisk(int major, int minor, int device)
if (i > 8) if (i > 8)
goto out; goto out;
if (bd_claim(bdev, &raid[device].disk[i]) < 0)
goto out;
raid[device].disk[i].bdev = bdev; 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].device = mk_kdev(major, minor);
raid[device].disk[i].sectors = maxsectors(major, minor); raid[device].disk[i].sectors = maxsectors(major, minor);
raid[device].stride = (1 << prom.raid0_shift); raid[device].stride = (1 << prom.raid0_shift);
...@@ -367,10 +310,6 @@ static __init int hptraid_init_one(int device) ...@@ -367,10 +310,6 @@ static __init int hptraid_init_one(int device)
fill_cutoff(device); fill_cutoff(device);
/* Initialize the gendisk structure */
ataraid_register_disk(device, raid[device].sectors);
count = 0; count = 0;
printk(KERN_INFO printk(KERN_INFO
"Highpoint HPT370 Softwareraid driver for linux version 0.01\n"); "Highpoint HPT370 Softwareraid driver for linux version 0.01\n");
...@@ -383,6 +322,7 @@ static __init int hptraid_init_one(int device) ...@@ -383,6 +322,7 @@ static __init int hptraid_init_one(int device)
} }
} }
if (count) { if (count) {
ataraid_register_disk(device, raid[device].sectors);
printk(KERN_INFO "Raid array consists of %i drives. \n", printk(KERN_INFO "Raid array consists of %i drives. \n",
count); count);
return 0; return 0;
...@@ -414,12 +354,16 @@ static void __exit hptraid_exit(void) ...@@ -414,12 +354,16 @@ static void __exit hptraid_exit(void)
struct block_device *bdev = struct block_device *bdev =
raid[device].disk[i].bdev; raid[device].disk[i].bdev;
raid[device].disk[i].bdev = NULL; raid[device].disk[i].bdev = NULL;
if (bdev) if (bdev) {
bd_release(bdev);
blkdev_put(bdev, BDEV_RAW); blkdev_put(bdev, BDEV_RAW);
} }
if (raid[device].sectors) }
if (raid[device].sectors) {
ataraid_unregister_disk(device);
ataraid_release_device(device); ataraid_release_device(device);
} }
}
} }
static int hptraid_open(struct inode *inode, struct file *filp) static int hptraid_open(struct inode *inode, struct file *filp)
......
...@@ -103,118 +103,18 @@ static struct pdcraid raid[16]; ...@@ -103,118 +103,18 @@ static struct pdcraid raid[16];
static int pdcraid_ioctl(struct inode *inode, struct file *file, static int pdcraid_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
unsigned int minor; unsigned int minor = minor(inode->i_rdev) >> SHIFT;
unsigned long sectors; struct hd_geometry *geometry = (struct hd_geometry *) arg;
struct hd_geometry g;
if (!inode || kdev_none(inode->i_rdev)) if (cmd != HDIO_GETGEO)
return -EINVAL;
minor = minor(inode->i_rdev) >> SHIFT;
switch (cmd) {
case BLKGETSIZE: /* Return device size */
if (!arg)
return -EINVAL; return -EINVAL;
sectors = g.heads = raid[minor].geom.heads;
ataraid_gendisk.part[minor(inode->i_rdev)].nr_sects; g.sectors = raid[minor].geom.sectors;
if (minor(inode->i_rdev) & 15) g.cylinders = raid[minor].geom.cylinders;
return put_user(sectors, (unsigned long *) arg); g.start = get_start_sect(inode->i_bdev);
return put_user(raid[minor].sectors, return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
(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;
}
static int pdcraid0_make_request(request_queue_t * q, int rw, static int pdcraid0_make_request(request_queue_t * q, int rw,
struct buffer_head *bh) struct buffer_head *bh)
{ {
...@@ -240,20 +140,11 @@ static int pdcraid0_make_request(request_queue_t * q, int rw, ...@@ -240,20 +140,11 @@ static int pdcraid0_make_request(request_queue_t * q, int rw,
* point, we have to divide by one less. * point, we have to divide by one less.
*/ */
device = (bh->b_rdev >> SHIFT) & MAJOR_MASK; device = minor(bh->b_rdev) >> SHIFT;
thisraid = &raid[device]; thisraid = &raid[device];
if (thisraid->stride == 0) if (thisraid->stride == 0)
thisraid->stride = 1; 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 */ /* Woops we need to split the request to avoid crossing a stride barrier */
if ((rsect / thisraid->stride) != if ((rsect / thisraid->stride) !=
((rsect + (bh->b_size / 512) - 1) / 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, ...@@ -320,7 +211,7 @@ static int pdcraid1_write_request(request_queue_t * q, int rw,
int device; int device;
int i; int i;
device = (bh->b_rdev >> SHIFT) & MAJOR_MASK; device = minor(bh->b_rdev) >> SHIFT;
private = ataraid_get_private(); private = ataraid_get_private();
if (private == NULL) if (private == NULL)
BUG(); BUG();
...@@ -341,7 +232,6 @@ static int pdcraid1_write_request(request_queue_t * q, int rw, ...@@ -341,7 +232,6 @@ static int pdcraid1_write_request(request_queue_t * q, int rw,
bh1->b_end_io = ataraid_end_request; bh1->b_end_io = ataraid_end_request;
bh1->b_private = private; 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; bh1->b_rdev = raid[device].disk[i].device;
/* update the last known head position for the drive */ /* update the last known head position for the drive */
...@@ -361,15 +251,13 @@ static int pdcraid1_read_request(request_queue_t * q, int rw, ...@@ -361,15 +251,13 @@ static int pdcraid1_read_request(request_queue_t * q, int rw,
int bestsofar, bestdist, i; int bestsofar, bestdist, i;
static int previous; static int previous;
device = minor(bh->b_rdev) >> SHIFT;
/* Reads are simple in principle. Pick a disk and go. /* Reads are simple in principle. Pick a disk and go.
Initially I cheat by just picking the one which the last known Initially I cheat by just picking the one which the last known
head position is closest by. head position is closest by.
Later on, online/offline checking and performance needs adding */ 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; bestsofar = 0;
bestdist = raid[device].disk[0].last_pos - bh->b_rsector; bestdist = raid[device].disk[0].last_pos - bh->b_rsector;
if (bestdist < 0) if (bestdist < 0)
...@@ -575,6 +463,7 @@ static void __init fill_cutoff(int device) ...@@ -575,6 +463,7 @@ static void __init fill_cutoff(int device)
static __init int pdcraid_init_one(int device, int raidlevel) static __init int pdcraid_init_one(int device, int raidlevel)
{ {
int i, count; int i, count;
struct pdcraid *p = raid + device;
for (i = 0; i < 14; i++) for (i = 0; i < 14; i++)
probedisk(i, device, raidlevel); probedisk(i, device, raidlevel);
...@@ -582,22 +471,19 @@ static __init int pdcraid_init_one(int device, int raidlevel) ...@@ -582,22 +471,19 @@ static __init int pdcraid_init_one(int device, int raidlevel)
if (raidlevel == 0) if (raidlevel == 0)
fill_cutoff(device); fill_cutoff(device);
/* Initialize the gendisk structure */
ataraid_register_disk(device, raid[device].sectors);
count = 0; count = 0;
for (i = 0; i < 8; i++) { 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", printk(KERN_INFO "Drive %i is %li Mb (%i / %i) \n",
i, raid[device].disk[i].sectors / 2048, i, p->disk[i].sectors / 2048,
major(raid[device].disk[i].device), major(p->disk[i].device),
minor(raid[device].disk[i].device)); minor(p->disk[i].device));
count++; count++;
} }
} }
if (count) { if (count) {
ataraid_register_disk(device, p->sectors);
printk(KERN_INFO "Raid%i array consists of %i drives. \n", printk(KERN_INFO "Raid%i array consists of %i drives. \n",
raidlevel, count); raidlevel, count);
return 0; return 0;
...@@ -660,9 +546,11 @@ static void __exit pdcraid_exit(void) ...@@ -660,9 +546,11 @@ static void __exit pdcraid_exit(void)
if (bdev) if (bdev)
blkdev_put(bdev, BDEV_RAW); blkdev_put(bdev, BDEV_RAW);
} }
if (raid[device].sectors) if (raid[device].sectors) {
ataraid_unregister_disk(device);
ataraid_release_device(device); ataraid_release_device(device);
} }
}
} }
static int pdcraid_open(struct inode *inode, struct file *filp) static int pdcraid_open(struct inode *inode, struct file *filp)
......
...@@ -137,10 +137,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf) ...@@ -137,10 +137,6 @@ char *disk_name (struct gendisk *hd, int minor, char *buf)
sprintf(s, "%s%d", "md", unit); sprintf(s, "%s%d", "md", unit);
maj = s; maj = s;
break; break;
case ATARAID_MAJOR:
sprintf(s, "ataraid/d%d", unit);
maj = s;
break;
case ACSI_MAJOR: case ACSI_MAJOR:
case I2O_MAJOR: case I2O_MAJOR:
case DASD_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