summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2022-08-05 09:07:15 +0200
committerHelge Deller <deller@gmx.de>2022-08-05 10:43:48 +0200
commitb7736781cb0c3386343f1360308f7f1296f4cacd (patch)
tree793608ab2ff60ddcb30f84140aab4f960ef42cb3
parent05ab9d3921cd267bdc61f4517e954e05620c98e1 (diff)
downloadpalo-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.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/ipl/ext2.c b/ipl/ext2.c
index a468790..d05ec6c 100644
--- a/ipl/ext2.c
+++ b/ipl/ext2.c
@@ -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);
}