Commit 443ac9b2 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] beginning of probe_disk() and gendisks for floppy

That's a tricky one and large part of that stuff is temporary - it will be
replaced as soon as we have gendisks for all block devices and get sane
refcounting for gendisks.
	* we add per-major lists of gendisks; get_gendisk() looks into
appropriate list instead of looking through the list of all gendisks.
	* we allow driver to override that search - it can call
blk_set_probe(major, probe) and then gendisk will call probe(minor).
blk_set_probe(major, NULL) restores the default behaviour.
	* floppy.c switched to use of gendisks; we have one gendisk per
disk and let floppy_find(minor) return the right one.
	Note that final mechanism will involve a similar construction
but floppy.c is actually the least interesting application - places
where it will really play will include stuff like loading the right
high-level driver when we open /dev/hdX, etc.  And it won't be major-based...
parent ceb1ee4c
...@@ -416,6 +416,8 @@ static struct floppy_drive_params drive_params[N_DRIVE]; ...@@ -416,6 +416,8 @@ static struct floppy_drive_params drive_params[N_DRIVE];
static struct floppy_drive_struct drive_state[N_DRIVE]; static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE];
static struct gendisk disks[N_DRIVE];
static char names[N_DRIVE][4];
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
/* /*
...@@ -3775,6 +3777,7 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3775,6 +3777,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
} }
UDRS->fd_device = minor(inode->i_rdev); UDRS->fd_device = minor(inode->i_rdev);
set_capacity(&disks[drive], floppy_sizes[minor(inode->i_rdev)]);
if (old_dev != -1 && old_dev != minor(inode->i_rdev)) { if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive) if (buffer_drive == drive)
buffer_track = -1; buffer_track = -1;
...@@ -3952,6 +3955,7 @@ static int floppy_revalidate(kdev_t dev) ...@@ -3952,6 +3955,7 @@ static int floppy_revalidate(kdev_t dev)
poll_drive(0, FD_RAW_NEED_DISK); poll_drive(0, FD_RAW_NEED_DISK);
process_fd_request(); process_fd_request();
} }
set_capacity(&disks[drive], floppy_sizes[minor(dev)]);
return 0; return 0;
} }
...@@ -4219,6 +4223,16 @@ static struct device device_floppy = { ...@@ -4219,6 +4223,16 @@ static struct device device_floppy = {
bus_id: "03?0", bus_id: "03?0",
}; };
static struct gendisk *floppy_find(int minor)
{
int drive = (minor&3) | ((minor&0x80) >> 5);
if (drive >= N_DRIVE ||
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL;
return &disks[drive];
}
int __init floppy_init(void) int __init floppy_init(void)
{ {
int i,unit,drive; int i,unit,drive;
...@@ -4231,13 +4245,22 @@ int __init floppy_init(void) ...@@ -4231,13 +4245,22 @@ int __init floppy_init(void)
return -EBUSY; return -EBUSY;
} }
for (i=0; i<N_DRIVE; i++) {
disks[i].major = MAJOR_NR;
disks[i].first_minor = TOMINOR(i);
disks[i].fops = &floppy_fops;
sprintf(names[i], "fd%d", i);
disks[i].major_name = names[i];
}
blk_set_probe(MAJOR_NR, floppy_find);
for (i=0; i<256; i++) for (i=0; i<256; i++)
if (ITYPE(i)) if (ITYPE(i))
floppy_sizes[i] = (floppy_type[ITYPE(i)].size+1) >> 1; floppy_sizes[i] = (floppy_type[ITYPE(i)].size+1) >> 1;
else else
floppy_sizes[i] = MAX_DISK_SIZE; floppy_sizes[i] = MAX_DISK_SIZE;
blk_size[MAJOR_NR] = floppy_sizes;
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &floppy_lock); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &floppy_lock);
reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT); reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
config_types(); config_types();
...@@ -4262,6 +4285,7 @@ int __init floppy_init(void) ...@@ -4262,6 +4285,7 @@ int __init floppy_init(void)
unregister_blkdev(MAJOR_NR,"fd"); unregister_blkdev(MAJOR_NR,"fd");
del_timer(&fd_timeout); del_timer(&fd_timeout);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
blk_set_probe(MAJOR_NR, NULL);
return -ENODEV; return -ENODEV;
} }
#if N_FDC > 1 #if N_FDC > 1
...@@ -4273,6 +4297,7 @@ int __init floppy_init(void) ...@@ -4273,6 +4297,7 @@ int __init floppy_init(void)
del_timer(&fd_timeout); del_timer(&fd_timeout);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR,"fd"); unregister_blkdev(MAJOR_NR,"fd");
blk_set_probe(MAJOR_NR, NULL);
return -EBUSY; return -EBUSY;
} }
...@@ -4336,6 +4361,7 @@ int __init floppy_init(void) ...@@ -4336,6 +4361,7 @@ int __init floppy_init(void)
floppy_release_irq_and_dma(); floppy_release_irq_and_dma();
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR,"fd"); unregister_blkdev(MAJOR_NR,"fd");
blk_set_probe(MAJOR_NR, NULL);
} }
for (drive = 0; drive < N_DRIVE; drive++) { for (drive = 0; drive < N_DRIVE; drive++) {
...@@ -4345,9 +4371,7 @@ int __init floppy_init(void) ...@@ -4345,9 +4371,7 @@ int __init floppy_init(void)
continue; continue;
if (fdc_state[FDC(drive)].version == FDC_NONE) if (fdc_state[FDC(drive)].version == FDC_NONE)
continue; continue;
for (i = 0; i<NUMBER(floppy_type); i++) add_disk(disks + drive);
register_disk(NULL, mk_kdev(MAJOR_NR,TOMINOR(drive)+i*4),
1, &floppy_fops, 0);
} }
register_sys_device(&device_floppy); register_sys_device(&device_floppy);
...@@ -4532,15 +4556,21 @@ int init_module(void) ...@@ -4532,15 +4556,21 @@ int init_module(void)
void cleanup_module(void) void cleanup_module(void)
{ {
int dummy; int i;
unregister_sys_device(&device_floppy); unregister_sys_device(&device_floppy);
devfs_unregister (devfs_handle); devfs_unregister (devfs_handle);
unregister_blkdev(MAJOR_NR, "fd"); unregister_blkdev(MAJOR_NR, "fd");
blk_set_probe(MAJOR_NR, NULL);
for (drive = 0; drive < N_DRIVE; drive++) {
if ((allowed_drive_mask & (1 << drive)) &&
fdc_state[FDC(drive)].version != FDC_NONE)
del_gendisk(disks + drive);
}
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
/* eject disk, if any */ /* eject disk, if any */
dummy = fd_eject(0); fd_eject(0);
} }
MODULE_PARM(floppy,"s"); MODULE_PARM(floppy,"s");
......
...@@ -33,6 +33,23 @@ static rwlock_t gendisk_lock; ...@@ -33,6 +33,23 @@ static rwlock_t gendisk_lock;
*/ */
static struct gendisk *gendisk_head; static struct gendisk *gendisk_head;
/*
* TEMPORARY KLUDGE.
*/
static struct {
struct list_head list;
struct gendisk *(*get)(int minor);
} gendisks[MAX_BLKDEV];
void blk_set_probe(int major, struct gendisk *(p)(int))
{
write_lock(&gendisk_lock);
gendisks[major].get = p;
write_unlock(&gendisk_lock);
}
EXPORT_SYMBOL(blk_set_probe); /* Will go away */
/** /**
* add_gendisk - add partitioning information to kernel list * add_gendisk - add partitioning information to kernel list
* @gp: per-device partitioning information * @gp: per-device partitioning information
...@@ -42,7 +59,6 @@ static struct gendisk *gendisk_head; ...@@ -42,7 +59,6 @@ static struct gendisk *gendisk_head;
*/ */
static void add_gendisk(struct gendisk *gp) static void add_gendisk(struct gendisk *gp)
{ {
struct gendisk *sgp;
struct hd_struct *p = NULL; struct hd_struct *p = NULL;
if (gp->minor_shift) { if (gp->minor_shift) {
...@@ -58,24 +74,9 @@ static void add_gendisk(struct gendisk *gp) ...@@ -58,24 +74,9 @@ static void add_gendisk(struct gendisk *gp)
gp->part = p; gp->part = p;
write_lock(&gendisk_lock); write_lock(&gendisk_lock);
list_add(&gp->list, &gendisks[gp->major].list);
/*
* In 2.5 this will go away. Fix the drivers who rely on
* old behaviour.
*/
for (sgp = gendisk_head; sgp; sgp = sgp->next)
{
if (sgp == gp)
{
printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
sgp->major);
goto out;
}
}
gp->next = gendisk_head; gp->next = gendisk_head;
gendisk_head = gp; gendisk_head = gp;
out:
write_unlock(&gendisk_lock); write_unlock(&gendisk_lock);
} }
...@@ -98,6 +99,7 @@ void unlink_gendisk(struct gendisk *disk) ...@@ -98,6 +99,7 @@ void unlink_gendisk(struct gendisk *disk)
break; break;
if (*p) if (*p)
*p = (*p)->next; *p = (*p)->next;
list_del_init(&disk->list);
write_unlock(&gendisk_lock); write_unlock(&gendisk_lock);
} }
...@@ -111,20 +113,25 @@ void unlink_gendisk(struct gendisk *disk) ...@@ -111,20 +113,25 @@ void unlink_gendisk(struct gendisk *disk)
struct gendisk * struct gendisk *
get_gendisk(kdev_t dev) get_gendisk(kdev_t dev)
{ {
struct gendisk *gp = NULL; struct gendisk *disk;
struct list_head *p;
int major = major(dev); int major = major(dev);
int minor = minor(dev); int minor = minor(dev);
read_lock(&gendisk_lock); read_lock(&gendisk_lock);
for (gp = gendisk_head; gp; gp = gp->next) { if (gendisks[major].get) {
if (gp->major != major) disk = gendisks[major].get(minor);
continue; read_unlock(&gendisk_lock);
if (gp->first_minor > minor) return disk;
}
list_for_each(p, &gendisks[major].list) {
disk = list_entry(p, struct gendisk, list);
if (disk->first_minor > minor)
continue; continue;
if (gp->first_minor + (1<<gp->minor_shift) <= minor) if (disk->first_minor + (1<<disk->minor_shift) <= minor)
continue; continue;
read_unlock(&gendisk_lock); read_unlock(&gendisk_lock);
return gp; return disk;
} }
read_unlock(&gendisk_lock); read_unlock(&gendisk_lock);
return NULL; return NULL;
...@@ -200,7 +207,10 @@ extern int cpqarray_init(void); ...@@ -200,7 +207,10 @@ extern int cpqarray_init(void);
int __init device_init(void) int __init device_init(void)
{ {
int i;
rwlock_init(&gendisk_lock); rwlock_init(&gendisk_lock);
for (i = 0; i < MAX_BLKDEV; i++)
INIT_LIST_HEAD(&gendisks[i].list);
blk_dev_init(); blk_dev_init();
#ifdef CONFIG_FC4_SOC #ifdef CONFIG_FC4_SOC
/* This has to be done before scsi_dev_init */ /* This has to be done before scsi_dev_init */
......
...@@ -81,6 +81,7 @@ struct gendisk { ...@@ -81,6 +81,7 @@ struct gendisk {
struct gendisk *next; struct gendisk *next;
struct block_device_operations *fops; struct block_device_operations *fops;
sector_t capacity; sector_t capacity;
struct list_head list;
int flags; int flags;
int number; /* devfs crap */ int number; /* devfs crap */
...@@ -260,6 +261,9 @@ char *disk_name (struct gendisk *hd, int part, char *buf); ...@@ -260,6 +261,9 @@ char *disk_name (struct gendisk *hd, int part, char *buf);
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
extern void update_partition(struct gendisk *disk, int part); extern void update_partition(struct gendisk *disk, int part);
/* will go away */
extern void blk_set_probe(int major, struct gendisk *(p)(int));
static inline unsigned int disk_index (kdev_t dev) static inline unsigned int disk_index (kdev_t dev)
{ {
struct gendisk *g = get_gendisk(dev); struct gendisk *g = get_gendisk(dev);
......
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