Commit 91fff028 authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Anton Blanchard

[PATCH] size_in_bytes

It is a step on the road to removal of the arrays.
It also solves other things, like the fact that Linux
is unable to read the last sector of a disk or partition
with an odd number of sectors.
parent 3bdd85a2
......@@ -213,7 +213,6 @@ extern int block_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg);
int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
{
request_queue_t *q;
struct gendisk *g;
u64 ullval = 0;
int intval;
unsigned short usval;
......@@ -252,20 +251,18 @@ int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
return 0;
case BLKSSZGET:
/* get block device sector size as needed e.g. by fdisk */
/* get block device hardware sector size */
intval = get_hardsect_size(dev);
return put_user(intval, (int *) arg);
case BLKGETSIZE:
/* size in sectors, works up to 2 TB */
ullval = blkdev_size_in_bytes(dev);
return put_user((unsigned long)(ullval >> 9), (unsigned long *) arg);
case BLKGETSIZE64:
g = get_gendisk(dev);
if (g)
ullval = g->part[minor(dev)].nr_sects;
if (cmd == BLKGETSIZE)
return put_user((unsigned long)ullval, (unsigned long *)arg);
else
return put_user((u64)ullval << 9 , (u64 *)arg);
/* size in bytes */
ullval = blkdev_size_in_bytes(dev);
return put_user(ullval, (u64 *) arg);
#if 0
case BLKRRPART: /* Re-read partition tables */
if (!capable(CAP_SYS_ADMIN))
......
......@@ -62,7 +62,7 @@ struct blk_dev_struct blk_dev[MAX_BLKDEV]; /* initialized by blk_dev_init() */
/*
* blk_size contains the size of all block-devices in units of 1024 byte
* sectors:
* blocks:
*
* blk_size[MAJOR][MINOR]
*
......@@ -1274,32 +1274,27 @@ static inline void blk_partition_remap(struct bio *bio)
* */
void generic_make_request(struct bio *bio)
{
int major = major(bio->bi_dev);
int minor = minor(bio->bi_dev);
request_queue_t *q;
sector_t minorsize = 0;
sector_t maxsector;
int ret, nr_sectors = bio_sectors(bio);
/* Test device or partition size, when known. */
if (blk_size[major])
minorsize = blk_size[major][minor];
if (minorsize) {
unsigned long maxsector = (minorsize << 1) + 1;
unsigned long sector = bio->bi_sector;
if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
if (blk_size[major][minor]) {
/* This may well happen - the kernel calls
* bread() without checking the size of the
* device, e.g., when mounting a device. */
printk(KERN_INFO
"attempt to access beyond end of device\n");
printk(KERN_INFO "%s: rw=%ld, want=%ld, limit=%Lu\n",
kdevname(bio->bi_dev), bio->bi_rw,
(sector + nr_sectors)>>1,
(long long) blk_size[major][minor]);
}
maxsector = (blkdev_size_in_bytes(bio->bi_dev) >> 9);
if (maxsector) {
sector_t sector = bio->bi_sector;
if (maxsector < nr_sectors ||
maxsector - nr_sectors < sector) {
/* This may well happen - the kernel calls
* bread() without checking the size of the
* device, e.g., when mounting a device. */
printk(KERN_INFO
"attempt to access beyond end of device\n");
printk(KERN_INFO "%s: rw=%ld, want=%ld, limit=%Lu\n",
kdevname(bio->bi_dev), bio->bi_rw,
sector + nr_sectors,
(long long) maxsector);
set_bit(BIO_EOF, &bio->bi_flags);
goto end_io;
}
......
......@@ -154,14 +154,20 @@ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
#define MAX_DISK_SIZE 1024*1024*1024
static unsigned long compute_loop_size(struct loop_device *lo, struct dentry * lo_dentry, kdev_t lodev)
static unsigned long
compute_loop_size(struct loop_device *lo,
struct dentry * lo_dentry, kdev_t lodev)
{
if (S_ISREG(lo_dentry->d_inode->i_mode))
return (lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS;
if (blk_size[major(lodev)])
return blk_size[major(lodev)][minor(lodev)] -
(lo->lo_offset >> BLOCK_SIZE_BITS);
return MAX_DISK_SIZE;
loff_t size = 0;
if (S_ISREG(lo_dentry->d_inode->i_mode)) {
size = lo_dentry->d_inode->i_size;
} else {
size = blkdev_size_in_bytes(lodev);
if (size == 0)
return MAX_DISK_SIZE;
}
return (size - lo->lo_offset) >> BLOCK_SIZE_BITS;
}
static void figure_loop_size(struct loop_device *lo)
......
......@@ -300,19 +300,13 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
}
up(&inode->i_bdev->bd_sem);
break;
case BLKGETSIZE: /* Return device size */
if (!arg)
break;
error = put_user(rd_kbsize[minor] << 1, (unsigned long *) arg);
break;
case BLKGETSIZE:
case BLKGETSIZE64:
error = put_user((u64)rd_kbsize[minor]<<10, (u64*)arg);
break;
case BLKROSET:
case BLKROGET:
case BLKSSZGET:
error = blk_ioctl(inode->i_bdev, cmd, arg);
};
}
out:
return error;
}
......@@ -419,11 +413,10 @@ static void __exit rd_cleanup (void)
/* This is the registration and initialization section of the RAM disk driver */
static int __init rd_init (void)
{
int i;
int i;
if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
(rd_blocksize & (rd_blocksize-1)))
{
(rd_blocksize & (rd_blocksize-1))) {
printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
rd_blocksize);
rd_blocksize = BLOCK_SIZE;
......@@ -450,7 +443,8 @@ static int __init rd_init (void)
&rd_bd_op, NULL);
for (i = 0; i < NUM_RAMDISKS; i++)
register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
register_disk(NULL, mk_kdev(MAJOR_NR,i), 1, &rd_bd_op,
rd_size<<1);
#ifdef CONFIG_BLK_DEV_INITRD
/* We ought to separate initrd operations here */
......@@ -459,10 +453,10 @@ static int __init rd_init (void)
INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL);
#endif
blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */
blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */
blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */
blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */
/* rd_size is given in kB */
/* rd_size is given in kB */
printk("RAMDISK driver initialized: "
"%d RAM disks of %dK size %d blocksize\n",
NUM_RAMDISKS, rd_size, rd_blocksize);
......
......@@ -289,11 +289,10 @@ ssize_t rw_raw_dev(int rw, struct file *filp, char *buf,
dev = to_kdev_t(raw_devices[minor].binding->bd_dev);
sector_size = raw_devices[minor].sector_size;
sector_bits = raw_devices[minor].sector_bits;
sector_mask = sector_size- 1;
if (blk_size[major(dev)])
limit = (((loff_t) blk_size[major(dev)][minor(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
else
sector_mask = sector_size - 1;
limit = blkdev_size_in_bytes(dev) >> sector_bits;
if (!limit)
limit = INT_MAX;
dprintk ("rw_raw_dev: dev %d:%d (+%d)\n",
major(dev), minor(dev), limit);
......
......@@ -283,10 +283,7 @@ char * partition_name(kdev_t dev)
static unsigned int calc_dev_sboffset(kdev_t dev, mddev_t *mddev,
int persistent)
{
unsigned int size = 0;
if (blk_size[major(dev)])
size = blk_size[major(dev)][minor(dev)];
unsigned int size = (blkdev_size_in_bytes(dev) >> BLOCK_SIZE_BITS);
if (persistent)
size = MD_NEW_SIZE_BLOCKS(size);
return size;
......@@ -1106,12 +1103,11 @@ static int md_import_device(kdev_t newdev, int on_disk)
rdev->desc_nr = -1;
rdev->faulty = 0;
size = 0;
if (blk_size[major(newdev)])
size = blk_size[major(newdev)][minor(newdev)];
size = (blkdev_size_in_bytes(newdev) >> BLOCK_SIZE_BITS);
if (!size) {
printk(KERN_WARNING "md: %s has zero size, marking faulty!\n",
partition_name(newdev));
printk(KERN_WARNING
"md: %s has zero or unknown size, marking faulty!\n",
partition_name(newdev));
err = -EINVAL;
goto abort_free;
}
......
......@@ -67,7 +67,6 @@
/* Default erase size in K, always make it a multiple of PAGE_SIZE */
#define CONFIG_MTD_BLKDEV_ERASESIZE 128
#define VERSION "1.7"
extern int *blk_size[];
/* Info for the block device */
typedef struct mtd_raw_dev_data_s {
......@@ -1062,7 +1061,7 @@ static int __init init_blkmtd(void)
int maj, min;
int i, blocksize, blocksize_bits;
loff_t size = 0;
loff_t size;
int readonly = 0;
int erase_size = CONFIG_MTD_BLKDEV_ERASESIZE;
kdev_t rdev;
......@@ -1143,14 +1142,8 @@ static int __init init_blkmtd(void)
i >>= 1;
}
if(count) {
size = count;
} else {
if (blk_size[maj]) {
size = ((loff_t) blk_size[maj][min] << BLOCK_SIZE_BITS) >> blocksize_bits;
}
}
size *= blocksize;
size = (count ? count*blocksize : blkdev_size_in_bytes(rdev));
DEBUG(1, "blkmtd: size = %ld\n", (long int)size);
if(size == 0) {
......
......@@ -1045,7 +1045,7 @@ int xpram_init(void)
for (i=0; i < xpram_devs; i++)
if (xpram_sizes[i] == 0) xpram_sizes[i] = mem_auto;
}
blk_size[major]=xpram_sizes;
blk_size[major] = xpram_sizes;
xpram_offsets = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
if (!xpram_offsets) {
......
......@@ -2387,7 +2387,7 @@ static void scsi_dump_status(int level)
kdevname(SCpnt->request.rq_dev),
SCpnt->request.sector,
SCpnt->request.nr_sectors,
SCpnt->request.current_nr_sectors,
(long)SCpnt->request.current_nr_sectors,
SCpnt->request.rq_status,
SCpnt->use_sg,
......
......@@ -373,7 +373,7 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
nbuff,
(SCpnt->request.cmd == WRITE) ? "writing" : "reading",
(rq_data_dir(&SCpnt->request) == WRITE) ? "writing" : "reading",
this_count, SCpnt->request.nr_sectors));
SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
......
......@@ -29,7 +29,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
extern int *blk_size[];
extern struct timezone sys_tz;
static int affs_statfs(struct super_block *sb, struct statfs *buf);
......@@ -321,7 +320,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
*/
size = sb->s_bdev->bd_inode->i_size >> 9;
pr_debug("AFFS: initial blksize=%d, blocks=%d\n", 512, blocks);
pr_debug("AFFS: initial blocksize=%d, #blocks=%d\n", 512, size);
affs_set_blocksize(sb, PAGE_SIZE);
/* Try to find root block. Its location depends on the block size. */
......
......@@ -27,33 +27,22 @@
static unsigned long max_block(kdev_t dev)
{
unsigned int retval = ~0U;
int major = major(dev);
if (blk_size[major]) {
int minor = minor(dev);
unsigned int blocks = blk_size[major][minor];
if (blocks) {
unsigned int size = block_size(dev);
unsigned int sizebits = blksize_bits(size);
blocks += (size-1) >> BLOCK_SIZE_BITS;
retval = blocks << (BLOCK_SIZE_BITS - sizebits);
if (sizebits > BLOCK_SIZE_BITS)
retval = blocks >> (sizebits - BLOCK_SIZE_BITS);
}
loff_t sz = blkdev_size_in_bytes(dev);
if (sz) {
unsigned int size = block_size(dev);
unsigned int sizebits = blksize_bits(size);
retval = (sz >> sizebits);
}
return retval;
}
static loff_t blkdev_size(kdev_t dev)
{
unsigned int blocks = ~0U;
int major = major(dev);
if (blk_size[major]) {
int minor = minor(dev);
blocks = blk_size[major][minor];
}
return (loff_t) blocks << BLOCK_SIZE_BITS;
loff_t sz = blkdev_size_in_bytes(dev);
if (sz)
return sz;
return ~0ULL;
}
/* Kill _all_ buffers, dirty or not.. */
......
......@@ -112,8 +112,6 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
struct buffer_head * read_array[BLKS_PER_BUF];
unsigned i, blocknr, buffer, unread;
unsigned long devsize;
unsigned int major, minor;
char *data;
if (!len)
......@@ -136,12 +134,9 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
return read_buffers[i] + blk_offset;
}
devsize = ~0UL;
major = major(sb->s_dev);
minor = minor(sb->s_dev);
if (blk_size[major])
devsize = blk_size[major][minor] >> 2;
devsize = blkdev_size_in_bytes(sb->s_dev) >> 12;
if (!devsize)
devsize = ~0UL;
/* Ok, read in BLKS_PER_BUF pages completely first. */
unread = 0;
......
......@@ -313,7 +313,7 @@ extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist
extern void blk_dump_rq_flags(struct request *, char *);
extern void generic_unplug_device(void *);
extern int * blk_size[MAX_BLKDEV];
extern int * blk_size[MAX_BLKDEV]; /* in units of 1024 bytes */
extern int * blksize_size[MAX_BLKDEV];
#define MAX_PHYS_SEGMENTS 128
......@@ -353,6 +353,7 @@ extern inline int get_hardsect_size(kdev_t dev)
#define blk_finished_io(nsects) do { } while (0)
#define blk_started_io(nsects) do { } while (0)
/* assumes size > 256 */
extern inline unsigned int blksize_bits(unsigned int size)
{
unsigned int bits = 8;
......@@ -376,6 +377,20 @@ extern inline unsigned int block_size(kdev_t dev)
return retval;
}
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 *);
......
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