> > +#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 <andi@xxxxxxxxxxxxxxxxxxx> --- 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 <andi@xxxxxxxxxxxxxxxxxxx> + * 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 != 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_endian: + if (!silent) + printk(KERN_ERR "cramfs: filesystems in big endian format are not supported any longer.\n"); + + goto out; + } /* get feature flags first */ if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { @@ -367,7 +438,8 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) copied = 0; while (offset < inode->i_size) { - struct cramfs_inode *de; + void *inode_data; + struct cramfs_inode de; unsigned long nextoffset; char *name; ino_t ino; @@ -375,20 +447,22 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) int namelen, error; mutex_lock(&read_mutex); - de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); - name = (char *)(de+1); + inode_data = cramfs_read(sb, OFFSET(inode) + offset, sizeof(de)+CRAMFS_MAXPATHLEN); + memcpy(&de, inode_data, sizeof(de)); + name = inode_data+sizeof(de); + cramfs_inode_to_host(&de); /* * Namelengths on disk are shifted by two * and the name padded out to 4-byte boundaries * with zeroes. */ - namelen = de->namelen << 2; + namelen = de.namelen << 2; memcpy(buf, name, namelen); - ino = CRAMINO(de); - mode = de->mode; + ino = CRAMINO(&de); + mode = de.mode; mutex_unlock(&read_mutex); - nextoffset = offset + sizeof(*de) + namelen; + nextoffset = offset + sizeof(de) + namelen; for (;;) { if (!namelen) { kfree(buf); @@ -421,19 +495,22 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s mutex_lock(&read_mutex); sorted = CRAMFS_SB(dir->i_sb)->flags & CRAMFS_FLAG_SORTED_DIRS; while (offset < dir->i_size) { - struct cramfs_inode *de; + void* inode_data; + struct cramfs_inode de; char *name; int namelen, retval; - de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN); - name = (char *)(de+1); + inode_data = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(de)+CRAMFS_MAXPATHLEN); + memcpy(&de, inode_data, sizeof(de)); + name = (char *)(inode_data+sizeof(de)); + cramfs_inode_to_host(&de); /* Try to take advantage of sorted directories */ if (sorted && (dentry->d_name.name[0] < name[0])) break; - namelen = de->namelen << 2; - offset += sizeof(*de) + namelen; + namelen = de.namelen << 2; + offset += sizeof(de) + namelen; /* Quick check that the name is roughly the right length */ if (((dentry->d_name.len + 3) & ~3) != namelen) @@ -454,7 +531,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s if (retval > 0) continue; if (!retval) { - struct cramfs_inode entry = *de; + struct cramfs_inode entry = de; mutex_unlock(&read_mutex); d_add(dentry, get_cramfs_inode(dir->i_sb, &entry)); return NULL; @@ -483,9 +560,13 @@ static int cramfs_readpage(struct file *file, struct page * page) start_offset = OFFSET(inode) + maxblock*4; mutex_lock(&read_mutex); - if (page->index) + if (page->index) { start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4); - compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); + start_offset = cramfs_u32_to_host(start_offset); + } + + compr_len = cramfs_u32_to_host(*(u32 *) cramfs_read(sb, blkptr_offset, 4)) - start_offset; + mutex_unlock(&read_mutex); pgdata = kmap(page); if (compr_len == 0) - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html