From 90df68e70b631886169c9287faebf2742f43484c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 14 Oct 2002 21:24:37 -0700 Subject: Block layer ioctl cleanups. Rename old "block_ioctl()" function: it's "scsi_cmd_ioctl()", as that is what the function does. Rename the whole file "scsi_ioctl.c" --- include/linux/blkdev.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'include/linux/blkdev.h') diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 4929d743683d..607641c6cfb1 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -60,6 +60,12 @@ struct request { int tag; void *special; char *buffer; + + /* For packet commands */ + unsigned int data_len; + void *data, *sense; + + unsigned int timeout; struct completion *waiting; struct bio *bio, *biotail; request_queue_t *q; @@ -85,6 +91,8 @@ enum rq_flag_bits { __REQ_BLOCK_PC, /* queued down pc from block layer */ __REQ_SENSE, /* sense retrival */ + __REQ_FAILED, /* set if the request failed */ + __REQ_QUIET, /* don't worry about errors */ __REQ_SPECIAL, /* driver suplied command */ __REQ_DRIVE_CMD, __REQ_DRIVE_TASK, @@ -103,6 +111,8 @@ enum rq_flag_bits { #define REQ_PC (1 << __REQ_PC) #define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC) #define REQ_SENSE (1 << __REQ_SENSE) +#define REQ_FAILED (1 << __REQ_FAILED) +#define REQ_QUIET (1 << __REQ_QUIET) #define REQ_SPECIAL (1 << __REQ_SPECIAL) #define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD) #define REQ_DRIVE_TASK (1 << __REQ_DRIVE_TASK) @@ -301,7 +311,7 @@ extern int blk_remove_plug(request_queue_t *); extern void blk_recount_segments(request_queue_t *, struct bio *); extern inline int blk_phys_contig_segment(request_queue_t *q, struct bio *, struct bio *); extern inline int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *); -extern int block_ioctl(struct block_device *, unsigned int, unsigned long); +extern int scsi_cmd_ioctl(struct block_device *, unsigned int, unsigned long); extern void blk_start_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q); extern void __blk_stop_queue(request_queue_t *q); -- cgit v1.2.3 From 5682bcc620dbee99319997718c8929ec0d797854 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Tue, 15 Oct 2002 04:25:37 -0700 Subject: [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... --- drivers/block/genhd.c | 10 ++----- drivers/block/ioctl.c | 65 +++++++++--------------------------------- drivers/block/ll_rw_blk.c | 15 +++++++++- drivers/block/rd.c | 1 + drivers/md/md.c | 23 ++------------- fs/block_dev.c | 72 ++++++++++++++++++----------------------------- include/linux/blkdev.h | 1 + include/linux/fs.h | 1 + include/linux/genhd.h | 13 +++------ 9 files changed, 68 insertions(+), 133 deletions(-) (limited to 'include/linux/blkdev.h') 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 -- cgit v1.2.3