[PATCH 2/2][resend] Make cramfs little endian only: Update documentation
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
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
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
> 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
> 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
> 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
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
> > 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
> > +/* 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
> > +#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
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
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
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"
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"
> > 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
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
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"
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
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
> 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
> > 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
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
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
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
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