Skip to contentSkip to conversation

mtd-utils: improve compatibility with klibc

PATCH Superseded Andrea Adami 1 participant 4 messages Jan 25, 2018 – Jan 28, 2018

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover mtd-utils: improve compatibility with klibc

Klibc does not support floating point calculations.
Here some fixes needed to build the ubi-utils against klibc for aarch64, without FPU.

These lines end up compiled with soft float for other arm targets w/out FPU thus this was discovered only cross-building for qemuarm64 using the flag
'-mgeneral-regs-only'.

Changes tested on armv5, same output is printed.

Andrea Adami (2):
mtd-utils: common.c: convert to integer arithmetic
ubi-utils: ubiformat.c: convert to integer arithmetic.

 lib/common.c          | 15 +++++++++------
 ubi-utils/ubiformat.c |  2 +-
 2 files changed, 10 insertions(+), 7 deletions(-)
Signature · 1 line
2.7.4
#1 lore raw

PATCH 1/2 mtd-utils: common.c: convert to integer arithmetic

We use floating point just to print out KiB, MiB, GiB. Avoid that to be klibc friendly.

Fixes compilation for aarch64 against klibc:

error: '-mgeneral-regs-only' is incompatible with floating-point argument
| printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
etc.

Note:
* In the KiB case, we could apparently multiply by 100 before dividing without risking overflow. This code simply avoids multiplications.

---
 lib/common.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
lib/common.c +9 -6
index 69b03b3..5e28853 100644
@@ -107,6 +107,9 @@ long long util_get_bytes(const char *str)
 void util_print_bytes(long long bytes, int bracket)
 {
 	const char *p;
+	int GiB = 1024 * 1024 * 1024;
+	int MiB = 1024 * 1024;
+	int KiB = 1024;
 
 	if (bracket)
 		p = " (";
@@ -115,12 +118,12 @@ void util_print_bytes(long long bytes, int bracket)
 
 	printf("%lld bytes", bytes);
 
-	if (bytes > 1024 * 1024 * 1024)
-		printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
-	else if (bytes > 1024 * 1024)
-		printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
-	else if (bytes > 1024 && bytes != 0)
-		printf("%s%.1f KiB", p, (double)bytes / 1024);
+	if (bytes > GiB)
+		printf("%s%d.%d GiB", p, bytes / GiB, bytes % GiB / (GiB / 10));
+	else if (bytes > MiB)
+		printf("%s%d.%d MiB", p, bytes / MiB, bytes % MiB / (MiB / 10));
+	else if (bytes > KiB && bytes != 0)
+		printf("%s%d.%d KiB", p, bytes / KiB, bytes % KiB / (KiB / 10));
 	else
 		return;
 
Signature · 1 line
2.7.4
#2 lore raw

Re: [PATCH 1/2] mtd-utils: common.c: convert to integer arithmetic

Quoted 52 lines · Andrea Adami

We use floating point just to print out KiB, MiB, GiB. Avoid that to be klibc friendly.

Fixes compilation for aarch64 against klibc:

error: '-mgeneral-regs-only' is incompatible with floating-point argument
| printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
etc.

Note:
* In the KiB case, we could apparently multiply by 100 before dividing without risking overflow. This code simply avoids multiplications.

---
 lib/common.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)
lib/common.c +9 -7
index 69b03b3..5e28853 100644
@@ -107,6 +107,9 @@ long long util_get_bytes(const char *str)
 void util_print_bytes(long long bytes, int bracket)
 {
        const char *p;
+       int GiB = 1024 * 1024 * 1024;
+       int MiB = 1024 * 1024;
+       int KiB = 1024;
 
        if (bracket)
                p = " (";
@@ -115,12 +118,12 @@ void util_print_bytes(long long bytes, int bracket)
 
        printf("%lld bytes", bytes);
 
-       if (bytes > 1024 * 1024 * 1024)
-               printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
-       else if (bytes > 1024 * 1024)
-               printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
-       else if (bytes > 1024 && bytes != 0)
-               printf("%s%.1f KiB", p, (double)bytes / 1024);
+       if (bytes > GiB)
+               printf("%s%d.%d GiB", p, bytes / GiB, bytes % GiB / (GiB / 10));
+       else if (bytes > MiB)
+               printf("%s%d.%d MiB", p, bytes / MiB, bytes % MiB / (MiB / 10));
+       else if (bytes > KiB && bytes != 0)
+               printf("%s%d.%d KiB", p, bytes / KiB, bytes % KiB / (KiB / 10));
        else
                return;
 
--
Quoted 2 lines

2.7.4

Missing cast to integer, the right specifier here would be %lld and not %d. Building 1.5.2-klibc I had no warnings but now I see them with 2.0.1. I'll send a v2.

Regards
Andrea

#3 lore raw

PATCH 2/2 ubi-utils: ubiformat.c: convert to integer arithmetic

In reply to Andrea Adami

Do not cast percent to double, it is just used as upper limit. Avoid floating point to fix compilation for aarch64 against klibc:

error: '-mgeneral-regs-only' is incompatible with floating-point code
| int percent = ((double)si->ok_cnt)/si->good_cnt * 100;
| ^~~~~~~

Notes:
* The checks in the code above this line ensure that si->good_cnt is not 0.

* The code assumes si->good_cnt * 100 will not overflow, then we can use (si->ok_cnt * 100) safely because the former is bigger.

* The truncated result does not affect the logic:
i.e. a value of 49.9 is truncated to 49 and is still <50.

---
 ubi-utils/ubiformat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
ubi-utils/ubiformat.c +1 -1
index ef0378a..c38b9b4 100644
@@ -844,7 +844,7 @@ int main(int argc, char * const argv[])
 	}
 
 	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
-		int percent = ((double)si->ok_cnt)/si->good_cnt * 100;
+		int percent = (si->ok_cnt * 100) / si->good_cnt;
 
 		/*
 		 * Make sure the majority of eraseblocks have valid
Signature · 1 line
2.7.4