* [PATCH] Big-endian reading/writing cramfs (vs 2.4.10)
@ 2001-09-28 21:58 Brad
2001-09-28 22:33 ` Andreas Dilger
0 siblings, 1 reply; 4+ messages in thread
From: Brad @ 2001-09-28 21:58 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1: Type: TEXT/PLAIN, Size: 764 bytes --]
A few people have expressed interest in this, and I needed it as
well. Currently, cramfs images aren't shareable between different endian
architectures. The documentation states the meta-data should always be
stored little endian, as the cost of swabbing would be low, but the code
doesn't do it. We needed shareable images, so I modified inode.c,
cramfs_fs.h, and mkcramfs.h to enable a big-endian machine to swab meta
data when writing (mkcramfs.c) and reading (inode.c). This is done with
#defined macros (the 26 bit/6 bit bitfield is kind of ugly to translate),
so the code doesn't change for little-endian machines, only big-endian.
I tested reading le on be, reading a be-written le image on le, etc...
This is a patch against 2.4.10.
-Brad Bozarth
[-- Attachment #2: Type: TEXT/PLAIN, Size: 7938 bytes --]
--- 2.4.10/include/linux/cramfs_fs.h Thu Jul 19 16:14:53 2001
+++ current/include/linux/cramfs_fs.h Thu Sep 27 17:36:57 2001
@@ -9,7 +9,12 @@
#endif
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+#define CRAMFS_MAGIC 0x453dcd28 /* endian reversed magic */
+#else
#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */
+#endif
+
#define CRAMFS_SIGNATURE "Compressed ROMFS"
/*
@@ -80,6 +85,40 @@
* changed to test super.future instead.
*/
#define CRAMFS_SUPPORTED_FLAGS (0x7ff)
+
+/*
+ * Since cramfs (according to docs) should always be stored little endian,
+ * provide macros to swab the bitfields (mkcramfs uses this file too).
+ */
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+
+#define CRAM_SWAB_16(x) ( ( (0x0000FF00 & (x)) >> 8 ) | \
+ ( (0x000000FF & (x)) << 8 ) )
+#define CRAM_SWAB_24(x) ( ( (0x00FF0000 & (x)) >> 16 ) | \
+ ( (0x0000FF00 & (x)) ) | \
+ ( (0x000000FF & (x)) << 16 ) )
+#define CRAM_SWAB_32(x) ( ( (0xFF000000 & (x)) >> 24 ) | \
+ ( (0x00FF0000 & (x)) >> 8 ) | \
+ ( (0x0000FF00 & (x)) << 8 ) | \
+ ( (0x000000FF & (x)) << 24 ) )
+#define GET_CRAM_NAMELEN(x) (((u8*)(x))[8] & 63)
+#define GET_CRAM_OFFSET(x) ((CRAM_SWAB_24(((u32*)(x))[2] & 0x00FFFFFF)<<2) | \
+ ((((u32*)(x))[2] & 0xC0000000)>>30) )
+#define SET_CRAM_OFFSET(x,y) ( ((u32*)(x))[2] = (((y)&3)<<30) | \
+ CRAM_SWAB_24( ( ((y) & 0x03FFFFFF) >> 2) ) | \
+ (((u32)(((u8*)(x))[8] & 0x3F)) << 24) )
+#define SET_CRAM_NAMELEN(x,y) ( ((u8*)(x))[8] = ( ((0x3F & (y))) | \
+ (0xC0 & ((u8*)(x))[8]) ) )
+
+#else
+#define CRAM_SWAB_16(x) (x)
+#define CRAM_SWAB_24(x) (x)
+#define CRAM_SWAB_32(x) (x)
+#define GET_CRAM_NAMELEN(x) ((x)->namelen)
+#define GET_CRAM_OFFSET(x) ((x)->offset)
+#define SET_LE_OFFSET(x,y) ((x)->offset = y)
+#define SET_LE_NAMELEN(x,y) ((x)->namelen = y)
+#endif
/* Uncompression interfaces to the underlying zlib */
int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);
--- 2.4.10/fs/cramfs/inode.c Mon Aug 27 07:53:49 2001
+++ current/fs/cramfs/inode.c Fri Sep 28 14:01:53 2001
@@ -35,7 +35,7 @@
/* These two macros may change in future, to provide better st_ino
semantics. */
-#define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
+#define CRAMINO(x) (GET_CRAM_OFFSET(x) ? GET_CRAM_OFFSET(x)<<2 : 1)
#define OFFSET(x) ((x)->i_ino)
static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
@@ -43,9 +43,9 @@
struct inode * inode = new_inode(sb);
if (inode) {
- inode->i_mode = cramfs_inode->mode;
- inode->i_uid = cramfs_inode->uid;
- inode->i_size = cramfs_inode->size;
+ inode->i_mode = CRAM_SWAB_16(cramfs_inode->mode);
+ inode->i_uid = CRAM_SWAB_16(cramfs_inode->uid);
+ inode->i_size = CRAM_SWAB_24(cramfs_inode->size);
inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_gid = cramfs_inode->gid;
@@ -66,7 +66,8 @@
inode->i_data.a_ops = &cramfs_aops;
} else {
inode->i_size = 0;
- init_special_inode(inode, inode->i_mode, cramfs_inode->size);
+ init_special_inode(inode, inode->i_mode,
+ CRAM_SWAB_24(cramfs_inode->size));
}
}
return inode;
@@ -219,11 +220,11 @@
}
/* Check that the root inode is in a sane state */
- if (!S_ISDIR(super.root.mode)) {
+ if (!S_ISDIR(CRAM_SWAB_16(super.root.mode))) {
printk(KERN_ERR "cramfs: root is not a directory\n");
goto out;
}
- root_offset = super.root.offset << 2;
+ root_offset = GET_CRAM_OFFSET(&(super.root)) << 2;
if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
sb->CRAMFS_SB_SIZE=super.size;
sb->CRAMFS_SB_BLOCKS=super.fsid.blocks;
@@ -299,7 +300,7 @@
* and the name padded out to 4-byte boundaries
* with zeroes.
*/
- namelen = de->namelen << 2;
+ namelen = GET_CRAM_NAMELEN(de) << 2;
nextoffset = offset + sizeof(*de) + namelen;
for (;;) {
if (!namelen)
@@ -308,7 +309,8 @@
break;
namelen--;
}
- error = filldir(dirent, name, namelen, offset, CRAMINO(de), de->mode >> 12);
+ error = filldir(dirent, name, namelen, offset, CRAMINO(de),
+ CRAM_SWAB_16(de->mode) >> 12);
if (error)
break;
@@ -339,7 +341,7 @@
if (sorted && (dentry->d_name.name[0] < name[0]))
break;
- namelen = de->namelen << 2;
+ namelen = GET_CRAM_NAMELEN(de) << 2;
offset += sizeof(*de) + namelen;
/* Quick check that the name is roughly the right length */
@@ -385,9 +387,10 @@
start_offset = OFFSET(inode) + maxblock*4;
if (page->index)
- start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4);
- compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4)
- - start_offset);
+ start_offset = CRAM_SWAB_32(*(u32 *)
+ cramfs_read(sb, blkptr_offset - 4, 4));
+ compr_len = CRAM_SWAB_32(*(u32 *)
+ cramfs_read(sb, blkptr_offset, 4)) - start_offset;
pgdata = kmap(page);
if (compr_len == 0)
; /* hole */
--- 2.4.10/scripts/cramfs/mkcramfs.c Thu Jul 19 16:14:53 2001
+++ current/scripts/cramfs/mkcramfs.c Fri Sep 28 14:15:37 2001
@@ -317,19 +317,20 @@
offset += opt_pad;
}
- super->magic = CRAMFS_MAGIC;
- super->flags = CRAMFS_FLAG_FSID_VERSION_2 | CRAMFS_FLAG_SORTED_DIRS;
+ super->magic = CRAMFS_MAGIC; /* #defined correctly on both endians */
+ super->flags = CRAM_SWAB_32(CRAMFS_FLAG_FSID_VERSION_2 |
+ CRAMFS_FLAG_SORTED_DIRS);
if (opt_holes)
- super->flags |= CRAMFS_FLAG_HOLES;
+ super->flags |= CRAM_SWAB_32(CRAMFS_FLAG_HOLES);
if (image_length > 0)
- super->flags |= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET;
- super->size = size;
+ super->flags |= CRAM_SWAB_32(CRAMFS_FLAG_SHIFTED_ROOT_OFFSET);
+ super->size = CRAM_SWAB_24(size);
memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
- super->fsid.crc = crc32(0L, Z_NULL, 0);
- super->fsid.edition = opt_edition;
- super->fsid.blocks = total_blocks;
- super->fsid.files = total_nodes;
+ super->fsid.crc = CRAM_SWAB_32(crc32(0L, Z_NULL, 0));
+ super->fsid.edition = CRAM_SWAB_32(opt_edition);
+ super->fsid.blocks = CRAM_SWAB_32(total_blocks);
+ super->fsid.files = CRAM_SWAB_32(total_nodes);
memset(super->name, 0x00, sizeof(super->name));
if (opt_name)
@@ -337,11 +338,11 @@
else
strncpy(super->name, "Compressed", sizeof(super->name));
- super->root.mode = root->mode;
- super->root.uid = root->uid;
+ super->root.mode = CRAM_SWAB_16(root->mode);
+ super->root.uid = CRAM_SWAB_16(root->uid);
super->root.gid = root->gid;
- super->root.size = root->size;
- super->root.offset = offset >> 2;
+ super->root.size = CRAM_SWAB_24(root->size);
+ SET_CRAM_OFFSET(&(super->root), offset >> 2);
return offset;
}
@@ -356,7 +357,7 @@
fprintf(stderr, "filesystem too big. Exiting.\n");
exit(8);
}
- inode->offset = (offset >> 2);
+ SET_CRAM_OFFSET(inode, offset >> 2);
}
@@ -379,10 +380,10 @@
entry->dir_offset = offset;
- inode->mode = entry->mode;
- inode->uid = entry->uid;
+ inode->mode = CRAM_SWAB_16(entry->mode);
+ inode->uid = CRAM_SWAB_16(entry->uid);
inode->gid = entry->gid;
- inode->size = entry->size;
+ inode->size = CRAM_SWAB_24(entry->size);
inode->offset = 0;
/* Non-empty directories, regfiles and symlinks will
write over inode->offset later. */
@@ -395,7 +396,7 @@
*(base + offset + len) = '\0';
len++;
}
- inode->namelen = len >> 2;
+ SET_CRAM_NAMELEN(inode, len >> 2);
offset += len;
/* TODO: this may get it wrong for chars >= 0x80.
@@ -503,7 +504,7 @@
exit(8);
}
- *(u32 *) (base + offset) = curr;
+ *(u32 *) (base + offset) = CRAM_SWAB_32(curr);
offset += 4;
} while (size);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Big-endian reading/writing cramfs (vs 2.4.10)
2001-09-28 21:58 [PATCH] Big-endian reading/writing cramfs (vs 2.4.10) Brad
@ 2001-09-28 22:33 ` Andreas Dilger
2001-09-28 22:54 ` Brad Bozarth
0 siblings, 1 reply; 4+ messages in thread
From: Andreas Dilger @ 2001-09-28 22:33 UTC (permalink / raw)
To: Brad; +Cc: linux-kernel
On Sep 28, 2001 14:58 -0700, Brad wrote:
> +#define CRAM_SWAB_16(x) ( ( (0x0000FF00 & (x)) >> 8 ) | \
> + ( (0x000000FF & (x)) << 8 ) )
Why not just use the well-defined le16_to_cpu() and le32_to_cpu() macros?
Cheers, Andreas
--
Andreas Dilger \ "If a man ate a pound of pasta and a pound of antipasto,
\ would they cancel out, leaving him still hungry?"
http://www-mddsp.enel.ucalgary.ca/People/adilger/ -- Dogbert
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Big-endian reading/writing cramfs (vs 2.4.10)
2001-09-28 22:33 ` Andreas Dilger
@ 2001-09-28 22:54 ` Brad Bozarth
2001-09-28 23:17 ` Andreas Dilger
0 siblings, 1 reply; 4+ messages in thread
From: Brad Bozarth @ 2001-09-28 22:54 UTC (permalink / raw)
To: Andreas Dilger; +Cc: linux-kernel
> On Sep 28, 2001 14:58 -0700, Brad wrote:
> > +#define CRAM_SWAB_16(x) ( ( (0x0000FF00 & (x)) >> 8 ) | \
> > + ( (0x000000FF & (x)) << 8 ) )
>
> Why not just use the well-defined le16_to_cpu() and le32_to_cpu() macros?
I did, originally... And it worked in inode.c, but I couldn't get mkcramfs
to compile using those macros. It's outside of __KERNEL__ so I tried
using __cpu_to_le32. The following error occurred:
/tmp/ccoK4KS0.o: In function `write_superblock':
mkcramfs.c(.text+0xefc): undefined reference to `__fswab32'
collect2: ld returned 1 exit status
__fswab32 is defined in include/linux/byteorder/swab.h as:
extern __inline__ __const__ __u32 __fswab32(__u32 x)
{
return __arch__swab32(x);
}
Can you shed some light on the error? I used my own macros to get around
this issue and it worked, but the defined ones would be cleaner...
Thanks,
Brad Bozarth
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Big-endian reading/writing cramfs (vs 2.4.10)
2001-09-28 22:54 ` Brad Bozarth
@ 2001-09-28 23:17 ` Andreas Dilger
0 siblings, 0 replies; 4+ messages in thread
From: Andreas Dilger @ 2001-09-28 23:17 UTC (permalink / raw)
To: Brad Bozarth; +Cc: linux-kernel
On Sep 28, 2001 15:54 -0700, Brad Bozarth wrote:
> > On Sep 28, 2001 14:58 -0700, Brad wrote:
> > > +#define CRAM_SWAB_16(x) ( ( (0x0000FF00 & (x)) >> 8 ) | \
> > > + ( (0x000000FF & (x)) << 8 ) )
> >
> > Why not just use the well-defined le16_to_cpu() and le32_to_cpu() macros?
>
> I did, originally... And it worked in inode.c, but I couldn't get mkcramfs
> to compile using those macros. It's outside of __KERNEL__ so I tried
> using __cpu_to_le32. The following error occurred:
I didn't realize that the header was also used in user-space. I would
still use the le32_to_cpu() style macros in the code, but only define
macros of your own if the kernel ones were not defined, using either
#ifndef __KERNEL__ or #ifndef le32_to_cpu, or both.
This way, you get the benefit of the fast asm-based instructions in
the kernel, and you only use the slow ones in user-space (mkcramfs)
where you don't really care.
Cheers, Andreas
--
Andreas Dilger \ "If a man ate a pound of pasta and a pound of antipasto,
\ would they cancel out, leaving him still hungry?"
http://www-mddsp.enel.ucalgary.ca/People/adilger/ -- Dogbert
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2001-09-28 23:18 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-09-28 21:58 [PATCH] Big-endian reading/writing cramfs (vs 2.4.10) Brad
2001-09-28 22:33 ` Andreas Dilger
2001-09-28 22:54 ` Brad Bozarth
2001-09-28 23:17 ` Andreas Dilger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox