diff options
author | Helge Deller <deller@gmx.de> | 2022-08-05 09:07:15 +0200 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2022-08-05 10:43:48 +0200 |
commit | b7736781cb0c3386343f1360308f7f1296f4cacd (patch) | |
tree | 793608ab2ff60ddcb30f84140aab4f960ef42cb3 | |
parent | 05ab9d3921cd267bdc61f4517e954e05620c98e1 (diff) | |
download | palo-b7736781cb0c3386343f1360308f7f1296f4cacd.tar.gz |
ipl: Avoid usage of 64-bit __udivdi3 millicode routine in ext2 code
Avoid using millicode routines in the ext2 code by using a simplified
bit-shifting mechanism to avoid u64 integer divisions.
Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r-- | ipl/ext2.c | 33 |
1 files changed, 27 insertions, 6 deletions
@@ -64,6 +64,27 @@ static struct inode_table_entry { #undef DEBUG #define Debug 0 +/* div_blocksize() and mul_blocksize() are trivial functions to avoid 64-bit + __udivdi3 and __muldi3 millicode routines. They only work because the ext2 + blocksize is a multiple of 2 */ +static __u64 div_blocksize(__u64 devaddr, unsigned blocksize) +{ + while (blocksize > 1) { + devaddr >>= 1; + blocksize >>= 1; + } + return devaddr; +} +static __u64 mul_blocksize(__u64 devaddr, unsigned blocksize) +{ + while (blocksize > 1) { + devaddr <<= 1; + blocksize >>= 1; + } + return devaddr; +} + + static struct ext3_extent_header *ext3_extent_header(struct ext2_inode *i) { return (struct ext3_extent_header *)&i->i_block[0]; @@ -363,7 +384,7 @@ static struct ext2_inode *ext2_iget(int ino) printf("group is %d\n", group); #endif offset = partition_offset - + ((__u64) ext2_gds(group)->bg_inode_table * ext2_blocksize) + + mul_blocksize(ext2_gds(group)->bg_inode_table, ext2_blocksize) + (((ino - 1) % EXT2_INODES_PER_GROUP(&sb)) * EXT2_INODE_SIZE(&sb)); #ifdef DEBUG @@ -583,7 +604,7 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff) /* Read the indirect block */ if (cached_iblkno != iblkno) { - offset = partition_offset + (__u64)iblkno * ext2_blocksize; + offset = partition_offset + mul_blocksize(iblkno, ext2_blocksize); if (cons_read(dev, iblkbuf, ext2_blocksize, offset) != ext2_blocksize) { @@ -610,7 +631,7 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff) /* Read in the double-indirect block */ if (cached_diblkno != diblkno) { - offset = partition_offset + (__u64) diblkno * ext2_blocksize; + offset = partition_offset + mul_blocksize(diblkno, ext2_blocksize); if (cons_read(dev, diblkbuf, ext2_blocksize, offset) != ext2_blocksize) { @@ -631,7 +652,7 @@ static int ext2_blkno(struct ext2_inode *ip, int blkoff) /* Read the indirect block */ if (cached_iblkno != iblkno) { - offset = partition_offset + (__u64) iblkno * ext2_blocksize; + offset = partition_offset + mul_blocksize(iblkno, ext2_blocksize); if (cons_read(dev, iblkbuf, ext2_blocksize, offset) != ext2_blocksize) { @@ -699,7 +720,7 @@ static int ext2_breadi(struct ext2_inode *ip, long blkno, long nblks, memset(buffer, 0, nbytes); } else { /* Read it for real */ - offset = partition_offset + (__u64) dev_blkno * ext2_blocksize; + offset = partition_offset + mul_blocksize(dev_blkno, ext2_blocksize); #ifdef DEBUG printf("ext2_bread: reading %ld bytes at offset %lld\n", nbytes, offset); @@ -970,7 +991,7 @@ static int ext2_read(int fd, char *buf, unsigned count, __u64 devaddr) fd, buf, count, devaddr); return ext2_breadi(ip, - devaddr / ext2_blocksize, + div_blocksize(devaddr, ext2_blocksize), count / ext2_blocksize, buf); } |