Commit 5844ac33 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[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).
parent a22f8253
......@@ -1573,16 +1573,10 @@ static int __make_request(request_queue_t *q, struct bio *bio)
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 */
}
......
......@@ -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 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
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;
......
......@@ -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 *);
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment