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_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: