[PATCH 2/2][resend] Make cramfs little endian only: Update documentation

2007-12-27 Thread Andi Drebes
The following patch updates the cramfs documentation according
to the changes that make cramfs little endian only.

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 fs/cramfs/README |   19 +--
 1 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/fs/cramfs/README b/fs/cramfs/README
index 445d1c2..91efe77 100644
--- a/fs/cramfs/README
+++ b/fs/cramfs/README
@@ -6,8 +6,11 @@ a bit looser, e.g. it doesn't care if the  items are
 swapped around (though it does care that directory entries (inodes) in
 a given directory are contiguous, as this is used by readdir).
 
-All data is currently in host-endian format; neither mkcramfs nor the
-kernel ever do swabbing.  (See section `Block Size' below.)
+All data is now in little endian format. Before, it was in host endian
+format. In order to make filesystem images more shareable between machines
+with a different byte order, cramfs' specification ("this README file")
+was updated. There will be no support for big endian filesystems in the
+future.
 
 :

@@ -108,18 +111,6 @@ kernels, not even necessarily kernels of the same 
architecture if
 PAGE_CACHE_SIZE is subject to change between kernel versions
 (currently possible with arm and ia64).
 
-The remaining options try to make cramfs more sharable.
-
-One part of that is addressing endianness.  The two options here are
-`always use little-endian' (like ext2fs) or `writer chooses
-endianness; kernel adapts at runtime'.  Little-endian wins because of
-code simplicity and little CPU overhead even on big-endian machines.
-
-The cost of swabbing is changing the code to use the le32_to_cpu
-etc. macros as used by ext2fs.  We don't need to swab the compressed
-data, only the superblock, inodes and block pointers.
-
-
 The other part of making cramfs more sharable is choosing a block
 size.  The options are:
 
-- 
1.5.1.53.g77e6f

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2][resend] Make cramfs little endian only

2007-12-27 Thread Andi Drebes
The following patch makes cramfs little endian only.
When trying to mount a big endian image, an error message is produced.

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 fs/cramfs/inode.c |  119 ++---
 include/linux/cramfs_fs.h |   22 
 2 files changed, 91 insertions(+), 50 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 350680f..30dc640 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -4,6 +4,10 @@
  * Copyright (C) 1999 Linus Torvalds.
  *
  * This file is released under the GPL.
+ *
+ * Changelog:
+ * 11/07 - Andi Drebes <[EMAIL PROTECTED]>
+ * Made cramfs little endian only.
  */
 
 /*
@@ -34,13 +38,46 @@ static const struct address_space_operations cramfs_aops;
 
 static DEFINE_MUTEX(read_mutex);
 
+#define CRAMFS_NAMELEN_MASK ((1ul << CRAMFS_NAMELEN_WIDTH)-1)
+#define CRAMFS_MODE_MASK ((1ul << CRAMFS_MODE_WIDTH)-1)
+#define CRAMFS_SIZE_MASK ((1ul << CRAMFS_SIZE_WIDTH)-1)
+
+static inline u32 cramfs_mode(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->mode_uid) & CRAMFS_MODE_MASK;
+}
+
+static inline u32 cramfs_uid(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->mode_uid) >> CRAMFS_MODE_WIDTH;
+}
+
+static inline u32 cramfs_size(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->size_gid) & CRAMFS_SIZE_MASK;
+}
+
+static inline u32 cramfs_gid(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->size_gid) >> CRAMFS_SIZE_WIDTH;
+}
+
+static inline u32 cramfs_offset(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->namelen_offset) >> CRAMFS_NAMELEN_WIDTH;
+}
+
+static inline u32 cramfs_namelen(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->namelen_offset) & CRAMFS_NAMELEN_MASK;
+}
 
 /* These two macros may change in future, to provide better st_ino
semantics. */
-#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
+#define CRAMINO(x) ((cramfs_offset(x) && cramfs_size(x)) ? \
+cramfs_offset(x) << 2 : 1)
 #define OFFSET(x)  ((x)->i_ino)
 
-
 static int cramfs_iget5_test(struct inode *inode, void *opaque)
 {
struct cramfs_inode *cramfs_inode = opaque;
@@ -53,13 +90,13 @@ static int cramfs_iget5_test(struct inode *inode, void 
*opaque)
 
/* all empty directories, char, block, pipe, and sock, share inode #1 */
 
-   if ((inode->i_mode != cramfs_inode->mode) ||
-   (inode->i_gid != cramfs_inode->gid) ||
-   (inode->i_uid != cramfs_inode->uid))
+   if ((inode->i_mode != cramfs_mode(cramfs_inode)) ||
+   (inode->i_gid != cramfs_gid(cramfs_inode)) ||
+   (inode->i_uid != cramfs_uid(cramfs_inode)))
return 0; /* does not match */
 
if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) &&
-   (inode->i_rdev != old_decode_dev(cramfs_inode->size)))
+   (inode->i_rdev != old_decode_dev(cramfs_size(cramfs_inode
return 0; /* does not match */
 
return 1; /* matches */
@@ -69,11 +106,11 @@ static int cramfs_iget5_set(struct inode *inode, void 
*opaque)
 {
static struct timespec zerotime;
struct cramfs_inode *cramfs_inode = opaque;
-   inode->i_mode = cramfs_inode->mode;
-   inode->i_uid = cramfs_inode->uid;
-   inode->i_size = cramfs_inode->size;
-   inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
-   inode->i_gid = cramfs_inode->gid;
+   inode->i_mode = cramfs_mode(cramfs_inode);
+   inode->i_uid = cramfs_uid(cramfs_inode);
+   inode->i_size = cramfs_size(cramfs_inode);
+   inode->i_blocks = (cramfs_size(cramfs_inode) - 1) / 512 + 1;
+   inode->i_gid = cramfs_gid(cramfs_inode);
/* Struct copy intentional */
inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
inode->i_ino = CRAMINO(cramfs_inode);
@@ -94,7 +131,7 @@ static int cramfs_iget5_set(struct inode *inode, void 
*opaque)
inode->i_size = 0;
inode->i_blocks = 0;
init_special_inode(inode, inode->i_mode,
-   old_decode_dev(cramfs_inode->size));
+   old_decode_dev(cramfs_size(cramfs_inode)));
}
return 0;
 }
@@ -256,53 +293,57 @@ static int cramfs_fill_super(struct super_block *sb, void 
*data, int silent)
mutex_unlock(&read_mutex);
 
/* Do sanity checks on the superblock */
-   if (super.magic != CRAMFS_MAGIC) {
-   /* check for wrong endianess */
-   if (super.magic == CRAMFS_MAGIC_WEND) {
-  

[PATCH 0/2][resend] Make cramfs little endian only

2007-12-27 Thread Andi Drebes
The following patchset makes cramfs little endian only and updates
the documentation.

I already sent this updated version three weeks ago as a reply in a
discussion (http://marc.info/?l=linux-fsdevel&m=119698067927762&w=2).

As I didn't get any further responses for the updated version (please
let me know if I did something terribly wrong that prevented people from
commenting it) I resend it.

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Diffed against Linus' git tree.

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] Make cramfs little endian only

2007-12-06 Thread Andi Drebes
> But then you just make sure that the little-endian bits are the same, and 
> now you're *done*.
Yes, you're perfectly right. Sorry for not getting it. I hope the next
time I will understand faster.

> > For little endian machines, the data arranged in the following way:
> > 
> > |o02.o01.n06.n05.n04.n03.n02.n01|o10.o09.o08.o07.o06.o05.o04.o03|
> > |o18.o17.o16.o15.o14.o13.o12.o11|o26.o25.o24.o23.o22.o21.o20.o19| 
> 
> That's a singularly confused way or looking at it. 
Yep. I saw everything with big-endian eyes and confused myself.
Shouldn't have happened.

> Yes it does. Try it.
I tried it. It does it. Here's the new patch (hopefully the last one
for this issue)...

Checked with sparse using C=2 and CF="-D__CHECK_ENDIAN__".
Tested on an i386 box.
Tested on an Ultrasparc IIi box.

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 fs/cramfs/inode.c |  119 ++---
 include/linux/cramfs_fs.h |   22 
 2 files changed, 91 insertions(+), 50 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 350680f..30dc640 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -4,6 +4,10 @@
  * Copyright (C) 1999 Linus Torvalds.
  *
  * This file is released under the GPL.
+ *
+ * Changelog:
+ * 11/07 - Andi Drebes <[EMAIL PROTECTED]>
+ * Made cramfs little endian only.
  */
 
 /*
@@ -34,13 +38,46 @@ static const struct address_space_operations cramfs_aops;
 
 static DEFINE_MUTEX(read_mutex);
 
+#define CRAMFS_NAMELEN_MASK ((1ul << CRAMFS_NAMELEN_WIDTH)-1)
+#define CRAMFS_MODE_MASK ((1ul << CRAMFS_MODE_WIDTH)-1)
+#define CRAMFS_SIZE_MASK ((1ul << CRAMFS_SIZE_WIDTH)-1)
+
+static inline u32 cramfs_mode(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->mode_uid) & CRAMFS_MODE_MASK;
+}
+
+static inline u32 cramfs_uid(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->mode_uid) >> CRAMFS_MODE_WIDTH;
+}
+
+static inline u32 cramfs_size(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->size_gid) & CRAMFS_SIZE_MASK;
+}
+
+static inline u32 cramfs_gid(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->size_gid) >> CRAMFS_SIZE_WIDTH;
+}
+
+static inline u32 cramfs_offset(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->namelen_offset) >> CRAMFS_NAMELEN_WIDTH;
+}
+
+static inline u32 cramfs_namelen(struct cramfs_inode *inode)
+{
+   return le32_to_cpu(inode->namelen_offset) & CRAMFS_NAMELEN_MASK;
+}
 
 /* These two macros may change in future, to provide better st_ino
semantics. */
-#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
+#define CRAMINO(x) ((cramfs_offset(x) && cramfs_size(x)) ? \
+cramfs_offset(x) << 2 : 1)
 #define OFFSET(x)  ((x)->i_ino)
 
-
 static int cramfs_iget5_test(struct inode *inode, void *opaque)
 {
struct cramfs_inode *cramfs_inode = opaque;
@@ -53,13 +90,13 @@ static int cramfs_iget5_test(struct inode *inode, void 
*opaque)
 
/* all empty directories, char, block, pipe, and sock, share inode #1 */
 
-   if ((inode->i_mode != cramfs_inode->mode) ||
-   (inode->i_gid != cramfs_inode->gid) ||
-   (inode->i_uid != cramfs_inode->uid))
+   if ((inode->i_mode != cramfs_mode(cramfs_inode)) ||
+   (inode->i_gid != cramfs_gid(cramfs_inode)) ||
+   (inode->i_uid != cramfs_uid(cramfs_inode)))
return 0; /* does not match */
 
if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) &&
-   (inode->i_rdev != old_decode_dev(cramfs_inode->size)))
+   (inode->i_rdev != old_decode_dev(cramfs_size(cramfs_inode
return 0; /* does not match */
 
return 1; /* matches */
@@ -69,11 +106,11 @@ static int cramfs_iget5_set(struct inode *inode, void 
*opaque)
 {
static struct timespec zerotime;
struct cramfs_inode *cramfs_inode = opaque;
-   inode->i_mode = cramfs_inode->mode;
-   inode->i_uid = cramfs_inode->uid;
-   inode->i_size = cramfs_inode->size;
-   inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
-   inode->i_gid = cramfs_inode->gid;
+   inode->i_mode = cramfs_mode(cramfs_inode);
+   inode->i_uid = cramfs_uid(cramfs_inode);
+   inode->i_size = cramfs_size(cramfs_inode);
+   inode->i_blocks = (cramfs_size(cramfs_inode) - 1) / 512 + 1;
+   inode->i_gid = cramfs_gid(cramfs_inode);
/* Struct copy intentional */
inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
inode->i_ino = CRAMINO(cramfs_inode);
@@ -94,7 +131,7 @@ static int cramfs_iget5_set(struct inode *inode, void 
*opaque)
inode-

Re: [PATCH 1/2] Make cramfs little endian only

2007-12-06 Thread Andi Drebes
> Mode and uid are both 16bit.  So maybe we can change the structure:
> 
>   struct cramfs_inode {
>   __le16 uid;
>   __le16 mode;
>   __le32 size_gid;/* CRAMFS_SIZE_WIDTH:CRAMFS_GID_WIDTH */
>   __le32 namelen_offset;  /* 
> CRAMFS_NAMELEN_WIDTH:CRAMFS_OFFSET_WIDTH */
>   };
Yep, looks better...

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] Make cramfs little endian only

2007-12-06 Thread Andi Drebes

> No, no, what I meant about not having any #ifdef __LITTLE_ENDIAN was to do 
> the code do the same thing *regardless* of endianness. In other words, a 
> simple:
> 
>   struct cramfs_inode {
>   __le32 mode_uid;/* CRAMFS_MODE_WIDTH:CRAMFS_UID_WIDTH */
>   __le32 size_gid;/* CRAMFS_SIZE_WIDTH:CRAMFS_GID_WIDTH */
>   __le32 namelen_offset;  /* 
> CRAMFS_NAMELEN_WIDTH:CRAMFS_OFFSET_WIDTH */
>   };
> 
>   #define CRAMFS_UID_MASK ((1ul << CRAMFS_UID_WIDTH)-1)
>   #define CRAMFS_GID_MASK ((1ul << CRAMFS_GID_WIDTH)-1)
>   #define CRAMFS_NAMELEN_MASK ((1ul << CRAMFS_NAMELEN_WIDTH)-1)
> 
[...]
>   static inline u32 cramfs_offset(struct cramfs_inode *inode)
>   {
>   return le32_to_cpu(node->namelen_offset) >> 
> CRAMFS_NAMELEN_WIDTH;
>   }
This requires changing the on-disk-structure (even the current "little endian 
only" one).
The problem is caused by the way GCC (and perhaps other compilers aswell) 
arranges
the 6 bits bits for the namelength and the 26 bits for the offset within the 32 
bits.
I spent quite some time on figuring out how this is actually done. For little 
endian
machines, the data arranged in the following way:

|o02.o01.n06.n05.n04.n03.n02.n01|o10.o09.o08.o07.o06.o05.o04.o03|
|o18.o17.o16.o15.o14.o13.o12.o11|o26.o25.o24.o23.o22.o21.o20.o19| 

(where oXX means offset bit XX, nXX means namelength bit XX, | marks the 
beginning
/ end of a byte and . is a bit separator)

On big endian machines, the data is arranged differently:

|n06.n05.n04.n03.n02.n01.o26.o25|o24.o23.o22.o21.o20.o19.o18.o17|
|o16.o15.o14.o13.o12.o11.o10.o09|o08.o07.o06.o05.o04.o03.o02.o01|

So masking and then shifting *the whole* masked data doesn't solve the problem.

>   static inline u32 cramfs_namelen(struct cramfs_inode *inode)
>   {
>   return le32_to_cpu(node->namelen_offset) & CRAMFS_NAMELEN_MASK;
>   }
> 
> See? No #ifdef's required, no different code-paths, and the code generated 
> will be pretty much optimal too.
See above.

> ([...]but you get the idea).
Yes. And I agree with you. But making this consistent for all fields of cramfs 
structures
requires changing the on-disk-structure. This would mean that we don't only 
break support
for big endian images, but also for current little endian images.
However, I'm not totally against this solution. But one should keep in mind 
what I pointed
out above.

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] Make cramfs little endian only

2007-12-05 Thread Andi Drebes
Jeff Garzik wrote:
> Bitfields also generate lower-quality assembly than masks&shifts 
> (typically more instructions using additional temporaries to accomplish 
> the same thing), based on my own informal gcc testing.
> 
> You would think gcc would be advanced enough to turn bitfield use into 
> masks and shifts under the hood, but for whatever reason that often is 
> not the case in kernel code.
OK. I'll modify the cramfs structures and replace the bitfields so that the
data can be accessed using masks and shifts. This requires updating the 
userspace
tools aswell. There will be a new patch avaliable soon.

I worked on the copy-and-convert-problem today and created a new patch that
avoids the negative things pointed out by Linus earlier. I hope I got that
in the right way. However, there are still some functions whose implementations
depend on the machine's endianness. I hope that they will be obsolete as soon as
the new patch is available.

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 fs/cramfs/inode.c |  131 +++---
 1 file changed, 96 insertions(+), 35 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 350680f..ceb2c6e 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -4,6 +4,10 @@
  * Copyright (C) 1999 Linus Torvalds.
  *
  * This file is released under the GPL.
+ *
+ * Changelog:
+ * 11/07 - Andi Drebes <[EMAIL PROTECTED]>
+ * Made cramfs little endian only.
  */
 
 /*
@@ -37,9 +41,62 @@ static DEFINE_MUTEX(read_mutex);
 
 /* These two macros may change in future, to provide better st_ino
semantics. */
-#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
+#define CRAMINO(x) ((cramfs_offset_to_cpu(x) && cramfs_size_to_cpu(x)) ? \
+cramfs_offset_to_cpu(x) << 2 : 1)
 #define OFFSET(x)  ((x)->i_ino)
 
+#ifdef __BIG_ENDIAN
+
+/* Converts a cramfs_inode's offset field
+   from little endianto cpu endian */
+static u32 cramfs_offset_to_cpu(struct cramfs_inode *inode)
+{
+   u8 *inode_bytes = (u8 *)inode;
+   return ((inode_bytes[8] & 0xc0) >> 6) | (inode_bytes[9] << 2) |
+   (inode_bytes[10] << 10) | (inode_bytes[11] << 18);
+}
+
+/* Converts a cramfs_inode's namelength field
+   from little endian to cpu endian */
+static u32 cramfs_namelen_to_cpu(struct cramfs_inode *inode)
+{
+   u8 *inode_bytes = (u8 *)inode;
+   return inode_bytes[8] & 0x3f;
+}
+
+/* Converts a cramfs_inode's size field
+   from little endian to cpu endian */
+static u32 cramfs_size_to_cpu(struct cramfs_inode *inode)
+{
+   return ((inode->size & 0xff) >> 16) | (inode->size & 0x00ff00) |
+   ((inode->size & 0xff) << 16);
+}
+
+#elif defined(__LITTLE_ENDIAN)
+
+/* Converts a cramfs_inode's offset field
+   from little endian to cpu endian */
+static u32 cramfs_offset_to_cpu(struct cramfs_inode *inode)
+{
+   return inode->offset;
+}
+
+/* Converts a cramfs_inode's namelength field
+   from little endian to cpu endian */
+static u32 cramfs_namelen_to_cpu(struct cramfs_inode *inode)
+{
+   return inode->namelen;
+}
+
+/* Converts a cramfs_inode's size field
+   from little endian to cpu endian */
+static u32 cramfs_size_to_cpu(struct cramfs_inode *inode)
+{
+   return inode->size;
+}
+#else
+#error "Neither __BIG_ENDIAN nor __LITTLE_ENDIAN defined."
+#endif
 
 static int cramfs_iget5_test(struct inode *inode, void *opaque)
 {
@@ -53,13 +110,13 @@ static int cramfs_iget5_test(struct inode *inode, void 
*opaque)
 
/* all empty directories, char, block, pipe, and sock, share inode #1 */
 
-   if ((inode->i_mode != cramfs_inode->mode) ||
+   if ((inode->i_mode != le16_to_cpu(cramfs_inode->mode)) ||
(inode->i_gid != cramfs_inode->gid) ||
-   (inode->i_uid != cramfs_inode->uid))
+   (inode->i_uid != le16_to_cpu(cramfs_inode->uid)))
return 0; /* does not match */
 
if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) &&
-   (inode->i_rdev != old_decode_dev(cramfs_inode->size)))
+   (inode->i_rdev != old_decode_dev(cramfs_size_to_cpu(cramfs_inode
return 0; /* does not match */
 
return 1; /* matches */
@@ -69,10 +126,10 @@ static int cramfs_iget5_set(struct inode *inode, void 
*opaque)
 {
static struct timespec zerotime;
struct cramfs_inode *cramfs_inode = opaque;
-   inode->i_mode = cramfs_inode->mode;
-   inode->i_uid = cramfs_inode->uid;
-   inode->i_size = cramfs_inode->size;
-   inode->i_blo

Re: [PATCH 1/2] Make cramfs little endian only

2007-12-04 Thread Andi Drebes
> > Sure. This saves some definitions (and lines of code)...
> > Here's the new patch (tested on the same machines mentioned in the first 
> > message).
> > I tried to move as many lines as possible out of the endian dependent 
> > section.
> 
> This really is the totally wrong way to do this.
> 
> You should *not* convert inodes to CPU-endian mode at all. You should 
> *keep* them in the native mode, and then just use "le32_to_cpu()" when 
> actually using them.
OK. I'll prepare a new patch and send it to the list (not today,
it's already too late in the evening here). 

> Basically, if you ever have a
> 
>   #ifdef __BIG_ENDIAN
> 
> or similar in the source code, you're simply doing something wrong. 
Perhaps I'm missing somehting, but I think for cramfs, unfortunately,
there has to be this statement. The bitfields in the cramfs_inode structure
cause some problems. You can't simply call le32_to_cpu() on them.
Especially the namelength and offset fields are weird. There has to be at least
one routine for each kind of machine that converts those values (or not -- 
depending
ont the machine's endianness).

> Btw, sparse can be a big help for things like this, by just marking the 
> actual disk data structures as being the right type (ie "__le32" and 
> friends), and then you can verify that any users will use "le32_to_cpu()" 
> as required, because sparse will warn about bad endianness.
Ok, thanks for your advice. But what about the problems mentioned above?

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] Make cramfs little endian only

2007-12-04 Thread Andi Drebes
> > +/* Converts a cramfs_info from little endian to big endian. */
> > +static inline void cramfs_convert_inode_letobe(struct cramfs_inode* inode)
> > +{
> > +   u8* inode_bytes = (u8*)inode;
> > +   u8 old_nloffs[4];
> > +
> > +   inode->mode = swab16(inode->mode);
> > +   inode->uid = swab16(inode->uid);
> > +   inode->size = (inode_bytes[6] << 16) | (inode_bytes[5] << 8) | 
> > (inode_bytes[4]);
> 
> eww.  Is there a nicer way of doing that?
Yes, I know it's ugly. I searched for a swab24 function. The file
fs/jfs/endian24.h defines such a function. Including this file in
fs/cramfs/inode.c would be even more ugly than the code above. What
about moving this to a header file in include/linux/byteorder? (just a 
suggestion,
perhaps it isn't worth the effort...)

> Might be a bit tricky given the weird way in which struct cramfs_inode was
> defined.
> 
> > +
> > +   /* Save the old values of the namelength and the offset */
> > +   memcpy(old_nloffs, inode_bytes+8, 4);
> > +
> > +   /* Convert the namelength and the offset */
> > +   inode_bytes[8] = ((old_nloffs[0] & 0x3f) << 2) | ((old_nloffs[3] & 
> > 0xc0) >> 6);
> > +   inode_bytes[9] = ((old_nloffs[3] & 0x3f) << 2) | ((old_nloffs[2] & 
> > 0xc0) >> 6);
> > +   inode_bytes[10] = ((old_nloffs[2] & 0x3f) << 2) | ((old_nloffs[1] & 
> > 0xc0) >> 6);
> > +   inode_bytes[11] = ((old_nloffs[1] & 0x3f) << 2) | ((old_nloffs[0] & 
> > 0xc0) >> 6);
> > +}
> > +
> > +/* Converts a cramfs superblock from little endian to big endian. */
> > +static inline void cramfs_convert_super_letobe(struct cramfs_super* super)
> > +{
> > +   super->magic = swab32(super->magic);
> > +   super->size = swab32(super->size);
> > +   super->flags = swab32(super->flags);
> > +   super->future = swab32(super->future);
> > +   cramfs_convert_info_letobe(&super->fsid);
> > +   cramfs_convert_inode_letobe(&super->root);
> > +}
> 
> These inlines are not sane.  Just removing those three takes the sparc64
> fs/cramfs/inode.o from 6856 bytes of text down to 5668, which is rather a
> large difference.
OK. I'll remove the inline keywords in my copies aswell. Should I prepare a new 
patch
and send it to the mailinglist?

> The patch has a number of trivial coding-style errors. 
> scripts/checkpatch.pl finds them.
Oh, I'm sorry. I should have checked that.

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] Make cramfs little endian only

2007-12-04 Thread Andi Drebes
> > +#ifdef __BIG_ENDIAN
> > +/* Converts a cramfs_info from little endian to big endian. */
> > +static inline void cramfs_convert_info_letobe(struct cramfs_info* info)
> > +{
> > +info->crc = swab32(info->crc);
> > +info->edition = swab32(info->edition);
> > +info->blocks = swab32(info->blocks);
> > +info->files = swab32(info->files);
> > +}
> 
> Can you remove the #ifdef and use le32_to_cpu() directly?
Sure. This saves some definitions (and lines of code)...
Here's the new patch (tested on the same machines mentioned in the first 
message).
I tried to move as many lines as possible out of the endian dependent section.

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 fs/cramfs/inode.c |  135 ++---
 1 files changed, 108 insertions(+), 27 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 350680f..ab05fd5 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -4,6 +4,10 @@
  * Copyright (C) 1999 Linus Torvalds.
  *
  * This file is released under the GPL.
+ *
+ * Changelog:
+ * 11/07 - Andi Drebes <[EMAIL PROTECTED]>
+ * Made cramfs little endian only.
  */
 
 /*
@@ -40,6 +44,67 @@ static DEFINE_MUTEX(read_mutex);
 #define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
 #define OFFSET(x)  ((x)->i_ino)
 
+/* Converts a cramfs_info from little endian to host endian. */
+static inline void cramfs_info_to_host(struct cramfs_info* info)
+{
+info->crc = le32_to_cpu(info->crc);
+info->edition = le32_to_cpu(info->edition);
+info->blocks = le32_to_cpu(info->blocks);
+info->files = le32_to_cpu(info->files);
+}
+
+/* Converts a 32 bit integer from little endian to host endian */
+static inline u32 cramfs_u32_to_host(u32 val)
+{
+   return le32_to_cpu(val);
+}
+
+#ifdef __BIG_ENDIAN
+/* Converts a cramfs_inode from little endian to big endian. */
+static inline void cramfs_convert_inode_letobe(struct cramfs_inode* inode)
+{
+   u8* inode_bytes = (u8*)inode;
+   u8 old_nloffs[4];
+
+   inode->mode = swab16(inode->mode);
+   inode->uid = swab16(inode->uid);
+   inode->size = (inode_bytes[6] << 16) | (inode_bytes[5] << 8) | 
(inode_bytes[4]);
+
+   /* Save the old values of the namelength and the offset */
+   memcpy(old_nloffs, inode_bytes+8, 4);
+
+   /* Convert the namelength and the offset */
+   inode_bytes[8] = ((old_nloffs[0] & 0x3f) << 2) | ((old_nloffs[3] & 
0xc0) >> 6);
+   inode_bytes[9] = ((old_nloffs[3] & 0x3f) << 2) | ((old_nloffs[2] & 
0xc0) >> 6);
+   inode_bytes[10] = ((old_nloffs[2] & 0x3f) << 2) | ((old_nloffs[1] & 
0xc0) >> 6);
+   inode_bytes[11] = ((old_nloffs[1] & 0x3f) << 2) | ((old_nloffs[0] & 
0xc0) >> 6);
+}
+
+static inline void cramfs_inode_to_host(struct cramfs_inode *inode)
+{
+   cramfs_convert_inode_letobe(inode);
+}
+
+#elif defined(__LITTLE_ENDIAN)
+
+static inline void cramfs_inode_to_host(struct cramfs_inode *inode)
+{
+}
+
+#else
+#error "Neither __BIG_ENDIAN nor __LITTLE_ENDIAN defined."
+#endif
+
+/* Converts a cramfs superblock from little endian to host endian. */
+static inline void cramfs_super_to_host(struct cramfs_super* super)
+{
+   super->magic = le32_to_cpu(super->magic);
+   super->size = le32_to_cpu(super->size);
+   super->flags = le32_to_cpu(super->flags);
+   super->future = le32_to_cpu(super->future);
+   cramfs_info_to_host(&super->fsid);
+   cramfs_inode_to_host(&super->root);
+}
 
 static int cramfs_iget5_test(struct inode *inode, void *opaque)
 {
@@ -253,29 +318,35 @@ static int cramfs_fill_super(struct super_block *sb, void 
*data, int silent)
 
/* Read the first block and get the superblock from it */
memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
+   cramfs_super_to_host(&super);
mutex_unlock(&read_mutex);
 
/* Do sanity checks on the superblock */
-   if (super.magic != CRAMFS_MAGIC) {
-   /* check for wrong endianess */
-   if (super.magic == CRAMFS_MAGIC_WEND) {
-   if (!silent)
-   printk(KERN_ERR "cramfs: wrong endianess\n");
-   goto out;
-   }
-
+   if (super.magic != CRAMFS_MAGIC && super.magic != CRAMFS_MAGIC_WEND) {
/* check at 512 byte offset */
mutex_lock(&read_mutex);
memcpy(&super, cramfs_read(sb, 512, sizeof(super)), 
sizeof(super));
+   cramfs_super_to_host(&super);
mutex_unlock(&read_mutex);
-   if (super.magic !=

[PATCH 1/2] Make cramfs little endian only

2007-12-04 Thread Andi Drebes
The following patch makes cramfs little endian only. When trying to mount a big 
endian image,
an error message is produced.

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 inode.c |  163 +---
 1 file changed, 136 insertions(+), 27 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 350680f..3fbf567 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -4,6 +4,10 @@
  * Copyright (C) 1999 Linus Torvalds.
  *
  * This file is released under the GPL.
+ *
+ * Changelog:
+ * 11/07 - Andi Drebes <[EMAIL PROTECTED]>
+ * Made cramfs little endian only.
  */
 
 /*
@@ -40,6 +44,95 @@ static DEFINE_MUTEX(read_mutex);
 #define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
 #define OFFSET(x)  ((x)->i_ino)
 
+#ifdef __BIG_ENDIAN
+/* Converts a cramfs_info from little endian to big endian. */
+static inline void cramfs_convert_info_letobe(struct cramfs_info* info)
+{
+info->crc = swab32(info->crc);
+info->edition = swab32(info->edition);
+info->blocks = swab32(info->blocks);
+info->files = swab32(info->files);
+}
+
+/* Converts a cramfs_info from little endian to big endian. */
+static inline void cramfs_convert_inode_letobe(struct cramfs_inode* inode)
+{
+   u8* inode_bytes = (u8*)inode;
+   u8 old_nloffs[4];
+
+   inode->mode = swab16(inode->mode);
+   inode->uid = swab16(inode->uid);
+   inode->size = (inode_bytes[6] << 16) | (inode_bytes[5] << 8) | 
(inode_bytes[4]);
+
+   /* Save the old values of the namelength and the offset */
+   memcpy(old_nloffs, inode_bytes+8, 4);
+
+   /* Convert the namelength and the offset */
+   inode_bytes[8] = ((old_nloffs[0] & 0x3f) << 2) | ((old_nloffs[3] & 
0xc0) >> 6);
+   inode_bytes[9] = ((old_nloffs[3] & 0x3f) << 2) | ((old_nloffs[2] & 
0xc0) >> 6);
+   inode_bytes[10] = ((old_nloffs[2] & 0x3f) << 2) | ((old_nloffs[1] & 
0xc0) >> 6);
+   inode_bytes[11] = ((old_nloffs[1] & 0x3f) << 2) | ((old_nloffs[0] & 
0xc0) >> 6);
+}
+
+/* Converts a cramfs superblock from little endian to big endian. */
+static inline void cramfs_convert_super_letobe(struct cramfs_super* super)
+{
+   super->magic = swab32(super->magic);
+   super->size = swab32(super->size);
+   super->flags = swab32(super->flags);
+   super->future = swab32(super->future);
+   cramfs_convert_info_letobe(&super->fsid);
+   cramfs_convert_inode_letobe(&super->root);
+}
+
+/* Converts a 32 bit integer from little endian to big endian */
+static inline u32 cramfs_convert_u32_letobe(u32 val)
+{
+   return swab32(val);
+}
+
+static inline void cramfs_info_to_host(struct cramfs_info *info)
+{
+   cramfs_convert_info_letobe(info);
+}
+
+static inline void cramfs_inode_to_host(struct cramfs_inode *inode)
+{
+   cramfs_convert_inode_letobe(inode);
+}
+
+static inline void cramfs_super_to_host(struct cramfs_super *super)
+{
+   cramfs_convert_super_letobe(super);
+}
+
+static inline u32 cramfs_u32_to_host(u32 val)
+{
+   return cramfs_convert_u32_letobe(val);
+}
+
+#elif defined(__LITTLE_ENDIAN)
+
+static inline void cramfs_info_to_host(struct cramfs_info *info)
+{
+}
+
+static inline void cramfs_inode_to_host(struct cramfs_inode *inode)
+{
+}
+
+static inline void cramfs_super_to_host(struct cramfs_super *super)
+{
+}
+
+static inline u32 cramfs_u32_to_host(u32 val)
+{
+   return val;
+}
+
+#else
+#error "Neither __BIG_ENDIAN nor __LITTLE_ENDIAN defined."
+#endif
 
 static int cramfs_iget5_test(struct inode *inode, void *opaque)
 {
@@ -253,29 +346,35 @@ static int cramfs_fill_super(struct super_block *sb, void 
*data, int silent)
 
/* Read the first block and get the superblock from it */
memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
+   cramfs_super_to_host(&super);
mutex_unlock(&read_mutex);
 
/* Do sanity checks on the superblock */
-   if (super.magic != CRAMFS_MAGIC) {
-   /* check for wrong endianess */
-   if (super.magic == CRAMFS_MAGIC_WEND) {
-   if (!silent)
-   printk(KERN_ERR "cramfs: wrong endianess\n");
-   goto out;
-   }
-
+   if (super.magic != CRAMFS_MAGIC && super.magic != CRAMFS_MAGIC_WEND) {
/* check at 512 byte offset */
mutex_lock(&read_mutex);
memcpy(&super, cramfs_read(sb, 512, sizeof(super)), 
sizeof(super));
+   cramfs_super_to_host(&super);
m

[PATCH 2/2] Update documentation

2007-12-04 Thread Andi Drebes
The following patch updates the cramfs documentation according to the changes 
in PATCH 1/2.

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 README |   19 +--
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/fs/cramfs/README b/fs/cramfs/README
index 445d1c2..91efe77 100644
--- a/fs/cramfs/README
+++ b/fs/cramfs/README
@@ -6,8 +6,11 @@ a bit looser, e.g. it doesn't care if the  items are
 swapped around (though it does care that directory entries (inodes) in
 a given directory are contiguous, as this is used by readdir).
 
-All data is currently in host-endian format; neither mkcramfs nor the
-kernel ever do swabbing.  (See section `Block Size' below.)
+All data is now in little endian format. Before, it was in host endian
+format. In order to make filesystem images more shareable between machines
+with a different byte order, cramfs' specification ("this README file")
+was updated. There will be no support for big endian filesystems in the
+future.
 
 :

@@ -108,18 +111,6 @@ kernels, not even necessarily kernels of the same 
architecture if
 PAGE_CACHE_SIZE is subject to change between kernel versions
 (currently possible with arm and ia64).
 
-The remaining options try to make cramfs more sharable.
-
-One part of that is addressing endianness.  The two options here are
-`always use little-endian' (like ext2fs) or `writer chooses
-endianness; kernel adapts at runtime'.  Little-endian wins because of
-code simplicity and little CPU overhead even on big-endian machines.
-
-The cost of swabbing is changing the code to use the le32_to_cpu
-etc. macros as used by ext2fs.  We don't need to swab the compressed
-data, only the superblock, inodes and block pointers.
-
-
 The other part of making cramfs more sharable is choosing a block
 size.  The options are:
 
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] Make cramfs little endian only

2007-12-04 Thread Andi Drebes
The following patchset makes cramfs little endian only and updates
the documentation.

The changes were tested on the following types of machines:
An i386 compatible box (little endian)
UltraSparc IIi (big endian)

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] cramfs: Add mount option "swapendian"

2007-11-16 Thread Andi Drebes
Am Donnerstag, 15. November 2007 23:48 schrieb Phillip Lougher:
> > So a "v2" cramfs would be a great idea.
> 
> That is what I always considered Squashfs to be.  But I also made the 
> mistake of making Squashfs both little and big endian.  That's going to
> be fixed and then I'll make a second attempt at submitting it for
> inclusion in the mainline kernel.
I didn't have a closer look on squashfs, but I am going to have it this weekend.
So far, it seems as if no "cramfs v2" is needed. My proposal is the following:

I'll write a new patch for inclusion in the mainline kernel that makes cramfs
"little endian only". For people who really want to be able to mount filesystems
with both kinds of endianness there will be a seperate patch (not intended to be
merged into mainline) available somewhere on the net (my website or so). It will
definitely be marked as non-official in order to prevent people from creating
images in big endian. Officially, cramfs should only support little endian 
images.
If squashfs will be merged, cramfs should be marked as obsolete.

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] cramfs: Add mount option "swapendian"

2007-11-15 Thread Andi Drebes
> > This patch introduces the mount option "swapendian" for cramfs.
> > When this option is set, cramfs is able to mount an image that
> > was created on a machine whose endianness differs from the mounting
> > machine's one.
> 
> Please don't do it this way.
> 
> It would be *much* better to just standardize on one endianness, and be 
> done with it. That way there are no config options, no confusion, and the 
> code is smaller, simpler, and faster. Because nn unconditional byte swap 
> is generally faster than a conditional non-byte-swap!
This is a valid objection. The problem is that the endianness for cramfs
has never been standardized. Now there are filesystem images in both little
and big endian out there. I encountered this problem first when I tried to
mount my router's initrd. Yes, I know, I could have converted the image into
little endian. I just find that it is more consistent to support both kinds
of endianness.

> So can you please just make it little-endian? 
Actually, in my eyes, it would be better to create a new version of cramfs
that standardizes the endianness and the block size. But that doesn't solve
the problems one might have with old images.

> There can't be that many big-endian machines that really care about old 
> cramfs images..
s.a. (There's at least one...)

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] cramfs: support for other endianness

2007-11-15 Thread Andi Drebes
I checked everything twice, except the patch numbers.
Sorry about that.

The right version of the patchset should look like this:

[PATCH 1/2] cramfs: Add mount option "swapendian"
[PATCH 2/2] cramfs: update README file

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] cramfs: update README file

2007-11-15 Thread Andi Drebes
This patch updates the readme file according to the
new mount option "swapendian".

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 fs/cramfs/README |   21 +
 1 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/fs/cramfs/README b/fs/cramfs/README
index 445d1c2..acbbdc4 100644
--- a/fs/cramfs/README
+++ b/fs/cramfs/README
@@ -1,3 +1,12 @@
+Mount options
+-
+
+Currently, there is only one mount option available for cramfs:
+
+swapendian:
+   causes the filesystem's metadata to be converted from
+   non-host-endianness to host-endianness.
+
 Notes on Filesystem Layout
 --
 
@@ -108,18 +117,6 @@ kernels, not even necessarily kernels of the same 
architecture if
 PAGE_CACHE_SIZE is subject to change between kernel versions
 (currently possible with arm and ia64).
 
-The remaining options try to make cramfs more sharable.
-
-One part of that is addressing endianness.  The two options here are
-`always use little-endian' (like ext2fs) or `writer chooses
-endianness; kernel adapts at runtime'.  Little-endian wins because of
-code simplicity and little CPU overhead even on big-endian machines.
-
-The cost of swabbing is changing the code to use the le32_to_cpu
-etc. macros as used by ext2fs.  We don't need to swab the compressed
-data, only the superblock, inodes and block pointers.
-
-
 The other part of making cramfs more sharable is choosing a block
 size.  The options are:
 
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] cramfs: Add mount option "swapendian"

2007-11-15 Thread Andi Drebes
This patch introduces the mount option "swapendian" for cramfs.
When this option is set, cramfs is able to mount an image that
was created on a machine whose endianness differs from the mounting
machine's one.
If somebody tries to mount an image with another endianness but
forgets to set this option, cramfs will give a hint for it.

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
 fs/cramfs/inode.c |  112 +++--
 include/linux/cramfs_endian.h |   58 +
 include/linux/cramfs_fs_sb.h  |1 +
 3 files changed, 144 insertions(+), 27 deletions(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 350680f..8da03b0 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -4,6 +4,10 @@
  * Copyright (C) 1999 Linus Torvalds.
  *
  * This file is released under the GPL.
+ *
+ * Changelog:
+ *     11/07 - Andi Drebes <[EMAIL PROTECTED]>
+ * Added mount option "swapendian"
  */
 
 /*
@@ -18,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -157,19 +162,24 @@ static void *cramfs_read(struct super_block *sb, unsigned 
int offset, unsigned i
blocknr = offset >> PAGE_CACHE_SHIFT;
offset &= PAGE_CACHE_SIZE - 1;
 
-   /* Check if an existing buffer already has the data.. */
-   for (i = 0; i < READ_BUFFERS; i++) {
-   unsigned int blk_offset;
-
-   if (buffer_dev[i] != sb)
-   continue;
-   if (blocknr < buffer_blocknr[i])
-   continue;
-   blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT;
-   blk_offset += offset;
-   if (blk_offset + len > BUFFER_SIZE)
-   continue;
-   return read_buffers[i] + blk_offset;
+   /* Caching is disabled if the filesystem's
+  and the machine's endianness differ. */
+   if(likely(CRAMFS_SB(sb)->endian))
+   {
+   /* Check if an existing buffer already has the data.. */
+   for (i = 0; i < READ_BUFFERS; i++) {
+   unsigned int blk_offset;
+
+   if (buffer_dev[i] != sb)
+   continue;
+   if (blocknr < buffer_blocknr[i])
+   continue;
+   blk_offset = (blocknr - buffer_blocknr[i]) << 
PAGE_CACHE_SHIFT;
+   blk_offset += offset;
+   if (blk_offset + len > BUFFER_SIZE)
+   continue;
+   return read_buffers[i] + blk_offset;
+   }
}
 
devsize = mapping->host->i_size >> PAGE_CACHE_SHIFT;
@@ -246,6 +256,14 @@ static int cramfs_fill_super(struct super_block *sb, void 
*data, int silent)
return -ENOMEM;
sb->s_fs_info = sbi;
 
+   /* assume the right endianness */
+   sbi->endian = 1;
+
+   /* Check mount options:
+  Does the user want to mount an image with a different endianness? */
+   if(strcmp("swapendian", data) == 0)
+   sbi->endian = 0;
+
/* Invalidate the read buffers on mount: think disk change.. */
mutex_lock(&read_mutex);
for (i = 0; i < READ_BUFFERS; i++)
@@ -256,26 +274,49 @@ static int cramfs_fill_super(struct super_block *sb, void 
*data, int silent)
mutex_unlock(&read_mutex);
 
/* Do sanity checks on the superblock */
-   if (super.magic != CRAMFS_MAGIC) {
-   /* check for wrong endianess */
-   if (super.magic == CRAMFS_MAGIC_WEND) {
-   if (!silent)
-   printk(KERN_ERR "cramfs: wrong endianess\n");
-   goto out;
-   }
-
+   if (super.magic != CRAMFS_MAGIC && super.magic != CRAMFS_MAGIC_WEND) {
/* check at 512 byte offset */
mutex_lock(&read_mutex);
memcpy(&super, cramfs_read(sb, 512, sizeof(super)), 
sizeof(super));
mutex_unlock(&read_mutex);
-   if (super.magic != CRAMFS_MAGIC) {
-   if (super.magic == CRAMFS_MAGIC_WEND && !silent)
-   printk(KERN_ERR "cramfs: wrong endianess\n");
-   else if (!silent)
+
+   if (super.magic == CRAMFS_MAGIC_WEND) {
+   goto other_endian;
+   }
+   else if (super.magic != CRAMFS_MAGIC) {
+   if (!silent)
printk(KERN_ERR "cramfs: wrong magic\n");
+
goto out;
}
}
+   /* check for wrong endianess */
+   else if (super.magic == CRAMFS_MAGIC_WEND)
+   {
+other_en

[PATCH 0/2] cramfs: support for other endianness

2007-11-15 Thread Andi Drebes
The following patchset enables cramfs to mount images that were
created on a machine whose endianness differs from the mounting
machine's one.

Tested on an i386 box.

A discussion about this feature can be found here:

http://marc.info/?l=linux-fsdevel&m=119438573309330&w=2

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: cramfs in big endian

2007-11-11 Thread Andi Drebes
> What about simply deep-sixing cramfs and replacing it with squashfs or 
> something else?
I think this is the long term solution. Cramfs isn't a very beautiful 
filesystem. It's a good candidate for removal. However, there are still some 
distributions that use cramfs for initrds. So removing it immediately isn't a 
good idea.

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: cramfs in big endian

2007-11-10 Thread Andi Drebes
> > Endian-independent code is slower than wrong-endian code, because of the 
> > necessary conditionals.  Thus, you DO NOT WANT this(*).
> 
> I'd prefer not to have it either.  But a someone (pinhead) was smart
> enough not to define an endianess for cramfs from the beginning we're
> stuck with it.

Indeed, this is the problem. The readme file fs/cramfs/README states:

"One part of that is addressing endianness.  The two options here are
`always use little-endian' (like ext2fs) or `writer chooses
endianness; kernel adapts at runtime'.  Little-endian wins because of
code simplicity and little CPU overhead even on big-endian machines."

Unfortunately, the better idea was never implemented. Further, there's no 
information about the endianness stored in the filesystem. Guessing it and 
mounting the filesystem isn't a clean solution. Even worse, there's no 
information about which compression algorithm was used to create the 
filesystem. Guessing the compression method may lead to serious problems.

So here is my proposal for future development of cramfs:
The should tell cramfs how to mount a filesystem. Therefore, the endianness 
and the compression method both have to be specified manually. If none is 
specified, cramfs will assume host endianness and that deflate can be used in 
order to decompress the contents. If something seems to be wrong with the 
filesystem (e.g. wrong magic), cramfs will guess the endianness and inform 
the user about the guess, but it won't mount the filesystem if it doesn't 
match the endianness specified or the host's one.

Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: cramfs in big endian

2007-11-08 Thread Andi Drebes
Hi!

> Making cramfs endianess-independent shouldn't be much work.  Take a look
> at the helpers in fs/ufs/swab.h and use them for every ondisk access in
> cramfs.  Drop me a not if you need some help.
I already started working on this feature some time ago. I think I am able to 
mount cramfs images with another endianness. But all I have to test this are 
images that use LZO compression istead of deflate.

In the original post I was just asking somebody possessing a big endian 
machine to create an image in big endian / deflate format. This would help me 
a lot. Later, I want to add support for multiple compression algorithms.

Thanks so far,
Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: cramfs in big endian

2007-11-07 Thread Andi Drebes
Hi!

> I would suggest you to use squashfs instead of cramfs.
> First, it's newer, it's better, it's actively developed, it doesn't have any
> limits like the bad cramfs. 
I'm developing a new linux based firmware for my router which uses cramfs. 
Switching to squashfs still needs some time. Meanwhile, I have to work with 
cramfs. As the router uses the big endian format and as my machine works with 
the little endian format, I'm unable to mount the router's filesystem images.


Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


cramfs in big endian

2007-11-06 Thread Andi Drebes
Hi!
I'm currently trying to enable the cramfs to mount filesystems with a 
different endianness. All I have is an intel compatible machine that produces 
cramfs images in little endian format. I found a modified version of mkcramfs 
that is able to produce images in big endian mode. Unfortunately it seems to 
use a different compression algorithm (LZO) than the standard implementation 
(zlib).

I would be very glad if somebody could send me an image in big endian mode 
using the zlib deflate compression algorithm. I have uploaded a bz2 archive 
containing some testfiles. You can find it at [1].


Regards,
Andi

[1] http://drebesium.org/~hackbert/cramfs-testfiles.tar.bz2
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] cramfs: Error message about endianess

2007-08-07 Thread Andi Drebes
The README file in the cramfs subdirectory says:

"All data is currently in host-endian format; neither mkcramfs nor the
kernel ever do swabbing."

If somebody tries to mount a cramfs with the wrong endianess,
cramfs only complains about a wrong magic but doesn't inform
the user that only the endianess isn't right.

The following patch adds an error message to the cramfs sources.
If a user tries to mount a cramfs with the wrong endianess using the
patched sources, cramfs will display the message "cramfs: wrong
endianess".

I'm currently not subscribed to the list, so please CC me for any comments.

Tested on an i386 box. Diffed against Linus' git-tree.

Signed-off-by: Andi Drebes <[EMAIL PROTECTED]>
---
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 3d194a2..34c9b91 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -258,12 +258,21 @@ static int cramfs_fill_super(struct super_block *sb, void 
*data, int silent)
 
/* Do sanity checks on the superblock */
if (super.magic != CRAMFS_MAGIC) {
+   /* check for wrong endianess */
+   if(super.magic == CRAMFS_MAGIC_WEND) {
+   if (!silent)
+   printk(KERN_ERR "cramfs: wrong endianess\n");
+   goto out;
+   }
+   
/* check at 512 byte offset */
mutex_lock(&read_mutex);
memcpy(&super, cramfs_read(sb, 512, sizeof(super)), 
sizeof(super));
mutex_unlock(&read_mutex);
if (super.magic != CRAMFS_MAGIC) {
-   if (!silent)
+   if(super.magic == CRAMFS_MAGIC_WEND && !silent)
+   printk(KERN_ERR "cramfs: wrong endianess\n");
+   else if (!silent)
printk(KERN_ERR "cramfs: wrong magic\n");
goto out;
}
diff --git a/include/linux/cramfs_fs.h b/include/linux/cramfs_fs.h
index 1dba681..3be4e5a 100644
--- a/include/linux/cramfs_fs.h
+++ b/include/linux/cramfs_fs.h
@@ -4,6 +4,7 @@
 #include 
 
 #define CRAMFS_MAGIC   0x28cd3d45  /* some random number */
+#define CRAMFS_MAGIC_WEND  0x453dcd28  /* magic number with the wrong 
endianess */
 #define CRAMFS_SIGNATURE   "Compressed ROMFS"
 
 /*
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html