Commit 5682bcc6 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] bdev->bd_disk introduced

There we go - now we can put a reference to gendisk into block_device.  Which
we do in do_open().  Most of the callers of get_gendisk() are simply using
bdev->bd_disk now (and most of the put_disk() calls introduced on previous
step disappear).  We also put that pointer into struct request - ->rq_disk.
That allows to get rid of disk_index() kludges in md.c (we simply count
relevant IO in the struct gendisk fields) and kill the export of get_gendisk().
	Notice that by now we can move _all_ IO counters into gendisk.  That
will kill a bunch of per-major arrays and more importantly, allow to merge
sard in clean way.  FWIW, we probably could show them as disk/partitions
attributes in driverfs...
parent 68c16870
......@@ -61,10 +61,7 @@ void add_disk(struct gendisk *disk)
{
write_lock(&gendisk_lock);
list_add(&disk->list, &gendisks[disk->major].list);
if (disk->minors > 1)
list_add_tail(&disk->full_list, &gendisk_list);
else
INIT_LIST_HEAD(&disk->full_list);
list_add_tail(&disk->full_list, &gendisk_list);
write_unlock(&gendisk_lock);
disk->flags |= GENHD_FL_UP;
register_disk(disk);
......@@ -120,8 +117,6 @@ get_gendisk(dev_t dev, int *part)
return NULL;
}
EXPORT_SYMBOL(get_gendisk);
#ifdef CONFIG_PROC_FS
/* iterator */
static void *part_start(struct seq_file *part, loff_t *pos)
......@@ -158,7 +153,7 @@ static int show_partition(struct seq_file *part, void *v)
seq_puts(part, "major minor #blocks name\n\n");
/* Don't show non-partitionable devices or empty devices */
if (!get_capacity(sgp))
if (!get_capacity(sgp) || sgp->minors == 1)
return 0;
/* show the full disk and all non-0 size partitions of it */
......@@ -239,6 +234,7 @@ struct gendisk *alloc_disk(int minors)
disk->minors = minors;
while (minors >>= 1)
disk->minor_shift++;
INIT_LIST_HEAD(&disk->full_list);
disk->disk_dev.bus = &disk_bus;
disk->disk_dev.release = disk_release;
disk->disk_dev.driver_data = disk;
......
......@@ -22,21 +22,12 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
return -EFAULT;
if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
return -EFAULT;
disk = get_gendisk(bdev->bd_dev, &part);
if (!disk)
return -ENXIO;
if (bdev != bdev->bd_contains) {
put_disk(disk);
disk = bdev->bd_disk;
if (bdev != bdev->bd_contains)
return -EINVAL;
}
if (part)
BUG();
part = p.pno;
if (part <= 0 || part >= disk->minors) {
put_disk(disk);
if (part <= 0 || part >= disk->minors)
return -EINVAL;
}
switch (a.op) {
case BLKPG_ADD_PARTITION:
start = p.start >> 9;
......@@ -46,49 +37,33 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
sizeof(long long) > sizeof(long)) {
long pstart = start, plength = length;
if (pstart != start || plength != length
|| pstart < 0 || plength < 0) {
put_disk(disk);
|| pstart < 0 || plength < 0)
return -EINVAL;
}
}
/* partition number in use? */
if (disk->part[part - 1].nr_sects != 0) {
put_disk(disk);
if (disk->part[part - 1].nr_sects != 0)
return -EBUSY;
}
/* overlap? */
for (i = 0; i < disk->minors - 1; i++) {
struct hd_struct *s = &disk->part[i];
if (!(start+length <= s->start_sect ||
start >= s->start_sect + s->nr_sects)) {
put_disk(disk);
start >= s->start_sect + s->nr_sects))
return -EBUSY;
}
}
/* all seems OK */
add_partition(disk, part, start, length);
put_disk(disk);
return 0;
case BLKPG_DEL_PARTITION:
if (disk->part[part - 1].nr_sects == 0) {
put_disk(disk);
if (disk->part[part - 1].nr_sects == 0)
return -ENXIO;
}
/* partition in use? Incomplete check for now. */
bdevp = bdget(MKDEV(disk->major, disk->first_minor) + part);
if (!bdevp) {
put_disk(disk);
if (!bdevp)
return -ENOMEM;
}
if (bd_claim(bdevp, &holder) < 0) {
bdput(bdevp);
put_disk(disk);
return -EBUSY;
}
/* all seems OK */
fsync_bdev(bdevp);
invalidate_bdev(bdevp, 0);
......@@ -96,39 +71,25 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg *arg)
delete_partition(disk, part);
bd_release(bdevp);
bdput(bdevp);
put_disk(disk);
return 0;
default:
put_disk(disk);
return -EINVAL;
}
}
static int blkdev_reread_part(struct block_device *bdev)
{
int part;
struct gendisk *disk = get_gendisk(bdev->bd_dev, &part);
int res = 0;
struct gendisk *disk = bdev->bd_disk;
int res;
if (!disk)
return -EINVAL;
if (disk->minors == 1 || bdev != bdev->bd_contains) {
put_disk(disk);
if (disk->minors == 1 || bdev != bdev->bd_contains)
return -EINVAL;
}
if (part)
BUG();
if (!capable(CAP_SYS_ADMIN)) {
put_disk(disk);
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
}
if (down_trylock(&bdev->bd_sem)) {
put_disk(disk);
if (down_trylock(&bdev->bd_sem))
return -EBUSY;
}
res = rescan_partitions(disk, bdev);
up(&bdev->bd_sem);
put_disk(disk);
return res;
}
......
......@@ -1427,7 +1427,19 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
int rw = rq_data_dir(rq);
unsigned int index;
index = disk_index(rq->rq_dev);
if (!rq->rq_disk)
return;
if (rw == READ) {
rq->rq_disk->rio += new_io;
rq->rq_disk->reads += nr_sectors;
} else if (rw == WRITE) {
rq->rq_disk->wio += new_io;
rq->rq_disk->writes += nr_sectors;
}
index = rq->rq_disk->first_minor >> rq->rq_disk->minor_shift;
if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
return;
......@@ -1747,6 +1759,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
req->waiting = NULL;
req->bio = req->biotail = bio;
req->rq_dev = to_kdev_t(bio->bi_bdev->bd_dev);
req->rq_disk = bio->bi_bdev->bd_disk;
add_request(q, req, insert_here);
out:
if (freereq)
......
......@@ -381,6 +381,7 @@ static int rd_open(struct inode * inode, struct file * filp)
rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops;
rd_bdev[unit]->bd_inode->i_size = rd_length[unit];
rd_bdev[unit]->bd_queue = &blk_dev[MAJOR_NR].request_queue;
rd_bdev[unit]->bd_disk = get_disk(rd_disks[unit]);
}
return 0;
......
......@@ -2731,18 +2731,9 @@ int unregister_md_personality(int pnum)
return 0;
}
static unsigned int sync_io[DK_MAX_MAJOR][DK_MAX_DISK];
void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors)
{
kdev_t dev = to_kdev_t(rdev->bdev->bd_dev);
unsigned int major = major(dev);
unsigned int index;
index = disk_index(dev);
if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
return;
sync_io[major][index] += nr_sectors;
rdev->bdev->bd_disk->sync_io += nr_sectors;
}
static int is_mddev_idle(mddev_t *mddev)
......@@ -2754,16 +2745,8 @@ static int is_mddev_idle(mddev_t *mddev)
idle = 1;
ITERATE_RDEV(mddev,rdev,tmp) {
kdev_t dev = to_kdev_t(rdev->bdev->bd_dev);
int major = major(dev);
int idx = disk_index(dev);
if ((idx >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
continue;
curr_events = kstat.dk_drive_rblk[major][idx] +
kstat.dk_drive_wblk[major][idx] ;
curr_events -= sync_io[major][idx];
struct gendisk *disk = rdev->bdev->bd_disk;
curr_events = disk->reads + disk->writes - disk->sync_io;
if ((curr_events - rdev->last_events) > 32) {
rdev->last_events = curr_events;
idle = 0;
......
......@@ -526,8 +526,6 @@ int check_disk_change(struct block_device *bdev)
{
struct block_device_operations * bdops = bdev->bd_op;
kdev_t dev = to_kdev_t(bdev->bd_dev);
struct gendisk *disk;
int part;
if (bdops->check_media_change == NULL)
return 0;
......@@ -537,26 +535,21 @@ int check_disk_change(struct block_device *bdev)
if (invalidate_device(dev, 0))
printk("VFS: busy inodes on changed media.\n");
disk = get_gendisk(bdev->bd_dev, &part);
if (bdops->revalidate)
bdops->revalidate(dev);
if (disk && disk->minors > 1)
if (bdev->bd_disk->minors > 1)
bdev->bd_invalidated = 1;
put_disk(disk);
return 1;
}
int full_check_disk_change(struct block_device *bdev)
{
int res = 0;
int n;
if (bdev->bd_contains != bdev)
BUG();
down(&bdev->bd_sem);
if (check_disk_change(bdev)) {
struct gendisk *disk = get_gendisk(bdev->bd_dev, &n);
rescan_partitions(disk, bdev);
put_disk(disk);
rescan_partitions(bdev->bd_disk, bdev);
res = 1;
}
up(&bdev->bd_sem);
......@@ -598,6 +591,8 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
kdev_t dev = to_kdev_t(bdev->bd_dev);
struct module *owner = NULL;
struct block_device_operations *ops, *old;
struct gendisk *disk;
int part;
lock_kernel();
ops = get_blkfops(major(dev));
......@@ -617,53 +612,41 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
if (owner)
__MOD_DEC_USE_COUNT(owner);
}
disk = get_gendisk(bdev->bd_dev, &part);
if (!disk)
goto out1;
if (!bdev->bd_contains) {
int part;
struct gendisk *g = get_gendisk(bdev->bd_dev, &part);
bdev->bd_contains = bdev;
if (g && part) {
struct block_device *disk;
disk = bdget(MKDEV(g->major, g->first_minor));
if (part) {
struct block_device *whole;
whole = bdget(MKDEV(disk->major, disk->first_minor));
ret = -ENOMEM;
if (!disk) {
put_disk(g);
if (!whole)
goto out1;
}
ret = blkdev_get(disk, file->f_mode, file->f_flags, BDEV_RAW);
if (ret) {
put_disk(g);
ret = blkdev_get(whole, file->f_mode, file->f_flags, BDEV_RAW);
if (ret)
goto out1;
}
bdev->bd_contains = disk;
bdev->bd_contains = whole;
}
put_disk(g);
}
if (bdev->bd_contains == bdev) {
int part;
struct gendisk *g = get_gendisk(bdev->bd_dev, &part);
if (!bdev->bd_openers)
bdev->bd_disk = disk;
if (!bdev->bd_queue) {
struct blk_dev_struct *p = blk_dev + major(dev);
bdev->bd_queue = &p->request_queue;
if (p->queue)
bdev->bd_queue = p->queue(dev);
}
if (bdev->bd_op->open) {
ret = bdev->bd_op->open(inode, file);
if (ret) {
put_disk(g);
if (ret)
goto out2;
}
}
if (!bdev->bd_openers) {
struct backing_dev_info *bdi;
sector_t sect = 0;
bdev->bd_offset = 0;
if (g)
sect = get_capacity(g);
bd_set_size(bdev, (loff_t)sect << 9);
bd_set_size(bdev, (loff_t)get_capacity(disk) << 9);
bdi = blk_get_backing_dev_info(bdev);
if (bdi == NULL)
bdi = &default_backing_dev_info;
......@@ -671,34 +654,31 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
bdev->bd_inode->i_data.backing_dev_info = bdi;
}
if (bdev->bd_invalidated)
rescan_partitions(g, bdev);
put_disk(g);
rescan_partitions(disk, bdev);
} else {
down(&bdev->bd_contains->bd_sem);
bdev->bd_contains->bd_part_count++;
if (!bdev->bd_openers) {
int part;
struct gendisk *g = get_gendisk(bdev->bd_dev, &part);
struct hd_struct *p;
p = g->part + part - 1;
p = disk->part + part - 1;
inode->i_data.backing_dev_info =
bdev->bd_inode->i_data.backing_dev_info =
bdev->bd_contains->bd_inode->i_data.backing_dev_info;
if (!(g->flags & GENHD_FL_UP) || !p->nr_sects) {
if (!(disk->flags & GENHD_FL_UP) || !p->nr_sects) {
bdev->bd_contains->bd_part_count--;
up(&bdev->bd_contains->bd_sem);
put_disk(g);
ret = -ENXIO;
goto out2;
}
bdev->bd_queue = bdev->bd_contains->bd_queue;
bdev->bd_offset = p->start_sect;
bd_set_size(bdev, (loff_t) p->nr_sects << 9);
put_disk(g);
bdev->bd_disk = disk;
}
up(&bdev->bd_contains->bd_sem);
}
bdev->bd_openers++;
if (bdev->bd_openers++)
put_disk(disk);
up(&bdev->bd_sem);
unlock_kernel();
return 0;
......@@ -712,6 +692,7 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
}
}
out1:
put_disk(disk);
if (!old) {
bdev->bd_op = NULL;
if (owner)
......@@ -785,15 +766,18 @@ int blkdev_put(struct block_device *bdev, int kind)
up(&bdev->bd_contains->bd_sem);
}
if (!bdev->bd_openers) {
struct gendisk *disk = bdev->bd_disk;
if (bdev->bd_op->owner)
__MOD_DEC_USE_COUNT(bdev->bd_op->owner);
bdev->bd_op = NULL;
bdev->bd_queue = NULL;
bdev->bd_disk = NULL;
bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
if (bdev != bdev->bd_contains) {
blkdev_put(bdev->bd_contains, BDEV_RAW);
bdev->bd_contains = NULL;
}
put_disk(disk);
}
unlock_kernel();
up(&bdev->bd_sem);
......
......@@ -34,6 +34,7 @@ struct request {
int rq_status; /* should split this into a few status bits */
kdev_t rq_dev;
struct gendisk *rq_disk;
int errors;
sector_t sector;
unsigned long nr_sectors;
......
......@@ -359,6 +359,7 @@ struct block_device {
sector_t bd_offset;
unsigned bd_part_count;
int bd_invalidated;
struct gendisk * bd_disk;
};
struct inode {
......
......@@ -90,6 +90,10 @@ struct gendisk {
devfs_handle_t disk_de; /* piled higher and deeper */
struct device *driverfs_dev;
struct device disk_dev;
unsigned sync_io; /* RAID */
unsigned reads, writes;
unsigned rio, wio;
};
/* drivers/block/genhd.c */
......@@ -272,15 +276,6 @@ extern void put_disk(struct gendisk *disk);
/* will go away */
extern void blk_set_probe(int major, struct gendisk *(p)(int));
static inline unsigned int disk_index (kdev_t dev)
{
int part, res;
struct gendisk *g = get_gendisk(kdev_t_to_nr(dev), &part);
res = g ? (minor(dev) >> g->minor_shift) : 0;
put_disk(g);
return res;
}
#endif
#endif
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