All of lore.kernel.org
 help / color / mirror / Atom feed
* freevxfs: hp-ux support. patchset 1-7/7
@ 2016-05-26 14:45 Krzysztof Błaszkowski
  2016-05-26 15:43 ` freevxfs: hp-ux support. (working) " Krzysztof Błaszkowski
                   ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-26 14:45 UTC (permalink / raw)
  To: Christoph Hellwig, Carlos Maiolino; +Cc: linux-fsdevel

Hi,

So then let it roll. 

Thanks

>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

>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

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



-- 
Krzysztof Blaszkowski



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

* Re: freevxfs: hp-ux support. (working) patchset 1-7/7
  2016-05-26 14:45 freevxfs: hp-ux support. patchset 1-7/7 Krzysztof Błaszkowski
@ 2016-05-26 15:43 ` Krzysztof Błaszkowski
  2016-05-26 15:53 ` r Christoph Hellwig
  2016-05-28 19:40 ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
  2 siblings, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-26 15:43 UTC (permalink / raw)
  To: Christoph Hellwig, Carlos Maiolino; +Cc: linux-fsdevel

And it stopped rolling. Get stuck on tab to space translation.
My goodness, sending patches is more complex than creating them.
nightmare.  .. kidding 
anyway evolution's:  "insert->text file" should do the job. (verified)

>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

>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

>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

>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

>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

>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

>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




On Thu, 2016-05-26 at 16:45 +0200, Krzysztof Błaszkowski wrote:
> Hi,
> 
> So then let it roll. 
-- 
Krzysztof Blaszkowski



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

* r
  2016-05-26 14:45 freevxfs: hp-ux support. patchset 1-7/7 Krzysztof Błaszkowski
  2016-05-26 15:43 ` freevxfs: hp-ux support. (working) " Krzysztof Błaszkowski
@ 2016-05-26 15:53 ` Christoph Hellwig
  2016-05-26 17:44   ` r Krzysztof Błaszkowski
  2016-05-28 19:40 ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
  2 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2016-05-26 15:53 UTC (permalink / raw)
  To: Krzysztof B??aszkowski; +Cc: Christoph Hellwig, Carlos Maiolino, linux-fsdevel

Hi Krzysztof,

first round of reviews below:

> Date: Wed, 25 May 2016 21:50:11 +0200
> Subject: [PATCH 1/7] kconfig note
> 
> 
> Signed-off-by: KB <kb@sysmikro.com.pl>

This part looks good, but I'd add a littlle more text and move it last
in the series.  The other patches could also use a little more
descriptive text in the changelogs.

> 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;

Can you explain why this is added?

>  
>  
>  /*
> @@ -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;
> +};

Can you align these with the rest of the fields?  Also where does the
silent flag come from here?

> +#define VXFS_FS32(field1, field2) fhp->field1 = fs32_to_cpu(bo, dbh->field2)

Please remove this wrapper.

> +#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)

and these.

> +	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;

I'd normally move this into a separate patch.  But even if this
stay in here it should be mentioned in the patch changelog.

>  	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);

brelse handles a null argument just fine.

>  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);
>  }

I'd rather go for embedding the VFS inode in the VxFS inode like most
modern file systems do.  Take a look at alloc_inode and destroy_inode
in ext2 for an example.


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

* Re: r
  2016-05-26 15:53 ` r Christoph Hellwig
@ 2016-05-26 17:44   ` Krzysztof Błaszkowski
  0 siblings, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-26 17:44 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

Hi Christoph,


On Thu, 2016-05-26 at 08:53 -0700, Christoph Hellwig wrote:
> Hi Krzysztof,
> 
> first round of reviews below:
> 
> > Date: Wed, 25 May 2016 21:50:11 +0200
> > Subject: [PATCH 1/7] kconfig note
> > 
> > 
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> 
> This part looks good, but I'd add a littlle more text and move it last
> in the series. 

okay, what would you write in this section ?
Will move the patch.


>  The other patches could also use a little more
> descriptive text in the changelogs.
> 
> > 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;
> 
> Can you explain why this is added?
> 

I was thinking that on-disk memory mapped structures should be "packed"
especially if they contain 1 or 2 bytes fields in the middle.
If the structure does not have the packed attribute then its size may be
bigger than the size of similar structure (by name) used on another OS
e.g. 32bit. An access to fields of such structure aligned differently
(due to e.g. 64 bit compiler) will end up with data corruption.

(that's the basics, why i write this ?)

the vxfs_sb structure has u8 and u16's so usage of __pack is desired
over here. the __pack will not cause any harm (because if we count all
u8 and u16, they are still u32 aligned) and it will prevent from
hypothetical misalignment (just in case). It is also a tip that the
structure is on-disk and must be compiler alignment independent.


> >  
> >  
> >  /*
> > @@ -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;
> > +};
> 
> Can you align these with the rest of the fields?  Also where does the
> silent flag come from here?

I reckon aligning it is not necessary, because this structure is
run-time, cpu endian and it lives in memory only (but storage device)

"silent" int comes from arg passed over to vxfs_fill_super() of the same
name. My workaround, I do not like functions which have long arguments
list. 2 args is fine, 3 - maybe too long, 4 - it must be done something,
5+ - bad day ? ;)


> 
> > +#define VXFS_FS32(field1, field2) fhp->field1 = fs32_to_cpu(bo, dbh->field2)
> 
> Please remove this wrapper.
> 
> > +#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)
> 
> and these.

well, this will be difficult. These macros help saving lots of typing
over and over again.

although they raise checkpatch errors I will not opt-out because scope
of these macros is local. These macros are not intended to be used
anywhere else than functions like: dip2vip_cpy() and dbh2fhp().

I can #undef them later. Will you agree ?


> 
> > +	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;
> 
> I'd normally move this into a separate patch.  But even if this
> stay in here it should be mentioned in the patch changelog.

indeed, that's quite important new feature.
changelog ?, where is it ?


> 
> >  	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);
> 
> brelse handles a null argument just fine.

wasn't sure so added the "if" just in case of it didn't handle.
that "if" may stay there still.

> 
> >  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);
> >  }
> 
> I'd rather go for embedding the VFS inode in the VxFS inode like most
> modern file systems do.  Take a look at alloc_inode and destroy_inode
> in ext2 for an example.

right, and then alloc callback will be necessary. this will introduce
more changes to e.g. get_fake_inode() and around this function. 

Do you really want to have this "more perfect" ?


> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-05-26 14:45 freevxfs: hp-ux support. patchset 1-7/7 Krzysztof Błaszkowski
  2016-05-26 15:43 ` freevxfs: hp-ux support. (working) " Krzysztof Błaszkowski
  2016-05-26 15:53 ` r Christoph Hellwig
@ 2016-05-28 19:40 ` Krzysztof Błaszkowski
  2016-05-30 11:19   ` Carlos Maiolino
  2016-05-31 12:25   ` Christoph Hellwig
  2 siblings, 2 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-28 19:40 UTC (permalink / raw)
  To: Carlos Maiolino; +Cc: Christoph Hellwig, linux-fsdevel

Hi Carlos,

Christoph told me that you can look at these patches I prepared.

The patchset has follwing changes since previous release:
- preprocesor expanded local macros,
- merged credits patches,
- struct inode placed inside local structure vxfs_vfs_inode.

Last change is the most complex and makes an impact on e.g.
read_fshead() and actually it is only one proper solution. A file system
must not use destroy_inode callback without alloc_inode. if it does
then inode structures will not be returned to fs/inode.c: inode_cachep.

>From 56ac335ff74706be4c3e30925d2c8c47a19eab9e Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Sat, 28 May 2016 20:55:19 +0200
Subject: [PATCH 1/7] cpu endianess vs file system, two locations of the sb


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  |   57 +++++++++++++++++++++++-
 fs/freevxfs/vxfs_inode.h  |    8 ++--
 fs/freevxfs/vxfs_lookup.c |   15 +++++-
 fs/freevxfs/vxfs_olt.c    |   15 +++---
 fs/freevxfs/vxfs_super.c  |  108 +++++++++++++++++++++++++++++++++------------
 8 files changed, 221 insertions(+), 56 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..05cced0 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -60,6 +60,29 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
 }
 #endif
 
+
+static inline void dbh2fhp(struct vxfs_fsh *fhp, void *_dbh, int bo)
+{
+ struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
+
+ fhp->fsh_version = fs32_to_cpu(bo, dbh->fsh_version);
+ fhp->fsh_fsindex = fs32_to_cpu(bo, dbh->fsh_fsindex);
+ fhp->fsh_time = fs32_to_cpu(bo, dbh->fsh_time);
+ fhp->fsh_utime = fs32_to_cpu(bo, dbh->fsh_utime);
+ fhp->fsh_extop = fs32_to_cpu(bo, dbh->fsh_extop);
+ fhp->fsh_ninodes = fs32_to_cpu(bo, dbh->fsh_ninodes);
+ fhp->fsh_nau = fs32_to_cpu(bo, dbh->fsh_nau);
+ fhp->fsh_old_ilesize = fs32_to_cpu(bo, dbh->fsh_old_ilesize);
+ fhp->fsh_dflags = fs32_to_cpu(bo, dbh->fsh_dflags);
+ fhp->fsh_quota = fs32_to_cpu(bo, dbh->fsh_quota);
+ fhp->fsh_maxinode = fs32_to_cpu(bo, dbh->fsh_maxinode);
+ fhp->fsh_iauino = fs32_to_cpu(bo, dbh->fsh_iauino);
+ fhp->fsh_ilistino[0] = fs32_to_cpu(bo, dbh->fsh_ilistino[0]);
+ fhp->fsh_ilistino[1] = fs32_to_cpu(bo, dbh->fsh_ilistino[1]);
+ fhp->fsh_lctino = fs32_to_cpu(bo, dbh->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..86db3c2 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -67,6 +67,59 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
 }
 #endif
 
+static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip, int bo)
+{
+ int j;
+
+ vip->vdi_mode = fs32_to_cpu(bo, dip->vdi_mode);
+ vip->vdi_nlink = fs32_to_cpu(bo, dip->vdi_nlink);
+ vip->vdi_uid = fs32_to_cpu(bo, dip->vdi_uid);
+ vip->vdi_gid = fs32_to_cpu(bo, dip->vdi_gid);
+ vip->vdi_size = fs64_to_cpu(bo, dip->vdi_size);
+ vip->vdi_atime = fs32_to_cpu(bo, dip->vdi_atime);
+ vip->vdi_autime = fs32_to_cpu(bo, dip->vdi_autime);
+ vip->vdi_mtime = fs32_to_cpu(bo, dip->vdi_mtime);
+ vip->vdi_mutime = fs32_to_cpu(bo, dip->vdi_mutime);
+ vip->vdi_ctime = fs32_to_cpu(bo, dip->vdi_ctime);
+ vip->vdi_cutime = fs32_to_cpu(bo, dip->vdi_cutime);
+ vip->vdi_aflags = dip->vdi_aflags;
+ vip->vdi_orgtype = dip->vdi_orgtype;
+ vip->vdi_eopflags = fs16_to_cpu(bo, dip->vdi_eopflags);
+ vip->vdi_eopdata = fs32_to_cpu(bo, dip->vdi_eopdata);
+
+ vip->vdi_ftarea.i_regular.reserved = fs32_to_cpu(bo, dip->vdi_ftarea.i_regular.reserved);
+ vip->vdi_ftarea.i_regular.fixextsize = fs32_to_cpu(bo, dip->vdi_ftarea.i_regular.fixextsize);
+ vip->vdi_blocks = fs32_to_cpu(bo, dip->vdi_blocks);
+ vip->vdi_gen = fs32_to_cpu(bo, dip->vdi_gen);
+ vip->vdi_version = fs64_to_cpu(bo, dip->vdi_version);
+
+ switch (dip->vdi_orgtype) {
+ case VXFS_ORG_EXT4:
+  vip->vdi_org.ext4.ve4_spare = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_spare);
+  vip->vdi_org.ext4.ve4_indsize = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_indsize);
+  for (j = 0; j < 2; j++) {
+   vip->vdi_org.ext4.ve4_indir[j] = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_indir[j]);
+  }
+  for (j = 0; j < 10; j++) {
+   vip->vdi_org.ext4.ve4_direct[j].extent = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_direct[j].extent);
+   vip->vdi_org.ext4.ve4_direct[j].size = fs32_to_cpu(bo, dip->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 < 6; j++) {
+   vip->vdi_org.typed[j].vt_hdr = fs64_to_cpu(bo, dip->vdi_org.typed[j].vt_hdr);
+   vip->vdi_org.typed[j].vt_block = fs32_to_cpu(bo, dip->vdi_org.typed[j].vt_block);
+   vip->vdi_org.typed[j].vt_size = fs32_to_cpu(bo, dip->vdi_org.typed[j].vt_size);
+  }
+  break;
+ };
+
+ vip->vdi_iattrino = fs32_to_cpu(bo, dip->vdi_iattrino);
+}
+
 
 /**
  * vxfs_blkiget - find inode based on extent #
@@ -101,7 +154,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 +196,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..6a69eb0 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,53 @@ 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 %08x at +%d\n",
+					rsbp->vs_magic, blk);
+			break;
+		}
+
+		rc = 0;
+		infp->vsi_raw = rsbp;
+		infp->vsi_bp = bp;
+	} while (0);
+
+	if (rc) {
+		infp->vsi_raw = NULL;
+		infp->vsi_bp = NULL;
+		brelse(bp);
+	}
+
+	return rc;
+}
+
+
+static const char * const vxfs_subtypes[] = {
+	"SCO",
+	"HP-UX(be)"
+};
+
 /**
  * vxfs_read_super - read superblock into memory and initialize filesystem
  * @sbp:		VFS superblock (to fill)
@@ -149,10 +197,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 +210,50 @@ 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 */
+			sbp->s_subtype = kstrdup(vxfs_subtypes[0], GFP_KERNEL);
+			break;
+		}
+
+		if (!vxfs_try_sb_magic(sbp, 8, cpu_to_be32(VXFS_SUPER_MAGIC))) {
+			infp->byte_order = BO_BE; /* HP-UX pa-risc likely */
+			sbp->s_subtype = kstrdup(vxfs_subtypes[1], GFP_KERNEL);
+			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: blocksize: %d\n", rsbp->vs_bsize);
+	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
+	printk(KERN_DEBUG "vxfs: blocksize: %d\n",
+	    fs32_to_cpu(infp->byte_order, 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 +287,7 @@ out_free_ilist:
 	vxfs_put_fake_inode(infp->vsi_ilist);
 	vxfs_put_fake_inode(infp->vsi_stilist);
 out:
-	brelse(bp);
+	brelse(infp->vsi_bp);
 	kfree(infp);
 	return ret;
 }
-- 
1.7.3.4

>From 0d0c7ed061edd846bd032fe1073d61169299a435 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Sat, 28 May 2016 20:55:19 +0200
Subject: [PATCH 2/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 05cced0..c4c6a86 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 86db3c2..9590f79 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -411,3 +411,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

>From c595f46ad63d71ac26dfc3ef23d87e372ac85426 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Sat, 28 May 2016 20:55:19 +0200
Subject: [PATCH 3/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 9590f79..f91a50c 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -393,7 +393,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);
 }
 
 /**
@@ -401,17 +409,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 6a69eb0..500087a 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

>From b02ffccdff5ca82922bf09cdcf1a9ea4471bbb62 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Sat, 28 May 2016 20:55:19 +0200
Subject: [PATCH 4/7] refactoring of vxfs_readdir() 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

>From eceb47a770b80d7f46a089f6a1744d66f0601e77 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Sat, 28 May 2016 20:55:19 +0200
Subject: [PATCH 5/7] static inode_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 f91a50c..1e20823 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
@@ -424,3 +424,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 500087a..9525818 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -315,29 +315,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

>From 2915ed2c92dd349203070eea8970fd4fb62ba5b4 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Sat, 28 May 2016 20:55:19 +0200
Subject: [PATCH 6/7] struct inode embedded in vxfs_vfs_inode

struct vxfs_vfs_inode is allocated from vxfs_inode_cachep
and vfs inode is initialized by inode_constructor().
sb->s_op must be set before read_fshead() otherwise 
3 inodes will be allocated from common inode_cachep.


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs.h        |    8 ---
 fs/freevxfs/vxfs_bmap.c   |    5 +-
 fs/freevxfs/vxfs_extern.h |   15 +++---
 fs/freevxfs/vxfs_fshead.c |   48 +++++++----------
 fs/freevxfs/vxfs_inode.c  |  130 ++++++++++++++++++++-------------------------
 fs/freevxfs/vxfs_inode.h  |   20 +++++++-
 fs/freevxfs/vxfs_super.c  |   16 +++---
 7 files changed, 114 insertions(+), 128 deletions(-)

diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 5dc8949..8124a10 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -38,7 +38,6 @@
  */
 #include <linux/types.h>
 
-
 /*
  * Data types for use with the VxFS ondisk format.
  */
@@ -270,13 +269,6 @@ enum {
 #define VXFS_ISIMMED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
 #define VXFS_ISTYPED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
 
-
-/*
- * Get filesystem private data from VFS inode.
- */
-#define VXFS_INO(ip) \
-	((struct vxfs_inode_info *)(ip)->i_private)
-
 /*
  * Get filesystem private data from VFS superblock.
  */
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index 95afd98..e39aea4 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -97,8 +97,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
 
 		brelse(buf);
 		return bno;
-	} else
-		printk(KERN_WARNING "no matching indir?");
+	} else {
+		printk(KERN_WARNING "%s:%d no matching indir?\n", __func__, __LINE__);
+	}
 
 	return 0;
 
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index cc43fd0..9648735 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -56,17 +56,16 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
 /* vxfs_inode.c */
 extern const struct address_space_operations vxfs_immed_aops;
 extern void			vxfs_dumpi(struct vxfs_inode_info *, ino_t);
-extern struct inode *		vxfs_get_fake_inode(struct super_block *,
-					struct vxfs_inode_info *);
-extern void			vxfs_put_fake_inode(struct inode *);
-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);
+
+extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
+extern struct inode *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 int vxfs_ii_cache_init(void);
 extern void vxfs_ii_cache_destroy(void);
+extern struct inode *vxfs_inode_alloc(struct super_block *sb);
 
 
 /* vxfs_lookup.c */
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c4c6a86..b24cb8c 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -131,31 +131,26 @@ vxfs_read_fshead(struct super_block *sbp)
 {
 	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
 	struct vxfs_fsh			*pfp, *sfp;
-	struct vxfs_inode_info		*vip, *tip;
+	struct inode *ip1;
+	struct inode *ip2;
 
-	vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
-	if (!vip) {
+	infp->vsi_fship = ip1 = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
+	if (IS_ERR(ip1)) {
 		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
 		return -EINVAL;
 	}
-	if (!VXFS_ISFSH(vip)) {
+
+	if (!VXFS_ISFSH(VXFS_INO(ip1))) {
 		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
-				vip->vii_mode & VXFS_TYPE_MASK); 
+				VXFS_INO(ip1)->vii_mode & VXFS_TYPE_MASK);
 		goto out_free_fship;
 	}
 
-
 #ifdef DIAGNOSTIC
 	printk("vxfs: fsh inode dump:\n");
-	vxfs_dumpi(vip, infp->vsi_fshino);
+	vxfs_dumpi(VXFS_INO(ip1), infp->vsi_fshino);
 #endif
 
-	infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
-	if (!infp->vsi_fship) {
-		printk(KERN_ERR "vxfs: unable to get fsh inode\n");
-		goto out_free_fship;
-	}
-
 	sfp = vxfs_getfsh(infp->vsi_fship, 0);
 	if (!sfp) {
 		printk(KERN_ERR "vxfs: unable to get structural fsh\n");
@@ -176,31 +171,25 @@ vxfs_read_fshead(struct super_block *sbp)
 	vxfs_dumpfsh(pfp);
 #endif
 
-	tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
-	if (!tip)
-		goto out_free_pfp;
+	infp->vsi_stilist =
+		ip2 = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
 
-	infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
-	if (!infp->vsi_stilist) {
-		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
-		vxfs_inode_info_free(tip);
+	if (IS_ERR(ip2)) {
 		goto out_free_pfp;
 	}
+
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
 		printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n",
 				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 
 		goto out_iput_stilist;
 	}
 
-	tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
-	if (!tip)
-		goto out_iput_stilist;
-	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
-	if (!infp->vsi_ilist) {
+	infp->vsi_ilist = ip2 = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
+	if (IS_ERR(ip2)) {
 		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
-		vxfs_inode_info_free(tip);
 		goto out_iput_stilist;
 	}
+
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
 		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
 				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
@@ -220,9 +209,10 @@ vxfs_read_fshead(struct super_block *sbp)
  out_free_sfp:
  	kfree(sfp);
  out_iput_fship:
-	iput(infp->vsi_fship);
-	return -EINVAL;
  out_free_fship:
-	vxfs_inode_info_free(vip);
+	iput(infp->vsi_fship);
+	infp->vsi_stilist = NULL;
+	infp->vsi_ilist = NULL;
+	infp->vsi_fship = NULL;
 	return -EINVAL;
 }
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 1e20823..ee0ca04 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -42,6 +42,7 @@
 
 
 static struct kmem_cache *vxfs_inode_cachep;
+static void vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip);
 
 
 #ifdef DIAGNOSTIC
@@ -137,35 +138,41 @@ static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *
  *  buffercache.  This function should not be used outside the
  *  read_super() method, otherwise the data may be incoherent.
  */
-struct vxfs_inode_info *
+struct inode *
 vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
 {
 	struct buffer_head		*bp;
 	u_long				block, offset;
+	struct inode *ip;
 
 	block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
 	offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
+
+	ip = new_inode(sbp);
+	if (!ip)
+		return ERR_PTR(-ENOMEM);
+
 	bp = sb_bread(sbp, block);
+	ip->i_ino = get_next_ino();
+	ip->i_mapping->a_ops = &vxfs_aops;
 
 	if (bp && buffer_mapped(bp)) {
-		struct vxfs_inode_info	*vip;
-		struct vxfs_dinode	*dip;
+		struct vxfs_inode_info	*vip = VXFS_INO(ip);
+		struct vxfs_dinode	*dip = (struct vxfs_dinode *)(bp->b_data + offset);
 
-		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
-			goto fail;
-		dip = (struct vxfs_dinode *)(bp->b_data + offset);
 		dip2vip_cpy(vip, dip, VXFS_SBI(sbp)->byte_order);
+		vxfs_iinit(ip, vip);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
-		brelse(bp);
-		return (vip);
+	} else {
+		printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
+		iput(ip);
+		ip = NULL;
 	}
-
-fail:
-	printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
 	brelse(bp);
-	return NULL;
+
+	return ip;
 }
 
 /**
@@ -180,21 +187,18 @@ fail:
  *  Returns the matching VxFS inode on success, else an error code.
  */
 static struct vxfs_inode_info *
-__vxfs_iget(ino_t ino, struct inode *ilistp)
+__vxfs_iget(struct inode *ip, struct inode *ilistp, ino_t ino)
 {
-	struct page			*pp;
-	u_long				offset;
+	struct page	*pp;
+	u_long offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
 
-	offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
 	pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
 
 	if (!IS_ERR(pp)) {
-		struct vxfs_inode_info	*vip;
+		struct vxfs_inode_info	*vip = VXFS_INO(ip);
 		struct vxfs_dinode	*dip;
 		caddr_t			kaddr = (char *)page_address(pp);
 
-		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
-			goto fail;
 		dip = (struct vxfs_dinode *)(kaddr + offset);
 		dip2vip_cpy(vip, dip, VXFS_SBI(ilistp->i_sb)->byte_order);
 #ifdef DIAGNOSTIC
@@ -206,11 +210,6 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
 
 	printk(KERN_WARNING "vxfs: error on page %p\n", pp);
 	return ERR_CAST(pp);
-
-fail:
-	printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
-	vxfs_put_page(pp);
-	return ERR_PTR(-ENOMEM);
 }
 
 /**
@@ -223,13 +222,24 @@ fail:
  *  the structural inode list.
  *  Returns the matching VxFS inode on success, else a NULL pointer.
  */
-struct vxfs_inode_info *
+struct inode *
 vxfs_stiget(struct super_block *sbp, ino_t ino)
 {
-	struct vxfs_inode_info *vip;
+	struct inode *ip = new_inode(sbp);
+	struct vxfs_inode_info *ii;
 
-	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
-	return IS_ERR(vip) ? NULL : vip;
+	if (!ip)
+		return NULL;
+
+	ip->i_ino = get_next_ino();
+	ip->i_mapping->a_ops = &vxfs_aops;
+	ii = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_stilist, ino);
+	if (IS_ERR(ii)) {
+		iput(ip);
+	} else {
+		vxfs_iinit(ip, ii);
+	}
+	return IS_ERR(ii) ? NULL : ip;
 }
 
 /**
@@ -297,41 +307,6 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
 	
 }
 
-/**
- * vxfs_get_fake_inode - get fake inode structure
- * @sbp:		filesystem superblock
- * @vip:		fspriv inode
- *
- * Description:
- *  vxfs_fake_inode gets a fake inode (not in the inode hash) for a
- *  superblock, vxfs_inode pair.
- *  Returns the filled VFS inode.
- */
-struct inode *
-vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
-{
-	struct inode			*ip = NULL;
-
-	if ((ip = new_inode(sbp))) {
-		ip->i_ino = get_next_ino();
-		vxfs_iinit(ip, vip);
-		ip->i_mapping->a_ops = &vxfs_aops;
-	}
-	return (ip);
-}
-
-/**
- * vxfs_put_fake_inode - free faked inode
- * *ip:			VFS inode
- *
- * Description:
- *  vxfs_put_fake_inode frees all data associated with @ip.
- */
-void
-vxfs_put_fake_inode(struct inode *ip)
-{
-	iput(ip);
-}
 
 /**
  * vxfs_iget - get an inode
@@ -355,7 +330,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
 	if (!(ip->i_state & I_NEW))
 		return ip;
 
-	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
+	vip = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_ilist, ino);
 	if (IS_ERR(vip)) {
 		iget_failed(ip);
 		return ERR_CAST(vip);
@@ -393,10 +368,9 @@ 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);
-	void *priv = inode->i_private;
+	struct vxfs_vfs_inode *i = container_of(inode, struct vxfs_vfs_inode, ino);
 
-	inode->i_private = NULL;
-	kmem_cache_free(vxfs_inode_cachep, priv);
+	kmem_cache_free(vxfs_inode_cachep, i);
 }
 
 void vxfs_destroy_inode(struct inode *ip)
@@ -405,11 +379,11 @@ void vxfs_destroy_inode(struct inode *ip)
 }
 
 /**
- * vxfs_evict_inode - remove inode from main memory
+ * vxfs_evict_inode - commit inode buffers if needed, may delete on-disk inode.
  * @ip:		inode to discard.
  *
  * Description:
- *  vxfs_evict_inode() is called on the final iput
+ *  vxfs_evict_inode() may be called on the final iput.
  */
 void
 vxfs_evict_inode(struct inode *ip)
@@ -420,17 +394,27 @@ vxfs_evict_inode(struct inode *ip)
 }
 
 
-void vxfs_inode_info_free(struct vxfs_inode_info *vip)
+
+
+struct inode *vxfs_inode_alloc(struct super_block *sb)
 {
-	kmem_cache_free(vxfs_inode_cachep, vip);
+	struct vxfs_vfs_inode *i = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
+
+	return i ? &i->ino : NULL;
 }
 
+static void vxfs_inode_constructor(void *ptr)
+{
+	struct vxfs_vfs_inode *i = (struct vxfs_vfs_inode *) ptr;
+
+	inode_init_once(&i->ino);
+}
 
 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);
+		sizeof(struct vxfs_vfs_inode), 0,
+		SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, vxfs_inode_constructor);
 
 	return vxfs_inode_cachep ? 0 : -ENOMEM;
 }
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 9a2c376..bba04a8 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -37,7 +37,6 @@
  * inodes of the Veritas Filesystem.
  */
 
-
 #define VXFS_ISIZE		0x100		/* Inode size */
 
 #define VXFS_NDADDR		10		/* Number of direct addrs in inode */
@@ -154,6 +153,16 @@ struct vxfs_dinode {
  */
 #define vxfs_inode_info	vxfs_dinode
 
+struct vxfs_vfs_inode {
+	struct inode ino;
+	struct vxfs_inode_info cpufs_ino;
+	/*
+	 * the cpufs_ino contains copy of on-disk inode but
+	 * it is cpu-endian formatted and it might be not aligned
+	 */
+};
+
+
 #define vii_mode	vdi_mode
 #define vii_uid		vdi_uid
 #define vii_gid		vdi_gid
@@ -177,4 +186,13 @@ struct vxfs_dinode {
 #define vii_ext4	vdi_org.ext4
 #define vii_typed	vdi_org.typed
 
+/*
+ * Get filesystem private data from VFS inode.
+ */
+static inline struct vxfs_inode_info *VXFS_INO(struct inode *i)
+{
+	return &(container_of(i, struct vxfs_vfs_inode, ino))->cpufs_ino;
+}
+
+
 #endif /* _VXFS_INODE_H_ */
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 9525818..7bd76ab 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 = {
+	.alloc_inode = vxfs_inode_alloc,
 	.destroy_inode = vxfs_destroy_inode,
 	.evict_inode =		vxfs_evict_inode,
 	.put_super =		vxfs_put_super,
@@ -80,9 +81,9 @@ vxfs_put_super(struct super_block *sbp)
 {
 	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
 
-	vxfs_put_fake_inode(infp->vsi_fship);
-	vxfs_put_fake_inode(infp->vsi_ilist);
-	vxfs_put_fake_inode(infp->vsi_stilist);
+	iput(infp->vsi_fship);
+	iput(infp->vsi_ilist);
+	iput(infp->vsi_stilist);
 
 	brelse(infp->vsi_bp);
 	kfree(infp);
@@ -259,17 +260,18 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 		goto out;
 	}
 
+
 	if (vxfs_read_olt(sbp, bsize)) {
 		printk(KERN_WARNING "vxfs: unable to read olt\n");
 		goto out;
 	}
 
+	sbp->s_op = &vxfs_super_ops;
 	if (vxfs_read_fshead(sbp)) {
 		printk(KERN_WARNING "vxfs: unable to read fshead\n");
 		goto out;
 	}
 
-	sbp->s_op = &vxfs_super_ops;
 	root = vxfs_iget(sbp, VXFS_ROOT_INO);
 	if (IS_ERR(root)) {
 		ret = PTR_ERR(root);
@@ -284,9 +286,9 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 	return 0;
 	
 out_free_ilist:
-	vxfs_put_fake_inode(infp->vsi_fship);
-	vxfs_put_fake_inode(infp->vsi_ilist);
-	vxfs_put_fake_inode(infp->vsi_stilist);
+	iput(infp->vsi_fship);
+	iput(infp->vsi_ilist);
+	iput(infp->vsi_stilist);
 out:
 	brelse(infp->vsi_bp);
 	kfree(infp);
-- 
1.7.3.4

>From ce7bce806419c15f7dad3c9a20b59318566c79ef Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Sat, 28 May 2016 20:55:19 +0200
Subject: [PATCH 7/7] the credits


Signed-off-by: KB <kb@sysmikro.com.pl>
---
 fs/freevxfs/Kconfig       |   10 +++++++++-
 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 +++++-
 6 files changed, 29 insertions(+), 2 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.
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 8124a10..54a1d02 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 b24cb8c..2fc5280 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 ee0ca04..4d84f5d 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 7bd76ab..964d402 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



On Thu, 2016-05-26 at 16:45 +0200, Krzysztof Błaszkowski wrote:
> Hi,
> 
> So then let it roll. 
> 
> Thanks
> 
> >From 3d3b4e1ed5df014ae191e0566ff86a17d7d9ac05 Mon Sep 17 00:00:00
> 2001
> From: KB <kb@sysmikro.com.pl> 
-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-05-28 19:40 ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
@ 2016-05-30 11:19   ` Carlos Maiolino
  2016-05-30 11:54     ` Krzysztof Błaszkowski
  2016-05-31 12:25   ` Christoph Hellwig
  1 sibling, 1 reply; 21+ messages in thread
From: Carlos Maiolino @ 2016-05-30 11:19 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: kb


Hi Krzysztof,

This is more a style review than functionality itself (although I've added a few
comments in this context too).

But, for now on, please:
	- Submit each patch in a single e-mail, it's much easier to review the
	  patches in a single context, than have 7 patches and 2k lines of
	  different contexts in a single e-mail.
	- Fix the kernel style and indentation problems.

If you need help regarding sending the patches in the right format to the list,
let me know off-list, since, I don't believe the list is the right place to keep
discussing how to properly send patches to the list and kernel coding style
stuff.
And people will be much happier reviewing properly formatted code, and different
patches in single e-mails.

I've added some comments below

On Sat, May 28, 2016 at 09:40:27PM +0200, Krzysztof Błaszkowski wrote:
> Hi Carlos,
> 
> Christoph told me that you can look at these patches I prepared.
> 
> The patchset has follwing changes since previous release:
> - preprocesor expanded local macros,
> - merged credits patches,
> - struct inode placed inside local structure vxfs_vfs_inode.
> 
> Last change is the most complex and makes an impact on e.g.
> read_fshead() and actually it is only one proper solution. A file system
> must not use destroy_inode callback without alloc_inode. if it does
> then inode structures will not be returned to fs/inode.c: inode_cachep.
> 
> From 56ac335ff74706be4c3e30925d2c8c47a19eab9e Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Sat, 28 May 2016 20:55:19 +0200
> Subject: [PATCH 1/7] cpu endianess vs file system, two locations of the sb
> 
> 
> 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  |   57 +++++++++++++++++++++++-
>  fs/freevxfs/vxfs_inode.h  |    8 ++--
>  fs/freevxfs/vxfs_lookup.c |   15 +++++-
>  fs/freevxfs/vxfs_olt.c    |   15 +++---
>  fs/freevxfs/vxfs_super.c  |  108 +++++++++++++++++++++++++++++++++------------
>  8 files changed, 221 insertions(+), 56 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;

These definitions are still not aligned. What Christoph meant before, was
indentation alignment.

> +};
> +
> +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;
>  
Indentation please.

>  	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..05cced0 100644
> --- a/fs/freevxfs/vxfs_fshead.c
> +++ b/fs/freevxfs/vxfs_fshead.c
> @@ -60,6 +60,29 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
>  }
>  #endif
>  
> +
> +static inline void dbh2fhp(struct vxfs_fsh *fhp, void *_dbh, int bo)
> +{
> + struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
> +
> + fhp->fsh_version = fs32_to_cpu(bo, dbh->fsh_version);
> + fhp->fsh_fsindex = fs32_to_cpu(bo, dbh->fsh_fsindex);
> + fhp->fsh_time = fs32_to_cpu(bo, dbh->fsh_time);
> + fhp->fsh_utime = fs32_to_cpu(bo, dbh->fsh_utime);
> + fhp->fsh_extop = fs32_to_cpu(bo, dbh->fsh_extop);
> + fhp->fsh_ninodes = fs32_to_cpu(bo, dbh->fsh_ninodes);
> + fhp->fsh_nau = fs32_to_cpu(bo, dbh->fsh_nau);
> + fhp->fsh_old_ilesize = fs32_to_cpu(bo, dbh->fsh_old_ilesize);
> + fhp->fsh_dflags = fs32_to_cpu(bo, dbh->fsh_dflags);
> + fhp->fsh_quota = fs32_to_cpu(bo, dbh->fsh_quota);
> + fhp->fsh_maxinode = fs32_to_cpu(bo, dbh->fsh_maxinode);
> + fhp->fsh_iauino = fs32_to_cpu(bo, dbh->fsh_iauino);
> + fhp->fsh_ilistino[0] = fs32_to_cpu(bo, dbh->fsh_ilistino[0]);
> + fhp->fsh_ilistino[1] = fs32_to_cpu(bo, dbh->fsh_ilistino[1]);
> + fhp->fsh_lctino = fs32_to_cpu(bo, dbh->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..86db3c2 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -67,6 +67,59 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
>  }
>  #endif
>  
> +static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip, int bo)
> +{
> + int j;
> +
> + vip->vdi_mode = fs32_to_cpu(bo, dip->vdi_mode);
> + vip->vdi_nlink = fs32_to_cpu(bo, dip->vdi_nlink);
> + vip->vdi_uid = fs32_to_cpu(bo, dip->vdi_uid);
> + vip->vdi_gid = fs32_to_cpu(bo, dip->vdi_gid);
> + vip->vdi_size = fs64_to_cpu(bo, dip->vdi_size);
> + vip->vdi_atime = fs32_to_cpu(bo, dip->vdi_atime);
> + vip->vdi_autime = fs32_to_cpu(bo, dip->vdi_autime);
> + vip->vdi_mtime = fs32_to_cpu(bo, dip->vdi_mtime);
> + vip->vdi_mutime = fs32_to_cpu(bo, dip->vdi_mutime);
> + vip->vdi_ctime = fs32_to_cpu(bo, dip->vdi_ctime);
> + vip->vdi_cutime = fs32_to_cpu(bo, dip->vdi_cutime);
> + vip->vdi_aflags = dip->vdi_aflags;
> + vip->vdi_orgtype = dip->vdi_orgtype;
> + vip->vdi_eopflags = fs16_to_cpu(bo, dip->vdi_eopflags);
> + vip->vdi_eopdata = fs32_to_cpu(bo, dip->vdi_eopdata);
> +
> + vip->vdi_ftarea.i_regular.reserved = fs32_to_cpu(bo, dip->vdi_ftarea.i_regular.reserved);
> + vip->vdi_ftarea.i_regular.fixextsize = fs32_to_cpu(bo, dip->vdi_ftarea.i_regular.fixextsize);
> + vip->vdi_blocks = fs32_to_cpu(bo, dip->vdi_blocks);
> + vip->vdi_gen = fs32_to_cpu(bo, dip->vdi_gen);
> + vip->vdi_version = fs64_to_cpu(bo, dip->vdi_version);
> +
> + switch (dip->vdi_orgtype) {
> + case VXFS_ORG_EXT4:
> +  vip->vdi_org.ext4.ve4_spare = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_spare);
> +  vip->vdi_org.ext4.ve4_indsize = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_indsize);
> +  for (j = 0; j < 2; j++) {
> +   vip->vdi_org.ext4.ve4_indir[j] = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_indir[j]);
> +  }
> +  for (j = 0; j < 10; j++) {
> +   vip->vdi_org.ext4.ve4_direct[j].extent = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_direct[j].extent);
> +   vip->vdi_org.ext4.ve4_direct[j].size = fs32_to_cpu(bo, dip->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 < 6; j++) {
> +   vip->vdi_org.typed[j].vt_hdr = fs64_to_cpu(bo, dip->vdi_org.typed[j].vt_hdr);
> +   vip->vdi_org.typed[j].vt_block = fs32_to_cpu(bo, dip->vdi_org.typed[j].vt_block);
> +   vip->vdi_org.typed[j].vt_size = fs32_to_cpu(bo, dip->vdi_org.typed[j].vt_size);
> +  }
> +  break;
> + };

Please, indent this switch statement, follow the 80columns rule (i.e. lines
should not have more than 80columns).

> +
> + vip->vdi_iattrino = fs32_to_cpu(bo, dip->vdi_iattrino);
> +}
> +
>  
>  /**
>   * vxfs_blkiget - find inode based on extent #
> @@ -101,7 +154,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 +196,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;
> +
Indentation.

>  
>  	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..6a69eb0 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,53 @@ 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 %08x at +%d\n",
> +					rsbp->vs_magic, blk);

				Please, avoid +80 columns, you did it in the
				printk above, no reason to not do it here too.

> +			break;
> +		}
> +
> +		rc = 0;
> +		infp->vsi_raw = rsbp;
> +		infp->vsi_bp = bp;
> +	} while (0);

	I'm not the best person to give a review here, but, I wouldn't use a
	do.while(0), but instead, goto error_X: statements and assign the error
	codes according to the conditional results, instead of re-assigning the
	error code if the previous code wasn't correct.
	But again, a POV of another person will be better.

> +
> +	if (rc) {
> +		infp->vsi_raw = NULL;
> +		infp->vsi_bp = NULL;
> +		brelse(bp);
> +	}
> +
> +	return rc;
> +}
> +
> +
> +static const char * const vxfs_subtypes[] = {
> +	"SCO",
> +	"HP-UX(be)"
> +};
> +
>  /**
>   * vxfs_read_super - read superblock into memory and initialize filesystem
>   * @sbp:		VFS superblock (to fill)
> @@ -149,10 +197,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;
>  
Indentation, goo opportunity to fix the another non-indented fields too.

>  	sbp->s_flags |= MS_RDONLY;
>  
> @@ -162,48 +210,50 @@ 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 */
> +			sbp->s_subtype = kstrdup(vxfs_subtypes[0], GFP_KERNEL);
> +			break;
> +		}
> +
> +		if (!vxfs_try_sb_magic(sbp, 8, cpu_to_be32(VXFS_SUPER_MAGIC))) {
> +			infp->byte_order = BO_BE; /* HP-UX pa-risc likely */
> +			sbp->s_subtype = kstrdup(vxfs_subtypes[1], GFP_KERNEL);
> +			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: blocksize: %d\n", rsbp->vs_bsize);
> +	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
> +	printk(KERN_DEBUG "vxfs: blocksize: %d\n",
> +	    fs32_to_cpu(infp->byte_order, 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 +287,7 @@ out_free_ilist:
>  	vxfs_put_fake_inode(infp->vsi_ilist);
>  	vxfs_put_fake_inode(infp->vsi_stilist);
>  out:
> -	brelse(bp);
> +	brelse(infp->vsi_bp);
>  	kfree(infp);
>  	return ret;
>  }
> -- 
> 1.7.3.4
> 
> From 0d0c7ed061edd846bd032fe1073d61169299a435 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Sat, 28 May 2016 20:55:19 +0200
> Subject: [PATCH 2/7] missing kfree and kfree on kmem_cache obj

Missing kfree and kfree?

"Missing to kfree objects" sounds better IMHO
> 
> 
> 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);

Indentation

>  
>  /* 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 05cced0..c4c6a86 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 86db3c2..9590f79 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -411,3 +411,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
> 
> From c595f46ad63d71ac26dfc3ef23d87e372ac85426 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Sat, 28 May 2016 20:55:19 +0200
> Subject: [PATCH 3/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 9590f79..f91a50c 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -393,7 +393,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);
>  }
>  
>  /**
> @@ -401,17 +409,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 6a69eb0..500087a 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,

Indentation

>  	.evict_inode =		vxfs_evict_inode,
>  	.put_super =		vxfs_put_super,
>  	.statfs =		vxfs_statfs,
> -- 
> 1.7.3.4
> 
> From b02ffccdff5ca82922bf09cdcf1a9ea4471bbb62 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Sat, 28 May 2016 20:55:19 +0200
> Subject: [PATCH 4/7] refactoring of vxfs_readdir() 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;

Indentation
> +
> +	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;
> +		}

		Kernel coding style states to not use braces with single-line if
		conditionals.

> +		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
> 
> From eceb47a770b80d7f46a089f6a1744d66f0601e77 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Sat, 28 May 2016 20:55:19 +0200
> Subject: [PATCH 5/7] static inode_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 f91a50c..1e20823 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
> @@ -424,3 +424,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 500087a..9525818 100644
> --- a/fs/freevxfs/vxfs_super.c
> +++ b/fs/freevxfs/vxfs_super.c
> @@ -315,29 +315,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
> 
> From 2915ed2c92dd349203070eea8970fd4fb62ba5b4 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Sat, 28 May 2016 20:55:19 +0200
> Subject: [PATCH 6/7] struct inode embedded in vxfs_vfs_inode
> 
> struct vxfs_vfs_inode is allocated from vxfs_inode_cachep
> and vfs inode is initialized by inode_constructor().
> sb->s_op must be set before read_fshead() otherwise 
> 3 inodes will be allocated from common inode_cachep.
> 
> 
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
>  fs/freevxfs/vxfs.h        |    8 ---
>  fs/freevxfs/vxfs_bmap.c   |    5 +-
>  fs/freevxfs/vxfs_extern.h |   15 +++---
>  fs/freevxfs/vxfs_fshead.c |   48 +++++++----------
>  fs/freevxfs/vxfs_inode.c  |  130 ++++++++++++++++++++-------------------------
>  fs/freevxfs/vxfs_inode.h  |   20 +++++++-
>  fs/freevxfs/vxfs_super.c  |   16 +++---
>  7 files changed, 114 insertions(+), 128 deletions(-)
> 
> diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> index 5dc8949..8124a10 100644
> --- a/fs/freevxfs/vxfs.h
> +++ b/fs/freevxfs/vxfs.h
> @@ -38,7 +38,6 @@
>   */
>  #include <linux/types.h>
>  
> -
>  /*
>   * Data types for use with the VxFS ondisk format.
>   */
> @@ -270,13 +269,6 @@ enum {
>  #define VXFS_ISIMMED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
>  #define VXFS_ISTYPED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
>  
> -
> -/*
> - * Get filesystem private data from VFS inode.
> - */
> -#define VXFS_INO(ip) \
> -	((struct vxfs_inode_info *)(ip)->i_private)
> -
>  /*
>   * Get filesystem private data from VFS superblock.
>   */
> diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
> index 95afd98..e39aea4 100644
> --- a/fs/freevxfs/vxfs_bmap.c
> +++ b/fs/freevxfs/vxfs_bmap.c
> @@ -97,8 +97,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
>  
>  		brelse(buf);
>  		return bno;
> -	} else
> -		printk(KERN_WARNING "no matching indir?");
> +	} else {
> +		printk(KERN_WARNING "%s:%d no matching indir?\n", __func__, __LINE__);
> +	}
>  
>  	return 0;
>  
> diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> index cc43fd0..9648735 100644
> --- a/fs/freevxfs/vxfs_extern.h
> +++ b/fs/freevxfs/vxfs_extern.h
> @@ -56,17 +56,16 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
>  /* vxfs_inode.c */
>  extern const struct address_space_operations vxfs_immed_aops;
>  extern void			vxfs_dumpi(struct vxfs_inode_info *, ino_t);
> -extern struct inode *		vxfs_get_fake_inode(struct super_block *,
> -					struct vxfs_inode_info *);
> -extern void			vxfs_put_fake_inode(struct inode *);
> -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);
> +
> +extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
> +extern struct inode *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 int vxfs_ii_cache_init(void);
>  extern void vxfs_ii_cache_destroy(void);
> +extern struct inode *vxfs_inode_alloc(struct super_block *sb);
>  
>  
>  /* vxfs_lookup.c */
> diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> index c4c6a86..b24cb8c 100644
> --- a/fs/freevxfs/vxfs_fshead.c
> +++ b/fs/freevxfs/vxfs_fshead.c
> @@ -131,31 +131,26 @@ vxfs_read_fshead(struct super_block *sbp)
>  {
>  	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
>  	struct vxfs_fsh			*pfp, *sfp;
> -	struct vxfs_inode_info		*vip, *tip;
> +	struct inode *ip1;
> +	struct inode *ip2;

Indentation.

>  
> -	vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
> -	if (!vip) {
> +	infp->vsi_fship = ip1 = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
> +	if (IS_ERR(ip1)) {
>  		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
>  		return -EINVAL;
>  	}
> -	if (!VXFS_ISFSH(vip)) {
> +
> +	if (!VXFS_ISFSH(VXFS_INO(ip1))) {
>  		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
> -				vip->vii_mode & VXFS_TYPE_MASK); 
> +				VXFS_INO(ip1)->vii_mode & VXFS_TYPE_MASK);
>  		goto out_free_fship;
>  	}
>  
> -
>  #ifdef DIAGNOSTIC
>  	printk("vxfs: fsh inode dump:\n");
> -	vxfs_dumpi(vip, infp->vsi_fshino);
> +	vxfs_dumpi(VXFS_INO(ip1), infp->vsi_fshino);
>  #endif
>  
> -	infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
> -	if (!infp->vsi_fship) {
> -		printk(KERN_ERR "vxfs: unable to get fsh inode\n");
> -		goto out_free_fship;
> -	}
> -
>  	sfp = vxfs_getfsh(infp->vsi_fship, 0);
>  	if (!sfp) {
>  		printk(KERN_ERR "vxfs: unable to get structural fsh\n");
> @@ -176,31 +171,25 @@ vxfs_read_fshead(struct super_block *sbp)
>  	vxfs_dumpfsh(pfp);
>  #endif
>  
> -	tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
> -	if (!tip)
> -		goto out_free_pfp;
> +	infp->vsi_stilist =
> +		ip2 = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
>  
> -	infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
> -	if (!infp->vsi_stilist) {
> -		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
> -		vxfs_inode_info_free(tip);
> +	if (IS_ERR(ip2)) {
>  		goto out_free_pfp;
>  	}
> +
>  	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
>  		printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n",
>  				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 
>  		goto out_iput_stilist;
>  	}
>  
> -	tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
> -	if (!tip)
> -		goto out_iput_stilist;
> -	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
> -	if (!infp->vsi_ilist) {
> +	infp->vsi_ilist = ip2 = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
> +	if (IS_ERR(ip2)) {
>  		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
> -		vxfs_inode_info_free(tip);
>  		goto out_iput_stilist;
>  	}
> +
>  	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
>  		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
>  				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
> @@ -220,9 +209,10 @@ vxfs_read_fshead(struct super_block *sbp)
>   out_free_sfp:
>   	kfree(sfp);
>   out_iput_fship:
> -	iput(infp->vsi_fship);
> -	return -EINVAL;
>   out_free_fship:
> -	vxfs_inode_info_free(vip);
> +	iput(infp->vsi_fship);
> +	infp->vsi_stilist = NULL;
> +	infp->vsi_ilist = NULL;
> +	infp->vsi_fship = NULL;
>  	return -EINVAL;
>  }
> diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> index 1e20823..ee0ca04 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -42,6 +42,7 @@
>  
>  
>  static struct kmem_cache *vxfs_inode_cachep;
> +static void vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip);
>  
>  
>  #ifdef DIAGNOSTIC
> @@ -137,35 +138,41 @@ static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *
>   *  buffercache.  This function should not be used outside the
>   *  read_super() method, otherwise the data may be incoherent.
>   */
> -struct vxfs_inode_info *
> +struct inode *
>  vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
>  {
>  	struct buffer_head		*bp;
>  	u_long				block, offset;
> +	struct inode *ip;
>  
>  	block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
>  	offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
> +
> +	ip = new_inode(sbp);
> +	if (!ip)
> +		return ERR_PTR(-ENOMEM);
> +
>  	bp = sb_bread(sbp, block);
> +	ip->i_ino = get_next_ino();
> +	ip->i_mapping->a_ops = &vxfs_aops;
>  
>  	if (bp && buffer_mapped(bp)) {
> -		struct vxfs_inode_info	*vip;
> -		struct vxfs_dinode	*dip;
> +		struct vxfs_inode_info	*vip = VXFS_INO(ip);
> +		struct vxfs_dinode	*dip = (struct vxfs_dinode *)(bp->b_data + offset);
>  
> -		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> -			goto fail;
> -		dip = (struct vxfs_dinode *)(bp->b_data + offset);
>  		dip2vip_cpy(vip, dip, VXFS_SBI(sbp)->byte_order);
> +		vxfs_iinit(ip, vip);
>  #ifdef DIAGNOSTIC
>  		vxfs_dumpi(vip, ino);
>  #endif
> -		brelse(bp);
> -		return (vip);
> +	} else {
> +		printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
> +		iput(ip);
> +		ip = NULL;
>  	}
> -
> -fail:
> -	printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
>  	brelse(bp);
> -	return NULL;
> +
> +	return ip;
>  }
>  
>  /**
> @@ -180,21 +187,18 @@ fail:
>   *  Returns the matching VxFS inode on success, else an error code.
>   */
>  static struct vxfs_inode_info *
> -__vxfs_iget(ino_t ino, struct inode *ilistp)
> +__vxfs_iget(struct inode *ip, struct inode *ilistp, ino_t ino)
>  {
> -	struct page			*pp;
> -	u_long				offset;
> +	struct page	*pp;
Indentation

> +	u_long offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
>  
> -	offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
>  	pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
>  
>  	if (!IS_ERR(pp)) {
> -		struct vxfs_inode_info	*vip;
> +		struct vxfs_inode_info	*vip = VXFS_INO(ip);
>  		struct vxfs_dinode	*dip;
>  		caddr_t			kaddr = (char *)page_address(pp);
>  
> -		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> -			goto fail;
>  		dip = (struct vxfs_dinode *)(kaddr + offset);
>  		dip2vip_cpy(vip, dip, VXFS_SBI(ilistp->i_sb)->byte_order);
>  #ifdef DIAGNOSTIC
> @@ -206,11 +210,6 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
>  
>  	printk(KERN_WARNING "vxfs: error on page %p\n", pp);
>  	return ERR_CAST(pp);
> -
> -fail:
> -	printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
> -	vxfs_put_page(pp);
> -	return ERR_PTR(-ENOMEM);
>  }
>  
>  /**
> @@ -223,13 +222,24 @@ fail:
>   *  the structural inode list.
>   *  Returns the matching VxFS inode on success, else a NULL pointer.
>   */
> -struct vxfs_inode_info *
> +struct inode *
>  vxfs_stiget(struct super_block *sbp, ino_t ino)
>  {
> -	struct vxfs_inode_info *vip;
> +	struct inode *ip = new_inode(sbp);
> +	struct vxfs_inode_info *ii;
>  
> -	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
> -	return IS_ERR(vip) ? NULL : vip;
> +	if (!ip)
> +		return NULL;
> +
> +	ip->i_ino = get_next_ino();
> +	ip->i_mapping->a_ops = &vxfs_aops;
> +	ii = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_stilist, ino);
> +	if (IS_ERR(ii)) {
> +		iput(ip);
> +	} else {
> +		vxfs_iinit(ip, ii);
> +	}
> +	return IS_ERR(ii) ? NULL : ip;
>  }
>  
>  /**
> @@ -297,41 +307,6 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
>  	
>  }
>  
> -/**
> - * vxfs_get_fake_inode - get fake inode structure
> - * @sbp:		filesystem superblock
> - * @vip:		fspriv inode
> - *
> - * Description:
> - *  vxfs_fake_inode gets a fake inode (not in the inode hash) for a
> - *  superblock, vxfs_inode pair.
> - *  Returns the filled VFS inode.
> - */
> -struct inode *
> -vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
> -{
> -	struct inode			*ip = NULL;
> -
> -	if ((ip = new_inode(sbp))) {
> -		ip->i_ino = get_next_ino();
> -		vxfs_iinit(ip, vip);
> -		ip->i_mapping->a_ops = &vxfs_aops;
> -	}
> -	return (ip);
> -}
> -
> -/**
> - * vxfs_put_fake_inode - free faked inode
> - * *ip:			VFS inode
> - *
> - * Description:
> - *  vxfs_put_fake_inode frees all data associated with @ip.
> - */
> -void
> -vxfs_put_fake_inode(struct inode *ip)
> -{
> -	iput(ip);
> -}
>  
>  /**
>   * vxfs_iget - get an inode
> @@ -355,7 +330,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
>  	if (!(ip->i_state & I_NEW))
>  		return ip;
>  
> -	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
> +	vip = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_ilist, ino);
>  	if (IS_ERR(vip)) {
>  		iget_failed(ip);
>  		return ERR_CAST(vip);
> @@ -393,10 +368,9 @@ 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);
> -	void *priv = inode->i_private;
> +	struct vxfs_vfs_inode *i = container_of(inode, struct vxfs_vfs_inode, ino);
>  
> -	inode->i_private = NULL;
> -	kmem_cache_free(vxfs_inode_cachep, priv);
> +	kmem_cache_free(vxfs_inode_cachep, i);
>  }
>  
>  void vxfs_destroy_inode(struct inode *ip)
> @@ -405,11 +379,11 @@ void vxfs_destroy_inode(struct inode *ip)
>  }
>  
>  /**
> - * vxfs_evict_inode - remove inode from main memory
> + * vxfs_evict_inode - commit inode buffers if needed, may delete on-disk inode.
>   * @ip:		inode to discard.
>   *
>   * Description:
> - *  vxfs_evict_inode() is called on the final iput
> + *  vxfs_evict_inode() may be called on the final iput.
>   */
>  void
>  vxfs_evict_inode(struct inode *ip)
> @@ -420,17 +394,27 @@ vxfs_evict_inode(struct inode *ip)
>  }
>  
>  
> -void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> +
> +
> +struct inode *vxfs_inode_alloc(struct super_block *sb)
>  {
> -	kmem_cache_free(vxfs_inode_cachep, vip);
> +	struct vxfs_vfs_inode *i = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
> +
> +	return i ? &i->ino : NULL;
>  }
>  
> +static void vxfs_inode_constructor(void *ptr)
> +{
> +	struct vxfs_vfs_inode *i = (struct vxfs_vfs_inode *) ptr;
> +
> +	inode_init_once(&i->ino);
> +}
>  
>  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);
> +		sizeof(struct vxfs_vfs_inode), 0,
> +		SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, vxfs_inode_constructor);
>  
>  	return vxfs_inode_cachep ? 0 : -ENOMEM;
>  }
> diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
> index 9a2c376..bba04a8 100644
> --- a/fs/freevxfs/vxfs_inode.h
> +++ b/fs/freevxfs/vxfs_inode.h
> @@ -37,7 +37,6 @@
>   * inodes of the Veritas Filesystem.
>   */
>  
> -
>  #define VXFS_ISIZE		0x100		/* Inode size */
>  
>  #define VXFS_NDADDR		10		/* Number of direct addrs in inode */
> @@ -154,6 +153,16 @@ struct vxfs_dinode {
>   */
>  #define vxfs_inode_info	vxfs_dinode
>  
> +struct vxfs_vfs_inode {
> +	struct inode ino;
> +	struct vxfs_inode_info cpufs_ino;
> +	/*
> +	 * the cpufs_ino contains copy of on-disk inode but
> +	 * it is cpu-endian formatted and it might be not aligned
> +	 */
> +};
> +
> +
>  #define vii_mode	vdi_mode
>  #define vii_uid		vdi_uid
>  #define vii_gid		vdi_gid
> @@ -177,4 +186,13 @@ struct vxfs_dinode {
>  #define vii_ext4	vdi_org.ext4
>  #define vii_typed	vdi_org.typed
>  
> +/*
> + * Get filesystem private data from VFS inode.
> + */
> +static inline struct vxfs_inode_info *VXFS_INO(struct inode *i)
> +{
> +	return &(container_of(i, struct vxfs_vfs_inode, ino))->cpufs_ino;
> +}
> +
> +
>  #endif /* _VXFS_INODE_H_ */
> diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> index 9525818..7bd76ab 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 = {
> +	.alloc_inode = vxfs_inode_alloc,
>  	.destroy_inode = vxfs_destroy_inode,
>  	.evict_inode =		vxfs_evict_inode,
>  	.put_super =		vxfs_put_super,

Please indent everything here
> @@ -80,9 +81,9 @@ vxfs_put_super(struct super_block *sbp)
>  {
>  	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
>  
> -	vxfs_put_fake_inode(infp->vsi_fship);
> -	vxfs_put_fake_inode(infp->vsi_ilist);
> -	vxfs_put_fake_inode(infp->vsi_stilist);
> +	iput(infp->vsi_fship);
> +	iput(infp->vsi_ilist);
> +	iput(infp->vsi_stilist);
>  
>  	brelse(infp->vsi_bp);
>  	kfree(infp);
> @@ -259,17 +260,18 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
>  		goto out;
>  	}
>  
> +
>  	if (vxfs_read_olt(sbp, bsize)) {
>  		printk(KERN_WARNING "vxfs: unable to read olt\n");
>  		goto out;
>  	}
>  
> +	sbp->s_op = &vxfs_super_ops;
>  	if (vxfs_read_fshead(sbp)) {
>  		printk(KERN_WARNING "vxfs: unable to read fshead\n");
>  		goto out;
>  	}
>  
> -	sbp->s_op = &vxfs_super_ops;
>  	root = vxfs_iget(sbp, VXFS_ROOT_INO);
>  	if (IS_ERR(root)) {
>  		ret = PTR_ERR(root);
> @@ -284,9 +286,9 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
>  	return 0;
>  	
>  out_free_ilist:
> -	vxfs_put_fake_inode(infp->vsi_fship);
> -	vxfs_put_fake_inode(infp->vsi_ilist);
> -	vxfs_put_fake_inode(infp->vsi_stilist);
> +	iput(infp->vsi_fship);
> +	iput(infp->vsi_ilist);
> +	iput(infp->vsi_stilist);
>  out:
>  	brelse(infp->vsi_bp);
>  	kfree(infp);
> -- 
> 1.7.3.4
> 
> From ce7bce806419c15f7dad3c9a20b59318566c79ef Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Sat, 28 May 2016 20:55:19 +0200
> Subject: [PATCH 7/7] the credits
> 
> 
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
>  fs/freevxfs/Kconfig       |   10 +++++++++-
>  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 +++++-
>  6 files changed, 29 insertions(+), 2 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.
> diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> index 8124a10..54a1d02 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 b24cb8c..2fc5280 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 ee0ca04..4d84f5d 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 7bd76ab..964d402 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");

Afaict MODULE_AUTHOR is supposed to only contain the original author, and not
collect all developers who actually worked on the modules, if that was the case,
we would have modules with thousands of names in the MODULE_AUTHOR macro, but
well, I'm not the best person to say if it's right or not :)

>  MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
>  MODULE_LICENSE("Dual BSD/GPL");
>  
> -- 
> 1.7.3.4
> 
> 
> 
> On Thu, 2016-05-26 at 16:45 +0200, Krzysztof Błaszkowski wrote:
> > Hi,
> > 
> > So then let it roll. 
> > 
> > Thanks
> > 
> > >From 3d3b4e1ed5df014ae191e0566ff86a17d7d9ac05 Mon Sep 17 00:00:00
> > 2001
> > From: KB <kb@sysmikro.com.pl> 
> -- 
> Krzysztof Blaszkowski
> 

-- 
Carlos

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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-05-30 11:19   ` Carlos Maiolino
@ 2016-05-30 11:54     ` Krzysztof Błaszkowski
  0 siblings, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-30 11:54 UTC (permalink / raw)
  To: Carlos Maiolino; +Cc: linux-fsdevel

Hi Carlos,

Thanks for review. Will fix these things and send tomorrow morning
likely. Today just can't.

On Mon, 2016-05-30 at 13:19 +0200, Carlos Maiolino wrote:
> Hi Krzysztof,
> 
> This is more a style review than functionality itself (although I've added a few
> comments in this context too).
> 
> But, for now on, please:
> 	- Submit each patch in a single e-mail, it's much easier to review the
> 	  patches in a single context, than have 7 patches and 2k lines of
> 	  different contexts in a single e-mail.
> 	- Fix the kernel style and indentation problems.
> 
> If you need help regarding sending the patches in the right format to the list,
> let me know off-list, since, I don't believe the list is the right place to keep
> discussing how to properly send patches to the list and kernel coding style
> stuff.
> And people will be much happier reviewing properly formatted code, and different
> patches in single e-mails.
> 
> I've added some comments below
> 
> On Sat, May 28, 2016 at 09:40:27PM +0200, Krzysztof Błaszkowski wrote:
> > Hi Carlos,
> > 
> > Christoph told me that you can look at these patches I prepared.
> > 
> > The patchset has follwing changes since previous release:
> > - preprocesor expanded local macros,
> > - merged credits patches,
> > - struct inode placed inside local structure vxfs_vfs_inode.
> > 
> > Last change is the most complex and makes an impact on e.g.
> > read_fshead() and actually it is only one proper solution. A file system
> > must not use destroy_inode callback without alloc_inode. if it does
> > then inode structures will not be returned to fs/inode.c: inode_cachep.
> > 
> > From 56ac335ff74706be4c3e30925d2c8c47a19eab9e Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Sat, 28 May 2016 20:55:19 +0200
> > Subject: [PATCH 1/7] cpu endianess vs file system, two locations of the sb
> > 
> > 
> > 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  |   57 +++++++++++++++++++++++-
> >  fs/freevxfs/vxfs_inode.h  |    8 ++--
> >  fs/freevxfs/vxfs_lookup.c |   15 +++++-
> >  fs/freevxfs/vxfs_olt.c    |   15 +++---
> >  fs/freevxfs/vxfs_super.c  |  108 +++++++++++++++++++++++++++++++++------------
> >  8 files changed, 221 insertions(+), 56 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;
> 
> These definitions are still not aligned. What Christoph meant before, was
> indentation alignment.

I see, okay, so the text alignment, good enough. I dislike the old
alignment because it looks bad anyway can add a few tabs.


> 
> > +};
> > +
> > +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;
> >  
> Indentation please.

....


> 
> >  	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..05cced0 100644
> > --- a/fs/freevxfs/vxfs_fshead.c
> > +++ b/fs/freevxfs/vxfs_fshead.c
> > @@ -60,6 +60,29 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
> >  }
> >  #endif
> >  
> > +
> > +static inline void dbh2fhp(struct vxfs_fsh *fhp, void *_dbh, int bo)
> > +{
> > + struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
> > +
> > + fhp->fsh_version = fs32_to_cpu(bo, dbh->fsh_version);
> > + fhp->fsh_fsindex = fs32_to_cpu(bo, dbh->fsh_fsindex);
> > + fhp->fsh_time = fs32_to_cpu(bo, dbh->fsh_time);
> > + fhp->fsh_utime = fs32_to_cpu(bo, dbh->fsh_utime);
> > + fhp->fsh_extop = fs32_to_cpu(bo, dbh->fsh_extop);
> > + fhp->fsh_ninodes = fs32_to_cpu(bo, dbh->fsh_ninodes);
> > + fhp->fsh_nau = fs32_to_cpu(bo, dbh->fsh_nau);
> > + fhp->fsh_old_ilesize = fs32_to_cpu(bo, dbh->fsh_old_ilesize);
> > + fhp->fsh_dflags = fs32_to_cpu(bo, dbh->fsh_dflags);
> > + fhp->fsh_quota = fs32_to_cpu(bo, dbh->fsh_quota);
> > + fhp->fsh_maxinode = fs32_to_cpu(bo, dbh->fsh_maxinode);
> > + fhp->fsh_iauino = fs32_to_cpu(bo, dbh->fsh_iauino);
> > + fhp->fsh_ilistino[0] = fs32_to_cpu(bo, dbh->fsh_ilistino[0]);
> > + fhp->fsh_ilistino[1] = fs32_to_cpu(bo, dbh->fsh_ilistino[1]);
> > + fhp->fsh_lctino = fs32_to_cpu(bo, dbh->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..86db3c2 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -67,6 +67,59 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
> >  }
> >  #endif
> >  
> > +static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip, int bo)
> > +{
> > + int j;
> > +
> > + vip->vdi_mode = fs32_to_cpu(bo, dip->vdi_mode);
> > + vip->vdi_nlink = fs32_to_cpu(bo, dip->vdi_nlink);
> > + vip->vdi_uid = fs32_to_cpu(bo, dip->vdi_uid);
> > + vip->vdi_gid = fs32_to_cpu(bo, dip->vdi_gid);
> > + vip->vdi_size = fs64_to_cpu(bo, dip->vdi_size);
> > + vip->vdi_atime = fs32_to_cpu(bo, dip->vdi_atime);
> > + vip->vdi_autime = fs32_to_cpu(bo, dip->vdi_autime);
> > + vip->vdi_mtime = fs32_to_cpu(bo, dip->vdi_mtime);
> > + vip->vdi_mutime = fs32_to_cpu(bo, dip->vdi_mutime);
> > + vip->vdi_ctime = fs32_to_cpu(bo, dip->vdi_ctime);
> > + vip->vdi_cutime = fs32_to_cpu(bo, dip->vdi_cutime);
> > + vip->vdi_aflags = dip->vdi_aflags;
> > + vip->vdi_orgtype = dip->vdi_orgtype;
> > + vip->vdi_eopflags = fs16_to_cpu(bo, dip->vdi_eopflags);
> > + vip->vdi_eopdata = fs32_to_cpu(bo, dip->vdi_eopdata);
> > +
> > + vip->vdi_ftarea.i_regular.reserved = fs32_to_cpu(bo, dip->vdi_ftarea.i_regular.reserved);
> > + vip->vdi_ftarea.i_regular.fixextsize = fs32_to_cpu(bo, dip->vdi_ftarea.i_regular.fixextsize);
> > + vip->vdi_blocks = fs32_to_cpu(bo, dip->vdi_blocks);
> > + vip->vdi_gen = fs32_to_cpu(bo, dip->vdi_gen);
> > + vip->vdi_version = fs64_to_cpu(bo, dip->vdi_version);
> > +
> > + switch (dip->vdi_orgtype) {
> > + case VXFS_ORG_EXT4:
> > +  vip->vdi_org.ext4.ve4_spare = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_spare);
> > +  vip->vdi_org.ext4.ve4_indsize = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_indsize);
> > +  for (j = 0; j < 2; j++) {
> > +   vip->vdi_org.ext4.ve4_indir[j] = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_indir[j]);
> > +  }
> > +  for (j = 0; j < 10; j++) {
> > +   vip->vdi_org.ext4.ve4_direct[j].extent = fs32_to_cpu(bo, dip->vdi_org.ext4.ve4_direct[j].extent);
> > +   vip->vdi_org.ext4.ve4_direct[j].size = fs32_to_cpu(bo, dip->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 < 6; j++) {
> > +   vip->vdi_org.typed[j].vt_hdr = fs64_to_cpu(bo, dip->vdi_org.typed[j].vt_hdr);
> > +   vip->vdi_org.typed[j].vt_block = fs32_to_cpu(bo, dip->vdi_org.typed[j].vt_block);
> > +   vip->vdi_org.typed[j].vt_size = fs32_to_cpu(bo, dip->vdi_org.typed[j].vt_size);
> > +  }
> > +  break;
> > + };
> 
> Please, indent this switch statement, follow the 80columns rule (i.e. lines
> should not have more than 80columns).
> 

okay, these were just warnings. speed limits on highways are supposed to
limit a speed and there are ones who think about them as suggestions to
not drive slower than .. I enjoy more the latter case.

> > +
> > + vip->vdi_iattrino = fs32_to_cpu(bo, dip->vdi_iattrino);
> > +}
> > +
> >  
> >  /**
> >   * vxfs_blkiget - find inode based on extent #
> > @@ -101,7 +154,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 +196,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;
> > +
> Indentation.

need to think about some clever sed syntax .. 


> 
> >  
> >  	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..6a69eb0 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,53 @@ 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 %08x at +%d\n",
> > +					rsbp->vs_magic, blk);
> 
> 				Please, avoid +80 columns, you did it in the
> 				printk above, no reason to not do it here too.

indeed I did. however checkpatch complained again and that was that the
string was split. Daft, isn't it?

Need to know checkpatch ....ed warnings rules.

> 
> > +			break;
> > +		}
> > +
> > +		rc = 0;
> > +		infp->vsi_raw = rsbp;
> > +		infp->vsi_bp = bp;
> > +	} while (0);
> 
> 	I'm not the best person to give a review here, but, I wouldn't use a
> 	do.while(0), but instead, goto error_X: statements and assign the error
> 	codes according to the conditional results, instead of re-assigning the
> 	error code if the previous code wasn't correct.

	some people hate gotos.

> 	But again, a POV of another person will be better.
> 
> > +
> > +	if (rc) {
> > +		infp->vsi_raw = NULL;
> > +		infp->vsi_bp = NULL;
> > +		brelse(bp);
> > +	}
> > +
> > +	return rc;
> > +}
> > +
> > +
> > +static const char * const vxfs_subtypes[] = {
> > +	"SCO",
> > +	"HP-UX(be)"
> > +};
> > +
> >  /**
> >   * vxfs_read_super - read superblock into memory and initialize filesystem
> >   * @sbp:		VFS superblock (to fill)
> > @@ -149,10 +197,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;
> >  
> Indentation, goo opportunity to fix the another non-indented fields too.

i will hate this word shortly soon.

> 
> >  	sbp->s_flags |= MS_RDONLY;
> >  
> > @@ -162,48 +210,50 @@ 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 */
> > +			sbp->s_subtype = kstrdup(vxfs_subtypes[0], GFP_KERNEL);
> > +			break;
> > +		}
> > +
> > +		if (!vxfs_try_sb_magic(sbp, 8, cpu_to_be32(VXFS_SUPER_MAGIC))) {
> > +			infp->byte_order = BO_BE; /* HP-UX pa-risc likely */
> > +			sbp->s_subtype = kstrdup(vxfs_subtypes[1], GFP_KERNEL);
> > +			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: blocksize: %d\n", rsbp->vs_bsize);
> > +	printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
> > +	printk(KERN_DEBUG "vxfs: blocksize: %d\n",
> > +	    fs32_to_cpu(infp->byte_order, 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 +287,7 @@ out_free_ilist:
> >  	vxfs_put_fake_inode(infp->vsi_ilist);
> >  	vxfs_put_fake_inode(infp->vsi_stilist);
> >  out:
> > -	brelse(bp);
> > +	brelse(infp->vsi_bp);
> >  	kfree(infp);
> >  	return ret;
> >  }
> > -- 
> > 1.7.3.4
> > 
> > From 0d0c7ed061edd846bd032fe1073d61169299a435 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Sat, 28 May 2016 20:55:19 +0200
> > Subject: [PATCH 2/7] missing kfree and kfree on kmem_cache obj
> 
> Missing kfree and kfree?
> 
> "Missing to kfree objects" sounds better IMHO

maybe. I meant kfree as function = noun.
as you wish. 

original message should be read like this: (missing kfree) && (kfree on
object allocated by kmem_cache_alloc() )


> > 
> > 
> > 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);
> 
> Indentation
> 
> >  
> >  /* 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 05cced0..c4c6a86 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 86db3c2..9590f79 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -411,3 +411,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
> > 
> > From c595f46ad63d71ac26dfc3ef23d87e372ac85426 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Sat, 28 May 2016 20:55:19 +0200
> > Subject: [PATCH 3/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 9590f79..f91a50c 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -393,7 +393,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);
> >  }
> >  
> >  /**
> > @@ -401,17 +409,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 6a69eb0..500087a 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,
> 
> Indentation
> 
> >  	.evict_inode =		vxfs_evict_inode,
> >  	.put_super =		vxfs_put_super,
> >  	.statfs =		vxfs_statfs,
> > -- 
> > 1.7.3.4
> > 
> > From b02ffccdff5ca82922bf09cdcf1a9ea4471bbb62 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Sat, 28 May 2016 20:55:19 +0200
> > Subject: [PATCH 4/7] refactoring of vxfs_readdir() 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;
> 
> Indentation
> > +
> > +	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;
> > +		}
> 
> 		Kernel coding style states to not use braces with single-line if
> 		conditionals.

okay. have seen this warning already.


> 
> > +		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
> > 
> > From eceb47a770b80d7f46a089f6a1744d66f0601e77 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Sat, 28 May 2016 20:55:19 +0200
> > Subject: [PATCH 5/7] static inode_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 f91a50c..1e20823 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
> > @@ -424,3 +424,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 500087a..9525818 100644
> > --- a/fs/freevxfs/vxfs_super.c
> > +++ b/fs/freevxfs/vxfs_super.c
> > @@ -315,29 +315,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
> > 
> > From 2915ed2c92dd349203070eea8970fd4fb62ba5b4 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Sat, 28 May 2016 20:55:19 +0200
> > Subject: [PATCH 6/7] struct inode embedded in vxfs_vfs_inode
> > 
> > struct vxfs_vfs_inode is allocated from vxfs_inode_cachep
> > and vfs inode is initialized by inode_constructor().
> > sb->s_op must be set before read_fshead() otherwise 
> > 3 inodes will be allocated from common inode_cachep.
> > 
> > 
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> >  fs/freevxfs/vxfs.h        |    8 ---
> >  fs/freevxfs/vxfs_bmap.c   |    5 +-
> >  fs/freevxfs/vxfs_extern.h |   15 +++---
> >  fs/freevxfs/vxfs_fshead.c |   48 +++++++----------
> >  fs/freevxfs/vxfs_inode.c  |  130 ++++++++++++++++++++-------------------------
> >  fs/freevxfs/vxfs_inode.h  |   20 +++++++-
> >  fs/freevxfs/vxfs_super.c  |   16 +++---
> >  7 files changed, 114 insertions(+), 128 deletions(-)
> > 
> > diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> > index 5dc8949..8124a10 100644
> > --- a/fs/freevxfs/vxfs.h
> > +++ b/fs/freevxfs/vxfs.h
> > @@ -38,7 +38,6 @@
> >   */
> >  #include <linux/types.h>
> >  
> > -
> >  /*
> >   * Data types for use with the VxFS ondisk format.
> >   */
> > @@ -270,13 +269,6 @@ enum {
> >  #define VXFS_ISIMMED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
> >  #define VXFS_ISTYPED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
> >  
> > -
> > -/*
> > - * Get filesystem private data from VFS inode.
> > - */
> > -#define VXFS_INO(ip) \
> > -	((struct vxfs_inode_info *)(ip)->i_private)
> > -
> >  /*
> >   * Get filesystem private data from VFS superblock.
> >   */
> > diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
> > index 95afd98..e39aea4 100644
> > --- a/fs/freevxfs/vxfs_bmap.c
> > +++ b/fs/freevxfs/vxfs_bmap.c
> > @@ -97,8 +97,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
> >  
> >  		brelse(buf);
> >  		return bno;
> > -	} else
> > -		printk(KERN_WARNING "no matching indir?");
> > +	} else {
> > +		printk(KERN_WARNING "%s:%d no matching indir?\n", __func__, __LINE__);
> > +	}
> >  
> >  	return 0;
> >  
> > diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> > index cc43fd0..9648735 100644
> > --- a/fs/freevxfs/vxfs_extern.h
> > +++ b/fs/freevxfs/vxfs_extern.h
> > @@ -56,17 +56,16 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
> >  /* vxfs_inode.c */
> >  extern const struct address_space_operations vxfs_immed_aops;
> >  extern void			vxfs_dumpi(struct vxfs_inode_info *, ino_t);
> > -extern struct inode *		vxfs_get_fake_inode(struct super_block *,
> > -					struct vxfs_inode_info *);
> > -extern void			vxfs_put_fake_inode(struct inode *);
> > -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);
> > +
> > +extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
> > +extern struct inode *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 int vxfs_ii_cache_init(void);
> >  extern void vxfs_ii_cache_destroy(void);
> > +extern struct inode *vxfs_inode_alloc(struct super_block *sb);
> >  
> >  
> >  /* vxfs_lookup.c */
> > diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> > index c4c6a86..b24cb8c 100644
> > --- a/fs/freevxfs/vxfs_fshead.c
> > +++ b/fs/freevxfs/vxfs_fshead.c
> > @@ -131,31 +131,26 @@ vxfs_read_fshead(struct super_block *sbp)
> >  {
> >  	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
> >  	struct vxfs_fsh			*pfp, *sfp;
> > -	struct vxfs_inode_info		*vip, *tip;
> > +	struct inode *ip1;
> > +	struct inode *ip2;
> 
> Indentation.
> 
> >  
> > -	vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
> > -	if (!vip) {
> > +	infp->vsi_fship = ip1 = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
> > +	if (IS_ERR(ip1)) {
> >  		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
> >  		return -EINVAL;
> >  	}
> > -	if (!VXFS_ISFSH(vip)) {
> > +
> > +	if (!VXFS_ISFSH(VXFS_INO(ip1))) {
> >  		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
> > -				vip->vii_mode & VXFS_TYPE_MASK); 
> > +				VXFS_INO(ip1)->vii_mode & VXFS_TYPE_MASK);
> >  		goto out_free_fship;
> >  	}
> >  
> > -
> >  #ifdef DIAGNOSTIC
> >  	printk("vxfs: fsh inode dump:\n");
> > -	vxfs_dumpi(vip, infp->vsi_fshino);
> > +	vxfs_dumpi(VXFS_INO(ip1), infp->vsi_fshino);
> >  #endif
> >  
> > -	infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
> > -	if (!infp->vsi_fship) {
> > -		printk(KERN_ERR "vxfs: unable to get fsh inode\n");
> > -		goto out_free_fship;
> > -	}
> > -
> >  	sfp = vxfs_getfsh(infp->vsi_fship, 0);
> >  	if (!sfp) {
> >  		printk(KERN_ERR "vxfs: unable to get structural fsh\n");
> > @@ -176,31 +171,25 @@ vxfs_read_fshead(struct super_block *sbp)
> >  	vxfs_dumpfsh(pfp);
> >  #endif
> >  
> > -	tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
> > -	if (!tip)
> > -		goto out_free_pfp;
> > +	infp->vsi_stilist =
> > +		ip2 = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
> >  
> > -	infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
> > -	if (!infp->vsi_stilist) {
> > -		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
> > -		vxfs_inode_info_free(tip);
> > +	if (IS_ERR(ip2)) {
> >  		goto out_free_pfp;
> >  	}
> > +
> >  	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
> >  		printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n",
> >  				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 
> >  		goto out_iput_stilist;
> >  	}
> >  
> > -	tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
> > -	if (!tip)
> > -		goto out_iput_stilist;
> > -	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
> > -	if (!infp->vsi_ilist) {
> > +	infp->vsi_ilist = ip2 = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
> > +	if (IS_ERR(ip2)) {
> >  		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
> > -		vxfs_inode_info_free(tip);
> >  		goto out_iput_stilist;
> >  	}
> > +
> >  	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
> >  		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
> >  				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
> > @@ -220,9 +209,10 @@ vxfs_read_fshead(struct super_block *sbp)
> >   out_free_sfp:
> >   	kfree(sfp);
> >   out_iput_fship:
> > -	iput(infp->vsi_fship);
> > -	return -EINVAL;
> >   out_free_fship:
> > -	vxfs_inode_info_free(vip);
> > +	iput(infp->vsi_fship);
> > +	infp->vsi_stilist = NULL;
> > +	infp->vsi_ilist = NULL;
> > +	infp->vsi_fship = NULL;
> >  	return -EINVAL;
> >  }
> > diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> > index 1e20823..ee0ca04 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -42,6 +42,7 @@
> >  
> >  
> >  static struct kmem_cache *vxfs_inode_cachep;
> > +static void vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip);
> >  
> >  
> >  #ifdef DIAGNOSTIC
> > @@ -137,35 +138,41 @@ static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *
> >   *  buffercache.  This function should not be used outside the
> >   *  read_super() method, otherwise the data may be incoherent.
> >   */
> > -struct vxfs_inode_info *
> > +struct inode *
> >  vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
> >  {
> >  	struct buffer_head		*bp;
> >  	u_long				block, offset;
> > +	struct inode *ip;
> >  
> >  	block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
> >  	offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
> > +
> > +	ip = new_inode(sbp);
> > +	if (!ip)
> > +		return ERR_PTR(-ENOMEM);
> > +
> >  	bp = sb_bread(sbp, block);
> > +	ip->i_ino = get_next_ino();
> > +	ip->i_mapping->a_ops = &vxfs_aops;
> >  
> >  	if (bp && buffer_mapped(bp)) {
> > -		struct vxfs_inode_info	*vip;
> > -		struct vxfs_dinode	*dip;
> > +		struct vxfs_inode_info	*vip = VXFS_INO(ip);
> > +		struct vxfs_dinode	*dip = (struct vxfs_dinode *)(bp->b_data + offset);
> >  
> > -		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> > -			goto fail;
> > -		dip = (struct vxfs_dinode *)(bp->b_data + offset);
> >  		dip2vip_cpy(vip, dip, VXFS_SBI(sbp)->byte_order);
> > +		vxfs_iinit(ip, vip);
> >  #ifdef DIAGNOSTIC
> >  		vxfs_dumpi(vip, ino);
> >  #endif
> > -		brelse(bp);
> > -		return (vip);
> > +	} else {
> > +		printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
> > +		iput(ip);
> > +		ip = NULL;
> >  	}
> > -
> > -fail:
> > -	printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
> >  	brelse(bp);
> > -	return NULL;
> > +
> > +	return ip;
> >  }
> >  
> >  /**
> > @@ -180,21 +187,18 @@ fail:
> >   *  Returns the matching VxFS inode on success, else an error code.
> >   */
> >  static struct vxfs_inode_info *
> > -__vxfs_iget(ino_t ino, struct inode *ilistp)
> > +__vxfs_iget(struct inode *ip, struct inode *ilistp, ino_t ino)
> >  {
> > -	struct page			*pp;
> > -	u_long				offset;
> > +	struct page	*pp;
> Indentation


and i hate the "Indentation" word...

I will use "indent -kr -l 120 more switches" on everything so everything
will look the same way.

Thanks

> 
> > +	u_long offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
> >  
> > -	offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
> >  	pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
> >  
> >  	if (!IS_ERR(pp)) {
> > -		struct vxfs_inode_info	*vip;
> > +		struct vxfs_inode_info	*vip = VXFS_INO(ip);
> >  		struct vxfs_dinode	*dip;
> >  		caddr_t			kaddr = (char *)page_address(pp);
> >  
> > -		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> > -			goto fail;
> >  		dip = (struct vxfs_dinode *)(kaddr + offset);
> >  		dip2vip_cpy(vip, dip, VXFS_SBI(ilistp->i_sb)->byte_order);
> >  #ifdef DIAGNOSTIC
> > @@ -206,11 +210,6 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
> >  
> >  	printk(KERN_WARNING "vxfs: error on page %p\n", pp);
> >  	return ERR_CAST(pp);
> > -
> > -fail:
> > -	printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
> > -	vxfs_put_page(pp);
> > -	return ERR_PTR(-ENOMEM);
> >  }
> >  
> >  /**
> > @@ -223,13 +222,24 @@ fail:
> >   *  the structural inode list.
> >   *  Returns the matching VxFS inode on success, else a NULL pointer.
> >   */
> > -struct vxfs_inode_info *
> > +struct inode *
> >  vxfs_stiget(struct super_block *sbp, ino_t ino)
> >  {
> > -	struct vxfs_inode_info *vip;
> > +	struct inode *ip = new_inode(sbp);
> > +	struct vxfs_inode_info *ii;
> >  
> > -	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
> > -	return IS_ERR(vip) ? NULL : vip;
> > +	if (!ip)
> > +		return NULL;
> > +
> > +	ip->i_ino = get_next_ino();
> > +	ip->i_mapping->a_ops = &vxfs_aops;
> > +	ii = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_stilist, ino);
> > +	if (IS_ERR(ii)) {
> > +		iput(ip);
> > +	} else {
> > +		vxfs_iinit(ip, ii);
> > +	}
> > +	return IS_ERR(ii) ? NULL : ip;
> >  }
> >  
> >  /**
> > @@ -297,41 +307,6 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
> >  	
> >  }
> >  
> > -/**
> > - * vxfs_get_fake_inode - get fake inode structure
> > - * @sbp:		filesystem superblock
> > - * @vip:		fspriv inode
> > - *
> > - * Description:
> > - *  vxfs_fake_inode gets a fake inode (not in the inode hash) for a
> > - *  superblock, vxfs_inode pair.
> > - *  Returns the filled VFS inode.
> > - */
> > -struct inode *
> > -vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
> > -{
> > -	struct inode			*ip = NULL;
> > -
> > -	if ((ip = new_inode(sbp))) {
> > -		ip->i_ino = get_next_ino();
> > -		vxfs_iinit(ip, vip);
> > -		ip->i_mapping->a_ops = &vxfs_aops;
> > -	}
> > -	return (ip);
> > -}
> > -
> > -/**
> > - * vxfs_put_fake_inode - free faked inode
> > - * *ip:			VFS inode
> > - *
> > - * Description:
> > - *  vxfs_put_fake_inode frees all data associated with @ip.
> > - */
> > -void
> > -vxfs_put_fake_inode(struct inode *ip)
> > -{
> > -	iput(ip);
> > -}
> >  
> >  /**
> >   * vxfs_iget - get an inode
> > @@ -355,7 +330,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
> >  	if (!(ip->i_state & I_NEW))
> >  		return ip;
> >  
> > -	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
> > +	vip = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_ilist, ino);
> >  	if (IS_ERR(vip)) {
> >  		iget_failed(ip);
> >  		return ERR_CAST(vip);
> > @@ -393,10 +368,9 @@ 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);
> > -	void *priv = inode->i_private;
> > +	struct vxfs_vfs_inode *i = container_of(inode, struct vxfs_vfs_inode, ino);
> >  
> > -	inode->i_private = NULL;
> > -	kmem_cache_free(vxfs_inode_cachep, priv);
> > +	kmem_cache_free(vxfs_inode_cachep, i);
> >  }
> >  
> >  void vxfs_destroy_inode(struct inode *ip)
> > @@ -405,11 +379,11 @@ void vxfs_destroy_inode(struct inode *ip)
> >  }
> >  
> >  /**
> > - * vxfs_evict_inode - remove inode from main memory
> > + * vxfs_evict_inode - commit inode buffers if needed, may delete on-disk inode.
> >   * @ip:		inode to discard.
> >   *
> >   * Description:
> > - *  vxfs_evict_inode() is called on the final iput
> > + *  vxfs_evict_inode() may be called on the final iput.
> >   */
> >  void
> >  vxfs_evict_inode(struct inode *ip)
> > @@ -420,17 +394,27 @@ vxfs_evict_inode(struct inode *ip)
> >  }
> >  
> >  
> > -void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> > +
> > +
> > +struct inode *vxfs_inode_alloc(struct super_block *sb)
> >  {
> > -	kmem_cache_free(vxfs_inode_cachep, vip);
> > +	struct vxfs_vfs_inode *i = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
> > +
> > +	return i ? &i->ino : NULL;
> >  }
> >  
> > +static void vxfs_inode_constructor(void *ptr)
> > +{
> > +	struct vxfs_vfs_inode *i = (struct vxfs_vfs_inode *) ptr;
> > +
> > +	inode_init_once(&i->ino);
> > +}
> >  
> >  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);
> > +		sizeof(struct vxfs_vfs_inode), 0,
> > +		SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, vxfs_inode_constructor);
> >  
> >  	return vxfs_inode_cachep ? 0 : -ENOMEM;
> >  }
> > diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
> > index 9a2c376..bba04a8 100644
> > --- a/fs/freevxfs/vxfs_inode.h
> > +++ b/fs/freevxfs/vxfs_inode.h
> > @@ -37,7 +37,6 @@
> >   * inodes of the Veritas Filesystem.
> >   */
> >  
> > -
> >  #define VXFS_ISIZE		0x100		/* Inode size */
> >  
> >  #define VXFS_NDADDR		10		/* Number of direct addrs in inode */
> > @@ -154,6 +153,16 @@ struct vxfs_dinode {
> >   */
> >  #define vxfs_inode_info	vxfs_dinode
> >  
> > +struct vxfs_vfs_inode {
> > +	struct inode ino;
> > +	struct vxfs_inode_info cpufs_ino;
> > +	/*
> > +	 * the cpufs_ino contains copy of on-disk inode but
> > +	 * it is cpu-endian formatted and it might be not aligned
> > +	 */
> > +};
> > +
> > +
> >  #define vii_mode	vdi_mode
> >  #define vii_uid		vdi_uid
> >  #define vii_gid		vdi_gid
> > @@ -177,4 +186,13 @@ struct vxfs_dinode {
> >  #define vii_ext4	vdi_org.ext4
> >  #define vii_typed	vdi_org.typed
> >  
> > +/*
> > + * Get filesystem private data from VFS inode.
> > + */
> > +static inline struct vxfs_inode_info *VXFS_INO(struct inode *i)
> > +{
> > +	return &(container_of(i, struct vxfs_vfs_inode, ino))->cpufs_ino;
> > +}
> > +
> > +
> >  #endif /* _VXFS_INODE_H_ */
> > diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> > index 9525818..7bd76ab 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 = {
> > +	.alloc_inode = vxfs_inode_alloc,
> >  	.destroy_inode = vxfs_destroy_inode,
> >  	.evict_inode =		vxfs_evict_inode,
> >  	.put_super =		vxfs_put_super,
> 
> Please indent everything here
> > @@ -80,9 +81,9 @@ vxfs_put_super(struct super_block *sbp)
> >  {
> >  	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
> >  
> > -	vxfs_put_fake_inode(infp->vsi_fship);
> > -	vxfs_put_fake_inode(infp->vsi_ilist);
> > -	vxfs_put_fake_inode(infp->vsi_stilist);
> > +	iput(infp->vsi_fship);
> > +	iput(infp->vsi_ilist);
> > +	iput(infp->vsi_stilist);
> >  
> >  	brelse(infp->vsi_bp);
> >  	kfree(infp);
> > @@ -259,17 +260,18 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> >  		goto out;
> >  	}
> >  
> > +
> >  	if (vxfs_read_olt(sbp, bsize)) {
> >  		printk(KERN_WARNING "vxfs: unable to read olt\n");
> >  		goto out;
> >  	}
> >  
> > +	sbp->s_op = &vxfs_super_ops;
> >  	if (vxfs_read_fshead(sbp)) {
> >  		printk(KERN_WARNING "vxfs: unable to read fshead\n");
> >  		goto out;
> >  	}
> >  
> > -	sbp->s_op = &vxfs_super_ops;
> >  	root = vxfs_iget(sbp, VXFS_ROOT_INO);
> >  	if (IS_ERR(root)) {
> >  		ret = PTR_ERR(root);
> > @@ -284,9 +286,9 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> >  	return 0;
> >  	
> >  out_free_ilist:
> > -	vxfs_put_fake_inode(infp->vsi_fship);
> > -	vxfs_put_fake_inode(infp->vsi_ilist);
> > -	vxfs_put_fake_inode(infp->vsi_stilist);
> > +	iput(infp->vsi_fship);
> > +	iput(infp->vsi_ilist);
> > +	iput(infp->vsi_stilist);
> >  out:
> >  	brelse(infp->vsi_bp);
> >  	kfree(infp);
> > -- 
> > 1.7.3.4
> > 
> > From ce7bce806419c15f7dad3c9a20b59318566c79ef Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Sat, 28 May 2016 20:55:19 +0200
> > Subject: [PATCH 7/7] the credits
> > 
> > 
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> >  fs/freevxfs/Kconfig       |   10 +++++++++-
> >  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 +++++-
> >  6 files changed, 29 insertions(+), 2 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.
> > diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> > index 8124a10..54a1d02 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 b24cb8c..2fc5280 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 ee0ca04..4d84f5d 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 7bd76ab..964d402 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");
> 
> Afaict MODULE_AUTHOR is supposed to only contain the original author, and not
> collect all developers who actually worked on the modules, if that was the case,
> we would have modules with thousands of names in the MODULE_AUTHOR macro, but
> well, I'm not the best person to say if it's right or not :)
> 
> >  MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
> >  MODULE_LICENSE("Dual BSD/GPL");
> >  
> > -- 
> > 1.7.3.4
> > 
> > 
> > 
> > On Thu, 2016-05-26 at 16:45 +0200, Krzysztof Błaszkowski wrote:
> > > Hi,
> > > 
> > > So then let it roll. 
> > > 
> > > Thanks
> > > 
> > > >From 3d3b4e1ed5df014ae191e0566ff86a17d7d9ac05 Mon Sep 17 00:00:00
> > > 2001
> > > From: KB <kb@sysmikro.com.pl> 
> > -- 
> > Krzysztof Blaszkowski
> > 
> 

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-05-28 19:40 ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
  2016-05-30 11:19   ` Carlos Maiolino
@ 2016-05-31 12:25   ` Christoph Hellwig
  2016-05-31 13:44     ` Krzysztof Błaszkowski
  1 sibling, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2016-05-31 12:25 UTC (permalink / raw)
  To: Krzysztof B??aszkowski; +Cc: Carlos Maiolino, Christoph Hellwig, linux-fsdevel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=unknown-8bit, Size: 41464 bytes --]

Hi Krzysztof,

I found some time to go over the patches and spent that on the byte
swap one.  I like it in general, but I'd really like to keep sparse
[1] happy to be able to static type check for it, so I reworked it
a bit.  I also used that as an opportunity to write a proper changelog,
xpand your full name in the signed off line and fix up small deviations
from the Linux coding style.

Can you check if this patch works for you and you are fine with it?
If so I'd like to commit it to a git tree and then work relative to it
for the other patches.

[1] See Documentation/sparse.txt in the kernel tree for instructions

Thanks,
	Christoph

---
>From a510a0e366e8bae7f825d131ad6f6f74dd4bef01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Krzysztof=20B=C5=82aszkowski?= <kb@sysmikro.com.pl>
Date: Tue, 31 May 2016 08:45:13 +0200
Subject: freevxfs: handle big endian HP-UX file systems
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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

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

Signed-off-by: Krzysztof Błaszkowski <kb@sysmikro.com.pl>
[hch: make spare happy]
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/freevxfs/vxfs.h        | 177 ++++++++++++++++++++++++++--------------------
 fs/freevxfs/vxfs_bmap.c   |  70 ++++++++++--------
 fs/freevxfs/vxfs_dir.h    |  17 ++---
 fs/freevxfs/vxfs_fshead.c |   5 +-
 fs/freevxfs/vxfs_fshead.h |  28 ++++----
 fs/freevxfs/vxfs_inode.c  |  31 +++++++-
 fs/freevxfs/vxfs_inode.h  | 140 +++++++++++++++++++-----------------
 fs/freevxfs/vxfs_lookup.c |  34 +++++----
 fs/freevxfs/vxfs_olt.c    |  15 ++--
 fs/freevxfs/vxfs_olt.h    |  70 +++++++++---------
 fs/freevxfs/vxfs_super.c  | 101 ++++++++++++++++++--------
 11 files changed, 409 insertions(+), 279 deletions(-)

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


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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-05-31 12:25   ` Christoph Hellwig
@ 2016-05-31 13:44     ` Krzysztof Błaszkowski
  2016-06-01  7:33       ` Christoph Hellwig
  0 siblings, 1 reply; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-31 13:44 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

Hi Christoph,

On Tue, 2016-05-31 at 05:25 -0700, Christoph Hellwig wrote:
> Hi Krzysztof,
> 
> I found some time to go over the patches and spent that on the byte
> swap one. 

Thanks.


>  I like it in general, but I'd really like to keep sparse
> [1] happy to be able to static type check for it, so I reworked it
> a bit.

okay.

>   I also used that as an opportunity to write a proper changelog,

many thanks. 

> xpand your full name in the signed off line and fix up small deviations
> from the Linux coding style.
> 

once again thanks. yes, I will look at this further soon.

> Can you check if this patch works for you and you are fine with it?
> If so I'd like to commit it to a git tree and then work relative to it
> for the other patches.

I can check but here are my remarks:
the dip2vip_cpy() does partial byte-swap from file system endian to cpu
endian, so the union uses fs native endianess and this raises difficulty
of using struct vxfs_inode_info to yet another level.
Is this a good practice ? (apart from a benefit like some minor speed
gain)

Are there any real benefits from marking anything "bitwise" except that
it is just another type ?

I reckon that this is just reworked my 0001 patch and one of chunks does
not apply to lookup.c

"
--- vxfs_lookup.c
+++ vxfs_lookup.c
@@ -298,8 +306,10 @@
 
 				offset = (char *)de - kaddr;
 				ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
-				if (!dir_emit(ctx, de->d_name, de->d_namelen,
-					de->d_ino, DT_UNKNOWN)) {
+				if (!dir_emit(ctx, de->d_name,
+						fs16_to_cpu(sbi, de->d_namelen),
+						fs32_to_cpu(sbi, de->d_ino),
+						DT_UNKNOWN)) {
 					vxfs_put_page(pp);
 					return 0;
 				}
"

because for some strange reason the patch uses "PAGE_SHIFT" while
original lookup.c from 3.16 or 3.18 kernels uses PAGE_CACHE_SHIFT but
4.6 kernel. so the patch below does not apply cleanly to source from 3.x
kernels. I use 3.16, double checked latest 3.18.

Anyway because readdir() is not aware of fs endianess (because 0004
patch is not in there) the hp-ux tests will fail with some general
protection fault very likely.

I am almost sure that this patch stands also for that patch 6/7 will
have to be changed heavily because it will not apply.

I can't see also patches which fix these obvious bugs like freeing
kmem_cache_alloc() objects with kfree.
Even worse is releasing inode->i_private from the "evict_inode"
callback.
This leads to dangling objects in vxfs's kmem_cache when the fs is
unmounted. Destroying cache on module unload causes kmem_cache_destroy
to complain about it and after a few tries ((module load, mount, some
ops on mountpoint, unmount, unload) x few times) hard lockup is
inevitable.

A fix is to utilize the "destroy_inode" callback however this will lead
to memory leaks to fs/inode.c cache. So it is partial fix.
A proper fix is to use both "alloc_inode" and "destroy_inode" callbacks
but this stands for that the vxfs inode structure must inherit generic
struct inode and the patch 0006 addresses this.


This is what, I think, is right in this situation: you put big effort to
split vxfs_dinfo from vxfs_inode_info, which was on "to do", fs endian
fields are marked bitwise. This work should not be wasted and I think
that it is wise to modify remaining patches to your "0001" and I can do
this.

It is pointless to give a try to that patch only below because of
readdir() and inode_cachep issue. (and wrong error handling:
kfree(kmem_cache_alloc()), small memory leak in fshead.c - these are
minors despite of that look bad)

Do you think other patches should be updated with regard to the patch
you sent ?

If so then let me do this.



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

-- 
Krzysztof Blaszkowski



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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-05-31 13:44     ` Krzysztof Błaszkowski
@ 2016-06-01  7:33       ` Christoph Hellwig
  2016-06-01  8:38         ` Krzysztof Błaszkowski
                           ` (2 more replies)
  0 siblings, 3 replies; 21+ messages in thread
From: Christoph Hellwig @ 2016-06-01  7:33 UTC (permalink / raw)
  To: Krzysztof B??aszkowski; +Cc: Christoph Hellwig, Carlos Maiolino, linux-fsdevel


Hi Krzysztof,

> I can check but here are my remarks:
> the dip2vip_cpy() does partial byte-swap from file system endian to cpu
> endian, so the union uses fs native endianess and this raises difficulty
> of using struct vxfs_inode_info to yet another level.
> Is this a good practice ? (apart from a benefit like some minor speed
> gain)

It seems easier this way around.  If you think byte swapping makes
life easier for you I'm happy to take an incremental patch.  Howerver
that means we'll need separate structure defintions for the union
members.

> Are there any real benefits from marking anything "bitwise" except that
> it is just another type ?

bitwise is an annotation for sparse so that you can't directly assign
to the variable, and need to use accessors instead.  In this case it's
used so that we are forced to use the byte swapping helpers and get a
warning from sparse if that's not done properly.

> 
> because for some strange reason the patch uses "PAGE_SHIFT" while
> original lookup.c from 3.16 or 3.18 kernels uses PAGE_CACHE_SHIFT but
> 4.6 kernel. so the patch below does not apply cleanly to source from 3.x
> kernels. I use 3.16, double checked latest 3.18.

Yes, PAGE_CACHE_SIZE, PAGE_CACHE_SHIFT and co were removed in kernel
4.6, as they have always been identical to the versions without _CACHE.

> Anyway because readdir() is not aware of fs endianess (because 0004
> patch is not in there) the hp-ux tests will fail with some general
> protection fault very likely.

I think all readdir structures are fixed up now, please check.

> I can't see also patches which fix these obvious bugs like freeing
> kmem_cache_alloc() objects with kfree.
> Even worse is releasing inode->i_private from the "evict_inode"
> callback.
> This leads to dangling objects in vxfs's kmem_cache when the fs is
> unmounted. Destroying cache on module unload causes kmem_cache_destroy
> to complain about it and after a few tries ((module load, mount, some
> ops on mountpoint, unmount, unload) x few times) hard lockup is
> inevitable.

Yeah, this was just getting started.  I've spent some more time on the
whole inode issues and have implemented this a bit different from what
you did, although the end result is very similar.  Can you take a look
at the tree here:

	http://git.infradead.org/users/hch/vfs.git/shortlog/refs/heads/freevxfs

> Do you think other patches should be updated with regard to the patch
> you sent ?

Please take a look at the branch above.  The only major thing that
should be missing is your directory code refactoring.

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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-06-01  7:33       ` Christoph Hellwig
@ 2016-06-01  8:38         ` Krzysztof Błaszkowski
  2016-06-01  8:41           ` freevxfs: hp-ux support. patchset r3, 2/4 Krzysztof Błaszkowski
                             ` (2 more replies)
  2016-06-01  9:23         ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
  2016-06-01  9:27         ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
  2 siblings, 3 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-01  8:38 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

Hi Christoph,

On Wed, 2016-06-01 at 00:33 -0700, Christoph Hellwig wrote:
> Hi Krzysztof,
> 
> > I can check but here are my remarks:
> > the dip2vip_cpy() does partial byte-swap from file system endian to cpu
> > endian, so the union uses fs native endianess and this raises difficulty
> > of using struct vxfs_inode_info to yet another level.
> > Is this a good practice ? (apart from a benefit like some minor speed
> > gain)
> 
> It seems easier this way around.  If you think byte swapping makes
> life easier for you I'm happy to take an incremental patch.  Howerver
> that means we'll need separate structure defintions for the union
> members.

yes, you are right. bitwise attribute is convenient for endian
annotation for automated checks. I did not know this feature and it
seemed like excessive typing overhead to me.
Anyway I must admit that it has benefits. Without that I wouldn't dare
to have a mixed endian structure. I would just put a //note somewhere
aside for me to remember that this structure requires special handling
with regard to endianess and whether it has been copied already or it is
just mapped piece of memory from backend device. 
Would I do this with every member of the structure ? of course,
wouldn't. (too many to remember)


> 
> > Are there any real benefits from marking anything "bitwise" except that
> > it is just another type ?
> 
> bitwise is an annotation for sparse so that you can't directly assign
> to the variable, and need to use accessors instead.  In this case it's
> used so that we are forced to use the byte swapping helpers and get a
> warning from sparse if that's not done properly.
> 
indeed, I realized this.


> > 
> > because for some strange reason the patch uses "PAGE_SHIFT" while
> > original lookup.c from 3.16 or 3.18 kernels uses PAGE_CACHE_SHIFT but
> > 4.6 kernel. so the patch below does not apply cleanly to source from 3.x
> > kernels. I use 3.16, double checked latest 3.18.
> 
> Yes, PAGE_CACHE_SIZE, PAGE_CACHE_SHIFT and co were removed in kernel
> 4.6, as they have always been identical to the versions without _CACHE.

I see. sorry, I reworked these remaining patches with 3.16 so you will
hit the issue with applying them again.

I will post them shortly soon. Good news is that regression tests are
ok. The patchset will start from 2nd patch. I think there is no need to
re-post the patch you created.

> 
> > Anyway because readdir() is not aware of fs endianess (because 0004
> > patch is not in there) the hp-ux tests will fail with some general
> > protection fault very likely.
> 
> I think all readdir structures are fixed up now, please check.

right.

> 
> > I can't see also patches which fix these obvious bugs like freeing
> > kmem_cache_alloc() objects with kfree.
> > Even worse is releasing inode->i_private from the "evict_inode"
> > callback.
> > This leads to dangling objects in vxfs's kmem_cache when the fs is
> > unmounted. Destroying cache on module unload causes kmem_cache_destroy
> > to complain about it and after a few tries ((module load, mount, some
> > ops on mountpoint, unmount, unload) x few times) hard lockup is
> > inevitable.
> 
> Yeah, this was just getting started.  I've spent some more time on the
> whole inode issues and have implemented this a bit different from what
> you did, although the end result is very similar.  Can you take a look
> at the tree here:
> 
> 	http://git.infradead.org/users/hch/vfs.git/shortlog/refs/heads/freevxfs
> 
> > Do you think other patches should be updated with regard to the patch
> > you sent ?
> 


okay .. once again we did the same thing in parallel without a mutex ...
will see your solution.

we will need to sort out which one is better and/or looks better.
I am afraid that I may loose because don't care about tabs&spaces.


> Please take a look at the branch above.  The only major thing that
> should be missing is your directory code refactoring.

Thanks. yes, the old readdir has a bug. this time my change logs are
more verbose.


-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset r3, 2/4
  2016-06-01  8:38         ` Krzysztof Błaszkowski
@ 2016-06-01  8:41           ` Krzysztof Błaszkowski
  2016-06-01  8:42           ` freevxfs: hp-ux support. patchset r3 3/4 Krzysztof Błaszkowski
  2016-06-01  8:43           ` freevxfs: hp-ux support. patchset r3 4/4 Krzysztof Błaszkowski
  2 siblings, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-01  8:41 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

>From 01d4fc410f9a9f011eec55055b341c3aa52bfb4e Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 1 Jun 2016 09:17:13 +0200
Subject: [PATCH 2/3] inode cache mgmt

Proper inode allocation policy requires to use super_operations.alloc_inode
and .destroy_inode callbacks. This solution requires file system specific
inode structure to be derived from generic struct inode.
Because old approach of allocating generic inode private data is proper
no longer the vxfs_blkiget()/_stiget() had to be redesigned and these functions
return now the generic inode pointer. This change impacted vxfs_read_fshead()
and it was also a time to fix bugs in read_fshead's error handling path like
kfree(kmem_cache_alloc()) in the old code.

Signed-off-by: Krzysztof Błaszkowski <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs.h        |    8 ---
 fs/freevxfs/vxfs_bmap.c   |    5 +-
 fs/freevxfs/vxfs_extern.h |   19 +++---
 fs/freevxfs/vxfs_fshead.c |  107 ++++++++++++++------------------
 fs/freevxfs/vxfs_inode.c  |  153 +++++++++++++++++++++++++--------------------
 fs/freevxfs/vxfs_inode.h  |   16 +++++-
 fs/freevxfs/vxfs_super.c  |   43 ++++++-------
 7 files changed, 182 insertions(+), 169 deletions(-)

diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 4b561de..8b0d1a2 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -155,7 +155,6 @@ struct vxfs_sb {
 	 */
 };
 
-
 /*
  * In core superblock filesystem private data for VxFS.
  */
@@ -272,13 +271,6 @@ enum {
 #define VXFS_ISIMMED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
 #define VXFS_ISTYPED(ip)	VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
 
-
-/*
- * Get filesystem private data from VFS inode.
- */
-#define VXFS_INO(ip) \
-	((struct vxfs_inode_info *)(ip)->i_private)
-
 /*
  * Get filesystem private data from VFS superblock.
  */
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index 1fd41cf..333093c 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -99,8 +99,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
 
 		brelse(buf);
 		return bno;
-	} else
-		printk(KERN_WARNING "no matching indir?");
+	} else {
+		printk(KERN_WARNING "%s:%d no matching indir?\n", __func__, __LINE__);
+	}
 
 	return 0;
 
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 881aa3d..9648735 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -55,15 +55,18 @@ 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 *);
-extern void			vxfs_put_fake_inode(struct inode *);
-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 struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
+extern struct inode *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 int vxfs_ii_cache_init(void);
+extern void vxfs_ii_cache_destroy(void);
+extern struct inode *vxfs_inode_alloc(struct super_block *sb);
+
 
 /* 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 e7501cb..0f3a806 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -86,6 +86,9 @@ vxfs_getfsh(struct inode *ip, int which)
 		memcpy(fhp, bp->b_data, sizeof(*fhp));
 
 		put_bh(bp);
+#ifdef DIAGNOSTIC
+		vxfs_dumpfsh(fhp);
+#endif
 		return (fhp);
 	}
 out:
@@ -93,6 +96,15 @@ out:
 	return NULL;
 }
 
+static inline void inode_err_put(struct inode **i)
+{
+	struct inode *i2 = *i;
+
+	if (i2 && !IS_ERR(i2))
+		iput(i2);
+	*i = NULL;
+}
+
 /**
  * vxfs_read_fshead - read the fileset headers
  * @sbp:	superblock to which the fileset belongs
@@ -107,98 +119,73 @@ int
 vxfs_read_fshead(struct super_block *sbp)
 {
 	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
-	struct vxfs_fsh			*pfp, *sfp;
-	struct vxfs_inode_info		*vip, *tip;
+	struct vxfs_fsh *pfp = NULL;
+	struct vxfs_fsh *sfp = NULL;
+	struct inode *ip1;
+	struct inode *ip2;
 
-	vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
-	if (!vip) {
+	infp->vsi_fship = ip1 = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
+	if (!ip1 || IS_ERR(ip1)) {
 		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
 		return -EINVAL;
 	}
-	if (!VXFS_ISFSH(vip)) {
+
+	if (!VXFS_ISFSH(VXFS_INO(ip1))) {
 		printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
-				vip->vii_mode & VXFS_TYPE_MASK); 
-		goto out_free_fship;
+				VXFS_INO(ip1)->vii_mode & VXFS_TYPE_MASK);
+		goto out_err;
 	}
 
-
 #ifdef DIAGNOSTIC
 	printk("vxfs: fsh inode dump:\n");
-	vxfs_dumpi(vip, infp->vsi_fshino);
+	vxfs_dumpi(VXFS_INO(ip1), infp->vsi_fshino);
 #endif
 
-	infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
-	if (!infp->vsi_fship) {
-		printk(KERN_ERR "vxfs: unable to get fsh inode\n");
-		goto out_free_fship;
-	}
-
 	sfp = vxfs_getfsh(infp->vsi_fship, 0);
 	if (!sfp) {
 		printk(KERN_ERR "vxfs: unable to get structural fsh\n");
-		goto out_iput_fship;
-	} 
-
-#ifdef DIAGNOSTIC
-	vxfs_dumpfsh(sfp);
-#endif
+		goto out_err;
+	}
 
 	pfp = vxfs_getfsh(infp->vsi_fship, 1);
 	if (!pfp) {
 		printk(KERN_ERR "vxfs: unable to get primary fsh\n");
-		goto out_free_sfp;
+		goto out_err;
 	}
 
-#ifdef DIAGNOSTIC
-	vxfs_dumpfsh(pfp);
-#endif
-
-	tip = vxfs_blkiget(sbp, infp->vsi_iext,
-			fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
-	if (!tip)
-		goto out_free_pfp;
-
-	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);
-		goto out_free_pfp;
+	infp->vsi_stilist =
+		ip2 = vxfs_blkiget(sbp, infp->vsi_iext,
+		    fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
+	if (!ip2 || IS_ERR(ip2)) {
+		goto out_err;
 	}
+
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
 		printk(KERN_ERR "vxfs: structural list inode is of wrong type (%x)\n",
-				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK); 
-		goto out_iput_stilist;
+				VXFS_INO(infp->vsi_stilist)->vii_mode & VXFS_TYPE_MASK);
+		goto out_err;
 	}
 
-	tip = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
-	if (!tip)
-		goto out_iput_stilist;
-	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
-	if (!infp->vsi_ilist) {
+	infp->vsi_ilist = ip2 = vxfs_stiget(sbp,
+	    fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
+	if (!ip2 || IS_ERR(ip2)) {
 		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
-		kfree(tip);
-		goto out_iput_stilist;
+		goto out_err;
 	}
+
 	if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
 		printk(KERN_ERR "vxfs: inode list inode is of wrong type (%x)\n",
 				VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
-		goto out_iput_ilist;
+		goto out_err;
 	}
-
+	kfree(pfp);
+	kfree(sfp);
 	return 0;
-
- out_iput_ilist:
- 	iput(infp->vsi_ilist);
- out_iput_stilist:
- 	iput(infp->vsi_stilist);
- out_free_pfp:
+out_err:
+	inode_err_put(&infp->vsi_fship);
+	inode_err_put(&infp->vsi_ilist);
+	inode_err_put(&infp->vsi_stilist);
 	kfree(pfp);
- out_free_sfp:
- 	kfree(sfp);
- out_iput_fship:
-	iput(infp->vsi_fship);
-	return -EINVAL;
- out_free_fship:
- 	kfree(vip);
+	kfree(sfp);
 	return -EINVAL;
 }
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index ab54ab3..582d652 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -41,7 +41,8 @@
 #include "vxfs_extern.h"
 
 
-struct kmem_cache		*vxfs_inode_cachep;
+static struct kmem_cache *vxfs_inode_cachep;
+static void vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip);
 
 
 #ifdef DIAGNOSTIC
@@ -111,35 +112,41 @@ static inline void dip2vip_cpy(struct vxfs_sb_info *sbi,
  *  buffercache.  This function should not be used outside the
  *  read_super() method, otherwise the data may be incoherent.
  */
-struct vxfs_inode_info *
+struct inode *
 vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
 {
 	struct buffer_head		*bp;
 	u_long				block, offset;
+	struct inode *ip;
 
 	block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
 	offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
+	ip = new_inode(sbp);
+	if (!ip)
+		return ERR_PTR(-ENOMEM);
+
 	bp = sb_bread(sbp, block);
+	ip->i_ino = get_next_ino();
+	ip->i_mapping->a_ops = &vxfs_aops;
 
 	if (bp && buffer_mapped(bp)) {
-		struct vxfs_inode_info	*vip;
+		struct vxfs_inode_info	*vip = VXFS_INO(ip);
 		struct vxfs_dinode	*dip;
 
-		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
-			goto fail;
 		dip = (struct vxfs_dinode *)(bp->b_data + offset);
 		dip2vip_cpy(VXFS_SBI(sbp), vip, dip);
+		vxfs_iinit(ip, vip);
 #ifdef DIAGNOSTIC
 		vxfs_dumpi(vip, ino);
 #endif
-		brelse(bp);
-		return (vip);
+	} else {
+		printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
+		iput(ip);
+		ip = NULL;
 	}
 
-fail:
-	printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
 	brelse(bp);
-	return NULL;
+	return ip;
 }
 
 /**
@@ -154,21 +161,18 @@ fail:
  *  Returns the matching VxFS inode on success, else an error code.
  */
 static struct vxfs_inode_info *
-__vxfs_iget(ino_t ino, struct inode *ilistp)
+__vxfs_iget(struct inode *ip, struct inode *ilistp, ino_t ino)
 {
-	struct page			*pp;
-	u_long				offset;
+	struct page	*pp;
+	u_long offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
 
-	offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE;
 	pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
 
 	if (!IS_ERR(pp)) {
-		struct vxfs_inode_info	*vip;
+		struct vxfs_inode_info	*vip = VXFS_INO(ip);
 		struct vxfs_dinode	*dip;
 		caddr_t			kaddr = (char *)page_address(pp);
 
-		if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
-			goto fail;
 		dip = (struct vxfs_dinode *)(kaddr + offset);
 		dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip);
 #ifdef DIAGNOSTIC
@@ -180,11 +184,6 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
 
 	printk(KERN_WARNING "vxfs: error on page %p\n", pp);
 	return ERR_CAST(pp);
-
-fail:
-	printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
-	vxfs_put_page(pp);
-	return ERR_PTR(-ENOMEM);
 }
 
 /**
@@ -197,13 +196,24 @@ fail:
  *  the structural inode list.
  *  Returns the matching VxFS inode on success, else a NULL pointer.
  */
-struct vxfs_inode_info *
+struct inode *
 vxfs_stiget(struct super_block *sbp, ino_t ino)
 {
-	struct vxfs_inode_info *vip;
+	struct inode *ip = new_inode(sbp);
+	struct vxfs_inode_info *ii;
 
-	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
-	return IS_ERR(vip) ? NULL : vip;
+	if (!ip)
+		return NULL;
+
+	ip->i_ino = get_next_ino();
+	ip->i_mapping->a_ops = &vxfs_aops;
+	ii = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_stilist, ino);
+	if (IS_ERR(ii)) {
+		iput(ip);
+	} else {
+		vxfs_iinit(ip, ii);
+	}
+	return IS_ERR(ii) ? NULL : ip;
 }
 
 /**
@@ -271,41 +281,6 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
 	
 }
 
-/**
- * vxfs_get_fake_inode - get fake inode structure
- * @sbp:		filesystem superblock
- * @vip:		fspriv inode
- *
- * Description:
- *  vxfs_fake_inode gets a fake inode (not in the inode hash) for a
- *  superblock, vxfs_inode pair.
- *  Returns the filled VFS inode.
- */
-struct inode *
-vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
-{
-	struct inode			*ip = NULL;
-
-	if ((ip = new_inode(sbp))) {
-		ip->i_ino = get_next_ino();
-		vxfs_iinit(ip, vip);
-		ip->i_mapping->a_ops = &vxfs_aops;
-	}
-	return (ip);
-}
-
-/**
- * vxfs_put_fake_inode - free faked inode
- * *ip:			VFS inode
- *
- * Description:
- *  vxfs_put_fake_inode frees all data associated with @ip.
- */
-void
-vxfs_put_fake_inode(struct inode *ip)
-{
-	iput(ip);
-}
 
 /**
  * vxfs_iget - get an inode
@@ -329,7 +304,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
 	if (!(ip->i_state & I_NEW))
 		return ip;
 
-	vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
+	vip = __vxfs_iget(ip, VXFS_SBI(sbp)->vsi_ilist, ino);
 	if (IS_ERR(vip)) {
 		iget_failed(ip);
 		return ERR_CAST(vip);
@@ -367,21 +342,65 @@ 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);
+	struct vxfs_vfs_inode *i = container_of(inode, struct vxfs_vfs_inode, ino);
+
+	kmem_cache_free(vxfs_inode_cachep, i);
+}
+
+void vxfs_destroy_inode(struct inode *ip)
+{
+	call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
 
 /**
- * vxfs_evict_inode - remove inode from main memory
+ * vxfs_evict_inode - commit inode buffers if needed, may delete on-disk inode.
  * @ip:		inode to discard.
  *
  * Description:
- *  vxfs_evict_inode() is called on the final iput and frees the private
- *  inode area.
+ *  vxfs_evict_inode() may be 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);
 }
+
+
+
+
+struct inode *vxfs_inode_alloc(struct super_block *sb)
+{
+	struct vxfs_vfs_inode *i = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
+
+	return i ? &i->ino : NULL;
+}
+
+static void vxfs_inode_constructor(void *ptr)
+{
+	struct vxfs_vfs_inode *i = (struct vxfs_vfs_inode *) ptr;
+
+	inode_init_once(&i->ino);
+}
+
+int vxfs_ii_cache_init(void)
+{
+	vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
+		sizeof(struct vxfs_vfs_inode), 0,
+		SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, vxfs_inode_constructor);
+
+	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_inode.h b/fs/freevxfs/vxfs_inode.h
index 3a29662..f372677 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -37,7 +37,6 @@
  * inodes of the Veritas Filesystem.
  */
 
-
 #define VXFS_ISIZE		0x100		/* Inode size */
 
 #define VXFS_NDADDR		10		/* Number of direct addrs in inode */
@@ -178,6 +177,12 @@ struct vxfs_inode_info {
 	} vii_org;
 };
 
+struct vxfs_vfs_inode {
+	struct inode ino;
+	struct vxfs_inode_info cpufs_ino;
+};
+
+
 #define vii_rdev	vii_ftarea.rdev
 #define vii_dotdot	vii_ftarea.dotdot
 
@@ -185,4 +190,13 @@ struct vxfs_inode_info {
 #define vii_ext4	vii_org.ext4
 #define vii_typed	vii_org.typed
 
+/*
+ * Get filesystem private data from VFS inode.
+ */
+static inline struct vxfs_inode_info *VXFS_INO(struct inode *i)
+{
+	return &(container_of(i, struct vxfs_vfs_inode, ino))->cpufs_ino;
+}
+
+
 #endif /* _VXFS_INODE_H_ */
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 6124091..efa3bc2 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -59,6 +59,8 @@ 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 = {
+	.alloc_inode = vxfs_inode_alloc,
+	.destroy_inode = vxfs_destroy_inode,
 	.evict_inode =		vxfs_evict_inode,
 	.put_super =		vxfs_put_super,
 	.statfs =		vxfs_statfs,
@@ -79,9 +81,9 @@ vxfs_put_super(struct super_block *sbp)
 {
 	struct vxfs_sb_info	*infp = VXFS_SBI(sbp);
 
-	vxfs_put_fake_inode(infp->vsi_fship);
-	vxfs_put_fake_inode(infp->vsi_ilist);
-	vxfs_put_fake_inode(infp->vsi_stilist);
+	iput(infp->vsi_fship);
+	iput(infp->vsi_ilist);
+	iput(infp->vsi_stilist);
 
 	brelse(infp->vsi_bp);
 	kfree(infp);
@@ -253,17 +255,18 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 		goto out;
 	}
 
+
 	if (vxfs_read_olt(sbp, bsize)) {
 		printk(KERN_WARNING "vxfs: unable to read olt\n");
 		goto out;
 	}
 
+	sbp->s_op = &vxfs_super_ops;
 	if (vxfs_read_fshead(sbp)) {
 		printk(KERN_WARNING "vxfs: unable to read fshead\n");
 		goto out;
 	}
 
-	sbp->s_op = &vxfs_super_ops;
 	root = vxfs_iget(sbp, VXFS_ROOT_INO);
 	if (IS_ERR(root)) {
 		ret = PTR_ERR(root);
@@ -278,9 +281,9 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 	return 0;
 	
 out_free_ilist:
-	vxfs_put_fake_inode(infp->vsi_fship);
-	vxfs_put_fake_inode(infp->vsi_ilist);
-	vxfs_put_fake_inode(infp->vsi_stilist);
+	iput(infp->vsi_fship);
+	iput(infp->vsi_ilist);
+	iput(infp->vsi_stilist);
 out:
 	brelse(infp->vsi_bp);
 	kfree(infp);
@@ -309,29 +312,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





> 
> > Please take a look at the branch above.  The only major thing that
> > should be missing is your directory code refactoring.
> 
> Thanks. yes, the old readdir has a bug. this time my change logs are
> more verbose.
> 
> 
> -- 
> Krzysztof Blaszkowski
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset r3 3/4
  2016-06-01  8:38         ` Krzysztof Błaszkowski
  2016-06-01  8:41           ` freevxfs: hp-ux support. patchset r3, 2/4 Krzysztof Błaszkowski
@ 2016-06-01  8:42           ` Krzysztof Błaszkowski
  2016-06-02  8:32             ` Christoph Hellwig
  2016-06-01  8:43           ` freevxfs: hp-ux support. patchset r3 4/4 Krzysztof Błaszkowski
  2 siblings, 1 reply; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-01  8:42 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

>From d3f13779deb42928ad1652604b941801fd8444cd Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 1 Jun 2016 09:17:43 +0200
Subject: [PATCH 3/3] readdir fix

the patch makes algorithm of walking over directory records simple
because it is linear. The idea is to evaluate page relative number,
file system block number inside the mapped page, and finally current
directory record offset from single index (pos or ctx->pos) advanced 
by size of directory record (and the length of dirblk record at 
beginning of every fs block). Thus the inner "for" (old code)
is not necessary. Furthermore, lack of the inner for fixes the issue
with accessing kaddr one block size beyond mapped page.
correct "for" should look like this:
 "for ( ; ... block < pblocks ; block++)" : "<" vs "<="
let's suppose pblocks is 4, thus last block would be 4 (old "for")
which stands for that 5th block would be parsed and this resulted in
adding some random garbage to e.g. ls output. it used to happen that
some files were missing in the directory list.

anyway the "for" is no longer needed and the vxfs directory holding
almost 2900 files was useful to verify the readdir().


Signed-off-by: Krzysztof Błaszkowski <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs_lookup.c |  268 +++++++++++++++++++++------------------------
 1 files changed, 125 insertions(+), 143 deletions(-)

diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 31bcebe..c9de653 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -61,42 +61,8 @@ 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(struct vxfs_sb_info *sbi, int len, const char *const name,
-		struct vxfs_direct *de)
-{
-	if (len != fs16_to_cpu(sbi, 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_sb_info *sbi, struct vxfs_direct *de)
-{
-	return ((struct vxfs_direct *)
-		((char *)de + fs16_to_cpu(sbi, de->d_reclen)));
-}
 
 /**
  * vxfs_find_entry - find a mathing directory entry for a dentry
@@ -115,53 +81,65 @@ vxfs_next_entry(struct vxfs_sb_info *sbi, struct vxfs_direct *de)
 static struct vxfs_direct *
 vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
 {
-	struct vxfs_sb_info		*sbi = VXFS_SBI(ip->i_sb);
-	u_long				npages, page, nblocks, pblocks, block;
-	u_long				bsize = ip->i_sb->s_blocksize;
-	const char			*name = dp->d_name.name;
-	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(sbi, dbp));
-
-			for (; (caddr_t)de <= limit;
-					de = vxfs_next_entry(sbi, de)) {
-				if (!de->d_reclen)
-					break;
-				if (!de->d_ino)
-					continue;
-				if (vxfs_match(sbi, 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;
+	struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
+
+	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(sbi, 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(sbi, de->d_reclen);
+			pos += fs16_to_cpu(sbi, de->d_reclen);
+			if (!de->d_ino) {
+				continue;
+			}
+
+			if (namelen != fs16_to_cpu(sbi, 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;
 }
 
 /**
@@ -181,7 +159,7 @@ 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) {
@@ -189,7 +167,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
 		kunmap(pp);
 		page_cache_release(pp);
 	}
-	
+
 	return (ino);
 }
 
@@ -212,17 +190,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;
 }
 
@@ -244,80 +222,84 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
 {
 	struct inode		*ip = file_inode(fp);
 	struct super_block	*sbp = ip->i_sb;
-	struct vxfs_sb_info	*sbi = VXFS_SBI(sbp);
 	u_long			bsize = sbp->s_blocksize;
-	u_long			page, npages, block, pblocks, nblocks, offset;
-	loff_t			pos;
-
+	loff_t			pos, limit;
+	struct vxfs_sb_info	*sbi = VXFS_SBI(sbp);
 
 	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(sbi, dbp)));
-
-			for (; (char *)de <= limit;
-					de = vxfs_next_entry(sbi, 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(sbi, de->d_namelen),
-						fs32_to_cpu(sbi, 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(sbi, 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(sbi, de->d_reclen);
+			pos += fs16_to_cpu(sbi, de->d_reclen);
+			if (!de->d_ino) {
+				continue;
+			}
+
+			rc = dir_emit(ctx, de->d_name, fs16_to_cpu(sbi, de->d_namelen),
+				fs32_to_cpu(sbi, de->d_ino), DT_UNKNOWN);
+			if (!rc) {
+				/* the dir entry was not submitted, so fix pos. */
+				pos -= fs16_to_cpu(sbi, 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



> 
> Thanks. yes, the old readdir has a bug. this time my change logs are
> more verbose.
> 
> 
> -- 
> Krzysztof Blaszkowski
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset r3 4/4
  2016-06-01  8:38         ` Krzysztof Błaszkowski
  2016-06-01  8:41           ` freevxfs: hp-ux support. patchset r3, 2/4 Krzysztof Błaszkowski
  2016-06-01  8:42           ` freevxfs: hp-ux support. patchset r3 3/4 Krzysztof Błaszkowski
@ 2016-06-01  8:43           ` Krzysztof Błaszkowski
  2 siblings, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-01  8:43 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

>From 802178068cf8bbf8a7c9c4b4efbb6a4108b1946b Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 1 Jun 2016 10:13:00 +0200
Subject: [PATCH 4/4] the credits


Signed-off-by: Krzysztof Błaszkowski <kb@sysmikro.com.pl>
---
 fs/freevxfs/Kconfig       |   10 +++++++++-
 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 +++++-
 6 files changed, 29 insertions(+), 2 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.
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 8b0d1a2..6f89a32 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
+ *       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 0f3a806..dd4e394 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
+ *       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 582d652..845b881 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
+ *       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 c9de653..ab495f5 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
+ *       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 efa3bc2..ece9691 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
+ *       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


> 
> > Please take a look at the branch above.  The only major thing that
> > should be missing is your directory code refactoring.
> 
> Thanks. yes, the old readdir has a bug. this time my change logs are
> more verbose.
> 
> 
> -- 
> Krzysztof Blaszkowski
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-06-01  7:33       ` Christoph Hellwig
  2016-06-01  8:38         ` Krzysztof Błaszkowski
@ 2016-06-01  9:23         ` Krzysztof Błaszkowski
  2016-06-02  8:25           ` Christoph Hellwig
  2016-06-01  9:27         ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
  2 siblings, 1 reply; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-01  9:23 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

Hi Christoph,

On Wed, 2016-06-01 at 00:33 -0700, Christoph Hellwig wrote:

> Yeah, this was just getting started.  I've spent some more time on the
> whole inode issues and have implemented this a bit different from what
> you did, although the end result is very similar.  Can you take a look
> at the tree here:
> 
> 	http://git.infradead.org/users/hch/vfs.git/shortlog/refs/heads/freevxfs
> 
> > Do you think other patches should be updated with regard to the patch
> > you sent ?
> 
> Please take a look at the branch above.  

I think that there are no "kfree(pfp); kfree(sfp); return 0;" in
vxfs_read_fshead() still. Are pfp and sfp needed anywhere ? I am sure
they are not so there is a memory leak without these kfrees every mount.

I am not sure absolutely of that read_fshead() is missing these kfrees
because I have seen just these diffs, anyway I did not notice "+kfree".

so .. whose patch is more accurate ?

needles to say that I prefer to have limited scope of visibility of
inode_cachep to the inode.c only.

Thanks,

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-06-01  7:33       ` Christoph Hellwig
  2016-06-01  8:38         ` Krzysztof Błaszkowski
  2016-06-01  9:23         ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
@ 2016-06-01  9:27         ` Krzysztof Błaszkowski
  2 siblings, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-01  9:27 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel


I forgot to say that 
http://git.infradead.org/users/hch/vfs.git/commit/1cce17017970c0797943e069cc520e17d068ca4b

looks good. I am fine with it so let's forget about 4th "the credits"
patch I have posted.

Thanks !

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-06-01  9:23         ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
@ 2016-06-02  8:25           ` Christoph Hellwig
  2016-06-02  9:16             ` Krzysztof Błaszkowski
  2016-06-10 14:46             ` freevxfs: hp-ux support. ( 1cce17017970c07) patchset 1/4 Krzysztof Błaszkowski
  0 siblings, 2 replies; 21+ messages in thread
From: Christoph Hellwig @ 2016-06-02  8:25 UTC (permalink / raw)
  To: Krzysztof B??aszkowski; +Cc: Christoph Hellwig, Carlos Maiolino, linux-fsdevel

On Wed, Jun 01, 2016 at 11:23:32AM +0200, Krzysztof B??aszkowski wrote:
> I think that there are no "kfree(pfp); kfree(sfp); return 0;" in
> vxfs_read_fshead() still. Are pfp and sfp needed anywhere ? I am sure
> they are not so there is a memory leak without these kfrees every mount.
> 
> I am not sure absolutely of that read_fshead() is missing these kfrees
> because I have seen just these diffs, anyway I did not notice "+kfree".

The frees are still missing.  Do you want to send me a patch for those?

> needles to say that I prefer to have limited scope of visibility of
> inode_cachep to the inode.c only.

In my tree the visibility is in vxfs_super.c only.  Given that the
alloc/destroy methods are super operations that seems to fit better
as they can have local scope, too.

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

* Re: freevxfs: hp-ux support. patchset r3 3/4
  2016-06-01  8:42           ` freevxfs: hp-ux support. patchset r3 3/4 Krzysztof Błaszkowski
@ 2016-06-02  8:32             ` Christoph Hellwig
  2016-06-02  9:18               ` Krzysztof Błaszkowski
  0 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2016-06-02  8:32 UTC (permalink / raw)
  To: Krzysztof B??aszkowski; +Cc: Christoph Hellwig, Carlos Maiolino, linux-fsdevel

> -static inline u_long
> -dir_pages(struct inode *inode)
> -{
> -	return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
> -}

This is still against a different tree than my branch, right?

Othwrwise the readdir changes look fine minus a few very minor
codingstyle issues that I'll happily fix up

> @@ -212,17 +190,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;

This change is unrelated to the readdir changes, and it looks incorrect
to me.  If we don't find an inode for a lookup we still want to call
d_add with a NULL inode - this creates a so called negative dentry,
which tells the VFS to not bother looking up this file name next time.

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

* Re: freevxfs: hp-ux support. patchset 1-7/7 rev 2
  2016-06-02  8:25           ` Christoph Hellwig
@ 2016-06-02  9:16             ` Krzysztof Błaszkowski
  2016-06-10 14:46             ` freevxfs: hp-ux support. ( 1cce17017970c07) patchset 1/4 Krzysztof Błaszkowski
  1 sibling, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-02  9:16 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

On Thu, 2016-06-02 at 01:25 -0700, Christoph Hellwig wrote:
> On Wed, Jun 01, 2016 at 11:23:32AM +0200, Krzysztof B??aszkowski wrote:
> > I think that there are no "kfree(pfp); kfree(sfp); return 0;" in
> > vxfs_read_fshead() still. Are pfp and sfp needed anywhere ? I am sure
> > they are not so there is a memory leak without these kfrees every mount.
> > 
> > I am not sure absolutely of that read_fshead() is missing these kfrees
> > because I have seen just these diffs, anyway I did not notice "+kfree".
> 
> The frees are still missing.  Do you want to send me a patch for those?

I see. Don't hesitate to add them, I was thinking that creating a
special patch because of these just two kfree()s is just too much formal
work.

> 
> > needles to say that I prefer to have limited scope of visibility of
> > inode_cachep to the inode.c only.
> 
> In my tree the visibility is in vxfs_super.c only.  Given that the
> alloc/destroy methods are super operations that seems to fit better
> as they can have local scope, too.

I see. We differ in point of views. I presumed that it is more
consistent to have everything regarding inodes creation
(getting)/destroying, etc in the inode.c. Anyway this is just pure
academic debate, we could argue on anything else (weather, politics and
politicians - hot topic especially in Poland) as well.

You decide. You enjoy more your approach - good enough.


-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. patchset r3 3/4
  2016-06-02  8:32             ` Christoph Hellwig
@ 2016-06-02  9:18               ` Krzysztof Błaszkowski
  0 siblings, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-02  9:18 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

On Thu, 2016-06-02 at 01:32 -0700, Christoph Hellwig wrote:
> > -static inline u_long
> > -dir_pages(struct inode *inode)
> > -{
> > -	return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
> > -}
> 
> This is still against a different tree than my branch, right?

yes, it is.

> 
> Othwrwise the readdir changes look fine minus a few very minor
> codingstyle issues that I'll happily fix up

many thanks :)

> 
> > @@ -212,17 +190,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;
> 
> This change is unrelated to the readdir changes, and it looks incorrect
> to me.  If we don't find an inode for a lookup we still want to call
> d_add with a NULL inode - this creates a so called negative dentry,
> which tells the VFS to not bother looking up this file name next time.

I see. Thank you for explanation of d_add() semantics, so you are right,
it was wrong change.


> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Krzysztof Blaszkowski


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

* Re: freevxfs: hp-ux support. ( 1cce17017970c07) patchset 1/4
  2016-06-02  8:25           ` Christoph Hellwig
  2016-06-02  9:16             ` Krzysztof Błaszkowski
@ 2016-06-10 14:46             ` Krzysztof Błaszkowski
  1 sibling, 0 replies; 21+ messages in thread
From: Krzysztof Błaszkowski @ 2016-06-10 14:46 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Carlos Maiolino, linux-fsdevel

Christoph,

Here are these kfree()s.


>From e82e484492af7a66b25510718783529bad345cfc Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Fri, 10 Jun 2016 09:52:19 +0200
Subject: [PATCH 1/4] vxfs_read_fshead() memory leak fixed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

every successful mount two structs vxfs_fsh were not released

Signed-off-by: Krzysztof Błaszkowski <kb@sysmikro.com.pl>
---
 fs/freevxfs/vxfs_fshead.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index 69a10d6..a4610a7 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -172,6 +172,8 @@ vxfs_read_fshead(struct super_block *sbp)
 		goto out_iput_ilist;
 	}
 
+	kfree(pfp);
+	kfree(sfp);
 	return 0;
 
  out_iput_ilist:
-- 
2.8.3




On Thu, 2016-06-02 at 01:25 -0700, Christoph Hellwig wrote:
> On Wed, Jun 01, 2016 at 11:23:32AM +0200, Krzysztof B??aszkowski wrote:
> > I think that there are no "kfree(pfp); kfree(sfp); return 0;" in
> > vxfs_read_fshead() still. Are pfp and sfp needed anywhere ? I am sure
> > they are not so there is a memory leak without these kfrees every mount.
> > 
> > I am not sure absolutely of that read_fshead() is missing these kfrees
> > because I have seen just these diffs, anyway I did not notice "+kfree".
> 
> The frees are still missing.  Do you want to send me a patch for those?
> 
> > needles to say that I prefer to have limited scope of visibility of
> > inode_cachep to the inode.c only.
> 
> In my tree the visibility is in vxfs_super.c only.  Given that the
> alloc/destroy methods are super operations that seems to fit better
> as they can have local scope, too.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Krzysztof Blaszkowski


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

end of thread, other threads:[~2016-06-10 14:46 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-26 14:45 freevxfs: hp-ux support. patchset 1-7/7 Krzysztof Błaszkowski
2016-05-26 15:43 ` freevxfs: hp-ux support. (working) " Krzysztof Błaszkowski
2016-05-26 15:53 ` r Christoph Hellwig
2016-05-26 17:44   ` r Krzysztof Błaszkowski
2016-05-28 19:40 ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
2016-05-30 11:19   ` Carlos Maiolino
2016-05-30 11:54     ` Krzysztof Błaszkowski
2016-05-31 12:25   ` Christoph Hellwig
2016-05-31 13:44     ` Krzysztof Błaszkowski
2016-06-01  7:33       ` Christoph Hellwig
2016-06-01  8:38         ` Krzysztof Błaszkowski
2016-06-01  8:41           ` freevxfs: hp-ux support. patchset r3, 2/4 Krzysztof Błaszkowski
2016-06-01  8:42           ` freevxfs: hp-ux support. patchset r3 3/4 Krzysztof Błaszkowski
2016-06-02  8:32             ` Christoph Hellwig
2016-06-02  9:18               ` Krzysztof Błaszkowski
2016-06-01  8:43           ` freevxfs: hp-ux support. patchset r3 4/4 Krzysztof Błaszkowski
2016-06-01  9:23         ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski
2016-06-02  8:25           ` Christoph Hellwig
2016-06-02  9:16             ` Krzysztof Błaszkowski
2016-06-10 14:46             ` freevxfs: hp-ux support. ( 1cce17017970c07) patchset 1/4 Krzysztof Błaszkowski
2016-06-01  9:27         ` freevxfs: hp-ux support. patchset 1-7/7 rev 2 Krzysztof Błaszkowski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.