freevxfs: handle big endian HP-UX file systems

To support VxFS filesystems from HP-UX on x86 systems we need to
implement byte swapping, and to keep support for Unixware filesystems
it needs to be the complicated dual-endian kind ala sysvfs.

To do this properly we have to split the on disk and in-core inode
so that we can keep the in-core one in native endianness.  All other
structures are byteswapped on demand.

Signed-off-by: Krzysztof Błaszkowski <kb@sysmikro.com.pl>
[hch: make spare happy]
Signed-off-by: Christoph Hellwig <hch@lst.de>
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index c8a9265..4b561de 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -38,13 +38,6 @@
  */
 #include <linux/types.h>
 
-
-/*
- * Data types for use with the VxFS ondisk format.
- */
-typedef	int32_t		vx_daddr_t;
-typedef int32_t		vx_ino_t;
-
 /*
  * Superblock magic number (vxfs_super->vs_magic).
  */
@@ -60,6 +53,14 @@
  */
 #define VXFS_NEFREE		32
 
+enum vxfs_byte_order {
+	VXFS_BO_LE,
+	VXFS_BO_BE,
+};
+
+typedef __u16 __bitwise __fs16;
+typedef __u32 __bitwise __fs32;
+typedef __u64 __bitwise __fs64;
 
 /*
  * VxFS superblock (disk).
@@ -71,83 +72,83 @@
 	 * Lots of this fields are no more used by version 2
 	 * and never filesystems.
 	 */
-	u_int32_t	vs_magic;		/* Magic number */
-	int32_t		vs_version;		/* VxFS version */
-	u_int32_t	vs_ctime;		/* create time - secs */
-	u_int32_t	vs_cutime;		/* create time - usecs */
-	int32_t		__unused1;		/* unused */
-	int32_t		__unused2;		/* unused */
-	vx_daddr_t	vs_old_logstart;	/* obsolete */
-	vx_daddr_t	vs_old_logend;		/* obsolete */
-	int32_t		vs_bsize;		/* block size */
-	int32_t		vs_size;		/* number of blocks */
-	int32_t		vs_dsize;		/* number of data blocks */
-	u_int32_t	vs_old_ninode;		/* obsolete */
-	int32_t		vs_old_nau;		/* obsolete */
-	int32_t		__unused3;		/* unused */
-	int32_t		vs_old_defiextsize;	/* obsolete */
-	int32_t		vs_old_ilbsize;		/* obsolete */
-	int32_t		vs_immedlen;		/* size of immediate data area */
-	int32_t		vs_ndaddr;		/* number of direct extentes */
-	vx_daddr_t	vs_firstau;		/* address of first AU */
-	vx_daddr_t	vs_emap;		/* offset of extent map in AU */
-	vx_daddr_t	vs_imap;		/* offset of inode map in AU */
-	vx_daddr_t	vs_iextop;		/* offset of ExtOp. map in AU */
-	vx_daddr_t	vs_istart;		/* offset of inode list in AU */
-	vx_daddr_t	vs_bstart;		/* offset of fdblock in AU */
-	vx_daddr_t	vs_femap;		/* aufirst + emap */
-	vx_daddr_t	vs_fimap;		/* aufirst + imap */
-	vx_daddr_t	vs_fiextop;		/* aufirst + iextop */
-	vx_daddr_t	vs_fistart;		/* aufirst + istart */
-	vx_daddr_t	vs_fbstart;		/* aufirst + bstart */
-	int32_t		vs_nindir;		/* number of entries in indir */
-	int32_t		vs_aulen;		/* length of AU in blocks */
-	int32_t		vs_auimlen;		/* length of imap in blocks */
-	int32_t		vs_auemlen;		/* length of emap in blocks */
-	int32_t		vs_auilen;		/* length of ilist in blocks */
-	int32_t		vs_aupad;		/* length of pad in blocks */
-	int32_t		vs_aublocks;		/* data blocks in AU */
-	int32_t		vs_maxtier;		/* log base 2 of aublocks */
-	int32_t		vs_inopb;		/* number of inodes per blk */
-	int32_t		vs_old_inopau;		/* obsolete */
-	int32_t		vs_old_inopilb;		/* obsolete */
-	int32_t		vs_old_ndiripau;	/* obsolete */
-	int32_t		vs_iaddrlen;		/* size of indirect addr ext. */
-	int32_t		vs_bshift;		/* log base 2 of bsize */
-	int32_t		vs_inoshift;		/* log base 2 of inobp */
-	int32_t		vs_bmask;		/* ~( bsize - 1 ) */
-	int32_t		vs_boffmask;		/* bsize - 1 */
-	int32_t		vs_old_inomask;		/* old_inopilb - 1 */
-	int32_t		vs_checksum;		/* checksum of V1 data */
+	__fs32		vs_magic;		/* Magic number */
+	__fs32		vs_version;		/* VxFS version */
+	__fs32		vs_ctime;		/* create time - secs */
+	__fs32		vs_cutime;		/* create time - usecs */
+	__fs32		__unused1;		/* unused */
+	__fs32		__unused2;		/* unused */
+	__fs32		vs_old_logstart;	/* obsolete */
+	__fs32		vs_old_logend;		/* obsolete */
+	__fs32		vs_bsize;		/* block size */
+	__fs32		vs_size;		/* number of blocks */
+	__fs32		vs_dsize;		/* number of data blocks */
+	__fs32		vs_old_ninode;		/* obsolete */
+	__fs32		vs_old_nau;		/* obsolete */
+	__fs32		__unused3;		/* unused */
+	__fs32		vs_old_defiextsize;	/* obsolete */
+	__fs32		vs_old_ilbsize;		/* obsolete */
+	__fs32		vs_immedlen;		/* size of immediate data area */
+	__fs32		vs_ndaddr;		/* number of direct extentes */
+	__fs32		vs_firstau;		/* address of first AU */
+	__fs32		vs_emap;		/* offset of extent map in AU */
+	__fs32		vs_imap;		/* offset of inode map in AU */
+	__fs32		vs_iextop;		/* offset of ExtOp. map in AU */
+	__fs32		vs_istart;		/* offset of inode list in AU */
+	__fs32		vs_bstart;		/* offset of fdblock in AU */
+	__fs32		vs_femap;		/* aufirst + emap */
+	__fs32		vs_fimap;		/* aufirst + imap */
+	__fs32		vs_fiextop;		/* aufirst + iextop */
+	__fs32		vs_fistart;		/* aufirst + istart */
+	__fs32		vs_fbstart;		/* aufirst + bstart */
+	__fs32		vs_nindir;		/* number of entries in indir */
+	__fs32		vs_aulen;		/* length of AU in blocks */
+	__fs32		vs_auimlen;		/* length of imap in blocks */
+	__fs32		vs_auemlen;		/* length of emap in blocks */
+	__fs32		vs_auilen;		/* length of ilist in blocks */
+	__fs32		vs_aupad;		/* length of pad in blocks */
+	__fs32		vs_aublocks;		/* data blocks in AU */
+	__fs32		vs_maxtier;		/* log base 2 of aublocks */
+	__fs32		vs_inopb;		/* number of inodes per blk */
+	__fs32		vs_old_inopau;		/* obsolete */
+	__fs32		vs_old_inopilb;		/* obsolete */
+	__fs32		vs_old_ndiripau;	/* obsolete */
+	__fs32		vs_iaddrlen;		/* size of indirect addr ext. */
+	__fs32		vs_bshift;		/* log base 2 of bsize */
+	__fs32		vs_inoshift;		/* log base 2 of inobp */
+	__fs32		vs_bmask;		/* ~( bsize - 1 ) */
+	__fs32		vs_boffmask;		/* bsize - 1 */
+	__fs32		vs_old_inomask;		/* old_inopilb - 1 */
+	__fs32		vs_checksum;		/* checksum of V1 data */
 	
 	/*
 	 * Version 1, writable
 	 */
-	int32_t		vs_free;		/* number of free blocks */
-	int32_t		vs_ifree;		/* number of free inodes */
-	int32_t		vs_efree[VXFS_NEFREE];	/* number of free extents by size */
-	int32_t		vs_flags;		/* flags ?!? */
-	u_int8_t	vs_mod;			/* filesystem has been changed */
-	u_int8_t	vs_clean;		/* clean FS */
-	u_int16_t	__unused4;		/* unused */
-	u_int32_t	vs_firstlogid;		/* mount time log ID */
-	u_int32_t	vs_wtime;		/* last time written - sec */
-	u_int32_t	vs_wutime;		/* last time written - usec */
-	u_int8_t	vs_fname[6];		/* FS name */
-	u_int8_t	vs_fpack[6];		/* FS pack name */
-	int32_t		vs_logversion;		/* log format version */
-	int32_t		__unused5;		/* unused */
+	__fs32		vs_free;		/* number of free blocks */
+	__fs32		vs_ifree;		/* number of free inodes */
+	__fs32		vs_efree[VXFS_NEFREE];	/* number of free extents by size */
+	__fs32		vs_flags;		/* flags ?!? */
+	__u8		vs_mod;			/* filesystem has been changed */
+	__u8		vs_clean;		/* clean FS */
+	__fs16		__unused4;		/* unused */
+	__fs32		vs_firstlogid;		/* mount time log ID */
+	__fs32		vs_wtime;		/* last time written - sec */
+	__fs32		vs_wutime;		/* last time written - usec */
+	__u8		vs_fname[6];		/* FS name */
+	__u8		vs_fpack[6];		/* FS pack name */
+	__fs32		vs_logversion;		/* log format version */
+	__u32		__unused5;		/* unused */
 	
 	/*
 	 * Version 2, Read-only
 	 */
-	vx_daddr_t	vs_oltext[2];		/* OLT extent and replica */
-	int32_t		vs_oltsize;		/* OLT extent size */
-	int32_t		vs_iauimlen;		/* size of inode map */
-	int32_t		vs_iausize;		/* size of IAU in blocks */
-	int32_t		vs_dinosize;		/* size of inode in bytes */
-	int32_t		vs_old_dniaddr;		/* indir levels per inode */
-	int32_t		vs_checksum2;		/* checksum of V2 RO */
+	__fs32		vs_oltext[2];		/* OLT extent and replica */
+	__fs32		vs_oltsize;		/* OLT extent size */
+	__fs32		vs_iauimlen;		/* size of inode map */
+	__fs32		vs_iausize;		/* size of IAU in blocks */
+	__fs32		vs_dinosize;		/* size of inode in bytes */
+	__fs32		vs_old_dniaddr;		/* indir levels per inode */
+	__fs32		vs_checksum2;		/* checksum of V2 RO */
 
 	/*
 	 * Actually much more...
@@ -168,8 +169,32 @@
 	ino_t			vsi_fshino;	/* fileset header inode */
 	daddr_t			vsi_oltext;	/* OLT extent */
 	daddr_t			vsi_oltsize;	/* OLT size */
+	enum vxfs_byte_order	byte_order;
 };
 
+static inline u16 fs16_to_cpu(struct vxfs_sb_info *sbi, __fs16 a)
+{
+	if (sbi->byte_order == VXFS_BO_BE)
+		return be16_to_cpu((__force __be16)a);
+	else
+		return le16_to_cpu((__force __le16)a);
+}
+
+static inline u32 fs32_to_cpu(struct vxfs_sb_info *sbi, __fs32 a)
+{
+	if (sbi->byte_order == VXFS_BO_BE)
+		return be32_to_cpu((__force __be32)a);
+	else
+		return le32_to_cpu((__force __le32)a);
+}
+
+static inline u64 fs64_to_cpu(struct vxfs_sb_info *sbi, __fs64 a)
+{
+	if (sbi->byte_order == VXFS_BO_BE)
+		return be64_to_cpu((__force __be64)a);
+	else
+		return le64_to_cpu((__force __le64)a);
+}
 
 /*
  * File modes.  File types above 0xf000 are vxfs internal only, they should
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index f86fd3c..1fd41cf 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -68,8 +68,9 @@
 {
 	struct super_block *sb = ip->i_sb;
 	struct vxfs_inode_info *vip = VXFS_INO(ip);
+	struct vxfs_sb_info *sbi = VXFS_SBI(sb);
 	unsigned long bsize = sb->s_blocksize;
-	u32 indsize = vip->vii_ext4.ve4_indsize;
+	u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize);
 	int i;
 
 	if (indsize > sb->s_blocksize)
@@ -77,22 +78,24 @@
 
 	for (i = 0; i < VXFS_NDADDR; i++) {
 		struct direct *d = vip->vii_ext4.ve4_direct + i;
-		if (bn >= 0 && bn < d->size)
-			return (bn + d->extent);
-		bn -= d->size;
+		if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
+			return (bn + fs32_to_cpu(sbi, d->extent));
+		bn -= fs32_to_cpu(sbi, d->size);
 	}
 
 	if ((bn / (indsize * indsize * bsize / 4)) == 0) {
 		struct buffer_head *buf;
 		daddr_t	bno;
-		u32 *indir;
+		__fs32 *indir;
 
-		buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]);
+		buf = sb_bread(sb,
+			fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0]));
 		if (!buf || !buffer_mapped(buf))
 			goto fail_buf;
 
-		indir = (u32 *)buf->b_data;
-		bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
+		indir = (__fs32 *)buf->b_data;
+		bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
+			(bn % indsize);
 
 		brelse(buf);
 		return bno;
@@ -127,6 +130,7 @@
 static daddr_t
 vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 {
+	struct vxfs_sb_info		*sbi = VXFS_SBI(ip->i_sb);
 	struct buffer_head		*bp = NULL;
 	daddr_t				pblock = 0;
 	int				i;
@@ -142,24 +146,27 @@
 
 		typ = ((struct vxfs_typed *)bp->b_data) +
 			(i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
-		off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+		off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
 
 		if (block < off) {
 			brelse(bp);
 			continue;
 		}
 
-		switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+		switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >>
+				VXFS_TYPED_TYPESHIFT)) {
 		case VXFS_TYPED_INDIRECT:
-			pblock = vxfs_bmap_indir(ip, typ->vt_block,
-					typ->vt_size, block - off);
+			pblock = vxfs_bmap_indir(ip,
+					fs32_to_cpu(sbi, typ->vt_block),
+					fs32_to_cpu(sbi, typ->vt_size),
+					block - off);
 			if (pblock == -2)
 				break;
 			goto out;
 		case VXFS_TYPED_DATA:
-			if ((block - off) >= typ->vt_size)
+			if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
 				break;
-			pblock = (typ->vt_block + block - off);
+			pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
 			goto out;
 		case VXFS_TYPED_INDIRECT_DEV4:
 		case VXFS_TYPED_DATA_DEV4: {
@@ -167,13 +174,15 @@
 				(struct vxfs_typed_dev4 *)typ;
 
 			printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
-			printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
-			       (unsigned long long) typ4->vd4_block,
-			       (unsigned long long) typ4->vd4_size,
-			       typ4->vd4_dev);
+			printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
+			       fs64_to_cpu(sbi, typ4->vd4_block),
+			       fs64_to_cpu(sbi, typ4->vd4_size),
+			       fs32_to_cpu(sbi, typ4->vd4_dev));
 			goto fail;
 		}
 		default:
+			printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
+				__LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
 			BUG();
 		}
 		brelse(bp);
@@ -201,28 +210,33 @@
 vxfs_bmap_typed(struct inode *ip, long iblock)
 {
 	struct vxfs_inode_info		*vip = VXFS_INO(ip);
+	struct vxfs_sb_info		*sbi = VXFS_SBI(ip->i_sb);
 	daddr_t				pblock = 0;
 	int				i;
 
 	for (i = 0; i < VXFS_NTYPED; i++) {
 		struct vxfs_typed	*typ = vip->vii_org.typed + i;
-		int64_t			off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+		u64			hdr = fs64_to_cpu(sbi, typ->vt_hdr);
+		int64_t			off = (hdr & VXFS_TYPED_OFFSETMASK);
 
 #ifdef DIAGNOSTIC
 		vxfs_typdump(typ);
 #endif
 		if (iblock < off)
 			continue;
-		switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+		switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
 		case VXFS_TYPED_INDIRECT:
-			pblock = vxfs_bmap_indir(ip, typ->vt_block,
-					typ->vt_size, iblock - off);
+			pblock = vxfs_bmap_indir(ip,
+					fs32_to_cpu(sbi, typ->vt_block),
+					fs32_to_cpu(sbi, typ->vt_size),
+					iblock - off);
 			if (pblock == -2)
 				break;
 			return (pblock);
 		case VXFS_TYPED_DATA:
-			if ((iblock - off) < typ->vt_size)
-				return (typ->vt_block + iblock - off);
+			if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
+				return (fs32_to_cpu(sbi, typ->vt_block) +
+						iblock - off);
 			break;
 		case VXFS_TYPED_INDIRECT_DEV4:
 		case VXFS_TYPED_DATA_DEV4: {
@@ -230,10 +244,10 @@
 				(struct vxfs_typed_dev4 *)typ;
 
 			printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
-			printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
-			       (unsigned long long) typ4->vd4_block,
-			       (unsigned long long) typ4->vd4_size,
-			       typ4->vd4_dev);
+			printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
+			       fs64_to_cpu(sbi, typ4->vd4_block),
+			       fs64_to_cpu(sbi, typ4->vd4_size),
+			       fs32_to_cpu(sbi, typ4->vd4_dev));
 			return 0;
 		}
 		default:
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index aaf1fb0..acc5477 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -48,9 +48,9 @@
  * Linux driver for now.
  */
 struct vxfs_dirblk {
-	u_int16_t	d_free;		/* free space in dirblock */
-	u_int16_t	d_nhash;	/* no of hash chains */
-	u_int16_t	d_hash[1];	/* hash chain */
+	__fs16		d_free;		/* free space in dirblock */
+	__fs16		d_nhash;	/* no of hash chains */
+	__fs16		d_hash[1];	/* hash chain */
 };
 
 /*
@@ -63,10 +63,10 @@
  * VxFS directory entry.
  */
 struct vxfs_direct {
-	vx_ino_t	d_ino;			/* inode number */
-	u_int16_t	d_reclen;		/* record length */
-	u_int16_t	d_namelen;		/* d_name length */
-	u_int16_t	d_hashnext;		/* next hash entry */
+	__fs32		d_ino;			/* inode number */
+	__fs16		d_reclen;		/* record length */
+	__fs16		d_namelen;		/* d_name length */
+	__fs16		d_hashnext;		/* next hash entry */
 	char		d_name[VXFS_NAMELEN];	/* name */
 };
 
@@ -87,6 +87,7 @@
 /*
  * VXFS_DIRBLKOV is the overhead of a specific dirblock.
  */
-#define VXFS_DIRBLKOV(dbp)	((sizeof(short) * dbp->d_nhash) + 4)
+#define VXFS_DIRBLKOV(sbi, dbp)	\
+	((sizeof(short) * fs16_to_cpu(sbi, dbp->d_nhash)) + 4)
 
 #endif /* _VXFS_DIR_H_ */
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c9a6a94..e7501cb 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -153,7 +153,8 @@
 	vxfs_dumpfsh(pfp);
 #endif
 
-	tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
+	tip = vxfs_blkiget(sbp, infp->vsi_iext,
+			fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
 	if (!tip)
 		goto out_free_pfp;
 
@@ -169,7 +170,7 @@
 		goto out_iput_stilist;
 	}
 
-	tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
+	tip = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
 	if (!tip)
 		goto out_iput_stilist;
 	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
diff --git a/fs/freevxfs/vxfs_fshead.h b/fs/freevxfs/vxfs_fshead.h
index ead0d64..a786cc5 100644
--- a/fs/freevxfs/vxfs_fshead.h
+++ b/fs/freevxfs/vxfs_fshead.h
@@ -42,20 +42,20 @@
  * Fileset header 
  */
 struct vxfs_fsh {
-	u_int32_t	fsh_version;		/* fileset header version */
-	u_int32_t	fsh_fsindex;		/* fileset index */
-	u_int32_t	fsh_time;		/* modification time - sec */
-	u_int32_t	fsh_utime;		/* modification time - usec */
-	u_int32_t	fsh_extop;		/* extop flags */
-	vx_ino_t	fsh_ninodes;		/* allocated inodes */
-	u_int32_t	fsh_nau;		/* number of IAUs */
-	u_int32_t	fsh_old_ilesize;	/* old size of ilist */
-	u_int32_t	fsh_dflags;		/* flags */
-	u_int32_t	fsh_quota;		/* quota limit */
-	vx_ino_t	fsh_maxinode;		/* maximum inode number */
-	vx_ino_t	fsh_iauino;		/* IAU inode */
-	vx_ino_t	fsh_ilistino[2];	/* ilist inodes */
-	vx_ino_t	fsh_lctino;		/* link count table inode */
+	__fs32		fsh_version;		/* fileset header version */
+	__fs32		fsh_fsindex;		/* fileset index */
+	__fs32		fsh_time;		/* modification time - sec */
+	__fs32		fsh_utime;		/* modification time - usec */
+	__fs32		fsh_extop;		/* extop flags */
+	__fs32		fsh_ninodes;		/* allocated inodes */
+	__fs32		fsh_nau;		/* number of IAUs */
+	__fs32		fsh_old_ilesize;	/* old size of ilist */
+	__fs32		fsh_dflags;		/* flags */
+	__fs32		fsh_quota;		/* quota limit */
+	__fs32		fsh_maxinode;		/* maximum inode number */
+	__fs32		fsh_iauino;		/* IAU inode */
+	__fs32		fsh_ilistino[2];	/* ilist inodes */
+	__fs32		fsh_lctino;		/* link count table inode */
 
 	/*
 	 * Slightly more fields follow, but they
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 3e2ccad..15de300 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -68,6 +68,33 @@
 }
 #endif
 
+static inline void dip2vip_cpy(struct vxfs_sb_info *sbi,
+		struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
+{
+	vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode);
+	vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink);
+	vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid);
+	vip->vii_gid = fs32_to_cpu(sbi, dip->vdi_gid);
+	vip->vii_size = fs64_to_cpu(sbi, dip->vdi_size);
+	vip->vii_atime = fs32_to_cpu(sbi, dip->vdi_atime);
+	vip->vii_autime = fs32_to_cpu(sbi, dip->vdi_autime);
+	vip->vii_mtime = fs32_to_cpu(sbi, dip->vdi_mtime);
+	vip->vii_mutime = fs32_to_cpu(sbi, dip->vdi_mutime);
+	vip->vii_ctime = fs32_to_cpu(sbi, dip->vdi_ctime);
+	vip->vii_cutime = fs32_to_cpu(sbi, dip->vdi_cutime);
+	vip->vii_orgtype = dip->vdi_orgtype;
+
+	vip->vii_blocks = fs32_to_cpu(sbi, dip->vdi_blocks);
+	vip->vii_gen = fs32_to_cpu(sbi, dip->vdi_gen);
+
+	if (VXFS_ISDIR(vip))
+		vip->vii_dotdot = fs32_to_cpu(sbi, dip->vdi_dotdot);
+	else if (!VXFS_ISREG(vip) && !VXFS_ISLNK(vip))
+		vip->vii_rdev = fs32_to_cpu(sbi, dip->vdi_rdev);
+
+	/* don't endian swap the fields that differ by orgtype */
+	memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org));
+}
 
 /**
  * vxfs_blkiget - find inode based on extent #
@@ -102,7 +129,7 @@
 		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
 			goto fail;
 		dip = (struct vxfs_dinode *)(bp->b_data + offset);
-		memcpy(vip, dip, sizeof(*vip));
+		dip2vip_cpy(VXFS_SBI(sbp), vip, dip);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
@@ -144,7 +171,7 @@
 		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
 			goto fail;
 		dip = (struct vxfs_dinode *)(kaddr + offset);
-		memcpy(vip, dip, sizeof(*vip));
+		dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 240aeb1..93d0114 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -66,74 +66,74 @@
  * Data stored immediately in the inode.
  */
 struct vxfs_immed {
-	u_int8_t	vi_immed[VXFS_NIMMED];
+	__u8			vi_immed[VXFS_NIMMED];
 };
 
 struct vxfs_ext4 {
-	u_int32_t		ve4_spare;		/* ?? */
-	u_int32_t		ve4_indsize;		/* Indirect extent size */
-	vx_daddr_t		ve4_indir[VXFS_NIADDR];	/* Indirect extents */
+	__fs32			ve4_spare;		/* ?? */
+	__fs32			ve4_indsize;		/* Indirect extent size */
+	__fs32			ve4_indir[VXFS_NIADDR];	/* Indirect extents */
 	struct direct {					/* Direct extents */
-		vx_daddr_t	extent;			/* Extent number */
-		int32_t		size;			/* Size of extent */
+		__fs32		extent;			/* Extent number */
+		__fs32		size;			/* Size of extent */
 	} ve4_direct[VXFS_NDADDR];
 };
 
 struct vxfs_typed {
-	u_int64_t	vt_hdr;		/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
-	vx_daddr_t	vt_block;	/* Extent block */
-	int32_t		vt_size;	/* Size in blocks */
+	__fs64		vt_hdr;		/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
+	__fs32		vt_block;	/* Extent block */
+	__fs32		vt_size;	/* Size in blocks */
 };
 
 struct vxfs_typed_dev4 {
-	u_int64_t	vd4_hdr;	/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
-	u_int64_t	vd4_block;	/* Extent block */
-	u_int64_t	vd4_size;	/* Size in blocks */
-	int32_t		vd4_dev;	/* Device ID */
-	u_int32_t	__pad1;
+	__fs64		vd4_hdr;	/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
+	__fs64		vd4_block;	/* Extent block */
+	__fs64		vd4_size;	/* Size in blocks */
+	__fs32		vd4_dev;	/* Device ID */
+	__u8		__pad1;
 };
 
 /*
  * The inode as contained on the physical device.
  */
 struct vxfs_dinode {
-	int32_t		vdi_mode;
-	u_int32_t	vdi_nlink;	/* Link count */
-	u_int32_t	vdi_uid;	/* UID */
-	u_int32_t	vdi_gid;	/* GID */
-	u_int64_t	vdi_size;	/* Inode size in bytes */
-	u_int32_t	vdi_atime;	/* Last time accessed - sec */
-	u_int32_t	vdi_autime;	/* Last time accessed - usec */
-	u_int32_t	vdi_mtime;	/* Last modify time - sec */
-	u_int32_t	vdi_mutime;	/* Last modify time - usec */
-	u_int32_t	vdi_ctime;	/* Create time - sec */
-	u_int32_t	vdi_cutime;	/* Create time - usec */
-	u_int8_t	vdi_aflags;	/* Allocation flags */
-	u_int8_t	vdi_orgtype;	/* Organisation type */
-	u_int16_t	vdi_eopflags;
-	u_int32_t	vdi_eopdata;
+	__fs32		vdi_mode;
+	__fs32		vdi_nlink;	/* Link count */
+	__fs32		vdi_uid;	/* UID */
+	__fs32		vdi_gid;	/* GID */
+	__fs64		vdi_size;	/* Inode size in bytes */
+	__fs32		vdi_atime;	/* Last time accessed - sec */
+	__fs32		vdi_autime;	/* Last time accessed - usec */
+	__fs32		vdi_mtime;	/* Last modify time - sec */
+	__fs32		vdi_mutime;	/* Last modify time - usec */
+	__fs32		vdi_ctime;	/* Create time - sec */
+	__fs32		vdi_cutime;	/* Create time - usec */
+	__u8		vdi_aflags;	/* Allocation flags */
+	__u8		vdi_orgtype;	/* Organisation type */
+	__fs16		vdi_eopflags;
+	__fs32		vdi_eopdata;
 	union {
-		u_int32_t		rdev;
-		u_int32_t		dotdot;
+		__fs32			rdev;
+		__fs32			dotdot;
 		struct {
-			u_int32_t	reserved;
-			u_int32_t	fixextsize;
+			__u32		reserved;
+			__fs32		fixextsize;
 		} i_regular;
 		struct {
-			u_int32_t	matchino;
-			u_int32_t	fsetindex;
+			__fs32		matchino;
+			__fs32		fsetindex;
 		} i_vxspec;
-		u_int64_t		align;
+		__u64			align;
 	} vdi_ftarea;
-	u_int32_t	vdi_blocks;	/* How much blocks does inode occupy */
-	u_int32_t	vdi_gen;	/* Inode generation */
-	u_int64_t	vdi_version;	/* Version */
+	__fs32		vdi_blocks;	/* How much blocks does inode occupy */
+	__fs32		vdi_gen;	/* Inode generation */
+	__fs64		vdi_version;	/* Version */
 	union {
 		struct vxfs_immed	immed;
 		struct vxfs_ext4	ext4;
 		struct vxfs_typed	typed[VXFS_NTYPED];
 	} vdi_org;
-	u_int32_t	vdi_iattrino;
+	__fs32		vdi_iattrino;
 };
 
 #define vdi_rdev	vdi_ftarea.rdev
@@ -149,32 +149,38 @@
 
 /*
  * The inode as represented in the main memory.
- *
- * TBD: This should become a separate structure...
  */
-#define vxfs_inode_info	vxfs_dinode
+struct vxfs_inode_info {
+	__u32		vii_mode;
+	__u32		vii_nlink;	/* Link count */
+	__u32		vii_uid;	/* UID */
+	__u32		vii_gid;	/* GID */
+	__u64		vii_size;	/* Inode size in bytes */
+	__u32		vii_atime;	/* Last time accessed - sec */
+	__u32		vii_autime;	/* Last time accessed - usec */
+	__u32		vii_mtime;	/* Last modify time - sec */
+	__u32		vii_mutime;	/* Last modify time - usec */
+	__u32		vii_ctime;	/* Create time - sec */
+	__u32		vii_cutime;	/* Create time - usec */
+	__u8		vii_orgtype;	/* Organisation type */
+	union {
+		__u32			rdev;
+		__u32			dotdot;
+	} vii_ftarea;
+	__u32		vii_blocks;	/* How much blocks does inode occupy */
+	__u32		vii_gen;	/* Inode generation */
+	union {
+		struct vxfs_immed	immed;
+		struct vxfs_ext4	ext4;
+		struct vxfs_typed	typed[VXFS_NTYPED];
+	} vii_org;
+};
 
-#define vii_mode	vdi_mode
-#define vii_uid		vdi_uid
-#define vii_gid		vdi_gid
-#define vii_nlink	vdi_nlink
-#define vii_size	vdi_size
-#define vii_atime	vdi_atime
-#define vii_ctime	vdi_ctime
-#define vii_mtime	vdi_mtime
-#define vii_blocks	vdi_blocks
-#define vii_org		vdi_org
-#define vii_orgtype	vdi_orgtype
-#define vii_gen		vdi_gen
+#define vii_rdev	vii_ftarea.rdev
+#define vii_dotdot	vii_ftarea.dotdot
 
-#define vii_rdev	vdi_ftarea.rdev
-#define vii_dotdot	vdi_ftarea.dotdot
-#define vii_fixextsize	vdi_ftarea.regular.fixextsize
-#define vii_matchino	vdi_ftarea.vxspec.matchino
-#define vii_fsetindex	vdi_ftarea.vxspec.fsetindex
-
-#define vii_immed	vdi_org.immed
-#define vii_ext4	vdi_org.ext4
-#define vii_typed	vdi_org.typed
+#define vii_immed	vii_org.immed
+#define vii_ext4	vii_org.ext4
+#define vii_typed	vii_org.typed
 
 #endif /* _VXFS_INODE_H_ */
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 6d576b9..09e93b3 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -74,9 +74,10 @@
  * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
  */
 static inline int
-vxfs_match(int len, const char * const name, struct vxfs_direct *de)
+vxfs_match(struct vxfs_sb_info *sbi, int len, const char *const name,
+		struct vxfs_direct *de)
 {
-	if (len != de->d_namelen)
+	if (len != fs16_to_cpu(sbi, de->d_namelen))
 		return 0;
 	if (!de->d_ino)
 		return 0;
@@ -84,9 +85,10 @@
 }
 
 static inline struct vxfs_direct *
-vxfs_next_entry(struct vxfs_direct *de)
+vxfs_next_entry(struct vxfs_sb_info *sbi, struct vxfs_direct *de)
 {
-	return ((struct vxfs_direct *)((char*)de + de->d_reclen));
+	return ((struct vxfs_direct *)
+		((char *)de + fs16_to_cpu(sbi, de->d_reclen)));
 }
 
 /**
@@ -106,6 +108,7 @@
 static struct vxfs_direct *
 vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
 {
+	struct vxfs_sb_info		*sbi = VXFS_SBI(ip->i_sb);
 	u_long				npages, page, nblocks, pblocks, block;
 	u_long				bsize = ip->i_sb->s_blocksize;
 	const char			*name = dp->d_name.name;
@@ -133,14 +136,16 @@
 			limit = baddr + bsize - VXFS_DIRLEN(1);
 			
 			dbp = (struct vxfs_dirblk *)baddr;
-			de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
+			de = (struct vxfs_direct *)
+				(baddr + VXFS_DIRBLKOV(sbi, dbp));
 
-			for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
+			for (; (caddr_t)de <= limit;
+					de = vxfs_next_entry(sbi, de)) {
 				if (!de->d_reclen)
 					break;
 				if (!de->d_ino)
 					continue;
-				if (vxfs_match(namelen, name, de)) {
+				if (vxfs_match(sbi, namelen, name, de)) {
 					*ppp = pp;
 					return (de);
 				}
@@ -173,7 +178,7 @@
 
 	de = vxfs_find_entry(dip, dp, &pp);
 	if (de) {
-		ino = de->d_ino;
+		ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
 		kunmap(pp);
 		put_page(pp);
 	}
@@ -232,10 +237,12 @@
 {
 	struct inode		*ip = file_inode(fp);
 	struct super_block	*sbp = ip->i_sb;
+	struct vxfs_sb_info	*sbi = VXFS_SBI(sbp);
 	u_long			bsize = sbp->s_blocksize;
 	u_long			page, npages, block, pblocks, nblocks, offset;
 	loff_t			pos;
 
+
 	if (ctx->pos == 0) {
 		if (!dir_emit_dot(fp, ctx))
 			return 0;
@@ -280,9 +287,10 @@
 			de = (struct vxfs_direct *)
 				(offset ?
 				 (kaddr + offset) :
-				 (baddr + VXFS_DIRBLKOV(dbp)));
+				 (baddr + VXFS_DIRBLKOV(sbi, dbp)));
 
-			for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
+			for (; (char *)de <= limit;
+					de = vxfs_next_entry(sbi, de)) {
 				if (!de->d_reclen)
 					break;
 				if (!de->d_ino)
@@ -290,8 +298,10 @@
 
 				offset = (char *)de - kaddr;
 				ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
-				if (!dir_emit(ctx, de->d_name, de->d_namelen,
-					de->d_ino, DT_UNKNOWN)) {
+				if (!dir_emit(ctx, de->d_name,
+						fs16_to_cpu(sbi, de->d_namelen),
+						fs32_to_cpu(sbi, de->d_ino),
+						DT_UNKNOWN)) {
 					vxfs_put_page(pp);
 					return 0;
 				}
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 049500847..813da66 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -43,14 +43,14 @@
 vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
 {
 	BUG_ON(infp->vsi_fshino);
-	infp->vsi_fshino = fshp->olt_fsino[0];
+	infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]);
 }
 
 static inline void
 vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
 {
 	BUG_ON(infp->vsi_iext);
-	infp->vsi_iext = ilistp->olt_iext[0]; 
+	infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]);
 }
 
 static inline u_long
@@ -81,13 +81,12 @@
 	struct vxfs_olt		*op;
 	char			*oaddr, *eaddr;
 
-
 	bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
 	if (!bp || !bp->b_data)
 		goto fail;
 
 	op = (struct vxfs_olt *)bp->b_data;
-	if (op->olt_magic != VXFS_OLT_MAGIC) {
+	if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) {
 		printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
 		goto fail;
 	}
@@ -102,14 +101,14 @@
 		goto fail;
 	}
 
-	oaddr = bp->b_data + op->olt_size;
+	oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
 	eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
 
 	while (oaddr < eaddr) {
 		struct vxfs_oltcommon	*ocp =
 			(struct vxfs_oltcommon *)oaddr;
 		
-		switch (ocp->olt_type) {
+		switch (fs32_to_cpu(infp, ocp->olt_type)) {
 		case VXFS_OLT_FSHEAD:
 			vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
 			break;
@@ -118,11 +117,11 @@
 			break;
 		}
 
-		oaddr += ocp->olt_size;
+		oaddr += fs32_to_cpu(infp, ocp->olt_size);
 	}
 
 	brelse(bp);
-	return 0;
+	return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
 
 fail:
 	brelse(bp);
diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h
index b7b3af5..0c0b0c9 100644
--- a/fs/freevxfs/vxfs_olt.h
+++ b/fs/freevxfs/vxfs_olt.h
@@ -63,83 +63,83 @@
  * the initial inode list, the fileset header or the device configuration.
  */
 struct vxfs_olt {
-	u_int32_t	olt_magic;	/* magic number			*/
-	u_int32_t	olt_size;	/* size of this entry		*/
-	u_int32_t	olt_checksum;	/* checksum of extent		*/
-	u_int32_t	__unused1;	/* ???				*/
-	u_int32_t	olt_mtime;	/* time of last mod. (sec)	*/
-	u_int32_t	olt_mutime;	/* time of last mod. (usec)	*/
-	u_int32_t	olt_totfree;	/* free space in OLT extent	*/
-	vx_daddr_t	olt_extents[2];	/* addr of this extent, replica	*/
-	u_int32_t	olt_esize;	/* size of this extent		*/
-	vx_daddr_t	olt_next[2];    /* addr of next extent, replica	*/
-	u_int32_t	olt_nsize;	/* size of next extent		*/
-	u_int32_t	__unused2;	/* align to 8 byte boundary	*/
+	__fs32		olt_magic;	/* magic number			*/
+	__fs32		olt_size;	/* size of this entry		*/
+	__fs32		olt_checksum;	/* checksum of extent		*/
+	__u32		__unused1;	/* ???				*/
+	__fs32		olt_mtime;	/* time of last mod. (sec)	*/
+	__fs32		olt_mutime;	/* time of last mod. (usec)	*/
+	__fs32		olt_totfree;	/* free space in OLT extent	*/
+	__fs32		olt_extents[2];	/* addr of this extent, replica	*/
+	__fs32		olt_esize;	/* size of this extent		*/
+	__fs32		olt_next[2];    /* addr of next extent, replica	*/
+	__fs32		olt_nsize;	/* size of next extent		*/
+	__u32		__unused2;	/* align to 8 byte boundary	*/
 };
 
 /*
  * VxFS common OLT entry (on disk).
  */
 struct vxfs_oltcommon {
-	u_int32_t	olt_type;	/* type of this record		*/
-	u_int32_t	olt_size;	/* size of this record		*/
+	__fs32		olt_type;	/* type of this record		*/
+	__fs32		olt_size;	/* size of this record		*/
 };
 
 /*
  * VxFS free OLT entry (on disk).
  */
 struct vxfs_oltfree {
-	u_int32_t	olt_type;	/* type of this record		*/
-	u_int32_t	olt_fsize;	/* size of this free record	*/
+	__fs32		olt_type;	/* type of this record		*/
+	__fs32		olt_fsize;	/* size of this free record	*/
 };
 
 /*
  * VxFS initial-inode list (on disk).
  */
 struct vxfs_oltilist {
-	u_int32_t	olt_type;	/* type of this record		*/
-	u_int32_t	olt_size;	/* size of this record		*/
-	vx_ino_t	olt_iext[2];	/* initial inode list, replica	*/
+	__fs32	olt_type;	/* type of this record		*/
+	__fs32	olt_size;	/* size of this record		*/
+	__fs32		olt_iext[2];	/* initial inode list, replica	*/
 };
 
 /*
  * Current Usage Table 
  */
 struct vxfs_oltcut {
-	u_int32_t	olt_type;	/* type of this record		*/
-	u_int32_t	olt_size;	/* size of this record		*/
-	vx_ino_t	olt_cutino;	/* inode of current usage table	*/
-	u_int32_t	__pad;		/* unused, 8 byte align		*/
+	__fs32		olt_type;	/* type of this record		*/
+	__fs32		olt_size;	/* size of this record		*/
+	__fs32		olt_cutino;	/* inode of current usage table	*/
+	__u8		__pad;		/* unused, 8 byte align		*/
 };
 
 /*
  * Inodes containing Superblock, Intent log and OLTs 
  */
 struct vxfs_oltsb {
-	u_int32_t	olt_type;	/* type of this record		*/
-	u_int32_t	olt_size;	/* size of this record		*/
-	vx_ino_t	olt_sbino;	/* inode of superblock file	*/
-	u_int32_t	__unused1;	/* ???				*/
-	vx_ino_t	olt_logino[2];	/* inode of log file,replica	*/
-	vx_ino_t	olt_oltino[2];	/* inode of OLT, replica	*/
+	__fs32		olt_type;	/* type of this record		*/
+	__fs32		olt_size;	/* size of this record		*/
+	__fs32		olt_sbino;	/* inode of superblock file	*/
+	__u32		__unused1;	/* ???				*/
+	__fs32		olt_logino[2];	/* inode of log file,replica	*/
+	__fs32		olt_oltino[2];	/* inode of OLT, replica	*/
 };
 
 /*
  * Inode containing device configuration + it's replica 
  */
 struct vxfs_oltdev {
-	u_int32_t	olt_type;	/* type of this record		*/
-	u_int32_t	olt_size;	/* size of this record		*/
-	vx_ino_t	olt_devino[2];	/* inode of device config files	*/
+	__fs32		olt_type;	/* type of this record		*/
+	__fs32		olt_size;	/* size of this record		*/
+	__fs32		olt_devino[2];	/* inode of device config files	*/
 };
 
 /*
  * Fileset header 
  */
 struct vxfs_oltfshead {
-	u_int32_t	olt_type;	/* type number			*/
-	u_int32_t	olt_size;	/* size of this record		*/
-	vx_ino_t	olt_fsino[2];   /* inodes of fileset header	*/
+	__fs32		olt_type;	/* type number			*/
+	__fs32		olt_size;	/* size of this record		*/
+	__fs32		olt_fsino[2];   /* inodes of fileset header	*/
 };
 
 #endif /* _VXFS_OLT_H_ */
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7ca8c75..6124091 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -109,14 +109,15 @@
 vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
 {
 	struct vxfs_sb_info		*infp = VXFS_SBI(dentry->d_sb);
+	struct vxfs_sb *raw_sb = infp->vsi_raw;
 
 	bufp->f_type = VXFS_SUPER_MAGIC;
 	bufp->f_bsize = dentry->d_sb->s_blocksize;
-	bufp->f_blocks = infp->vsi_raw->vs_dsize;
-	bufp->f_bfree = infp->vsi_raw->vs_free;
+	bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize);
+	bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free);
 	bufp->f_bavail = 0;
 	bufp->f_files = 0;
-	bufp->f_ffree = infp->vsi_raw->vs_ifree;
+	bufp->f_ffree = fs32_to_cpu(infp, raw_sb->vs_ifree);
 	bufp->f_namelen = VXFS_NAMELEN;
 
 	return 0;
@@ -129,6 +130,50 @@
 	return 0;
 }
 
+
+static int vxfs_try_sb_magic(struct super_block *sbp, int silent,
+		unsigned blk, __fs32 magic)
+{
+	struct buffer_head *bp;
+	struct vxfs_sb *rsbp;
+	struct vxfs_sb_info *infp = VXFS_SBI(sbp);
+	int rc = -ENOMEM;
+
+	bp = sb_bread(sbp, blk);
+	do {
+		if (!bp || !buffer_mapped(bp)) {
+			if (!silent) {
+				printk(KERN_WARNING
+					"vxfs: unable to read disk superblock at %u\n",
+					blk);
+			}
+			break;
+		}
+
+		rc = -EINVAL;
+		rsbp = (struct vxfs_sb *)bp->b_data;
+		if (rsbp->vs_magic != magic) {
+			if (!silent)
+				printk(KERN_NOTICE
+					"vxfs: WRONG superblock magic %08x at %u\n",
+					rsbp->vs_magic, blk);
+			break;
+		}
+
+		rc = 0;
+		infp->vsi_raw = rsbp;
+		infp->vsi_bp = bp;
+	} while (0);
+
+	if (rc) {
+		infp->vsi_raw = NULL;
+		infp->vsi_bp = NULL;
+		brelse(bp);
+	}
+
+	return rc;
+}
+
 /**
  * vxfs_read_super - read superblock into memory and initialize filesystem
  * @sbp:		VFS superblock (to fill)
@@ -149,10 +194,10 @@
 {
 	struct vxfs_sb_info	*infp;
 	struct vxfs_sb		*rsbp;
-	struct buffer_head	*bp = NULL;
 	u_long			bsize;
 	struct inode *root;
 	int ret = -EINVAL;
+	u32 j;
 
 	sbp->s_flags |= MS_RDONLY;
 
@@ -168,42 +213,42 @@
 		goto out;
 	}
 
-	bp = sb_bread(sbp, 1);
-	if (!bp || !buffer_mapped(bp)) {
-		if (!silent) {
-			printk(KERN_WARNING
-				"vxfs: unable to read disk superblock\n");
-		}
-		goto out;
-	}
+	sbp->s_fs_info = infp;
 
-	rsbp = (struct vxfs_sb *)bp->b_data;
-	if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
+	if (!vxfs_try_sb_magic(sbp, silent, 1,
+			(__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) {
+		/* Unixware, x86 */
+		infp->byte_order = VXFS_BO_LE;
+	} else if (!vxfs_try_sb_magic(sbp, silent, 8,
+			(__force __fs32)cpu_to_be32(VXFS_SUPER_MAGIC))) {
+		/* HP-UX, parisc */
+		infp->byte_order = VXFS_BO_BE;
+	} else {
 		if (!silent)
-			printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
+			printk(KERN_NOTICE "vxfs: can't find superblock.\n");
 		goto out;
 	}
 
-	if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
-		printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
-		       rsbp->vs_version);
+	rsbp = infp->vsi_raw;
+	j = fs32_to_cpu(infp, rsbp->vs_version);
+	if ((j < 2 || j > 4) && !silent) {
+		printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
 		goto out;
 	}
 
 #ifdef DIAGNOSTIC
-	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
-	printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
+	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
+	printk(KERN_DEBUG "vxfs: blocksize: %d\n",
+		fs32_to_cpu(infp, rsbp->vs_bsize));
 #endif
 
-	sbp->s_magic = rsbp->vs_magic;
-	sbp->s_fs_info = infp;
+	sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic);
 
-	infp->vsi_raw = rsbp;
-	infp->vsi_bp = bp;
-	infp->vsi_oltext = rsbp->vs_oltext[0];
-	infp->vsi_oltsize = rsbp->vs_oltsize;
+	infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]);
+	infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize);
 
-	if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
+	j = fs32_to_cpu(infp, rsbp->vs_bsize);
+	if (!sb_set_blocksize(sbp, j)) {
 		printk(KERN_WARNING "vxfs: unable to set final block size\n");
 		goto out;
 	}
@@ -237,7 +282,7 @@
 	vxfs_put_fake_inode(infp->vsi_ilist);
 	vxfs_put_fake_inode(infp->vsi_stilist);
 out:
-	brelse(bp);
+	brelse(infp->vsi_bp);
 	kfree(infp);
 	return ret;
 }