[RFC, v2] SquashFS not compiling due to missing __udivdi3 and __umoddi3

Mauro Condarelli mc5686 at mclink.it
Thu Sep 3 14:55:27 CEST 2020


Second update.
It turns out I was  bit too aggressive in my "fix".
Unfortunately that is not cause of malfunction and
code is still unable to load files.
Any hint on how to proceed would be useful, current
plan is to add printouts to code to trace what happens,
but that is going to be a real PITA.

Thanks in Advance
Mauro


>From 74ba63e93099515950a8dcd57162d8f5b98b9e5d Mon Sep 17 00:00:00 2001
From: Mauro Condarelli <mc5686 at mclink.it>
Date: Thu, 3 Sep 2020 08:37:58 +0200
Subject: [PATCH 4/4] Fix missing __udivdi3 in SquashFS implementation.

Signed-off-by: Mauro Condarelli <mc5686 at mclink.it>
---
 fs/squashfs/sqfs.c       | 40 ++++++++++++++++++++++++----------------
 fs/squashfs/sqfs_inode.c |  8 ++++----
 2 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index f67f7c4a40..2abb603afc 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -18,6 +18,7 @@
 #include <string.h>
 #include <squashfs.h>
 #include <part.h>
+#include <div64.h>
 
 #include "sqfs_decompressor.h"
 #include "sqfs_filesystem.h"
@@ -82,13 +83,16 @@ static int sqfs_count_tokens(const char *filename)
  */
 static int sqfs_calc_n_blks(__le64 start, __le64 end, u64 *offset)
 {
-    u64 start_, table_size;
+    u64 start_, table_size, blks;
 
     table_size = le64_to_cpu(end) - le64_to_cpu(start);
-    start_ = le64_to_cpu(start) / ctxt.cur_dev->blksz;
+    start_ = le64_to_cpu(start);
+    do_div(start_, ctxt.cur_dev->blksz);
     *offset = le64_to_cpu(start) - (start_ * ctxt.cur_dev->blksz);
 
-    return DIV_ROUND_UP(table_size + *offset, ctxt.cur_dev->blksz);
+    blks = table_size + *offset;
+    if (do_div(blks, ctxt.cur_dev->blksz)) blks++;
+    return blks;
 }
 
 /*
@@ -109,8 +113,8 @@ static int sqfs_frag_lookup(u32 inode_fragment_index,
     if (inode_fragment_index >= get_unaligned_le32(&sblk->fragments))
         return -EINVAL;
 
-    start = get_unaligned_le64(&sblk->fragment_table_start) /
-        ctxt.cur_dev->blksz;
+    start = get_unaligned_le64(&sblk->fragment_table_start);
+    do_div(start, ctxt.cur_dev->blksz);
     n_blks = sqfs_calc_n_blks(sblk->fragment_table_start,
                   sblk->export_table_start,
                   &table_offset);
@@ -135,7 +139,8 @@ static int sqfs_frag_lookup(u32 inode_fragment_index,
     start_block = get_unaligned_le64(table + table_offset + block *
                      sizeof(u64));
 
-    start = start_block / ctxt.cur_dev->blksz;
+    start = start_block;
+    do_div(start, ctxt.cur_dev->blksz);
     n_blks = sqfs_calc_n_blks(cpu_to_le64(start_block),
                   sblk->fragment_table_start, &table_offset);
 
@@ -641,8 +646,8 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
 
     table_size = get_unaligned_le64(&sblk->directory_table_start) -
         get_unaligned_le64(&sblk->inode_table_start);
-    start = get_unaligned_le64(&sblk->inode_table_start) /
-        ctxt.cur_dev->blksz;
+    start = get_unaligned_le64(&sblk->inode_table_start);
+    do_div(start, ctxt.cur_dev->blksz);
     n_blks = sqfs_calc_n_blks(sblk->inode_table_start,
                   sblk->directory_table_start, &table_offset);
 
@@ -725,8 +730,8 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list)
     /* DIRECTORY TABLE */
     table_size = get_unaligned_le64(&sblk->fragment_table_start) -
         get_unaligned_le64(&sblk->directory_table_start);
-    start = get_unaligned_le64(&sblk->directory_table_start) /
-        ctxt.cur_dev->blksz;
+    start = get_unaligned_le64(&sblk->directory_table_start);
+    do_div(start, ctxt.cur_dev->blksz);
     n_blks = sqfs_calc_n_blks(sblk->directory_table_start,
                   sblk->fragment_table_start, &table_offset);
 
@@ -1159,7 +1164,7 @@ static int sqfs_get_regfile_info(struct squashfs_reg_inode *reg,
         if (fentry->size < 1 || fentry->start < 0)
             return -EINVAL;
     } else {
-        datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
+        datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
     }
 
     finfo->blk_sizes = malloc(datablk_count * sizeof(u32));
@@ -1328,11 +1333,12 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
     }
 
     for (j = 0; j < datablk_count; j++) {
-        start = data_offset / ctxt.cur_dev->blksz;
+        start = data_offset;
+        do_div(start, ctxt.cur_dev->blksz);
         table_size = SQFS_BLOCK_SIZE(finfo.blk_sizes[j]);
         table_offset = data_offset - (start * ctxt.cur_dev->blksz);
-        n_blks = DIV_ROUND_UP(table_size + table_offset,
-                      ctxt.cur_dev->blksz);
+        n_blks = table_size + table_offset;
+        if (do_div(n_blks, ctxt.cur_dev->blksz)) n_blks++;
 
         data_buffer = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz);
 
@@ -1382,10 +1388,12 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
         goto free_buffer;
     }
 
-    start = frag_entry.start / ctxt.cur_dev->blksz;
+    start = frag_entry.start;
+    do_div(start, ctxt.cur_dev->blksz);
     table_size = SQFS_BLOCK_SIZE(frag_entry.size);
     table_offset = frag_entry.start - (start * ctxt.cur_dev->blksz);
-    n_blks = DIV_ROUND_UP(table_size + table_offset, ctxt.cur_dev->blksz);
+    n_blks = table_size + table_offset;
+    if (do_div(n_blks, ctxt.cur_dev->blksz)) n_blks++;
 
     fragment = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz);
 
diff --git a/fs/squashfs/sqfs_inode.c b/fs/squashfs/sqfs_inode.c
index 1387779a85..f0e916e6a3 100644
--- a/fs/squashfs/sqfs_inode.c
+++ b/fs/squashfs/sqfs_inode.c
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <div64.h>
 
 #include "sqfs_decompressor.h"
 #include "sqfs_filesystem.h"
@@ -67,10 +68,9 @@ int sqfs_inode_size(struct squashfs_base_inode *inode, u32 blk_size)
         u64 file_size = get_unaligned_le64(&lreg->file_size);
         unsigned int blk_list_size;
 
-        if (fragment == 0xFFFFFFFF)
-            blk_list_size = DIV_ROUND_UP(file_size, blk_size);
-        else
-            blk_list_size = file_size / blk_size;
+        if (do_div(file_size, blk_size) && (fragment == 0xFFFFFFFF))
+            file_size++;
+        blk_list_size = file_size;
 
         return sizeof(*lreg) + blk_list_size * sizeof(u32);
     }
-- 
2.25.1



On 9/3/20 12:24 PM, Mauro Condarelli wrote:
> Small update, see below.
>
> On 9/3/20 10:41 AM, Mauro Condarelli wrote:
>> Hi,
>> enabling squashfs on my target (vocore2) result in multiple errors:
>>
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/built-in.o: in function `sqfs_calc_n_blks':
>>> fs/squashfs/sqfs.c:(.text.sqfs_calc_n_blks+0x44): undefined reference to `__umoddi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/squashfs/sqfs.c:(.text.sqfs_calc_n_blks+0x98): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/built-in.o: in function `sqfs_frag_lookup':
>>> fs/squashfs/sqfs.c:(.text.sqfs_frag_lookup+0x74): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/squashfs/sqfs.c:(.text.sqfs_frag_lookup+0x1b0): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/built-in.o: in function `sqfs_opendir':
>>> (.text.sqfs_opendir+0xbc): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: (.text.sqfs_opendir+0x178): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/built-in.o:(.text.sqfs_read+0x324): more undefined references to `__udivdi3' follow
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/built-in.o: in function `sqfs_read':
>>> (.text.sqfs_read+0x348): undefined reference to `__umoddi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: (.text.sqfs_read+0x388): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: (.text.sqfs_read+0x5bc): undefined reference to `__umoddi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: (.text.sqfs_read+0x600): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: (.text.sqfs_read+0x64c): undefined reference to `__udivdi3'
>>> /home/mcon/vocore/__V2__/Buildroot-2/recov/per-package/uboot/host/bin/mipsel-linux-ld.bfd: fs/built-in.o: in function `sqfs_inode_size':
>>> (.text.sqfs_inode_size+0x140): undefined reference to `__udivdi3'
>>> make[2]: *** [Makefile:1753: u-boot] Error 1
>>> make[1]: *** [package/pkg-generic.mk:269: /home/mcon/vocore/__V2__/Buildroot-2/recov/build/uboot-v2020.10-rc3/.stamp_built] Error 2
>>> make: *** [Makefile:23: _all] Error 2
>> Following some advice on IRC (I can be contacted there as "mcon")
>> I tried to fix issue by explicit calling `lldiv()` (full patch below).
>> Fix allows full compilation, and is also somewhat working:
>> Directory list works, file load does not :(
>>
>>> => ls mmc 0:6 /boot    
>>>         0   not_mounted
>>>   2512916   uImage
>>>
>>> 2 file(s), 0 dir(s)
>>>
>>> => load mmc 0:6 85000000 /boot/uImage
>>> Failed to load '/boot/uImage'
> After load failure also dir listing becomes non-functional.
> I didn't find any way to cure problem without full reboot.
> I have no idea how to debug this.
>
> => ls mmc 0:6 /boot
>         0   not_mounted
>   2512916   uImage
>
> 2 file(s), 0 dir(s)
>
> => ls mmc 0:6 /root
>        26   .profile
>             .ssh/
>       673   is_ssh3
>      1251   kmsgd
>     65536   master.bin
>        77   persist_data.lst
>       451   public.pem
>      1186   termsize
>      1675   update
>      2853   verkey
>      2336   wifi.py
>
> 10 file(s), 1 dir(s)
>
> => load mmc 0:6 85000000 /root/persist_data.lst
> Failed to load '/root/persist_data.lst'
> => ls mmc 0:6 /root                           
> =>
>
>> Here I have two questions:
>> 1) can someone check my patch end tell me where I goofed?
>> 2) is this supposedly the right way to fix? One other suggestion I had
>> on IRC is to simply implement __udivdi3/__umoddi3 in my architecture
>> (i.e.: u-boot/arch/mips/lib), but that doesn't seem like what has been
>> done in other places. I would like to provide an upstreamable patch.
>>
>>
>> ==8<--- Here comes the (tentative) patch==================================
>> From cfd07aac0aa00345df1a0f2fac04ee549c78f87a Mon Sep 17 00:00:00 2001
>> From: Mauro Condarelli <mc5686 at mclink.it>
>> Date: Thu, 3 Sep 2020 08:37:58 +0200
>> Subject: [PATCH 4/4] Fix missing __udivdi3 in SquashFS implementation.
>>
>> Signed-off-by: Mauro Condarelli <mc5686 at mclink.it>
>> ---
>>  fs/squashfs/sqfs.c       | 27 ++++++++++++++++-----------
>>  fs/squashfs/sqfs_inode.c | 11 +++++++++--
>>  2 files changed, 25 insertions(+), 13 deletions(-)
>>
>> diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
>> index f67f7c4a40..12115b6baa 100644
>> --- a/fs/squashfs/sqfs.c
>> +++ b/fs/squashfs/sqfs.c
>> @@ -23,6 +23,12 @@
>>  #include "sqfs_filesystem.h"
>>  #include "sqfs_utils.h"
>>  
>> +#include <div64.h>
>> +#ifdef DIV_ROUND_UP
>> +#undef DIV_ROUND_UP
>> +#endif
>> +#define DIV_ROUND_UP(n,d) (lldiv(((n) + (d) - 1), (d)))
>> +
>>  static struct squashfs_ctxt ctxt;
>>  
>>  static int sqfs_disk_read(__u32 block, __u32 nr_blocks, void *buf)
>> @@ -85,7 +91,7 @@ static int sqfs_calc_n_blks(__le64 start, __le64 end, u64 *offset)
>>      u64 start_, table_size;
>>  
>>      table_size = le64_to_cpu(end) - le64_to_cpu(start);
>> -    start_ = le64_to_cpu(start) / ctxt.cur_dev->blksz;
>> +    start_ = lldiv(le64_to_cpu(start), ctxt.cur_dev->blksz);
>>      *offset = le64_to_cpu(start) - (start_ * ctxt.cur_dev->blksz);
>>  
>>      return DIV_ROUND_UP(table_size + *offset, ctxt.cur_dev->blksz);
>> @@ -109,8 +115,8 @@ static int sqfs_frag_lookup(u32 inode_fragment_index,
>>      if (inode_fragment_index >= get_unaligned_le32(&sblk->fragments))
>>          return -EINVAL;
>>  
>> -    start = get_unaligned_le64(&sblk->fragment_table_start) /
>> -        ctxt.cur_dev->blksz;
>> +    start = lldiv(get_unaligned_le64(&sblk->fragment_table_start),
>> +        ctxt.cur_dev->blksz);
>>      n_blks = sqfs_calc_n_blks(sblk->fragment_table_start,
>>                    sblk->export_table_start,
>>                    &table_offset);
>> @@ -135,7 +141,7 @@ static int sqfs_frag_lookup(u32 inode_fragment_index,
>>      start_block = get_unaligned_le64(table + table_offset + block *
>>                       sizeof(u64));
>>  
>> -    start = start_block / ctxt.cur_dev->blksz;
>> +    start = lldiv(start_block, ctxt.cur_dev->blksz);
>>      n_blks = sqfs_calc_n_blks(cpu_to_le64(start_block),
>>                    sblk->fragment_table_start, &table_offset);
>>  
>> @@ -641,8 +647,8 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
>>  
>>      table_size = get_unaligned_le64(&sblk->directory_table_start) -
>>          get_unaligned_le64(&sblk->inode_table_start);
>> -    start = get_unaligned_le64(&sblk->inode_table_start) /
>> -        ctxt.cur_dev->blksz;
>> +    start = lldiv(get_unaligned_le64(&sblk->inode_table_start),
>> +        ctxt.cur_dev->blksz);
>>      n_blks = sqfs_calc_n_blks(sblk->inode_table_start,
>>                    sblk->directory_table_start, &table_offset);
>>  
>> @@ -725,8 +731,8 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list)
>>      /* DIRECTORY TABLE */
>>      table_size = get_unaligned_le64(&sblk->fragment_table_start) -
>>          get_unaligned_le64(&sblk->directory_table_start);
>> -    start = get_unaligned_le64(&sblk->directory_table_start) /
>> -        ctxt.cur_dev->blksz;
>> +    start = lldiv(get_unaligned_le64(&sblk->directory_table_start),
>> +        ctxt.cur_dev->blksz);
>>      n_blks = sqfs_calc_n_blks(sblk->directory_table_start,
>>                    sblk->fragment_table_start, &table_offset);
>>  
>> @@ -1328,7 +1333,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
>>      }
>>  
>>      for (j = 0; j < datablk_count; j++) {
>> -        start = data_offset / ctxt.cur_dev->blksz;
>> +        start = lldiv(data_offset, ctxt.cur_dev->blksz);
>>          table_size = SQFS_BLOCK_SIZE(finfo.blk_sizes[j]);
>>          table_offset = data_offset - (start * ctxt.cur_dev->blksz);
>>          n_blks = DIV_ROUND_UP(table_size + table_offset,
>> @@ -1382,7 +1387,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
>>          goto free_buffer;
>>      }
>>  
>> -    start = frag_entry.start / ctxt.cur_dev->blksz;
>> +    start = lldiv(frag_entry.start, ctxt.cur_dev->blksz);
>>      table_size = SQFS_BLOCK_SIZE(frag_entry.size);
>>      table_offset = frag_entry.start - (start * ctxt.cur_dev->blksz);
>>      n_blks = DIV_ROUND_UP(table_size + table_offset, ctxt.cur_dev->blksz);
>> diff --git a/fs/squashfs/sqfs_inode.c b/fs/squashfs/sqfs_inode.c
>> index 1387779a85..cfb2b8374c 100644
>> --- a/fs/squashfs/sqfs_inode.c
>> +++ b/fs/squashfs/sqfs_inode.c
>> @@ -16,6 +16,13 @@
>>  #include "sqfs_filesystem.h"
>>  #include "sqfs_utils.h"
>>  
>> +#include <div64.h>
>> +#ifdef DIV_ROUND_UP
>> +#undef DIV_ROUND_UP
>> +#endif
>> +#define DIV_ROUND_UP(n,d) (lldiv(((n) + (d) - 1), (d)))
>> +
>> +
>>  int sqfs_inode_size(struct squashfs_base_inode *inode, u32 blk_size)
>>  {
>>      switch (get_unaligned_le16(&inode->inode_type)) {
>> @@ -30,7 +37,7 @@ int sqfs_inode_size(struct squashfs_base_inode *inode, u32 blk_size)
>>          unsigned int blk_list_size;
>>  
>>          if (SQFS_IS_FRAGMENTED(fragment))
>> -            blk_list_size = file_size / blk_size;
>> +            blk_list_size = lldiv(file_size, blk_size);
>>          else
>>              blk_list_size = DIV_ROUND_UP(file_size, blk_size);
>>  
>> @@ -70,7 +77,7 @@ int sqfs_inode_size(struct squashfs_base_inode *inode, u32 blk_size)
>>          if (fragment == 0xFFFFFFFF)
>>              blk_list_size = DIV_ROUND_UP(file_size, blk_size);
>>          else
>> -            blk_list_size = file_size / blk_size;
>> +            blk_list_size = lldiv(file_size, blk_size);
>>  
>>          return sizeof(*lreg) + blk_list_size * sizeof(u32);
>>      }



More information about the U-Boot mailing list