Skip to contentSkip to conversation

ubi: kill homegrown endian macros

PATCH In review Christoph Hellwig 14 participants 38 messages May 17, 2007 – May 20, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ubi: kill homegrown endian macros

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

drivers/mtd/ubi/debug.c +19 -19
Index: linux-2.6/drivers/mtd/ubi/debug.c
===================================================================
@@ -35,12 +35,12 @@
 void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
 {
 	dbg_msg("erase counter header dump:");
-	dbg_msg("magic          %#08x", ubi32_to_cpu(ec_hdr->magic));
+	dbg_msg("magic          %#08x", be32_to_cpu(ec_hdr->magic));
 	dbg_msg("version        %d",    (int)ec_hdr->version);
-	dbg_msg("ec             %llu",  (long long)ubi64_to_cpu(ec_hdr->ec));
-	dbg_msg("vid_hdr_offset %d",    ubi32_to_cpu(ec_hdr->vid_hdr_offset));
-	dbg_msg("data_offset    %d",    ubi32_to_cpu(ec_hdr->data_offset));
-	dbg_msg("hdr_crc        %#08x", ubi32_to_cpu(ec_hdr->hdr_crc));
+	dbg_msg("ec             %llu",  (long long)be64_to_cpu(ec_hdr->ec));
+	dbg_msg("vid_hdr_offset %d",    be32_to_cpu(ec_hdr->vid_hdr_offset));
+	dbg_msg("data_offset    %d",    be32_to_cpu(ec_hdr->data_offset));
+	dbg_msg("hdr_crc        %#08x", be32_to_cpu(ec_hdr->hdr_crc));
 	dbg_msg("erase counter header hexdump:");
 	ubi_dbg_hexdump(ec_hdr, UBI_EC_HDR_SIZE);
 }
@@ -52,20 +52,20 @@ void ubi_dbg_dump_ec_hdr(const struct ub
 void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
 {
 	dbg_msg("volume identifier header dump:");
-	dbg_msg("magic     %08x", ubi32_to_cpu(vid_hdr->magic));
+	dbg_msg("magic     %08x", be32_to_cpu(vid_hdr->magic));
 	dbg_msg("version   %d",   (int)vid_hdr->version);
 	dbg_msg("vol_type  %d",   (int)vid_hdr->vol_type);
 	dbg_msg("copy_flag %d",   (int)vid_hdr->copy_flag);
 	dbg_msg("compat    %d",   (int)vid_hdr->compat);
-	dbg_msg("vol_id    %d",   ubi32_to_cpu(vid_hdr->vol_id));
-	dbg_msg("lnum      %d",   ubi32_to_cpu(vid_hdr->lnum));
-	dbg_msg("leb_ver   %u",   ubi32_to_cpu(vid_hdr->leb_ver));
-	dbg_msg("data_size %d",   ubi32_to_cpu(vid_hdr->data_size));
-	dbg_msg("used_ebs  %d",   ubi32_to_cpu(vid_hdr->used_ebs));
-	dbg_msg("data_pad  %d",   ubi32_to_cpu(vid_hdr->data_pad));
+	dbg_msg("vol_id    %d",   be32_to_cpu(vid_hdr->vol_id));
+	dbg_msg("lnum      %d",   be32_to_cpu(vid_hdr->lnum));
+	dbg_msg("leb_ver   %u",   be32_to_cpu(vid_hdr->leb_ver));
+	dbg_msg("data_size %d",   be32_to_cpu(vid_hdr->data_size));
+	dbg_msg("used_ebs  %d",   be32_to_cpu(vid_hdr->used_ebs));
+	dbg_msg("data_pad  %d",   be32_to_cpu(vid_hdr->data_pad));
 	dbg_msg("sqnum     %llu",
-		(unsigned long long)ubi64_to_cpu(vid_hdr->sqnum));
-	dbg_msg("hdr_crc   %08x", ubi32_to_cpu(vid_hdr->hdr_crc));
+		(unsigned long long)be64_to_cpu(vid_hdr->sqnum));
+	dbg_msg("hdr_crc   %08x", be32_to_cpu(vid_hdr->hdr_crc));
 	dbg_msg("volume identifier header hexdump:");
 }
 
@@ -106,12 +106,12 @@ void ubi_dbg_dump_vol_info(const struct 
  */
 void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
 {
-	int name_len = ubi16_to_cpu(r->name_len);
+	int name_len = be16_to_cpu(r->name_len);
 
 	dbg_msg("volume table record %d dump:", idx);
-	dbg_msg("reserved_pebs   %d", ubi32_to_cpu(r->reserved_pebs));
-	dbg_msg("alignment       %d", ubi32_to_cpu(r->alignment));
-	dbg_msg("data_pad        %d", ubi32_to_cpu(r->data_pad));
+	dbg_msg("reserved_pebs   %d", be32_to_cpu(r->reserved_pebs));
+	dbg_msg("alignment       %d", be32_to_cpu(r->alignment));
+	dbg_msg("data_pad        %d", be32_to_cpu(r->data_pad));
 	dbg_msg("vol_type        %d", (int)r->vol_type);
 	dbg_msg("upd_marker      %d", (int)r->upd_marker);
 	dbg_msg("name_len        %d", name_len);
@@ -129,7 +129,7 @@ void ubi_dbg_dump_vtbl_record(const stru
 			r->name[0], r->name[1], r->name[2], r->name[3],
 			r->name[4]);
 	}
-	dbg_msg("crc             %#08x", ubi32_to_cpu(r->crc));
+	dbg_msg("crc             %#08x", be32_to_cpu(r->crc));
 }
 
 /**
drivers/mtd/ubi/eba.c +31 -31

141 lines not on this page · raw message

drivers/mtd/ubi/io.c +23 -23

123 lines not on this page · raw message

drivers/mtd/ubi/scan.c +28 -28

169 lines not on this page · raw message

drivers/mtd/ubi/vmt.c +9 -9
Index: linux-2.6/drivers/mtd/ubi/vmt.c
===================================================================
@@ -320,10 +320,10 @@ int ubi_create_volume(struct ubi_device 
 
 	/* Fill volume table record */
 	memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
-	vtbl_rec.reserved_pebs = cpu_to_ubi32(vol->reserved_pebs);
-	vtbl_rec.alignment     = cpu_to_ubi32(vol->alignment);
-	vtbl_rec.data_pad      = cpu_to_ubi32(vol->data_pad);
-	vtbl_rec.name_len      = cpu_to_ubi16(vol->name_len);
+	vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs);
+	vtbl_rec.alignment     = cpu_to_be32(vol->alignment);
+	vtbl_rec.data_pad      = cpu_to_be32(vol->data_pad);
+	vtbl_rec.name_len      = cpu_to_be16(vol->name_len);
 	if (vol->vol_type == UBI_DYNAMIC_VOLUME)
 		vtbl_rec.vol_type = UBI_VID_DYNAMIC;
 	else
@@ -503,7 +503,7 @@ int ubi_resize_volume(struct ubi_volume_
 
 	/* Change volume table record */
 	memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record));
-	vtbl_rec.reserved_pebs = cpu_to_ubi32(reserved_pebs);
+	vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
 	err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
 	if (err)
 		goto out_acc;
@@ -651,7 +651,7 @@ static void paranoid_check_volume(const 
 	long long n;
 	const char *name;
 
-	reserved_pebs = ubi32_to_cpu(ubi->vtbl[vol_id].reserved_pebs);
+	reserved_pebs = be32_to_cpu(ubi->vtbl[vol_id].reserved_pebs);
 
 	if (!vol) {
 		if (reserved_pebs) {
@@ -765,9 +765,9 @@ static void paranoid_check_volume(const 
 		}
 	}
 
-	alignment  = ubi32_to_cpu(ubi->vtbl[vol_id].alignment);
-	data_pad   = ubi32_to_cpu(ubi->vtbl[vol_id].data_pad);
-	name_len   = ubi16_to_cpu(ubi->vtbl[vol_id].name_len);
+	alignment  = be32_to_cpu(ubi->vtbl[vol_id].alignment);
+	data_pad   = be32_to_cpu(ubi->vtbl[vol_id].data_pad);
+	name_len   = be16_to_cpu(ubi->vtbl[vol_id].name_len);
 	upd_marker = ubi->vtbl[vol_id].upd_marker;
 	name       = &ubi->vtbl[vol_id].name[0];
 	if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC)
drivers/mtd/ubi/vtbl.c +20 -20
Index: linux-2.6/drivers/mtd/ubi/vtbl.c
===================================================================
@@ -93,7 +93,7 @@ int ubi_change_vtbl_record(struct ubi_de
 		vtbl_rec = &empty_vtbl_record;
 	else {
 		crc = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
-		vtbl_rec->crc = cpu_to_ubi32(crc);
+		vtbl_rec->crc = cpu_to_be32(crc);
 	}
 
 	dbg_msg("change record %d", idx);
@@ -141,18 +141,18 @@ static int vtbl_check(const struct ubi_d
 	for (i = 0; i < ubi->vtbl_slots; i++) {
 		cond_resched();
 
-		reserved_pebs = ubi32_to_cpu(vtbl[i].reserved_pebs);
-		alignment = ubi32_to_cpu(vtbl[i].alignment);
-		data_pad = ubi32_to_cpu(vtbl[i].data_pad);
+		reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
+		alignment = be32_to_cpu(vtbl[i].alignment);
+		data_pad = be32_to_cpu(vtbl[i].data_pad);
 		upd_marker = vtbl[i].upd_marker;
 		vol_type = vtbl[i].vol_type;
-		name_len = ubi16_to_cpu(vtbl[i].name_len);
+		name_len = be16_to_cpu(vtbl[i].name_len);
 		name = &vtbl[i].name[0];
 
 		crc = crc32(UBI_CRC32_INIT, &vtbl[i], UBI_VTBL_RECORD_SIZE_CRC);
-		if (ubi32_to_cpu(vtbl[i].crc) != crc) {
+		if (be32_to_cpu(vtbl[i].crc) != crc) {
 			ubi_err("bad CRC at record %u: %#08x, not %#08x",
-				 i, crc, ubi32_to_cpu(vtbl[i].crc));
+				 i, crc, be32_to_cpu(vtbl[i].crc));
 			ubi_dbg_dump_vtbl_record(&vtbl[i], i);
 			return 1;
 		}
@@ -225,8 +225,8 @@ static int vtbl_check(const struct ubi_d
 	/* Checks that all names are unique */
 	for (i = 0; i < ubi->vtbl_slots - 1; i++) {
 		for (n = i + 1; n < ubi->vtbl_slots; n++) {
-			int len1 = ubi16_to_cpu(vtbl[i].name_len);
-			int len2 = ubi16_to_cpu(vtbl[n].name_len);
+			int len1 = be16_to_cpu(vtbl[i].name_len);
+			int len2 = be16_to_cpu(vtbl[n].name_len);
 
 			if (len1 > 0 && len1 == len2 &&
 			    !strncmp(vtbl[i].name, vtbl[n].name, len1)) {
@@ -288,13 +288,13 @@ retry:
 	}
 
 	vid_hdr->vol_type = UBI_VID_DYNAMIC;
-	vid_hdr->vol_id = cpu_to_ubi32(UBI_LAYOUT_VOL_ID);
+	vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOL_ID);
 	vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT;
 	vid_hdr->data_size = vid_hdr->used_ebs =
-			     vid_hdr->data_pad = cpu_to_ubi32(0);
-	vid_hdr->lnum = cpu_to_ubi32(copy);
-	vid_hdr->sqnum = cpu_to_ubi64(++si->max_sqnum);
-	vid_hdr->leb_ver = cpu_to_ubi32(old_seb ? old_seb->leb_ver + 1: 0);
+			     vid_hdr->data_pad = cpu_to_be32(0);
+	vid_hdr->lnum = cpu_to_be32(copy);
+	vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum);
+	vid_hdr->leb_ver = cpu_to_be32(old_seb ? old_seb->leb_ver + 1: 0);
 
 	/* The EC header is already there, write the VID header */
 	err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr);
@@ -500,19 +500,19 @@ static int init_volumes(struct ubi_devic
 	for (i = 0; i < ubi->vtbl_slots; i++) {
 		cond_resched();
 
-		if (ubi32_to_cpu(vtbl[i].reserved_pebs) == 0)
+		if (be32_to_cpu(vtbl[i].reserved_pebs) == 0)
 			continue; /* Empty record */
 
 		vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);
 		if (!vol)
 			return -ENOMEM;
 
-		vol->reserved_pebs = ubi32_to_cpu(vtbl[i].reserved_pebs);
-		vol->alignment = ubi32_to_cpu(vtbl[i].alignment);
-		vol->data_pad = ubi32_to_cpu(vtbl[i].data_pad);
+		vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
+		vol->alignment = be32_to_cpu(vtbl[i].alignment);
+		vol->data_pad = be32_to_cpu(vtbl[i].data_pad);
 		vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ?
 					UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
-		vol->name_len = ubi16_to_cpu(vtbl[i].name_len);
+		vol->name_len = be16_to_cpu(vtbl[i].name_len);
 		vol->usable_leb_size = ubi->leb_size - vol->data_pad;
 		memcpy(vol->name, vtbl[i].name, vol->name_len);
 		vol->name[vol->name_len] = '\0';
@@ -718,7 +718,7 @@ int ubi_read_volume_table(struct ubi_dev
 	int i, err;
 	struct ubi_scan_volume *sv;
 
-	empty_vtbl_record.crc = cpu_to_ubi32(0xf116c36b);
+	empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
 
 	/*
 	 * The number of supported volumes is limited by the eraseblock size
include/mtd/ubi-header.h +36 -65

136 lines not on this page · raw message

drivers/mtd/ubi/wl.c +2 -2
Index: linux-2.6/drivers/mtd/ubi/wl.c
===================================================================
@@ -667,7 +667,7 @@ static int sync_erase(struct ubi_device 
 
 	dbg_wl("erased PEB %d, new EC %llu", e->pnum, ec);
 
-	ec_hdr->ec = cpu_to_ubi64(ec);
+	ec_hdr->ec = cpu_to_be64(ec);
 
 	err = ubi_io_write_ec_hdr(ubi, e->pnum, ec_hdr);
 	if (err)
@@ -1633,7 +1633,7 @@ static int paranoid_check_ec(const struc
 		goto out_free;
 	}
 
-	read_ec = ubi64_to_cpu(ec_hdr->ec);
+	read_ec = be64_to_cpu(ec_hdr->ec);
 	if (ec != read_ec) {
 		ubi_err("paranoid check failed for PEB %d", pnum);
 		ubi_err("read EC is %lld, should be %d", read_ec, ec);
#1 lore raw

Christoph,

Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

Err,__be32 and the company are just sparse things, while I have compiler checks with my struct ubi32_t and friends. JFFS2 also uses the same technique. Why do you force me to rely on sparse instead instead of compiler?

Well, I see the good side of your change - no home-brewed media<->cpu things. Fair enough and nice. But why don't you make __be32 a struct (just like I do) so that compiler could complain then?

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
#2 lore raw
Quoted 10 lines · Artem Bityutskiy

Christoph,

Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

Err,__be32 and the company are just sparse things, while I have compiler checks with my struct ubi32_t and friends. JFFS2 also uses the same technique. Why do you force me to rely on sparse instead instead of compiler?

Yes. Like all other code in the kernel aswell.

#3 lore raw
Quoted 7 lines · Christoph Hellwig
Quoted 6 lines · Artem Bityutskiy

Christoph,

Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

Quoted 6 lines
Quoted 4 lines

Err,__be32 and the company are just sparse things, while I have compiler checks with my struct ubi32_t and friends. JFFS2 also uses the same technique. Why do you force me to rely on sparse instead instead of compiler?

Yes. Like all other code in the kernel aswell.

Andrew, may I please have your ack that I absolutely have to use __be32 instead of my own types since Christoph tends to provide no explanation to his requests.

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
#4 lore raw
Quoted 13 lines · On Thu, 17 May 2007 18:09:50 +0300 Artem Bityutskiy <[email protected]>…
Quoted 12 lines · Christoph Hellwig
Quoted 10 lines · Artem Bityutskiy

Christoph,

Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

Err,__be32 and the company are just sparse things, while I have compiler checks with my struct ubi32_t and friends. JFFS2 also uses the same technique. Why do you force me to rely on sparse instead instead of compiler?

Quoted 5 lines
Quoted 1 line

Yes. Like all other code in the kernel aswell.

Andrew, may I please have your ack that I absolutely have to use __be32 instead of my own types since Christoph tends to provide no explanation to his requests.

umm.. I'd say what you've done in there is an improvement to the exiting
stuff: getting gcc to check it is better than having to use sparse.

I'd have expected gcc to generate poorer code with your approach but I'm showing zero text size changes from Christoph's patch (gcc-4.1 and gcc-3.4.5).

So I wouldn't be averse to creating a new, generic, kernel-wide alternative to the existing __be32/__le32/etc code. It is an improvement.

But I don't think we want driver-private implementations.

We could conceivably simply switch the existing stuff to use structs, but quite a lot of code assumes that cpu_to_foo32(0) == 0 and just does open-coded assigments of zero. They'd need fixups.

#5 lore raw
Quoted 7 lines · Andrew Morton

umm.. I'd say what you've done in there is an improvement to the exiting
stuff: getting gcc to check it is better than having to use sparse.

I'd have expected gcc to generate poorer code with your approach but I'm showing zero text size changes from Christoph's patch (gcc-4.1 and gcc-3.4.5).

Quoted 6 lines

So I wouldn't be averse to creating a new, generic, kernel-wide alternative to the existing __be32/__le32/etc code. It is an improvement.

We could conceivably simply switch the existing stuff to use structs, but quite a lot of code assumes that cpu_to_foo32(0) == 0 and just does open-coded assigments of zero. They'd need fixups.

Andrew,

thanks for answer. I personally do not think this should be applied before we have better __be32 and friends. Thus, if I can do so, I will just sit and wait for your decision - whether you include this patch to -mm or not :-) .

Signature · 2 lines
Best regards,
Artem Bityutskiy (Битюцкий Артём)
#6 lore raw
Quoted 15 lines · On Thu, 17 May 2007 20:46:46 +0300 Artem Bityutskiy <[email protected]>…
Quoted 7 lines · Andrew Morton

umm.. I'd say what you've done in there is an improvement to the exiting
stuff: getting gcc to check it is better than having to use sparse.

I'd have expected gcc to generate poorer code with your approach but I'm showing zero text size changes from Christoph's patch (gcc-4.1 and gcc-3.4.5).

Quoted 6 lines

So I wouldn't be averse to creating a new, generic, kernel-wide alternative to the existing __be32/__le32/etc code. It is an improvement.

We could conceivably simply switch the existing stuff to use structs, but quite a lot of code assumes that cpu_to_foo32(0) == 0 and just does open-coded assigments of zero. They'd need fixups.

Quoted 7 lines

Andrew,

thanks for answer. I personally do not think this should be applied before we have better __be32 and friends. Thus, if I can do so, I will just sit and wait for your decision - whether you include this patch to -mm or not :-) .

Drat, and here was I hoping I'd lured you into implementing the generic code.

#7 lore raw
Quoted 2 lines · Andrew Morton

Drat, and here was I hoping I'd lured you into implementing the generic code.

Well, I am really happy to contribute, but I am not a generic janitor like
Cristoph, who (amaizingly) knows many differet kernel subsystems. I am a specific developer and I would rather concentrate on the Flash file system I am writing, and this will be my later contribution.

Artem.

#8 lore raw
In reply to Andrew Morton
Quoted 12 lines · Andrew Morton

On Thu, 17 May 2007 18:09:50 +0300 Artem Bityutskiy <[email protected]> wrote:

umm.. I'd say what you've done in there is an improvement to the exiting stuff: getting gcc to check it is better than having to use sparse.

I'd have expected gcc to generate poorer code with your approach but I'm showing zero text size changes from Christoph's patch (gcc-4.1 and gcc-3.4.5).

On which arch did you try ?
X86 where unaligned access are ok ?

On arch that don't support aligned access, packed struct access will be done byte per byte (but it could be the expected behavior if there unaligned access).

Matthieu

#9 lore raw
Quoted 14 lines · Matthieu CASTET
Quoted 12 lines · Andrew Morton

On Thu, 17 May 2007 18:09:50 +0300 Artem Bityutskiy <[email protected]> wrote:

umm.. I'd say what you've done in there is an improvement to the exiting stuff: getting gcc to check it is better than having to use sparse.

I'd have expected gcc to generate poorer code with your approach but I'm showing zero text size changes from Christoph's patch (gcc-4.1 and gcc-3.4.5).

Quoted 6 lines

On which arch did you try ?
X86 where unaligned access are ok ?

On arch that don't support aligned access, packed struct access will be done byte per byte (but it could be the expected behavior if there unaligned access).

When I tested this on ARM, the output for je32_to_cpu et al was fine. For _other_ structures where I'd used __attribute__((packed)) to be safe, gcc would emit code to handle unaligned loads. But not in the simple case where the struct has only one member.

Are you suggesting that this has changed since I did my testing?

Signature · 1 line
dwmw2
#10 lore raw
Quoted 22 lines · David Woodhouse
Quoted 14 lines · Matthieu CASTET
Quoted 12 lines · Andrew Morton

On Thu, 17 May 2007 18:09:50 +0300 Artem Bityutskiy <[email protected]> wrote:

umm.. I'd say what you've done in there is an improvement to the exiting stuff: getting gcc to check it is better than having to use sparse.

I'd have expected gcc to generate poorer code with your approach but I'm showing zero text size changes from Christoph's patch (gcc-4.1 and gcc-3.4.5).

Quoted 6 lines

On which arch did you try ?
X86 where unaligned access are ok ?

On arch that don't support aligned access, packed struct access will be done byte per byte (but it could be the expected behavior if there unaligned access).

Quoted 6 lines

When I tested this on ARM, the output for je32_to_cpu et al was fine. For _other_ structures where I'd used __attribute__((packed)) to be safe, gcc would emit code to handle unaligned loads. But not in the simple case where the struct has only one member.

Are you suggesting that this has changed since I did my testing?

Wouldn't the appropriate test be to demonstrate that the same program text opcodes are generated in both cases for all architectures? If that's not the case, even if the generation isn't -worse-, it shows that the compiler is doing different things with each, which means different versions of the compiler could do different things with it, and all of a sudden another nice programming construct which helps compile-time issues ends up increasing the number of cases where compiler differences generate faster or slower kernels with the same code, whereas in the test cases it was "no better, no worse" so deemed fine.

#11 lore raw
Quoted 2 lines · John Anthony Kazos Jr.

Wouldn't the appropriate test be to demonstrate that the same program text opcodes are generated in both cases for all architectures?

No, empirical testing with the compiler is never the _correct_ thing to do. It's just expedient.

Quoted 3 lines

If that's not the case, even if the generation isn't -worse-, it shows that the compiler is doing different things with each, which means different versions of the compiler could do different things with it,

Well yes, but even it _is_ generating precisely the same output today, there's no reason why the compiler shouldn't behave differently under a different phase of the moon.

The _correct_ thing to do is act upon my mutterings at the time I removed the '__attribute__((packed))' from various JFFS2 structures to improve the generated code on ARM -- actually implement an attribute for GCC which has the same "don't insert any padding" meaning, but without the unwanted "assume arbitrary alignment" implications.

It'd actually be nice if GCC knew about endianness too. I don't want to have to do:

   *x = le32_to_cpu(cpu_to_le32(*x) + 5);

I just want

  uint32_t __attribute__((littleendian)) *x;

  *x += 5;

I know we can hack around it for masks, with '*x |= cpu_to_le32(X_BAR);' and such like, and we can load it into local native-endian variables and then copy it back again later -- but it's better just to let the compiler know what's going on and do its own optimisation. Especially on architectures which have 'load-and-swap' or 'store-and-swap' instructions.

Signature · 1 line
dwmw2
#12 lore raw
Quoted 15 lines · David Woodhouse
Quoted 2 lines · John Anthony Kazos Jr.

Wouldn't the appropriate test be to demonstrate that the same program text opcodes are generated in both cases for all architectures?

No, empirical testing with the compiler is never the _correct_ thing to do. It's just expedient.

Quoted 3 lines

If that's not the case, even if the generation isn't -worse-, it shows that the compiler is doing different things with each, which means different versions of the compiler could do different things with it,

Well yes, but even it _is_ generating precisely the same output today, there's no reason why the compiler shouldn't behave differently under a different phase of the moon.

Quoted 5 lines

The _correct_ thing to do is act upon my mutterings at the time I removed the '__attribute__((packed))' from various JFFS2 structures to improve the generated code on ARM -- actually implement an attribute for GCC which has the same "don't insert any padding" meaning, but without the unwanted "assume arbitrary alignment" implications.

Out of curiosity, why would a compiler ever insert padding in a structure that has all its elements properly-aligned?

Quoted 17 lines

It'd actually be nice if GCC knew about endianness too. I don't want to have to do:

   *x = le32_to_cpu(cpu_to_le32(*x) + 5);

I just want

  uint32_t __attribute__((littleendian)) *x;

  *x += 5;

I know we can hack around it for masks, with '*x |= cpu_to_le32(X_BAR);' and such like, and we can load it into local native-endian variables and then copy it back again later -- but it's better just to let the compiler know what's going on and do its own optimisation. Especially on architectures which have 'load-and-swap' or 'store-and-swap' instructions.

#13 lore raw
Quoted 2 lines · John Anthony Kazos Jr.

Out of curiosity, why would a compiler ever insert padding in a structure that has all its elements properly-aligned?

Well, it might decide it would be nicer if some elements were aligned to 64 bits. Or to a cache line. Or something. I don't care about _why_ -- the point is that it's _allowed_ to. Hence the original use of __attribute__((packed)).

In practice, there's no real reason why it would do such a thing, which is why I removed the packed attribute and replaced it with a runtime check on the size of the structures in question.

Signature · 1 line
dwmw2
#14 lore raw
Quoted 7 lines
Quoted 2 lines

Out of curiosity, why would a compiler ever insert padding in a structure that has all its elements properly-aligned?

Well, it might decide it would be nicer if some elements were aligned to 64 bits. Or to a cache line. Or something. I don't care about _why_ -- the point is that it's _allowed_ to. Hence the original use of __attribute__((packed)).

It's not the compiler who decides -- struct layout is dictated by the ABI you're compiling for.

Segher

#15 lore raw
Quoted 2 lines · Segher Boessenkool

It's not the compiler who decides -- struct layout is dictated by the ABI you're compiling for.

This is true in the case of externally-visible stuff. I think the compiler is permitted to violate the ABI for purely unit-internal things if it makes sense though, isn't it?

Besides, in the case of the Linux kernel the ABI in question could be one of many. It could even be a new one which was added a couple of weeks ago, and which I had no _chance_ of considering.

The rule stands -- empirical testing of what the compiler will do isn't usually the right answer.

Signature · 1 line
dwmw2
#16 lore raw
Quoted 6 lines
Quoted 2 lines

It's not the compiler who decides -- struct layout is dictated by the ABI you're compiling for.

This is true in the case of externally-visible stuff. I think the compiler is permitted to violate the ABI for purely unit-internal things if it makes sense though, isn't it?

Sure. It isn't "violating the ABI" in that case though, to be perfectly clear.

Quoted 3 lines

Besides, in the case of the Linux kernel the ABI in question could be one of many. It could even be a new one which was added a couple of weeks ago, and which I had no _chance_ of considering.

Of course.

Quoted 2 lines

The rule stands -- empirical testing of what the compiler will do isn't usually the right answer.

It is *never* the right answer. You should always write your code so that it will do the right thing no matter what the compiler decides to do to it.

Segher

#17 lore raw
Quoted 10 lines · Segher Boessenkool
Quoted 7 lines
Quoted 2 lines

It's not the compiler who decides -- struct layout is dictated by the ABI you're compiling for.

This is true in the case of externally-visible stuff. I think the compiler is permitted to violate the ABI for purely unit-internal things
if it makes sense though, isn't it?

Sure. It isn't "violating the ABI" in that case though, to be perfectly clear.

Of course. It's not conforming to the ABI because there's no need to.

Quoted 6 lines
Quoted 2 lines

The rule stands -- empirical testing of what the compiler will do isn't usually the right answer.

It is *never* the right answer. You should always write your code so that it will do the right thing no matter what the compiler decides to do to it.

Well, there's sometimes some benefit in _also_ checking that the output of the compiler matches your expectations. :)

Signature · 1 line
dwmw2
#18 lore raw
In reply to David Woodhouse
Quoted 8 lines · David Woodhouse
Quoted 3 lines · Matthieu CASTET
Quoted 1 line · Andrew Morton

On Thu, 17 May 2007 18:09:50 +0300 Artem Bityutskiy

When I tested this on ARM, the output for je32_to_cpu et al was fine. For _other_ structures where I'd used __attribute__((packed)) to be safe, gcc would emit code to handle unaligned loads. But not in the simple case where the struct has only one member.

I don't think it is true.

When porting some summary stuff to bootloader, I hit some unaligned access problem :
in summary.c:405 there is a
switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { and
struct jffs2_sum_unknown_flash
{
jint16_t nodetype; /* node type */
};

note that sp isn't aligned to a 32 bits boundary (it can be anything and depend for example of the size of the dirent name).

if gcc doesn't emit code to handle unaligned loads in this case, there is unaligned access.

When compiling my code for arm, I use a gcc-4.1.1 with a bug and it break. With another compiler (last gcc from codesourcery) it worked (because gcc emit load it bit per bit).

Quoted 3 lines

Are you suggesting that this has changed since I did my testing?

Which version of gcc did you try ?

Matthieu

#19 lore raw
Quoted 3 lines · matthieu castet
Quoted 2 lines

Are you suggesting that this has changed since I did my testing?

Which version of gcc did you try ?

It was a while ago -- probably 3.2 or something like that. I think it might even predate the summary support.

When I get home I'll take another look.

Signature · 1 line
dwmw2
#20 lore raw
In reply to David Woodhouse

Hi,

Quoted 10 lines · David Woodhouse
Quoted 1 line · Matthieu CASTET

On arch that don't support aligned access, packed struct access will be done byte per byte (but it could be the expected behavior if there unaligned access).

When I tested this on ARM, the output for je32_to_cpu et al was fine. For _other_ structures where I'd used __attribute__((packed)) to be safe, gcc would emit code to handle unaligned loads. But not in the simple case where the struct has only one member.

Are you suggesting that this has changed since I did my testing?

here a small example I made and try with a sourcery 2006q3-27

/tmp/arm-2006q3/bin/arm-none-linux-gnueabi-gcc -S test.c -O3 -o test.s.packed /tmp/arm-2006q3/bin/arm-none-linux-gnueabi-gcc -S test.c -DNOP -O3 -o test.s

$diff test.s test.s.packed 19,23c19,34

<       @ link register save eliminated.
<       ldrh    r2, [r1, #0]
<       ldrh    r1, [r0, #2]
<       ldr     r0, [r0, #4]
<       @ lr needed for prologue

---

Quoted 8 lines
      stmfd   sp!, {r4, r5, r6, lr}
      ldrb    r2, [r0, #5]    @ zero_extendqisi2
      ldrb    r3, [r0, #4]    @ zero_extendqisi2
      mov     lr, r1
      ldrb    r4, [r0, #6]    @ zero_extendqisi2
      ldrb    r5, [r0, #3]    @ zero_extendqisi2
      ldrb    r6, [r1, #1]    @ zero_extendqisi2
      orr     r3, r3, r2, asl #8
Quoted 8 lines
      ldrb    r1, [r0, #2]    @ zero_extendqisi2
      ldrb    ip, [r0, #7]    @ zero_extendqisi2
      ldrb    r2, [lr, #0]    @ zero_extendqisi2
      orr     r3, r3, r4, asl #16
      orr     r0, r3, ip, asl #24
      orr     r1, r1, r5, asl #8
      orr     r2, r2, r6, asl #8
      ldmfd   sp!, {r4, r5, r6, lr}

Matthieu

#include <stdint.h>
#ifdef NOP
#define jint32_t uint32_t
#define jint16_t uint16_t

#define je16_to_cpu(x) ((x))
#define je32_to_cpu(x) ((x))
#else

typedef struct {
    uint32_t v32;
} __attribute__((packed)) jint32_t;
typedef struct {
    uint16_t v16;
} __attribute__((packed)) jint16_t;

#define je16_to_cpu(x) ((x).v16)
#define je32_to_cpu(x) ((x).v32)
#endif
struct jffs2_sum_unknown_flash
{
jint16_t nodetype; /* node type */
};

struct jffs2_unknown_node

{
    /* All start like this */
    jint16_t magic;
    jint16_t nodetype;
    jint32_t totlen; /* So we can skip over nodes we don't grok */
    jint32_t hdr_crc;
};

int boo(struct jffs2_unknown_node *node, void *sp)

{
	
	foo(je32_to_cpu(node->totlen), je16_to_cpu(node->nodetype), je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype));
}
#21 lore raw
In reply to Andrew Morton
Quoted 15 lines · Andrew Morton
Quoted 13 lines · On Thu, 17 May 2007 18:09:50 +0300 Artem Bityutskiy <[email protected]>…
Quoted 12 lines · Christoph Hellwig
Quoted 10 lines · Artem Bityutskiy

Christoph,

Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

Err,__be32 and the company are just sparse things, while I have compiler checks with my struct ubi32_t and friends. JFFS2 also uses the same technique. Why do you force me to rely on sparse instead instead of compiler?

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Yes. Like all other code in the kernel aswell.

Andrew, may I please have your ack that I absolutely have to use __be32 instead of my own types since Christoph tends to provide no explanation to his requests.

umm.. I'd say what you've done in there is an improvement to the exiting
stuff: getting gcc to check it is better than having to use sparse.

Ahem... So what does

	x |= y;

turns into with that approach?

#22 lore raw
Quoted 3 lines

Ahem... So what does

	x |= y;

turns into with that approach?

BTW, you can simply typedef __be16 ubi16_t; etc. and define conversion functions as cpu_to_ubi16(x) being (__force ubi16_t)cpu_to_be16(x), etc.

sparse will do all checks just fine, you still have bitwise operations (might or might be not relevant in your case) and for gcc it simply becomes __be16, etc - i.e. an integer type.

#23 lore raw
Quoted 6 lines · Al Viro

BTW, you can simply typedef __be16 ubi16_t; etc. and define conversion functions as cpu_to_ubi16(x) being (__force ubi16_t)cpu_to_be16(x), etc.

sparse will do all checks just fine, you still have bitwise operations (might or might be not relevant in your case) and for gcc it simply becomes __be16, etc - i.e. an integer type.

Err, what is the benefit of it? If we relied on sparce, why not would we be just using __be16 directly?

Signature · 2 lines
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
#24 lore raw
Quoted 10 lines · Artem Bityutskiy
Quoted 6 lines · Al Viro

BTW, you can simply typedef __be16 ubi16_t; etc. and define conversion functions as cpu_to_ubi16(x) being (__force ubi16_t)cpu_to_be16(x), etc.

sparse will do all checks just fine, you still have bitwise operations (might or might be not relevant in your case) and for gcc it simply becomes __be16, etc - i.e. an integer type.

Err, what is the benefit of it? If we relied on sparce, why not would we be just using __be16 directly?

Because you might legitimately want your type to be *not* mixed with whatever other big-endian 16bit types you have out there?

#25 lore raw
In reply to Al Viro
Quoted 4 lines · Al Viro

Ahem... So what does

       x |= y;

turns into with that approach?

Do we want to do such kind of operations on endian-annotated data? I'd imagine you want to convert ot host-endianess first anyway.

Signature · 1 line
Dmitry
#26 lore raw
Quoted 8 lines · Dmitry Torokhov
Quoted 4 lines · Al Viro

Ahem... So what does

      x |= y;

turns into with that approach?

Do we want to do such kind of operations on endian-annotated data? I'd imagine you want to convert ot host-endianess first anyway.

Why? When both x and y are of the same type, it's a perfectly sane and safe operation. And yes, sparse checks handle that.

#27 lore raw
In reply to Dmitry Torokhov

From: "Dmitry Torokhov" <[email protected]>
Date: Thu, 17 May 2007 17:14:26 -0400

Quoted 8 lines · Al Viro
Quoted 4 lines

Ahem... So what does

       x |= y;

turns into with that approach?

Do we want to do such kind of operations on endian-annotated data? I'd imagine you want to convert ot host-endianess first anyway.

Generally you don't, if 'x' and 'y' are both in the needed endinaness already, there is no reason to convert anything.

#28 lore raw
Quoted 9 lines · David Miller

From: "Dmitry Torokhov" <[email protected]>
Date: Thu, 17 May 2007 17:14:26 -0400

Quoted 6 lines · Al Viro
Quoted 4 lines

Ahem... So what does

       x |= y;

turns into with that approach?

Quoted 5 lines
Quoted 2 lines

Do we want to do such kind of operations on endian-annotated data? I'd imagine you want to convert ot host-endianess first anyway.

Generally you don't, if 'x' and 'y' are both in the needed endinaness already, there is no reason to convert anything.

BTW, if you have two independently defined bitwise types, sparse will complain about mixing them, so you still have protection against mixing unrelated types that happen to have the same endianness.

Folks, just doing annotations of net/* had been large enough and it mostly had been about annotating declarations. If we have to rewrite every sodding place where we happen to do bitwise operations on those... Forget about it. BTW, another fun kind of places is comparing for equality - also adds a fsckload of lines to rewrite^Wobscure.

#29 lore raw
In reply to Al Viro
Quoted 3 lines · Al Viro

Ahem... So what does

	x |= y;

turns into with that approach?

Another case is

#define FLAG1 cpu_to_be32(2)
#define FLAG2 cpu_to_be32(0x400)

	if (packet_header->field & (FLAG1 | FLAG2))
		....

which is a bloody common idiom in net/* and it happens on some pretty hot paths. Approaches that would require converting it to something like

	if (be32_to_cpu(packet_header->field) & (FLAG1 | FLAG2))

would be not just obnoxious, they would actually generate worse code.

#30 lore raw
In reply to Artem Bityutskiy

From: Artem Bityutskiy <[email protected]>
Date: Thu, 17 May 2007 17:50:43 +0300

Quoted 3 lines

Well, I see the good side of your change - no home-brewed media<->cpu things. Fair enough and nice. But why don't you make __be32 a struct (just like I do) so that compiler could complain then?

structs get passed on the stack instead of via registers, regardless of size, when passed as arguments on some architectures, so there is a terrible performance cost of doing things that way

#31 lore raw
Quoted 10 lines · David Miller

From: Artem Bityutskiy <[email protected]>
Date: Thu, 17 May 2007 17:50:43 +0300

Quoted 3 lines

Well, I see the good side of your change - no home-brewed media<->cpu things. Fair enough and nice. But why don't you make __be32 a struct (just like I do) so that compiler could complain then?

structs get passed on the stack instead of via registers, regardless of size, when passed as arguments on some architectures, so there is a terrible performance cost of doing things that way

BTW, the lack of home-grown coversions is not a benefit - it's _nice_ to have protections against mixing be32 and ubi32, etc. Avoiding the mess with struct, OTOH, *is* a benefit.

So I'd rather go with independent bitwise types and conversions done by use of be... ones + force-cast. The rest of ubi code remain unchanged.

#32 lore raw
In reply to Christoph Hellwig
Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

NAK. The 'normal' kernel stuff doesn't work in GCC; only in sparse.

If you want to go removing the ones which _do_ work in GCC, then fix the 'normal' one first. _Then_ go about converting others over to it.

Signature · 1 line
dwmw2
#33 lore raw
Quoted 8 lines · David Woodhouse
Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

NAK. The 'normal' kernel stuff doesn't work in GCC; only in sparse.

If you want to go removing the ones which _do_ work in GCC, then fix the 'normal' one first. _Then_ go about converting others over to it.

Nope. gcc checking is crap and we need to run sparse anyway. It's what everyone in the kernel use so it's perfect for some random code almost no one uses aswell.

#34 lore raw
Quoted 5 lines · Christoph Hellwig
Quoted 4 lines · David Woodhouse
Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

Quoted 8 lines
Quoted 4 lines

NAK. The 'normal' kernel stuff doesn't work in GCC; only in sparse.

If you want to go removing the ones which _do_ work in GCC, then fix the 'normal' one first. _Then_ go about converting others over to it.

Nope. gcc checking is crap and we need to run sparse anyway. It's what everyone in the kernel use so it's perfect for some random code almost no one uses aswell.

Care to explain what is wrong with the gcc checks as used by UBI? Would be nice to know before someone start to migrate current stuff so gcc can check for correct endian.

Sam

#35 lore raw
Quoted 11 lines · Sam Ravnborg
Quoted 10 lines · Christoph Hellwig
Quoted 8 lines · David Woodhouse
Quoted 2 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

NAK. The 'normal' kernel stuff doesn't work in GCC; only in sparse.

If you want to go removing the ones which _do_ work in GCC, then fix the 'normal' one first. _Then_ go about converting others over to it.

Quoted 7 lines
Quoted 3 lines

Nope. gcc checking is crap and we need to run sparse anyway. It's what everyone in the kernel use so it's perfect for some random code almost no one uses aswell.

Care to explain what is wrong with the gcc checks as used by UBI? Would be nice to know before someone start to migrate current stuff so gcc can check for correct endian.

The major wrong thing is that it makes a little subsysttem artifically different from the rest of the kernel.

At a technical level it overdoing things. The attribute syntax is perfecltly find to address endianess issues without introducing wrapper structs the lead to horrible code generation in some situations (e.g. trying to return such a value)

#36 lore raw
Quoted 4 lines · Christoph Hellwig

The attribute syntax is perfecltly
find to address endianess issues without introducing wrapper structs the lead to horrible code generation in some situations (e.g. trying to return such a value)

Small structs are returned in register; it is indistinguishable from returning a scalar.

J

#37 lore raw
In reply to Christoph Hellwig
Quoted 3 lines · Christoph Hellwig

Kill ubis homegrown endianess handling crap and replace it with the normal kernel endianess handling.

Hum, you should check about alignment stuff.
Jffs2 use a similar mechanism and the packed struct also take care of some unaligned data (present in summary node for example).

Matthieu