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