]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] bdev->bd_disk introduced
authorAlexander Viro <viro@math.psu.edu>
Tue, 15 Oct 2002 11:25:37 +0000 (04:25 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 15 Oct 2002 11:25:37 +0000 (04:25 -0700)
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...

drivers/block/genhd.c
drivers/block/ioctl.c
drivers/block/ll_rw_blk.c
drivers/block/rd.c
drivers/md/md.c
fs/block_dev.c
include/linux/blkdev.h
include/linux/fs.h
include/linux/genhd.h

index 1cc4655c04c99c03cb14571d74985f2afda2332c..449e69061bbc4600d4d36d965d63d5baa588aff0 100644 (file)
@@ -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;
index de2da2b44cad94f2ca0bc8cafa37370f206ede50..e420c691763d0623eea6e58f8446e81c69053fe9 100644 (file)
@@ -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;
 }
 
index ea56c1d8456c790355144c34d8bd3a7be335080a..eb877e50a8d11c4149f65a6cbe520a376a0e1068 100644 (file)
@@ -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)
index 7d72b786080ca2bf2d24431d59ab3a9c5332ce98..bbd247fa29dcccaa4a0296b8309018367430763b 100644 (file)
@@ -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;
index 205bb0fdeee06e644dddb7ac88987a6cae6f2442..784e3b69213e4f828d773a2dd0cafc6ba5ee5aed 100644 (file)
@@ -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;
index d029636b07e66f466e530678b74849fba3ec2d97..1ad7f467993bcd94f6ec3e6eaa0572fb7f745000 100644 (file)
@@ -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);
index 607641c6cfb1e719d0c26aa29be44a8cac467b51..ccb56d58de6ae66de310d38d280d8e89c896c8af 100644 (file)
@@ -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;
index cac13f931cecc7a85ea8792441382e0bfc244dd6..bca164f4265aa061720a3be295928525505a4c8d 100644 (file)
@@ -359,6 +359,7 @@ struct block_device {
        sector_t                bd_offset;
        unsigned                bd_part_count;
        int                     bd_invalidated;
+       struct gendisk *        bd_disk;
 };
 
 struct inode {
index 030ee2f87891e7d4683cb595d2380c222c39c7f3..9de2f51ae935fc3d1348d8eb2ca1196d5a50cbf5 100644 (file)
@@ -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