summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Viro <viro@math.psu.edu>2002-10-15 04:25:37 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-10-15 04:25:37 -0700
commit5682bcc620dbee99319997718c8929ec0d797854 (patch)
tree09a95ed6c8f9233f0182b037ead14982059c8d09
parent68c16870dcfaba7c9e2dd5055a2caf4edcf42e87 (diff)
[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...
-rw-r--r--drivers/block/genhd.c10
-rw-r--r--drivers/block/ioctl.c65
-rw-r--r--drivers/block/ll_rw_blk.c15
-rw-r--r--drivers/block/rd.c1
-rw-r--r--drivers/md/md.c23
-rw-r--r--fs/block_dev.c72
-rw-r--r--include/linux/blkdev.h1
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/genhd.h13
9 files changed, 68 insertions, 133 deletions
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 1cc4655c04c9..449e69061bbc 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -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;
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
index de2da2b44cad..e420c691763d 100644
--- a/drivers/block/ioctl.c
+++ b/drivers/block/ioctl.c
@@ -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;
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index ea56c1d8456c..eb877e50a8d1 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -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 @@ get_rq:
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)
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 7d72b786080c..bbd247fa29dc 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -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;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 205bb0fdeee0..784e3b69213e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -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;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index d029636b07e6..1ad7f467993b 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -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 @@ out2:
}
}
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);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 607641c6cfb1..ccb56d58de6a 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -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;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cac13f931cec..bca164f4265a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -359,6 +359,7 @@ struct block_device {
sector_t bd_offset;
unsigned bd_part_count;
int bd_invalidated;
+ struct gendisk * bd_disk;
};
struct inode {
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 030ee2f87891..9de2f51ae935 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -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