* [PATCH 0/2][resend] Make cramfs little endian only
@ 2007-12-27 14:22 Andi Drebes
2007-12-27 14:24 ` [PATCH 1/2][resend] " Andi Drebes
2007-12-27 14:25 ` [PATCH 2/2][resend] Make cramfs little endian only: Update documentation Andi Drebes
0 siblings, 2 replies; 3+ messages in thread
From: Andi Drebes @ 2007-12-27 14:22 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-fsdevel, Karel Zak, Andrew Morton, Phillip Lougher
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 <andi@programmierforen.de>
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2][resend] Make cramfs little endian only
2007-12-27 14:22 [PATCH 0/2][resend] Make cramfs little endian only Andi Drebes
@ 2007-12-27 14:24 ` Andi Drebes
2007-12-27 14:25 ` [PATCH 2/2][resend] Make cramfs little endian only: Update documentation Andi Drebes
1 sibling, 0 replies; 3+ messages in thread
From: Andi Drebes @ 2007-12-27 14:24 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-fsdevel, Karel Zak, Andrew Morton, Phillip Lougher
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 <andi@programmierforen.de>
---
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 <andi@programmierforen.de>
+ * 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) {
- if (!silent)
- printk(KERN_ERR "cramfs: wrong endianess\n");
- goto out;
- }
-
+ if (le32_to_cpu(super.magic) != CRAMFS_MAGIC &&
+ le32_to_cpu(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 (le32_to_cpu(super.magic) == CRAMFS_MAGIC_WEND)
+ goto other_endian;
+ else if (le32_to_cpu(super.magic) != CRAMFS_MAGIC) {
+ if (!silent)
printk(KERN_ERR "cramfs: wrong magic\n");
+
goto out;
}
}
+ /* check for wrong endianess */
+ else if (le32_to_cpu(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) {
+ if (le32_to_cpu(super.flags) & ~CRAMFS_SUPPORTED_FLAGS) {
printk(KERN_ERR "cramfs: unsupported filesystem features\n");
goto out;
}
/* Check that the root inode is in a sane state */
- if (!S_ISDIR(super.root.mode)) {
+ if (!S_ISDIR(cramfs_mode(&super.root))) {
printk(KERN_ERR "cramfs: root is not a directory\n");
goto out;
}
- root_offset = super.root.offset << 2;
- if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
- sbi->size=super.size;
- sbi->blocks=super.fsid.blocks;
- sbi->files=super.fsid.files;
+ root_offset = cramfs_offset(&super.root) << 2;
+ if (__le32_to_cpu(super.flags) & CRAMFS_FLAG_FSID_VERSION_2) {
+ sbi->size = le32_to_cpu(super.size);
+ sbi->blocks = le32_to_cpu(super.fsid.blocks);
+ sbi->files = le32_to_cpu(super.fsid.files);
} else {
sbi->size=1<<28;
sbi->blocks=0;
sbi->files=0;
}
- sbi->magic=super.magic;
- sbi->flags=super.flags;
+ sbi->magic = le32_to_cpu(super.magic);
+ sbi->flags = le32_to_cpu(super.flags);
if (root_offset == 0)
printk(KERN_INFO "cramfs: empty filesystem");
- else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
+ else if (!(le32_to_cpu(super.flags) & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
((root_offset != sizeof(struct cramfs_super)) &&
(root_offset != 512 + sizeof(struct cramfs_super))))
{
@@ -383,10 +424,10 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
* and the name padded out to 4-byte boundaries
* with zeroes.
*/
- namelen = de->namelen << 2;
+ namelen = cramfs_namelen(de) << 2;
memcpy(buf, name, namelen);
ino = CRAMINO(de);
- mode = de->mode;
+ mode = cramfs_mode(de);
mutex_unlock(&read_mutex);
nextoffset = offset + sizeof(*de) + namelen;
for (;;) {
@@ -432,7 +473,7 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s
if (sorted && (dentry->d_name.name[0] < name[0]))
break;
- namelen = de->namelen << 2;
+ namelen = cramfs_namelen(de) << 2;
offset += sizeof(*de) + namelen;
/* Quick check that the name is roughly the right length */
@@ -484,8 +525,8 @@ static int cramfs_readpage(struct file *file, struct page * page)
start_offset = OFFSET(inode) + maxblock*4;
mutex_lock(&read_mutex);
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 = le32_to_cpu(*(__le32 *) cramfs_read(sb, blkptr_offset-4, 4));
+ compr_len = le32_to_cpu(*(__le32 *) cramfs_read(sb, blkptr_offset, 4)) - start_offset;
mutex_unlock(&read_mutex);
pgdata = kmap(page);
if (compr_len == 0)
diff --git a/include/linux/cramfs_fs.h b/include/linux/cramfs_fs.h
index 3be4e5a..66aba06 100644
--- a/include/linux/cramfs_fs.h
+++ b/include/linux/cramfs_fs.h
@@ -28,9 +28,9 @@
* Reasonably terse representation of the inode data.
*/
struct cramfs_inode {
- __u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;
+ __le32 mode_uid;
/* SIZE for device files is i_rdev */
- __u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;
+ __le32 size_gid;
/* NAMELEN is the length of the file name, divided by 4 and
rounded up. (cramfs doesn't support hard links.) */
/* OFFSET: For symlinks and non-empty regular files, this
@@ -39,24 +39,24 @@ struct cramfs_inode {
see README). For non-empty directories it is the offset
(divided by 4) of the inode of the first file in that
directory. For anything else, offset is zero. */
- __u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;
+ __le32 namelen_offset;
};
struct cramfs_info {
- __u32 crc;
- __u32 edition;
- __u32 blocks;
- __u32 files;
+ __le32 crc;
+ __le32 edition;
+ __le32 blocks;
+ __le32 files;
};
/*
* Superblock information at the beginning of the FS.
*/
struct cramfs_super {
- __u32 magic; /* 0x28cd3d45 - random number */
- __u32 size; /* length in bytes */
- __u32 flags; /* feature flags */
- __u32 future; /* reserved for future use */
+ __le32 magic; /* 0x28cd3d45 - random number */
+ __le32 size; /* length in bytes */
+ __le32 flags; /* feature flags */
+ __le32 future; /* reserved for future use */
__u8 signature[16]; /* "Compressed ROMFS" */
struct cramfs_info fsid; /* unique filesystem info */
__u8 name[16]; /* user-defined name */
--
1.5.1.53.g77e6f
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2][resend] Make cramfs little endian only: Update documentation
2007-12-27 14:22 [PATCH 0/2][resend] Make cramfs little endian only Andi Drebes
2007-12-27 14:24 ` [PATCH 1/2][resend] " Andi Drebes
@ 2007-12-27 14:25 ` Andi Drebes
1 sibling, 0 replies; 3+ messages in thread
From: Andi Drebes @ 2007-12-27 14:25 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-fsdevel, Karel Zak, Andrew Morton, Phillip Lougher
The following patch updates the cramfs documentation according
to the changes that make cramfs little endian only.
Signed-off-by: Andi Drebes <andi@programmierforen.de>
---
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 <file_data> 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.
<filesystem>:
<superblock>
@@ -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
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-12-27 14:25 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-27 14:22 [PATCH 0/2][resend] Make cramfs little endian only Andi Drebes
2007-12-27 14:24 ` [PATCH 1/2][resend] " Andi Drebes
2007-12-27 14:25 ` [PATCH 2/2][resend] Make cramfs little endian only: Update documentation Andi Drebes
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.