preliminary patch for littleendian minixfs on bigendian system
Oliver.Neukum at lrz.uni-muenchen.de
Oliver.Neukum at lrz.uni-muenchen.de
Fri May 14 07:58:46 EST 1999
Hi,
here i have the first, preliminary version of a patch that allows
the use of non-native minixfs. I am looking forward to your comments.
DO NOT USE ON IMPORTANT FILESYSTEMS. The patch has caused corruption.
Oliver Neukum
diff -u --recursive /usr/src/linux/fs/minix/inode.c tree/fs/minix/inode.c
--- /usr/src/linux/fs/minix/inode.c Thu Apr 29 22:43:28 1999
+++ tree/fs/minix/inode.c Thu May 13 22:34:45 1999
@@ -7,6 +7,9 @@
* Minix V2 fs support.
*
* Modified for 680x0 by Andreas Schwab
+ *
+ * Modified for foreign endianness by Oliver Neukum
+ *
*/
#include <linux/module.h>
@@ -19,6 +22,7 @@
#include <linux/stat.h>
#include <linux/locks.h>
#include <linux/init.h>
+#include <linux/byteorder/generic.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -26,6 +30,8 @@
#include <linux/minix_fs.h>
+#define MINIX_ENDIAN_DEBUG
+
static void minix_read_inode(struct inode * inode);
static void minix_write_inode(struct inode * inode);
static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
@@ -47,12 +53,26 @@
static void minix_write_super(struct super_block * sb)
{
struct minix_super_block * ms;
-
+ int state;
+ char endian;
if (!(sb->s_flags & MS_RDONLY)) {
ms = sb->u.minix_sb.s_ms;
-
- if (ms->s_state & MINIX_VALID_FS)
- ms->s_state &= ~MINIX_VALID_FS;
+ endian = sb->u.minix_sb.s_endianness;
+ if (endian == MINIX_BIGENDIAN) {
+ state = be16_to_cpu(ms->s_state);
+ } else if (endian == MINIX_LITTLEENDIAN) {
+ state = le16_to_cpu(ms->s_state);
+ }
+
+ if (state & MINIX_VALID_FS)
+ state &= ~MINIX_VALID_FS;
+
+ if (endian == MINIX_BIGENDIAN) {
+ ms->s_state = cpu_to_be16(state);
+ } else if (endian == MINIX_BIGENDIAN) {
+ ms->s_state = cpu_to_le16(state);
+ }
+
minix_commit_super(sb);
}
sb->s_dirt = 0;
@@ -62,11 +82,20 @@
static void minix_put_super(struct super_block *sb)
{
int i;
-
+ char endian;
+
if (!(sb->s_flags & MS_RDONLY)) {
- sb->u.minix_sb.s_ms->s_state = sb->u.minix_sb.s_mount_state;
- mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
- }
+ endian = sb->u.minix_sb.s_endianness;
+ if (endian == MINIX_BIGENDIAN) {
+ sb->u.minix_sb.s_ms->s_state =
+ cpu_to_be16(sb->u.minix_sb.s_mount_state);
+ mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
+ } else if (endian == MINIX_LITTLEENDIAN) {
+ sb->u.minix_sb.s_ms->s_state =
+ cpu_to_le16(sb->u.minix_sb.s_mount_state);
+ mark_buffer_dirty(sb->u.minix_sb.s_sbh, 1);
+ }
+ }
for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++)
brelse(sb->u.minix_sb.s_imap[i]);
for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++)
@@ -129,10 +158,12 @@
* it really _is_ a Minix filesystem, and to check the size
* of the directory entry.
*/
-static const char * minix_checkroot(struct super_block *s, struct inode *dir)
+static const char * minix_checkroot(struct super_block *s, struct inode *dir,
+ char endian)
{
struct buffer_head *bh;
struct minix_dir_entry *de;
+ u16 inumber;
const char * errmsg;
int dirsize;
@@ -146,14 +177,22 @@
de = (struct minix_dir_entry *) bh->b_data;
errmsg = "bad root directory '.' entry";
dirsize = BLOCK_SIZE;
- if (de->inode == MINIX_ROOT_INO && strcmp(de->name, ".") == 0) {
+ if (endian == MINIX_BIGENDIAN)
+ inumber = be16_to_cpu(de->inode);
+ else
+ inumber = le16_to_cpu(de->inode);
+ if (inumber == MINIX_ROOT_INO && strcmp(de->name, ".") == 0) {
errmsg = "bad root directory '..' entry";
dirsize = 8;
}
while ((dirsize <<= 1) < BLOCK_SIZE) {
de = (struct minix_dir_entry *) (bh->b_data + dirsize);
- if (de->inode != MINIX_ROOT_INO)
+ if (endian == MINIX_BIGENDIAN)
+ inumber = be16_to_cpu(de->inode);
+ else
+ inumber = le16_to_cpu(de->inode);
+ if (inumber != MINIX_ROOT_INO)
continue;
if (strcmp(de->name, ".."))
continue;
@@ -176,58 +215,124 @@
kdev_t dev = s->s_dev;
const char * errmsg;
struct inode *root_inode;
-
- /* N.B. These should be compile-time tests.
- Unfortunately that is impossible. */
- if (32 != sizeof (struct minix_inode))
- panic("bad V1 i-node size");
- if (64 != sizeof(struct minix2_inode))
- panic("bad V2 i-node size");
+ short state;
+ char endian;
MOD_INC_USE_COUNT;
lock_super(s);
set_blocksize(dev, BLOCK_SIZE);
if (!(bh = bread(dev,1,BLOCK_SIZE)))
goto out_bad_sb;
-
ms = (struct minix_super_block *) bh->b_data;
+#ifdef MINIX_ENDIAN_DEBUG
+ printk("%04x",ms->s_magic);
+#endif
+ switch (ntohs(ms->s_magic)) {
+ case MINIX_SUPER_MAGIC :
+ s->u.minix_sb.s_version = MINIX_V1;
+ s->u.minix_sb.s_dirsize = 16;
+ s->u.minix_sb.s_namelen = 14;
+ s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
+ endian = MINIX_BIGENDIAN;
+ break;
+ case MINIX_SUPER_MAGIC2 :
+ s->u.minix_sb.s_version = MINIX_V1;
+ s->u.minix_sb.s_dirsize = 32;
+ s->u.minix_sb.s_namelen = 30;
+ s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
+ endian = MINIX_BIGENDIAN;
+ break;
+ case MINIX2_SUPER_MAGIC :
+ s->u.minix_sb.s_version = MINIX_V2;
+ s->u.minix_sb.s_nzones = ms->s_zones;
+ s->u.minix_sb.s_dirsize = 16;
+ s->u.minix_sb.s_namelen = 14;
+ s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
+ endian = MINIX_BIGENDIAN;
+ break;
+ case MINIX2_SUPER_MAGIC2 :
+ s->u.minix_sb.s_version = MINIX_V2;
+ s->u.minix_sb.s_nzones = ms->s_zones;
+ s->u.minix_sb.s_dirsize = 32;
+ s->u.minix_sb.s_namelen = 30;
+ s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
+ endian = MINIX_BIGENDIAN;
+ break;
+ case MINIX_SUPER_MAGIC_REVERSED :
+ s->u.minix_sb.s_version = MINIX_V1;
+ s->u.minix_sb.s_dirsize = 16;
+ s->u.minix_sb.s_namelen = 14;
+ s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
+ endian = MINIX_LITTLEENDIAN;
+ break;
+ case MINIX_SUPER_MAGIC2_REVERSED :
+ s->u.minix_sb.s_version = MINIX_V1;
+ s->u.minix_sb.s_dirsize = 32;
+ s->u.minix_sb.s_namelen = 30;
+ s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
+ endian = MINIX_LITTLEENDIAN;
+ break;
+ case MINIX2_SUPER_MAGIC_REVERSED :
+ s->u.minix_sb.s_version = MINIX_V2;
+ s->u.minix_sb.s_nzones = ms->s_zones;
+ s->u.minix_sb.s_dirsize = 16;
+ s->u.minix_sb.s_namelen = 14;
+ s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
+ endian = MINIX_LITTLEENDIAN;
+ break;
+ case MINIX2_SUPER_MAGIC2_REVERSED :
+ s->u.minix_sb.s_version = MINIX_V2;
+ s->u.minix_sb.s_nzones = ms->s_zones;
+ s->u.minix_sb.s_dirsize = 32;
+ s->u.minix_sb.s_namelen = 30;
+ s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
+ endian = MINIX_LITTLEENDIAN;
+ break;
+ default :
+#ifdef MINIX_ENDIAN_DEBUG
+ printk("Magic not recognized.\n");
+#endif
+ goto out_no_fs;
+ }
+#ifdef MINIX_ENDIAN_DEBUG
+ if (!(endian)) printk("bigendian minixfs.\n"); else
+ printk("littleendian minixfs.\n");
+#endif
+ s->u.minix_sb.s_endianness = endian;
+
+ switch (endian) {
+ case MINIX_BIGENDIAN :
+ s->u.minix_sb.s_mount_state = be16_to_cpu(ms->s_state);
+ s->u.minix_sb.s_ninodes = be16_to_cpu(ms->s_ninodes);
+ s->u.minix_sb.s_nzones = be16_to_cpu(ms->s_nzones);
+ s->u.minix_sb.s_imap_blocks = be16_to_cpu(ms->s_imap_blocks);
+ s->u.minix_sb.s_zmap_blocks = be16_to_cpu(ms->s_zmap_blocks);
+ s->u.minix_sb.s_firstdatazone = be16_to_cpu(ms->s_firstdatazone);
+ s->u.minix_sb.s_log_zone_size = be16_to_cpu(ms->s_log_zone_size);
+ s->u.minix_sb.s_max_size = be16_to_cpu(ms->s_max_size);
+ s->s_magic = be16_to_cpu(ms->s_magic);
+ break;
+ case MINIX_LITTLEENDIAN :
+ s->u.minix_sb.s_mount_state = le16_to_cpu(ms->s_state);
+ s->u.minix_sb.s_ninodes = le16_to_cpu(ms->s_ninodes);
+ s->u.minix_sb.s_nzones = le16_to_cpu(ms->s_nzones);
+ s->u.minix_sb.s_imap_blocks = le16_to_cpu(ms->s_imap_blocks);
+ s->u.minix_sb.s_zmap_blocks = le16_to_cpu(ms->s_zmap_blocks);
+ s->u.minix_sb.s_firstdatazone = le16_to_cpu(ms->s_firstdatazone);
+ s->u.minix_sb.s_log_zone_size = le16_to_cpu(ms->s_log_zone_size);
+ s->u.minix_sb.s_max_size = le16_to_cpu(ms->s_max_size);
+ s->s_magic = le16_to_cpu(ms->s_magic);
+ break;
+ default :
+ printk("Minixfs:Strange endianness.\n");
+ goto out_unlock;
+ }
+
s->u.minix_sb.s_ms = ms;
- s->u.minix_sb.s_sbh = bh;
- s->u.minix_sb.s_mount_state = ms->s_state;
+ s->u.minix_sb.s_sbh = bh;
s->s_blocksize = BLOCK_SIZE;
s->s_blocksize_bits = BLOCK_SIZE_BITS;
- s->u.minix_sb.s_ninodes = ms->s_ninodes;
- s->u.minix_sb.s_nzones = ms->s_nzones;
- s->u.minix_sb.s_imap_blocks = ms->s_imap_blocks;
- s->u.minix_sb.s_zmap_blocks = ms->s_zmap_blocks;
- s->u.minix_sb.s_firstdatazone = ms->s_firstdatazone;
- s->u.minix_sb.s_log_zone_size = ms->s_log_zone_size;
- s->u.minix_sb.s_max_size = ms->s_max_size;
- s->s_magic = ms->s_magic;
- if (s->s_magic == MINIX_SUPER_MAGIC) {
- s->u.minix_sb.s_version = MINIX_V1;
- s->u.minix_sb.s_dirsize = 16;
- s->u.minix_sb.s_namelen = 14;
- s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
- } else if (s->s_magic == MINIX_SUPER_MAGIC2) {
- s->u.minix_sb.s_version = MINIX_V1;
- s->u.minix_sb.s_dirsize = 32;
- s->u.minix_sb.s_namelen = 30;
- s->u.minix_sb.s_link_max = MINIX_LINK_MAX;
- } else if (s->s_magic == MINIX2_SUPER_MAGIC) {
- s->u.minix_sb.s_version = MINIX_V2;
- s->u.minix_sb.s_nzones = ms->s_zones;
- s->u.minix_sb.s_dirsize = 16;
- s->u.minix_sb.s_namelen = 14;
- s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
- } else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
- s->u.minix_sb.s_version = MINIX_V2;
- s->u.minix_sb.s_nzones = ms->s_zones;
- s->u.minix_sb.s_dirsize = 32;
- s->u.minix_sb.s_namelen = 30;
- s->u.minix_sb.s_link_max = MINIX2_LINK_MAX;
- } else
- goto out_no_fs;
+
/*
* Allocate the buffer map to keep the superblock small.
@@ -262,7 +367,7 @@
/*
* Check the fs before we get the root dentry ...
*/
- errmsg = minix_checkroot(s, root_inode);
+ errmsg = minix_checkroot(s, root_inode, endian);
if (errmsg)
goto out_bad_root;
@@ -273,7 +378,15 @@
s->s_root->d_op = &minix_dentry_operations;
if (!(s->s_flags & MS_RDONLY)) {
- ms->s_state &= ~MINIX_VALID_FS;
+ if (endian == MINIX_BIGENDIAN)
+ state = be16_to_cpu(ms->s_state);
+ else
+ state = le16_to_cpu(ms->s_state);
+ state &= ~MINIX_VALID_FS;
+ if (endian == MINIX_BIGENDIAN)
+ ms->s_state = cpu_to_be16(state);
+ else
+ ms->s_state = cpu_to_le16(state);
mark_buffer_dirty(bh, 1);
s->s_dirt = 1;
}
@@ -323,7 +436,7 @@
out_bad_sb:
printk("MINIX-fs: unable to read superblock\n");
- out_unlock:
+out_unlock:
s->s_dev = 0;
unlock_super(s);
MOD_DEC_USE_COUNT;
@@ -729,7 +842,9 @@
struct buffer_head * bh;
struct minix_inode * raw_inode;
int block, ino;
-
+ char endian;
+
+
ino = inode->i_ino;
inode->i_op = NULL;
inode->i_mode = 0;
@@ -739,6 +854,7 @@
kdevname(inode->i_dev), ino);
return;
}
+ endian = inode->i_sb->u.minix_sb.s_endianness;
block = 2 + inode->i_sb->u.minix_sb.s_imap_blocks +
inode->i_sb->u.minix_sb.s_zmap_blocks +
(ino-1)/MINIX_INODES_PER_BLOCK;
@@ -749,17 +865,39 @@
}
raw_inode = ((struct minix_inode *) bh->b_data) +
(ino-1)%MINIX_INODES_PER_BLOCK;
- inode->i_mode = raw_inode->i_mode;
- inode->i_uid = raw_inode->i_uid;
- inode->i_gid = raw_inode->i_gid;
- inode->i_nlink = raw_inode->i_nlinks;
- inode->i_size = raw_inode->i_size;
- inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
- inode->i_blocks = inode->i_blksize = 0;
- if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
- inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
- else for (block = 0; block < 9; block++)
- inode->u.minix_i.u.i1_data[block] = raw_inode->i_zone[block];
+
+ if (endian == MINIX_BIGENDIAN) {
+ inode->i_mode = be16_to_cpu(raw_inode->i_mode);
+ inode->i_uid = be16_to_cpu(raw_inode->i_uid);
+ inode->i_gid = raw_inode->i_gid;
+ inode->i_nlink = raw_inode->i_nlinks;
+ inode->i_size = be32_to_cpu(raw_inode->i_size);
+ inode->i_mtime = inode->i_atime = inode->i_ctime =
+ be32_to_cpu(raw_inode->i_time);
+ inode->i_blocks = inode->i_blksize = 0;
+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+ inode->i_rdev =
+ to_kdev_t(be16_to_cpu(raw_inode->i_zone[0]));
+ else for (block = 0; block < 9; block++)
+ inode->u.minix_i.u.i1_data[block] =
+ be16_to_cpu(raw_inode->i_zone[block]);
+ } else {
+ inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+ inode->i_uid = le16_to_cpu(raw_inode->i_uid);
+ inode->i_gid = raw_inode->i_gid;
+ inode->i_nlink = raw_inode->i_nlinks;
+ inode->i_size = le32_to_cpu(raw_inode->i_size);
+ inode->i_mtime = inode->i_atime = inode->i_ctime =
+ le32_to_cpu(raw_inode->i_time);
+ inode->i_blocks = inode->i_blksize = 0;
+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+ inode->i_rdev =
+ to_kdev_t(le16_to_cpu(raw_inode->i_zone[0]));
+ else for (block = 0; block < 9; block++)
+ inode->u.minix_i.u.i1_data[block] =
+ le16_to_cpu(raw_inode->i_zone[block]);
+ }
+
brelse(bh);
if (S_ISREG(inode->i_mode))
inode->i_op = &minix_file_inode_operations;
diff -u --recursive /usr/src/linux/include/linux/minix_fs.h tree/include/linux/minix_fs.h
--- /usr/src/linux/include/linux/minix_fs.h Thu Apr 29 22:43:31 1999
+++ tree/include/linux/minix_fs.h Thu May 13 21:11:03 1999
@@ -19,10 +19,22 @@
#define MINIX_I_MAP_SLOTS 8
#define MINIX_Z_MAP_SLOTS 64
+
+/*
+minixfs exists in both endiannesses, for this purposes network byte
+order is considered primary
+*/
+
#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */
#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */
+
+#define MINIX_SUPER_MAGIC_REVERSED 0x7F13
+#define MINIX_SUPER_MAGIC2_REVERSED 0x8F13
+#define MINIX2_SUPER_MAGIC_REVERSED 0x6824
+#define MINIX2_SUPER_MAGIC2_REVERSED 0x7824
+
#define MINIX_VALID_FS 0x0001 /* Clean fs. */
#define MINIX_ERROR_FS 0x0002 /* fs has errors. */
@@ -31,6 +43,10 @@
#define MINIX_V1 0x0001 /* original minix fs */
#define MINIX_V2 0x0002 /* minix V2 fs */
+
+#define MINIX_BIGENDIAN 0x00 /* indicate endianess */
+#define MINIX_LITTLEENDIAN 0x01 /* on disk */
+#define MINIX_PDP11ENDIAN 0x02 /* not implemented */
#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version
diff -u --recursive /usr/src/linux/include/linux/minix_fs_sb.h tree/include/linux/minix_fs_sb.h
--- /usr/src/linux/include/linux/minix_fs_sb.h Sat Jun 13 22:25:12 1998
+++ tree/include/linux/minix_fs_sb.h Thu May 13 12:40:47 1999
@@ -21,6 +21,7 @@
struct minix_super_block * s_ms;
unsigned short s_mount_state;
unsigned short s_version;
+ char s_endianness;
};
#endif
[[ This message was sent via the linuxppc-dev mailing list. Replies are ]]
[[ not forced back to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting. ]]
More information about the Linuxppc-dev
mailing list