summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Viro <viro@math.psu.edu>2002-07-20 20:47:53 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-07-20 20:47:53 -0700
commit5844ac33e46839babf72edf7e8315b45cb95ebc6 (patch)
tree91b38eeb23cbf72668f1b6270b19d83f0de140c6
parenta22f8253014bf053a5253ad9388611c368a7e285 (diff)
[PATCH] block device size cleanups
for partitioned devices we use ->nr_sect to find the size; blk_size[] is still used for things like floppy.c, etc.; that will go away later. There was only one place (do_open()) that needed it - the rest uses ->bd_inode->i_size now. So blkdev_size_in_bytes() is gone - it's expanded in its only caller. Same place (do_open()) finds the partition offset and stores it in new field ->bd_offset. As the result, call of get_gendisk() is gone from the IO path - in blk_partition_remap() we just add ->bd_offset. Additionally, we take driver probing (get_blkfops()) outside of ->bd_sem (again, do_open()) - that will allow to kill ad-hackery in check_partitions() (opening bdev by hand).
-rw-r--r--drivers/block/ll_rw_blk.c8
-rw-r--r--fs/block_dev.c57
-rw-r--r--include/linux/blkdev.h14
-rw-r--r--include/linux/fs.h1
4 files changed, 36 insertions, 44 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 48616f94f5ee..8ada278181c8 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1573,16 +1573,10 @@ end_io:
static inline void blk_partition_remap(struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
- struct gendisk *g;
-
if (bdev == bdev->bd_contains)
return;
- g = get_gendisk(to_kdev_t(bdev->bd_dev));
- if (!g)
- BUG();
-
- bio->bi_sector += g->part[minor(to_kdev_t((bdev->bd_dev)))].start_sect;
+ bio->bi_sector += bdev->bd_offset;
bio->bi_bdev = bdev->bd_contains;
/* lots of checks are possible */
}
diff --git a/fs/block_dev.c b/fs/block_dev.c
index aa496e1bdd29..90c46b454f3c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -37,14 +37,6 @@ static unsigned long max_block(struct block_device *bdev)
return retval;
}
-static loff_t blkdev_size(kdev_t dev)
-{
- loff_t sz = blkdev_size_in_bytes(dev);
- if (sz)
- return sz;
- return ~0ULL;
-}
-
/* Kill _all_ buffers, dirty or not.. */
static void kill_bdev(struct block_device *bdev)
{
@@ -538,17 +530,23 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
int ret = -ENXIO;
kdev_t dev = to_kdev_t(bdev->bd_dev);
struct module *owner = NULL;
+ struct block_device_operations *ops, *current_ops;
- down(&bdev->bd_sem);
lock_kernel();
- if (!bdev->bd_op) {
- bdev->bd_op = get_blkfops(major(dev));
- if (!bdev->bd_op)
- goto out;
- owner = bdev->bd_op->owner;
+ ops = get_blkfops(major(dev));
+ if (ops) {
+ owner = ops->owner;
if (owner)
__MOD_INC_USE_COUNT(owner);
}
+
+ down(&bdev->bd_sem);
+ if (!bdev->bd_op)
+ current_ops = ops;
+ else
+ current_ops = bdev->bd_op;
+ if (!current_ops)
+ goto out;
if (!bdev->bd_contains) {
unsigned minor = minor(dev);
struct gendisk *g = get_gendisk(dev);
@@ -569,15 +567,30 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
}
}
}
- if (bdev->bd_op->open) {
- ret = bdev->bd_op->open(inode, file);
+ if (current_ops->open) {
+ ret = current_ops->open(inode, file);
if (ret)
goto out2;
}
- bdev->bd_inode->i_size = blkdev_size(dev);
+ if (!bdev->bd_op)
+ bdev->bd_op = ops;
+ else if (owner)
+ __MOD_DEC_USE_COUNT(owner);
if (!bdev->bd_openers) {
struct blk_dev_struct *p = blk_dev + major(dev);
+ struct gendisk *g = get_gendisk(dev);
unsigned bsize = bdev_hardsect_size(bdev);
+
+ bdev->bd_offset = 0;
+ if (g) {
+ bdev->bd_inode->i_size =
+ (loff_t) g->part[minor(dev)].nr_sects << 9;
+ bdev->bd_offset = g->part[minor(dev)].start_sect;
+ } else if (blk_size[major(dev)])
+ bdev->bd_inode->i_size =
+ (loff_t) blk_size[major(dev)][minor(dev)] << 10;
+ else
+ bdev->bd_inode->i_size = 0;
while (bsize < PAGE_CACHE_SIZE) {
if (bdev->bd_inode->i_size & bsize)
break;
@@ -601,14 +614,12 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
}
}
bdev->bd_openers++;
- unlock_kernel();
up(&bdev->bd_sem);
+ unlock_kernel();
return 0;
out2:
if (!bdev->bd_openers) {
- bdev->bd_op = NULL;
- bdev->bd_queue = 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);
@@ -619,8 +630,8 @@ out1:
if (owner)
__MOD_DEC_USE_COUNT(owner);
out:
- unlock_kernel();
up(&bdev->bd_sem);
+ unlock_kernel();
if (ret)
bdput(bdev);
return ret;
@@ -679,9 +690,9 @@ int blkdev_put(struct block_device *bdev, int kind)
kill_bdev(bdev);
if (bdev->bd_op->release)
ret = bdev->bd_op->release(bd_inode, NULL);
- if (bdev->bd_op->owner)
- __MOD_DEC_USE_COUNT(bdev->bd_op->owner);
if (!bdev->bd_openers) {
+ if (bdev->bd_op->owner)
+ __MOD_DEC_USE_COUNT(bdev->bd_op->owner);
bdev->bd_op = NULL;
bdev->bd_queue = NULL;
bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 297cb0ba10c1..7460a98bb0b3 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -389,20 +389,6 @@ extern inline unsigned int block_size(struct block_device *bdev)
return bdev->bd_block_size;
}
-static inline loff_t blkdev_size_in_bytes(kdev_t dev)
-{
-#if 0
- if (blk_size_in_bytes[major(dev)])
- return blk_size_in_bytes[major(dev)][minor(dev)];
- else
-#endif
- if (blk_size[major(dev)])
- return (loff_t) blk_size[major(dev)][minor(dev)]
- << BLOCK_SIZE_BITS;
- else
- return 0;
-}
-
typedef struct {struct page *v;} Sector;
unsigned char *read_dev_sector(struct block_device *, unsigned long, Sector *);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 84413138923e..83f5a21b5d26 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -350,6 +350,7 @@ struct block_device {
int bd_holders;
struct block_device * bd_contains;
unsigned bd_block_size;
+ unsigned long bd_offset;
};
struct inode {