linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* freevxfs
@ 2016-05-25 21:27 Krzysztof Błaszkowski
  2016-05-26 11:50 ` freevxfs Carlos Maiolino
  0 siblings, 1 reply; 8+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-25 21:27 UTC (permalink / raw)
  To: Christoph Hellwig, Carlos Maiolino; +Cc: linux-fsdevel

[-- Attachment #1: Type: text/plain, Size: 593 bytes --]

Hi,

Please find included patchset which addresses all major features we have
discussed (unless I forgot about something).

I verified correctness of operation with my regression tests and HP-UX's
vxfs image. No difference spotted. However I can't do this with SCO
image because I do not have such. I reckon that it is highly possible
that SCO image will work as usual because the only difference is data
endianess and offset of super block.

I included for reference these scripts just in case one is curious.
(chksum8-sorted.log comes from hp-ux's cksum)

Regards,
-- 
Krzysztof Blaszkowski

[-- Attachment #2: 0001-kconfig-note.patch --]
[-- Type: text/x-patch, Size: 1615 bytes --]

>From 3d3b4e1ed5df014ae191e0566ff86a17d7d9ac05 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 21:50:11 +0200
Subject: [PATCH 1/7] kconfig note


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/Kconfig |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig
index 8dc1cd5..a4c9075 100644
--- a/fs/freevxfs/Kconfig
+++ b/fs/freevxfs/Kconfig
@@ -5,12 +5,20 @@ config VXFS_FS
 	  FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
 	  file system format.  VERITAS VxFS(TM) is the standard file system
 	  of SCO UnixWare (and possibly others) and optionally available
-	  for Sunsoft Solaris, HP-UX and many other operating systems.
+	  for Sunsoft Solaris, HP-UX and many other operating systems. However
+	  these particular OS implementations of vxfs may differ in on-disk
+	  data endianess and/or superblock offset. The vxfs module has been 
+	  tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.)
 	  Currently only readonly access is supported.
 
 	  NOTE: the file system type as used by mount(1), mount(2) and
 	  fstab(5) is 'vxfs' as it describes the file system format, not
 	  the actual driver.
 
+	  There is a userspace utility for HP-UX logical volumes which makes 
+	  creating HP-UX logical volumes easy from HP-UX disk block device file 
+	  or regular file with image of the disk. See:
+	         https://sourceforge.net/projects/linux-vxfs/
+
 	  To compile this as a module, choose M here: the module will be
 	  called freevxfs.  If unsure, say N.
-- 
1.7.3.4


[-- Attachment #3: 0002-cpu-endian-vs-file-system-endian.patch --]
[-- Type: text/x-patch, Size: 17532 bytes --]

>From c617f6bceedc2f68c62e7432f12b59124bab34f7 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:12:05 +0200
Subject: [PATCH 2/7] cpu endian vs file system endian


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs.h        |   25 +++++++++++-
 fs/freevxfs/vxfs_bmap.c   |   24 ++++++-----
 fs/freevxfs/vxfs_fshead.c |   25 +++++++++++-
 fs/freevxfs/vxfs_inode.c  |   61 +++++++++++++++++++++++++++-
 fs/freevxfs/vxfs_inode.h  |    8 ++--
 fs/freevxfs/vxfs_lookup.c |   15 ++++++-
 fs/freevxfs/vxfs_olt.c    |   15 ++++---
 fs/freevxfs/vxfs_super.c  |   97 ++++++++++++++++++++++++++++++++-------------
 8 files changed, 215 insertions(+), 55 deletions(-)

diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index c8a9265..5dc8949 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -152,7 +152,7 @@ struct vxfs_sb {
 	/*
 	 * Actually much more...
 	 */
-};
+} __packed;
 
 
 /*
@@ -168,9 +168,32 @@ struct vxfs_sb_info {
 	ino_t			vsi_fshino;	/* fileset header inode */
 	daddr_t			vsi_oltext;	/* OLT extent */
 	daddr_t			vsi_oltsize;	/* OLT size */
+	int byte_order;
+	int silent;
+};
+
+enum {
+	BO_LE = 1,
+	BO_BE
 };
 
 
+static inline u32 fs32_to_cpu(int bo, u32 a)
+{
+	return (bo == BO_BE) ? be32_to_cpu(a) : le32_to_cpu(a);
+}
+
+static inline u16 fs16_to_cpu(int bo, u16 a)
+{
+	return (bo == BO_BE) ? be16_to_cpu(a) : le16_to_cpu(a);
+}
+
+static inline u64 fs64_to_cpu(int bo, u64 a)
+{
+	return (bo == BO_BE) ? be64_to_cpu(a) : le64_to_cpu(a);
+}
+
+
 /*
  * File modes.  File types above 0xf000 are vxfs internal only, they should
  * not be passed back to higher levels of the system.  vxfs file types must
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index f86fd3c..95afd98 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -92,7 +92,8 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
 			goto fail_buf;
 
 		indir = (u32 *)buf->b_data;
-		bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
+		bno = fs32_to_cpu(VXFS_SBI(sb)->byte_order,
+		    indir[(bn/indsize) % (indsize*bn)]) + (bn % indsize);
 
 		brelse(buf);
 		return bno;
@@ -130,6 +131,7 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 	struct buffer_head		*bp = NULL;
 	daddr_t				pblock = 0;
 	int				i;
+	int bo = VXFS_SBI(ip->i_sb)->byte_order;
 
 	for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
 		struct vxfs_typed	*typ;
@@ -142,24 +144,24 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 
 		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(bo, 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(bo, 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(bo, typ->vt_block),
+					fs32_to_cpu(bo, 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(bo, typ->vt_size))
 				break;
-			pblock = (typ->vt_block + block - off);
+			pblock = fs32_to_cpu(bo, typ->vt_block) + block - off;
 			goto out;
 		case VXFS_TYPED_INDIRECT_DEV4:
 		case VXFS_TYPED_DATA_DEV4: {
@@ -168,12 +170,14 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 
 			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);
+			       (unsigned long long) fs64_to_cpu(bo, typ4->vd4_block),
+			       (unsigned long long) fs64_to_cpu(bo, typ4->vd4_size),
+			       fs32_to_cpu(bo, typ4->vd4_dev));
 			goto fail;
 		}
 		default:
+			printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__, __LINE__,
+			    fs64_to_cpu(bo, typ->vt_hdr));
 			BUG();
 		}
 		brelse(bp);
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c9a6a94..6cbdde7 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -60,6 +60,29 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
 }
 #endif
 
+#define VXFS_FS32(field1, field2) fhp->field1 = fs32_to_cpu(bo, dbh->field2)
+static inline void dbh2fhp(struct vxfs_fsh *fhp, void *_dbh, int bo)
+{
+	struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
+
+	VXFS_FS32(fsh_version, fsh_version);
+	VXFS_FS32(fsh_fsindex, fsh_fsindex);
+	VXFS_FS32(fsh_time, fsh_time);
+	VXFS_FS32(fsh_utime, fsh_utime);
+	VXFS_FS32(fsh_extop, fsh_extop);
+	VXFS_FS32(fsh_ninodes, fsh_ninodes);
+	VXFS_FS32(fsh_nau, fsh_nau);
+	VXFS_FS32(fsh_old_ilesize, fsh_old_ilesize);
+	VXFS_FS32(fsh_dflags, fsh_dflags);
+	VXFS_FS32(fsh_quota, fsh_quota);
+	VXFS_FS32(fsh_maxinode, fsh_maxinode);
+	VXFS_FS32(fsh_iauino, fsh_iauino);
+	VXFS_FS32(fsh_ilistino[0], fsh_ilistino[0]);
+	VXFS_FS32(fsh_ilistino[1], fsh_ilistino[1]);
+	VXFS_FS32(fsh_lctino, fsh_lctino);
+}
+
+
 /**
  * vxfs_getfsh - read fileset header into memory
  * @ip:		the (fake) fileset header inode
@@ -83,7 +106,7 @@ vxfs_getfsh(struct inode *ip, int which)
 
 		if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
 			goto out;
-		memcpy(fhp, bp->b_data, sizeof(*fhp));
+		dbh2fhp(fhp, bp->b_data, VXFS_SBI(ip->i_sb)->byte_order);
 
 		put_bh(bp);
 		return (fhp);
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 363e3ae..53b8757 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -67,6 +67,63 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
 }
 #endif
 
+#define VXFS_FS32(field1, field2) vip->field1 = fs32_to_cpu(bo, dip->field2)
+#define VXFS_FS64(field1, field2) vip->field1 = fs64_to_cpu(bo, dip->field2)
+#define VXFS_FS16(field1, field2) vip->field1 = fs16_to_cpu(bo, dip->field2)
+
+static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip, int bo)
+{
+	int j;
+
+	VXFS_FS32(vdi_mode, vdi_mode);
+	VXFS_FS32(vdi_nlink, vdi_nlink);
+	VXFS_FS32(vdi_uid, vdi_uid);
+	VXFS_FS32(vdi_gid, vdi_gid);
+	VXFS_FS64(vdi_size, vdi_size);
+	VXFS_FS32(vdi_atime, vdi_atime);
+	VXFS_FS32(vdi_autime, vdi_autime);
+	VXFS_FS32(vdi_mtime, vdi_mtime);
+	VXFS_FS32(vdi_mutime, vdi_mutime);
+	VXFS_FS32(vdi_ctime, vdi_ctime);
+	VXFS_FS32(vdi_cutime, vdi_cutime);
+	vip->vdi_aflags = dip->vdi_aflags;
+	vip->vdi_orgtype = dip->vdi_orgtype;
+	VXFS_FS16(vdi_eopflags, vdi_eopflags);
+	VXFS_FS32(vdi_eopdata, vdi_eopdata);
+
+	VXFS_FS32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
+	VXFS_FS32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
+	VXFS_FS32(vdi_blocks, vdi_blocks);
+	VXFS_FS32(vdi_gen, vdi_gen);
+	VXFS_FS64(vdi_version, vdi_version);
+
+	switch (dip->vdi_orgtype) {
+	case VXFS_ORG_EXT4:
+		VXFS_FS32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
+		VXFS_FS32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
+		for (j = 0; j < VXFS_NIADDR; j++) {
+			VXFS_FS32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
+		}
+		for (j = 0; j < VXFS_NDADDR; j++) {
+			VXFS_FS32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
+			VXFS_FS32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
+		}
+		break;
+	case VXFS_ORG_IMMED:
+		memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
+		break;
+	case VXFS_ORG_TYPED:
+		for (j = 0; j < VXFS_NTYPED; j++) {
+			VXFS_FS64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
+			VXFS_FS32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
+			VXFS_FS32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
+		}
+		break;
+	};
+
+	VXFS_FS32(vdi_iattrino, vdi_iattrino);
+}
+
 
 /**
  * vxfs_blkiget - find inode based on extent #
@@ -101,7 +158,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
 		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(vip, dip, VXFS_SBI(sbp)->byte_order);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
@@ -143,7 +200,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
 		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(vip, dip, VXFS_SBI(ilistp->i_sb)->byte_order);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 240aeb1..9a2c376 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -77,13 +77,13 @@ struct vxfs_ext4 {
 		vx_daddr_t	extent;			/* Extent number */
 		int32_t		size;			/* Size of extent */
 	} ve4_direct[VXFS_NDADDR];
-};
+} __packed;
 
 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 */
-};
+} __packed;
 
 struct vxfs_typed_dev4 {
 	u_int64_t	vd4_hdr;	/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
@@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
 	u_int64_t	vd4_size;	/* Size in blocks */
 	int32_t		vd4_dev;	/* Device ID */
 	u_int32_t	__pad1;
-};
+} __packed;
 
 /*
  * The inode as contained on the physical device.
@@ -134,7 +134,7 @@ struct vxfs_dinode {
 		struct vxfs_typed	typed[VXFS_NTYPED];
 	} vdi_org;
 	u_int32_t	vdi_iattrino;
-};
+} __packed;
 
 #define vdi_rdev	vdi_ftarea.rdev
 #define vdi_dotdot	vdi_ftarea.dotdot
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 99c7f0a..cea158a 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -96,6 +96,15 @@ vxfs_next_entry(struct vxfs_direct *de)
 	return ((struct vxfs_direct *)((char*)de + de->d_reclen));
 }
 
+/*
+ * VXFS_dirblk_ovh is the overhead of a specific dirblock.
+ */
+static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
+{
+	return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
+}
+
+
 /**
  * vxfs_find_entry - find a mathing directory entry for a dentry
  * @ip:		directory inode
@@ -242,6 +251,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
 	u_long			bsize = sbp->s_blocksize;
 	u_long			page, npages, block, pblocks, nblocks, offset;
 	loff_t			pos;
+	int bo = VXFS_SBI(sbp)->byte_order;
+
 
 	if (ctx->pos == 0) {
 		if (!dir_emit_dot(fp, ctx))
@@ -297,8 +308,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
 
 				offset = (char *)de - kaddr;
 				ctx->pos = ((page << PAGE_CACHE_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(bo, de->d_namelen),
+					fs32_to_cpu(bo, 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 0495008..6b50188 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -43,14 +43,14 @@ static inline void
 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->byte_order, 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->byte_order, ilistp->olt_iext[0]);
 }
 
 static inline u_long
@@ -80,6 +80,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 	struct buffer_head	*bp;
 	struct vxfs_olt		*op;
 	char			*oaddr, *eaddr;
+	int bo = infp->byte_order;
 
 
 	bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
@@ -87,7 +88,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 		goto fail;
 
 	op = (struct vxfs_olt *)bp->b_data;
-	if (op->olt_magic != VXFS_OLT_MAGIC) {
+	if (fs32_to_cpu(bo, op->olt_magic) != VXFS_OLT_MAGIC) {
 		printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
 		goto fail;
 	}
@@ -102,14 +103,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 		goto fail;
 	}
 
-	oaddr = bp->b_data + op->olt_size;
+	oaddr = bp->b_data + fs32_to_cpu(bo, 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(bo, ocp->olt_type)) {
 		case VXFS_OLT_FSHEAD:
 			vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
 			break;
@@ -118,11 +119,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 			break;
 		}
 
-		oaddr += ocp->olt_size;
+		oaddr += fs32_to_cpu(bo, 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_super.c b/fs/freevxfs/vxfs_super.c
index 7ca8c75..6a19802 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -109,14 +109,15 @@ static int
 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->byte_order, raw_sb->vs_dsize);
+	bufp->f_bfree = fs32_to_cpu(infp->byte_order, 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->byte_order, raw_sb->vs_ifree);
 	bufp->f_namelen = VXFS_NAMELEN;
 
 	return 0;
@@ -129,6 +130,46 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
 	return 0;
 }
 
+
+static int vxfs_try_sb_magic(struct super_block *sbp, int blk, u32 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 (!infp->silent) {
+				printk(KERN_WARNING "vxfs: unable to read"
+				    " disk superblock at %d\n", blk);
+			}
+			break;
+		}
+
+		rc = -EINVAL;
+		rsbp = (struct vxfs_sb *)bp->b_data;
+		if (rsbp->vs_magic != magic) {
+			if (!infp->silent)
+				printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
+			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 +190,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 {
 	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;
 
@@ -162,48 +203,47 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 		return -ENOMEM;
 	}
 
+	infp->silent = silent;
 	bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
 	if (!bsize) {
 		printk(KERN_WARNING "vxfs: unable to set blocksize\n");
 		goto out;
 	}
 
-	bp = sb_bread(sbp, 1);
-	if (!bp || !buffer_mapped(bp)) {
-		if (!silent) {
-			printk(KERN_WARNING
-				"vxfs: unable to read disk superblock\n");
+	sbp->s_fs_info = infp;
+	do {
+		if (!vxfs_try_sb_magic(sbp, 1, cpu_to_le32(VXFS_SUPER_MAGIC))) {
+			infp->byte_order = BO_LE; /* SCO */
+			break;
+		}
+
+		if (!vxfs_try_sb_magic(sbp, 8, cpu_to_be32(VXFS_SUPER_MAGIC))) {
+			infp->byte_order = BO_BE; /* HP-UX pa-risc likely */
+			break;
 		}
-		goto out;
-	}
 
-	rsbp = (struct vxfs_sb *)bp->b_data;
-	if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
-		if (!silent)
-			printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
 		goto out;
-	}
+	} while (0);
 
-	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->byte_order, 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: supported VxFS version (%d)\n", j);
 	printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
 #endif
 
-	sbp->s_magic = rsbp->vs_magic;
-	sbp->s_fs_info = infp;
+	sbp->s_magic = fs32_to_cpu(infp->byte_order, 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->byte_order, rsbp->vs_oltext[0]);
+	infp->vsi_oltsize = fs32_to_cpu(infp->byte_order, rsbp->vs_oltsize);
 
-	if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
+	j = fs32_to_cpu(infp->byte_order, rsbp->vs_bsize);
+	if (!sb_set_blocksize(sbp, j)) {
 		printk(KERN_WARNING "vxfs: unable to set final block size\n");
 		goto out;
 	}
@@ -237,7 +277,8 @@ out_free_ilist:
 	vxfs_put_fake_inode(infp->vsi_ilist);
 	vxfs_put_fake_inode(infp->vsi_stilist);
 out:
-	brelse(bp);
+	if (infp->vsi_bp)
+		brelse(infp->vsi_bp);
 	kfree(infp);
 	return ret;
 }
-- 
1.7.3.4


[-- Attachment #4: 0003-missing-kfree-and-kfree-on-kmem_cache-obj.patch --]
[-- Type: text/x-patch, Size: 2605 bytes --]

>From b95e9b749b85be347c953ce33d2b3c5dde4e56d6 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:13:20 +0200
Subject: [PATCH 3/7] missing kfree and kfree on kmem_cache obj


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs_extern.h |    1 +
 fs/freevxfs/vxfs_fshead.c |    8 +++++---
 fs/freevxfs/vxfs_inode.c  |    5 +++++
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 881aa3d..0a3ff86 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -64,6 +64,7 @@ extern struct vxfs_inode_info *	vxfs_blkiget(struct super_block *, u_long, ino_t
 extern struct vxfs_inode_info *	vxfs_stiget(struct super_block *, ino_t);
 extern struct inode *		vxfs_iget(struct super_block *, ino_t);
 extern void			vxfs_evict_inode(struct inode *);
+extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
 
 /* vxfs_lookup.c */
 extern const struct inode_operations	vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index 6cbdde7..67ca2f9 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -183,7 +183,7 @@ vxfs_read_fshead(struct super_block *sbp)
 	infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
 	if (!infp->vsi_stilist) {
 		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
-		kfree(tip);
+		vxfs_inode_info_free(tip);
 		goto out_free_pfp;
 	}
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
@@ -198,7 +198,7 @@ vxfs_read_fshead(struct super_block *sbp)
 	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
 	if (!infp->vsi_ilist) {
 		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
-		kfree(tip);
+		vxfs_inode_info_free(tip);
 		goto out_iput_stilist;
 	}
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
@@ -206,6 +206,8 @@ vxfs_read_fshead(struct super_block *sbp)
 				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
 		goto out_iput_ilist;
 	}
+	kfree(pfp);
+	kfree(sfp);
 
 	return 0;
 
@@ -221,6 +223,6 @@ vxfs_read_fshead(struct super_block *sbp)
 	iput(infp->vsi_fship);
 	return -EINVAL;
  out_free_fship:
- 	kfree(vip);
+	vxfs_inode_info_free(vip);
 	return -EINVAL;
 }
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 53b8757..16d8d27 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -415,3 +415,8 @@ vxfs_evict_inode(struct inode *ip)
 	clear_inode(ip);
 	call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
+
+void vxfs_inode_info_free(struct vxfs_inode_info *vip)
+{
+	kmem_cache_free(vxfs_inode_cachep, vip);
+}
-- 
1.7.3.4


[-- Attachment #5: 0004-super_operations.destroy_inode.patch --]
[-- Type: text/x-patch, Size: 2645 bytes --]

>From e4979c6a29eb79d59d8bc2eca9acc0d2b416780f Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:15:20 +0200
Subject: [PATCH 4/7] super_operations.destroy_inode


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs_extern.h |    1 +
 fs/freevxfs/vxfs_inode.c  |   16 ++++++++++++----
 fs/freevxfs/vxfs_super.c  |    1 +
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 0a3ff86..4d8298b 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -65,6 +65,7 @@ extern struct vxfs_inode_info *	vxfs_stiget(struct super_block *, ino_t);
 extern struct inode *		vxfs_iget(struct super_block *, ino_t);
 extern void			vxfs_evict_inode(struct inode *);
 extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
+extern void vxfs_destroy_inode(struct inode *ip);
 
 /* vxfs_lookup.c */
 extern const struct inode_operations	vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 16d8d27..9b45ad7 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -397,7 +397,15 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
 static void vxfs_i_callback(struct rcu_head *head)
 {
 	struct inode *inode = container_of(head, struct inode, i_rcu);
-	kmem_cache_free(vxfs_inode_cachep, inode->i_private);
+	void *priv = inode->i_private;
+
+	inode->i_private = NULL;
+	kmem_cache_free(vxfs_inode_cachep, priv);
+}
+
+void vxfs_destroy_inode(struct inode *ip)
+{
+	call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
 
 /**
@@ -405,17 +413,17 @@ static void vxfs_i_callback(struct rcu_head *head)
  * @ip:		inode to discard.
  *
  * Description:
- *  vxfs_evict_inode() is called on the final iput and frees the private
- *  inode area.
+ *  vxfs_evict_inode() is called on the final iput
  */
 void
 vxfs_evict_inode(struct inode *ip)
 {
 	truncate_inode_pages_final(&ip->i_data);
+	invalidate_inode_buffers(ip);
 	clear_inode(ip);
-	call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
 
+
 void vxfs_inode_info_free(struct vxfs_inode_info *vip)
 {
 	kmem_cache_free(vxfs_inode_cachep, vip);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 6a19802..11a535a 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -59,6 +59,7 @@ static int		vxfs_statfs(struct dentry *, struct kstatfs *);
 static int		vxfs_remount(struct super_block *, int *, char *);
 
 static const struct super_operations vxfs_super_ops = {
+	.destroy_inode = vxfs_destroy_inode,
 	.evict_inode =		vxfs_evict_inode,
 	.put_super =		vxfs_put_super,
 	.statfs =		vxfs_statfs,
-- 
1.7.3.4


[-- Attachment #6: 0005-refactoring-of-vxfs_readir-and-find_entry.patch --]
[-- Type: text/x-patch, Size: 8246 bytes --]

>From 4a6ae0e351b6046367bbd2939547f292ed2b6e47 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:28:37 +0200
Subject: [PATCH 5/7] refactoring of vxfs_readir() and find_entry()


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs_lookup.c |  267 +++++++++++++++++++++------------------------
 1 files changed, 124 insertions(+), 143 deletions(-)

diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index cea158a..8eacb27 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -61,48 +61,6 @@ const struct file_operations vxfs_dir_operations = {
 	.iterate =		vxfs_readdir,
 };
 
- 
-static inline u_long
-dir_pages(struct inode *inode)
-{
-	return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-}
- 
-static inline u_long
-dir_blocks(struct inode *ip)
-{
-	u_long			bsize = ip->i_sb->s_blocksize;
-	return (ip->i_size + bsize - 1) & ~(bsize - 1);
-}
-
-/*
- * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
- *
- * 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)
-{
-	if (len != de->d_namelen)
-		return 0;
-	if (!de->d_ino)
-		return 0;
-	return !memcmp(name, de->d_name, len);
-}
-
-static inline struct vxfs_direct *
-vxfs_next_entry(struct vxfs_direct *de)
-{
-	return ((struct vxfs_direct *)((char*)de + de->d_reclen));
-}
-
-/*
- * VXFS_dirblk_ovh is the overhead of a specific dirblock.
- */
-static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
-{
-	return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
-}
 
 
 /**
@@ -122,50 +80,65 @@ static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
 static struct vxfs_direct *
 vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
 {
-	u_long				npages, page, nblocks, pblocks, block;
-	u_long				bsize = ip->i_sb->s_blocksize;
-	const char			*name = dp->d_name.name;
-	int				namelen = dp->d_name.len;
-
-	npages = dir_pages(ip);
-	nblocks = dir_blocks(ip);
-	pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
-	
-	for (page = 0; page < npages; page++) {
-		caddr_t			kaddr;
-		struct page		*pp;
-
-		pp = vxfs_get_page(ip->i_mapping, page);
-		if (IS_ERR(pp))
-			continue;
-		kaddr = (caddr_t)page_address(pp);
-
-		for (block = 0; block <= nblocks && block <= pblocks; block++) {
-			caddr_t			baddr, limit;
-			struct vxfs_dirblk	*dbp;
-			struct vxfs_direct	*de;
-
-			baddr = kaddr + (block * bsize);
-			limit = baddr + bsize - VXFS_DIRLEN(1);
-			
-			dbp = (struct vxfs_dirblk *)baddr;
-			de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
-
-			for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
-				if (!de->d_reclen)
-					break;
-				if (!de->d_ino)
-					continue;
-				if (vxfs_match(namelen, name, de)) {
-					*ppp = pp;
-					return (de);
-				}
+	u_long bsize = ip->i_sb->s_blocksize;
+	const char *name = dp->d_name.name;
+	int namelen = dp->d_name.len;
+	loff_t limit = VXFS_DIRROUND(ip->i_size);
+	struct vxfs_direct *de_exit = NULL;
+	loff_t pos = 0;
+	int bo = VXFS_SBI(ip->i_sb)->byte_order;
+
+	while (pos < limit) {
+		struct page *pp;
+		char *kaddr;
+		int pg_ofs = pos & ~PAGE_CACHE_MASK;
+
+		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+		if (IS_ERR(pp)) {
+			return NULL;
+		}
+		kaddr = (char *)page_address(pp);
+
+		while (pg_ofs < PAGE_SIZE && pos < limit) {
+			struct vxfs_direct *de;
+
+			if ((pos & (bsize - 1)) < 4) {
+				struct vxfs_dirblk *dbp =
+				    (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
+				int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
+
+				pos += overhead;
+				pg_ofs += overhead;
+			}
+			de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+			if (!de->d_reclen) {
+				pos += bsize - 1;
+				pos &= ~(bsize - 1);
+				break;
+			}
+
+			pg_ofs += fs16_to_cpu(bo, de->d_reclen);
+			pos += fs16_to_cpu(bo, de->d_reclen);
+			if (!de->d_ino) {
+				continue;
+			}
+
+			if (namelen != fs16_to_cpu(bo, de->d_namelen))
+				continue;
+			if (!memcmp(name, de->d_name, namelen)) {
+				*ppp = pp;
+				de_exit = de;
+				break;
 			}
 		}
-		vxfs_put_page(pp);
+		if (!de_exit)
+			vxfs_put_page(pp);
+		else
+			break;
 	}
 
-	return NULL;
+	return de_exit;
 }
 
 /**
@@ -185,15 +158,17 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
 {
 	struct vxfs_direct		*de;
 	struct page			*pp;
-	ino_t				ino = 0;
+	ino_t ino = 0;
 
 	de = vxfs_find_entry(dip, dp, &pp);
 	if (de) {
-		ino = de->d_ino;
+		int bo = VXFS_SBI(dip->i_sb)->byte_order;
+
+		ino = fs32_to_cpu(bo, de->d_ino);
 		kunmap(pp);
 		page_cache_release(pp);
 	}
-	
+
 	return (ino);
 }
 
@@ -225,8 +200,8 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
 		ip = vxfs_iget(dip->i_sb, ino);
 		if (IS_ERR(ip))
 			return ERR_CAST(ip);
+		d_add(dp, ip);
 	}
-	d_add(dp, ip);
 	return NULL;
 }
 
@@ -249,76 +224,82 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
 	struct inode		*ip = file_inode(fp);
 	struct super_block	*sbp = ip->i_sb;
 	u_long			bsize = sbp->s_blocksize;
-	u_long			page, npages, block, pblocks, nblocks, offset;
-	loff_t			pos;
+	loff_t			pos, limit;
 	int bo = VXFS_SBI(sbp)->byte_order;
 
-
 	if (ctx->pos == 0) {
 		if (!dir_emit_dot(fp, ctx))
-			return 0;
-		ctx->pos = 1;
+			goto out;
+		ctx->pos++;
 	}
 	if (ctx->pos == 1) {
 		if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
-			return 0;
-		ctx->pos = 2;
+			goto out;
+		ctx->pos++;
+	}
+
+	limit = VXFS_DIRROUND(ip->i_size);
+	if (ctx->pos > limit) {
+#if 0
+		ctx->pos = 0;
+#endif
+		goto out;
 	}
-	pos = ctx->pos - 2;
-	
-	if (pos > VXFS_DIRROUND(ip->i_size))
-		return 0;
-
-	npages = dir_pages(ip);
-	nblocks = dir_blocks(ip);
-	pblocks = VXFS_BLOCK_PER_PAGE(sbp);
-
-	page = pos >> PAGE_CACHE_SHIFT;
-	offset = pos & ~PAGE_CACHE_MASK;
-	block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
-
-	for (; page < npages; page++, block = 0) {
-		char			*kaddr;
-		struct page		*pp;
-
-		pp = vxfs_get_page(ip->i_mapping, page);
-		if (IS_ERR(pp))
-			continue;
+
+	pos = ctx->pos & ~3L;
+
+	while (pos < limit) {
+		struct page *pp;
+		char *kaddr;
+		int pg_ofs = pos & ~PAGE_CACHE_MASK;
+		int rc = 0;
+
+		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+		if (IS_ERR(pp)) {
+			return -ENOMEM;
+		}
 		kaddr = (char *)page_address(pp);
 
-		for (; block <= nblocks && block <= pblocks; block++) {
-			char			*baddr, *limit;
-			struct vxfs_dirblk	*dbp;
-			struct vxfs_direct	*de;
-
-			baddr = kaddr + (block * bsize);
-			limit = baddr + bsize - VXFS_DIRLEN(1);
-	
-			dbp = (struct vxfs_dirblk *)baddr;
-			de = (struct vxfs_direct *)
-				(offset ?
-				 (kaddr + offset) :
-				 (baddr + VXFS_DIRBLKOV(dbp)));
-
-			for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
-				if (!de->d_reclen)
-					break;
-				if (!de->d_ino)
-					continue;
-
-				offset = (char *)de - kaddr;
-				ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
-				if (!dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
-					fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN)) {
-					vxfs_put_page(pp);
-					return 0;
-				}
+		while (pg_ofs < PAGE_SIZE && pos < limit) {
+			struct vxfs_direct *de;
+
+			if ((pos & (bsize - 1)) < 4) {
+				struct vxfs_dirblk *dbp =
+				    (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
+				int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
+
+				pos += overhead;
+				pg_ofs += overhead;
+			}
+			de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+			if (!de->d_reclen) {
+				pos += bsize - 1;
+				pos &= ~(bsize - 1);
+				break;
+			}
+
+			pg_ofs += fs16_to_cpu(bo, de->d_reclen);
+			pos += fs16_to_cpu(bo, de->d_reclen);
+			if (!de->d_ino) {
+				continue;
+			}
+
+			rc = dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
+				fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN);
+			if (!rc) {
+				/* the dir entry was not submitted, so fix pos. */
+				pos -= fs16_to_cpu(bo, de->d_reclen);
+				break;
 			}
-			offset = 0;
 		}
 		vxfs_put_page(pp);
-		offset = 0;
+		if (!rc)
+			break;
 	}
-	ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
+
+	ctx->pos = pos | 2;
+
+out:
 	return 0;
 }
-- 
1.7.3.4


[-- Attachment #7: 0006-static-cachep.patch --]
[-- Type: text/x-patch, Size: 3331 bytes --]

>From e7f68291aada1535016c767a4f5a5fcfb19a1de6 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:41:22 +0200
Subject: [PATCH 6/7] static cachep


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs_extern.h |    4 +++-
 fs/freevxfs/vxfs_inode.c  |   24 +++++++++++++++++++++++-
 fs/freevxfs/vxfs_super.c  |   26 ++++++++++----------------
 3 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 4d8298b..cc43fd0 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -55,7 +55,6 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
 
 /* vxfs_inode.c */
 extern const struct address_space_operations vxfs_immed_aops;
-extern struct kmem_cache	*vxfs_inode_cachep;
 extern void			vxfs_dumpi(struct vxfs_inode_info *, ino_t);
 extern struct inode *		vxfs_get_fake_inode(struct super_block *,
 					struct vxfs_inode_info *);
@@ -66,6 +65,9 @@ extern struct inode *		vxfs_iget(struct super_block *, ino_t);
 extern void			vxfs_evict_inode(struct inode *);
 extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
 extern void vxfs_destroy_inode(struct inode *ip);
+extern int vxfs_ii_cache_init(void);
+extern void vxfs_ii_cache_destroy(void);
+
 
 /* vxfs_lookup.c */
 extern const struct inode_operations	vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 9b45ad7..73ac417 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -41,7 +41,7 @@
 #include "vxfs_extern.h"
 
 
-struct kmem_cache		*vxfs_inode_cachep;
+static struct kmem_cache *vxfs_inode_cachep;
 
 
 #ifdef DIAGNOSTIC
@@ -428,3 +428,25 @@ void vxfs_inode_info_free(struct vxfs_inode_info *vip)
 {
 	kmem_cache_free(vxfs_inode_cachep, vip);
 }
+
+
+int vxfs_ii_cache_init(void)
+{
+	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
+		sizeof(struct vxfs_inode_info), 0,
+		SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
+
+	return vxfs_inode_cachep ? 0 : -ENOMEM;
+}
+
+
+void vxfs_ii_cache_destroy(void)
+{
+	/*
+	 * Make sure all delayed rcu free inodes are flushed before we
+	 * destroy cache.
+	 */
+	rcu_barrier();
+	kmem_cache_destroy(vxfs_inode_cachep);
+}
+
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 11a535a..7579500 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -306,29 +306,23 @@ MODULE_ALIAS("vxfs");
 static int __init
 vxfs_init(void)
 {
-	int rv;
+	int rc = vxfs_ii_cache_init();
 
-	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
-			sizeof(struct vxfs_inode_info), 0,
-			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
-	if (!vxfs_inode_cachep)
-		return -ENOMEM;
-	rv = register_filesystem(&vxfs_fs_type);
-	if (rv < 0)
-		kmem_cache_destroy(vxfs_inode_cachep);
-	return rv;
+	if (!rc) {
+		rc = register_filesystem(&vxfs_fs_type);
+		if (rc < 0)
+			vxfs_ii_cache_destroy();
+	}
+	printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __func__, __DATE__, __TIME__, rc);
+
+	return rc;
 }
 
 static void __exit
 vxfs_cleanup(void)
 {
 	unregister_filesystem(&vxfs_fs_type);
-	/*
-	 * Make sure all delayed rcu free inodes are flushed before we
-	 * destroy cache.
-	 */
-	rcu_barrier();
-	kmem_cache_destroy(vxfs_inode_cachep);
+	vxfs_ii_cache_destroy();
 }
 
 module_init(vxfs_init);
-- 
1.7.3.4


[-- Attachment #8: 0007-the-credits.patch --]
[-- Type: text/x-patch, Size: 3314 bytes --]

>From 2c0008e9f2f4e62bb3e10eecad54e2a0140e0c4c Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:58:08 +0200
Subject: [PATCH 7/7] the credits


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs.h        |    3 +++
 fs/freevxfs/vxfs_fshead.c |    4 ++++
 fs/freevxfs/vxfs_inode.c  |    4 ++++
 fs/freevxfs/vxfs_lookup.c |    4 ++++
 fs/freevxfs/vxfs_super.c  |    6 +++++-
 5 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 5dc8949..35f56b7 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -2,6 +2,9 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ * (c) 2016 Krzysztof Blaszkowski
+ *       Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index 67ca2f9..44b87d0 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -2,6 +2,10 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ *       Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 73ac417..4c8a625 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -2,6 +2,10 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ *       Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 8eacb27..173aeea 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -2,6 +2,10 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ *       Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7579500..bd121aa 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -2,6 +2,10 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ *       Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -48,7 +52,7 @@
 #include "vxfs_inode.h"
 
 
-MODULE_AUTHOR("Christoph Hellwig");
+MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
 MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
-- 
1.7.3.4


[-- Attachment #9: Check.sh --]
[-- Type: application/x-shellscript, Size: 180 bytes --]

[-- Attachment #10: cksum8-sorted.log --]
[-- Type: text/x-log, Size: 5629 bytes --]

3531594148 32829 /usr/sprockets/bin/bw_map
3973234498 518896 /usr/sprockets/bin/cifslist
3973234498 518896 /usr/sprockets/bin/cifslogout
4171014129 518904 /usr/sprockets/bin/cifsmount
4171014129 518904 /usr/sprockets/bin/cifsumount
256627809 1171456 /usr/sprockets/bin/convert
4193697053 242843 /usr/sprockets/bin/createLicensingFiles
2780783712 51 /usr/sprockets/bin/createSprocFile
3285775584 825 /usr/sprockets/bin/dcexec
4073641898 94 /usr/sprockets/bin/defaultResources
4039074287 6610 /usr/sprockets/bin/disableNIS
313350104 20480 /usr/sprockets/bin/dos2ux
1872597524 65536 /usr/sprockets/bin/doschmod
1872597524 65536 /usr/sprockets/bin/doscp
1872597524 65536 /usr/sprockets/bin/dosdf
1872597524 65536 /usr/sprockets/bin/doslib
1872597524 65536 /usr/sprockets/bin/dosll
1872597524 65536 /usr/sprockets/bin/dosls
1872597524 65536 /usr/sprockets/bin/dosmkdir
1872597524 65536 /usr/sprockets/bin/dosrm
1872597524 65536 /usr/sprockets/bin/dosrmdir
1968087462 7112 /usr/sprockets/bin/enableNIS
3282246790 360 /usr/sprockets/bin/endexec
2151751185 553 /usr/sprockets/bin/endsession
3927613487 1115 /usr/sprockets/bin/env_var_sub
3738550324 157 /usr/sprockets/bin/format_dos
3888232633 172649 /usr/sprockets/bin/fppv
2279585942 466 /usr/sprockets/bin/getHostname
2946778792 5648 /usr/sprockets/bin/getSharedConnections
3306388627 20480 /usr/sprockets/bin/ibmsync
3041502972 28781 /usr/sprockets/bin/ipconfig700
3113659230 391815 /usr/sprockets/bin/kpp
908094753 24630 /usr/sprockets/bin/kxst
1329462070 36864 /usr/sprockets/bin/lanload
1015322628 36947 /usr/sprockets/bin/listener
486757159 339968 /usr/sprockets/bin/lmgrd
2620320940 339968 /usr/sprockets/bin/lmutil
951644065 243039 /usr/sprockets/bin/mattrib
951644065 243039 /usr/sprockets/bin/mbadblocks
951644065 243039 /usr/sprockets/bin/mcd
3650177936 951 /usr/sprockets/bin/mcheck
514586869 56 /usr/sprockets/bin/mcomp
951644065 243039 /usr/sprockets/bin/mcopy
951644065 243039 /usr/sprockets/bin/mdel
951644065 243039 /usr/sprockets/bin/mdeltree
951644065 243039 /usr/sprockets/bin/mdir
951644065 243039 /usr/sprockets/bin/mformat
951644065 243039 /usr/sprockets/bin/minfo
951644065 243039 /usr/sprockets/bin/mlabel
951644065 243039 /usr/sprockets/bin/mmd
951644065 243039 /usr/sprockets/bin/mmount
951644065 243039 /usr/sprockets/bin/mmove
951644065 243039 /usr/sprockets/bin/mpartition
662030829 1478557 /usr/sprockets/bin/mpv
951644065 243039 /usr/sprockets/bin/mrd
951644065 243039 /usr/sprockets/bin/mread
951644065 243039 /usr/sprockets/bin/mren
3443865238 32829 /usr/sprockets/bin/msgintcpt
951644065 243039 /usr/sprockets/bin/mtools
951644065 243039 /usr/sprockets/bin/mtoolstest
951644065 243039 /usr/sprockets/bin/mtype
951644065 243039 /usr/sprockets/bin/mwrite
1915353244 82 /usr/sprockets/bin/mxtar
951644065 243039 /usr/sprockets/bin/mzip
2033389047 379158 /usr/sprockets/bin/nmbd
1043940798 32843 /usr/sprockets/bin/nsbuild
421327339 32843 /usr/sprockets/bin/nsdump
2156955828 32843 /usr/sprockets/bin/nsquery
1030470949 28737 /usr/sprockets/bin/pciinfo
889541250 61560 /usr/sprockets/bin/pcipeek
1431205578 28737 /usr/sprockets/bin/pciprog
3351126604 126976 /usr/sprockets/bin/pkunzip
3351126604 126976 /usr/sprockets/bin/pkzip
2166142790 53390 /usr/sprockets/bin/probeload
694305221 41144 /usr/sprockets/bin/progflash
1141035887 445257 /usr/sprockets/bin/pv
974426301 3882 /usr/sprockets/bin/runnetscape
1879287959 1801 /usr/sprockets/bin/running
2273866242 74107 /usr/sprockets/bin/runroot
2616587298 79 /usr/sprockets/bin/runTouch
4222109660 875 /usr/sprockets/bin/samba
1912440105 24633 /usr/sprockets/bin/sbscrsvr
2558012300 3904 /usr/sprockets/bin/screensaverControl
4256537430 1780 /usr/sprockets/bin/sd-set_parms
1151924416 688 /usr/sprockets/bin/sendSignal
2744646624 32829 /usr/sprockets/bin/sessionDisallow
1227674200 1346161 /usr/sprockets/bin/sessionMgr
3332668870 98791 /usr/sprockets/bin/sessionWrapper
1477797090 82487 /usr/sprockets/bin/setlight
3759253613 1122 /usr/sprockets/bin/sharity
3313588847 3448000 /usr/sprockets/bin/sharityd
1569390236 24630 /usr/sprockets/bin/shmLock
3791448153 317300 /usr/sprockets/bin/smbclient
1018298877 506532 /usr/sprockets/bin/smbd
4009501079 45140 /usr/sprockets/bin/smtpclient
991996913 144424 /usr/sprockets/bin/starhw
3124681867 4311 /usr/sprockets/bin/startVNC
1468091312 919 /usr/sprockets/bin/startVNCviewer
304853428 1994350 /usr/sprockets/bin/sw_admin
304853428 1994350 /usr/sprockets/bin/sw_autoinstall
1455142555 123406 /usr/sprockets/bin/sw_copyfdset
2157175922 111102 /usr/sprockets/bin/sw_depot2bin
304853428 1994350 /usr/sprockets/bin/sw_install
304853428 1994350 /usr/sprockets/bin/sw_list
1842505403 7100 /usr/sprockets/bin/sw_makefdset
304853428 1994350 /usr/sprockets/bin/sw_remove
1743298644 2342 /usr/sprockets/bin/sw_rmprevious
1582083858 20548 /usr/sprockets/bin/sw_vendorfdset
178332129 1794 /usr/sprockets/bin/sysInfo
3657811479 1574 /usr/sprockets/bin/tgz
4018370132 36951 /usr/sprockets/bin/tp_license
1649141155 11843 /usr/sprockets/bin/updsharitycfg
2980018004 20480 /usr/sprockets/bin/ux2dos
3745508150 1318 /usr/sprockets/bin/uz
1348652714 32864 /usr/sprockets/bin/vncpasswd
4059637159 12757 /usr/sprockets/bin/vncserver
4128771573 366263 /usr/sprockets/bin/vncviewer
285011189 1526819 /usr/sprockets/bin/vp
589630079 387 /usr/sprockets/bin/vpexit
528762950 1132 /usr/sprockets/bin/xcopy
1793380080 521816 /usr/sprockets/bin/xscreensaver
24739470 145832 /usr/sprockets/bin/xscreensaver-command
4079099643 2167483 /usr/sprockets/bin/Xvnc
49651643 41091 /usr/sprockets/bin/yakdebug
2578809639 127914 /usr/sprockets/bin/yakhw
306877946 189649 /usr/sprockets/bin/yakserver

[-- Attachment #11: Test3d.sh --]
[-- Type: application/x-shellscript, Size: 923 bytes --]

^ permalink raw reply related	[flat|nested] 8+ messages in thread
* freevxfs
@ 2016-05-22 15:13 Krzysztof Błaszkowski
  2016-05-23  8:23 ` freevxfs Carlos Maiolino
  2016-05-23  8:36 ` freevxfs Christoph Hellwig
  0 siblings, 2 replies; 8+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-22 15:13 UTC (permalink / raw)
  To: linux-fsdevel, hch

[-- Attachment #1: Type: text/plain, Size: 577 bytes --]

Hello All,

I recently gave a try to vxfs (veritas fs) which is common to HP-UX and
it turned out that the module has been broken for very long time.

I fixed several issues with current freevxfs and also designed a
userspace tool which helps creating dm block devices from e.g. regular
file with raw image of hp-ux disk.
https://sourceforge.net/projects/linux-vxfs/


I send the patch because I believe that some people would appreciate
support for this vintage file system (e.g. me) and also it will be nice
to see my name in the kernel.

Regards,

-- 
Krzysztof Blaszkowski

[-- Attachment #2: vxfs-fixes-and-improvements.diff --]
[-- Type: text/x-patch, Size: 43984 bytes --]

diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index c8a9265..9890a84 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -2,6 +2,39 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * (c) 2016 Krzysztof Blaszkowski.
+ *       Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ *   - code not aware of cpu endianess and ondisk data is BE.
+ *   - misaligned structures read from block device
+ *   - wrong SB block number. default offset is 8kB
+ *   - kmem_cache_alloc() objectes released with kfree()
+ *   - inode.i_private released in evict_inode() callback.
+ *   - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// *  cksum mnt/usr/share/man/man3.Z/* 
+// *  cksum mnt/usr/share/doc/10.20RelNotes 
+// *  cksum mnt/usr/local/doom/*
+// *  cksum mnt/usr/sprockets/tools/instrument/16700/*
+// *  cksum mnt/usr/share/doc/*
+// *  cksum mnt/usr/sprockets/lib/*
+// *  cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ *  3457951056 4196020 /usr/local/doom/doom1.wad
+ *  2527157998 35344 /usr/local/doom/doomlaunch
+ *  2974998129 413696 /usr/local/doom/hpdoom
+ *
+ * The hpux_mdsetup tool project which is aimed at making possible
+ * accessing HP-UX logical volumes by device mapper is here:
+ *       https://sourceforge.net/projects/linux-vxfs/
+ *
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -38,6 +71,10 @@
  */
 #include <linux/types.h>
 
+//#define DIAGNOSTIC
+#undef DIAGNOSTIC
+#undef DIAGNOSTIC_V2
+#undef DIAGNOSTIC_V3
 
 /*
  * Data types for use with the VxFS ondisk format.
@@ -152,7 +189,7 @@ struct vxfs_sb {
 	/*
 	 * Actually much more...
 	 */
-};
+} __attribute__((packed));
 
 
 /*
@@ -260,4 +297,35 @@ enum {
 #define VXFS_SBI(sbp) \
 	((struct vxfs_sb_info *)(sbp)->s_fs_info)
 
+
+#ifdef DIAGNOSTIC
+#define F_ENTER(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#define F_EXIT(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+
+#ifdef DIAGNOSTIC_V2
+#define F_ENTER_V2(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#define F_EXIT_V2(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#else
+#define F_ENTER_V2(a, b...) 
+#define F_EXIT_V2(a, b...) 
+#endif
+
+#ifdef DIAGNOSTIC_V3
+#define F_ENTER_V3(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#define F_EXIT_V3(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#else
+#define F_ENTER_V3(a, b...) 
+#define F_EXIT_V3(a, b...) 
+#endif
+
+#else // DIAGNOSTIC
+#define F_ENTER(a, b...) 
+#define F_EXIT(a, b...) 
+#define F_ENTER_V2(a, b...) 
+#define F_EXIT_V2(a, b...) 
+#define F_ENTER_V3(a, b...) 
+#define F_EXIT_V3(a, b...) 
+#endif
+
+
 #endif /* _VXFS_SUPER_H_ */
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index f86fd3c..58e6a17 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -2,6 +2,10 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * 2016 Krzysztof Blaszkowski.
+ *       Many bug fixes, improvements & tests
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -39,17 +43,6 @@
 #include "vxfs_extern.h"
 
 
-#ifdef DIAGNOSTIC
-static void
-vxfs_typdump(struct vxfs_typed *typ)
-{
-	printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
-	printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
-	printk("block=%x ", typ->vt_block);
-	printk("size=%x\n", typ->vt_size);
-}
-#endif
-
 /**
  * vxfs_bmap_ext4 - do bmap for ext4 extents
  * @ip:		pointer to the inode we do bmap for
@@ -71,18 +64,23 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
 	unsigned long bsize = sb->s_blocksize;
 	u32 indsize = vip->vii_ext4.ve4_indsize;
 	int i;
+	daddr_t rc = 0;
+
+	F_ENTER_V2();
 
 	if (indsize > sb->s_blocksize)
 		goto fail_size;
 
 	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);
+		struct direct *d = vip->vii_ext4.ve4_direct + i; // cpu endian
+		if (bn >= 0 && bn < d->size) {
+			rc = bn + d->extent;
+			break;
+		}
 		bn -= d->size;
 	}
 
-	if ((bn / (indsize * indsize * bsize / 4)) == 0) {
+	if (!rc && ((bn / (indsize * indsize * bsize / 4)) == 0)) {
 		struct buffer_head *buf;
 		daddr_t	bno;
 		u32 *indir;
@@ -92,18 +90,21 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
 			goto fail_buf;
 
 		indir = (u32 *)buf->b_data;
-		bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
+		bno = be32_to_cpu(indir[(bn/indsize) % (indsize*bn)]) + (bn%indsize);
 
 		brelse(buf);
-		return bno;
-	} else
-		printk(KERN_WARNING "no matching indir?");
+		rc = bno;
+	}
+	if (!rc)
+		printk(KERN_WARNING "%s:%d no matching indir?\n", __FUNCTION__, __LINE__);
 
-	return 0;
+	F_EXIT_V2("pblk %d", rc);
+	return rc;
 
 fail_size:
 	printk("vxfs: indirect extent too big!\n");
 fail_buf:
+	F_EXIT();
 	return 0;
 }
 
@@ -129,51 +130,53 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 {
 	struct buffer_head		*bp = NULL;
 	daddr_t				pblock = 0;
-	int				i;
+	int i;
 
+	F_ENTER_V2();
 	for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
 		struct vxfs_typed	*typ;
-		int64_t			off;
+		int64_t off;
 
 		bp = sb_bread(ip->i_sb,
 				indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
 		if (!bp || !buffer_mapped(bp))
-			return 0;
+			break;
 
 		typ = ((struct vxfs_typed *)bp->b_data) +
 			(i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
-		off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+		off = be64_to_cpu(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)(be64_to_cpu(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, be32_to_cpu(typ->vt_block),
+					be32_to_cpu(typ->vt_size), block - off);
 			if (pblock == -2)
 				break;
 			goto out;
 		case VXFS_TYPED_DATA:
-			if ((block - off) >= typ->vt_size)
+			if ((block - off) >= be32_to_cpu(typ->vt_size))
 				break;
-			pblock = (typ->vt_block + block - off);
+			pblock = be32_to_cpu(typ->vt_block) + block - off;
 			goto out;
 		case VXFS_TYPED_INDIRECT_DEV4:
 		case VXFS_TYPED_DATA_DEV4: {
 			struct vxfs_typed_dev4	*typ4 =
 				(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_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
+				__FUNCTION__, __LINE__,
+			       (unsigned long long) be64_to_cpu(typ4->vd4_block),
+			       (unsigned long long) be64_to_cpu(typ4->vd4_size),
+			       be32_to_cpu(typ4->vd4_dev));
 			goto fail;
 		}
 		default:
+			printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, be64_to_cpu(typ->vt_hdr));
 			BUG();
 		}
 		brelse(bp);
@@ -182,7 +185,9 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 fail:
 	pblock = 0;
 out:
-	brelse(bp);
+	if (bp)
+		brelse(bp);
+	F_EXIT_V2();
 	return (pblock);
 }
 
@@ -200,16 +205,18 @@ out:
 static daddr_t
 vxfs_bmap_typed(struct inode *ip, long iblock)
 {
-	struct vxfs_inode_info		*vip = VXFS_INO(ip);
-	daddr_t				pblock = 0;
-	int				i;
+	struct vxfs_inode_info *vip = VXFS_INO(ip);
+	daddr_t pblock = 0;
+	int i;
 
+	F_ENTER_V2();
 	for (i = 0; i < VXFS_NTYPED; i++) {
-		struct vxfs_typed	*typ = vip->vii_org.typed + i;
+		struct vxfs_typed	*typ = vip->vii_org.typed + i; // cpu endian
 		int64_t			off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
 
-#ifdef DIAGNOSTIC
-		vxfs_typdump(typ);
+#ifdef DIAGNOSTIC_V2
+		printk(KERN_DEBUG "%s:%d type=%Lu, ofs=0x%Lx, blk=%d, size=%d\n", __FUNCTION__, __LINE__,
+			typ->vt_hdr >> VXFS_TYPED_TYPESHIFT, off, typ->vt_block, typ->vt_size );
 #endif
 		if (iblock < off)
 			continue;
@@ -219,29 +226,36 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
 					typ->vt_size, iblock - off);
 			if (pblock == -2)
 				break;
-			return (pblock);
+			goto out;
+
 		case VXFS_TYPED_DATA:
-			if ((iblock - off) < typ->vt_size)
-				return (typ->vt_block + iblock - off);
+			if ((iblock - off) < typ->vt_size) {
+				pblock = typ->vt_block + iblock - off;
+				goto out;
+			}
 			break;
 		case VXFS_TYPED_INDIRECT_DEV4:
 		case VXFS_TYPED_DATA_DEV4: {
 			struct vxfs_typed_dev4	*typ4 =
 				(struct vxfs_typed_dev4 *)typ;
 
-			printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
-			printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
+			printk(KERN_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
+				__FUNCTION__, __LINE__,
 			       (unsigned long long) typ4->vd4_block,
 			       (unsigned long long) typ4->vd4_size,
 			       typ4->vd4_dev);
-			return 0;
+			pblock = 0;
+			goto out;
 		}
 		default:
+			printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, typ->vt_hdr);
 			BUG();
 		}
 	}
 
-	return 0;
+out:
+	F_EXIT_V2("pblk %d", pblock);
+	return pblock;
 }
 
 /**
@@ -270,12 +284,14 @@ vxfs_bmap1(struct inode *ip, long iblock)
 	if (VXFS_ISIMMED(vip))
 		goto unsupp;
 
-	printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
-			ip->i_ino, vip->vii_orgtype);
+	printk(KERN_ERR "%s:%d inode %ld has no valid orgtype (%x)\n",
+		__FUNCTION__, __LINE__,
+		ip->i_ino, vip->vii_orgtype);
 	BUG();
 
 unsupp:
-	printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
-			ip->i_ino, vip->vii_orgtype);
+	printk(KERN_WARNING "%s:%d inode %ld has an unsupported orgtype (%x)\n",
+		__FUNCTION__, __LINE__,
+		ip->i_ino, vip->vii_orgtype);
 	return 0;
 }
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index aaf1fb0..d8b52e6 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -84,9 +84,5 @@ struct vxfs_direct {
 #define VXFS_DIRROUND(len)	((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
 #define VXFS_DIRLEN(len)	(VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
 
-/*
- * VXFS_DIRBLKOV is the overhead of a specific dirblock.
- */
-#define VXFS_DIRBLKOV(dbp)	((sizeof(short) * dbp->d_nhash) + 4)
 
 #endif /* _VXFS_DIR_H_ */
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 881aa3d..3d20421 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -55,7 +55,7 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
 
 /* vxfs_inode.c */
 extern const struct address_space_operations vxfs_immed_aops;
-extern struct kmem_cache	*vxfs_inode_cachep;
+//extern struct kmem_cache	*vxfs_inode_cachep;
 extern void			vxfs_dumpi(struct vxfs_inode_info *, ino_t);
 extern struct inode *		vxfs_get_fake_inode(struct super_block *,
 					struct vxfs_inode_info *);
@@ -64,6 +64,10 @@ extern struct vxfs_inode_info *	vxfs_blkiget(struct super_block *, u_long, ino_t
 extern struct vxfs_inode_info *	vxfs_stiget(struct super_block *, ino_t);
 extern struct inode *		vxfs_iget(struct super_block *, ino_t);
 extern void			vxfs_evict_inode(struct inode *);
+extern void vxfs_destroy_inode(struct inode *ip);
+extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
+extern int vxfs_inode_info_cache(int setup);
+
 
 /* vxfs_lookup.c */
 extern const struct inode_operations	vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c9a6a94..69fcd7f 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -2,6 +2,35 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * (c) 2016 Krzysztof Blaszkowski.
+ *       Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ *   - code not aware of cpu endianess and ondisk data is BE.
+ *   - misaligned structures read from block device
+ *   - wrong SB block number. default offset is 8kB
+ *   - kmem_cache_alloc() objectes released with kfree()
+ *   - inode.i_private released in evict_inode() callback.
+ *   - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// *  cksum mnt/usr/share/man/man3.Z/* 
+// *  cksum mnt/usr/share/doc/10.20RelNotes 
+// *  cksum mnt/usr/local/doom/*
+// *  cksum mnt/usr/sprockets/tools/instrument/16700/*
+// *  cksum mnt/usr/share/doc/*
+// *  cksum mnt/usr/sprockets/lib/*
+// *  cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ *  3457951056 4196020 /usr/local/doom/doom1.wad
+ *  2527157998 35344 /usr/local/doom/doomlaunch
+ *  2974998129 413696 /usr/local/doom/hpdoom
+ *
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -60,6 +89,34 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
 }
 #endif
 
+#define VXFS_BE32(field1, field2) fhp->field1 = be32_to_cpu(dbh->field2)
+
+
+static void inline dbh2fhp(struct vxfs_fsh *fhp, void *_dbh)
+{
+#ifdef __LITTLE_ENDIAN
+	struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
+
+	VXFS_BE32(fsh_version, fsh_version);
+	VXFS_BE32(fsh_fsindex, fsh_fsindex);
+	VXFS_BE32(fsh_time, fsh_time);
+	VXFS_BE32(fsh_utime, fsh_utime);
+	VXFS_BE32(fsh_extop, fsh_extop);
+	VXFS_BE32(fsh_ninodes, fsh_ninodes);
+	VXFS_BE32(fsh_nau, fsh_nau);
+	VXFS_BE32(fsh_old_ilesize, fsh_old_ilesize);
+	VXFS_BE32(fsh_dflags, fsh_dflags);
+	VXFS_BE32(fsh_quota, fsh_quota);
+	VXFS_BE32(fsh_maxinode, fsh_maxinode);
+	VXFS_BE32(fsh_iauino, fsh_iauino);
+	VXFS_BE32(fsh_ilistino[0], fsh_ilistino[0]);
+	VXFS_BE32(fsh_ilistino[1], fsh_ilistino[1]);
+	VXFS_BE32(fsh_lctino, fsh_lctino);
+#else
+	memcpy(fhp, _dbh, sizeof(*fhp));
+#endif
+}
+
 /**
  * vxfs_getfsh - read fileset header into memory
  * @ip:		the (fake) fileset header inode
@@ -83,7 +140,8 @@ vxfs_getfsh(struct inode *ip, int which)
 
 		if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
 			goto out;
-		memcpy(fhp, bp->b_data, sizeof(*fhp));
+
+		dbh2fhp(fhp, bp->b_data);
 
 		put_bh(bp);
 		return (fhp);
@@ -110,9 +168,12 @@ vxfs_read_fshead(struct super_block *sbp)
 	struct vxfs_fsh			*pfp, *sfp;
 	struct vxfs_inode_info		*vip, *tip;
 
+	F_ENTER();
+
 	vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
 	if (!vip) {
 		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
+		F_EXIT();
 		return -EINVAL;
 	}
 	if (!VXFS_ISFSH(vip)) {
@@ -121,10 +182,8 @@ vxfs_read_fshead(struct super_block *sbp)
 		goto out_free_fship;
 	}
 
-
 #ifdef DIAGNOSTIC
-	printk("vxfs: fsh inode dump:\n");
-	vxfs_dumpi(vip, infp->vsi_fshino);
+	printk("%s:%d\n", __FUNCTION__, __LINE__);
 #endif
 
 	infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
@@ -160,7 +219,7 @@ vxfs_read_fshead(struct super_block *sbp)
 	infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
 	if (!infp->vsi_stilist) {
 		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
-		kfree(tip);
+		vxfs_inode_info_free(tip);
 		goto out_free_pfp;
 	}
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
@@ -175,7 +234,7 @@ vxfs_read_fshead(struct super_block *sbp)
 	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
 	if (!infp->vsi_ilist) {
 		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
-		kfree(tip);
+		vxfs_inode_info_free(tip);
 		goto out_iput_stilist;
 	}
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
@@ -184,6 +243,7 @@ vxfs_read_fshead(struct super_block *sbp)
 		goto out_iput_ilist;
 	}
 
+	F_EXIT();
 	return 0;
 
  out_iput_ilist:
@@ -196,8 +256,10 @@ vxfs_read_fshead(struct super_block *sbp)
  	kfree(sfp);
  out_iput_fship:
 	iput(infp->vsi_fship);
+	F_EXIT();
 	return -EINVAL;
  out_free_fship:
- 	kfree(vip);
+	vxfs_inode_info_free(vip);
+	F_EXIT();
 	return -EINVAL;
 }
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 363e3ae..84dec28 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -2,6 +2,34 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * (c) 2016 Krzysztof Blaszkowski.
+ *       Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ *   - code not aware of cpu endianess and ondisk data is BE.
+ *   - misaligned structures read from block device
+ *   - wrong SB block number. default offset is 8kB
+ *   - kmem_cache_alloc() objectes released with kfree()
+ *   - inode.i_private released in evict_inode() callback.
+ *   - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// *  cksum mnt/usr/share/man/man3.Z/* 
+// *  cksum mnt/usr/share/doc/10.20RelNotes 
+// *  cksum mnt/usr/local/doom/*
+// *  cksum mnt/usr/sprockets/tools/instrument/16700/*
+// *  cksum mnt/usr/share/doc/*
+// *  cksum mnt/usr/sprockets/lib/*
+// *  cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ *  3457951056 4196020 /usr/local/doom/doom1.wad
+ *  2527157998 35344 /usr/local/doom/doomlaunch
+ *  2974998129 413696 /usr/local/doom/hpdoom
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -41,7 +69,7 @@
 #include "vxfs_extern.h"
 
 
-struct kmem_cache		*vxfs_inode_cachep;
+static struct kmem_cache *vxfs_inode_cachep;
 
 
 #ifdef DIAGNOSTIC
@@ -51,23 +79,88 @@ struct kmem_cache		*vxfs_inode_cachep;
 void
 vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
 {
-	printk(KERN_DEBUG "\n\n");
-	if (ino)
-		printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino);
+#ifdef DIAGNOSTIC_V2
+	if (ino && vip)
+		printk(KERN_DEBUG "\nvxfs inode %ld dump **** %p\n", ino, vip);
 	else
-		printk(KERN_DEBUG "dumping unknown vxfs inode\n");
+		printk(KERN_DEBUG "\ndumping unknown vxfs inode %p\n", vip);
 
-	printk(KERN_DEBUG "---------------------------\n");
-	printk(KERN_DEBUG "mode is %x\n", vip->vii_mode);
-	printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n",
-			vip->vii_nlink, vip->vii_uid, vip->vii_gid);
-	printk(KERN_DEBUG "size:%Lx, blocks:%u\n",
+	if (vip) {
+		printk(KERN_DEBUG " * mode: %x, type %d\n", vip->vii_mode, vip->vii_orgtype);
+		printk(KERN_DEBUG " * size:%Lx, blocks:%u\n",
 			vip->vii_size, vip->vii_blocks);
-	printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype);
+		printk(KERN_DEBUG " * nlink:%u, uid:%u, gid:%u\n",
+			vip->vii_nlink, vip->vii_uid, vip->vii_gid);
+	}
+#endif
 }
 #endif
 
 
+#define VXFS_BE32(field1, field2) vip->field1 = be32_to_cpu(dip->field2)
+#define VXFS_BE64(field1, field2) vip->field1 = be64_to_cpu(dip->field2)
+#define VXFS_BE16(field1, field2) vip->field1 = be16_to_cpu(dip->field2)
+
+
+static void inline dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
+{
+#ifdef __LITTLE_ENDIAN
+	int j;
+
+	VXFS_BE32(vdi_mode, vdi_mode);
+	VXFS_BE32(vdi_nlink, vdi_nlink);
+	VXFS_BE32(vdi_uid, vdi_uid);
+	VXFS_BE32(vdi_gid, vdi_gid);
+	VXFS_BE64(vdi_size, vdi_size);
+	VXFS_BE32(vdi_atime, vdi_atime);
+	VXFS_BE32(vdi_autime, vdi_autime);
+	VXFS_BE32(vdi_mtime, vdi_mtime);
+	VXFS_BE32(vdi_mutime, vdi_mutime);
+	VXFS_BE32(vdi_ctime, vdi_ctime);
+	VXFS_BE32(vdi_cutime, vdi_cutime);
+	vip->vdi_aflags = dip->vdi_aflags;
+	vip->vdi_orgtype = dip->vdi_orgtype;
+	VXFS_BE16(vdi_eopflags, vdi_eopflags);
+	VXFS_BE32(vdi_eopdata, vdi_eopdata);
+
+	VXFS_BE32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
+	VXFS_BE32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
+	VXFS_BE32(vdi_blocks, vdi_blocks);
+	VXFS_BE32(vdi_gen, vdi_gen);
+	VXFS_BE64(vdi_version, vdi_version);
+
+	switch (dip->vdi_orgtype) {
+	case VXFS_ORG_EXT4:
+		VXFS_BE32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
+		VXFS_BE32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
+		for (j = 0; j < VXFS_NIADDR; j++) {
+			VXFS_BE32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
+		}
+		for (j = 0; j < VXFS_NDADDR; j++) {
+			VXFS_BE32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
+			VXFS_BE32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
+		}
+		break;
+	case VXFS_ORG_IMMED:
+		memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
+		break;
+	case VXFS_ORG_TYPED:
+		for (j = 0; j < VXFS_NTYPED; j++) {
+			VXFS_BE64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
+			VXFS_BE32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
+			VXFS_BE32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
+		}
+		break;
+	
+	};
+
+	VXFS_BE32(vdi_iattrino, vdi_iattrino);
+#else
+	memcpy(vip, dip, sizeof(*vip));
+#endif
+}
+
+
 /**
  * vxfs_blkiget - find inode based on extent #
  * @sbp:	superblock of the filesystem we search in
@@ -84,6 +177,9 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
  *  buffercache.  This function should not be used outside the
  *  read_super() method, otherwise the data may be incoherent.
  */
+
+
+
 struct vxfs_inode_info *
 vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
 {
@@ -101,7 +197,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
 		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(vip, dip);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
@@ -143,7 +239,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
 		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(vip, dip);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
@@ -190,7 +286,7 @@ vxfs_stiget(struct super_block *sbp, ino_t ino)
 static __inline__ umode_t
 vxfs_transmod(struct vxfs_inode_info *vip)
 {
-	umode_t			ret = vip->vii_mode & ~VXFS_TYPE_MASK;
+	umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
 
 	if (VXFS_ISFIFO(vip))
 		ret |= S_IFIFO;
@@ -340,21 +436,61 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
 static void vxfs_i_callback(struct rcu_head *head)
 {
 	struct inode *inode = container_of(head, struct inode, i_rcu);
-	kmem_cache_free(vxfs_inode_cachep, inode->i_private);
+	void *priv = inode->i_private;
+
+	inode->i_private = NULL;
+	// just in case the same inode was used elsewhere after releasing i_private.
+	// if it was then dereferencing NULL is far better than using invalid
+	// pointer to memory claimed by something.
+	kmem_cache_free(vxfs_inode_cachep, priv);
+}
+
+void vxfs_destroy_inode(struct inode *ip)
+{
+	call_rcu(&ip->i_rcu, vxfs_i_callback);
+}
+
+void vxfs_inode_info_free(struct vxfs_inode_info *vip)
+{
+	kmem_cache_free(vxfs_inode_cachep, vip);
 }
 
+
 /**
  * vxfs_evict_inode - remove inode from main memory
  * @ip:		inode to discard.
  *
  * Description:
- *  vxfs_evict_inode() is called on the final iput and frees the private
- *  inode area.
+ *  vxfs_evict_inode() is called on the final iput 
  */
 void
 vxfs_evict_inode(struct inode *ip)
 {
 	truncate_inode_pages_final(&ip->i_data);
+	invalidate_inode_buffers(ip);
 	clear_inode(ip);
-	call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
+
+int vxfs_inode_info_cache(int setup)
+{
+	int rc = 0;
+
+	if (!setup) {
+		vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
+			sizeof(struct vxfs_inode_info), 0,
+			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
+
+		if (!vxfs_inode_cachep)
+			rc = -ENOMEM;
+	} else {
+	/*
+	 * Make sure all delayed rcu free inodes are flushed before we
+	 * destroy cache.
+	 */
+		rcu_barrier();
+		kmem_cache_destroy(vxfs_inode_cachep);
+	}
+
+	return rc;
+}
+
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 240aeb1..9fc3533 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -77,13 +77,13 @@ struct vxfs_ext4 {
 		vx_daddr_t	extent;			/* Extent number */
 		int32_t		size;			/* Size of extent */
 	} ve4_direct[VXFS_NDADDR];
-};
+}  __attribute__((packed));
 
 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 */
-};
+}  __attribute__((packed));
 
 struct vxfs_typed_dev4 {
 	u_int64_t	vd4_hdr;	/* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
@@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
 	u_int64_t	vd4_size;	/* Size in blocks */
 	int32_t		vd4_dev;	/* Device ID */
 	u_int32_t	__pad1;
-};
+}  __attribute__((packed));
 
 /*
  * The inode as contained on the physical device.
@@ -134,7 +134,7 @@ struct vxfs_dinode {
 		struct vxfs_typed	typed[VXFS_NTYPED];
 	} vdi_org;
 	u_int32_t	vdi_iattrino;
-};
+} __attribute__((packed));
 
 #define vdi_rdev	vdi_ftarea.rdev
 #define vdi_dotdot	vdi_ftarea.dotdot
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 99c7f0a..2e5365b 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -2,6 +2,34 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ * (c) 2016 Krzysztof Blaszkowski.
+ *       Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ *   - code not aware of cpu endianess and ondisk data is BE.
+ *   - misaligned structures read from block device
+ *   - wrong SB block number. default offset is 8kB
+ *   - kmem_cache_alloc() objectes released with kfree()
+ *   - inode.i_private released in evict_inode() callback.
+ *   - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// *  cksum mnt/usr/share/man/man3.Z/* 
+// *  cksum mnt/usr/share/doc/10.20RelNotes 
+// *  cksum mnt/usr/local/doom/*
+// *  cksum mnt/usr/sprockets/tools/instrument/16700/*
+// *  cksum mnt/usr/share/doc/*
+// *  cksum mnt/usr/sprockets/lib/*
+// *  cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ *  3457951056 4196020 /usr/local/doom/doom1.wad
+ *  2527157998 35344 /usr/local/doom/doomlaunch
+ *  2974998129 413696 /usr/local/doom/hpdoom
+ *
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -76,6 +104,15 @@ dir_blocks(struct inode *ip)
 }
 
 /*
+ * VXFS_dirblk_ovh is the overhead of a specific dirblock.
+ */
+static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp)
+{
+	return (sizeof(short) * be16_to_cpu(dbp->d_nhash)) + 4;
+}
+
+
+/*
  * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
  *
  * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
@@ -83,19 +120,13 @@ dir_blocks(struct inode *ip)
 static inline int
 vxfs_match(int len, const char * const name, struct vxfs_direct *de)
 {
-	if (len != de->d_namelen)
+	if (len != be16_to_cpu(de->d_namelen))
 		return 0;
 	if (!de->d_ino)
 		return 0;
 	return !memcmp(name, de->d_name, len);
 }
 
-static inline struct vxfs_direct *
-vxfs_next_entry(struct vxfs_direct *de)
-{
-	return ((struct vxfs_direct *)((char*)de + de->d_reclen));
-}
-
 /**
  * vxfs_find_entry - find a mathing directory entry for a dentry
  * @ip:		directory inode
@@ -113,50 +144,73 @@ vxfs_next_entry(struct vxfs_direct *de)
 static struct vxfs_direct *
 vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
 {
-	u_long				npages, page, nblocks, pblocks, block;
-	u_long				bsize = ip->i_sb->s_blocksize;
-	const char			*name = dp->d_name.name;
-	int				namelen = dp->d_name.len;
-
-	npages = dir_pages(ip);
-	nblocks = dir_blocks(ip);
-	pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
-	
-	for (page = 0; page < npages; page++) {
-		caddr_t			kaddr;
-		struct page		*pp;
-
-		pp = vxfs_get_page(ip->i_mapping, page);
-		if (IS_ERR(pp))
-			continue;
-		kaddr = (caddr_t)page_address(pp);
-
-		for (block = 0; block <= nblocks && block <= pblocks; block++) {
-			caddr_t			baddr, limit;
-			struct vxfs_dirblk	*dbp;
-			struct vxfs_direct	*de;
-
-			baddr = kaddr + (block * bsize);
-			limit = baddr + bsize - VXFS_DIRLEN(1);
-			
-			dbp = (struct vxfs_dirblk *)baddr;
-			de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
-
-			for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
-				if (!de->d_reclen)
-					break;
-				if (!de->d_ino)
-					continue;
-				if (vxfs_match(namelen, name, de)) {
-					*ppp = pp;
-					return (de);
-				}
+	u_long bsize = ip->i_sb->s_blocksize;
+	const char *name = dp->d_name.name;
+	int namelen = dp->d_name.len;
+	loff_t limit = VXFS_DIRROUND(ip->i_size);
+	struct vxfs_direct *de_exit = NULL;
+	loff_t pos = 0;
+
+
+	F_ENTER_V2("\"%s\" %d", name, namelen);
+
+	while (pos < limit) {
+		struct page *pp;
+		char *kaddr;
+		int pg_ofs = pos & ~PAGE_CACHE_MASK;
+
+		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+		if (IS_ERR(pp)) {
+			return NULL;
+		}
+		kaddr = (char *)page_address(pp);
+
+#ifdef DIAGNOSTIC_V2
+		printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
+#endif
+		while (pg_ofs < PAGE_SIZE && pos < limit) {
+			struct vxfs_direct *de;
+
+			if ((pos & (bsize - 1)) < 4) {
+				struct vxfs_dirblk *dbp = 
+				    (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
+				pos += VXFS_dirblk_ovh(dbp);
+				pg_ofs += VXFS_dirblk_ovh(dbp);
+			}
+			de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+#ifdef DIAGNOSTIC_V2
+			printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
+				de, pg_ofs,
+				de->d_name, be16_to_cpu(de->d_namelen),
+				be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
+#endif
+			if (!de->d_reclen) {
+				pos += bsize - 1;
+				pos &= ~(bsize - 1);
+				break;
+			}
+
+			pg_ofs += be16_to_cpu(de->d_reclen);
+			pos += be16_to_cpu(de->d_reclen);
+			if (!de->d_ino) {
+				continue;
+			}
+
+			if (vxfs_match(namelen, name, de)) {
+				*ppp = pp;
+				de_exit= de; //return (de);
+				break;
 			}
 		}
-		vxfs_put_page(pp);
+		if (!de_exit)
+			vxfs_put_page(pp);
+		else
+			break;
 	}
 
-	return NULL;
+	F_EXIT_V2("\"%s\": %p", name, de_exit);
+	return de_exit;
 }
 
 /**
@@ -180,11 +234,10 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
 
 	de = vxfs_find_entry(dip, dp, &pp);
 	if (de) {
-		ino = de->d_ino;
-		kunmap(pp);
-		page_cache_release(pp);
+		ino = be32_to_cpu(de->d_ino);
+		vxfs_put_page(pp);
 	}
-	
+
 	return (ino);
 }
 
@@ -207,17 +260,17 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
 {
 	struct inode		*ip = NULL;
 	ino_t			ino;
-			 
+
 	if (dp->d_name.len > VXFS_NAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
-				 
+
 	ino = vxfs_inode_by_name(dip, dp);
 	if (ino) {
 		ip = vxfs_iget(dip->i_sb, ino);
 		if (IS_ERR(ip))
 			return ERR_CAST(ip);
+		d_add(dp, ip);
 	}
-	d_add(dp, ip);
 	return NULL;
 }
 
@@ -234,80 +287,95 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
  * Returns:
  *   Zero.
  */
+
 static int
 vxfs_readdir(struct file *fp, struct dir_context *ctx)
 {
 	struct inode		*ip = file_inode(fp);
 	struct super_block	*sbp = ip->i_sb;
 	u_long			bsize = sbp->s_blocksize;
-	u_long			page, npages, block, pblocks, nblocks, offset;
-	loff_t			pos;
+	loff_t			pos, limit;
+
+	F_ENTER_V3("pos %ld, ino %ld, size %ld", (long)ctx->pos, ip->i_ino, (long)ip->i_size);
 
 	if (ctx->pos == 0) {
 		if (!dir_emit_dot(fp, ctx))
-			return 0;
-		ctx->pos = 1;
+			goto out;
+		ctx->pos++;
 	}
 	if (ctx->pos == 1) {
 		if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
-			return 0;
-		ctx->pos = 2;
+			goto out;
+		ctx->pos++;
 	}
-	pos = ctx->pos - 2;
-	
-	if (pos > VXFS_DIRROUND(ip->i_size))
-		return 0;
 
-	npages = dir_pages(ip);
-	nblocks = dir_blocks(ip);
-	pblocks = VXFS_BLOCK_PER_PAGE(sbp);
+	limit = VXFS_DIRROUND(ip->i_size);
+	if (ctx->pos > limit) {
+//		ctx->pos = 0;
+		goto out;
+	}
 
-	page = pos >> PAGE_CACHE_SHIFT;
-	offset = pos & ~PAGE_CACHE_MASK;
-	block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
+	pos = ctx->pos & ~3L;
 
-	for (; page < npages; page++, block = 0) {
-		char			*kaddr;
-		struct page		*pp;
+	while (pos < limit) {
+		struct page *pp;
+		char *kaddr;
+		int pg_ofs = pos & ~PAGE_CACHE_MASK;
+		int rc = 0;
 
-		pp = vxfs_get_page(ip->i_mapping, page);
-		if (IS_ERR(pp))
-			continue;
+		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+		if (IS_ERR(pp)) {
+			return -ENOMEM;
+		}
 		kaddr = (char *)page_address(pp);
 
-		for (; block <= nblocks && block <= pblocks; block++) {
-			char			*baddr, *limit;
-			struct vxfs_dirblk	*dbp;
-			struct vxfs_direct	*de;
-
-			baddr = kaddr + (block * bsize);
-			limit = baddr + bsize - VXFS_DIRLEN(1);
-	
-			dbp = (struct vxfs_dirblk *)baddr;
-			de = (struct vxfs_direct *)
-				(offset ?
-				 (kaddr + offset) :
-				 (baddr + VXFS_DIRBLKOV(dbp)));
-
-			for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
-				if (!de->d_reclen)
-					break;
-				if (!de->d_ino)
-					continue;
-
-				offset = (char *)de - kaddr;
-				ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
-				if (!dir_emit(ctx, de->d_name, de->d_namelen,
-					de->d_ino, DT_UNKNOWN)) {
-					vxfs_put_page(pp);
-					return 0;
-				}
+#ifdef DIAGNOSTIC_V3
+		printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
+#endif
+		while (pg_ofs < PAGE_SIZE && pos < limit) {
+			struct vxfs_direct *de;
+
+			if ((pos & (bsize - 1)) < 4) {
+				struct vxfs_dirblk *dbp = 
+				    (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
+				pos += VXFS_dirblk_ovh(dbp);
+				pg_ofs += VXFS_dirblk_ovh(dbp);
+			}
+			de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+#ifdef DIAGNOSTIC_V3
+			printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
+				de, pg_ofs,
+				de->d_name, be16_to_cpu(de->d_namelen),
+				be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
+#endif
+			if (!de->d_reclen) {
+				pos += bsize - 1;
+				pos &= ~(bsize - 1);
+				break;
+			}
+
+			pg_ofs += be16_to_cpu(de->d_reclen);
+			pos += be16_to_cpu(de->d_reclen);
+			if (!de->d_ino) {
+				continue;
+			}
+
+			if (! (rc = dir_emit(ctx, de->d_name, be16_to_cpu(de->d_namelen),
+				be32_to_cpu(de->d_ino), DT_UNKNOWN))) {
+				// the dir entry was not submitted, so fix pos.
+				pos -= be16_to_cpu(de->d_reclen); 
+				break;
 			}
-			offset = 0;
 		}
 		vxfs_put_page(pp);
-		offset = 0;
+		if (!rc)
+			break;
 	}
-	ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
+
+	ctx->pos = pos | 2;
+
+out:
+	F_EXIT_V3("pos %ld", (long)ctx->pos);
 	return 0;
 }
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 0495008..19a1cab 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -2,6 +2,10 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ *
+ * 2016 Krzysztof Blaszkowski.
+ *       Many bug fixes, improvements & tests
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -43,14 +47,14 @@ static inline void
 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 = be32_to_cpu(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 = be32_to_cpu(ilistp->olt_iext[0]); 
 }
 
 static inline u_long
@@ -80,6 +84,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 	struct buffer_head	*bp;
 	struct vxfs_olt		*op;
 	char			*oaddr, *eaddr;
+	u32 j;
 
 
 	bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
@@ -87,8 +92,8 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 		goto fail;
 
 	op = (struct vxfs_olt *)bp->b_data;
-	if (op->olt_magic != VXFS_OLT_MAGIC) {
-		printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
+	if ((j = be32_to_cpu(op->olt_magic)) != VXFS_OLT_MAGIC) {
+		printk(KERN_NOTICE "vxfs: ivalid olt magic number %08x at +%d\n", j, infp->vsi_oltext);
 		goto fail;
 	}
 
@@ -97,19 +102,24 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 	 * I've not seen any such filesystem yet and I'm lazy..  --hch
 	 */
 	if (infp->vsi_oltsize > 1) {
-		printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
+		printk(KERN_NOTICE "vxfs: oltsize > 1 detected (%d).\n", infp->vsi_oltsize);
 		printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
 		goto fail;
 	}
 
-	oaddr = bp->b_data + op->olt_size;
+	oaddr = bp->b_data + be32_to_cpu(op->olt_size);
 	eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
 
 	while (oaddr < eaddr) {
-		struct vxfs_oltcommon	*ocp =
+		struct vxfs_oltcommon *ocp =
 			(struct vxfs_oltcommon *)oaddr;
-		
-		switch (ocp->olt_type) {
+
+#ifdef DIAGNOSTIC
+		printk(KERN_DEBUG "oltc_type %d, sz %d at +%d\n", 
+			be32_to_cpu(ocp->olt_type), be32_to_cpu(ocp->olt_size), (int)(oaddr - bp->b_data));
+#endif
+
+		switch (be32_to_cpu(ocp->olt_type)) {
 		case VXFS_OLT_FSHEAD:
 			vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
 			break;
@@ -118,11 +128,16 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
 			break;
 		}
 
-		oaddr += ocp->olt_size;
+		oaddr += be32_to_cpu(ocp->olt_size);
 	}
 
+#ifdef DIAGNOSTIC
+	printk(KERN_DEBUG "olt_size %d, vsi_fshino %d, vsi_iext %ld\n",
+	    be32_to_cpu(op->olt_size), (u32)infp->vsi_fshino, infp->vsi_iext);
+#endif
+
 	brelse(bp);
-	return 0;
+	return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
 
 fail:
 	brelse(bp);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7ca8c75..9fbf271 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -2,6 +2,38 @@
  * Copyright (c) 2000-2001 Christoph Hellwig.
  * All rights reserved.
  *
+ * (c) 2016 Krzysztof Blaszkowski.
+ *       Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ *   - code not aware of cpu endianess and ondisk data is BE.
+ *   - misaligned structures read from block device
+ *   - wrong SB block number. default offset is 8kB
+ *   - kmem_cache_alloc() objectes released with kfree()
+ *   - inode.i_private released in evict_inode() callback.
+ *   - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// *  cksum mnt/usr/share/man/man3.Z/* 
+// *  cksum mnt/usr/share/doc/10.20RelNotes 
+// *  cksum mnt/usr/local/doom/*
+// *  cksum mnt/usr/sprockets/tools/instrument/16700/*
+// *  cksum mnt/usr/share/doc/*
+// *  cksum mnt/usr/sprockets/lib/*
+// *  cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ *  3457951056 4196020 /usr/local/doom/doom1.wad
+ *  2527157998 35344 /usr/local/doom/doomlaunch
+ *  2974998129 413696 /usr/local/doom/hpdoom
+ *
+ * The hpux_mdsetup tool project which is aimed at making possible
+ * accessing HP-UX logical volumes by device mapper is here:
+ *       https://sourceforge.net/projects/linux-vxfs/
+ *
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -41,6 +73,7 @@
 #include <linux/stat.h>
 #include <linux/vfs.h>
 #include <linux/mount.h>
+#include <linux/byteorder/generic.h>
 
 #include "vxfs.h"
 #include "vxfs_extern.h"
@@ -48,7 +81,7 @@
 #include "vxfs_inode.h"
 
 
-MODULE_AUTHOR("Christoph Hellwig");
+MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
 MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
 MODULE_LICENSE("Dual BSD/GPL");
 
@@ -59,6 +92,7 @@ static int		vxfs_statfs(struct dentry *, struct kstatfs *);
 static int		vxfs_remount(struct super_block *, int *, char *);
 
 static const struct super_operations vxfs_super_ops = {
+	.destroy_inode = vxfs_destroy_inode,
 	.evict_inode =		vxfs_evict_inode,
 	.put_super =		vxfs_put_super,
 	.statfs =		vxfs_statfs,
@@ -153,6 +187,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 	u_long			bsize;
 	struct inode *root;
 	int ret = -EINVAL;
+	int j;
 
 	sbp->s_flags |= MS_RDONLY;
 
@@ -168,7 +203,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 		goto out;
 	}
 
-	bp = sb_bread(sbp, 1);
+	bp = sb_bread(sbp, 8);
 	if (!bp || !buffer_mapped(bp)) {
 		if (!silent) {
 			printk(KERN_WARNING
@@ -178,32 +213,30 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 	}
 
 	rsbp = (struct vxfs_sb *)bp->b_data;
-	if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
+	if (be32_to_cpu(rsbp->vs_magic) != VXFS_SUPER_MAGIC) {
 		if (!silent)
-			printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
+			printk(KERN_NOTICE "vxfs: WRONG superblock magic %08x\n", rsbp->vs_magic);
 		goto out;
 	}
 
-	if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
-		printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
-		       rsbp->vs_version);
+	j = be32_to_cpu(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);
-#endif
 
-	sbp->s_magic = rsbp->vs_magic;
+	sbp->s_magic = be32_to_cpu(rsbp->vs_magic);
 	sbp->s_fs_info = infp;
 
 	infp->vsi_raw = rsbp;
 	infp->vsi_bp = bp;
-	infp->vsi_oltext = rsbp->vs_oltext[0];
-	infp->vsi_oltsize = rsbp->vs_oltsize;
+	infp->vsi_oltext = be32_to_cpu(rsbp->vs_oltext[0]);
+	infp->vsi_oltsize = be32_to_cpu(rsbp->vs_oltsize);
+
+	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", be32_to_cpu(rsbp->vs_version));
 
-	if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
+	if (!sb_set_blocksize(sbp, be32_to_cpu(rsbp->vs_bsize))) {
 		printk(KERN_WARNING "vxfs: unable to set final block size\n");
 		goto out;
 	}
@@ -229,6 +262,8 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 		printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
 		goto out_free_ilist;
 	}
+	printk(KERN_DEBUG "vxfs: blocksize: %d, oltext %d, oltsize %d\n", 
+	    be32_to_cpu(rsbp->vs_bsize), infp->vsi_oltext, infp->vsi_oltsize);
 
 	return 0;
 	
@@ -237,6 +272,7 @@ out_free_ilist:
 	vxfs_put_fake_inode(infp->vsi_ilist);
 	vxfs_put_fake_inode(infp->vsi_stilist);
 out:
+	printk(KERN_ERR "vxfs: mount failed %d\n", ret);
 	brelse(bp);
 	kfree(infp);
 	return ret;
@@ -264,29 +300,22 @@ MODULE_ALIAS("vxfs");
 static int __init
 vxfs_init(void)
 {
-	int rv;
+	int rc = vxfs_inode_info_cache(0);
 
-	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
-			sizeof(struct vxfs_inode_info), 0,
-			SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
-	if (!vxfs_inode_cachep)
-		return -ENOMEM;
-	rv = register_filesystem(&vxfs_fs_type);
-	if (rv < 0)
-		kmem_cache_destroy(vxfs_inode_cachep);
-	return rv;
+	if (!rc) {
+		rc = register_filesystem(&vxfs_fs_type);
+		if (rc < 0)
+			vxfs_inode_info_cache(1);
+	}
+	printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __FUNCTION__, __DATE__, __TIME__, rc);
+	return rc;
 }
 
 static void __exit
 vxfs_cleanup(void)
 {
 	unregister_filesystem(&vxfs_fs_type);
-	/*
-	 * Make sure all delayed rcu free inodes are flushed before we
-	 * destroy cache.
-	 */
-	rcu_barrier();
-	kmem_cache_destroy(vxfs_inode_cachep);
+	vxfs_inode_info_cache(1);
 }
 
 module_init(vxfs_init);

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2016-05-26 14:44 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-25 21:27 freevxfs Krzysztof Błaszkowski
2016-05-26 11:50 ` freevxfs Carlos Maiolino
2016-05-26 14:44   ` freevxfs Krzysztof Błaszkowski
  -- strict thread matches above, loose matches on Subject: below --
2016-05-22 15:13 freevxfs Krzysztof Błaszkowski
2016-05-23  8:23 ` freevxfs Carlos Maiolino
2016-05-24 11:50   ` freevxfs Krzysztof Błaszkowski
2016-05-23  8:36 ` freevxfs Christoph Hellwig
2016-05-24  8:48   ` freevxfs Krzysztof Błaszkowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).