diff options
| author | Alexander Viro <viro@math.psu.edu> | 2002-10-15 04:25:37 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-15 04:25:37 -0700 |
| commit | 5682bcc620dbee99319997718c8929ec0d797854 (patch) | |
| tree | 09a95ed6c8f9233f0182b037ead14982059c8d09 | |
| parent | 68c16870dcfaba7c9e2dd5055a2caf4edcf42e87 (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.c | 10 | ||||
| -rw-r--r-- | drivers/block/ioctl.c | 65 | ||||
| -rw-r--r-- | drivers/block/ll_rw_blk.c | 15 | ||||
| -rw-r--r-- | drivers/block/rd.c | 1 | ||||
| -rw-r--r-- | drivers/md/md.c | 23 | ||||
| -rw-r--r-- | fs/block_dev.c | 72 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 1 | ||||
| -rw-r--r-- | include/linux/fs.h | 1 | ||||
| -rw-r--r-- | include/linux/genhd.h | 13 |
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 |
