diff mbox

freevxfs: hp-ux support. patchset 1-7/7 rev 2

Message ID 1464464428.3689.14.camel@linux-q3cb.site (mailing list archive)
State New, archived
Headers show

Commit Message

Krzysztof Błaszkowski May 28, 2016, 7:40 p.m. UTC
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(-)

Comments

Carlos Maiolino May 30, 2016, 11:19 a.m. UTC | #1
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
>
Krzysztof Błaszkowski May 30, 2016, 11:54 a.m. UTC | #2
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
> > 
>
diff mbox

Patch

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