Merge tag 'freevxfs-for-4.8' of git://git.infradead.org/users/hch/freevxfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Jul 2016 18:56:29 +0000 (11:56 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Jul 2016 18:56:29 +0000 (11:56 -0700)
Pull freevxfs updates from Christoph Hellwig:
 "Support for foreign endianess and HP-UP superblocks from
  Krzysztof Błaszkowski"

* tag 'freevxfs-for-4.8' of git://git.infradead.org/users/hch/freevxfs:
  freevxfs: update Kconfig information
  freevxfs: refactor readdir and lookup code
  freevxfs: fix lack of inode initialization
  freevxfs: fix memory leak in vxfs_read_fshead()
  freevxfs: update documentation and cresdits for HP-UX support
  freevxfs: implement ->alloc_inode and ->destroy_inode
  freevxfs: avoid the need for forward declaring the super operations
  freevxfs: move VFS inode allocation into vxfs_blkiget and vxfs_stiget
  freevxfs: remove vxfs_put_fake_inode
  freevxfs: handle big endian HP-UX file systems

13 files changed:
fs/freevxfs/Kconfig
fs/freevxfs/vxfs.h
fs/freevxfs/vxfs_bmap.c
fs/freevxfs/vxfs_dir.h
fs/freevxfs/vxfs_extern.h
fs/freevxfs/vxfs_fshead.c
fs/freevxfs/vxfs_fshead.h
fs/freevxfs/vxfs_inode.c
fs/freevxfs/vxfs_inode.h
fs/freevxfs/vxfs_lookup.c
fs/freevxfs/vxfs_olt.c
fs/freevxfs/vxfs_olt.h
fs/freevxfs/vxfs_super.c

index 8dc1cd5..ce49df1 100644 (file)
@@ -5,12 +5,21 @@ 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.
-         Currently only readonly access is supported.
+         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 and VxFX versions
+         2, 3 and 4. Tests were performed with HP-UX VxFS version 3.
 
          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.
index c8a9265..a41ea0b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  */
 #include <linux/types.h>
 
-
-/*
- * Data types for use with the VxFS ondisk format.
- */
-typedef        int32_t         vx_daddr_t;
-typedef int32_t                vx_ino_t;
-
 /*
  * Superblock magic number (vxfs_super->vs_magic).
  */
@@ -60,6 +54,14 @@ typedef int32_t              vx_ino_t;
  */
 #define VXFS_NEFREE            32
 
+enum vxfs_byte_order {
+       VXFS_BO_LE,
+       VXFS_BO_BE,
+};
+
+typedef __u16 __bitwise __fs16;
+typedef __u32 __bitwise __fs32;
+typedef __u64 __bitwise __fs64;
 
 /*
  * VxFS superblock (disk).
@@ -71,83 +73,83 @@ struct vxfs_sb {
         * Lots of this fields are no more used by version 2
         * and never filesystems.
         */
-       u_int32_t       vs_magic;               /* Magic number */
-       int32_t         vs_version;             /* VxFS version */
-       u_int32_t       vs_ctime;               /* create time - secs */
-       u_int32_t       vs_cutime;              /* create time - usecs */
-       int32_t         __unused1;              /* unused */
-       int32_t         __unused2;              /* unused */
-       vx_daddr_t      vs_old_logstart;        /* obsolete */
-       vx_daddr_t      vs_old_logend;          /* obsolete */
-       int32_t         vs_bsize;               /* block size */
-       int32_t         vs_size;                /* number of blocks */
-       int32_t         vs_dsize;               /* number of data blocks */
-       u_int32_t       vs_old_ninode;          /* obsolete */
-       int32_t         vs_old_nau;             /* obsolete */
-       int32_t         __unused3;              /* unused */
-       int32_t         vs_old_defiextsize;     /* obsolete */
-       int32_t         vs_old_ilbsize;         /* obsolete */
-       int32_t         vs_immedlen;            /* size of immediate data area */
-       int32_t         vs_ndaddr;              /* number of direct extentes */
-       vx_daddr_t      vs_firstau;             /* address of first AU */
-       vx_daddr_t      vs_emap;                /* offset of extent map in AU */
-       vx_daddr_t      vs_imap;                /* offset of inode map in AU */
-       vx_daddr_t      vs_iextop;              /* offset of ExtOp. map in AU */
-       vx_daddr_t      vs_istart;              /* offset of inode list in AU */
-       vx_daddr_t      vs_bstart;              /* offset of fdblock in AU */
-       vx_daddr_t      vs_femap;               /* aufirst + emap */
-       vx_daddr_t      vs_fimap;               /* aufirst + imap */
-       vx_daddr_t      vs_fiextop;             /* aufirst + iextop */
-       vx_daddr_t      vs_fistart;             /* aufirst + istart */
-       vx_daddr_t      vs_fbstart;             /* aufirst + bstart */
-       int32_t         vs_nindir;              /* number of entries in indir */
-       int32_t         vs_aulen;               /* length of AU in blocks */
-       int32_t         vs_auimlen;             /* length of imap in blocks */
-       int32_t         vs_auemlen;             /* length of emap in blocks */
-       int32_t         vs_auilen;              /* length of ilist in blocks */
-       int32_t         vs_aupad;               /* length of pad in blocks */
-       int32_t         vs_aublocks;            /* data blocks in AU */
-       int32_t         vs_maxtier;             /* log base 2 of aublocks */
-       int32_t         vs_inopb;               /* number of inodes per blk */
-       int32_t         vs_old_inopau;          /* obsolete */
-       int32_t         vs_old_inopilb;         /* obsolete */
-       int32_t         vs_old_ndiripau;        /* obsolete */
-       int32_t         vs_iaddrlen;            /* size of indirect addr ext. */
-       int32_t         vs_bshift;              /* log base 2 of bsize */
-       int32_t         vs_inoshift;            /* log base 2 of inobp */
-       int32_t         vs_bmask;               /* ~( bsize - 1 ) */
-       int32_t         vs_boffmask;            /* bsize - 1 */
-       int32_t         vs_old_inomask;         /* old_inopilb - 1 */
-       int32_t         vs_checksum;            /* checksum of V1 data */
+       __fs32          vs_magic;               /* Magic number */
+       __fs32          vs_version;             /* VxFS version */
+       __fs32          vs_ctime;               /* create time - secs */
+       __fs32          vs_cutime;              /* create time - usecs */
+       __fs32          __unused1;              /* unused */
+       __fs32          __unused2;              /* unused */
+       __fs32          vs_old_logstart;        /* obsolete */
+       __fs32          vs_old_logend;          /* obsolete */
+       __fs32          vs_bsize;               /* block size */
+       __fs32          vs_size;                /* number of blocks */
+       __fs32          vs_dsize;               /* number of data blocks */
+       __fs32          vs_old_ninode;          /* obsolete */
+       __fs32          vs_old_nau;             /* obsolete */
+       __fs32          __unused3;              /* unused */
+       __fs32          vs_old_defiextsize;     /* obsolete */
+       __fs32          vs_old_ilbsize;         /* obsolete */
+       __fs32          vs_immedlen;            /* size of immediate data area */
+       __fs32          vs_ndaddr;              /* number of direct extentes */
+       __fs32          vs_firstau;             /* address of first AU */
+       __fs32          vs_emap;                /* offset of extent map in AU */
+       __fs32          vs_imap;                /* offset of inode map in AU */
+       __fs32          vs_iextop;              /* offset of ExtOp. map in AU */
+       __fs32          vs_istart;              /* offset of inode list in AU */
+       __fs32          vs_bstart;              /* offset of fdblock in AU */
+       __fs32          vs_femap;               /* aufirst + emap */
+       __fs32          vs_fimap;               /* aufirst + imap */
+       __fs32          vs_fiextop;             /* aufirst + iextop */
+       __fs32          vs_fistart;             /* aufirst + istart */
+       __fs32          vs_fbstart;             /* aufirst + bstart */
+       __fs32          vs_nindir;              /* number of entries in indir */
+       __fs32          vs_aulen;               /* length of AU in blocks */
+       __fs32          vs_auimlen;             /* length of imap in blocks */
+       __fs32          vs_auemlen;             /* length of emap in blocks */
+       __fs32          vs_auilen;              /* length of ilist in blocks */
+       __fs32          vs_aupad;               /* length of pad in blocks */
+       __fs32          vs_aublocks;            /* data blocks in AU */
+       __fs32          vs_maxtier;             /* log base 2 of aublocks */
+       __fs32          vs_inopb;               /* number of inodes per blk */
+       __fs32          vs_old_inopau;          /* obsolete */
+       __fs32          vs_old_inopilb;         /* obsolete */
+       __fs32          vs_old_ndiripau;        /* obsolete */
+       __fs32          vs_iaddrlen;            /* size of indirect addr ext. */
+       __fs32          vs_bshift;              /* log base 2 of bsize */
+       __fs32          vs_inoshift;            /* log base 2 of inobp */
+       __fs32          vs_bmask;               /* ~( bsize - 1 ) */
+       __fs32          vs_boffmask;            /* bsize - 1 */
+       __fs32          vs_old_inomask;         /* old_inopilb - 1 */
+       __fs32          vs_checksum;            /* checksum of V1 data */
        
        /*
         * Version 1, writable
         */
-       int32_t         vs_free;                /* number of free blocks */
-       int32_t         vs_ifree;               /* number of free inodes */
-       int32_t         vs_efree[VXFS_NEFREE];  /* number of free extents by size */
-       int32_t         vs_flags;               /* flags ?!? */
-       u_int8_t        vs_mod;                 /* filesystem has been changed */
-       u_int8_t        vs_clean;               /* clean FS */
-       u_int16_t       __unused4;              /* unused */
-       u_int32_t       vs_firstlogid;          /* mount time log ID */
-       u_int32_t       vs_wtime;               /* last time written - sec */
-       u_int32_t       vs_wutime;              /* last time written - usec */
-       u_int8_t        vs_fname[6];            /* FS name */
-       u_int8_t        vs_fpack[6];            /* FS pack name */
-       int32_t         vs_logversion;          /* log format version */
-       int32_t         __unused5;              /* unused */
+       __fs32          vs_free;                /* number of free blocks */
+       __fs32          vs_ifree;               /* number of free inodes */
+       __fs32          vs_efree[VXFS_NEFREE];  /* number of free extents by size */
+       __fs32          vs_flags;               /* flags ?!? */
+       __u8            vs_mod;                 /* filesystem has been changed */
+       __u8            vs_clean;               /* clean FS */
+       __fs16          __unused4;              /* unused */
+       __fs32          vs_firstlogid;          /* mount time log ID */
+       __fs32          vs_wtime;               /* last time written - sec */
+       __fs32          vs_wutime;              /* last time written - usec */
+       __u8            vs_fname[6];            /* FS name */
+       __u8            vs_fpack[6];            /* FS pack name */
+       __fs32          vs_logversion;          /* log format version */
+       __u32           __unused5;              /* unused */
        
        /*
         * Version 2, Read-only
         */
-       vx_daddr_t      vs_oltext[2];           /* OLT extent and replica */
-       int32_t         vs_oltsize;             /* OLT extent size */
-       int32_t         vs_iauimlen;            /* size of inode map */
-       int32_t         vs_iausize;             /* size of IAU in blocks */
-       int32_t         vs_dinosize;            /* size of inode in bytes */
-       int32_t         vs_old_dniaddr;         /* indir levels per inode */
-       int32_t         vs_checksum2;           /* checksum of V2 RO */
+       __fs32          vs_oltext[2];           /* OLT extent and replica */
+       __fs32          vs_oltsize;             /* OLT extent size */
+       __fs32          vs_iauimlen;            /* size of inode map */
+       __fs32          vs_iausize;             /* size of IAU in blocks */
+       __fs32          vs_dinosize;            /* size of inode in bytes */
+       __fs32          vs_old_dniaddr;         /* indir levels per inode */
+       __fs32          vs_checksum2;           /* checksum of V2 RO */
 
        /*
         * Actually much more...
@@ -168,8 +170,32 @@ struct vxfs_sb_info {
        ino_t                   vsi_fshino;     /* fileset header inode */
        daddr_t                 vsi_oltext;     /* OLT extent */
        daddr_t                 vsi_oltsize;    /* OLT size */
+       enum vxfs_byte_order    byte_order;
 };
 
+static inline u16 fs16_to_cpu(struct vxfs_sb_info *sbi, __fs16 a)
+{
+       if (sbi->byte_order == VXFS_BO_BE)
+               return be16_to_cpu((__force __be16)a);
+       else
+               return le16_to_cpu((__force __le16)a);
+}
+
+static inline u32 fs32_to_cpu(struct vxfs_sb_info *sbi, __fs32 a)
+{
+       if (sbi->byte_order == VXFS_BO_BE)
+               return be32_to_cpu((__force __be32)a);
+       else
+               return le32_to_cpu((__force __le32)a);
+}
+
+static inline u64 fs64_to_cpu(struct vxfs_sb_info *sbi, __fs64 a)
+{
+       if (sbi->byte_order == VXFS_BO_BE)
+               return be64_to_cpu((__force __be64)a);
+       else
+               return le64_to_cpu((__force __le64)a);
+}
 
 /*
  * File modes.  File types above 0xf000 are vxfs internal only, they should
@@ -247,13 +273,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.
  */
index f86fd3c..1fd41cf 100644 (file)
@@ -68,8 +68,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
 {
        struct super_block *sb = ip->i_sb;
        struct vxfs_inode_info *vip = VXFS_INO(ip);
+       struct vxfs_sb_info *sbi = VXFS_SBI(sb);
        unsigned long bsize = sb->s_blocksize;
-       u32 indsize = vip->vii_ext4.ve4_indsize;
+       u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize);
        int i;
 
        if (indsize > sb->s_blocksize)
@@ -77,22 +78,24 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
 
        for (i = 0; i < VXFS_NDADDR; i++) {
                struct direct *d = vip->vii_ext4.ve4_direct + i;
-               if (bn >= 0 && bn < d->size)
-                       return (bn + d->extent);
-               bn -= d->size;
+               if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
+                       return (bn + fs32_to_cpu(sbi, d->extent));
+               bn -= fs32_to_cpu(sbi, d->size);
        }
 
        if ((bn / (indsize * indsize * bsize / 4)) == 0) {
                struct buffer_head *buf;
                daddr_t bno;
-               u32 *indir;
+               __fs32 *indir;
 
-               buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]);
+               buf = sb_bread(sb,
+                       fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0]));
                if (!buf || !buffer_mapped(buf))
                        goto fail_buf;
 
-               indir = (u32 *)buf->b_data;
-               bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
+               indir = (__fs32 *)buf->b_data;
+               bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
+                       (bn % indsize);
 
                brelse(buf);
                return bno;
@@ -127,6 +130,7 @@ fail_buf:
 static daddr_t
 vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 {
+       struct vxfs_sb_info             *sbi = VXFS_SBI(ip->i_sb);
        struct buffer_head              *bp = NULL;
        daddr_t                         pblock = 0;
        int                             i;
@@ -142,24 +146,27 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
 
                typ = ((struct vxfs_typed *)bp->b_data) +
                        (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
-               off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+               off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
 
                if (block < off) {
                        brelse(bp);
                        continue;
                }
 
-               switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+               switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >>
+                               VXFS_TYPED_TYPESHIFT)) {
                case VXFS_TYPED_INDIRECT:
-                       pblock = vxfs_bmap_indir(ip, typ->vt_block,
-                                       typ->vt_size, block - off);
+                       pblock = vxfs_bmap_indir(ip,
+                                       fs32_to_cpu(sbi, typ->vt_block),
+                                       fs32_to_cpu(sbi, typ->vt_size),
+                                       block - off);
                        if (pblock == -2)
                                break;
                        goto out;
                case VXFS_TYPED_DATA:
-                       if ((block - off) >= typ->vt_size)
+                       if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
                                break;
-                       pblock = (typ->vt_block + block - off);
+                       pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
                        goto out;
                case VXFS_TYPED_INDIRECT_DEV4:
                case VXFS_TYPED_DATA_DEV4: {
@@ -167,13 +174,15 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
                                (struct vxfs_typed_dev4 *)typ;
 
                        printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
-                       printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
-                              (unsigned long long) typ4->vd4_block,
-                              (unsigned long long) typ4->vd4_size,
-                              typ4->vd4_dev);
+                       printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
+                              fs64_to_cpu(sbi, typ4->vd4_block),
+                              fs64_to_cpu(sbi, typ4->vd4_size),
+                              fs32_to_cpu(sbi, typ4->vd4_dev));
                        goto fail;
                }
                default:
+                       printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
+                               __LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
                        BUG();
                }
                brelse(bp);
@@ -201,28 +210,33 @@ static daddr_t
 vxfs_bmap_typed(struct inode *ip, long iblock)
 {
        struct vxfs_inode_info          *vip = VXFS_INO(ip);
+       struct vxfs_sb_info             *sbi = VXFS_SBI(ip->i_sb);
        daddr_t                         pblock = 0;
        int                             i;
 
        for (i = 0; i < VXFS_NTYPED; i++) {
                struct vxfs_typed       *typ = vip->vii_org.typed + i;
-               int64_t                 off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+               u64                     hdr = fs64_to_cpu(sbi, typ->vt_hdr);
+               int64_t                 off = (hdr & VXFS_TYPED_OFFSETMASK);
 
 #ifdef DIAGNOSTIC
                vxfs_typdump(typ);
 #endif
                if (iblock < off)
                        continue;
-               switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+               switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
                case VXFS_TYPED_INDIRECT:
-                       pblock = vxfs_bmap_indir(ip, typ->vt_block,
-                                       typ->vt_size, iblock - off);
+                       pblock = vxfs_bmap_indir(ip,
+                                       fs32_to_cpu(sbi, typ->vt_block),
+                                       fs32_to_cpu(sbi, typ->vt_size),
+                                       iblock - off);
                        if (pblock == -2)
                                break;
                        return (pblock);
                case VXFS_TYPED_DATA:
-                       if ((iblock - off) < typ->vt_size)
-                               return (typ->vt_block + iblock - off);
+                       if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
+                               return (fs32_to_cpu(sbi, typ->vt_block) +
+                                               iblock - off);
                        break;
                case VXFS_TYPED_INDIRECT_DEV4:
                case VXFS_TYPED_DATA_DEV4: {
@@ -230,10 +244,10 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
                                (struct vxfs_typed_dev4 *)typ;
 
                        printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
-                       printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
-                              (unsigned long long) typ4->vd4_block,
-                              (unsigned long long) typ4->vd4_size,
-                              typ4->vd4_dev);
+                       printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
+                              fs64_to_cpu(sbi, typ4->vd4_block),
+                              fs64_to_cpu(sbi, typ4->vd4_size),
+                              fs32_to_cpu(sbi, typ4->vd4_dev));
                        return 0;
                }
                default:
index aaf1fb0..acc5477 100644 (file)
@@ -48,9 +48,9 @@
  * Linux driver for now.
  */
 struct vxfs_dirblk {
-       u_int16_t       d_free;         /* free space in dirblock */
-       u_int16_t       d_nhash;        /* no of hash chains */
-       u_int16_t       d_hash[1];      /* hash chain */
+       __fs16          d_free;         /* free space in dirblock */
+       __fs16          d_nhash;        /* no of hash chains */
+       __fs16          d_hash[1];      /* hash chain */
 };
 
 /*
@@ -63,10 +63,10 @@ struct vxfs_dirblk {
  * VxFS directory entry.
  */
 struct vxfs_direct {
-       vx_ino_t        d_ino;                  /* inode number */
-       u_int16_t       d_reclen;               /* record length */
-       u_int16_t       d_namelen;              /* d_name length */
-       u_int16_t       d_hashnext;             /* next hash entry */
+       __fs32          d_ino;                  /* inode number */
+       __fs16          d_reclen;               /* record length */
+       __fs16          d_namelen;              /* d_name length */
+       __fs16          d_hashnext;             /* next hash entry */
        char            d_name[VXFS_NAMELEN];   /* name */
 };
 
@@ -87,6 +87,7 @@ struct vxfs_direct {
 /*
  * VXFS_DIRBLKOV is the overhead of a specific dirblock.
  */
-#define VXFS_DIRBLKOV(dbp)     ((sizeof(short) * dbp->d_nhash) + 4)
+#define VXFS_DIRBLKOV(sbi, dbp)        \
+       ((sizeof(short) * fs16_to_cpu(sbi, dbp->d_nhash)) + 4)
 
 #endif /* _VXFS_DIR_H_ */
index e3dcb44..f5c428e 100644 (file)
@@ -52,14 +52,10 @@ extern int                  vxfs_read_fshead(struct super_block *);
 
 /* vxfs_inode.c */
 extern const struct address_space_operations vxfs_immed_aops;
-extern struct kmem_cache       *vxfs_inode_cachep;
 extern void                    vxfs_dumpi(struct vxfs_inode_info *, ino_t);
-extern struct inode *          vxfs_get_fake_inode(struct super_block *,
-                                       struct vxfs_inode_info *);
-extern void                    vxfs_put_fake_inode(struct inode *);
-extern struct vxfs_inode_info *        vxfs_blkiget(struct super_block *, u_long, ino_t);
-extern struct vxfs_inode_info *        vxfs_stiget(struct super_block *, ino_t);
-extern struct inode *          vxfs_iget(struct super_block *, ino_t);
+extern 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 *);
 
 /* vxfs_lookup.c */
index c9a6a94..a4610a7 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -108,31 +109,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 vxfs_inode_info          *vip;
 
-       vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
-       if (!vip) {
+       infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
+       if (!infp->vsi_fship) {
                printk(KERN_ERR "vxfs: unable to read fsh inode\n");
                return -EINVAL;
        }
+
+       vip = VXFS_INO(infp->vsi_fship);
        if (!VXFS_ISFSH(vip)) {
                printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
                                vip->vii_mode & VXFS_TYPE_MASK); 
-               goto out_free_fship;
+               goto out_iput_fship;
        }
 
-
 #ifdef DIAGNOSTIC
        printk("vxfs: fsh inode dump:\n");
        vxfs_dumpi(vip, 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");
@@ -153,14 +149,10 @@ 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 = vxfs_get_fake_inode(sbp, tip);
+       infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext,
+                       fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
        if (!infp->vsi_stilist) {
                printk(KERN_ERR "vxfs: unable to get structural list inode\n");
-               kfree(tip);
                goto out_free_pfp;
        }
        if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
@@ -169,13 +161,9 @@ vxfs_read_fshead(struct super_block *sbp)
                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);
+       infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
        if (!infp->vsi_ilist) {
                printk(KERN_ERR "vxfs: unable to get inode list inode\n");
-               kfree(tip);
                goto out_iput_stilist;
        }
        if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
@@ -184,6 +172,8 @@ vxfs_read_fshead(struct super_block *sbp)
                goto out_iput_ilist;
        }
 
+       kfree(pfp);
+       kfree(sfp);
        return 0;
 
  out_iput_ilist:
@@ -197,7 +187,4 @@ vxfs_read_fshead(struct super_block *sbp)
  out_iput_fship:
        iput(infp->vsi_fship);
        return -EINVAL;
- out_free_fship:
-       kfree(vip);
-       return -EINVAL;
 }
index ead0d64..e026f0c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * Fileset header 
  */
 struct vxfs_fsh {
-       u_int32_t       fsh_version;            /* fileset header version */
-       u_int32_t       fsh_fsindex;            /* fileset index */
-       u_int32_t       fsh_time;               /* modification time - sec */
-       u_int32_t       fsh_utime;              /* modification time - usec */
-       u_int32_t       fsh_extop;              /* extop flags */
-       vx_ino_t        fsh_ninodes;            /* allocated inodes */
-       u_int32_t       fsh_nau;                /* number of IAUs */
-       u_int32_t       fsh_old_ilesize;        /* old size of ilist */
-       u_int32_t       fsh_dflags;             /* flags */
-       u_int32_t       fsh_quota;              /* quota limit */
-       vx_ino_t        fsh_maxinode;           /* maximum inode number */
-       vx_ino_t        fsh_iauino;             /* IAU inode */
-       vx_ino_t        fsh_ilistino[2];        /* ilist inodes */
-       vx_ino_t        fsh_lctino;             /* link count table inode */
+       __fs32          fsh_version;            /* fileset header version */
+       __fs32          fsh_fsindex;            /* fileset index */
+       __fs32          fsh_time;               /* modification time - sec */
+       __fs32          fsh_utime;              /* modification time - usec */
+       __fs32          fsh_extop;              /* extop flags */
+       __fs32          fsh_ninodes;            /* allocated inodes */
+       __fs32          fsh_nau;                /* number of IAUs */
+       __fs32          fsh_old_ilesize;        /* old size of ilist */
+       __fs32          fsh_dflags;             /* flags */
+       __fs32          fsh_quota;              /* quota limit */
+       __fs32          fsh_maxinode;           /* maximum inode number */
+       __fs32          fsh_iauino;             /* IAU inode */
+       __fs32          fsh_ilistino[2];        /* ilist inodes */
+       __fs32          fsh_lctino;             /* link count table inode */
 
        /*
         * Slightly more fields follow, but they
index 3e2ccad..1f41b25 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,9 +43,6 @@
 #include "vxfs_extern.h"
 
 
-struct kmem_cache              *vxfs_inode_cachep;
-
-
 #ifdef DIAGNOSTIC
 /*
  * Dump inode contents (partially).
@@ -68,6 +66,83 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
 }
 #endif
 
+/**
+ * vxfs_transmod - mode for a VxFS inode
+ * @vip:       VxFS inode
+ *
+ * Description:
+ *  vxfs_transmod returns a Linux mode_t for a given
+ *  VxFS inode structure.
+ */
+static __inline__ umode_t
+vxfs_transmod(struct vxfs_inode_info *vip)
+{
+       umode_t                 ret = vip->vii_mode & ~VXFS_TYPE_MASK;
+
+       if (VXFS_ISFIFO(vip))
+               ret |= S_IFIFO;
+       if (VXFS_ISCHR(vip))
+               ret |= S_IFCHR;
+       if (VXFS_ISDIR(vip))
+               ret |= S_IFDIR;
+       if (VXFS_ISBLK(vip))
+               ret |= S_IFBLK;
+       if (VXFS_ISLNK(vip))
+               ret |= S_IFLNK;
+       if (VXFS_ISREG(vip))
+               ret |= S_IFREG;
+       if (VXFS_ISSOC(vip))
+               ret |= S_IFSOCK;
+
+       return (ret);
+}
+
+static inline void dip2vip_cpy(struct vxfs_sb_info *sbi,
+               struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
+{
+       struct inode *inode = &vip->vfs_inode;
+
+       vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode);
+       vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink);
+       vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid);
+       vip->vii_gid = fs32_to_cpu(sbi, dip->vdi_gid);
+       vip->vii_size = fs64_to_cpu(sbi, dip->vdi_size);
+       vip->vii_atime = fs32_to_cpu(sbi, dip->vdi_atime);
+       vip->vii_autime = fs32_to_cpu(sbi, dip->vdi_autime);
+       vip->vii_mtime = fs32_to_cpu(sbi, dip->vdi_mtime);
+       vip->vii_mutime = fs32_to_cpu(sbi, dip->vdi_mutime);
+       vip->vii_ctime = fs32_to_cpu(sbi, dip->vdi_ctime);
+       vip->vii_cutime = fs32_to_cpu(sbi, dip->vdi_cutime);
+       vip->vii_orgtype = dip->vdi_orgtype;
+
+       vip->vii_blocks = fs32_to_cpu(sbi, dip->vdi_blocks);
+       vip->vii_gen = fs32_to_cpu(sbi, dip->vdi_gen);
+
+       if (VXFS_ISDIR(vip))
+               vip->vii_dotdot = fs32_to_cpu(sbi, dip->vdi_dotdot);
+       else if (!VXFS_ISREG(vip) && !VXFS_ISLNK(vip))
+               vip->vii_rdev = fs32_to_cpu(sbi, dip->vdi_rdev);
+
+       /* don't endian swap the fields that differ by orgtype */
+       memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org));
+
+       inode->i_mode = vxfs_transmod(vip);
+       i_uid_write(inode, (uid_t)vip->vii_uid);
+       i_gid_write(inode, (gid_t)vip->vii_gid);
+
+       set_nlink(inode, vip->vii_nlink);
+       inode->i_size = vip->vii_size;
+
+       inode->i_atime.tv_sec = vip->vii_atime;
+       inode->i_ctime.tv_sec = vip->vii_ctime;
+       inode->i_mtime.tv_sec = vip->vii_mtime;
+       inode->i_atime.tv_nsec = 0;
+       inode->i_ctime.tv_nsec = 0;
+       inode->i_mtime.tv_nsec = 0;
+
+       inode->i_blocks = vip->vii_blocks;
+       inode->i_generation = vip->vii_gen;
+}
 
 /**
  * vxfs_blkiget - find inode based on extent #
@@ -85,50 +160,55 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
  *  buffercache.  This function should not be used outside the
  *  read_super() method, otherwise the data may be incoherent.
  */
-struct vxfs_inode_info *
+struct inode *
 vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
 {
        struct buffer_head              *bp;
+       struct inode                    *inode;
        u_long                          block, offset;
 
+       inode = new_inode(sbp);
+       if (!inode)
+               return NULL;
+       inode->i_ino = get_next_ino();
+
        block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
        offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
        bp = sb_bread(sbp, block);
 
        if (bp && buffer_mapped(bp)) {
-               struct vxfs_inode_info  *vip;
+               struct vxfs_inode_info  *vip = VXFS_INO(inode);
                struct vxfs_dinode      *dip;
 
-               if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
-                       goto fail;
                dip = (struct vxfs_dinode *)(bp->b_data + offset);
-               memcpy(vip, dip, sizeof(*vip));
+               dip2vip_cpy(VXFS_SBI(sbp), vip, dip);
+               vip->vfs_inode.i_mapping->a_ops = &vxfs_aops;
 #ifdef DIAGNOSTIC
                vxfs_dumpi(vip, ino);
 #endif
                brelse(bp);
-               return (vip);
+               return inode;
        }
 
-fail:
        printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
        brelse(bp);
+       iput(inode);
        return NULL;
 }
 
 /**
  * __vxfs_iget - generic find inode facility
- * @sbp:               VFS superblock
- * @ino:               inode number
  * @ilistp:            inode list
+ * @vip:               VxFS inode to fill in
+ * @ino:               inode number
  *
  * Description:
  *  Search the for inode number @ino in the filesystem
  *  described by @sbp.  Use the specified inode table (@ilistp).
- *  Returns the matching VxFS inode on success, else an error code.
+ *  Returns the matching inode on success, else an error code.
  */
-static struct vxfs_inode_info *
-__vxfs_iget(ino_t ino, struct inode *ilistp)
+static int
+__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino)
 {
        struct page                     *pp;
        u_long                          offset;
@@ -137,28 +217,22 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
        pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
 
        if (!IS_ERR(pp)) {
-               struct vxfs_inode_info  *vip;
                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);
-               memcpy(vip, dip, sizeof(*vip));
+               dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip);
+               vip->vfs_inode.i_mapping->a_ops = &vxfs_aops;
 #ifdef DIAGNOSTIC
                vxfs_dumpi(vip, ino);
 #endif
                vxfs_put_page(pp);
-               return (vip);
+               return 0;
        }
 
-       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);
+       printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n",
+               pp, (unsigned long)ino);
+       return PTR_ERR(pp);
 }
 
 /**
@@ -169,116 +243,26 @@ fail:
  * Description:
  *  Find inode @ino in the filesystem described by @sbp using
  *  the structural inode list.
- *  Returns the matching VxFS inode on success, else a NULL pointer.
- */
-struct vxfs_inode_info *
-vxfs_stiget(struct super_block *sbp, ino_t ino)
-{
-       struct vxfs_inode_info *vip;
-
-       vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
-       return IS_ERR(vip) ? NULL : vip;
-}
-
-/**
- * vxfs_transmod - mode for a VxFS inode
- * @vip:       VxFS inode
- *
- * Description:
- *  vxfs_transmod returns a Linux mode_t for a given
- *  VxFS inode structure.
- */
-static __inline__ umode_t
-vxfs_transmod(struct vxfs_inode_info *vip)
-{
-       umode_t                 ret = vip->vii_mode & ~VXFS_TYPE_MASK;
-
-       if (VXFS_ISFIFO(vip))
-               ret |= S_IFIFO;
-       if (VXFS_ISCHR(vip))
-               ret |= S_IFCHR;
-       if (VXFS_ISDIR(vip))
-               ret |= S_IFDIR;
-       if (VXFS_ISBLK(vip))
-               ret |= S_IFBLK;
-       if (VXFS_ISLNK(vip))
-               ret |= S_IFLNK;
-       if (VXFS_ISREG(vip))
-               ret |= S_IFREG;
-       if (VXFS_ISSOC(vip))
-               ret |= S_IFSOCK;
-
-       return (ret);
-}
-
-/**
- * vxfs_iinit- helper to fill inode fields
- * @ip:                VFS inode
- * @vip:       VxFS inode
- *
- * Description:
- *  vxfs_instino is a helper function to fill in all relevant
- *  fields in @ip from @vip.
- */
-static void
-vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
-{
-
-       ip->i_mode = vxfs_transmod(vip);
-       i_uid_write(ip, (uid_t)vip->vii_uid);
-       i_gid_write(ip, (gid_t)vip->vii_gid);
-
-       set_nlink(ip, vip->vii_nlink);
-       ip->i_size = vip->vii_size;
-
-       ip->i_atime.tv_sec = vip->vii_atime;
-       ip->i_ctime.tv_sec = vip->vii_ctime;
-       ip->i_mtime.tv_sec = vip->vii_mtime;
-       ip->i_atime.tv_nsec = 0;
-       ip->i_ctime.tv_nsec = 0;
-       ip->i_mtime.tv_nsec = 0;
-
-       ip->i_blocks = vip->vii_blocks;
-       ip->i_generation = vip->vii_gen;
-
-       ip->i_private = 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.
+ *  Returns the matching inode on success, else a NULL pointer.
  */
 struct inode *
-vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
+vxfs_stiget(struct super_block *sbp, ino_t ino)
 {
-       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;
+       struct inode *inode;
+       int error;
+
+       inode = new_inode(sbp);
+       if (!inode)
+               return NULL;
+       inode->i_ino = get_next_ino();
+
+       error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino);
+       if (error) {
+               iput(inode);
+               return NULL;
        }
-       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);
+       return inode;
 }
 
 /**
@@ -296,6 +280,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
        struct vxfs_inode_info          *vip;
        const struct address_space_operations   *aops;
        struct inode *ip;
+       int error;
 
        ip = iget_locked(sbp, ino);
        if (!ip)
@@ -303,14 +288,13 @@ 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);
-       if (IS_ERR(vip)) {
+       vip = VXFS_INO(ip);
+       error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino);
+       if (error) {
                iget_failed(ip);
-               return ERR_CAST(vip);
+               return ERR_PTR(error);
        }
 
-       vxfs_iinit(ip, vip);
-
        if (VXFS_ISIMMED(vip))
                aops = &vxfs_immed_aops;
        else
@@ -341,12 +325,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
        return ip;
 }
 
-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);
-}
-
 /**
  * vxfs_evict_inode - remove inode from main memory
  * @ip:                inode to discard.
@@ -360,5 +338,4 @@ vxfs_evict_inode(struct inode *ip)
 {
        truncate_inode_pages_final(&ip->i_data);
        clear_inode(ip);
-       call_rcu(&ip->i_rcu, vxfs_i_callback);
 }
index 240aeb1..f012abe 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -66,74 +67,74 @@ enum {
  * Data stored immediately in the inode.
  */
 struct vxfs_immed {
-       u_int8_t        vi_immed[VXFS_NIMMED];
+       __u8                    vi_immed[VXFS_NIMMED];
 };
 
 struct vxfs_ext4 {
-       u_int32_t               ve4_spare;              /* ?? */
-       u_int32_t               ve4_indsize;            /* Indirect extent size */
-       vx_daddr_t              ve4_indir[VXFS_NIADDR]; /* Indirect extents */
+       __fs32                  ve4_spare;              /* ?? */
+       __fs32                  ve4_indsize;            /* Indirect extent size */
+       __fs32                  ve4_indir[VXFS_NIADDR]; /* Indirect extents */
        struct direct {                                 /* Direct extents */
-               vx_daddr_t      extent;                 /* Extent number */
-               int32_t         size;                   /* Size of extent */
+               __fs32          extent;                 /* Extent number */
+               __fs32          size;                   /* Size of extent */
        } ve4_direct[VXFS_NDADDR];
 };
 
 struct vxfs_typed {
-       u_int64_t       vt_hdr;         /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
-       vx_daddr_t      vt_block;       /* Extent block */
-       int32_t         vt_size;        /* Size in blocks */
+       __fs64          vt_hdr;         /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
+       __fs32          vt_block;       /* Extent block */
+       __fs32          vt_size;        /* Size in blocks */
 };
 
 struct vxfs_typed_dev4 {
-       u_int64_t       vd4_hdr;        /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
-       u_int64_t       vd4_block;      /* Extent block */
-       u_int64_t       vd4_size;       /* Size in blocks */
-       int32_t         vd4_dev;        /* Device ID */
-       u_int32_t       __pad1;
+       __fs64          vd4_hdr;        /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
+       __fs64          vd4_block;      /* Extent block */
+       __fs64          vd4_size;       /* Size in blocks */
+       __fs32          vd4_dev;        /* Device ID */
+       __u8            __pad1;
 };
 
 /*
  * The inode as contained on the physical device.
  */
 struct vxfs_dinode {
-       int32_t         vdi_mode;
-       u_int32_t       vdi_nlink;      /* Link count */
-       u_int32_t       vdi_uid;        /* UID */
-       u_int32_t       vdi_gid;        /* GID */
-       u_int64_t       vdi_size;       /* Inode size in bytes */
-       u_int32_t       vdi_atime;      /* Last time accessed - sec */
-       u_int32_t       vdi_autime;     /* Last time accessed - usec */
-       u_int32_t       vdi_mtime;      /* Last modify time - sec */
-       u_int32_t       vdi_mutime;     /* Last modify time - usec */
-       u_int32_t       vdi_ctime;      /* Create time - sec */
-       u_int32_t       vdi_cutime;     /* Create time - usec */
-       u_int8_t        vdi_aflags;     /* Allocation flags */
-       u_int8_t        vdi_orgtype;    /* Organisation type */
-       u_int16_t       vdi_eopflags;
-       u_int32_t       vdi_eopdata;
+       __fs32          vdi_mode;
+       __fs32          vdi_nlink;      /* Link count */
+       __fs32          vdi_uid;        /* UID */
+       __fs32          vdi_gid;        /* GID */
+       __fs64          vdi_size;       /* Inode size in bytes */
+       __fs32          vdi_atime;      /* Last time accessed - sec */
+       __fs32          vdi_autime;     /* Last time accessed - usec */
+       __fs32          vdi_mtime;      /* Last modify time - sec */
+       __fs32          vdi_mutime;     /* Last modify time - usec */
+       __fs32          vdi_ctime;      /* Create time - sec */
+       __fs32          vdi_cutime;     /* Create time - usec */
+       __u8            vdi_aflags;     /* Allocation flags */
+       __u8            vdi_orgtype;    /* Organisation type */
+       __fs16          vdi_eopflags;
+       __fs32          vdi_eopdata;
        union {
-               u_int32_t               rdev;
-               u_int32_t               dotdot;
+               __fs32                  rdev;
+               __fs32                  dotdot;
                struct {
-                       u_int32_t       reserved;
-                       u_int32_t       fixextsize;
+                       __u32           reserved;
+                       __fs32          fixextsize;
                } i_regular;
                struct {
-                       u_int32_t       matchino;
-                       u_int32_t       fsetindex;
+                       __fs32          matchino;
+                       __fs32          fsetindex;
                } i_vxspec;
-               u_int64_t               align;
+               __u64                   align;
        } vdi_ftarea;
-       u_int32_t       vdi_blocks;     /* How much blocks does inode occupy */
-       u_int32_t       vdi_gen;        /* Inode generation */
-       u_int64_t       vdi_version;    /* Version */
+       __fs32          vdi_blocks;     /* How much blocks does inode occupy */
+       __fs32          vdi_gen;        /* Inode generation */
+       __fs64          vdi_version;    /* Version */
        union {
                struct vxfs_immed       immed;
                struct vxfs_ext4        ext4;
                struct vxfs_typed       typed[VXFS_NTYPED];
        } vdi_org;
-       u_int32_t       vdi_iattrino;
+       __fs32          vdi_iattrino;
 };
 
 #define vdi_rdev       vdi_ftarea.rdev
@@ -149,32 +150,45 @@ struct vxfs_dinode {
 
 /*
  * The inode as represented in the main memory.
- *
- * TBD: This should become a separate structure...
  */
-#define vxfs_inode_info        vxfs_dinode
-
-#define vii_mode       vdi_mode
-#define vii_uid                vdi_uid
-#define vii_gid                vdi_gid
-#define vii_nlink      vdi_nlink
-#define vii_size       vdi_size
-#define vii_atime      vdi_atime
-#define vii_ctime      vdi_ctime
-#define vii_mtime      vdi_mtime
-#define vii_blocks     vdi_blocks
-#define vii_org                vdi_org
-#define vii_orgtype    vdi_orgtype
-#define vii_gen                vdi_gen
-
-#define vii_rdev       vdi_ftarea.rdev
-#define vii_dotdot     vdi_ftarea.dotdot
-#define vii_fixextsize vdi_ftarea.regular.fixextsize
-#define vii_matchino   vdi_ftarea.vxspec.matchino
-#define vii_fsetindex  vdi_ftarea.vxspec.fsetindex
-
-#define vii_immed      vdi_org.immed
-#define vii_ext4       vdi_org.ext4
-#define vii_typed      vdi_org.typed
+struct vxfs_inode_info {
+       struct inode    vfs_inode;
+
+       __u32           vii_mode;
+       __u32           vii_nlink;      /* Link count */
+       __u32           vii_uid;        /* UID */
+       __u32           vii_gid;        /* GID */
+       __u64           vii_size;       /* Inode size in bytes */
+       __u32           vii_atime;      /* Last time accessed - sec */
+       __u32           vii_autime;     /* Last time accessed - usec */
+       __u32           vii_mtime;      /* Last modify time - sec */
+       __u32           vii_mutime;     /* Last modify time - usec */
+       __u32           vii_ctime;      /* Create time - sec */
+       __u32           vii_cutime;     /* Create time - usec */
+       __u8            vii_orgtype;    /* Organisation type */
+       union {
+               __u32                   rdev;
+               __u32                   dotdot;
+       } vii_ftarea;
+       __u32           vii_blocks;     /* How much blocks does inode occupy */
+       __u32           vii_gen;        /* Inode generation */
+       union {
+               struct vxfs_immed       immed;
+               struct vxfs_ext4        ext4;
+               struct vxfs_typed       typed[VXFS_NTYPED];
+       } vii_org;
+};
+
+#define vii_rdev       vii_ftarea.rdev
+#define vii_dotdot     vii_ftarea.dotdot
+
+#define vii_immed      vii_org.immed
+#define vii_ext4       vii_org.ext4
+#define vii_typed      vii_org.typed
+
+static inline struct vxfs_inode_info *VXFS_INO(struct inode *inode)
+{
+       return container_of(inode, struct vxfs_inode_info, vfs_inode);
+}
 
 #endif /* _VXFS_INODE_H_ */
index 6d576b9..ce4785f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,33 +62,6 @@ const struct file_operations vxfs_dir_operations = {
        .iterate_shared =       vxfs_readdir,
 };
 
-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_find_entry - find a mathing directory entry for a dentry
@@ -106,50 +80,64 @@ vxfs_next_entry(struct vxfs_direct *de)
 static struct vxfs_direct *
 vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
 {
-       u_long                          npages, page, nblocks, pblocks, block;
-       u_long                          bsize = ip->i_sb->s_blocksize;
-       const char                      *name = dp->d_name.name;
-       int                             namelen = dp->d_name.len;
-
-       npages = dir_pages(ip);
-       nblocks = dir_blocks(ip);
-       pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
-       
-       for (page = 0; page < npages; page++) {
-               caddr_t                 kaddr;
-               struct page             *pp;
+       u_long bsize = ip->i_sb->s_blocksize;
+       const char *name = dp->d_name.name;
+       int namelen = dp->d_name.len;
+       loff_t limit = VXFS_DIRROUND(ip->i_size);
+       struct vxfs_direct *de_exit = NULL;
+       loff_t pos = 0;
+       struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
 
-               pp = vxfs_get_page(ip->i_mapping, page);
+       while (pos < limit) {
+               struct page *pp;
+               char *kaddr;
+               int pg_ofs = pos & ~PAGE_MASK;
+
+               pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
                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);
-                               }
+                       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_MASK));
+                               int overhead = VXFS_DIRBLKOV(sbi, dbp);
+
+                               pos += overhead;
+                               pg_ofs += overhead;
+                       }
+                       de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+                       if (!de->d_reclen) {
+                               pos += bsize - 1;
+                               pos &= ~(bsize - 1);
+                               break;
+                       }
+
+                       pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
+                       pos += fs16_to_cpu(sbi, de->d_reclen);
+                       if (!de->d_ino)
+                               continue;
+
+                       if (namelen != fs16_to_cpu(sbi, de->d_namelen))
+                               continue;
+                       if (!memcmp(name, de->d_name, namelen)) {
+                               *ppp = pp;
+                               de_exit = de;
+                               break;
                        }
                }
-               vxfs_put_page(pp);
+               if (!de_exit)
+                       vxfs_put_page(pp);
+               else
+                       break;
        }
 
-       return NULL;
+       return de_exit;
 }
 
 /**
@@ -173,7 +161,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
 
        de = vxfs_find_entry(dip, dp, &pp);
        if (de) {
-               ino = de->d_ino;
+               ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
                kunmap(pp);
                put_page(pp);
        }
@@ -233,74 +221,80 @@ 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;
+       struct vxfs_sb_info     *sbi = VXFS_SBI(sbp);
 
        if (ctx->pos == 0) {
                if (!dir_emit_dot(fp, ctx))
-                       return 0;
-               ctx->pos = 1;
+                       goto out;
+               ctx->pos++;
        }
        if (ctx->pos == 1) {
                if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
-                       return 0;
-               ctx->pos = 2;
+                       goto out;
+               ctx->pos++;
        }
-       pos = ctx->pos - 2;
-       
-       if (pos > VXFS_DIRROUND(ip->i_size))
-               return 0;
 
-       npages = dir_pages(ip);
-       nblocks = dir_blocks(ip);
-       pblocks = VXFS_BLOCK_PER_PAGE(sbp);
+       limit = VXFS_DIRROUND(ip->i_size);
+       if (ctx->pos > limit)
+               goto out;
 
-       page = pos >> PAGE_SHIFT;
-       offset = pos & ~PAGE_MASK;
-       block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
+       pos = ctx->pos & ~3L;
 
-       for (; page < npages; page++, block = 0) {
-               char                    *kaddr;
-               struct page             *pp;
+       while (pos < limit) {
+               struct page *pp;
+               char *kaddr;
+               int pg_ofs = pos & ~PAGE_MASK;
+               int rc = 0;
 
-               pp = vxfs_get_page(ip->i_mapping, page);
+               pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
                if (IS_ERR(pp))
-                       continue;
+                       return -ENOMEM;
+
                kaddr = (char *)page_address(pp);
 
-               for (; block <= nblocks && block <= pblocks; block++) {
-                       char                    *baddr, *limit;
-                       struct vxfs_dirblk      *dbp;
-                       struct vxfs_direct      *de;
+               while (pg_ofs < PAGE_SIZE && pos < limit) {
+                       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_SHIFT) | offset) + 2;
-                               if (!dir_emit(ctx, de->d_name, de->d_namelen,
-                                       de->d_ino, DT_UNKNOWN)) {
-                                       vxfs_put_page(pp);
-                                       return 0;
-                               }
+                       if ((pos & (bsize - 1)) < 4) {
+                               struct vxfs_dirblk *dbp =
+                                       (struct vxfs_dirblk *)
+                                        (kaddr + (pos & ~PAGE_MASK));
+                               int overhead = VXFS_DIRBLKOV(sbi, dbp);
+
+                               pos += overhead;
+                               pg_ofs += overhead;
+                       }
+                       de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+                       if (!de->d_reclen) {
+                               pos += bsize - 1;
+                               pos &= ~(bsize - 1);
+                               break;
+                       }
+
+                       pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
+                       pos += fs16_to_cpu(sbi, de->d_reclen);
+                       if (!de->d_ino)
+                               continue;
+
+                       rc = dir_emit(ctx, de->d_name,
+                                       fs16_to_cpu(sbi, de->d_namelen),
+                                       fs32_to_cpu(sbi, de->d_ino),
+                                       DT_UNKNOWN);
+                       if (!rc) {
+                               /* the dir entry was not read, fix pos. */
+                               pos -= fs16_to_cpu(sbi, de->d_reclen);
+                               break;
                        }
-                       offset = 0;
                }
                vxfs_put_page(pp);
-               offset = 0;
+               if (!rc)
+                       break;
        }
-       ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
+
+       ctx->pos = pos | 2;
+
+out:
        return 0;
 }
index 0495008..813da66 100644 (file)
@@ -43,14 +43,14 @@ static inline void
 vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
 {
        BUG_ON(infp->vsi_fshino);
-       infp->vsi_fshino = fshp->olt_fsino[0];
+       infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]);
 }
 
 static inline void
 vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
 {
        BUG_ON(infp->vsi_iext);
-       infp->vsi_iext = ilistp->olt_iext[0]; 
+       infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]);
 }
 
 static inline u_long
@@ -81,13 +81,12 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
        struct vxfs_olt         *op;
        char                    *oaddr, *eaddr;
 
-
        bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
        if (!bp || !bp->b_data)
                goto fail;
 
        op = (struct vxfs_olt *)bp->b_data;
-       if (op->olt_magic != VXFS_OLT_MAGIC) {
+       if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) {
                printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
                goto fail;
        }
@@ -102,14 +101,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
                goto fail;
        }
 
-       oaddr = bp->b_data + op->olt_size;
+       oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
        eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
 
        while (oaddr < eaddr) {
                struct vxfs_oltcommon   *ocp =
                        (struct vxfs_oltcommon *)oaddr;
                
-               switch (ocp->olt_type) {
+               switch (fs32_to_cpu(infp, ocp->olt_type)) {
                case VXFS_OLT_FSHEAD:
                        vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
                        break;
@@ -118,11 +117,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
                        break;
                }
 
-               oaddr += ocp->olt_size;
+               oaddr += fs32_to_cpu(infp, ocp->olt_size);
        }
 
        brelse(bp);
-       return 0;
+       return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
 
 fail:
        brelse(bp);
index b7b3af5..0c0b0c9 100644 (file)
@@ -63,83 +63,83 @@ enum {
  * the initial inode list, the fileset header or the device configuration.
  */
 struct vxfs_olt {
-       u_int32_t       olt_magic;      /* magic number                 */
-       u_int32_t       olt_size;       /* size of this entry           */
-       u_int32_t       olt_checksum;   /* checksum of extent           */
-       u_int32_t       __unused1;      /* ???                          */
-       u_int32_t       olt_mtime;      /* time of last mod. (sec)      */
-       u_int32_t       olt_mutime;     /* time of last mod. (usec)     */
-       u_int32_t       olt_totfree;    /* free space in OLT extent     */
-       vx_daddr_t      olt_extents[2]; /* addr of this extent, replica */
-       u_int32_t       olt_esize;      /* size of this extent          */
-       vx_daddr_t      olt_next[2];    /* addr of next extent, replica */
-       u_int32_t       olt_nsize;      /* size of next extent          */
-       u_int32_t       __unused2;      /* align to 8 byte boundary     */
+       __fs32          olt_magic;      /* magic number                 */
+       __fs32          olt_size;       /* size of this entry           */
+       __fs32          olt_checksum;   /* checksum of extent           */
+       __u32           __unused1;      /* ???                          */
+       __fs32          olt_mtime;      /* time of last mod. (sec)      */
+       __fs32          olt_mutime;     /* time of last mod. (usec)     */
+       __fs32          olt_totfree;    /* free space in OLT extent     */
+       __fs32          olt_extents[2]; /* addr of this extent, replica */
+       __fs32          olt_esize;      /* size of this extent          */
+       __fs32          olt_next[2];    /* addr of next extent, replica */
+       __fs32          olt_nsize;      /* size of next extent          */
+       __u32           __unused2;      /* align to 8 byte boundary     */
 };
 
 /*
  * VxFS common OLT entry (on disk).
  */
 struct vxfs_oltcommon {
-       u_int32_t       olt_type;       /* type of this record          */
-       u_int32_t       olt_size;       /* size of this record          */
+       __fs32          olt_type;       /* type of this record          */
+       __fs32          olt_size;       /* size of this record          */
 };
 
 /*
  * VxFS free OLT entry (on disk).
  */
 struct vxfs_oltfree {
-       u_int32_t       olt_type;       /* type of this record          */
-       u_int32_t       olt_fsize;      /* size of this free record     */
+       __fs32          olt_type;       /* type of this record          */
+       __fs32          olt_fsize;      /* size of this free record     */
 };
 
 /*
  * VxFS initial-inode list (on disk).
  */
 struct vxfs_oltilist {
-       u_int32_t       olt_type;       /* type of this record          */
-       u_int32_t       olt_size;       /* size of this record          */
-       vx_ino_t        olt_iext[2];    /* initial inode list, replica  */
+       __fs32  olt_type;       /* type of this record          */
+       __fs32  olt_size;       /* size of this record          */
+       __fs32          olt_iext[2];    /* initial inode list, replica  */
 };
 
 /*
  * Current Usage Table 
  */
 struct vxfs_oltcut {
-       u_int32_t       olt_type;       /* type of this record          */
-       u_int32_t       olt_size;       /* size of this record          */
-       vx_ino_t        olt_cutino;     /* inode of current usage table */
-       u_int32_t       __pad;          /* unused, 8 byte align         */
+       __fs32          olt_type;       /* type of this record          */
+       __fs32          olt_size;       /* size of this record          */
+       __fs32          olt_cutino;     /* inode of current usage table */
+       __u8            __pad;          /* unused, 8 byte align         */
 };
 
 /*
  * Inodes containing Superblock, Intent log and OLTs 
  */
 struct vxfs_oltsb {
-       u_int32_t       olt_type;       /* type of this record          */
-       u_int32_t       olt_size;       /* size of this record          */
-       vx_ino_t        olt_sbino;      /* inode of superblock file     */
-       u_int32_t       __unused1;      /* ???                          */
-       vx_ino_t        olt_logino[2];  /* inode of log file,replica    */
-       vx_ino_t        olt_oltino[2];  /* inode of OLT, replica        */
+       __fs32          olt_type;       /* type of this record          */
+       __fs32          olt_size;       /* size of this record          */
+       __fs32          olt_sbino;      /* inode of superblock file     */
+       __u32           __unused1;      /* ???                          */
+       __fs32          olt_logino[2];  /* inode of log file,replica    */
+       __fs32          olt_oltino[2];  /* inode of OLT, replica        */
 };
 
 /*
  * Inode containing device configuration + it's replica 
  */
 struct vxfs_oltdev {
-       u_int32_t       olt_type;       /* type of this record          */
-       u_int32_t       olt_size;       /* size of this record          */
-       vx_ino_t        olt_devino[2];  /* inode of device config files */
+       __fs32          olt_type;       /* type of this record          */
+       __fs32          olt_size;       /* size of this record          */
+       __fs32          olt_devino[2];  /* inode of device config files */
 };
 
 /*
  * Fileset header 
  */
 struct vxfs_oltfshead {
-       u_int32_t       olt_type;       /* type number                  */
-       u_int32_t       olt_size;       /* size of this record          */
-       vx_ino_t        olt_fsino[2];   /* inodes of fileset header     */
+       __fs32          olt_type;       /* type number                  */
+       __fs32          olt_size;       /* size of this record          */
+       __fs32          olt_fsino[2];   /* inodes of fileset header     */
 };
 
 #endif /* _VXFS_OLT_H_ */
index 7ca8c75..455ce5b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #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");
 
-
-
-static void            vxfs_put_super(struct super_block *);
-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 = {
-       .evict_inode =          vxfs_evict_inode,
-       .put_super =            vxfs_put_super,
-       .statfs =               vxfs_statfs,
-       .remount_fs =           vxfs_remount,
-};
+static struct kmem_cache *vxfs_inode_cachep;
 
 /**
  * vxfs_put_super - free superblock resources
@@ -79,9 +69,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);
@@ -109,14 +99,15 @@ static int
 vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
 {
        struct vxfs_sb_info             *infp = VXFS_SBI(dentry->d_sb);
+       struct vxfs_sb *raw_sb = infp->vsi_raw;
 
        bufp->f_type = VXFS_SUPER_MAGIC;
        bufp->f_bsize = dentry->d_sb->s_blocksize;
-       bufp->f_blocks = infp->vsi_raw->vs_dsize;
-       bufp->f_bfree = infp->vsi_raw->vs_free;
+       bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize);
+       bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free);
        bufp->f_bavail = 0;
        bufp->f_files = 0;
-       bufp->f_ffree = infp->vsi_raw->vs_ifree;
+       bufp->f_ffree = fs32_to_cpu(infp, raw_sb->vs_ifree);
        bufp->f_namelen = VXFS_NAMELEN;
 
        return 0;
@@ -129,6 +120,81 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
        return 0;
 }
 
+static struct inode *vxfs_alloc_inode(struct super_block *sb)
+{
+       struct vxfs_inode_info *vi;
+
+       vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
+       if (!vi)
+               return NULL;
+       inode_init_once(&vi->vfs_inode);
+       return &vi->vfs_inode;
+}
+
+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, VXFS_INO(inode));
+}
+
+static void vxfs_destroy_inode(struct inode *inode)
+{
+       call_rcu(&inode->i_rcu, vxfs_i_callback);
+}
+
+static const struct super_operations vxfs_super_ops = {
+       .alloc_inode            = vxfs_alloc_inode,
+       .destroy_inode          = vxfs_destroy_inode,
+       .evict_inode            = vxfs_evict_inode,
+       .put_super              = vxfs_put_super,
+       .statfs                 = vxfs_statfs,
+       .remount_fs             = vxfs_remount,
+};
+
+static int vxfs_try_sb_magic(struct super_block *sbp, int silent,
+               unsigned blk, __fs32 magic)
+{
+       struct buffer_head *bp;
+       struct vxfs_sb *rsbp;
+       struct vxfs_sb_info *infp = VXFS_SBI(sbp);
+       int rc = -ENOMEM;
+
+       bp = sb_bread(sbp, blk);
+       do {
+               if (!bp || !buffer_mapped(bp)) {
+                       if (!silent) {
+                               printk(KERN_WARNING
+                                       "vxfs: unable to read disk superblock at %u\n",
+                                       blk);
+                       }
+                       break;
+               }
+
+               rc = -EINVAL;
+               rsbp = (struct vxfs_sb *)bp->b_data;
+               if (rsbp->vs_magic != magic) {
+                       if (!silent)
+                               printk(KERN_NOTICE
+                                       "vxfs: WRONG superblock magic %08x at %u\n",
+                                       rsbp->vs_magic, blk);
+                       break;
+               }
+
+               rc = 0;
+               infp->vsi_raw = rsbp;
+               infp->vsi_bp = bp;
+       } while (0);
+
+       if (rc) {
+               infp->vsi_raw = NULL;
+               infp->vsi_bp = NULL;
+               brelse(bp);
+       }
+
+       return rc;
+}
+
 /**
  * vxfs_read_super - read superblock into memory and initialize filesystem
  * @sbp:               VFS superblock (to fill)
@@ -149,10 +215,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
 {
        struct vxfs_sb_info     *infp;
        struct vxfs_sb          *rsbp;
-       struct buffer_head      *bp = NULL;
        u_long                  bsize;
        struct inode *root;
        int ret = -EINVAL;
+       u32 j;
 
        sbp->s_flags |= MS_RDONLY;
 
@@ -168,42 +234,43 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
                goto out;
        }
 
-       bp = sb_bread(sbp, 1);
-       if (!bp || !buffer_mapped(bp)) {
-               if (!silent) {
-                       printk(KERN_WARNING
-                               "vxfs: unable to read disk superblock\n");
-               }
-               goto out;
-       }
+       sbp->s_op = &vxfs_super_ops;
+       sbp->s_fs_info = infp;
 
-       rsbp = (struct vxfs_sb *)bp->b_data;
-       if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
+       if (!vxfs_try_sb_magic(sbp, silent, 1,
+                       (__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) {
+               /* Unixware, x86 */
+               infp->byte_order = VXFS_BO_LE;
+       } else if (!vxfs_try_sb_magic(sbp, silent, 8,
+                       (__force __fs32)cpu_to_be32(VXFS_SUPER_MAGIC))) {
+               /* HP-UX, parisc */
+               infp->byte_order = VXFS_BO_BE;
+       } else {
                if (!silent)
-                       printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
+                       printk(KERN_NOTICE "vxfs: can't find superblock.\n");
                goto out;
        }
 
-       if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
-               printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
-                      rsbp->vs_version);
+       rsbp = infp->vsi_raw;
+       j = fs32_to_cpu(infp, rsbp->vs_version);
+       if ((j < 2 || j > 4) && !silent) {
+               printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
                goto out;
        }
 
 #ifdef DIAGNOSTIC
-       printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
-       printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
+       printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
+       printk(KERN_DEBUG "vxfs: blocksize: %d\n",
+               fs32_to_cpu(infp, rsbp->vs_bsize));
 #endif
 
-       sbp->s_magic = rsbp->vs_magic;
-       sbp->s_fs_info = infp;
+       sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic);
 
-       infp->vsi_raw = rsbp;
-       infp->vsi_bp = bp;
-       infp->vsi_oltext = rsbp->vs_oltext[0];
-       infp->vsi_oltsize = rsbp->vs_oltsize;
+       infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]);
+       infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize);
 
-       if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
+       j = fs32_to_cpu(infp, rsbp->vs_bsize);
+       if (!sb_set_blocksize(sbp, j)) {
                printk(KERN_WARNING "vxfs: unable to set final block size\n");
                goto out;
        }
@@ -218,7 +285,6 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
                goto out;
        }
 
-       sbp->s_op = &vxfs_super_ops;
        root = vxfs_iget(sbp, VXFS_ROOT_INO);
        if (IS_ERR(root)) {
                ret = PTR_ERR(root);
@@ -233,11 +299,11 @@ 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(bp);
+       brelse(infp->vsi_bp);
        kfree(infp);
        return ret;
 }