* freevxfs
@ 2016-05-22 15:13 Krzysztof Błaszkowski
2016-05-23 8:23 ` freevxfs Carlos Maiolino
2016-05-23 8:36 ` freevxfs Christoph Hellwig
0 siblings, 2 replies; 8+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-22 15:13 UTC (permalink / raw)
To: linux-fsdevel, hch
[-- Attachment #1: Type: text/plain, Size: 577 bytes --]
Hello All,
I recently gave a try to vxfs (veritas fs) which is common to HP-UX and
it turned out that the module has been broken for very long time.
I fixed several issues with current freevxfs and also designed a
userspace tool which helps creating dm block devices from e.g. regular
file with raw image of hp-ux disk.
https://sourceforge.net/projects/linux-vxfs/
I send the patch because I believe that some people would appreciate
support for this vintage file system (e.g. me) and also it will be nice
to see my name in the kernel.
Regards,
--
Krzysztof Blaszkowski
[-- Attachment #2: vxfs-fixes-and-improvements.diff --]
[-- Type: text/x-patch, Size: 43984 bytes --]
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index c8a9265..9890a84 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -2,6 +2,39 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * (c) 2016 Krzysztof Blaszkowski.
+ * Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ * - code not aware of cpu endianess and ondisk data is BE.
+ * - misaligned structures read from block device
+ * - wrong SB block number. default offset is 8kB
+ * - kmem_cache_alloc() objectes released with kfree()
+ * - inode.i_private released in evict_inode() callback.
+ * - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// * cksum mnt/usr/share/man/man3.Z/*
+// * cksum mnt/usr/share/doc/10.20RelNotes
+// * cksum mnt/usr/local/doom/*
+// * cksum mnt/usr/sprockets/tools/instrument/16700/*
+// * cksum mnt/usr/share/doc/*
+// * cksum mnt/usr/sprockets/lib/*
+// * cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ * 3457951056 4196020 /usr/local/doom/doom1.wad
+ * 2527157998 35344 /usr/local/doom/doomlaunch
+ * 2974998129 413696 /usr/local/doom/hpdoom
+ *
+ * The hpux_mdsetup tool project which is aimed at making possible
+ * accessing HP-UX logical volumes by device mapper is here:
+ * https://sourceforge.net/projects/linux-vxfs/
+ *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -38,6 +71,10 @@
*/
#include <linux/types.h>
+//#define DIAGNOSTIC
+#undef DIAGNOSTIC
+#undef DIAGNOSTIC_V2
+#undef DIAGNOSTIC_V3
/*
* Data types for use with the VxFS ondisk format.
@@ -152,7 +189,7 @@ struct vxfs_sb {
/*
* Actually much more...
*/
-};
+} __attribute__((packed));
/*
@@ -260,4 +297,35 @@ enum {
#define VXFS_SBI(sbp) \
((struct vxfs_sb_info *)(sbp)->s_fs_info)
+
+#ifdef DIAGNOSTIC
+#define F_ENTER(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#define F_EXIT(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+
+#ifdef DIAGNOSTIC_V2
+#define F_ENTER_V2(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#define F_EXIT_V2(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#else
+#define F_ENTER_V2(a, b...)
+#define F_EXIT_V2(a, b...)
+#endif
+
+#ifdef DIAGNOSTIC_V3
+#define F_ENTER_V3(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#define F_EXIT_V3(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
+#else
+#define F_ENTER_V3(a, b...)
+#define F_EXIT_V3(a, b...)
+#endif
+
+#else // DIAGNOSTIC
+#define F_ENTER(a, b...)
+#define F_EXIT(a, b...)
+#define F_ENTER_V2(a, b...)
+#define F_EXIT_V2(a, b...)
+#define F_ENTER_V3(a, b...)
+#define F_EXIT_V3(a, b...)
+#endif
+
+
#endif /* _VXFS_SUPER_H_ */
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index f86fd3c..58e6a17 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -2,6 +2,10 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * 2016 Krzysztof Blaszkowski.
+ * Many bug fixes, improvements & tests
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -39,17 +43,6 @@
#include "vxfs_extern.h"
-#ifdef DIAGNOSTIC
-static void
-vxfs_typdump(struct vxfs_typed *typ)
-{
- printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
- printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
- printk("block=%x ", typ->vt_block);
- printk("size=%x\n", typ->vt_size);
-}
-#endif
-
/**
* vxfs_bmap_ext4 - do bmap for ext4 extents
* @ip: pointer to the inode we do bmap for
@@ -71,18 +64,23 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
unsigned long bsize = sb->s_blocksize;
u32 indsize = vip->vii_ext4.ve4_indsize;
int i;
+ daddr_t rc = 0;
+
+ F_ENTER_V2();
if (indsize > sb->s_blocksize)
goto fail_size;
for (i = 0; i < VXFS_NDADDR; i++) {
- struct direct *d = vip->vii_ext4.ve4_direct + i;
- if (bn >= 0 && bn < d->size)
- return (bn + d->extent);
+ struct direct *d = vip->vii_ext4.ve4_direct + i; // cpu endian
+ if (bn >= 0 && bn < d->size) {
+ rc = bn + d->extent;
+ break;
+ }
bn -= d->size;
}
- if ((bn / (indsize * indsize * bsize / 4)) == 0) {
+ if (!rc && ((bn / (indsize * indsize * bsize / 4)) == 0)) {
struct buffer_head *buf;
daddr_t bno;
u32 *indir;
@@ -92,18 +90,21 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
goto fail_buf;
indir = (u32 *)buf->b_data;
- bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
+ bno = be32_to_cpu(indir[(bn/indsize) % (indsize*bn)]) + (bn%indsize);
brelse(buf);
- return bno;
- } else
- printk(KERN_WARNING "no matching indir?");
+ rc = bno;
+ }
+ if (!rc)
+ printk(KERN_WARNING "%s:%d no matching indir?\n", __FUNCTION__, __LINE__);
- return 0;
+ F_EXIT_V2("pblk %d", rc);
+ return rc;
fail_size:
printk("vxfs: indirect extent too big!\n");
fail_buf:
+ F_EXIT();
return 0;
}
@@ -129,51 +130,53 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
{
struct buffer_head *bp = NULL;
daddr_t pblock = 0;
- int i;
+ int i;
+ F_ENTER_V2();
for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
struct vxfs_typed *typ;
- int64_t off;
+ int64_t off;
bp = sb_bread(ip->i_sb,
indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
if (!bp || !buffer_mapped(bp))
- return 0;
+ break;
typ = ((struct vxfs_typed *)bp->b_data) +
(i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
- off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+ off = be64_to_cpu(typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
if (block < off) {
brelse(bp);
continue;
}
- switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+ switch ((u_int32_t)(be64_to_cpu(typ->vt_hdr) >> VXFS_TYPED_TYPESHIFT)) {
case VXFS_TYPED_INDIRECT:
- pblock = vxfs_bmap_indir(ip, typ->vt_block,
- typ->vt_size, block - off);
+ pblock = vxfs_bmap_indir(ip, be32_to_cpu(typ->vt_block),
+ be32_to_cpu(typ->vt_size), block - off);
if (pblock == -2)
break;
goto out;
case VXFS_TYPED_DATA:
- if ((block - off) >= typ->vt_size)
+ if ((block - off) >= be32_to_cpu(typ->vt_size))
break;
- pblock = (typ->vt_block + block - off);
+ pblock = be32_to_cpu(typ->vt_block) + block - off;
goto out;
case VXFS_TYPED_INDIRECT_DEV4:
case VXFS_TYPED_DATA_DEV4: {
struct vxfs_typed_dev4 *typ4 =
(struct vxfs_typed_dev4 *)typ;
- printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
- printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
- (unsigned long long) typ4->vd4_block,
- (unsigned long long) typ4->vd4_size,
- typ4->vd4_dev);
+ printk(KERN_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
+ __FUNCTION__, __LINE__,
+ (unsigned long long) be64_to_cpu(typ4->vd4_block),
+ (unsigned long long) be64_to_cpu(typ4->vd4_size),
+ be32_to_cpu(typ4->vd4_dev));
goto fail;
}
default:
+ printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, be64_to_cpu(typ->vt_hdr));
BUG();
}
brelse(bp);
@@ -182,7 +185,9 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
fail:
pblock = 0;
out:
- brelse(bp);
+ if (bp)
+ brelse(bp);
+ F_EXIT_V2();
return (pblock);
}
@@ -200,16 +205,18 @@ out:
static daddr_t
vxfs_bmap_typed(struct inode *ip, long iblock)
{
- struct vxfs_inode_info *vip = VXFS_INO(ip);
- daddr_t pblock = 0;
- int i;
+ struct vxfs_inode_info *vip = VXFS_INO(ip);
+ daddr_t pblock = 0;
+ int i;
+ F_ENTER_V2();
for (i = 0; i < VXFS_NTYPED; i++) {
- struct vxfs_typed *typ = vip->vii_org.typed + i;
+ struct vxfs_typed *typ = vip->vii_org.typed + i; // cpu endian
int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
-#ifdef DIAGNOSTIC
- vxfs_typdump(typ);
+#ifdef DIAGNOSTIC_V2
+ printk(KERN_DEBUG "%s:%d type=%Lu, ofs=0x%Lx, blk=%d, size=%d\n", __FUNCTION__, __LINE__,
+ typ->vt_hdr >> VXFS_TYPED_TYPESHIFT, off, typ->vt_block, typ->vt_size );
#endif
if (iblock < off)
continue;
@@ -219,29 +226,36 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
typ->vt_size, iblock - off);
if (pblock == -2)
break;
- return (pblock);
+ goto out;
+
case VXFS_TYPED_DATA:
- if ((iblock - off) < typ->vt_size)
- return (typ->vt_block + iblock - off);
+ if ((iblock - off) < typ->vt_size) {
+ pblock = typ->vt_block + iblock - off;
+ goto out;
+ }
break;
case VXFS_TYPED_INDIRECT_DEV4:
case VXFS_TYPED_DATA_DEV4: {
struct vxfs_typed_dev4 *typ4 =
(struct vxfs_typed_dev4 *)typ;
- printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
- printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
+ printk(KERN_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
+ __FUNCTION__, __LINE__,
(unsigned long long) typ4->vd4_block,
(unsigned long long) typ4->vd4_size,
typ4->vd4_dev);
- return 0;
+ pblock = 0;
+ goto out;
}
default:
+ printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, typ->vt_hdr);
BUG();
}
}
- return 0;
+out:
+ F_EXIT_V2("pblk %d", pblock);
+ return pblock;
}
/**
@@ -270,12 +284,14 @@ vxfs_bmap1(struct inode *ip, long iblock)
if (VXFS_ISIMMED(vip))
goto unsupp;
- printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
- ip->i_ino, vip->vii_orgtype);
+ printk(KERN_ERR "%s:%d inode %ld has no valid orgtype (%x)\n",
+ __FUNCTION__, __LINE__,
+ ip->i_ino, vip->vii_orgtype);
BUG();
unsupp:
- printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
- ip->i_ino, vip->vii_orgtype);
+ printk(KERN_WARNING "%s:%d inode %ld has an unsupported orgtype (%x)\n",
+ __FUNCTION__, __LINE__,
+ ip->i_ino, vip->vii_orgtype);
return 0;
}
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index aaf1fb0..d8b52e6 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -84,9 +84,5 @@ struct vxfs_direct {
#define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
#define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
-/*
- * VXFS_DIRBLKOV is the overhead of a specific dirblock.
- */
-#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4)
#endif /* _VXFS_DIR_H_ */
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 881aa3d..3d20421 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -55,7 +55,7 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
/* vxfs_inode.c */
extern const struct address_space_operations vxfs_immed_aops;
-extern struct kmem_cache *vxfs_inode_cachep;
+//extern struct kmem_cache *vxfs_inode_cachep;
extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
extern struct inode * vxfs_get_fake_inode(struct super_block *,
struct vxfs_inode_info *);
@@ -64,6 +64,10 @@ extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t
extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
extern struct inode * vxfs_iget(struct super_block *, ino_t);
extern void vxfs_evict_inode(struct inode *);
+extern void vxfs_destroy_inode(struct inode *ip);
+extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
+extern int vxfs_inode_info_cache(int setup);
+
/* vxfs_lookup.c */
extern const struct inode_operations vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c9a6a94..69fcd7f 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -2,6 +2,35 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * (c) 2016 Krzysztof Blaszkowski.
+ * Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ * - code not aware of cpu endianess and ondisk data is BE.
+ * - misaligned structures read from block device
+ * - wrong SB block number. default offset is 8kB
+ * - kmem_cache_alloc() objectes released with kfree()
+ * - inode.i_private released in evict_inode() callback.
+ * - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// * cksum mnt/usr/share/man/man3.Z/*
+// * cksum mnt/usr/share/doc/10.20RelNotes
+// * cksum mnt/usr/local/doom/*
+// * cksum mnt/usr/sprockets/tools/instrument/16700/*
+// * cksum mnt/usr/share/doc/*
+// * cksum mnt/usr/sprockets/lib/*
+// * cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ * 3457951056 4196020 /usr/local/doom/doom1.wad
+ * 2527157998 35344 /usr/local/doom/doomlaunch
+ * 2974998129 413696 /usr/local/doom/hpdoom
+ *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -60,6 +89,34 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
}
#endif
+#define VXFS_BE32(field1, field2) fhp->field1 = be32_to_cpu(dbh->field2)
+
+
+static void inline dbh2fhp(struct vxfs_fsh *fhp, void *_dbh)
+{
+#ifdef __LITTLE_ENDIAN
+ struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
+
+ VXFS_BE32(fsh_version, fsh_version);
+ VXFS_BE32(fsh_fsindex, fsh_fsindex);
+ VXFS_BE32(fsh_time, fsh_time);
+ VXFS_BE32(fsh_utime, fsh_utime);
+ VXFS_BE32(fsh_extop, fsh_extop);
+ VXFS_BE32(fsh_ninodes, fsh_ninodes);
+ VXFS_BE32(fsh_nau, fsh_nau);
+ VXFS_BE32(fsh_old_ilesize, fsh_old_ilesize);
+ VXFS_BE32(fsh_dflags, fsh_dflags);
+ VXFS_BE32(fsh_quota, fsh_quota);
+ VXFS_BE32(fsh_maxinode, fsh_maxinode);
+ VXFS_BE32(fsh_iauino, fsh_iauino);
+ VXFS_BE32(fsh_ilistino[0], fsh_ilistino[0]);
+ VXFS_BE32(fsh_ilistino[1], fsh_ilistino[1]);
+ VXFS_BE32(fsh_lctino, fsh_lctino);
+#else
+ memcpy(fhp, _dbh, sizeof(*fhp));
+#endif
+}
+
/**
* vxfs_getfsh - read fileset header into memory
* @ip: the (fake) fileset header inode
@@ -83,7 +140,8 @@ vxfs_getfsh(struct inode *ip, int which)
if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
goto out;
- memcpy(fhp, bp->b_data, sizeof(*fhp));
+
+ dbh2fhp(fhp, bp->b_data);
put_bh(bp);
return (fhp);
@@ -110,9 +168,12 @@ vxfs_read_fshead(struct super_block *sbp)
struct vxfs_fsh *pfp, *sfp;
struct vxfs_inode_info *vip, *tip;
+ F_ENTER();
+
vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
if (!vip) {
printk(KERN_ERR "vxfs: unable to read fsh inode\n");
+ F_EXIT();
return -EINVAL;
}
if (!VXFS_ISFSH(vip)) {
@@ -121,10 +182,8 @@ vxfs_read_fshead(struct super_block *sbp)
goto out_free_fship;
}
-
#ifdef DIAGNOSTIC
- printk("vxfs: fsh inode dump:\n");
- vxfs_dumpi(vip, infp->vsi_fshino);
+ printk("%s:%d\n", __FUNCTION__, __LINE__);
#endif
infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
@@ -160,7 +219,7 @@ vxfs_read_fshead(struct super_block *sbp)
infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
if (!infp->vsi_stilist) {
printk(KERN_ERR "vxfs: unable to get structural list inode\n");
- kfree(tip);
+ vxfs_inode_info_free(tip);
goto out_free_pfp;
}
if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
@@ -175,7 +234,7 @@ vxfs_read_fshead(struct super_block *sbp)
infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
if (!infp->vsi_ilist) {
printk(KERN_ERR "vxfs: unable to get inode list inode\n");
- kfree(tip);
+ vxfs_inode_info_free(tip);
goto out_iput_stilist;
}
if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
@@ -184,6 +243,7 @@ vxfs_read_fshead(struct super_block *sbp)
goto out_iput_ilist;
}
+ F_EXIT();
return 0;
out_iput_ilist:
@@ -196,8 +256,10 @@ vxfs_read_fshead(struct super_block *sbp)
kfree(sfp);
out_iput_fship:
iput(infp->vsi_fship);
+ F_EXIT();
return -EINVAL;
out_free_fship:
- kfree(vip);
+ vxfs_inode_info_free(vip);
+ F_EXIT();
return -EINVAL;
}
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 363e3ae..84dec28 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -2,6 +2,34 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * (c) 2016 Krzysztof Blaszkowski.
+ * Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ * - code not aware of cpu endianess and ondisk data is BE.
+ * - misaligned structures read from block device
+ * - wrong SB block number. default offset is 8kB
+ * - kmem_cache_alloc() objectes released with kfree()
+ * - inode.i_private released in evict_inode() callback.
+ * - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// * cksum mnt/usr/share/man/man3.Z/*
+// * cksum mnt/usr/share/doc/10.20RelNotes
+// * cksum mnt/usr/local/doom/*
+// * cksum mnt/usr/sprockets/tools/instrument/16700/*
+// * cksum mnt/usr/share/doc/*
+// * cksum mnt/usr/sprockets/lib/*
+// * cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ * 3457951056 4196020 /usr/local/doom/doom1.wad
+ * 2527157998 35344 /usr/local/doom/doomlaunch
+ * 2974998129 413696 /usr/local/doom/hpdoom
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -41,7 +69,7 @@
#include "vxfs_extern.h"
-struct kmem_cache *vxfs_inode_cachep;
+static struct kmem_cache *vxfs_inode_cachep;
#ifdef DIAGNOSTIC
@@ -51,23 +79,88 @@ struct kmem_cache *vxfs_inode_cachep;
void
vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
{
- printk(KERN_DEBUG "\n\n");
- if (ino)
- printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino);
+#ifdef DIAGNOSTIC_V2
+ if (ino && vip)
+ printk(KERN_DEBUG "\nvxfs inode %ld dump **** %p\n", ino, vip);
else
- printk(KERN_DEBUG "dumping unknown vxfs inode\n");
+ printk(KERN_DEBUG "\ndumping unknown vxfs inode %p\n", vip);
- printk(KERN_DEBUG "---------------------------\n");
- printk(KERN_DEBUG "mode is %x\n", vip->vii_mode);
- printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n",
- vip->vii_nlink, vip->vii_uid, vip->vii_gid);
- printk(KERN_DEBUG "size:%Lx, blocks:%u\n",
+ if (vip) {
+ printk(KERN_DEBUG " * mode: %x, type %d\n", vip->vii_mode, vip->vii_orgtype);
+ printk(KERN_DEBUG " * size:%Lx, blocks:%u\n",
vip->vii_size, vip->vii_blocks);
- printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype);
+ printk(KERN_DEBUG " * nlink:%u, uid:%u, gid:%u\n",
+ vip->vii_nlink, vip->vii_uid, vip->vii_gid);
+ }
+#endif
}
#endif
+#define VXFS_BE32(field1, field2) vip->field1 = be32_to_cpu(dip->field2)
+#define VXFS_BE64(field1, field2) vip->field1 = be64_to_cpu(dip->field2)
+#define VXFS_BE16(field1, field2) vip->field1 = be16_to_cpu(dip->field2)
+
+
+static void inline dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
+{
+#ifdef __LITTLE_ENDIAN
+ int j;
+
+ VXFS_BE32(vdi_mode, vdi_mode);
+ VXFS_BE32(vdi_nlink, vdi_nlink);
+ VXFS_BE32(vdi_uid, vdi_uid);
+ VXFS_BE32(vdi_gid, vdi_gid);
+ VXFS_BE64(vdi_size, vdi_size);
+ VXFS_BE32(vdi_atime, vdi_atime);
+ VXFS_BE32(vdi_autime, vdi_autime);
+ VXFS_BE32(vdi_mtime, vdi_mtime);
+ VXFS_BE32(vdi_mutime, vdi_mutime);
+ VXFS_BE32(vdi_ctime, vdi_ctime);
+ VXFS_BE32(vdi_cutime, vdi_cutime);
+ vip->vdi_aflags = dip->vdi_aflags;
+ vip->vdi_orgtype = dip->vdi_orgtype;
+ VXFS_BE16(vdi_eopflags, vdi_eopflags);
+ VXFS_BE32(vdi_eopdata, vdi_eopdata);
+
+ VXFS_BE32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
+ VXFS_BE32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
+ VXFS_BE32(vdi_blocks, vdi_blocks);
+ VXFS_BE32(vdi_gen, vdi_gen);
+ VXFS_BE64(vdi_version, vdi_version);
+
+ switch (dip->vdi_orgtype) {
+ case VXFS_ORG_EXT4:
+ VXFS_BE32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
+ VXFS_BE32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
+ for (j = 0; j < VXFS_NIADDR; j++) {
+ VXFS_BE32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
+ }
+ for (j = 0; j < VXFS_NDADDR; j++) {
+ VXFS_BE32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
+ VXFS_BE32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
+ }
+ break;
+ case VXFS_ORG_IMMED:
+ memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
+ break;
+ case VXFS_ORG_TYPED:
+ for (j = 0; j < VXFS_NTYPED; j++) {
+ VXFS_BE64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
+ VXFS_BE32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
+ VXFS_BE32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
+ }
+ break;
+
+ };
+
+ VXFS_BE32(vdi_iattrino, vdi_iattrino);
+#else
+ memcpy(vip, dip, sizeof(*vip));
+#endif
+}
+
+
/**
* vxfs_blkiget - find inode based on extent #
* @sbp: superblock of the filesystem we search in
@@ -84,6 +177,9 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
* buffercache. This function should not be used outside the
* read_super() method, otherwise the data may be incoherent.
*/
+
+
+
struct vxfs_inode_info *
vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
{
@@ -101,7 +197,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
goto fail;
dip = (struct vxfs_dinode *)(bp->b_data + offset);
- memcpy(vip, dip, sizeof(*vip));
+ dip2vip_cpy(vip, dip);
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
@@ -143,7 +239,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
goto fail;
dip = (struct vxfs_dinode *)(kaddr + offset);
- memcpy(vip, dip, sizeof(*vip));
+ dip2vip_cpy(vip, dip);
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
@@ -190,7 +286,7 @@ vxfs_stiget(struct super_block *sbp, ino_t ino)
static __inline__ umode_t
vxfs_transmod(struct vxfs_inode_info *vip)
{
- umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
+ umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
if (VXFS_ISFIFO(vip))
ret |= S_IFIFO;
@@ -340,21 +436,61 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
static void vxfs_i_callback(struct rcu_head *head)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
- kmem_cache_free(vxfs_inode_cachep, inode->i_private);
+ void *priv = inode->i_private;
+
+ inode->i_private = NULL;
+ // just in case the same inode was used elsewhere after releasing i_private.
+ // if it was then dereferencing NULL is far better than using invalid
+ // pointer to memory claimed by something.
+ kmem_cache_free(vxfs_inode_cachep, priv);
+}
+
+void vxfs_destroy_inode(struct inode *ip)
+{
+ call_rcu(&ip->i_rcu, vxfs_i_callback);
+}
+
+void vxfs_inode_info_free(struct vxfs_inode_info *vip)
+{
+ kmem_cache_free(vxfs_inode_cachep, vip);
}
+
/**
* vxfs_evict_inode - remove inode from main memory
* @ip: inode to discard.
*
* Description:
- * vxfs_evict_inode() is called on the final iput and frees the private
- * inode area.
+ * vxfs_evict_inode() is called on the final iput
*/
void
vxfs_evict_inode(struct inode *ip)
{
truncate_inode_pages_final(&ip->i_data);
+ invalidate_inode_buffers(ip);
clear_inode(ip);
- call_rcu(&ip->i_rcu, vxfs_i_callback);
}
+
+int vxfs_inode_info_cache(int setup)
+{
+ int rc = 0;
+
+ if (!setup) {
+ vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
+ sizeof(struct vxfs_inode_info), 0,
+ SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
+
+ if (!vxfs_inode_cachep)
+ rc = -ENOMEM;
+ } else {
+ /*
+ * Make sure all delayed rcu free inodes are flushed before we
+ * destroy cache.
+ */
+ rcu_barrier();
+ kmem_cache_destroy(vxfs_inode_cachep);
+ }
+
+ return rc;
+}
+
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 240aeb1..9fc3533 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -77,13 +77,13 @@ struct vxfs_ext4 {
vx_daddr_t extent; /* Extent number */
int32_t size; /* Size of extent */
} ve4_direct[VXFS_NDADDR];
-};
+} __attribute__((packed));
struct vxfs_typed {
u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
vx_daddr_t vt_block; /* Extent block */
int32_t vt_size; /* Size in blocks */
-};
+} __attribute__((packed));
struct vxfs_typed_dev4 {
u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
@@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
u_int64_t vd4_size; /* Size in blocks */
int32_t vd4_dev; /* Device ID */
u_int32_t __pad1;
-};
+} __attribute__((packed));
/*
* The inode as contained on the physical device.
@@ -134,7 +134,7 @@ struct vxfs_dinode {
struct vxfs_typed typed[VXFS_NTYPED];
} vdi_org;
u_int32_t vdi_iattrino;
-};
+} __attribute__((packed));
#define vdi_rdev vdi_ftarea.rdev
#define vdi_dotdot vdi_ftarea.dotdot
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 99c7f0a..2e5365b 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -2,6 +2,34 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ * (c) 2016 Krzysztof Blaszkowski.
+ * Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ * - code not aware of cpu endianess and ondisk data is BE.
+ * - misaligned structures read from block device
+ * - wrong SB block number. default offset is 8kB
+ * - kmem_cache_alloc() objectes released with kfree()
+ * - inode.i_private released in evict_inode() callback.
+ * - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// * cksum mnt/usr/share/man/man3.Z/*
+// * cksum mnt/usr/share/doc/10.20RelNotes
+// * cksum mnt/usr/local/doom/*
+// * cksum mnt/usr/sprockets/tools/instrument/16700/*
+// * cksum mnt/usr/share/doc/*
+// * cksum mnt/usr/sprockets/lib/*
+// * cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ * 3457951056 4196020 /usr/local/doom/doom1.wad
+ * 2527157998 35344 /usr/local/doom/doomlaunch
+ * 2974998129 413696 /usr/local/doom/hpdoom
+ *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -76,6 +104,15 @@ dir_blocks(struct inode *ip)
}
/*
+ * VXFS_dirblk_ovh is the overhead of a specific dirblock.
+ */
+static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp)
+{
+ return (sizeof(short) * be16_to_cpu(dbp->d_nhash)) + 4;
+}
+
+
+/*
* NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
*
* len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
@@ -83,19 +120,13 @@ dir_blocks(struct inode *ip)
static inline int
vxfs_match(int len, const char * const name, struct vxfs_direct *de)
{
- if (len != de->d_namelen)
+ if (len != be16_to_cpu(de->d_namelen))
return 0;
if (!de->d_ino)
return 0;
return !memcmp(name, de->d_name, len);
}
-static inline struct vxfs_direct *
-vxfs_next_entry(struct vxfs_direct *de)
-{
- return ((struct vxfs_direct *)((char*)de + de->d_reclen));
-}
-
/**
* vxfs_find_entry - find a mathing directory entry for a dentry
* @ip: directory inode
@@ -113,50 +144,73 @@ vxfs_next_entry(struct vxfs_direct *de)
static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
{
- u_long npages, page, nblocks, pblocks, block;
- u_long bsize = ip->i_sb->s_blocksize;
- const char *name = dp->d_name.name;
- int namelen = dp->d_name.len;
-
- npages = dir_pages(ip);
- nblocks = dir_blocks(ip);
- pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
-
- for (page = 0; page < npages; page++) {
- caddr_t kaddr;
- struct page *pp;
-
- pp = vxfs_get_page(ip->i_mapping, page);
- if (IS_ERR(pp))
- continue;
- kaddr = (caddr_t)page_address(pp);
-
- for (block = 0; block <= nblocks && block <= pblocks; block++) {
- caddr_t baddr, limit;
- struct vxfs_dirblk *dbp;
- struct vxfs_direct *de;
-
- baddr = kaddr + (block * bsize);
- limit = baddr + bsize - VXFS_DIRLEN(1);
-
- dbp = (struct vxfs_dirblk *)baddr;
- de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
-
- for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
- if (!de->d_reclen)
- break;
- if (!de->d_ino)
- continue;
- if (vxfs_match(namelen, name, de)) {
- *ppp = pp;
- return (de);
- }
+ u_long bsize = ip->i_sb->s_blocksize;
+ const char *name = dp->d_name.name;
+ int namelen = dp->d_name.len;
+ loff_t limit = VXFS_DIRROUND(ip->i_size);
+ struct vxfs_direct *de_exit = NULL;
+ loff_t pos = 0;
+
+
+ F_ENTER_V2("\"%s\" %d", name, namelen);
+
+ while (pos < limit) {
+ struct page *pp;
+ char *kaddr;
+ int pg_ofs = pos & ~PAGE_CACHE_MASK;
+
+ pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+ if (IS_ERR(pp)) {
+ return NULL;
+ }
+ kaddr = (char *)page_address(pp);
+
+#ifdef DIAGNOSTIC_V2
+ printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
+#endif
+ while (pg_ofs < PAGE_SIZE && pos < limit) {
+ struct vxfs_direct *de;
+
+ if ((pos & (bsize - 1)) < 4) {
+ struct vxfs_dirblk *dbp =
+ (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
+ pos += VXFS_dirblk_ovh(dbp);
+ pg_ofs += VXFS_dirblk_ovh(dbp);
+ }
+ de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+#ifdef DIAGNOSTIC_V2
+ printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
+ de, pg_ofs,
+ de->d_name, be16_to_cpu(de->d_namelen),
+ be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
+#endif
+ if (!de->d_reclen) {
+ pos += bsize - 1;
+ pos &= ~(bsize - 1);
+ break;
+ }
+
+ pg_ofs += be16_to_cpu(de->d_reclen);
+ pos += be16_to_cpu(de->d_reclen);
+ if (!de->d_ino) {
+ continue;
+ }
+
+ if (vxfs_match(namelen, name, de)) {
+ *ppp = pp;
+ de_exit= de; //return (de);
+ break;
}
}
- vxfs_put_page(pp);
+ if (!de_exit)
+ vxfs_put_page(pp);
+ else
+ break;
}
- return NULL;
+ F_EXIT_V2("\"%s\": %p", name, de_exit);
+ return de_exit;
}
/**
@@ -180,11 +234,10 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
de = vxfs_find_entry(dip, dp, &pp);
if (de) {
- ino = de->d_ino;
- kunmap(pp);
- page_cache_release(pp);
+ ino = be32_to_cpu(de->d_ino);
+ vxfs_put_page(pp);
}
-
+
return (ino);
}
@@ -207,17 +260,17 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
{
struct inode *ip = NULL;
ino_t ino;
-
+
if (dp->d_name.len > VXFS_NAMELEN)
return ERR_PTR(-ENAMETOOLONG);
-
+
ino = vxfs_inode_by_name(dip, dp);
if (ino) {
ip = vxfs_iget(dip->i_sb, ino);
if (IS_ERR(ip))
return ERR_CAST(ip);
+ d_add(dp, ip);
}
- d_add(dp, ip);
return NULL;
}
@@ -234,80 +287,95 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
* Returns:
* Zero.
*/
+
static int
vxfs_readdir(struct file *fp, struct dir_context *ctx)
{
struct inode *ip = file_inode(fp);
struct super_block *sbp = ip->i_sb;
u_long bsize = sbp->s_blocksize;
- u_long page, npages, block, pblocks, nblocks, offset;
- loff_t pos;
+ loff_t pos, limit;
+
+ F_ENTER_V3("pos %ld, ino %ld, size %ld", (long)ctx->pos, ip->i_ino, (long)ip->i_size);
if (ctx->pos == 0) {
if (!dir_emit_dot(fp, ctx))
- return 0;
- ctx->pos = 1;
+ goto out;
+ ctx->pos++;
}
if (ctx->pos == 1) {
if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
- return 0;
- ctx->pos = 2;
+ goto out;
+ ctx->pos++;
}
- pos = ctx->pos - 2;
-
- if (pos > VXFS_DIRROUND(ip->i_size))
- return 0;
- npages = dir_pages(ip);
- nblocks = dir_blocks(ip);
- pblocks = VXFS_BLOCK_PER_PAGE(sbp);
+ limit = VXFS_DIRROUND(ip->i_size);
+ if (ctx->pos > limit) {
+// ctx->pos = 0;
+ goto out;
+ }
- page = pos >> PAGE_CACHE_SHIFT;
- offset = pos & ~PAGE_CACHE_MASK;
- block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
+ pos = ctx->pos & ~3L;
- for (; page < npages; page++, block = 0) {
- char *kaddr;
- struct page *pp;
+ while (pos < limit) {
+ struct page *pp;
+ char *kaddr;
+ int pg_ofs = pos & ~PAGE_CACHE_MASK;
+ int rc = 0;
- pp = vxfs_get_page(ip->i_mapping, page);
- if (IS_ERR(pp))
- continue;
+ pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+ if (IS_ERR(pp)) {
+ return -ENOMEM;
+ }
kaddr = (char *)page_address(pp);
- for (; block <= nblocks && block <= pblocks; block++) {
- char *baddr, *limit;
- struct vxfs_dirblk *dbp;
- struct vxfs_direct *de;
-
- baddr = kaddr + (block * bsize);
- limit = baddr + bsize - VXFS_DIRLEN(1);
-
- dbp = (struct vxfs_dirblk *)baddr;
- de = (struct vxfs_direct *)
- (offset ?
- (kaddr + offset) :
- (baddr + VXFS_DIRBLKOV(dbp)));
-
- for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
- if (!de->d_reclen)
- break;
- if (!de->d_ino)
- continue;
-
- offset = (char *)de - kaddr;
- ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
- if (!dir_emit(ctx, de->d_name, de->d_namelen,
- de->d_ino, DT_UNKNOWN)) {
- vxfs_put_page(pp);
- return 0;
- }
+#ifdef DIAGNOSTIC_V3
+ printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
+#endif
+ while (pg_ofs < PAGE_SIZE && pos < limit) {
+ struct vxfs_direct *de;
+
+ if ((pos & (bsize - 1)) < 4) {
+ struct vxfs_dirblk *dbp =
+ (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
+ pos += VXFS_dirblk_ovh(dbp);
+ pg_ofs += VXFS_dirblk_ovh(dbp);
+ }
+ de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+#ifdef DIAGNOSTIC_V3
+ printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
+ de, pg_ofs,
+ de->d_name, be16_to_cpu(de->d_namelen),
+ be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
+#endif
+ if (!de->d_reclen) {
+ pos += bsize - 1;
+ pos &= ~(bsize - 1);
+ break;
+ }
+
+ pg_ofs += be16_to_cpu(de->d_reclen);
+ pos += be16_to_cpu(de->d_reclen);
+ if (!de->d_ino) {
+ continue;
+ }
+
+ if (! (rc = dir_emit(ctx, de->d_name, be16_to_cpu(de->d_namelen),
+ be32_to_cpu(de->d_ino), DT_UNKNOWN))) {
+ // the dir entry was not submitted, so fix pos.
+ pos -= be16_to_cpu(de->d_reclen);
+ break;
}
- offset = 0;
}
vxfs_put_page(pp);
- offset = 0;
+ if (!rc)
+ break;
}
- ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
+
+ ctx->pos = pos | 2;
+
+out:
+ F_EXIT_V3("pos %ld", (long)ctx->pos);
return 0;
}
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 0495008..19a1cab 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -2,6 +2,10 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * 2016 Krzysztof Blaszkowski.
+ * Many bug fixes, improvements & tests
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -43,14 +47,14 @@ static inline void
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
{
BUG_ON(infp->vsi_fshino);
- infp->vsi_fshino = fshp->olt_fsino[0];
+ infp->vsi_fshino = be32_to_cpu(fshp->olt_fsino[0]);
}
static inline void
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
{
BUG_ON(infp->vsi_iext);
- infp->vsi_iext = ilistp->olt_iext[0];
+ infp->vsi_iext = be32_to_cpu(ilistp->olt_iext[0]);
}
static inline u_long
@@ -80,6 +84,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
struct buffer_head *bp;
struct vxfs_olt *op;
char *oaddr, *eaddr;
+ u32 j;
bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
@@ -87,8 +92,8 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
goto fail;
op = (struct vxfs_olt *)bp->b_data;
- if (op->olt_magic != VXFS_OLT_MAGIC) {
- printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
+ if ((j = be32_to_cpu(op->olt_magic)) != VXFS_OLT_MAGIC) {
+ printk(KERN_NOTICE "vxfs: ivalid olt magic number %08x at +%d\n", j, infp->vsi_oltext);
goto fail;
}
@@ -97,19 +102,24 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
* I've not seen any such filesystem yet and I'm lazy.. --hch
*/
if (infp->vsi_oltsize > 1) {
- printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
+ printk(KERN_NOTICE "vxfs: oltsize > 1 detected (%d).\n", infp->vsi_oltsize);
printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
goto fail;
}
- oaddr = bp->b_data + op->olt_size;
+ oaddr = bp->b_data + be32_to_cpu(op->olt_size);
eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
while (oaddr < eaddr) {
- struct vxfs_oltcommon *ocp =
+ struct vxfs_oltcommon *ocp =
(struct vxfs_oltcommon *)oaddr;
-
- switch (ocp->olt_type) {
+
+#ifdef DIAGNOSTIC
+ printk(KERN_DEBUG "oltc_type %d, sz %d at +%d\n",
+ be32_to_cpu(ocp->olt_type), be32_to_cpu(ocp->olt_size), (int)(oaddr - bp->b_data));
+#endif
+
+ switch (be32_to_cpu(ocp->olt_type)) {
case VXFS_OLT_FSHEAD:
vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
break;
@@ -118,11 +128,16 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
break;
}
- oaddr += ocp->olt_size;
+ oaddr += be32_to_cpu(ocp->olt_size);
}
+#ifdef DIAGNOSTIC
+ printk(KERN_DEBUG "olt_size %d, vsi_fshino %d, vsi_iext %ld\n",
+ be32_to_cpu(op->olt_size), (u32)infp->vsi_fshino, infp->vsi_iext);
+#endif
+
brelse(bp);
- return 0;
+ return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
fail:
brelse(bp);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7ca8c75..9fbf271 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -2,6 +2,38 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ * (c) 2016 Krzysztof Blaszkowski.
+ * Many bug fixes, improvements & tests.
+ *
+ * These bugs and improvements were as follows:
+ * - code not aware of cpu endianess and ondisk data is BE.
+ * - misaligned structures read from block device
+ * - wrong SB block number. default offset is 8kB
+ * - kmem_cache_alloc() objectes released with kfree()
+ * - inode.i_private released in evict_inode() callback.
+ * - refactored vxfs_readdir() and vxfs_find_entry()
+ *
+ * Tests were performed with image of HP 9000/779 disk (/ lvol)
+ * Example: */
+// * cksum mnt/usr/share/man/man3.Z/*
+// * cksum mnt/usr/share/doc/10.20RelNotes
+// * cksum mnt/usr/local/doom/*
+// * cksum mnt/usr/sprockets/tools/instrument/16700/*
+// * cksum mnt/usr/share/doc/*
+// * cksum mnt/usr/sprockets/lib/*
+// * cksum mnt/usr/sprockets/bin/*
+/*
+ * Needles to say that checksums of files match these evaluated by
+ * HP-UX B.10.20 cksum. E.g.:
+ * 3457951056 4196020 /usr/local/doom/doom1.wad
+ * 2527157998 35344 /usr/local/doom/doomlaunch
+ * 2974998129 413696 /usr/local/doom/hpdoom
+ *
+ * The hpux_mdsetup tool project which is aimed at making possible
+ * accessing HP-UX logical volumes by device mapper is here:
+ * https://sourceforge.net/projects/linux-vxfs/
+ *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -41,6 +73,7 @@
#include <linux/stat.h>
#include <linux/vfs.h>
#include <linux/mount.h>
+#include <linux/byteorder/generic.h>
#include "vxfs.h"
#include "vxfs_extern.h"
@@ -48,7 +81,7 @@
#include "vxfs_inode.h"
-MODULE_AUTHOR("Christoph Hellwig");
+MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
MODULE_LICENSE("Dual BSD/GPL");
@@ -59,6 +92,7 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *);
static int vxfs_remount(struct super_block *, int *, char *);
static const struct super_operations vxfs_super_ops = {
+ .destroy_inode = vxfs_destroy_inode,
.evict_inode = vxfs_evict_inode,
.put_super = vxfs_put_super,
.statfs = vxfs_statfs,
@@ -153,6 +187,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
u_long bsize;
struct inode *root;
int ret = -EINVAL;
+ int j;
sbp->s_flags |= MS_RDONLY;
@@ -168,7 +203,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
goto out;
}
- bp = sb_bread(sbp, 1);
+ bp = sb_bread(sbp, 8);
if (!bp || !buffer_mapped(bp)) {
if (!silent) {
printk(KERN_WARNING
@@ -178,32 +213,30 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
}
rsbp = (struct vxfs_sb *)bp->b_data;
- if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
+ if (be32_to_cpu(rsbp->vs_magic) != VXFS_SUPER_MAGIC) {
if (!silent)
- printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
+ printk(KERN_NOTICE "vxfs: WRONG superblock magic %08x\n", rsbp->vs_magic);
goto out;
}
- if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
- printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
- rsbp->vs_version);
+ j = be32_to_cpu(rsbp->vs_version);
+ if ((j < 2 || j > 4) && !silent) {
+ printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
goto out;
}
-#ifdef DIAGNOSTIC
- printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
- printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
-#endif
- sbp->s_magic = rsbp->vs_magic;
+ sbp->s_magic = be32_to_cpu(rsbp->vs_magic);
sbp->s_fs_info = infp;
infp->vsi_raw = rsbp;
infp->vsi_bp = bp;
- infp->vsi_oltext = rsbp->vs_oltext[0];
- infp->vsi_oltsize = rsbp->vs_oltsize;
+ infp->vsi_oltext = be32_to_cpu(rsbp->vs_oltext[0]);
+ infp->vsi_oltsize = be32_to_cpu(rsbp->vs_oltsize);
+
+ printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", be32_to_cpu(rsbp->vs_version));
- if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
+ if (!sb_set_blocksize(sbp, be32_to_cpu(rsbp->vs_bsize))) {
printk(KERN_WARNING "vxfs: unable to set final block size\n");
goto out;
}
@@ -229,6 +262,8 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
goto out_free_ilist;
}
+ printk(KERN_DEBUG "vxfs: blocksize: %d, oltext %d, oltsize %d\n",
+ be32_to_cpu(rsbp->vs_bsize), infp->vsi_oltext, infp->vsi_oltsize);
return 0;
@@ -237,6 +272,7 @@ out_free_ilist:
vxfs_put_fake_inode(infp->vsi_ilist);
vxfs_put_fake_inode(infp->vsi_stilist);
out:
+ printk(KERN_ERR "vxfs: mount failed %d\n", ret);
brelse(bp);
kfree(infp);
return ret;
@@ -264,29 +300,22 @@ MODULE_ALIAS("vxfs");
static int __init
vxfs_init(void)
{
- int rv;
+ int rc = vxfs_inode_info_cache(0);
- vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
- sizeof(struct vxfs_inode_info), 0,
- SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
- if (!vxfs_inode_cachep)
- return -ENOMEM;
- rv = register_filesystem(&vxfs_fs_type);
- if (rv < 0)
- kmem_cache_destroy(vxfs_inode_cachep);
- return rv;
+ if (!rc) {
+ rc = register_filesystem(&vxfs_fs_type);
+ if (rc < 0)
+ vxfs_inode_info_cache(1);
+ }
+ printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __FUNCTION__, __DATE__, __TIME__, rc);
+ return rc;
}
static void __exit
vxfs_cleanup(void)
{
unregister_filesystem(&vxfs_fs_type);
- /*
- * Make sure all delayed rcu free inodes are flushed before we
- * destroy cache.
- */
- rcu_barrier();
- kmem_cache_destroy(vxfs_inode_cachep);
+ vxfs_inode_info_cache(1);
}
module_init(vxfs_init);
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: freevxfs
2016-05-22 15:13 freevxfs Krzysztof Błaszkowski
@ 2016-05-23 8:23 ` Carlos Maiolino
2016-05-24 11:50 ` freevxfs Krzysztof Błaszkowski
2016-05-23 8:36 ` freevxfs Christoph Hellwig
1 sibling, 1 reply; 8+ messages in thread
From: Carlos Maiolino @ 2016-05-23 8:23 UTC (permalink / raw)
To: linux-fsdevel; +Cc: kb
On Sun, May 22, 2016 at 05:13:14PM +0200, Krzysztof Błaszkowski wrote:
> Hello All,
>
> I recently gave a try to vxfs (veritas fs) which is common to HP-UX and
> it turned out that the module has been broken for very long time.
>
> I fixed several issues with current freevxfs and also designed a
> userspace tool which helps creating dm block devices from e.g. regular
> file with raw image of hp-ux disk.
> https://sourceforge.net/projects/linux-vxfs/
>
>
> I send the patch because I believe that some people would appreciate
> support for this vintage file system (e.g. me) and also it will be nice
> to see my name in the kernel.
>
Hi,
- Can you please split this patch into individual patches fixing each specific
problem? It's easier to review, instead of a big patch with several fixes into
it.
- Also, as a quick view, there are a lot of trailing white spaces over the whole
patch, which, should be removed.
you can use the scripts/checkpatch.pl script to check your patches and see
match at least the basics requirements for sending patches to kernel and, a
read of Documentation/SubmittingPatches is interesting too.
> Regards,
>
> --
> Krzysztof Blaszkowski
> diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> index c8a9265..9890a84 100644
> --- a/fs/freevxfs/vxfs.h
> +++ b/fs/freevxfs/vxfs.h
> @@ -2,6 +2,39 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski.
> + * Many bug fixes, improvements & tests.
> + *
> + * These bugs and improvements were as follows:
> + * - code not aware of cpu endianess and ondisk data is BE.
> + * - misaligned structures read from block device
> + * - wrong SB block number. default offset is 8kB
> + * - kmem_cache_alloc() objectes released with kfree()
> + * - inode.i_private released in evict_inode() callback.
> + * - refactored vxfs_readdir() and vxfs_find_entry()
> + *
> + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> + * Example: */
> +// * cksum mnt/usr/share/man/man3.Z/*
> +// * cksum mnt/usr/share/doc/10.20RelNotes
> +// * cksum mnt/usr/local/doom/*
> +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> +// * cksum mnt/usr/share/doc/*
> +// * cksum mnt/usr/sprockets/lib/*
> +// * cksum mnt/usr/sprockets/bin/*
> +/*
Don't use //
> + * Needles to say that checksums of files match these evaluated by
> + * HP-UX B.10.20 cksum. E.g.:
> + * 3457951056 4196020 /usr/local/doom/doom1.wad
> + * 2527157998 35344 /usr/local/doom/doomlaunch
> + * 2974998129 413696 /usr/local/doom/hpdoom
> + *
> + * The hpux_mdsetup tool project which is aimed at making possible
> + * accessing HP-UX logical volumes by device mapper is here:
> + * https://sourceforge.net/projects/linux-vxfs/
> + *
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -38,6 +71,10 @@
> */
> #include <linux/types.h>
>
> +//#define DIAGNOSTIC
> +#undef DIAGNOSTIC
> +#undef DIAGNOSTIC_V2
> +#undef DIAGNOSTIC_V3
>
> /*
> * Data types for use with the VxFS ondisk format.
> @@ -152,7 +189,7 @@ struct vxfs_sb {
> /*
> * Actually much more...
> */
> -};
> +} __attribute__((packed));
>
>
> /*
> @@ -260,4 +297,35 @@ enum {
> #define VXFS_SBI(sbp) \
> ((struct vxfs_sb_info *)(sbp)->s_fs_info)
>
> +
> +#ifdef DIAGNOSTIC
> +#define F_ENTER(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#define F_EXIT(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +
> +#ifdef DIAGNOSTIC_V2
> +#define F_ENTER_V2(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#define F_EXIT_V2(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#else
> +#define F_ENTER_V2(a, b...)
> +#define F_EXIT_V2(a, b...)
> +#endif
> +
> +#ifdef DIAGNOSTIC_V3
> +#define F_ENTER_V3(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#define F_EXIT_V3(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#else
> +#define F_ENTER_V3(a, b...)
> +#define F_EXIT_V3(a, b...)
> +#endif
> +
> +#else // DIAGNOSTIC
> +#define F_ENTER(a, b...)
> +#define F_EXIT(a, b...)
> +#define F_ENTER_V2(a, b...)
> +#define F_EXIT_V2(a, b...)
> +#define F_ENTER_V3(a, b...)
> +#define F_EXIT_V3(a, b...)
> +#endif
> +
Lots of trailing white spaces here
> +
> #endif /* _VXFS_SUPER_H_ */
> diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
> index f86fd3c..58e6a17 100644
> --- a/fs/freevxfs/vxfs_bmap.c
> +++ b/fs/freevxfs/vxfs_bmap.c
> @@ -2,6 +2,10 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * 2016 Krzysztof Blaszkowski.
> + * Many bug fixes, improvements & tests
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -39,17 +43,6 @@
> #include "vxfs_extern.h"
>
>
> -#ifdef DIAGNOSTIC
> -static void
> -vxfs_typdump(struct vxfs_typed *typ)
> -{
> - printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
> - printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
> - printk("block=%x ", typ->vt_block);
> - printk("size=%x\n", typ->vt_size);
> -}
> -#endif
> -
> /**
> * vxfs_bmap_ext4 - do bmap for ext4 extents
> * @ip: pointer to the inode we do bmap for
> @@ -71,18 +64,23 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
> unsigned long bsize = sb->s_blocksize;
> u32 indsize = vip->vii_ext4.ve4_indsize;
> int i;
> + daddr_t rc = 0;
> +
> + F_ENTER_V2();
>
> if (indsize > sb->s_blocksize)
> goto fail_size;
>
> for (i = 0; i < VXFS_NDADDR; i++) {
> - struct direct *d = vip->vii_ext4.ve4_direct + i;
> - if (bn >= 0 && bn < d->size)
> - return (bn + d->extent);
> + struct direct *d = vip->vii_ext4.ve4_direct + i; // cpu endian
> + if (bn >= 0 && bn < d->size) {
> + rc = bn + d->extent;
> + break;
> + }
> bn -= d->size;
> }
>
> - if ((bn / (indsize * indsize * bsize / 4)) == 0) {
> + if (!rc && ((bn / (indsize * indsize * bsize / 4)) == 0)) {
> struct buffer_head *buf;
> daddr_t bno;
> u32 *indir;
> @@ -92,18 +90,21 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
> goto fail_buf;
>
> indir = (u32 *)buf->b_data;
> - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
> + bno = be32_to_cpu(indir[(bn/indsize) % (indsize*bn)]) + (bn%indsize);
>
> brelse(buf);
> - return bno;
> - } else
> - printk(KERN_WARNING "no matching indir?");
> + rc = bno;
> + }
> + if (!rc)
> + printk(KERN_WARNING "%s:%d no matching indir?\n", __FUNCTION__, __LINE__);
>
> - return 0;
> + F_EXIT_V2("pblk %d", rc);
> + return rc;
>
> fail_size:
> printk("vxfs: indirect extent too big!\n");
> fail_buf:
> + F_EXIT();
> return 0;
> }
>
> @@ -129,51 +130,53 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> {
> struct buffer_head *bp = NULL;
> daddr_t pblock = 0;
> - int i;
> + int i;
>
> + F_ENTER_V2();
> for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
> struct vxfs_typed *typ;
> - int64_t off;
> + int64_t off;
>
> bp = sb_bread(ip->i_sb,
> indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
> if (!bp || !buffer_mapped(bp))
> - return 0;
> + break;
>
> typ = ((struct vxfs_typed *)bp->b_data) +
> (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
> - off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
> + off = be64_to_cpu(typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
>
> if (block < off) {
> brelse(bp);
> continue;
> }
>
> - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
> + switch ((u_int32_t)(be64_to_cpu(typ->vt_hdr) >> VXFS_TYPED_TYPESHIFT)) {
> case VXFS_TYPED_INDIRECT:
> - pblock = vxfs_bmap_indir(ip, typ->vt_block,
> - typ->vt_size, block - off);
> + pblock = vxfs_bmap_indir(ip, be32_to_cpu(typ->vt_block),
> + be32_to_cpu(typ->vt_size), block - off);
> if (pblock == -2)
> break;
> goto out;
> case VXFS_TYPED_DATA:
> - if ((block - off) >= typ->vt_size)
> + if ((block - off) >= be32_to_cpu(typ->vt_size))
> break;
> - pblock = (typ->vt_block + block - off);
> + pblock = be32_to_cpu(typ->vt_block) + block - off;
> goto out;
> case VXFS_TYPED_INDIRECT_DEV4:
> case VXFS_TYPED_DATA_DEV4: {
> struct vxfs_typed_dev4 *typ4 =
> (struct vxfs_typed_dev4 *)typ;
>
> - printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
> - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
> - (unsigned long long) typ4->vd4_block,
> - (unsigned long long) typ4->vd4_size,
> - typ4->vd4_dev);
> + printk(KERN_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
> + __FUNCTION__, __LINE__,
> + (unsigned long long) be64_to_cpu(typ4->vd4_block),
> + (unsigned long long) be64_to_cpu(typ4->vd4_size),
> + be32_to_cpu(typ4->vd4_dev));
> goto fail;
> }
> default:
> + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, be64_to_cpu(typ->vt_hdr));
> BUG();
> }
> brelse(bp);
> @@ -182,7 +185,9 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> fail:
> pblock = 0;
> out:
> - brelse(bp);
> + if (bp)
> + brelse(bp);
> + F_EXIT_V2();
> return (pblock);
> }
>
> @@ -200,16 +205,18 @@ out:
> static daddr_t
> vxfs_bmap_typed(struct inode *ip, long iblock)
> {
> - struct vxfs_inode_info *vip = VXFS_INO(ip);
> - daddr_t pblock = 0;
> - int i;
> + struct vxfs_inode_info *vip = VXFS_INO(ip);
> + daddr_t pblock = 0;
> + int i;
>
> + F_ENTER_V2();
> for (i = 0; i < VXFS_NTYPED; i++) {
> - struct vxfs_typed *typ = vip->vii_org.typed + i;
> + struct vxfs_typed *typ = vip->vii_org.typed + i; // cpu endian
> int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
>
> -#ifdef DIAGNOSTIC
> - vxfs_typdump(typ);
> +#ifdef DIAGNOSTIC_V2
> + printk(KERN_DEBUG "%s:%d type=%Lu, ofs=0x%Lx, blk=%d, size=%d\n", __FUNCTION__, __LINE__,
> + typ->vt_hdr >> VXFS_TYPED_TYPESHIFT, off, typ->vt_block, typ->vt_size );
> #endif
> if (iblock < off)
> continue;
> @@ -219,29 +226,36 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
> typ->vt_size, iblock - off);
> if (pblock == -2)
> break;
> - return (pblock);
> + goto out;
> +
> case VXFS_TYPED_DATA:
> - if ((iblock - off) < typ->vt_size)
> - return (typ->vt_block + iblock - off);
> + if ((iblock - off) < typ->vt_size) {
> + pblock = typ->vt_block + iblock - off;
> + goto out;
> + }
> break;
> case VXFS_TYPED_INDIRECT_DEV4:
> case VXFS_TYPED_DATA_DEV4: {
> struct vxfs_typed_dev4 *typ4 =
> (struct vxfs_typed_dev4 *)typ;
>
> - printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
> - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
> + printk(KERN_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
> + __FUNCTION__, __LINE__,
> (unsigned long long) typ4->vd4_block,
> (unsigned long long) typ4->vd4_size,
> typ4->vd4_dev);
> - return 0;
> + pblock = 0;
> + goto out;
> }
> default:
> + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, typ->vt_hdr);
> BUG();
> }
> }
>
> - return 0;
> +out:
> + F_EXIT_V2("pblk %d", pblock);
> + return pblock;
> }
>
> /**
> @@ -270,12 +284,14 @@ vxfs_bmap1(struct inode *ip, long iblock)
> if (VXFS_ISIMMED(vip))
> goto unsupp;
>
> - printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
> - ip->i_ino, vip->vii_orgtype);
> + printk(KERN_ERR "%s:%d inode %ld has no valid orgtype (%x)\n",
> + __FUNCTION__, __LINE__,
> + ip->i_ino, vip->vii_orgtype);
> BUG();
>
> unsupp:
> - printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
> - ip->i_ino, vip->vii_orgtype);
> + printk(KERN_WARNING "%s:%d inode %ld has an unsupported orgtype (%x)\n",
> + __FUNCTION__, __LINE__,
> + ip->i_ino, vip->vii_orgtype);
> return 0;
> }
> diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
> index aaf1fb0..d8b52e6 100644
> --- a/fs/freevxfs/vxfs_dir.h
> +++ b/fs/freevxfs/vxfs_dir.h
> @@ -84,9 +84,5 @@ struct vxfs_direct {
> #define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
> #define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
>
> -/*
> - * VXFS_DIRBLKOV is the overhead of a specific dirblock.
> - */
> -#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4)
>
> #endif /* _VXFS_DIR_H_ */
> diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> index 881aa3d..3d20421 100644
> --- a/fs/freevxfs/vxfs_extern.h
> +++ b/fs/freevxfs/vxfs_extern.h
> @@ -55,7 +55,7 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
>
> /* vxfs_inode.c */
> extern const struct address_space_operations vxfs_immed_aops;
> -extern struct kmem_cache *vxfs_inode_cachep;
> +//extern struct kmem_cache *vxfs_inode_cachep;
> extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
> extern struct inode * vxfs_get_fake_inode(struct super_block *,
> struct vxfs_inode_info *);
> @@ -64,6 +64,10 @@ extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t
> extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
> extern struct inode * vxfs_iget(struct super_block *, ino_t);
> extern void vxfs_evict_inode(struct inode *);
> +extern void vxfs_destroy_inode(struct inode *ip);
> +extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
> +extern int vxfs_inode_info_cache(int setup);
> +
>
> /* vxfs_lookup.c */
> extern const struct inode_operations vxfs_dir_inode_ops;
> diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> index c9a6a94..69fcd7f 100644
> --- a/fs/freevxfs/vxfs_fshead.c
> +++ b/fs/freevxfs/vxfs_fshead.c
> @@ -2,6 +2,35 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski.
> + * Many bug fixes, improvements & tests.
> + *
> + * These bugs and improvements were as follows:
> + * - code not aware of cpu endianess and ondisk data is BE.
> + * - misaligned structures read from block device
> + * - wrong SB block number. default offset is 8kB
> + * - kmem_cache_alloc() objectes released with kfree()
> + * - inode.i_private released in evict_inode() callback.
> + * - refactored vxfs_readdir() and vxfs_find_entry()
> + *
> + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> + * Example: */
> +// * cksum mnt/usr/share/man/man3.Z/*
> +// * cksum mnt/usr/share/doc/10.20RelNotes
More white spaces and more //
> +// * cksum mnt/usr/local/doom/*
> +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> +// * cksum mnt/usr/share/doc/*
> +// * cksum mnt/usr/sprockets/lib/*
> +// * cksum mnt/usr/sprockets/bin/*
> +/*
> + * Needles to say that checksums of files match these evaluated by
> + * HP-UX B.10.20 cksum. E.g.:
> + * 3457951056 4196020 /usr/local/doom/doom1.wad
> + * 2527157998 35344 /usr/local/doom/doomlaunch
> + * 2974998129 413696 /usr/local/doom/hpdoom
> + *
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -60,6 +89,34 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
> }
> #endif
>
> +#define VXFS_BE32(field1, field2) fhp->field1 = be32_to_cpu(dbh->field2)
> +
> +
> +static void inline dbh2fhp(struct vxfs_fsh *fhp, void *_dbh)
> +{
> +#ifdef __LITTLE_ENDIAN
> + struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
> +
> + VXFS_BE32(fsh_version, fsh_version);
> + VXFS_BE32(fsh_fsindex, fsh_fsindex);
> + VXFS_BE32(fsh_time, fsh_time);
> + VXFS_BE32(fsh_utime, fsh_utime);
> + VXFS_BE32(fsh_extop, fsh_extop);
> + VXFS_BE32(fsh_ninodes, fsh_ninodes);
> + VXFS_BE32(fsh_nau, fsh_nau);
> + VXFS_BE32(fsh_old_ilesize, fsh_old_ilesize);
> + VXFS_BE32(fsh_dflags, fsh_dflags);
> + VXFS_BE32(fsh_quota, fsh_quota);
> + VXFS_BE32(fsh_maxinode, fsh_maxinode);
> + VXFS_BE32(fsh_iauino, fsh_iauino);
> + VXFS_BE32(fsh_ilistino[0], fsh_ilistino[0]);
> + VXFS_BE32(fsh_ilistino[1], fsh_ilistino[1]);
> + VXFS_BE32(fsh_lctino, fsh_lctino);
> +#else
> + memcpy(fhp, _dbh, sizeof(*fhp));
> +#endif
> +}
> +
> /**
> * vxfs_getfsh - read fileset header into memory
> * @ip: the (fake) fileset header inode
> @@ -83,7 +140,8 @@ vxfs_getfsh(struct inode *ip, int which)
>
> if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
> goto out;
> - memcpy(fhp, bp->b_data, sizeof(*fhp));
> +
> + dbh2fhp(fhp, bp->b_data);
>
> put_bh(bp);
> return (fhp);
> @@ -110,9 +168,12 @@ vxfs_read_fshead(struct super_block *sbp)
> struct vxfs_fsh *pfp, *sfp;
> struct vxfs_inode_info *vip, *tip;
>
> + F_ENTER();
> +
> vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
> if (!vip) {
> printk(KERN_ERR "vxfs: unable to read fsh inode\n");
> + F_EXIT();
> return -EINVAL;
> }
> if (!VXFS_ISFSH(vip)) {
> @@ -121,10 +182,8 @@ vxfs_read_fshead(struct super_block *sbp)
> goto out_free_fship;
> }
>
> -
> #ifdef DIAGNOSTIC
> - printk("vxfs: fsh inode dump:\n");
> - vxfs_dumpi(vip, infp->vsi_fshino);
> + printk("%s:%d\n", __FUNCTION__, __LINE__);
> #endif
>
> infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
> @@ -160,7 +219,7 @@ vxfs_read_fshead(struct super_block *sbp)
> infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
> if (!infp->vsi_stilist) {
> printk(KERN_ERR "vxfs: unable to get structural list inode\n");
> - kfree(tip);
> + vxfs_inode_info_free(tip);
> goto out_free_pfp;
> }
> if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
> @@ -175,7 +234,7 @@ vxfs_read_fshead(struct super_block *sbp)
> infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
> if (!infp->vsi_ilist) {
> printk(KERN_ERR "vxfs: unable to get inode list inode\n");
> - kfree(tip);
> + vxfs_inode_info_free(tip);
> goto out_iput_stilist;
> }
> if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
> @@ -184,6 +243,7 @@ vxfs_read_fshead(struct super_block *sbp)
> goto out_iput_ilist;
> }
>
> + F_EXIT();
> return 0;
>
> out_iput_ilist:
> @@ -196,8 +256,10 @@ vxfs_read_fshead(struct super_block *sbp)
> kfree(sfp);
> out_iput_fship:
> iput(infp->vsi_fship);
> + F_EXIT();
> return -EINVAL;
> out_free_fship:
> - kfree(vip);
> + vxfs_inode_info_free(vip);
> + F_EXIT();
> return -EINVAL;
> }
> diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> index 363e3ae..84dec28 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -2,6 +2,34 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski.
> + * Many bug fixes, improvements & tests.
> + *
> + * These bugs and improvements were as follows:
> + * - code not aware of cpu endianess and ondisk data is BE.
> + * - misaligned structures read from block device
> + * - wrong SB block number. default offset is 8kB
> + * - kmem_cache_alloc() objectes released with kfree()
> + * - inode.i_private released in evict_inode() callback.
> + * - refactored vxfs_readdir() and vxfs_find_entry()
> + *
> + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> + * Example: */
> +// * cksum mnt/usr/share/man/man3.Z/*
> +// * cksum mnt/usr/share/doc/10.20RelNotes
More white spaces and more //
> +// * cksum mnt/usr/local/doom/*
> +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> +// * cksum mnt/usr/share/doc/*
> +// * cksum mnt/usr/sprockets/lib/*
> +// * cksum mnt/usr/sprockets/bin/*
> +/*
> + * Needles to say that checksums of files match these evaluated by
> + * HP-UX B.10.20 cksum. E.g.:
> + * 3457951056 4196020 /usr/local/doom/doom1.wad
> + * 2527157998 35344 /usr/local/doom/doomlaunch
> + * 2974998129 413696 /usr/local/doom/hpdoom
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -41,7 +69,7 @@
> #include "vxfs_extern.h"
>
>
> -struct kmem_cache *vxfs_inode_cachep;
> +static struct kmem_cache *vxfs_inode_cachep;
>
>
> #ifdef DIAGNOSTIC
> @@ -51,23 +79,88 @@ struct kmem_cache *vxfs_inode_cachep;
> void
> vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
> {
> - printk(KERN_DEBUG "\n\n");
> - if (ino)
> - printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino);
> +#ifdef DIAGNOSTIC_V2
> + if (ino && vip)
> + printk(KERN_DEBUG "\nvxfs inode %ld dump **** %p\n", ino, vip);
> else
> - printk(KERN_DEBUG "dumping unknown vxfs inode\n");
> + printk(KERN_DEBUG "\ndumping unknown vxfs inode %p\n", vip);
>
> - printk(KERN_DEBUG "---------------------------\n");
> - printk(KERN_DEBUG "mode is %x\n", vip->vii_mode);
> - printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n",
> - vip->vii_nlink, vip->vii_uid, vip->vii_gid);
> - printk(KERN_DEBUG "size:%Lx, blocks:%u\n",
> + if (vip) {
> + printk(KERN_DEBUG " * mode: %x, type %d\n", vip->vii_mode, vip->vii_orgtype);
> + printk(KERN_DEBUG " * size:%Lx, blocks:%u\n",
> vip->vii_size, vip->vii_blocks);
> - printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype);
> + printk(KERN_DEBUG " * nlink:%u, uid:%u, gid:%u\n",
> + vip->vii_nlink, vip->vii_uid, vip->vii_gid);
> + }
> +#endif
> }
> #endif
>
>
> +#define VXFS_BE32(field1, field2) vip->field1 = be32_to_cpu(dip->field2)
> +#define VXFS_BE64(field1, field2) vip->field1 = be64_to_cpu(dip->field2)
> +#define VXFS_BE16(field1, field2) vip->field1 = be16_to_cpu(dip->field2)
> +
> +
> +static void inline dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
> +{
> +#ifdef __LITTLE_ENDIAN
> + int j;
> +
> + VXFS_BE32(vdi_mode, vdi_mode);
> + VXFS_BE32(vdi_nlink, vdi_nlink);
> + VXFS_BE32(vdi_uid, vdi_uid);
> + VXFS_BE32(vdi_gid, vdi_gid);
> + VXFS_BE64(vdi_size, vdi_size);
> + VXFS_BE32(vdi_atime, vdi_atime);
> + VXFS_BE32(vdi_autime, vdi_autime);
> + VXFS_BE32(vdi_mtime, vdi_mtime);
> + VXFS_BE32(vdi_mutime, vdi_mutime);
> + VXFS_BE32(vdi_ctime, vdi_ctime);
> + VXFS_BE32(vdi_cutime, vdi_cutime);
> + vip->vdi_aflags = dip->vdi_aflags;
> + vip->vdi_orgtype = dip->vdi_orgtype;
> + VXFS_BE16(vdi_eopflags, vdi_eopflags);
> + VXFS_BE32(vdi_eopdata, vdi_eopdata);
> +
> + VXFS_BE32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
> + VXFS_BE32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
> + VXFS_BE32(vdi_blocks, vdi_blocks);
> + VXFS_BE32(vdi_gen, vdi_gen);
> + VXFS_BE64(vdi_version, vdi_version);
> +
> + switch (dip->vdi_orgtype) {
> + case VXFS_ORG_EXT4:
> + VXFS_BE32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
> + VXFS_BE32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
> + for (j = 0; j < VXFS_NIADDR; j++) {
> + VXFS_BE32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
> + }
> + for (j = 0; j < VXFS_NDADDR; j++) {
> + VXFS_BE32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
> + VXFS_BE32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
> + }
> + break;
> + case VXFS_ORG_IMMED:
> + memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
> + break;
> + case VXFS_ORG_TYPED:
> + for (j = 0; j < VXFS_NTYPED; j++) {
> + VXFS_BE64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
> + VXFS_BE32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
> + VXFS_BE32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
> + }
> + break;
> +
> + };
> +
> + VXFS_BE32(vdi_iattrino, vdi_iattrino);
> +#else
> + memcpy(vip, dip, sizeof(*vip));
> +#endif
> +}
> +
> +
> /**
> * vxfs_blkiget - find inode based on extent #
> * @sbp: superblock of the filesystem we search in
> @@ -84,6 +177,9 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
> * buffercache. This function should not be used outside the
> * read_super() method, otherwise the data may be incoherent.
> */
> +
> +
> +
> struct vxfs_inode_info *
> vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
> {
> @@ -101,7 +197,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
> if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> goto fail;
> dip = (struct vxfs_dinode *)(bp->b_data + offset);
> - memcpy(vip, dip, sizeof(*vip));
> + dip2vip_cpy(vip, dip);
> #ifdef DIAGNOSTIC
> vxfs_dumpi(vip, ino);
> #endif
> @@ -143,7 +239,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
> if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> goto fail;
> dip = (struct vxfs_dinode *)(kaddr + offset);
> - memcpy(vip, dip, sizeof(*vip));
> + dip2vip_cpy(vip, dip);
> #ifdef DIAGNOSTIC
> vxfs_dumpi(vip, ino);
> #endif
> @@ -190,7 +286,7 @@ vxfs_stiget(struct super_block *sbp, ino_t ino)
> static __inline__ umode_t
> vxfs_transmod(struct vxfs_inode_info *vip)
> {
> - umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
> + umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
>
> if (VXFS_ISFIFO(vip))
> ret |= S_IFIFO;
> @@ -340,21 +436,61 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
> static void vxfs_i_callback(struct rcu_head *head)
> {
> struct inode *inode = container_of(head, struct inode, i_rcu);
> - kmem_cache_free(vxfs_inode_cachep, inode->i_private);
> + void *priv = inode->i_private;
> +
> + inode->i_private = NULL;
> + // just in case the same inode was used elsewhere after releasing i_private.
> + // if it was then dereferencing NULL is far better than using invalid
> + // pointer to memory claimed by something.
> + kmem_cache_free(vxfs_inode_cachep, priv);
> +}
> +
> +void vxfs_destroy_inode(struct inode *ip)
> +{
> + call_rcu(&ip->i_rcu, vxfs_i_callback);
> +}
> +
> +void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> +{
> + kmem_cache_free(vxfs_inode_cachep, vip);
> }
>
> +
> /**
> * vxfs_evict_inode - remove inode from main memory
> * @ip: inode to discard.
> *
> * Description:
> - * vxfs_evict_inode() is called on the final iput and frees the private
> - * inode area.
> + * vxfs_evict_inode() is called on the final iput
> */
> void
> vxfs_evict_inode(struct inode *ip)
> {
> truncate_inode_pages_final(&ip->i_data);
> + invalidate_inode_buffers(ip);
> clear_inode(ip);
> - call_rcu(&ip->i_rcu, vxfs_i_callback);
> }
> +
> +int vxfs_inode_info_cache(int setup)
> +{
> + int rc = 0;
> +
> + if (!setup) {
> + vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> + sizeof(struct vxfs_inode_info), 0,
> + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> +
> + if (!vxfs_inode_cachep)
> + rc = -ENOMEM;
> + } else {
> + /*
> + * Make sure all delayed rcu free inodes are flushed before we
> + * destroy cache.
> + */
> + rcu_barrier();
> + kmem_cache_destroy(vxfs_inode_cachep);
> + }
> +
> + return rc;
> +}
> +
> diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
> index 240aeb1..9fc3533 100644
> --- a/fs/freevxfs/vxfs_inode.h
> +++ b/fs/freevxfs/vxfs_inode.h
> @@ -77,13 +77,13 @@ struct vxfs_ext4 {
> vx_daddr_t extent; /* Extent number */
> int32_t size; /* Size of extent */
> } ve4_direct[VXFS_NDADDR];
> -};
> +} __attribute__((packed));
>
> struct vxfs_typed {
> u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> vx_daddr_t vt_block; /* Extent block */
> int32_t vt_size; /* Size in blocks */
> -};
> +} __attribute__((packed));
>
> struct vxfs_typed_dev4 {
> u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> @@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
> u_int64_t vd4_size; /* Size in blocks */
> int32_t vd4_dev; /* Device ID */
> u_int32_t __pad1;
> -};
> +} __attribute__((packed));
>
> /*
> * The inode as contained on the physical device.
> @@ -134,7 +134,7 @@ struct vxfs_dinode {
> struct vxfs_typed typed[VXFS_NTYPED];
> } vdi_org;
> u_int32_t vdi_iattrino;
> -};
> +} __attribute__((packed));
>
> #define vdi_rdev vdi_ftarea.rdev
> #define vdi_dotdot vdi_ftarea.dotdot
> diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> index 99c7f0a..2e5365b 100644
> --- a/fs/freevxfs/vxfs_lookup.c
> +++ b/fs/freevxfs/vxfs_lookup.c
> @@ -2,6 +2,34 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + * (c) 2016 Krzysztof Blaszkowski.
> + * Many bug fixes, improvements & tests.
> + *
> + * These bugs and improvements were as follows:
> + * - code not aware of cpu endianess and ondisk data is BE.
> + * - misaligned structures read from block device
> + * - wrong SB block number. default offset is 8kB
> + * - kmem_cache_alloc() objectes released with kfree()
> + * - inode.i_private released in evict_inode() callback.
> + * - refactored vxfs_readdir() and vxfs_find_entry()
> + *
> + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> + * Example: */
> +// * cksum mnt/usr/share/man/man3.Z/*
> +// * cksum mnt/usr/share/doc/10.20RelNotes
> +// * cksum mnt/usr/local/doom/*
> +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> +// * cksum mnt/usr/share/doc/*
> +// * cksum mnt/usr/sprockets/lib/*
> +// * cksum mnt/usr/sprockets/bin/*
> +/*
> + * Needles to say that checksums of files match these evaluated by
> + * HP-UX B.10.20 cksum. E.g.:
> + * 3457951056 4196020 /usr/local/doom/doom1.wad
> + * 2527157998 35344 /usr/local/doom/doomlaunch
> + * 2974998129 413696 /usr/local/doom/hpdoom
> + *
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -76,6 +104,15 @@ dir_blocks(struct inode *ip)
> }
>
> /*
> + * VXFS_dirblk_ovh is the overhead of a specific dirblock.
> + */
> +static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp)
> +{
> + return (sizeof(short) * be16_to_cpu(dbp->d_nhash)) + 4;
> +}
> +
> +
> +/*
> * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
> *
> * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
> @@ -83,19 +120,13 @@ dir_blocks(struct inode *ip)
> static inline int
> vxfs_match(int len, const char * const name, struct vxfs_direct *de)
> {
> - if (len != de->d_namelen)
> + if (len != be16_to_cpu(de->d_namelen))
> return 0;
> if (!de->d_ino)
> return 0;
> return !memcmp(name, de->d_name, len);
> }
>
> -static inline struct vxfs_direct *
> -vxfs_next_entry(struct vxfs_direct *de)
> -{
> - return ((struct vxfs_direct *)((char*)de + de->d_reclen));
> -}
> -
> /**
> * vxfs_find_entry - find a mathing directory entry for a dentry
> * @ip: directory inode
> @@ -113,50 +144,73 @@ vxfs_next_entry(struct vxfs_direct *de)
> static struct vxfs_direct *
> vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
> {
> - u_long npages, page, nblocks, pblocks, block;
> - u_long bsize = ip->i_sb->s_blocksize;
> - const char *name = dp->d_name.name;
> - int namelen = dp->d_name.len;
> -
> - npages = dir_pages(ip);
> - nblocks = dir_blocks(ip);
> - pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
> -
> - for (page = 0; page < npages; page++) {
> - caddr_t kaddr;
> - struct page *pp;
> -
> - pp = vxfs_get_page(ip->i_mapping, page);
> - if (IS_ERR(pp))
> - continue;
> - kaddr = (caddr_t)page_address(pp);
> -
> - for (block = 0; block <= nblocks && block <= pblocks; block++) {
> - caddr_t baddr, limit;
> - struct vxfs_dirblk *dbp;
> - struct vxfs_direct *de;
> -
> - baddr = kaddr + (block * bsize);
> - limit = baddr + bsize - VXFS_DIRLEN(1);
> -
> - dbp = (struct vxfs_dirblk *)baddr;
> - de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
> -
> - for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
> - if (!de->d_reclen)
> - break;
> - if (!de->d_ino)
> - continue;
> - if (vxfs_match(namelen, name, de)) {
> - *ppp = pp;
> - return (de);
> - }
> + u_long bsize = ip->i_sb->s_blocksize;
> + const char *name = dp->d_name.name;
> + int namelen = dp->d_name.len;
> + loff_t limit = VXFS_DIRROUND(ip->i_size);
> + struct vxfs_direct *de_exit = NULL;
> + loff_t pos = 0;
> +
> +
> + F_ENTER_V2("\"%s\" %d", name, namelen);
> +
> + while (pos < limit) {
> + struct page *pp;
> + char *kaddr;
> + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> +
> + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> + if (IS_ERR(pp)) {
> + return NULL;
> + }
> + kaddr = (char *)page_address(pp);
> +
> +#ifdef DIAGNOSTIC_V2
> + printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
> +#endif
> + while (pg_ofs < PAGE_SIZE && pos < limit) {
> + struct vxfs_direct *de;
> +
> + if ((pos & (bsize - 1)) < 4) {
> + struct vxfs_dirblk *dbp =
White space here too
> + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
> + pos += VXFS_dirblk_ovh(dbp);
> + pg_ofs += VXFS_dirblk_ovh(dbp);
> + }
> + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> +
> +#ifdef DIAGNOSTIC_V2
> + printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
> + de, pg_ofs,
> + de->d_name, be16_to_cpu(de->d_namelen),
> + be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
> +#endif
> + if (!de->d_reclen) {
> + pos += bsize - 1;
> + pos &= ~(bsize - 1);
> + break;
> + }
> +
> + pg_ofs += be16_to_cpu(de->d_reclen);
> + pos += be16_to_cpu(de->d_reclen);
> + if (!de->d_ino) {
> + continue;
> + }
> +
> + if (vxfs_match(namelen, name, de)) {
> + *ppp = pp;
> + de_exit= de; //return (de);
> + break;
> }
> }
> - vxfs_put_page(pp);
> + if (!de_exit)
> + vxfs_put_page(pp);
> + else
> + break;
> }
>
> - return NULL;
> + F_EXIT_V2("\"%s\": %p", name, de_exit);
> + return de_exit;
> }
>
> /**
> @@ -180,11 +234,10 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
>
> de = vxfs_find_entry(dip, dp, &pp);
> if (de) {
> - ino = de->d_ino;
> - kunmap(pp);
> - page_cache_release(pp);
> + ino = be32_to_cpu(de->d_ino);
> + vxfs_put_page(pp);
> }
> -
> +
> return (ino);
> }
>
> @@ -207,17 +260,17 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
> {
> struct inode *ip = NULL;
> ino_t ino;
> -
> +
> if (dp->d_name.len > VXFS_NAMELEN)
> return ERR_PTR(-ENAMETOOLONG);
> -
> +
> ino = vxfs_inode_by_name(dip, dp);
> if (ino) {
> ip = vxfs_iget(dip->i_sb, ino);
> if (IS_ERR(ip))
> return ERR_CAST(ip);
> + d_add(dp, ip);
> }
> - d_add(dp, ip);
> return NULL;
> }
>
> @@ -234,80 +287,95 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
> * Returns:
> * Zero.
> */
> +
> static int
> vxfs_readdir(struct file *fp, struct dir_context *ctx)
> {
> struct inode *ip = file_inode(fp);
> struct super_block *sbp = ip->i_sb;
> u_long bsize = sbp->s_blocksize;
> - u_long page, npages, block, pblocks, nblocks, offset;
> - loff_t pos;
> + loff_t pos, limit;
> +
> + F_ENTER_V3("pos %ld, ino %ld, size %ld", (long)ctx->pos, ip->i_ino, (long)ip->i_size);
>
> if (ctx->pos == 0) {
> if (!dir_emit_dot(fp, ctx))
> - return 0;
> - ctx->pos = 1;
> + goto out;
> + ctx->pos++;
> }
> if (ctx->pos == 1) {
> if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
> - return 0;
> - ctx->pos = 2;
> + goto out;
> + ctx->pos++;
> }
> - pos = ctx->pos - 2;
> -
> - if (pos > VXFS_DIRROUND(ip->i_size))
> - return 0;
>
> - npages = dir_pages(ip);
> - nblocks = dir_blocks(ip);
> - pblocks = VXFS_BLOCK_PER_PAGE(sbp);
> + limit = VXFS_DIRROUND(ip->i_size);
> + if (ctx->pos > limit) {
> +// ctx->pos = 0;
> + goto out;
> + }
>
> - page = pos >> PAGE_CACHE_SHIFT;
> - offset = pos & ~PAGE_CACHE_MASK;
> - block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
> + pos = ctx->pos & ~3L;
>
> - for (; page < npages; page++, block = 0) {
> - char *kaddr;
> - struct page *pp;
> + while (pos < limit) {
> + struct page *pp;
> + char *kaddr;
> + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> + int rc = 0;
>
> - pp = vxfs_get_page(ip->i_mapping, page);
> - if (IS_ERR(pp))
> - continue;
> + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> + if (IS_ERR(pp)) {
> + return -ENOMEM;
> + }
> kaddr = (char *)page_address(pp);
>
> - for (; block <= nblocks && block <= pblocks; block++) {
> - char *baddr, *limit;
> - struct vxfs_dirblk *dbp;
> - struct vxfs_direct *de;
> -
> - baddr = kaddr + (block * bsize);
> - limit = baddr + bsize - VXFS_DIRLEN(1);
> -
> - dbp = (struct vxfs_dirblk *)baddr;
> - de = (struct vxfs_direct *)
> - (offset ?
> - (kaddr + offset) :
> - (baddr + VXFS_DIRBLKOV(dbp)));
> -
> - for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
> - if (!de->d_reclen)
> - break;
> - if (!de->d_ino)
> - continue;
> -
> - offset = (char *)de - kaddr;
> - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> - if (!dir_emit(ctx, de->d_name, de->d_namelen,
> - de->d_ino, DT_UNKNOWN)) {
> - vxfs_put_page(pp);
> - return 0;
> - }
> +#ifdef DIAGNOSTIC_V3
> + printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
> +#endif
> + while (pg_ofs < PAGE_SIZE && pos < limit) {
> + struct vxfs_direct *de;
> +
> + if ((pos & (bsize - 1)) < 4) {
> + struct vxfs_dirblk *dbp =
White space
> + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
> + pos += VXFS_dirblk_ovh(dbp);
> + pg_ofs += VXFS_dirblk_ovh(dbp);
> + }
> + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> +
> +#ifdef DIAGNOSTIC_V3
> + printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
> + de, pg_ofs,
> + de->d_name, be16_to_cpu(de->d_namelen),
> + be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
> +#endif
> + if (!de->d_reclen) {
> + pos += bsize - 1;
> + pos &= ~(bsize - 1);
> + break;
> + }
> +
> + pg_ofs += be16_to_cpu(de->d_reclen);
> + pos += be16_to_cpu(de->d_reclen);
> + if (!de->d_ino) {
> + continue;
> + }
> +
> + if (! (rc = dir_emit(ctx, de->d_name, be16_to_cpu(de->d_namelen),
> + be32_to_cpu(de->d_ino), DT_UNKNOWN))) {
> + // the dir entry was not submitted, so fix pos.
> + pos -= be16_to_cpu(de->d_reclen);
White space
> + break;
> }
> - offset = 0;
> }
> vxfs_put_page(pp);
> - offset = 0;
> + if (!rc)
> + break;
> }
> - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> +
> + ctx->pos = pos | 2;
> +
> +out:
> + F_EXIT_V3("pos %ld", (long)ctx->pos);
> return 0;
> }
> diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
> index 0495008..19a1cab 100644
> --- a/fs/freevxfs/vxfs_olt.c
> +++ b/fs/freevxfs/vxfs_olt.c
> @@ -2,6 +2,10 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * 2016 Krzysztof Blaszkowski.
> + * Many bug fixes, improvements & tests
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -43,14 +47,14 @@ static inline void
> vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
> {
> BUG_ON(infp->vsi_fshino);
> - infp->vsi_fshino = fshp->olt_fsino[0];
> + infp->vsi_fshino = be32_to_cpu(fshp->olt_fsino[0]);
> }
>
> static inline void
> vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
> {
> BUG_ON(infp->vsi_iext);
> - infp->vsi_iext = ilistp->olt_iext[0];
> + infp->vsi_iext = be32_to_cpu(ilistp->olt_iext[0]);
White space in these lines
> }
>
> static inline u_long
> @@ -80,6 +84,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> struct buffer_head *bp;
> struct vxfs_olt *op;
> char *oaddr, *eaddr;
> + u32 j;
>
>
> bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
> @@ -87,8 +92,8 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> goto fail;
>
> op = (struct vxfs_olt *)bp->b_data;
> - if (op->olt_magic != VXFS_OLT_MAGIC) {
> - printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
> + if ((j = be32_to_cpu(op->olt_magic)) != VXFS_OLT_MAGIC) {
> + printk(KERN_NOTICE "vxfs: ivalid olt magic number %08x at +%d\n", j, infp->vsi_oltext);
> goto fail;
> }
>
> @@ -97,19 +102,24 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> * I've not seen any such filesystem yet and I'm lazy.. --hch
> */
> if (infp->vsi_oltsize > 1) {
> - printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
> + printk(KERN_NOTICE "vxfs: oltsize > 1 detected (%d).\n", infp->vsi_oltsize);
> printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
> goto fail;
> }
>
> - oaddr = bp->b_data + op->olt_size;
> + oaddr = bp->b_data + be32_to_cpu(op->olt_size);
> eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
>
> while (oaddr < eaddr) {
> - struct vxfs_oltcommon *ocp =
> + struct vxfs_oltcommon *ocp =
> (struct vxfs_oltcommon *)oaddr;
> -
> - switch (ocp->olt_type) {
> +
> +#ifdef DIAGNOSTIC
> + printk(KERN_DEBUG "oltc_type %d, sz %d at +%d\n",
White space
> + be32_to_cpu(ocp->olt_type), be32_to_cpu(ocp->olt_size), (int)(oaddr - bp->b_data));
> +#endif
> +
> + switch (be32_to_cpu(ocp->olt_type)) {
> case VXFS_OLT_FSHEAD:
> vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
> break;
> @@ -118,11 +128,16 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> break;
> }
>
> - oaddr += ocp->olt_size;
> + oaddr += be32_to_cpu(ocp->olt_size);
> }
>
> +#ifdef DIAGNOSTIC
> + printk(KERN_DEBUG "olt_size %d, vsi_fshino %d, vsi_iext %ld\n",
> + be32_to_cpu(op->olt_size), (u32)infp->vsi_fshino, infp->vsi_iext);
> +#endif
> +
> brelse(bp);
> - return 0;
> + return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
>
> fail:
> brelse(bp);
> diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> index 7ca8c75..9fbf271 100644
> --- a/fs/freevxfs/vxfs_super.c
> +++ b/fs/freevxfs/vxfs_super.c
> @@ -2,6 +2,38 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + * (c) 2016 Krzysztof Blaszkowski.
> + * Many bug fixes, improvements & tests.
> + *
> + * These bugs and improvements were as follows:
> + * - code not aware of cpu endianess and ondisk data is BE.
> + * - misaligned structures read from block device
> + * - wrong SB block number. default offset is 8kB
> + * - kmem_cache_alloc() objectes released with kfree()
> + * - inode.i_private released in evict_inode() callback.
> + * - refactored vxfs_readdir() and vxfs_find_entry()
> + *
> + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> + * Example: */
> +// * cksum mnt/usr/share/man/man3.Z/*
> +// * cksum mnt/usr/share/doc/10.20RelNotes
White space
> +// * cksum mnt/usr/local/doom/*
> +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> +// * cksum mnt/usr/share/doc/*
> +// * cksum mnt/usr/sprockets/lib/*
> +// * cksum mnt/usr/sprockets/bin/*
> +/*
> + * Needles to say that checksums of files match these evaluated by
> + * HP-UX B.10.20 cksum. E.g.:
> + * 3457951056 4196020 /usr/local/doom/doom1.wad
> + * 2527157998 35344 /usr/local/doom/doomlaunch
> + * 2974998129 413696 /usr/local/doom/hpdoom
> + *
> + * The hpux_mdsetup tool project which is aimed at making possible
> + * accessing HP-UX logical volumes by device mapper is here:
> + * https://sourceforge.net/projects/linux-vxfs/
> + *
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -41,6 +73,7 @@
> #include <linux/stat.h>
> #include <linux/vfs.h>
> #include <linux/mount.h>
> +#include <linux/byteorder/generic.h>
>
> #include "vxfs.h"
> #include "vxfs_extern.h"
> @@ -48,7 +81,7 @@
> #include "vxfs_inode.h"
>
>
> -MODULE_AUTHOR("Christoph Hellwig");
> +MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
> MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
> MODULE_LICENSE("Dual BSD/GPL");
>
> @@ -59,6 +92,7 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *);
> static int vxfs_remount(struct super_block *, int *, char *);
>
> static const struct super_operations vxfs_super_ops = {
> + .destroy_inode = vxfs_destroy_inode,
> .evict_inode = vxfs_evict_inode,
> .put_super = vxfs_put_super,
> .statfs = vxfs_statfs,
> @@ -153,6 +187,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> u_long bsize;
> struct inode *root;
> int ret = -EINVAL;
> + int j;
>
> sbp->s_flags |= MS_RDONLY;
>
> @@ -168,7 +203,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> goto out;
> }
>
> - bp = sb_bread(sbp, 1);
> + bp = sb_bread(sbp, 8);
> if (!bp || !buffer_mapped(bp)) {
> if (!silent) {
> printk(KERN_WARNING
> @@ -178,32 +213,30 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> }
>
> rsbp = (struct vxfs_sb *)bp->b_data;
> - if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
> + if (be32_to_cpu(rsbp->vs_magic) != VXFS_SUPER_MAGIC) {
> if (!silent)
> - printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
> + printk(KERN_NOTICE "vxfs: WRONG superblock magic %08x\n", rsbp->vs_magic);
> goto out;
> }
>
> - if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
> - printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
> - rsbp->vs_version);
> + j = be32_to_cpu(rsbp->vs_version);
> + if ((j < 2 || j > 4) && !silent) {
> + printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
> goto out;
> }
>
> -#ifdef DIAGNOSTIC
> - printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
> - printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
> -#endif
>
> - sbp->s_magic = rsbp->vs_magic;
> + sbp->s_magic = be32_to_cpu(rsbp->vs_magic);
> sbp->s_fs_info = infp;
>
> infp->vsi_raw = rsbp;
> infp->vsi_bp = bp;
> - infp->vsi_oltext = rsbp->vs_oltext[0];
> - infp->vsi_oltsize = rsbp->vs_oltsize;
> + infp->vsi_oltext = be32_to_cpu(rsbp->vs_oltext[0]);
> + infp->vsi_oltsize = be32_to_cpu(rsbp->vs_oltsize);
> +
> + printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", be32_to_cpu(rsbp->vs_version));
>
> - if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
> + if (!sb_set_blocksize(sbp, be32_to_cpu(rsbp->vs_bsize))) {
> printk(KERN_WARNING "vxfs: unable to set final block size\n");
> goto out;
> }
> @@ -229,6 +262,8 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
> goto out_free_ilist;
> }
> + printk(KERN_DEBUG "vxfs: blocksize: %d, oltext %d, oltsize %d\n",
White space
> + be32_to_cpu(rsbp->vs_bsize), infp->vsi_oltext, infp->vsi_oltsize);
>
> return 0;
>
> @@ -237,6 +272,7 @@ out_free_ilist:
> vxfs_put_fake_inode(infp->vsi_ilist);
> vxfs_put_fake_inode(infp->vsi_stilist);
> out:
> + printk(KERN_ERR "vxfs: mount failed %d\n", ret);
> brelse(bp);
> kfree(infp);
> return ret;
> @@ -264,29 +300,22 @@ MODULE_ALIAS("vxfs");
> static int __init
> vxfs_init(void)
> {
> - int rv;
> + int rc = vxfs_inode_info_cache(0);
>
> - vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> - sizeof(struct vxfs_inode_info), 0,
> - SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> - if (!vxfs_inode_cachep)
> - return -ENOMEM;
> - rv = register_filesystem(&vxfs_fs_type);
> - if (rv < 0)
> - kmem_cache_destroy(vxfs_inode_cachep);
> - return rv;
> + if (!rc) {
> + rc = register_filesystem(&vxfs_fs_type);
> + if (rc < 0)
> + vxfs_inode_info_cache(1);
> + }
> + printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __FUNCTION__, __DATE__, __TIME__, rc);
> + return rc;
> }
>
> static void __exit
> vxfs_cleanup(void)
> {
> unregister_filesystem(&vxfs_fs_type);
> - /*
> - * Make sure all delayed rcu free inodes are flushed before we
> - * destroy cache.
> - */
> - rcu_barrier();
> - kmem_cache_destroy(vxfs_inode_cachep);
> + vxfs_inode_info_cache(1);
> }
>
> module_init(vxfs_init);
--
Carlos
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: freevxfs
2016-05-22 15:13 freevxfs Krzysztof Błaszkowski
2016-05-23 8:23 ` freevxfs Carlos Maiolino
@ 2016-05-23 8:36 ` Christoph Hellwig
2016-05-24 8:48 ` freevxfs Krzysztof Błaszkowski
1 sibling, 1 reply; 8+ messages in thread
From: Christoph Hellwig @ 2016-05-23 8:36 UTC (permalink / raw)
To: Krzysztof B??aszkowski; +Cc: linux-fsdevel, hch
Hi Krzysztof,
thanks for doing this work. I did the vxfs work for SCO Unixware
file systems and never even looked at a HP-UX system. Good to know that
it's useful for HP-UX as well with a few changes.
I'd love to merged it, but we should go through it a bit and make it
fit our normal kernel process and style. I'm happy to help you on the
list or in personal mails with that.
Initial comments below:
> index c8a9265..9890a84 100644
> --- a/fs/freevxfs/vxfs.h
> +++ b/fs/freevxfs/vxfs.h
> @@ -2,6 +2,39 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski.
Just add your copyrights on the top next to mine.
> + * Many bug fixes, improvements & tests.
> + *
> + * These bugs and improvements were as follows:
> + * - code not aware of cpu endianess and ondisk data is BE.
> + * - misaligned structures read from block device
> + * - wrong SB block number. default offset is 8kB
> + * - kmem_cache_alloc() objectes released with kfree()
> + * - inode.i_private released in evict_inode() callback.
> + * - refactored vxfs_readdir() and vxfs_find_entry()
> + *
> + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> + * Example: */
> +// * cksum mnt/usr/share/man/man3.Z/*
> +// * cksum mnt/usr/share/doc/10.20RelNotes
> +// * cksum mnt/usr/local/doom/*
> +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> +// * cksum mnt/usr/share/doc/*
> +// * cksum mnt/usr/sprockets/lib/*
> +// * cksum mnt/usr/sprockets/bin/*
> +/*
> + * Needles to say that checksums of files match these evaluated by
> + * HP-UX B.10.20 cksum. E.g.:
> + * 3457951056 4196020 /usr/local/doom/doom1.wad
> + * 2527157998 35344 /usr/local/doom/doomlaunch
> + * 2974998129 413696 /usr/local/doom/hpdoom
This just belongs into the git commit log and not into the file.
> + * The hpux_mdsetup tool project which is aimed at making possible
> + * accessing HP-UX logical volumes by device mapper is here:
> + * https://sourceforge.net/projects/linux-vxfs/
> + *
I think this should just go into the Kconfig help text, or a
documentation text file if we want to add one.
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -38,6 +71,10 @@
> */
> #include <linux/types.h>
>
> +//#define DIAGNOSTIC
> +#undef DIAGNOSTIC
> +#undef DIAGNOSTIC_V2
> +#undef DIAGNOSTIC_V3
>
> /*
> * Data types for use with the VxFS ondisk format.
> @@ -152,7 +189,7 @@ struct vxfs_sb {
> /*
> * Actually much more...
> */
> -};
> +} __attribute__((packed));
Can you explain why we need the packed annoation? It should probably
be a patch on it's own and use __packed.
> +#ifdef DIAGNOSTIC
> +#define F_ENTER(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#define F_EXIT(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +
> +#ifdef DIAGNOSTIC_V2
> +#define F_ENTER_V2(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#define F_EXIT_V2(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#else
> +#define F_ENTER_V2(a, b...)
> +#define F_EXIT_V2(a, b...)
> +#endif
> +
> +#ifdef DIAGNOSTIC_V3
> +#define F_ENTER_V3(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#define F_EXIT_V3(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> +#else
> +#define F_ENTER_V3(a, b...)
> +#define F_EXIT_V3(a, b...)
> +#endif
Have you looked into ftrace for function tracing? I'd prefer not to
add all these macros if we can avoid it.
> for (i = 0; i < VXFS_NDADDR; i++) {
> - struct direct *d = vip->vii_ext4.ve4_direct + i;
> - if (bn >= 0 && bn < d->size)
> - return (bn + d->extent);
> + struct direct *d = vip->vii_ext4.ve4_direct + i; // cpu endian
no // comments for Linux kernel code please. Also we should not need
comments about endianess. Instead we should use sparse annotations
(see Documentation/sparse.txt for details). We also have a few examples
for code that supports both little and big endian in a single driver
that way - take a look at the end of fs/sysv/sysv.h for an example.
> - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
> + bno = be32_to_cpu(indir[(bn/indsize) % (indsize*bn)]) + (bn%indsize);
This would break the existing Unixware support - we'll need helpers like
the one I just mentioned above instead.
> @@ -340,21 +436,61 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
> static void vxfs_i_callback(struct rcu_head *head)
> {
> struct inode *inode = container_of(head, struct inode, i_rcu);
> - kmem_cache_free(vxfs_inode_cachep, inode->i_private);
> + void *priv = inode->i_private;
> +
> + inode->i_private = NULL;
> + // just in case the same inode was used elsewhere after releasing i_private.
> + // if it was then dereferencing NULL is far better than using invalid
> + // pointer to memory claimed by something.
> + kmem_cache_free(vxfs_inode_cachep, priv);
> +}
> +
> +void vxfs_destroy_inode(struct inode *ip)
> +{
> + call_rcu(&ip->i_rcu, vxfs_i_callback);
> +}
> +
> +void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> +{
> + kmem_cache_free(vxfs_inode_cachep, vip);
> }
Can you explain these changes? Being able to explain each change in
the changelog is one of the reasons why we prefer multiple small
changes, one for each issue.
> +{
> + int rc = 0;
> +
> + if (!setup) {
> + vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> + sizeof(struct vxfs_inode_info), 0,
> + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> +
> + if (!vxfs_inode_cachep)
> + rc = -ENOMEM;
> + } else {
> + /*
> + * Make sure all delayed rcu free inodes are flushed before we
> + * destroy cache.
> + */
> + rcu_barrier();
> + kmem_cache_destroy(vxfs_inode_cachep);
> + }
> +
> + return rc;
> +}
I don't think a function that does two different things depending on the
argument is a good idea. I suspect you added it to keep
vxfs_inode_cachep static in this file? I'm fine with that in general,
but please add two function for it then, and split it into a separate
patch.
> #include <linux/stat.h>
> #include <linux/vfs.h>
> #include <linux/mount.h>
> +#include <linux/byteorder/generic.h>
Please use <asm/byteorder.h> instead.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: freevxfs
2016-05-23 8:36 ` freevxfs Christoph Hellwig
@ 2016-05-24 8:48 ` Krzysztof Błaszkowski
0 siblings, 0 replies; 8+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-24 8:48 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-fsdevel
Hi Christoph,
Thank you for prompt response. Yes, please tell me what I should do to
complete this successfully. In the mean time I will look through the
rest of your reply.
I couldn't do this yesterday (drove 500km away from city I live in).
And my 1st thought of vxfs_fill_super() is that it should check sb magic
at two places +1k in case of SCO Unixware and +8k for HP-UX vxfs image
to preserve compatibility.
Also what is on-disk format of data written by SCO ? HP-UX 10.20 writes
everything big endian. (guess it's native to pa-risc 1.1)
The information can be utilized later to fine tune more corner case
issues with these two images of vxfs. e.g. for vxfs_bmap_ext4()
Best regards
On Mon, 2016-05-23 at 01:36 -0700, Christoph Hellwig wrote:
> Hi Krzysztof,
>
> thanks for doing this work. I did the vxfs work for SCO Unixware
> file systems and never even looked at a HP-UX system. Good to know that
> it's useful for HP-UX as well with a few changes.
>
> I'd love to merged it, but we should go through it a bit and make it
> fit our normal kernel process and style. I'm happy to help you on the
> list or in personal mails with that.
>
> Initial comments below:
>
> > index c8a9265..9890a84 100644
> > --- a/fs/freevxfs/vxfs.h
> > +++ b/fs/freevxfs/vxfs.h
> > @@ -2,6 +2,39 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski.
>
> Just add your copyrights on the top next to mine.
>
> > + * Many bug fixes, improvements & tests.
> > + *
> > + * These bugs and improvements were as follows:
> > + * - code not aware of cpu endianess and ondisk data is BE.
> > + * - misaligned structures read from block device
> > + * - wrong SB block number. default offset is 8kB
> > + * - kmem_cache_alloc() objectes released with kfree()
> > + * - inode.i_private released in evict_inode() callback.
> > + * - refactored vxfs_readdir() and vxfs_find_entry()
> > + *
> > + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> > + * Example: */
> > +// * cksum mnt/usr/share/man/man3.Z/*
> > +// * cksum mnt/usr/share/doc/10.20RelNotes
> > +// * cksum mnt/usr/local/doom/*
> > +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> > +// * cksum mnt/usr/share/doc/*
> > +// * cksum mnt/usr/sprockets/lib/*
> > +// * cksum mnt/usr/sprockets/bin/*
> > +/*
> > + * Needles to say that checksums of files match these evaluated by
> > + * HP-UX B.10.20 cksum. E.g.:
> > + * 3457951056 4196020 /usr/local/doom/doom1.wad
> > + * 2527157998 35344 /usr/local/doom/doomlaunch
> > + * 2974998129 413696 /usr/local/doom/hpdoom
>
> This just belongs into the git commit log and not into the file.
>
>
> > + * The hpux_mdsetup tool project which is aimed at making possible
> > + * accessing HP-UX logical volumes by device mapper is here:
> > + * https://sourceforge.net/projects/linux-vxfs/
> > + *
>
> I think this should just go into the Kconfig help text, or a
> documentation text file if we want to add one.
>
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -38,6 +71,10 @@
> > */
> > #include <linux/types.h>
> >
> > +//#define DIAGNOSTIC
> > +#undef DIAGNOSTIC
> > +#undef DIAGNOSTIC_V2
> > +#undef DIAGNOSTIC_V3
> >
> > /*
> > * Data types for use with the VxFS ondisk format.
> > @@ -152,7 +189,7 @@ struct vxfs_sb {
> > /*
> > * Actually much more...
> > */
> > -};
> > +} __attribute__((packed));
>
> Can you explain why we need the packed annoation? It should probably
> be a patch on it's own and use __packed.
>
> > +#ifdef DIAGNOSTIC
> > +#define F_ENTER(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#define F_EXIT(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +
> > +#ifdef DIAGNOSTIC_V2
> > +#define F_ENTER_V2(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#define F_EXIT_V2(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#else
> > +#define F_ENTER_V2(a, b...)
> > +#define F_EXIT_V2(a, b...)
> > +#endif
> > +
> > +#ifdef DIAGNOSTIC_V3
> > +#define F_ENTER_V3(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#define F_EXIT_V3(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#else
> > +#define F_ENTER_V3(a, b...)
> > +#define F_EXIT_V3(a, b...)
> > +#endif
>
> Have you looked into ftrace for function tracing? I'd prefer not to
> add all these macros if we can avoid it.
>
> > for (i = 0; i < VXFS_NDADDR; i++) {
> > - struct direct *d = vip->vii_ext4.ve4_direct + i;
> > - if (bn >= 0 && bn < d->size)
> > - return (bn + d->extent);
> > + struct direct *d = vip->vii_ext4.ve4_direct + i; // cpu endian
>
> no // comments for Linux kernel code please. Also we should not need
> comments about endianess. Instead we should use sparse annotations
> (see Documentation/sparse.txt for details). We also have a few examples
> for code that supports both little and big endian in a single driver
> that way - take a look at the end of fs/sysv/sysv.h for an example.
>
> > - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
> > + bno = be32_to_cpu(indir[(bn/indsize) % (indsize*bn)]) + (bn%indsize);
>
> This would break the existing Unixware support - we'll need helpers like
> the one I just mentioned above instead.
>
> > @@ -340,21 +436,61 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
> > static void vxfs_i_callback(struct rcu_head *head)
> > {
> > struct inode *inode = container_of(head, struct inode, i_rcu);
> > - kmem_cache_free(vxfs_inode_cachep, inode->i_private);
> > + void *priv = inode->i_private;
> > +
> > + inode->i_private = NULL;
> > + // just in case the same inode was used elsewhere after releasing i_private.
> > + // if it was then dereferencing NULL is far better than using invalid
> > + // pointer to memory claimed by something.
> > + kmem_cache_free(vxfs_inode_cachep, priv);
> > +}
> > +
> > +void vxfs_destroy_inode(struct inode *ip)
> > +{
> > + call_rcu(&ip->i_rcu, vxfs_i_callback);
> > +}
> > +
> > +void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> > +{
> > + kmem_cache_free(vxfs_inode_cachep, vip);
> > }
>
> Can you explain these changes? Being able to explain each change in
> the changelog is one of the reasons why we prefer multiple small
> changes, one for each issue.
>
> > +{
> > + int rc = 0;
> > +
> > + if (!setup) {
> > + vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> > + sizeof(struct vxfs_inode_info), 0,
> > + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> > +
> > + if (!vxfs_inode_cachep)
> > + rc = -ENOMEM;
> > + } else {
> > + /*
> > + * Make sure all delayed rcu free inodes are flushed before we
> > + * destroy cache.
> > + */
> > + rcu_barrier();
> > + kmem_cache_destroy(vxfs_inode_cachep);
> > + }
> > +
> > + return rc;
> > +}
>
> I don't think a function that does two different things depending on the
> argument is a good idea. I suspect you added it to keep
> vxfs_inode_cachep static in this file? I'm fine with that in general,
> but please add two function for it then, and split it into a separate
> patch.
>
> > #include <linux/stat.h>
> > #include <linux/vfs.h>
> > #include <linux/mount.h>
> > +#include <linux/byteorder/generic.h>
>
> Please use <asm/byteorder.h> instead.
--
Krzysztof Blaszkowski
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: freevxfs
2016-05-23 8:23 ` freevxfs Carlos Maiolino
@ 2016-05-24 11:50 ` Krzysztof Błaszkowski
0 siblings, 0 replies; 8+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-24 11:50 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-fsdevel
Hi,
Yes, I think I can do this.
Sure, will use the script.
I reckon that this process will take more time than I expect because of
preserving functionality of SCO.
On Mon, 2016-05-23 at 10:23 +0200, Carlos Maiolino wrote:
> On Sun, May 22, 2016 at 05:13:14PM +0200, Krzysztof Błaszkowski wrote:
> > Hello All,
> >
> > I recently gave a try to vxfs (veritas fs) which is common to HP-UX and
> > it turned out that the module has been broken for very long time.
> >
> > I fixed several issues with current freevxfs and also designed a
> > userspace tool which helps creating dm block devices from e.g. regular
> > file with raw image of hp-ux disk.
> > https://sourceforge.net/projects/linux-vxfs/
> >
> >
> > I send the patch because I believe that some people would appreciate
> > support for this vintage file system (e.g. me) and also it will be nice
> > to see my name in the kernel.
> >
>
> Hi,
>
> - Can you please split this patch into individual patches fixing each specific
> problem? It's easier to review, instead of a big patch with several fixes into
> it.
>
> - Also, as a quick view, there are a lot of trailing white spaces over the whole
> patch, which, should be removed.
>
> you can use the scripts/checkpatch.pl script to check your patches and see
> match at least the basics requirements for sending patches to kernel and, a
> read of Documentation/SubmittingPatches is interesting too.
>
> > Regards,
> >
> > --
> > Krzysztof Blaszkowski
>
> > diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> > index c8a9265..9890a84 100644
> > --- a/fs/freevxfs/vxfs.h
> > +++ b/fs/freevxfs/vxfs.h
> > @@ -2,6 +2,39 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski.
> > + * Many bug fixes, improvements & tests.
> > + *
> > + * These bugs and improvements were as follows:
> > + * - code not aware of cpu endianess and ondisk data is BE.
> > + * - misaligned structures read from block device
> > + * - wrong SB block number. default offset is 8kB
> > + * - kmem_cache_alloc() objectes released with kfree()
> > + * - inode.i_private released in evict_inode() callback.
> > + * - refactored vxfs_readdir() and vxfs_find_entry()
> > + *
> > + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> > + * Example: */
> > +// * cksum mnt/usr/share/man/man3.Z/*
> > +// * cksum mnt/usr/share/doc/10.20RelNotes
> > +// * cksum mnt/usr/local/doom/*
> > +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> > +// * cksum mnt/usr/share/doc/*
> > +// * cksum mnt/usr/sprockets/lib/*
> > +// * cksum mnt/usr/sprockets/bin/*
> > +/*
>
> Don't use //
>
> > + * Needles to say that checksums of files match these evaluated by
> > + * HP-UX B.10.20 cksum. E.g.:
> > + * 3457951056 4196020 /usr/local/doom/doom1.wad
> > + * 2527157998 35344 /usr/local/doom/doomlaunch
> > + * 2974998129 413696 /usr/local/doom/hpdoom
> > + *
> > + * The hpux_mdsetup tool project which is aimed at making possible
> > + * accessing HP-UX logical volumes by device mapper is here:
> > + * https://sourceforge.net/projects/linux-vxfs/
> > + *
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -38,6 +71,10 @@
> > */
> > #include <linux/types.h>
> >
> > +//#define DIAGNOSTIC
> > +#undef DIAGNOSTIC
> > +#undef DIAGNOSTIC_V2
> > +#undef DIAGNOSTIC_V3
> >
> > /*
> > * Data types for use with the VxFS ondisk format.
> > @@ -152,7 +189,7 @@ struct vxfs_sb {
> > /*
> > * Actually much more...
> > */
> > -};
> > +} __attribute__((packed));
> >
> >
> > /*
> > @@ -260,4 +297,35 @@ enum {
> > #define VXFS_SBI(sbp) \
> > ((struct vxfs_sb_info *)(sbp)->s_fs_info)
> >
> > +
> > +#ifdef DIAGNOSTIC
> > +#define F_ENTER(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#define F_EXIT(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +
> > +#ifdef DIAGNOSTIC_V2
> > +#define F_ENTER_V2(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#define F_EXIT_V2(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#else
> > +#define F_ENTER_V2(a, b...)
> > +#define F_EXIT_V2(a, b...)
> > +#endif
> > +
> > +#ifdef DIAGNOSTIC_V3
> > +#define F_ENTER_V3(fmt, arg...) printk("%s:%d ENTER. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#define F_EXIT_V3(fmt, arg...) printk("%s:%d EXIT. " fmt "\n", __FUNCTION__, __LINE__, ##arg)
> > +#else
> > +#define F_ENTER_V3(a, b...)
> > +#define F_EXIT_V3(a, b...)
> > +#endif
> > +
> > +#else // DIAGNOSTIC
> > +#define F_ENTER(a, b...)
> > +#define F_EXIT(a, b...)
> > +#define F_ENTER_V2(a, b...)
> > +#define F_EXIT_V2(a, b...)
> > +#define F_ENTER_V3(a, b...)
> > +#define F_EXIT_V3(a, b...)
> > +#endif
> > +
>
> Lots of trailing white spaces here
>
> > +
> > #endif /* _VXFS_SUPER_H_ */
> > diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
> > index f86fd3c..58e6a17 100644
> > --- a/fs/freevxfs/vxfs_bmap.c
> > +++ b/fs/freevxfs/vxfs_bmap.c
> > @@ -2,6 +2,10 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * 2016 Krzysztof Blaszkowski.
> > + * Many bug fixes, improvements & tests
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -39,17 +43,6 @@
> > #include "vxfs_extern.h"
> >
> >
> > -#ifdef DIAGNOSTIC
> > -static void
> > -vxfs_typdump(struct vxfs_typed *typ)
> > -{
> > - printk(KERN_DEBUG "type=%Lu ", typ->vt_hdr >> VXFS_TYPED_TYPESHIFT);
> > - printk("offset=%Lx ", typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
> > - printk("block=%x ", typ->vt_block);
> > - printk("size=%x\n", typ->vt_size);
> > -}
> > -#endif
> > -
> > /**
> > * vxfs_bmap_ext4 - do bmap for ext4 extents
> > * @ip: pointer to the inode we do bmap for
> > @@ -71,18 +64,23 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
> > unsigned long bsize = sb->s_blocksize;
> > u32 indsize = vip->vii_ext4.ve4_indsize;
> > int i;
> > + daddr_t rc = 0;
> > +
> > + F_ENTER_V2();
> >
> > if (indsize > sb->s_blocksize)
> > goto fail_size;
> >
> > for (i = 0; i < VXFS_NDADDR; i++) {
> > - struct direct *d = vip->vii_ext4.ve4_direct + i;
> > - if (bn >= 0 && bn < d->size)
> > - return (bn + d->extent);
> > + struct direct *d = vip->vii_ext4.ve4_direct + i; // cpu endian
> > + if (bn >= 0 && bn < d->size) {
> > + rc = bn + d->extent;
> > + break;
> > + }
> > bn -= d->size;
> > }
> >
> > - if ((bn / (indsize * indsize * bsize / 4)) == 0) {
> > + if (!rc && ((bn / (indsize * indsize * bsize / 4)) == 0)) {
> > struct buffer_head *buf;
> > daddr_t bno;
> > u32 *indir;
> > @@ -92,18 +90,21 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
> > goto fail_buf;
> >
> > indir = (u32 *)buf->b_data;
> > - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
> > + bno = be32_to_cpu(indir[(bn/indsize) % (indsize*bn)]) + (bn%indsize);
> >
> > brelse(buf);
> > - return bno;
> > - } else
> > - printk(KERN_WARNING "no matching indir?");
> > + rc = bno;
> > + }
> > + if (!rc)
> > + printk(KERN_WARNING "%s:%d no matching indir?\n", __FUNCTION__, __LINE__);
> >
> > - return 0;
> > + F_EXIT_V2("pblk %d", rc);
> > + return rc;
> >
> > fail_size:
> > printk("vxfs: indirect extent too big!\n");
> > fail_buf:
> > + F_EXIT();
> > return 0;
> > }
> >
> > @@ -129,51 +130,53 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> > {
> > struct buffer_head *bp = NULL;
> > daddr_t pblock = 0;
> > - int i;
> > + int i;
> >
> > + F_ENTER_V2();
> > for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
> > struct vxfs_typed *typ;
> > - int64_t off;
> > + int64_t off;
> >
> > bp = sb_bread(ip->i_sb,
> > indir + (i / VXFS_TYPED_PER_BLOCK(ip->i_sb)));
> > if (!bp || !buffer_mapped(bp))
> > - return 0;
> > + break;
> >
> > typ = ((struct vxfs_typed *)bp->b_data) +
> > (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
> > - off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
> > + off = be64_to_cpu(typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
> >
> > if (block < off) {
> > brelse(bp);
> > continue;
> > }
> >
> > - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
> > + switch ((u_int32_t)(be64_to_cpu(typ->vt_hdr) >> VXFS_TYPED_TYPESHIFT)) {
> > case VXFS_TYPED_INDIRECT:
> > - pblock = vxfs_bmap_indir(ip, typ->vt_block,
> > - typ->vt_size, block - off);
> > + pblock = vxfs_bmap_indir(ip, be32_to_cpu(typ->vt_block),
> > + be32_to_cpu(typ->vt_size), block - off);
> > if (pblock == -2)
> > break;
> > goto out;
> > case VXFS_TYPED_DATA:
> > - if ((block - off) >= typ->vt_size)
> > + if ((block - off) >= be32_to_cpu(typ->vt_size))
> > break;
> > - pblock = (typ->vt_block + block - off);
> > + pblock = be32_to_cpu(typ->vt_block) + block - off;
> > goto out;
> > case VXFS_TYPED_INDIRECT_DEV4:
> > case VXFS_TYPED_DATA_DEV4: {
> > struct vxfs_typed_dev4 *typ4 =
> > (struct vxfs_typed_dev4 *)typ;
> >
> > - printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
> > - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
> > - (unsigned long long) typ4->vd4_block,
> > - (unsigned long long) typ4->vd4_size,
> > - typ4->vd4_dev);
> > + printk(KERN_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
> > + __FUNCTION__, __LINE__,
> > + (unsigned long long) be64_to_cpu(typ4->vd4_block),
> > + (unsigned long long) be64_to_cpu(typ4->vd4_size),
> > + be32_to_cpu(typ4->vd4_dev));
> > goto fail;
> > }
> > default:
> > + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, be64_to_cpu(typ->vt_hdr));
> > BUG();
> > }
> > brelse(bp);
> > @@ -182,7 +185,9 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> > fail:
> > pblock = 0;
> > out:
> > - brelse(bp);
> > + if (bp)
> > + brelse(bp);
> > + F_EXIT_V2();
> > return (pblock);
> > }
> >
> > @@ -200,16 +205,18 @@ out:
> > static daddr_t
> > vxfs_bmap_typed(struct inode *ip, long iblock)
> > {
> > - struct vxfs_inode_info *vip = VXFS_INO(ip);
> > - daddr_t pblock = 0;
> > - int i;
> > + struct vxfs_inode_info *vip = VXFS_INO(ip);
> > + daddr_t pblock = 0;
> > + int i;
> >
> > + F_ENTER_V2();
> > for (i = 0; i < VXFS_NTYPED; i++) {
> > - struct vxfs_typed *typ = vip->vii_org.typed + i;
> > + struct vxfs_typed *typ = vip->vii_org.typed + i; // cpu endian
> > int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
> >
> > -#ifdef DIAGNOSTIC
> > - vxfs_typdump(typ);
> > +#ifdef DIAGNOSTIC_V2
> > + printk(KERN_DEBUG "%s:%d type=%Lu, ofs=0x%Lx, blk=%d, size=%d\n", __FUNCTION__, __LINE__,
> > + typ->vt_hdr >> VXFS_TYPED_TYPESHIFT, off, typ->vt_block, typ->vt_size );
> > #endif
> > if (iblock < off)
> > continue;
> > @@ -219,29 +226,36 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
> > typ->vt_size, iblock - off);
> > if (pblock == -2)
> > break;
> > - return (pblock);
> > + goto out;
> > +
> > case VXFS_TYPED_DATA:
> > - if ((iblock - off) < typ->vt_size)
> > - return (typ->vt_block + iblock - off);
> > + if ((iblock - off) < typ->vt_size) {
> > + pblock = typ->vt_block + iblock - off;
> > + goto out;
> > + }
> > break;
> > case VXFS_TYPED_INDIRECT_DEV4:
> > case VXFS_TYPED_DATA_DEV4: {
> > struct vxfs_typed_dev4 *typ4 =
> > (struct vxfs_typed_dev4 *)typ;
> >
> > - printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
> > - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
> > + printk(KERN_ERR "%s:%d TYPED_DEV4 detected!. block: %Lu\tsize: %Ld\tdev: %d\n",
> > + __FUNCTION__, __LINE__,
> > (unsigned long long) typ4->vd4_block,
> > (unsigned long long) typ4->vd4_size,
> > typ4->vd4_dev);
> > - return 0;
> > + pblock = 0;
> > + goto out;
> > }
> > default:
> > + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __FUNCTION__, __LINE__, typ->vt_hdr);
> > BUG();
> > }
> > }
> >
> > - return 0;
> > +out:
> > + F_EXIT_V2("pblk %d", pblock);
> > + return pblock;
> > }
> >
> > /**
> > @@ -270,12 +284,14 @@ vxfs_bmap1(struct inode *ip, long iblock)
> > if (VXFS_ISIMMED(vip))
> > goto unsupp;
> >
> > - printk(KERN_WARNING "vxfs: inode %ld has no valid orgtype (%x)\n",
> > - ip->i_ino, vip->vii_orgtype);
> > + printk(KERN_ERR "%s:%d inode %ld has no valid orgtype (%x)\n",
> > + __FUNCTION__, __LINE__,
> > + ip->i_ino, vip->vii_orgtype);
> > BUG();
> >
> > unsupp:
> > - printk(KERN_WARNING "vxfs: inode %ld has an unsupported orgtype (%x)\n",
> > - ip->i_ino, vip->vii_orgtype);
> > + printk(KERN_WARNING "%s:%d inode %ld has an unsupported orgtype (%x)\n",
> > + __FUNCTION__, __LINE__,
> > + ip->i_ino, vip->vii_orgtype);
> > return 0;
> > }
> > diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
> > index aaf1fb0..d8b52e6 100644
> > --- a/fs/freevxfs/vxfs_dir.h
> > +++ b/fs/freevxfs/vxfs_dir.h
> > @@ -84,9 +84,5 @@ struct vxfs_direct {
> > #define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1))
> > #define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len)))
> >
> > -/*
> > - * VXFS_DIRBLKOV is the overhead of a specific dirblock.
> > - */
> > -#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4)
> >
> > #endif /* _VXFS_DIR_H_ */
> > diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> > index 881aa3d..3d20421 100644
> > --- a/fs/freevxfs/vxfs_extern.h
> > +++ b/fs/freevxfs/vxfs_extern.h
> > @@ -55,7 +55,7 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
> >
> > /* vxfs_inode.c */
> > extern const struct address_space_operations vxfs_immed_aops;
> > -extern struct kmem_cache *vxfs_inode_cachep;
> > +//extern struct kmem_cache *vxfs_inode_cachep;
> > extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
> > extern struct inode * vxfs_get_fake_inode(struct super_block *,
> > struct vxfs_inode_info *);
> > @@ -64,6 +64,10 @@ extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t
> > extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
> > extern struct inode * vxfs_iget(struct super_block *, ino_t);
> > extern void vxfs_evict_inode(struct inode *);
> > +extern void vxfs_destroy_inode(struct inode *ip);
> > +extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
> > +extern int vxfs_inode_info_cache(int setup);
> > +
> >
> > /* vxfs_lookup.c */
> > extern const struct inode_operations vxfs_dir_inode_ops;
> > diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> > index c9a6a94..69fcd7f 100644
> > --- a/fs/freevxfs/vxfs_fshead.c
> > +++ b/fs/freevxfs/vxfs_fshead.c
> > @@ -2,6 +2,35 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski.
> > + * Many bug fixes, improvements & tests.
> > + *
> > + * These bugs and improvements were as follows:
> > + * - code not aware of cpu endianess and ondisk data is BE.
> > + * - misaligned structures read from block device
> > + * - wrong SB block number. default offset is 8kB
> > + * - kmem_cache_alloc() objectes released with kfree()
> > + * - inode.i_private released in evict_inode() callback.
> > + * - refactored vxfs_readdir() and vxfs_find_entry()
> > + *
> > + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> > + * Example: */
> > +// * cksum mnt/usr/share/man/man3.Z/*
> > +// * cksum mnt/usr/share/doc/10.20RelNotes
>
> More white spaces and more //
>
> > +// * cksum mnt/usr/local/doom/*
> > +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> > +// * cksum mnt/usr/share/doc/*
> > +// * cksum mnt/usr/sprockets/lib/*
> > +// * cksum mnt/usr/sprockets/bin/*
> > +/*
> > + * Needles to say that checksums of files match these evaluated by
> > + * HP-UX B.10.20 cksum. E.g.:
> > + * 3457951056 4196020 /usr/local/doom/doom1.wad
> > + * 2527157998 35344 /usr/local/doom/doomlaunch
> > + * 2974998129 413696 /usr/local/doom/hpdoom
> > + *
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -60,6 +89,34 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
> > }
> > #endif
> >
> > +#define VXFS_BE32(field1, field2) fhp->field1 = be32_to_cpu(dbh->field2)
> > +
> > +
> > +static void inline dbh2fhp(struct vxfs_fsh *fhp, void *_dbh)
> > +{
> > +#ifdef __LITTLE_ENDIAN
> > + struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
> > +
> > + VXFS_BE32(fsh_version, fsh_version);
> > + VXFS_BE32(fsh_fsindex, fsh_fsindex);
> > + VXFS_BE32(fsh_time, fsh_time);
> > + VXFS_BE32(fsh_utime, fsh_utime);
> > + VXFS_BE32(fsh_extop, fsh_extop);
> > + VXFS_BE32(fsh_ninodes, fsh_ninodes);
> > + VXFS_BE32(fsh_nau, fsh_nau);
> > + VXFS_BE32(fsh_old_ilesize, fsh_old_ilesize);
> > + VXFS_BE32(fsh_dflags, fsh_dflags);
> > + VXFS_BE32(fsh_quota, fsh_quota);
> > + VXFS_BE32(fsh_maxinode, fsh_maxinode);
> > + VXFS_BE32(fsh_iauino, fsh_iauino);
> > + VXFS_BE32(fsh_ilistino[0], fsh_ilistino[0]);
> > + VXFS_BE32(fsh_ilistino[1], fsh_ilistino[1]);
> > + VXFS_BE32(fsh_lctino, fsh_lctino);
> > +#else
> > + memcpy(fhp, _dbh, sizeof(*fhp));
> > +#endif
> > +}
> > +
> > /**
> > * vxfs_getfsh - read fileset header into memory
> > * @ip: the (fake) fileset header inode
> > @@ -83,7 +140,8 @@ vxfs_getfsh(struct inode *ip, int which)
> >
> > if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
> > goto out;
> > - memcpy(fhp, bp->b_data, sizeof(*fhp));
> > +
> > + dbh2fhp(fhp, bp->b_data);
> >
> > put_bh(bp);
> > return (fhp);
> > @@ -110,9 +168,12 @@ vxfs_read_fshead(struct super_block *sbp)
> > struct vxfs_fsh *pfp, *sfp;
> > struct vxfs_inode_info *vip, *tip;
> >
> > + F_ENTER();
> > +
> > vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
> > if (!vip) {
> > printk(KERN_ERR "vxfs: unable to read fsh inode\n");
> > + F_EXIT();
> > return -EINVAL;
> > }
> > if (!VXFS_ISFSH(vip)) {
> > @@ -121,10 +182,8 @@ vxfs_read_fshead(struct super_block *sbp)
> > goto out_free_fship;
> > }
> >
> > -
> > #ifdef DIAGNOSTIC
> > - printk("vxfs: fsh inode dump:\n");
> > - vxfs_dumpi(vip, infp->vsi_fshino);
> > + printk("%s:%d\n", __FUNCTION__, __LINE__);
> > #endif
> >
> > infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
> > @@ -160,7 +219,7 @@ vxfs_read_fshead(struct super_block *sbp)
> > infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
> > if (!infp->vsi_stilist) {
> > printk(KERN_ERR "vxfs: unable to get structural list inode\n");
> > - kfree(tip);
> > + vxfs_inode_info_free(tip);
> > goto out_free_pfp;
> > }
> > if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
> > @@ -175,7 +234,7 @@ vxfs_read_fshead(struct super_block *sbp)
> > infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
> > if (!infp->vsi_ilist) {
> > printk(KERN_ERR "vxfs: unable to get inode list inode\n");
> > - kfree(tip);
> > + vxfs_inode_info_free(tip);
> > goto out_iput_stilist;
> > }
> > if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
> > @@ -184,6 +243,7 @@ vxfs_read_fshead(struct super_block *sbp)
> > goto out_iput_ilist;
> > }
> >
> > + F_EXIT();
> > return 0;
> >
> > out_iput_ilist:
> > @@ -196,8 +256,10 @@ vxfs_read_fshead(struct super_block *sbp)
> > kfree(sfp);
> > out_iput_fship:
> > iput(infp->vsi_fship);
> > + F_EXIT();
> > return -EINVAL;
> > out_free_fship:
> > - kfree(vip);
> > + vxfs_inode_info_free(vip);
> > + F_EXIT();
> > return -EINVAL;
> > }
> > diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> > index 363e3ae..84dec28 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -2,6 +2,34 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski.
> > + * Many bug fixes, improvements & tests.
> > + *
> > + * These bugs and improvements were as follows:
> > + * - code not aware of cpu endianess and ondisk data is BE.
> > + * - misaligned structures read from block device
> > + * - wrong SB block number. default offset is 8kB
> > + * - kmem_cache_alloc() objectes released with kfree()
> > + * - inode.i_private released in evict_inode() callback.
> > + * - refactored vxfs_readdir() and vxfs_find_entry()
> > + *
> > + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> > + * Example: */
> > +// * cksum mnt/usr/share/man/man3.Z/*
> > +// * cksum mnt/usr/share/doc/10.20RelNotes
>
> More white spaces and more //
>
> > +// * cksum mnt/usr/local/doom/*
> > +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> > +// * cksum mnt/usr/share/doc/*
> > +// * cksum mnt/usr/sprockets/lib/*
> > +// * cksum mnt/usr/sprockets/bin/*
> > +/*
> > + * Needles to say that checksums of files match these evaluated by
> > + * HP-UX B.10.20 cksum. E.g.:
> > + * 3457951056 4196020 /usr/local/doom/doom1.wad
> > + * 2527157998 35344 /usr/local/doom/doomlaunch
> > + * 2974998129 413696 /usr/local/doom/hpdoom
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -41,7 +69,7 @@
> > #include "vxfs_extern.h"
> >
> >
> > -struct kmem_cache *vxfs_inode_cachep;
> > +static struct kmem_cache *vxfs_inode_cachep;
> >
> >
> > #ifdef DIAGNOSTIC
> > @@ -51,23 +79,88 @@ struct kmem_cache *vxfs_inode_cachep;
> > void
> > vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
> > {
> > - printk(KERN_DEBUG "\n\n");
> > - if (ino)
> > - printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino);
> > +#ifdef DIAGNOSTIC_V2
> > + if (ino && vip)
> > + printk(KERN_DEBUG "\nvxfs inode %ld dump **** %p\n", ino, vip);
> > else
> > - printk(KERN_DEBUG "dumping unknown vxfs inode\n");
> > + printk(KERN_DEBUG "\ndumping unknown vxfs inode %p\n", vip);
> >
> > - printk(KERN_DEBUG "---------------------------\n");
> > - printk(KERN_DEBUG "mode is %x\n", vip->vii_mode);
> > - printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n",
> > - vip->vii_nlink, vip->vii_uid, vip->vii_gid);
> > - printk(KERN_DEBUG "size:%Lx, blocks:%u\n",
> > + if (vip) {
> > + printk(KERN_DEBUG " * mode: %x, type %d\n", vip->vii_mode, vip->vii_orgtype);
> > + printk(KERN_DEBUG " * size:%Lx, blocks:%u\n",
> > vip->vii_size, vip->vii_blocks);
> > - printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype);
> > + printk(KERN_DEBUG " * nlink:%u, uid:%u, gid:%u\n",
> > + vip->vii_nlink, vip->vii_uid, vip->vii_gid);
> > + }
> > +#endif
> > }
> > #endif
> >
> >
> > +#define VXFS_BE32(field1, field2) vip->field1 = be32_to_cpu(dip->field2)
> > +#define VXFS_BE64(field1, field2) vip->field1 = be64_to_cpu(dip->field2)
> > +#define VXFS_BE16(field1, field2) vip->field1 = be16_to_cpu(dip->field2)
> > +
> > +
> > +static void inline dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
> > +{
> > +#ifdef __LITTLE_ENDIAN
> > + int j;
> > +
> > + VXFS_BE32(vdi_mode, vdi_mode);
> > + VXFS_BE32(vdi_nlink, vdi_nlink);
> > + VXFS_BE32(vdi_uid, vdi_uid);
> > + VXFS_BE32(vdi_gid, vdi_gid);
> > + VXFS_BE64(vdi_size, vdi_size);
> > + VXFS_BE32(vdi_atime, vdi_atime);
> > + VXFS_BE32(vdi_autime, vdi_autime);
> > + VXFS_BE32(vdi_mtime, vdi_mtime);
> > + VXFS_BE32(vdi_mutime, vdi_mutime);
> > + VXFS_BE32(vdi_ctime, vdi_ctime);
> > + VXFS_BE32(vdi_cutime, vdi_cutime);
> > + vip->vdi_aflags = dip->vdi_aflags;
> > + vip->vdi_orgtype = dip->vdi_orgtype;
> > + VXFS_BE16(vdi_eopflags, vdi_eopflags);
> > + VXFS_BE32(vdi_eopdata, vdi_eopdata);
> > +
> > + VXFS_BE32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
> > + VXFS_BE32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
> > + VXFS_BE32(vdi_blocks, vdi_blocks);
> > + VXFS_BE32(vdi_gen, vdi_gen);
> > + VXFS_BE64(vdi_version, vdi_version);
> > +
> > + switch (dip->vdi_orgtype) {
> > + case VXFS_ORG_EXT4:
> > + VXFS_BE32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
> > + VXFS_BE32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
> > + for (j = 0; j < VXFS_NIADDR; j++) {
> > + VXFS_BE32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
> > + }
> > + for (j = 0; j < VXFS_NDADDR; j++) {
> > + VXFS_BE32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
> > + VXFS_BE32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
> > + }
> > + break;
> > + case VXFS_ORG_IMMED:
> > + memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
> > + break;
> > + case VXFS_ORG_TYPED:
> > + for (j = 0; j < VXFS_NTYPED; j++) {
> > + VXFS_BE64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
> > + VXFS_BE32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
> > + VXFS_BE32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
> > + }
> > + break;
> > +
> > + };
> > +
> > + VXFS_BE32(vdi_iattrino, vdi_iattrino);
> > +#else
> > + memcpy(vip, dip, sizeof(*vip));
> > +#endif
> > +}
> > +
> > +
> > /**
> > * vxfs_blkiget - find inode based on extent #
> > * @sbp: superblock of the filesystem we search in
> > @@ -84,6 +177,9 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
> > * buffercache. This function should not be used outside the
> > * read_super() method, otherwise the data may be incoherent.
> > */
> > +
> > +
> > +
> > struct vxfs_inode_info *
> > vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
> > {
> > @@ -101,7 +197,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
> > if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> > goto fail;
> > dip = (struct vxfs_dinode *)(bp->b_data + offset);
> > - memcpy(vip, dip, sizeof(*vip));
> > + dip2vip_cpy(vip, dip);
> > #ifdef DIAGNOSTIC
> > vxfs_dumpi(vip, ino);
> > #endif
> > @@ -143,7 +239,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
> > if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> > goto fail;
> > dip = (struct vxfs_dinode *)(kaddr + offset);
> > - memcpy(vip, dip, sizeof(*vip));
> > + dip2vip_cpy(vip, dip);
> > #ifdef DIAGNOSTIC
> > vxfs_dumpi(vip, ino);
> > #endif
> > @@ -190,7 +286,7 @@ vxfs_stiget(struct super_block *sbp, ino_t ino)
> > static __inline__ umode_t
> > vxfs_transmod(struct vxfs_inode_info *vip)
> > {
> > - umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
> > + umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
> >
> > if (VXFS_ISFIFO(vip))
> > ret |= S_IFIFO;
> > @@ -340,21 +436,61 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
> > static void vxfs_i_callback(struct rcu_head *head)
> > {
> > struct inode *inode = container_of(head, struct inode, i_rcu);
> > - kmem_cache_free(vxfs_inode_cachep, inode->i_private);
> > + void *priv = inode->i_private;
> > +
> > + inode->i_private = NULL;
> > + // just in case the same inode was used elsewhere after releasing i_private.
> > + // if it was then dereferencing NULL is far better than using invalid
> > + // pointer to memory claimed by something.
> > + kmem_cache_free(vxfs_inode_cachep, priv);
> > +}
> > +
> > +void vxfs_destroy_inode(struct inode *ip)
> > +{
> > + call_rcu(&ip->i_rcu, vxfs_i_callback);
> > +}
> > +
> > +void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> > +{
> > + kmem_cache_free(vxfs_inode_cachep, vip);
> > }
> >
> > +
> > /**
> > * vxfs_evict_inode - remove inode from main memory
> > * @ip: inode to discard.
> > *
> > * Description:
> > - * vxfs_evict_inode() is called on the final iput and frees the private
> > - * inode area.
> > + * vxfs_evict_inode() is called on the final iput
> > */
> > void
> > vxfs_evict_inode(struct inode *ip)
> > {
> > truncate_inode_pages_final(&ip->i_data);
> > + invalidate_inode_buffers(ip);
> > clear_inode(ip);
> > - call_rcu(&ip->i_rcu, vxfs_i_callback);
> > }
> > +
> > +int vxfs_inode_info_cache(int setup)
> > +{
> > + int rc = 0;
> > +
> > + if (!setup) {
> > + vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> > + sizeof(struct vxfs_inode_info), 0,
> > + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> > +
> > + if (!vxfs_inode_cachep)
> > + rc = -ENOMEM;
> > + } else {
> > + /*
> > + * Make sure all delayed rcu free inodes are flushed before we
> > + * destroy cache.
> > + */
> > + rcu_barrier();
> > + kmem_cache_destroy(vxfs_inode_cachep);
> > + }
> > +
> > + return rc;
> > +}
> > +
> > diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
> > index 240aeb1..9fc3533 100644
> > --- a/fs/freevxfs/vxfs_inode.h
> > +++ b/fs/freevxfs/vxfs_inode.h
> > @@ -77,13 +77,13 @@ struct vxfs_ext4 {
> > vx_daddr_t extent; /* Extent number */
> > int32_t size; /* Size of extent */
> > } ve4_direct[VXFS_NDADDR];
> > -};
> > +} __attribute__((packed));
> >
> > struct vxfs_typed {
> > u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> > vx_daddr_t vt_block; /* Extent block */
> > int32_t vt_size; /* Size in blocks */
> > -};
> > +} __attribute__((packed));
> >
> > struct vxfs_typed_dev4 {
> > u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> > @@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
> > u_int64_t vd4_size; /* Size in blocks */
> > int32_t vd4_dev; /* Device ID */
> > u_int32_t __pad1;
> > -};
> > +} __attribute__((packed));
> >
> > /*
> > * The inode as contained on the physical device.
> > @@ -134,7 +134,7 @@ struct vxfs_dinode {
> > struct vxfs_typed typed[VXFS_NTYPED];
> > } vdi_org;
> > u_int32_t vdi_iattrino;
> > -};
> > +} __attribute__((packed));
> >
> > #define vdi_rdev vdi_ftarea.rdev
> > #define vdi_dotdot vdi_ftarea.dotdot
> > diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> > index 99c7f0a..2e5365b 100644
> > --- a/fs/freevxfs/vxfs_lookup.c
> > +++ b/fs/freevxfs/vxfs_lookup.c
> > @@ -2,6 +2,34 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + * (c) 2016 Krzysztof Blaszkowski.
> > + * Many bug fixes, improvements & tests.
> > + *
> > + * These bugs and improvements were as follows:
> > + * - code not aware of cpu endianess and ondisk data is BE.
> > + * - misaligned structures read from block device
> > + * - wrong SB block number. default offset is 8kB
> > + * - kmem_cache_alloc() objectes released with kfree()
> > + * - inode.i_private released in evict_inode() callback.
> > + * - refactored vxfs_readdir() and vxfs_find_entry()
> > + *
> > + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> > + * Example: */
> > +// * cksum mnt/usr/share/man/man3.Z/*
> > +// * cksum mnt/usr/share/doc/10.20RelNotes
> > +// * cksum mnt/usr/local/doom/*
> > +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> > +// * cksum mnt/usr/share/doc/*
> > +// * cksum mnt/usr/sprockets/lib/*
> > +// * cksum mnt/usr/sprockets/bin/*
> > +/*
> > + * Needles to say that checksums of files match these evaluated by
> > + * HP-UX B.10.20 cksum. E.g.:
> > + * 3457951056 4196020 /usr/local/doom/doom1.wad
> > + * 2527157998 35344 /usr/local/doom/doomlaunch
> > + * 2974998129 413696 /usr/local/doom/hpdoom
> > + *
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -76,6 +104,15 @@ dir_blocks(struct inode *ip)
> > }
> >
> > /*
> > + * VXFS_dirblk_ovh is the overhead of a specific dirblock.
> > + */
> > +static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp)
> > +{
> > + return (sizeof(short) * be16_to_cpu(dbp->d_nhash)) + 4;
> > +}
> > +
> > +
> > +/*
> > * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
> > *
> > * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
> > @@ -83,19 +120,13 @@ dir_blocks(struct inode *ip)
> > static inline int
> > vxfs_match(int len, const char * const name, struct vxfs_direct *de)
> > {
> > - if (len != de->d_namelen)
> > + if (len != be16_to_cpu(de->d_namelen))
> > return 0;
> > if (!de->d_ino)
> > return 0;
> > return !memcmp(name, de->d_name, len);
> > }
> >
> > -static inline struct vxfs_direct *
> > -vxfs_next_entry(struct vxfs_direct *de)
> > -{
> > - return ((struct vxfs_direct *)((char*)de + de->d_reclen));
> > -}
> > -
> > /**
> > * vxfs_find_entry - find a mathing directory entry for a dentry
> > * @ip: directory inode
> > @@ -113,50 +144,73 @@ vxfs_next_entry(struct vxfs_direct *de)
> > static struct vxfs_direct *
> > vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
> > {
> > - u_long npages, page, nblocks, pblocks, block;
> > - u_long bsize = ip->i_sb->s_blocksize;
> > - const char *name = dp->d_name.name;
> > - int namelen = dp->d_name.len;
> > -
> > - npages = dir_pages(ip);
> > - nblocks = dir_blocks(ip);
> > - pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
> > -
> > - for (page = 0; page < npages; page++) {
> > - caddr_t kaddr;
> > - struct page *pp;
> > -
> > - pp = vxfs_get_page(ip->i_mapping, page);
> > - if (IS_ERR(pp))
> > - continue;
> > - kaddr = (caddr_t)page_address(pp);
> > -
> > - for (block = 0; block <= nblocks && block <= pblocks; block++) {
> > - caddr_t baddr, limit;
> > - struct vxfs_dirblk *dbp;
> > - struct vxfs_direct *de;
> > -
> > - baddr = kaddr + (block * bsize);
> > - limit = baddr + bsize - VXFS_DIRLEN(1);
> > -
> > - dbp = (struct vxfs_dirblk *)baddr;
> > - de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
> > -
> > - for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
> > - if (!de->d_reclen)
> > - break;
> > - if (!de->d_ino)
> > - continue;
> > - if (vxfs_match(namelen, name, de)) {
> > - *ppp = pp;
> > - return (de);
> > - }
> > + u_long bsize = ip->i_sb->s_blocksize;
> > + const char *name = dp->d_name.name;
> > + int namelen = dp->d_name.len;
> > + loff_t limit = VXFS_DIRROUND(ip->i_size);
> > + struct vxfs_direct *de_exit = NULL;
> > + loff_t pos = 0;
> > +
> > +
> > + F_ENTER_V2("\"%s\" %d", name, namelen);
> > +
> > + while (pos < limit) {
> > + struct page *pp;
> > + char *kaddr;
> > + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> > +
> > + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> > + if (IS_ERR(pp)) {
> > + return NULL;
> > + }
> > + kaddr = (char *)page_address(pp);
> > +
> > +#ifdef DIAGNOSTIC_V2
> > + printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
> > +#endif
> > + while (pg_ofs < PAGE_SIZE && pos < limit) {
> > + struct vxfs_direct *de;
> > +
> > + if ((pos & (bsize - 1)) < 4) {
> > + struct vxfs_dirblk *dbp =
>
> White space here too
>
> > + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
> > + pos += VXFS_dirblk_ovh(dbp);
> > + pg_ofs += VXFS_dirblk_ovh(dbp);
> > + }
> > + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> > +
> > +#ifdef DIAGNOSTIC_V2
> > + printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
> > + de, pg_ofs,
> > + de->d_name, be16_to_cpu(de->d_namelen),
> > + be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
> > +#endif
> > + if (!de->d_reclen) {
> > + pos += bsize - 1;
> > + pos &= ~(bsize - 1);
> > + break;
> > + }
> > +
> > + pg_ofs += be16_to_cpu(de->d_reclen);
> > + pos += be16_to_cpu(de->d_reclen);
> > + if (!de->d_ino) {
> > + continue;
> > + }
> > +
> > + if (vxfs_match(namelen, name, de)) {
> > + *ppp = pp;
> > + de_exit= de; //return (de);
> > + break;
> > }
> > }
> > - vxfs_put_page(pp);
> > + if (!de_exit)
> > + vxfs_put_page(pp);
> > + else
> > + break;
> > }
> >
> > - return NULL;
> > + F_EXIT_V2("\"%s\": %p", name, de_exit);
> > + return de_exit;
> > }
> >
> > /**
> > @@ -180,11 +234,10 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
> >
> > de = vxfs_find_entry(dip, dp, &pp);
> > if (de) {
> > - ino = de->d_ino;
> > - kunmap(pp);
> > - page_cache_release(pp);
> > + ino = be32_to_cpu(de->d_ino);
> > + vxfs_put_page(pp);
> > }
> > -
> > +
> > return (ino);
> > }
> >
> > @@ -207,17 +260,17 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
> > {
> > struct inode *ip = NULL;
> > ino_t ino;
> > -
> > +
> > if (dp->d_name.len > VXFS_NAMELEN)
> > return ERR_PTR(-ENAMETOOLONG);
> > -
> > +
> > ino = vxfs_inode_by_name(dip, dp);
> > if (ino) {
> > ip = vxfs_iget(dip->i_sb, ino);
> > if (IS_ERR(ip))
> > return ERR_CAST(ip);
> > + d_add(dp, ip);
> > }
> > - d_add(dp, ip);
> > return NULL;
> > }
> >
> > @@ -234,80 +287,95 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
> > * Returns:
> > * Zero.
> > */
> > +
> > static int
> > vxfs_readdir(struct file *fp, struct dir_context *ctx)
> > {
> > struct inode *ip = file_inode(fp);
> > struct super_block *sbp = ip->i_sb;
> > u_long bsize = sbp->s_blocksize;
> > - u_long page, npages, block, pblocks, nblocks, offset;
> > - loff_t pos;
> > + loff_t pos, limit;
> > +
> > + F_ENTER_V3("pos %ld, ino %ld, size %ld", (long)ctx->pos, ip->i_ino, (long)ip->i_size);
> >
> > if (ctx->pos == 0) {
> > if (!dir_emit_dot(fp, ctx))
> > - return 0;
> > - ctx->pos = 1;
> > + goto out;
> > + ctx->pos++;
> > }
> > if (ctx->pos == 1) {
> > if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
> > - return 0;
> > - ctx->pos = 2;
> > + goto out;
> > + ctx->pos++;
> > }
> > - pos = ctx->pos - 2;
> > -
> > - if (pos > VXFS_DIRROUND(ip->i_size))
> > - return 0;
> >
> > - npages = dir_pages(ip);
> > - nblocks = dir_blocks(ip);
> > - pblocks = VXFS_BLOCK_PER_PAGE(sbp);
> > + limit = VXFS_DIRROUND(ip->i_size);
> > + if (ctx->pos > limit) {
> > +// ctx->pos = 0;
> > + goto out;
> > + }
> >
> > - page = pos >> PAGE_CACHE_SHIFT;
> > - offset = pos & ~PAGE_CACHE_MASK;
> > - block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
> > + pos = ctx->pos & ~3L;
> >
> > - for (; page < npages; page++, block = 0) {
> > - char *kaddr;
> > - struct page *pp;
> > + while (pos < limit) {
> > + struct page *pp;
> > + char *kaddr;
> > + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> > + int rc = 0;
> >
> > - pp = vxfs_get_page(ip->i_mapping, page);
> > - if (IS_ERR(pp))
> > - continue;
> > + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> > + if (IS_ERR(pp)) {
> > + return -ENOMEM;
> > + }
> > kaddr = (char *)page_address(pp);
> >
> > - for (; block <= nblocks && block <= pblocks; block++) {
> > - char *baddr, *limit;
> > - struct vxfs_dirblk *dbp;
> > - struct vxfs_direct *de;
> > -
> > - baddr = kaddr + (block * bsize);
> > - limit = baddr + bsize - VXFS_DIRLEN(1);
> > -
> > - dbp = (struct vxfs_dirblk *)baddr;
> > - de = (struct vxfs_direct *)
> > - (offset ?
> > - (kaddr + offset) :
> > - (baddr + VXFS_DIRBLKOV(dbp)));
> > -
> > - for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
> > - if (!de->d_reclen)
> > - break;
> > - if (!de->d_ino)
> > - continue;
> > -
> > - offset = (char *)de - kaddr;
> > - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> > - if (!dir_emit(ctx, de->d_name, de->d_namelen,
> > - de->d_ino, DT_UNKNOWN)) {
> > - vxfs_put_page(pp);
> > - return 0;
> > - }
> > +#ifdef DIAGNOSTIC_V3
> > + printk("%s:%d pos %ld, lim %ld, %p\n", __FUNCTION__, __LINE__, pos, limit, kaddr);
> > +#endif
> > + while (pg_ofs < PAGE_SIZE && pos < limit) {
> > + struct vxfs_direct *de;
> > +
> > + if ((pos & (bsize - 1)) < 4) {
> > + struct vxfs_dirblk *dbp =
>
> White space
>
> > + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK ));
> > + pos += VXFS_dirblk_ovh(dbp);
> > + pg_ofs += VXFS_dirblk_ovh(dbp);
> > + }
> > + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> > +
> > +#ifdef DIAGNOSTIC_V3
> > + printk("%s:%d de=%p, pgo %d: \"%10s\", %d %d %d\n", __FUNCTION__, __LINE__,
> > + de, pg_ofs,
> > + de->d_name, be16_to_cpu(de->d_namelen),
> > + be16_to_cpu(de->d_reclen), be32_to_cpu(de->d_ino));
> > +#endif
> > + if (!de->d_reclen) {
> > + pos += bsize - 1;
> > + pos &= ~(bsize - 1);
> > + break;
> > + }
> > +
> > + pg_ofs += be16_to_cpu(de->d_reclen);
> > + pos += be16_to_cpu(de->d_reclen);
> > + if (!de->d_ino) {
> > + continue;
> > + }
> > +
> > + if (! (rc = dir_emit(ctx, de->d_name, be16_to_cpu(de->d_namelen),
> > + be32_to_cpu(de->d_ino), DT_UNKNOWN))) {
> > + // the dir entry was not submitted, so fix pos.
> > + pos -= be16_to_cpu(de->d_reclen);
> White space
> > + break;
> > }
> > - offset = 0;
> > }
> > vxfs_put_page(pp);
> > - offset = 0;
> > + if (!rc)
> > + break;
> > }
> > - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> > +
> > + ctx->pos = pos | 2;
> > +
> > +out:
> > + F_EXIT_V3("pos %ld", (long)ctx->pos);
> > return 0;
> > }
> > diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
> > index 0495008..19a1cab 100644
> > --- a/fs/freevxfs/vxfs_olt.c
> > +++ b/fs/freevxfs/vxfs_olt.c
> > @@ -2,6 +2,10 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * 2016 Krzysztof Blaszkowski.
> > + * Many bug fixes, improvements & tests
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -43,14 +47,14 @@ static inline void
> > vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
> > {
> > BUG_ON(infp->vsi_fshino);
> > - infp->vsi_fshino = fshp->olt_fsino[0];
> > + infp->vsi_fshino = be32_to_cpu(fshp->olt_fsino[0]);
> > }
> >
> > static inline void
> > vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
> > {
> > BUG_ON(infp->vsi_iext);
> > - infp->vsi_iext = ilistp->olt_iext[0];
> > + infp->vsi_iext = be32_to_cpu(ilistp->olt_iext[0]);
>
> White space in these lines
>
> > }
> >
> > static inline u_long
> > @@ -80,6 +84,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > struct buffer_head *bp;
> > struct vxfs_olt *op;
> > char *oaddr, *eaddr;
> > + u32 j;
> >
> >
> > bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
> > @@ -87,8 +92,8 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > goto fail;
> >
> > op = (struct vxfs_olt *)bp->b_data;
> > - if (op->olt_magic != VXFS_OLT_MAGIC) {
> > - printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
> > + if ((j = be32_to_cpu(op->olt_magic)) != VXFS_OLT_MAGIC) {
> > + printk(KERN_NOTICE "vxfs: ivalid olt magic number %08x at +%d\n", j, infp->vsi_oltext);
> > goto fail;
> > }
> >
> > @@ -97,19 +102,24 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > * I've not seen any such filesystem yet and I'm lazy.. --hch
> > */
> > if (infp->vsi_oltsize > 1) {
> > - printk(KERN_NOTICE "vxfs: oltsize > 1 detected.\n");
> > + printk(KERN_NOTICE "vxfs: oltsize > 1 detected (%d).\n", infp->vsi_oltsize);
> > printk(KERN_NOTICE "vxfs: please notify hch@infradead.org\n");
> > goto fail;
> > }
> >
> > - oaddr = bp->b_data + op->olt_size;
> > + oaddr = bp->b_data + be32_to_cpu(op->olt_size);
> > eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
> >
> > while (oaddr < eaddr) {
> > - struct vxfs_oltcommon *ocp =
> > + struct vxfs_oltcommon *ocp =
> > (struct vxfs_oltcommon *)oaddr;
> > -
> > - switch (ocp->olt_type) {
> > +
> > +#ifdef DIAGNOSTIC
> > + printk(KERN_DEBUG "oltc_type %d, sz %d at +%d\n",
>
> White space
> > + be32_to_cpu(ocp->olt_type), be32_to_cpu(ocp->olt_size), (int)(oaddr - bp->b_data));
> > +#endif
> > +
> > + switch (be32_to_cpu(ocp->olt_type)) {
> > case VXFS_OLT_FSHEAD:
> > vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
> > break;
> > @@ -118,11 +128,16 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > break;
> > }
> >
> > - oaddr += ocp->olt_size;
> > + oaddr += be32_to_cpu(ocp->olt_size);
> > }
> >
> > +#ifdef DIAGNOSTIC
> > + printk(KERN_DEBUG "olt_size %d, vsi_fshino %d, vsi_iext %ld\n",
> > + be32_to_cpu(op->olt_size), (u32)infp->vsi_fshino, infp->vsi_iext);
> > +#endif
> > +
> > brelse(bp);
> > - return 0;
> > + return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
> >
> > fail:
> > brelse(bp);
> > diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> > index 7ca8c75..9fbf271 100644
> > --- a/fs/freevxfs/vxfs_super.c
> > +++ b/fs/freevxfs/vxfs_super.c
> > @@ -2,6 +2,38 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + * (c) 2016 Krzysztof Blaszkowski.
> > + * Many bug fixes, improvements & tests.
> > + *
> > + * These bugs and improvements were as follows:
> > + * - code not aware of cpu endianess and ondisk data is BE.
> > + * - misaligned structures read from block device
> > + * - wrong SB block number. default offset is 8kB
> > + * - kmem_cache_alloc() objectes released with kfree()
> > + * - inode.i_private released in evict_inode() callback.
> > + * - refactored vxfs_readdir() and vxfs_find_entry()
> > + *
> > + * Tests were performed with image of HP 9000/779 disk (/ lvol)
> > + * Example: */
> > +// * cksum mnt/usr/share/man/man3.Z/*
> > +// * cksum mnt/usr/share/doc/10.20RelNotes
>
> White space
>
> > +// * cksum mnt/usr/local/doom/*
> > +// * cksum mnt/usr/sprockets/tools/instrument/16700/*
> > +// * cksum mnt/usr/share/doc/*
> > +// * cksum mnt/usr/sprockets/lib/*
> > +// * cksum mnt/usr/sprockets/bin/*
> > +/*
> > + * Needles to say that checksums of files match these evaluated by
> > + * HP-UX B.10.20 cksum. E.g.:
> > + * 3457951056 4196020 /usr/local/doom/doom1.wad
> > + * 2527157998 35344 /usr/local/doom/doomlaunch
> > + * 2974998129 413696 /usr/local/doom/hpdoom
> > + *
> > + * The hpux_mdsetup tool project which is aimed at making possible
> > + * accessing HP-UX logical volumes by device mapper is here:
> > + * https://sourceforge.net/projects/linux-vxfs/
> > + *
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -41,6 +73,7 @@
> > #include <linux/stat.h>
> > #include <linux/vfs.h>
> > #include <linux/mount.h>
> > +#include <linux/byteorder/generic.h>
> >
> > #include "vxfs.h"
> > #include "vxfs_extern.h"
> > @@ -48,7 +81,7 @@
> > #include "vxfs_inode.h"
> >
> >
> > -MODULE_AUTHOR("Christoph Hellwig");
> > +MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
> > MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
> > MODULE_LICENSE("Dual BSD/GPL");
> >
> > @@ -59,6 +92,7 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *);
> > static int vxfs_remount(struct super_block *, int *, char *);
> >
> > static const struct super_operations vxfs_super_ops = {
> > + .destroy_inode = vxfs_destroy_inode,
> > .evict_inode = vxfs_evict_inode,
> > .put_super = vxfs_put_super,
> > .statfs = vxfs_statfs,
> > @@ -153,6 +187,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> > u_long bsize;
> > struct inode *root;
> > int ret = -EINVAL;
> > + int j;
> >
> > sbp->s_flags |= MS_RDONLY;
> >
> > @@ -168,7 +203,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> > goto out;
> > }
> >
> > - bp = sb_bread(sbp, 1);
> > + bp = sb_bread(sbp, 8);
> > if (!bp || !buffer_mapped(bp)) {
> > if (!silent) {
> > printk(KERN_WARNING
> > @@ -178,32 +213,30 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> > }
> >
> > rsbp = (struct vxfs_sb *)bp->b_data;
> > - if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
> > + if (be32_to_cpu(rsbp->vs_magic) != VXFS_SUPER_MAGIC) {
> > if (!silent)
> > - printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
> > + printk(KERN_NOTICE "vxfs: WRONG superblock magic %08x\n", rsbp->vs_magic);
> > goto out;
> > }
> >
> > - if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
> > - printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
> > - rsbp->vs_version);
> > + j = be32_to_cpu(rsbp->vs_version);
> > + if ((j < 2 || j > 4) && !silent) {
> > + printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
> > goto out;
> > }
> >
> > -#ifdef DIAGNOSTIC
> > - printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
> > - printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
> > -#endif
> >
> > - sbp->s_magic = rsbp->vs_magic;
> > + sbp->s_magic = be32_to_cpu(rsbp->vs_magic);
> > sbp->s_fs_info = infp;
> >
> > infp->vsi_raw = rsbp;
> > infp->vsi_bp = bp;
> > - infp->vsi_oltext = rsbp->vs_oltext[0];
> > - infp->vsi_oltsize = rsbp->vs_oltsize;
> > + infp->vsi_oltext = be32_to_cpu(rsbp->vs_oltext[0]);
> > + infp->vsi_oltsize = be32_to_cpu(rsbp->vs_oltsize);
> > +
> > + printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", be32_to_cpu(rsbp->vs_version));
> >
> > - if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
> > + if (!sb_set_blocksize(sbp, be32_to_cpu(rsbp->vs_bsize))) {
> > printk(KERN_WARNING "vxfs: unable to set final block size\n");
> > goto out;
> > }
> > @@ -229,6 +262,8 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> > printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
> > goto out_free_ilist;
> > }
> > + printk(KERN_DEBUG "vxfs: blocksize: %d, oltext %d, oltsize %d\n",
>
> White space
>
> > + be32_to_cpu(rsbp->vs_bsize), infp->vsi_oltext, infp->vsi_oltsize);
> >
> > return 0;
> >
> > @@ -237,6 +272,7 @@ out_free_ilist:
> > vxfs_put_fake_inode(infp->vsi_ilist);
> > vxfs_put_fake_inode(infp->vsi_stilist);
> > out:
> > + printk(KERN_ERR "vxfs: mount failed %d\n", ret);
> > brelse(bp);
> > kfree(infp);
> > return ret;
> > @@ -264,29 +300,22 @@ MODULE_ALIAS("vxfs");
> > static int __init
> > vxfs_init(void)
> > {
> > - int rv;
> > + int rc = vxfs_inode_info_cache(0);
> >
> > - vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> > - sizeof(struct vxfs_inode_info), 0,
> > - SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> > - if (!vxfs_inode_cachep)
> > - return -ENOMEM;
> > - rv = register_filesystem(&vxfs_fs_type);
> > - if (rv < 0)
> > - kmem_cache_destroy(vxfs_inode_cachep);
> > - return rv;
> > + if (!rc) {
> > + rc = register_filesystem(&vxfs_fs_type);
> > + if (rc < 0)
> > + vxfs_inode_info_cache(1);
> > + }
> > + printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __FUNCTION__, __DATE__, __TIME__, rc);
> > + return rc;
> > }
> >
> > static void __exit
> > vxfs_cleanup(void)
> > {
> > unregister_filesystem(&vxfs_fs_type);
> > - /*
> > - * Make sure all delayed rcu free inodes are flushed before we
> > - * destroy cache.
> > - */
> > - rcu_barrier();
> > - kmem_cache_destroy(vxfs_inode_cachep);
> > + vxfs_inode_info_cache(1);
> > }
> >
> > module_init(vxfs_init);
>
>
--
Krzysztof Blaszkowski
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: freevxfs
2016-05-26 11:50 ` freevxfs Carlos Maiolino
@ 2016-05-26 14:44 ` Krzysztof Błaszkowski
0 siblings, 0 replies; 8+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-26 14:44 UTC (permalink / raw)
To: Carlos Maiolino; +Cc: linux-fsdevel
Hi Carlos,
On Thu, 2016-05-26 at 13:50 +0200, Carlos Maiolino wrote:
> On Wed, May 25, 2016 at 11:27:27PM +0200, Krzysztof Błaszkowski wrote:
> > Hi,
> >
> > Please find included patchset which addresses all major features we have
> > discussed (unless I forgot about something).
> >
>
> Hi Krzysztof,
>
> please send the patches one-by one, inlined in the e-mail message, not attached
> to the e-mail, mainly all of them attached to a single message.
>
> You can use git send-email to send the patches.
Thanks for the tip. Will send the email shortly soon.
I will not use git send-mail because can't recall password for my mail account now.
I hope only that these patches can be applied still after receiving them.
(patches won't be malformed).
Thanks
>
> See: Documentation/SubmittingPatches
>
> Cheers
>
> > I verified correctness of operation with my regression tests and HP-UX's
> > vxfs image. No difference spotted. However I can't do this with SCO
> > image because I do not have such. I reckon that it is highly possible
> > that SCO image will work as usual because the only difference is data
> > endianess and offset of super block.
> >
> > I included for reference these scripts just in case one is curious.
> > (chksum8-sorted.log comes from hp-ux's cksum)
> >
> > Regards,
> > --
> > Krzysztof Blaszkowski
>
> > From 3d3b4e1ed5df014ae191e0566ff86a17d7d9ac05 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Wed, 25 May 2016 21:50:11 +0200
> > Subject: [PATCH 1/7] kconfig note
> >
> >
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> > fs/freevxfs/Kconfig | 10 +++++++++-
> > 1 files changed, 9 insertions(+), 1 deletions(-)
> >
> > diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig
> > index 8dc1cd5..a4c9075 100644
> > --- a/fs/freevxfs/Kconfig
> > +++ b/fs/freevxfs/Kconfig
> > @@ -5,12 +5,20 @@ config VXFS_FS
> > FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
> > file system format. VERITAS VxFS(TM) is the standard file system
> > of SCO UnixWare (and possibly others) and optionally available
> > - for Sunsoft Solaris, HP-UX and many other operating systems.
> > + for Sunsoft Solaris, HP-UX and many other operating systems. However
> > + these particular OS implementations of vxfs may differ in on-disk
> > + data endianess and/or superblock offset. The vxfs module has been
> > + tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.)
> > Currently only readonly access is supported.
> >
> > NOTE: the file system type as used by mount(1), mount(2) and
> > fstab(5) is 'vxfs' as it describes the file system format, not
> > the actual driver.
> >
> > + There is a userspace utility for HP-UX logical volumes which makes
> > + creating HP-UX logical volumes easy from HP-UX disk block device file
> > + or regular file with image of the disk. See:
> > + https://sourceforge.net/projects/linux-vxfs/
> > +
> > To compile this as a module, choose M here: the module will be
> > called freevxfs. If unsure, say N.
> > --
> > 1.7.3.4
> >
>
> > From c617f6bceedc2f68c62e7432f12b59124bab34f7 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Wed, 25 May 2016 22:12:05 +0200
> > Subject: [PATCH 2/7] cpu endian vs file system endian
> >
> >
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> > fs/freevxfs/vxfs.h | 25 +++++++++++-
> > fs/freevxfs/vxfs_bmap.c | 24 ++++++-----
> > fs/freevxfs/vxfs_fshead.c | 25 +++++++++++-
> > fs/freevxfs/vxfs_inode.c | 61 +++++++++++++++++++++++++++-
> > fs/freevxfs/vxfs_inode.h | 8 ++--
> > fs/freevxfs/vxfs_lookup.c | 15 ++++++-
> > fs/freevxfs/vxfs_olt.c | 15 ++++---
> > fs/freevxfs/vxfs_super.c | 97 ++++++++++++++++++++++++++++++++-------------
> > 8 files changed, 215 insertions(+), 55 deletions(-)
> >
> > diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> > index c8a9265..5dc8949 100644
> > --- a/fs/freevxfs/vxfs.h
> > +++ b/fs/freevxfs/vxfs.h
> > @@ -152,7 +152,7 @@ struct vxfs_sb {
> > /*
> > * Actually much more...
> > */
> > -};
> > +} __packed;
> >
> >
> > /*
> > @@ -168,9 +168,32 @@ struct vxfs_sb_info {
> > ino_t vsi_fshino; /* fileset header inode */
> > daddr_t vsi_oltext; /* OLT extent */
> > daddr_t vsi_oltsize; /* OLT size */
> > + int byte_order;
> > + int silent;
> > +};
> > +
> > +enum {
> > + BO_LE = 1,
> > + BO_BE
> > };
> >
> >
> > +static inline u32 fs32_to_cpu(int bo, u32 a)
> > +{
> > + return (bo == BO_BE) ? be32_to_cpu(a) : le32_to_cpu(a);
> > +}
> > +
> > +static inline u16 fs16_to_cpu(int bo, u16 a)
> > +{
> > + return (bo == BO_BE) ? be16_to_cpu(a) : le16_to_cpu(a);
> > +}
> > +
> > +static inline u64 fs64_to_cpu(int bo, u64 a)
> > +{
> > + return (bo == BO_BE) ? be64_to_cpu(a) : le64_to_cpu(a);
> > +}
> > +
> > +
> > /*
> > * File modes. File types above 0xf000 are vxfs internal only, they should
> > * not be passed back to higher levels of the system. vxfs file types must
> > diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
> > index f86fd3c..95afd98 100644
> > --- a/fs/freevxfs/vxfs_bmap.c
> > +++ b/fs/freevxfs/vxfs_bmap.c
> > @@ -92,7 +92,8 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
> > goto fail_buf;
> >
> > indir = (u32 *)buf->b_data;
> > - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
> > + bno = fs32_to_cpu(VXFS_SBI(sb)->byte_order,
> > + indir[(bn/indsize) % (indsize*bn)]) + (bn % indsize);
> >
> > brelse(buf);
> > return bno;
> > @@ -130,6 +131,7 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> > struct buffer_head *bp = NULL;
> > daddr_t pblock = 0;
> > int i;
> > + int bo = VXFS_SBI(ip->i_sb)->byte_order;
> >
> > for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
> > struct vxfs_typed *typ;
> > @@ -142,24 +144,24 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> >
> > typ = ((struct vxfs_typed *)bp->b_data) +
> > (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
> > - off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
> > + off = fs64_to_cpu(bo, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
> >
> > if (block < off) {
> > brelse(bp);
> > continue;
> > }
> >
> > - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
> > + switch ((u_int32_t)(fs64_to_cpu(bo, typ->vt_hdr) >> VXFS_TYPED_TYPESHIFT)) {
> > case VXFS_TYPED_INDIRECT:
> > - pblock = vxfs_bmap_indir(ip, typ->vt_block,
> > - typ->vt_size, block - off);
> > + pblock = vxfs_bmap_indir(ip, fs32_to_cpu(bo, typ->vt_block),
> > + fs32_to_cpu(bo, typ->vt_size), block - off);
> > if (pblock == -2)
> > break;
> > goto out;
> > case VXFS_TYPED_DATA:
> > - if ((block - off) >= typ->vt_size)
> > + if ((block - off) >= fs32_to_cpu(bo, typ->vt_size))
> > break;
> > - pblock = (typ->vt_block + block - off);
> > + pblock = fs32_to_cpu(bo, typ->vt_block) + block - off;
> > goto out;
> > case VXFS_TYPED_INDIRECT_DEV4:
> > case VXFS_TYPED_DATA_DEV4: {
> > @@ -168,12 +170,14 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> >
> > printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
> > printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
> > - (unsigned long long) typ4->vd4_block,
> > - (unsigned long long) typ4->vd4_size,
> > - typ4->vd4_dev);
> > + (unsigned long long) fs64_to_cpu(bo, typ4->vd4_block),
> > + (unsigned long long) fs64_to_cpu(bo, typ4->vd4_size),
> > + fs32_to_cpu(bo, typ4->vd4_dev));
> > goto fail;
> > }
> > default:
> > + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__, __LINE__,
> > + fs64_to_cpu(bo, typ->vt_hdr));
> > BUG();
> > }
> > brelse(bp);
> > diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> > index c9a6a94..6cbdde7 100644
> > --- a/fs/freevxfs/vxfs_fshead.c
> > +++ b/fs/freevxfs/vxfs_fshead.c
> > @@ -60,6 +60,29 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
> > }
> > #endif
> >
> > +#define VXFS_FS32(field1, field2) fhp->field1 = fs32_to_cpu(bo, dbh->field2)
> > +static inline void dbh2fhp(struct vxfs_fsh *fhp, void *_dbh, int bo)
> > +{
> > + struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
> > +
> > + VXFS_FS32(fsh_version, fsh_version);
> > + VXFS_FS32(fsh_fsindex, fsh_fsindex);
> > + VXFS_FS32(fsh_time, fsh_time);
> > + VXFS_FS32(fsh_utime, fsh_utime);
> > + VXFS_FS32(fsh_extop, fsh_extop);
> > + VXFS_FS32(fsh_ninodes, fsh_ninodes);
> > + VXFS_FS32(fsh_nau, fsh_nau);
> > + VXFS_FS32(fsh_old_ilesize, fsh_old_ilesize);
> > + VXFS_FS32(fsh_dflags, fsh_dflags);
> > + VXFS_FS32(fsh_quota, fsh_quota);
> > + VXFS_FS32(fsh_maxinode, fsh_maxinode);
> > + VXFS_FS32(fsh_iauino, fsh_iauino);
> > + VXFS_FS32(fsh_ilistino[0], fsh_ilistino[0]);
> > + VXFS_FS32(fsh_ilistino[1], fsh_ilistino[1]);
> > + VXFS_FS32(fsh_lctino, fsh_lctino);
> > +}
> > +
> > +
> > /**
> > * vxfs_getfsh - read fileset header into memory
> > * @ip: the (fake) fileset header inode
> > @@ -83,7 +106,7 @@ vxfs_getfsh(struct inode *ip, int which)
> >
> > if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
> > goto out;
> > - memcpy(fhp, bp->b_data, sizeof(*fhp));
> > + dbh2fhp(fhp, bp->b_data, VXFS_SBI(ip->i_sb)->byte_order);
> >
> > put_bh(bp);
> > return (fhp);
> > diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> > index 363e3ae..53b8757 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -67,6 +67,63 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
> > }
> > #endif
> >
> > +#define VXFS_FS32(field1, field2) vip->field1 = fs32_to_cpu(bo, dip->field2)
> > +#define VXFS_FS64(field1, field2) vip->field1 = fs64_to_cpu(bo, dip->field2)
> > +#define VXFS_FS16(field1, field2) vip->field1 = fs16_to_cpu(bo, dip->field2)
> > +
> > +static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip, int bo)
> > +{
> > + int j;
> > +
> > + VXFS_FS32(vdi_mode, vdi_mode);
> > + VXFS_FS32(vdi_nlink, vdi_nlink);
> > + VXFS_FS32(vdi_uid, vdi_uid);
> > + VXFS_FS32(vdi_gid, vdi_gid);
> > + VXFS_FS64(vdi_size, vdi_size);
> > + VXFS_FS32(vdi_atime, vdi_atime);
> > + VXFS_FS32(vdi_autime, vdi_autime);
> > + VXFS_FS32(vdi_mtime, vdi_mtime);
> > + VXFS_FS32(vdi_mutime, vdi_mutime);
> > + VXFS_FS32(vdi_ctime, vdi_ctime);
> > + VXFS_FS32(vdi_cutime, vdi_cutime);
> > + vip->vdi_aflags = dip->vdi_aflags;
> > + vip->vdi_orgtype = dip->vdi_orgtype;
> > + VXFS_FS16(vdi_eopflags, vdi_eopflags);
> > + VXFS_FS32(vdi_eopdata, vdi_eopdata);
> > +
> > + VXFS_FS32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
> > + VXFS_FS32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
> > + VXFS_FS32(vdi_blocks, vdi_blocks);
> > + VXFS_FS32(vdi_gen, vdi_gen);
> > + VXFS_FS64(vdi_version, vdi_version);
> > +
> > + switch (dip->vdi_orgtype) {
> > + case VXFS_ORG_EXT4:
> > + VXFS_FS32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
> > + VXFS_FS32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
> > + for (j = 0; j < VXFS_NIADDR; j++) {
> > + VXFS_FS32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
> > + }
> > + for (j = 0; j < VXFS_NDADDR; j++) {
> > + VXFS_FS32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
> > + VXFS_FS32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
> > + }
> > + break;
> > + case VXFS_ORG_IMMED:
> > + memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
> > + break;
> > + case VXFS_ORG_TYPED:
> > + for (j = 0; j < VXFS_NTYPED; j++) {
> > + VXFS_FS64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
> > + VXFS_FS32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
> > + VXFS_FS32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
> > + }
> > + break;
> > + };
> > +
> > + VXFS_FS32(vdi_iattrino, vdi_iattrino);
> > +}
> > +
> >
> > /**
> > * vxfs_blkiget - find inode based on extent #
> > @@ -101,7 +158,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
> > if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> > goto fail;
> > dip = (struct vxfs_dinode *)(bp->b_data + offset);
> > - memcpy(vip, dip, sizeof(*vip));
> > + dip2vip_cpy(vip, dip, VXFS_SBI(sbp)->byte_order);
> > #ifdef DIAGNOSTIC
> > vxfs_dumpi(vip, ino);
> > #endif
> > @@ -143,7 +200,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
> > if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> > goto fail;
> > dip = (struct vxfs_dinode *)(kaddr + offset);
> > - memcpy(vip, dip, sizeof(*vip));
> > + dip2vip_cpy(vip, dip, VXFS_SBI(ilistp->i_sb)->byte_order);
> > #ifdef DIAGNOSTIC
> > vxfs_dumpi(vip, ino);
> > #endif
> > diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
> > index 240aeb1..9a2c376 100644
> > --- a/fs/freevxfs/vxfs_inode.h
> > +++ b/fs/freevxfs/vxfs_inode.h
> > @@ -77,13 +77,13 @@ struct vxfs_ext4 {
> > vx_daddr_t extent; /* Extent number */
> > int32_t size; /* Size of extent */
> > } ve4_direct[VXFS_NDADDR];
> > -};
> > +} __packed;
> >
> > struct vxfs_typed {
> > u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> > vx_daddr_t vt_block; /* Extent block */
> > int32_t vt_size; /* Size in blocks */
> > -};
> > +} __packed;
> >
> > struct vxfs_typed_dev4 {
> > u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> > @@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
> > u_int64_t vd4_size; /* Size in blocks */
> > int32_t vd4_dev; /* Device ID */
> > u_int32_t __pad1;
> > -};
> > +} __packed;
> >
> > /*
> > * The inode as contained on the physical device.
> > @@ -134,7 +134,7 @@ struct vxfs_dinode {
> > struct vxfs_typed typed[VXFS_NTYPED];
> > } vdi_org;
> > u_int32_t vdi_iattrino;
> > -};
> > +} __packed;
> >
> > #define vdi_rdev vdi_ftarea.rdev
> > #define vdi_dotdot vdi_ftarea.dotdot
> > diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> > index 99c7f0a..cea158a 100644
> > --- a/fs/freevxfs/vxfs_lookup.c
> > +++ b/fs/freevxfs/vxfs_lookup.c
> > @@ -96,6 +96,15 @@ vxfs_next_entry(struct vxfs_direct *de)
> > return ((struct vxfs_direct *)((char*)de + de->d_reclen));
> > }
> >
> > +/*
> > + * VXFS_dirblk_ovh is the overhead of a specific dirblock.
> > + */
> > +static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
> > +{
> > + return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> > +}
> > +
> > +
> > /**
> > * vxfs_find_entry - find a mathing directory entry for a dentry
> > * @ip: directory inode
> > @@ -242,6 +251,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
> > u_long bsize = sbp->s_blocksize;
> > u_long page, npages, block, pblocks, nblocks, offset;
> > loff_t pos;
> > + int bo = VXFS_SBI(sbp)->byte_order;
> > +
> >
> > if (ctx->pos == 0) {
> > if (!dir_emit_dot(fp, ctx))
> > @@ -297,8 +308,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
> >
> > offset = (char *)de - kaddr;
> > ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> > - if (!dir_emit(ctx, de->d_name, de->d_namelen,
> > - de->d_ino, DT_UNKNOWN)) {
> > + if (!dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
> > + fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN)) {
> > vxfs_put_page(pp);
> > return 0;
> > }
> > diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
> > index 0495008..6b50188 100644
> > --- a/fs/freevxfs/vxfs_olt.c
> > +++ b/fs/freevxfs/vxfs_olt.c
> > @@ -43,14 +43,14 @@ static inline void
> > vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
> > {
> > BUG_ON(infp->vsi_fshino);
> > - infp->vsi_fshino = fshp->olt_fsino[0];
> > + infp->vsi_fshino = fs32_to_cpu(infp->byte_order, fshp->olt_fsino[0]);
> > }
> >
> > static inline void
> > vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
> > {
> > BUG_ON(infp->vsi_iext);
> > - infp->vsi_iext = ilistp->olt_iext[0];
> > + infp->vsi_iext = fs32_to_cpu(infp->byte_order, ilistp->olt_iext[0]);
> > }
> >
> > static inline u_long
> > @@ -80,6 +80,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > struct buffer_head *bp;
> > struct vxfs_olt *op;
> > char *oaddr, *eaddr;
> > + int bo = infp->byte_order;
> >
> >
> > bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
> > @@ -87,7 +88,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > goto fail;
> >
> > op = (struct vxfs_olt *)bp->b_data;
> > - if (op->olt_magic != VXFS_OLT_MAGIC) {
> > + if (fs32_to_cpu(bo, op->olt_magic) != VXFS_OLT_MAGIC) {
> > printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
> > goto fail;
> > }
> > @@ -102,14 +103,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > goto fail;
> > }
> >
> > - oaddr = bp->b_data + op->olt_size;
> > + oaddr = bp->b_data + fs32_to_cpu(bo, op->olt_size);
> > eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
> >
> > while (oaddr < eaddr) {
> > struct vxfs_oltcommon *ocp =
> > (struct vxfs_oltcommon *)oaddr;
> >
> > - switch (ocp->olt_type) {
> > + switch (fs32_to_cpu(bo, ocp->olt_type)) {
> > case VXFS_OLT_FSHEAD:
> > vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
> > break;
> > @@ -118,11 +119,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> > break;
> > }
> >
> > - oaddr += ocp->olt_size;
> > + oaddr += fs32_to_cpu(bo, ocp->olt_size);
> > }
> >
> > brelse(bp);
> > - return 0;
> > + return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
> >
> > fail:
> > brelse(bp);
> > diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> > index 7ca8c75..6a19802 100644
> > --- a/fs/freevxfs/vxfs_super.c
> > +++ b/fs/freevxfs/vxfs_super.c
> > @@ -109,14 +109,15 @@ static int
> > vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
> > {
> > struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb);
> > + struct vxfs_sb *raw_sb = infp->vsi_raw;
> >
> > bufp->f_type = VXFS_SUPER_MAGIC;
> > bufp->f_bsize = dentry->d_sb->s_blocksize;
> > - bufp->f_blocks = infp->vsi_raw->vs_dsize;
> > - bufp->f_bfree = infp->vsi_raw->vs_free;
> > + bufp->f_blocks = fs32_to_cpu(infp->byte_order, raw_sb->vs_dsize);
> > + bufp->f_bfree = fs32_to_cpu(infp->byte_order, raw_sb->vs_free);
> > bufp->f_bavail = 0;
> > bufp->f_files = 0;
> > - bufp->f_ffree = infp->vsi_raw->vs_ifree;
> > + bufp->f_ffree = fs32_to_cpu(infp->byte_order, raw_sb->vs_ifree);
> > bufp->f_namelen = VXFS_NAMELEN;
> >
> > return 0;
> > @@ -129,6 +130,46 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
> > return 0;
> > }
> >
> > +
> > +static int vxfs_try_sb_magic(struct super_block *sbp, int blk, u32 magic)
> > +{
> > + struct buffer_head *bp;
> > + struct vxfs_sb *rsbp;
> > + struct vxfs_sb_info *infp = VXFS_SBI(sbp);
> > + int rc = -ENOMEM;
> > +
> > + bp = sb_bread(sbp, blk);
> > + do {
> > + if (!bp || !buffer_mapped(bp)) {
> > + if (!infp->silent) {
> > + printk(KERN_WARNING "vxfs: unable to read"
> > + " disk superblock at %d\n", blk);
> > + }
> > + break;
> > + }
> > +
> > + rc = -EINVAL;
> > + rsbp = (struct vxfs_sb *)bp->b_data;
> > + if (rsbp->vs_magic != magic) {
> > + if (!infp->silent)
> > + printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
> > + break;
> > + }
> > +
> > + rc = 0;
> > + infp->vsi_raw = rsbp;
> > + infp->vsi_bp = bp;
> > + } while (0);
> > +
> > + if (rc) {
> > + infp->vsi_raw = NULL;
> > + infp->vsi_bp = NULL;
> > + brelse(bp);
> > + }
> > +
> > + return rc;
> > +}
> > +
> > /**
> > * vxfs_read_super - read superblock into memory and initialize filesystem
> > * @sbp: VFS superblock (to fill)
> > @@ -149,10 +190,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> > {
> > struct vxfs_sb_info *infp;
> > struct vxfs_sb *rsbp;
> > - struct buffer_head *bp = NULL;
> > u_long bsize;
> > struct inode *root;
> > int ret = -EINVAL;
> > + u32 j;
> >
> > sbp->s_flags |= MS_RDONLY;
> >
> > @@ -162,48 +203,47 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> > return -ENOMEM;
> > }
> >
> > + infp->silent = silent;
> > bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
> > if (!bsize) {
> > printk(KERN_WARNING "vxfs: unable to set blocksize\n");
> > goto out;
> > }
> >
> > - bp = sb_bread(sbp, 1);
> > - if (!bp || !buffer_mapped(bp)) {
> > - if (!silent) {
> > - printk(KERN_WARNING
> > - "vxfs: unable to read disk superblock\n");
> > + sbp->s_fs_info = infp;
> > + do {
> > + if (!vxfs_try_sb_magic(sbp, 1, cpu_to_le32(VXFS_SUPER_MAGIC))) {
> > + infp->byte_order = BO_LE; /* SCO */
> > + break;
> > + }
> > +
> > + if (!vxfs_try_sb_magic(sbp, 8, cpu_to_be32(VXFS_SUPER_MAGIC))) {
> > + infp->byte_order = BO_BE; /* HP-UX pa-risc likely */
> > + break;
> > }
> > - goto out;
> > - }
> >
> > - rsbp = (struct vxfs_sb *)bp->b_data;
> > - if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
> > - if (!silent)
> > - printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
> > goto out;
> > - }
> > + } while (0);
> >
> > - if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
> > - printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
> > - rsbp->vs_version);
> > + rsbp = infp->vsi_raw;
> > + j = fs32_to_cpu(infp->byte_order, rsbp->vs_version);
> > + if ((j < 2 || j > 4) && !silent) {
> > + printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
> > goto out;
> > }
> >
> > #ifdef DIAGNOSTIC
> > - printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
> > + printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
> > printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
> > #endif
> >
> > - sbp->s_magic = rsbp->vs_magic;
> > - sbp->s_fs_info = infp;
> > + sbp->s_magic = fs32_to_cpu(infp->byte_order, rsbp->vs_magic);
> >
> > - infp->vsi_raw = rsbp;
> > - infp->vsi_bp = bp;
> > - infp->vsi_oltext = rsbp->vs_oltext[0];
> > - infp->vsi_oltsize = rsbp->vs_oltsize;
> > + infp->vsi_oltext = fs32_to_cpu(infp->byte_order, rsbp->vs_oltext[0]);
> > + infp->vsi_oltsize = fs32_to_cpu(infp->byte_order, rsbp->vs_oltsize);
> >
> > - if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
> > + j = fs32_to_cpu(infp->byte_order, rsbp->vs_bsize);
> > + if (!sb_set_blocksize(sbp, j)) {
> > printk(KERN_WARNING "vxfs: unable to set final block size\n");
> > goto out;
> > }
> > @@ -237,7 +277,8 @@ out_free_ilist:
> > vxfs_put_fake_inode(infp->vsi_ilist);
> > vxfs_put_fake_inode(infp->vsi_stilist);
> > out:
> > - brelse(bp);
> > + if (infp->vsi_bp)
> > + brelse(infp->vsi_bp);
> > kfree(infp);
> > return ret;
> > }
> > --
> > 1.7.3.4
> >
>
> > From b95e9b749b85be347c953ce33d2b3c5dde4e56d6 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Wed, 25 May 2016 22:13:20 +0200
> > Subject: [PATCH 3/7] missing kfree and kfree on kmem_cache obj
> >
> >
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> > fs/freevxfs/vxfs_extern.h | 1 +
> > fs/freevxfs/vxfs_fshead.c | 8 +++++---
> > fs/freevxfs/vxfs_inode.c | 5 +++++
> > 3 files changed, 11 insertions(+), 3 deletions(-)
> >
> > diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> > index 881aa3d..0a3ff86 100644
> > --- a/fs/freevxfs/vxfs_extern.h
> > +++ b/fs/freevxfs/vxfs_extern.h
> > @@ -64,6 +64,7 @@ extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t
> > extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
> > extern struct inode * vxfs_iget(struct super_block *, ino_t);
> > extern void vxfs_evict_inode(struct inode *);
> > +extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
> >
> > /* vxfs_lookup.c */
> > extern const struct inode_operations vxfs_dir_inode_ops;
> > diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> > index 6cbdde7..67ca2f9 100644
> > --- a/fs/freevxfs/vxfs_fshead.c
> > +++ b/fs/freevxfs/vxfs_fshead.c
> > @@ -183,7 +183,7 @@ vxfs_read_fshead(struct super_block *sbp)
> > infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
> > if (!infp->vsi_stilist) {
> > printk(KERN_ERR "vxfs: unable to get structural list inode\n");
> > - kfree(tip);
> > + vxfs_inode_info_free(tip);
> > goto out_free_pfp;
> > }
> > if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
> > @@ -198,7 +198,7 @@ vxfs_read_fshead(struct super_block *sbp)
> > infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
> > if (!infp->vsi_ilist) {
> > printk(KERN_ERR "vxfs: unable to get inode list inode\n");
> > - kfree(tip);
> > + vxfs_inode_info_free(tip);
> > goto out_iput_stilist;
> > }
> > if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
> > @@ -206,6 +206,8 @@ vxfs_read_fshead(struct super_block *sbp)
> > VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
> > goto out_iput_ilist;
> > }
> > + kfree(pfp);
> > + kfree(sfp);
> >
> > return 0;
> >
> > @@ -221,6 +223,6 @@ vxfs_read_fshead(struct super_block *sbp)
> > iput(infp->vsi_fship);
> > return -EINVAL;
> > out_free_fship:
> > - kfree(vip);
> > + vxfs_inode_info_free(vip);
> > return -EINVAL;
> > }
> > diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> > index 53b8757..16d8d27 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -415,3 +415,8 @@ vxfs_evict_inode(struct inode *ip)
> > clear_inode(ip);
> > call_rcu(&ip->i_rcu, vxfs_i_callback);
> > }
> > +
> > +void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> > +{
> > + kmem_cache_free(vxfs_inode_cachep, vip);
> > +}
> > --
> > 1.7.3.4
> >
>
> > From e4979c6a29eb79d59d8bc2eca9acc0d2b416780f Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Wed, 25 May 2016 22:15:20 +0200
> > Subject: [PATCH 4/7] super_operations.destroy_inode
> >
> >
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> > fs/freevxfs/vxfs_extern.h | 1 +
> > fs/freevxfs/vxfs_inode.c | 16 ++++++++++++----
> > fs/freevxfs/vxfs_super.c | 1 +
> > 3 files changed, 14 insertions(+), 4 deletions(-)
> >
> > diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> > index 0a3ff86..4d8298b 100644
> > --- a/fs/freevxfs/vxfs_extern.h
> > +++ b/fs/freevxfs/vxfs_extern.h
> > @@ -65,6 +65,7 @@ extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
> > extern struct inode * vxfs_iget(struct super_block *, ino_t);
> > extern void vxfs_evict_inode(struct inode *);
> > extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
> > +extern void vxfs_destroy_inode(struct inode *ip);
> >
> > /* vxfs_lookup.c */
> > extern const struct inode_operations vxfs_dir_inode_ops;
> > diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> > index 16d8d27..9b45ad7 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -397,7 +397,15 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
> > static void vxfs_i_callback(struct rcu_head *head)
> > {
> > struct inode *inode = container_of(head, struct inode, i_rcu);
> > - kmem_cache_free(vxfs_inode_cachep, inode->i_private);
> > + void *priv = inode->i_private;
> > +
> > + inode->i_private = NULL;
> > + kmem_cache_free(vxfs_inode_cachep, priv);
> > +}
> > +
> > +void vxfs_destroy_inode(struct inode *ip)
> > +{
> > + call_rcu(&ip->i_rcu, vxfs_i_callback);
> > }
> >
> > /**
> > @@ -405,17 +413,17 @@ static void vxfs_i_callback(struct rcu_head *head)
> > * @ip: inode to discard.
> > *
> > * Description:
> > - * vxfs_evict_inode() is called on the final iput and frees the private
> > - * inode area.
> > + * vxfs_evict_inode() is called on the final iput
> > */
> > void
> > vxfs_evict_inode(struct inode *ip)
> > {
> > truncate_inode_pages_final(&ip->i_data);
> > + invalidate_inode_buffers(ip);
> > clear_inode(ip);
> > - call_rcu(&ip->i_rcu, vxfs_i_callback);
> > }
> >
> > +
> > void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> > {
> > kmem_cache_free(vxfs_inode_cachep, vip);
> > diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> > index 6a19802..11a535a 100644
> > --- a/fs/freevxfs/vxfs_super.c
> > +++ b/fs/freevxfs/vxfs_super.c
> > @@ -59,6 +59,7 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *);
> > static int vxfs_remount(struct super_block *, int *, char *);
> >
> > static const struct super_operations vxfs_super_ops = {
> > + .destroy_inode = vxfs_destroy_inode,
> > .evict_inode = vxfs_evict_inode,
> > .put_super = vxfs_put_super,
> > .statfs = vxfs_statfs,
> > --
> > 1.7.3.4
> >
>
> > From 4a6ae0e351b6046367bbd2939547f292ed2b6e47 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Wed, 25 May 2016 22:28:37 +0200
> > Subject: [PATCH 5/7] refactoring of vxfs_readir() and find_entry()
> >
> >
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> > fs/freevxfs/vxfs_lookup.c | 267 +++++++++++++++++++++------------------------
> > 1 files changed, 124 insertions(+), 143 deletions(-)
> >
> > diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> > index cea158a..8eacb27 100644
> > --- a/fs/freevxfs/vxfs_lookup.c
> > +++ b/fs/freevxfs/vxfs_lookup.c
> > @@ -61,48 +61,6 @@ const struct file_operations vxfs_dir_operations = {
> > .iterate = vxfs_readdir,
> > };
> >
> > -
> > -static inline u_long
> > -dir_pages(struct inode *inode)
> > -{
> > - return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
> > -}
> > -
> > -static inline u_long
> > -dir_blocks(struct inode *ip)
> > -{
> > - u_long bsize = ip->i_sb->s_blocksize;
> > - return (ip->i_size + bsize - 1) & ~(bsize - 1);
> > -}
> > -
> > -/*
> > - * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
> > - *
> > - * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
> > - */
> > -static inline int
> > -vxfs_match(int len, const char * const name, struct vxfs_direct *de)
> > -{
> > - if (len != de->d_namelen)
> > - return 0;
> > - if (!de->d_ino)
> > - return 0;
> > - return !memcmp(name, de->d_name, len);
> > -}
> > -
> > -static inline struct vxfs_direct *
> > -vxfs_next_entry(struct vxfs_direct *de)
> > -{
> > - return ((struct vxfs_direct *)((char*)de + de->d_reclen));
> > -}
> > -
> > -/*
> > - * VXFS_dirblk_ovh is the overhead of a specific dirblock.
> > - */
> > -static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
> > -{
> > - return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> > -}
> >
> >
> > /**
> > @@ -122,50 +80,65 @@ static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
> > static struct vxfs_direct *
> > vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
> > {
> > - u_long npages, page, nblocks, pblocks, block;
> > - u_long bsize = ip->i_sb->s_blocksize;
> > - const char *name = dp->d_name.name;
> > - int namelen = dp->d_name.len;
> > -
> > - npages = dir_pages(ip);
> > - nblocks = dir_blocks(ip);
> > - pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
> > -
> > - for (page = 0; page < npages; page++) {
> > - caddr_t kaddr;
> > - struct page *pp;
> > -
> > - pp = vxfs_get_page(ip->i_mapping, page);
> > - if (IS_ERR(pp))
> > - continue;
> > - kaddr = (caddr_t)page_address(pp);
> > -
> > - for (block = 0; block <= nblocks && block <= pblocks; block++) {
> > - caddr_t baddr, limit;
> > - struct vxfs_dirblk *dbp;
> > - struct vxfs_direct *de;
> > -
> > - baddr = kaddr + (block * bsize);
> > - limit = baddr + bsize - VXFS_DIRLEN(1);
> > -
> > - dbp = (struct vxfs_dirblk *)baddr;
> > - de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
> > -
> > - for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
> > - if (!de->d_reclen)
> > - break;
> > - if (!de->d_ino)
> > - continue;
> > - if (vxfs_match(namelen, name, de)) {
> > - *ppp = pp;
> > - return (de);
> > - }
> > + u_long bsize = ip->i_sb->s_blocksize;
> > + const char *name = dp->d_name.name;
> > + int namelen = dp->d_name.len;
> > + loff_t limit = VXFS_DIRROUND(ip->i_size);
> > + struct vxfs_direct *de_exit = NULL;
> > + loff_t pos = 0;
> > + int bo = VXFS_SBI(ip->i_sb)->byte_order;
> > +
> > + while (pos < limit) {
> > + struct page *pp;
> > + char *kaddr;
> > + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> > +
> > + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> > + if (IS_ERR(pp)) {
> > + return NULL;
> > + }
> > + kaddr = (char *)page_address(pp);
> > +
> > + while (pg_ofs < PAGE_SIZE && pos < limit) {
> > + struct vxfs_direct *de;
> > +
> > + if ((pos & (bsize - 1)) < 4) {
> > + struct vxfs_dirblk *dbp =
> > + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
> > + int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> > +
> > + pos += overhead;
> > + pg_ofs += overhead;
> > + }
> > + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> > +
> > + if (!de->d_reclen) {
> > + pos += bsize - 1;
> > + pos &= ~(bsize - 1);
> > + break;
> > + }
> > +
> > + pg_ofs += fs16_to_cpu(bo, de->d_reclen);
> > + pos += fs16_to_cpu(bo, de->d_reclen);
> > + if (!de->d_ino) {
> > + continue;
> > + }
> > +
> > + if (namelen != fs16_to_cpu(bo, de->d_namelen))
> > + continue;
> > + if (!memcmp(name, de->d_name, namelen)) {
> > + *ppp = pp;
> > + de_exit = de;
> > + break;
> > }
> > }
> > - vxfs_put_page(pp);
> > + if (!de_exit)
> > + vxfs_put_page(pp);
> > + else
> > + break;
> > }
> >
> > - return NULL;
> > + return de_exit;
> > }
> >
> > /**
> > @@ -185,15 +158,17 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
> > {
> > struct vxfs_direct *de;
> > struct page *pp;
> > - ino_t ino = 0;
> > + ino_t ino = 0;
> >
> > de = vxfs_find_entry(dip, dp, &pp);
> > if (de) {
> > - ino = de->d_ino;
> > + int bo = VXFS_SBI(dip->i_sb)->byte_order;
> > +
> > + ino = fs32_to_cpu(bo, de->d_ino);
> > kunmap(pp);
> > page_cache_release(pp);
> > }
> > -
> > +
> > return (ino);
> > }
> >
> > @@ -225,8 +200,8 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
> > ip = vxfs_iget(dip->i_sb, ino);
> > if (IS_ERR(ip))
> > return ERR_CAST(ip);
> > + d_add(dp, ip);
> > }
> > - d_add(dp, ip);
> > return NULL;
> > }
> >
> > @@ -249,76 +224,82 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
> > struct inode *ip = file_inode(fp);
> > struct super_block *sbp = ip->i_sb;
> > u_long bsize = sbp->s_blocksize;
> > - u_long page, npages, block, pblocks, nblocks, offset;
> > - loff_t pos;
> > + loff_t pos, limit;
> > int bo = VXFS_SBI(sbp)->byte_order;
> >
> > -
> > if (ctx->pos == 0) {
> > if (!dir_emit_dot(fp, ctx))
> > - return 0;
> > - ctx->pos = 1;
> > + goto out;
> > + ctx->pos++;
> > }
> > if (ctx->pos == 1) {
> > if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
> > - return 0;
> > - ctx->pos = 2;
> > + goto out;
> > + ctx->pos++;
> > + }
> > +
> > + limit = VXFS_DIRROUND(ip->i_size);
> > + if (ctx->pos > limit) {
> > +#if 0
> > + ctx->pos = 0;
> > +#endif
> > + goto out;
> > }
> > - pos = ctx->pos - 2;
> > -
> > - if (pos > VXFS_DIRROUND(ip->i_size))
> > - return 0;
> > -
> > - npages = dir_pages(ip);
> > - nblocks = dir_blocks(ip);
> > - pblocks = VXFS_BLOCK_PER_PAGE(sbp);
> > -
> > - page = pos >> PAGE_CACHE_SHIFT;
> > - offset = pos & ~PAGE_CACHE_MASK;
> > - block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
> > -
> > - for (; page < npages; page++, block = 0) {
> > - char *kaddr;
> > - struct page *pp;
> > -
> > - pp = vxfs_get_page(ip->i_mapping, page);
> > - if (IS_ERR(pp))
> > - continue;
> > +
> > + pos = ctx->pos & ~3L;
> > +
> > + while (pos < limit) {
> > + struct page *pp;
> > + char *kaddr;
> > + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> > + int rc = 0;
> > +
> > + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> > + if (IS_ERR(pp)) {
> > + return -ENOMEM;
> > + }
> > kaddr = (char *)page_address(pp);
> >
> > - for (; block <= nblocks && block <= pblocks; block++) {
> > - char *baddr, *limit;
> > - struct vxfs_dirblk *dbp;
> > - struct vxfs_direct *de;
> > -
> > - baddr = kaddr + (block * bsize);
> > - limit = baddr + bsize - VXFS_DIRLEN(1);
> > -
> > - dbp = (struct vxfs_dirblk *)baddr;
> > - de = (struct vxfs_direct *)
> > - (offset ?
> > - (kaddr + offset) :
> > - (baddr + VXFS_DIRBLKOV(dbp)));
> > -
> > - for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
> > - if (!de->d_reclen)
> > - break;
> > - if (!de->d_ino)
> > - continue;
> > -
> > - offset = (char *)de - kaddr;
> > - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> > - if (!dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
> > - fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN)) {
> > - vxfs_put_page(pp);
> > - return 0;
> > - }
> > + while (pg_ofs < PAGE_SIZE && pos < limit) {
> > + struct vxfs_direct *de;
> > +
> > + if ((pos & (bsize - 1)) < 4) {
> > + struct vxfs_dirblk *dbp =
> > + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
> > + int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> > +
> > + pos += overhead;
> > + pg_ofs += overhead;
> > + }
> > + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> > +
> > + if (!de->d_reclen) {
> > + pos += bsize - 1;
> > + pos &= ~(bsize - 1);
> > + break;
> > + }
> > +
> > + pg_ofs += fs16_to_cpu(bo, de->d_reclen);
> > + pos += fs16_to_cpu(bo, de->d_reclen);
> > + if (!de->d_ino) {
> > + continue;
> > + }
> > +
> > + rc = dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
> > + fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN);
> > + if (!rc) {
> > + /* the dir entry was not submitted, so fix pos. */
> > + pos -= fs16_to_cpu(bo, de->d_reclen);
> > + break;
> > }
> > - offset = 0;
> > }
> > vxfs_put_page(pp);
> > - offset = 0;
> > + if (!rc)
> > + break;
> > }
> > - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> > +
> > + ctx->pos = pos | 2;
> > +
> > +out:
> > return 0;
> > }
> > --
> > 1.7.3.4
> >
>
> > From e7f68291aada1535016c767a4f5a5fcfb19a1de6 Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Wed, 25 May 2016 22:41:22 +0200
> > Subject: [PATCH 6/7] static cachep
> >
> >
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> > fs/freevxfs/vxfs_extern.h | 4 +++-
> > fs/freevxfs/vxfs_inode.c | 24 +++++++++++++++++++++++-
> > fs/freevxfs/vxfs_super.c | 26 ++++++++++----------------
> > 3 files changed, 36 insertions(+), 18 deletions(-)
> >
> > diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> > index 4d8298b..cc43fd0 100644
> > --- a/fs/freevxfs/vxfs_extern.h
> > +++ b/fs/freevxfs/vxfs_extern.h
> > @@ -55,7 +55,6 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
> >
> > /* vxfs_inode.c */
> > extern const struct address_space_operations vxfs_immed_aops;
> > -extern struct kmem_cache *vxfs_inode_cachep;
> > extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
> > extern struct inode * vxfs_get_fake_inode(struct super_block *,
> > struct vxfs_inode_info *);
> > @@ -66,6 +65,9 @@ extern struct inode * vxfs_iget(struct super_block *, ino_t);
> > extern void vxfs_evict_inode(struct inode *);
> > extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
> > extern void vxfs_destroy_inode(struct inode *ip);
> > +extern int vxfs_ii_cache_init(void);
> > +extern void vxfs_ii_cache_destroy(void);
> > +
> >
> > /* vxfs_lookup.c */
> > extern const struct inode_operations vxfs_dir_inode_ops;
> > diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> > index 9b45ad7..73ac417 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -41,7 +41,7 @@
> > #include "vxfs_extern.h"
> >
> >
> > -struct kmem_cache *vxfs_inode_cachep;
> > +static struct kmem_cache *vxfs_inode_cachep;
> >
> >
> > #ifdef DIAGNOSTIC
> > @@ -428,3 +428,25 @@ void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> > {
> > kmem_cache_free(vxfs_inode_cachep, vip);
> > }
> > +
> > +
> > +int vxfs_ii_cache_init(void)
> > +{
> > + vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> > + sizeof(struct vxfs_inode_info), 0,
> > + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> > +
> > + return vxfs_inode_cachep ? 0 : -ENOMEM;
> > +}
> > +
> > +
> > +void vxfs_ii_cache_destroy(void)
> > +{
> > + /*
> > + * Make sure all delayed rcu free inodes are flushed before we
> > + * destroy cache.
> > + */
> > + rcu_barrier();
> > + kmem_cache_destroy(vxfs_inode_cachep);
> > +}
> > +
> > diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> > index 11a535a..7579500 100644
> > --- a/fs/freevxfs/vxfs_super.c
> > +++ b/fs/freevxfs/vxfs_super.c
> > @@ -306,29 +306,23 @@ MODULE_ALIAS("vxfs");
> > static int __init
> > vxfs_init(void)
> > {
> > - int rv;
> > + int rc = vxfs_ii_cache_init();
> >
> > - vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> > - sizeof(struct vxfs_inode_info), 0,
> > - SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> > - if (!vxfs_inode_cachep)
> > - return -ENOMEM;
> > - rv = register_filesystem(&vxfs_fs_type);
> > - if (rv < 0)
> > - kmem_cache_destroy(vxfs_inode_cachep);
> > - return rv;
> > + if (!rc) {
> > + rc = register_filesystem(&vxfs_fs_type);
> > + if (rc < 0)
> > + vxfs_ii_cache_destroy();
> > + }
> > + printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __func__, __DATE__, __TIME__, rc);
> > +
> > + return rc;
> > }
> >
> > static void __exit
> > vxfs_cleanup(void)
> > {
> > unregister_filesystem(&vxfs_fs_type);
> > - /*
> > - * Make sure all delayed rcu free inodes are flushed before we
> > - * destroy cache.
> > - */
> > - rcu_barrier();
> > - kmem_cache_destroy(vxfs_inode_cachep);
> > + vxfs_ii_cache_destroy();
> > }
> >
> > module_init(vxfs_init);
> > --
> > 1.7.3.4
> >
>
> > From 2c0008e9f2f4e62bb3e10eecad54e2a0140e0c4c Mon Sep 17 00:00:00 2001
> > From: KB <kb@sysmikro.com.pl>
> > Date: Wed, 25 May 2016 22:58:08 +0200
> > Subject: [PATCH 7/7] the credits
> >
> >
> > Signed-off-by: KB <kb@sysmikro.com.pl>
> > ---
> > fs/freevxfs/vxfs.h | 3 +++
> > fs/freevxfs/vxfs_fshead.c | 4 ++++
> > fs/freevxfs/vxfs_inode.c | 4 ++++
> > fs/freevxfs/vxfs_lookup.c | 4 ++++
> > fs/freevxfs/vxfs_super.c | 6 +++++-
> > 5 files changed, 20 insertions(+), 1 deletions(-)
> >
> > diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> > index 5dc8949..35f56b7 100644
> > --- a/fs/freevxfs/vxfs.h
> > +++ b/fs/freevxfs/vxfs.h
> > @@ -2,6 +2,9 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + * (c) 2016 Krzysztof Blaszkowski
> > + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> > index 67ca2f9..44b87d0 100644
> > --- a/fs/freevxfs/vxfs_fshead.c
> > +++ b/fs/freevxfs/vxfs_fshead.c
> > @@ -2,6 +2,10 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski
> > + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> > index 73ac417..4c8a625 100644
> > --- a/fs/freevxfs/vxfs_inode.c
> > +++ b/fs/freevxfs/vxfs_inode.c
> > @@ -2,6 +2,10 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski
> > + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> > index 8eacb27..173aeea 100644
> > --- a/fs/freevxfs/vxfs_lookup.c
> > +++ b/fs/freevxfs/vxfs_lookup.c
> > @@ -2,6 +2,10 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski
> > + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> > index 7579500..bd121aa 100644
> > --- a/fs/freevxfs/vxfs_super.c
> > +++ b/fs/freevxfs/vxfs_super.c
> > @@ -2,6 +2,10 @@
> > * Copyright (c) 2000-2001 Christoph Hellwig.
> > * All rights reserved.
> > *
> > + *
> > + * (c) 2016 Krzysztof Blaszkowski
> > + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> > + *
> > * Redistribution and use in source and binary forms, with or without
> > * modification, are permitted provided that the following conditions
> > * are met:
> > @@ -48,7 +52,7 @@
> > #include "vxfs_inode.h"
> >
> >
> > -MODULE_AUTHOR("Christoph Hellwig");
> > +MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
> > MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
> > MODULE_LICENSE("Dual BSD/GPL");
> >
> > --
> > 1.7.3.4
> >
>
>
> > 3531594148 32829 /usr/sprockets/bin/bw_map
> > 3973234498 518896 /usr/sprockets/bin/cifslist
> > 3973234498 518896 /usr/sprockets/bin/cifslogout
> > 4171014129 518904 /usr/sprockets/bin/cifsmount
> > 4171014129 518904 /usr/sprockets/bin/cifsumount
> > 256627809 1171456 /usr/sprockets/bin/convert
> > 4193697053 242843 /usr/sprockets/bin/createLicensingFiles
> > 2780783712 51 /usr/sprockets/bin/createSprocFile
> > 3285775584 825 /usr/sprockets/bin/dcexec
> > 4073641898 94 /usr/sprockets/bin/defaultResources
> > 4039074287 6610 /usr/sprockets/bin/disableNIS
> > 313350104 20480 /usr/sprockets/bin/dos2ux
> > 1872597524 65536 /usr/sprockets/bin/doschmod
> > 1872597524 65536 /usr/sprockets/bin/doscp
> > 1872597524 65536 /usr/sprockets/bin/dosdf
> > 1872597524 65536 /usr/sprockets/bin/doslib
> > 1872597524 65536 /usr/sprockets/bin/dosll
> > 1872597524 65536 /usr/sprockets/bin/dosls
> > 1872597524 65536 /usr/sprockets/bin/dosmkdir
> > 1872597524 65536 /usr/sprockets/bin/dosrm
> > 1872597524 65536 /usr/sprockets/bin/dosrmdir
> > 1968087462 7112 /usr/sprockets/bin/enableNIS
> > 3282246790 360 /usr/sprockets/bin/endexec
> > 2151751185 553 /usr/sprockets/bin/endsession
> > 3927613487 1115 /usr/sprockets/bin/env_var_sub
> > 3738550324 157 /usr/sprockets/bin/format_dos
> > 3888232633 172649 /usr/sprockets/bin/fppv
> > 2279585942 466 /usr/sprockets/bin/getHostname
> > 2946778792 5648 /usr/sprockets/bin/getSharedConnections
> > 3306388627 20480 /usr/sprockets/bin/ibmsync
> > 3041502972 28781 /usr/sprockets/bin/ipconfig700
> > 3113659230 391815 /usr/sprockets/bin/kpp
> > 908094753 24630 /usr/sprockets/bin/kxst
> > 1329462070 36864 /usr/sprockets/bin/lanload
> > 1015322628 36947 /usr/sprockets/bin/listener
> > 486757159 339968 /usr/sprockets/bin/lmgrd
> > 2620320940 339968 /usr/sprockets/bin/lmutil
> > 951644065 243039 /usr/sprockets/bin/mattrib
> > 951644065 243039 /usr/sprockets/bin/mbadblocks
> > 951644065 243039 /usr/sprockets/bin/mcd
> > 3650177936 951 /usr/sprockets/bin/mcheck
> > 514586869 56 /usr/sprockets/bin/mcomp
> > 951644065 243039 /usr/sprockets/bin/mcopy
> > 951644065 243039 /usr/sprockets/bin/mdel
> > 951644065 243039 /usr/sprockets/bin/mdeltree
> > 951644065 243039 /usr/sprockets/bin/mdir
> > 951644065 243039 /usr/sprockets/bin/mformat
> > 951644065 243039 /usr/sprockets/bin/minfo
> > 951644065 243039 /usr/sprockets/bin/mlabel
> > 951644065 243039 /usr/sprockets/bin/mmd
> > 951644065 243039 /usr/sprockets/bin/mmount
> > 951644065 243039 /usr/sprockets/bin/mmove
> > 951644065 243039 /usr/sprockets/bin/mpartition
> > 662030829 1478557 /usr/sprockets/bin/mpv
> > 951644065 243039 /usr/sprockets/bin/mrd
> > 951644065 243039 /usr/sprockets/bin/mread
> > 951644065 243039 /usr/sprockets/bin/mren
> > 3443865238 32829 /usr/sprockets/bin/msgintcpt
> > 951644065 243039 /usr/sprockets/bin/mtools
> > 951644065 243039 /usr/sprockets/bin/mtoolstest
> > 951644065 243039 /usr/sprockets/bin/mtype
> > 951644065 243039 /usr/sprockets/bin/mwrite
> > 1915353244 82 /usr/sprockets/bin/mxtar
> > 951644065 243039 /usr/sprockets/bin/mzip
> > 2033389047 379158 /usr/sprockets/bin/nmbd
> > 1043940798 32843 /usr/sprockets/bin/nsbuild
> > 421327339 32843 /usr/sprockets/bin/nsdump
> > 2156955828 32843 /usr/sprockets/bin/nsquery
> > 1030470949 28737 /usr/sprockets/bin/pciinfo
> > 889541250 61560 /usr/sprockets/bin/pcipeek
> > 1431205578 28737 /usr/sprockets/bin/pciprog
> > 3351126604 126976 /usr/sprockets/bin/pkunzip
> > 3351126604 126976 /usr/sprockets/bin/pkzip
> > 2166142790 53390 /usr/sprockets/bin/probeload
> > 694305221 41144 /usr/sprockets/bin/progflash
> > 1141035887 445257 /usr/sprockets/bin/pv
> > 974426301 3882 /usr/sprockets/bin/runnetscape
> > 1879287959 1801 /usr/sprockets/bin/running
> > 2273866242 74107 /usr/sprockets/bin/runroot
> > 2616587298 79 /usr/sprockets/bin/runTouch
> > 4222109660 875 /usr/sprockets/bin/samba
> > 1912440105 24633 /usr/sprockets/bin/sbscrsvr
> > 2558012300 3904 /usr/sprockets/bin/screensaverControl
> > 4256537430 1780 /usr/sprockets/bin/sd-set_parms
> > 1151924416 688 /usr/sprockets/bin/sendSignal
> > 2744646624 32829 /usr/sprockets/bin/sessionDisallow
> > 1227674200 1346161 /usr/sprockets/bin/sessionMgr
> > 3332668870 98791 /usr/sprockets/bin/sessionWrapper
> > 1477797090 82487 /usr/sprockets/bin/setlight
> > 3759253613 1122 /usr/sprockets/bin/sharity
> > 3313588847 3448000 /usr/sprockets/bin/sharityd
> > 1569390236 24630 /usr/sprockets/bin/shmLock
> > 3791448153 317300 /usr/sprockets/bin/smbclient
> > 1018298877 506532 /usr/sprockets/bin/smbd
> > 4009501079 45140 /usr/sprockets/bin/smtpclient
> > 991996913 144424 /usr/sprockets/bin/starhw
> > 3124681867 4311 /usr/sprockets/bin/startVNC
> > 1468091312 919 /usr/sprockets/bin/startVNCviewer
> > 304853428 1994350 /usr/sprockets/bin/sw_admin
> > 304853428 1994350 /usr/sprockets/bin/sw_autoinstall
> > 1455142555 123406 /usr/sprockets/bin/sw_copyfdset
> > 2157175922 111102 /usr/sprockets/bin/sw_depot2bin
> > 304853428 1994350 /usr/sprockets/bin/sw_install
> > 304853428 1994350 /usr/sprockets/bin/sw_list
> > 1842505403 7100 /usr/sprockets/bin/sw_makefdset
> > 304853428 1994350 /usr/sprockets/bin/sw_remove
> > 1743298644 2342 /usr/sprockets/bin/sw_rmprevious
> > 1582083858 20548 /usr/sprockets/bin/sw_vendorfdset
> > 178332129 1794 /usr/sprockets/bin/sysInfo
> > 3657811479 1574 /usr/sprockets/bin/tgz
> > 4018370132 36951 /usr/sprockets/bin/tp_license
> > 1649141155 11843 /usr/sprockets/bin/updsharitycfg
> > 2980018004 20480 /usr/sprockets/bin/ux2dos
> > 3745508150 1318 /usr/sprockets/bin/uz
> > 1348652714 32864 /usr/sprockets/bin/vncpasswd
> > 4059637159 12757 /usr/sprockets/bin/vncserver
> > 4128771573 366263 /usr/sprockets/bin/vncviewer
> > 285011189 1526819 /usr/sprockets/bin/vp
> > 589630079 387 /usr/sprockets/bin/vpexit
> > 528762950 1132 /usr/sprockets/bin/xcopy
> > 1793380080 521816 /usr/sprockets/bin/xscreensaver
> > 24739470 145832 /usr/sprockets/bin/xscreensaver-command
> > 4079099643 2167483 /usr/sprockets/bin/Xvnc
> > 49651643 41091 /usr/sprockets/bin/yakdebug
> > 2578809639 127914 /usr/sprockets/bin/yakhw
> > 306877946 189649 /usr/sprockets/bin/yakserver
>
>
>
--
Krzysztof Blaszkowski
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: freevxfs
2016-05-25 21:27 freevxfs Krzysztof Błaszkowski
@ 2016-05-26 11:50 ` Carlos Maiolino
2016-05-26 14:44 ` freevxfs Krzysztof Błaszkowski
0 siblings, 1 reply; 8+ messages in thread
From: Carlos Maiolino @ 2016-05-26 11:50 UTC (permalink / raw)
To: linux-fsdevel
On Wed, May 25, 2016 at 11:27:27PM +0200, Krzysztof Błaszkowski wrote:
> Hi,
>
> Please find included patchset which addresses all major features we have
> discussed (unless I forgot about something).
>
Hi Krzysztof,
please send the patches one-by one, inlined in the e-mail message, not attached
to the e-mail, mainly all of them attached to a single message.
You can use git send-email to send the patches.
See: Documentation/SubmittingPatches
Cheers
> I verified correctness of operation with my regression tests and HP-UX's
> vxfs image. No difference spotted. However I can't do this with SCO
> image because I do not have such. I reckon that it is highly possible
> that SCO image will work as usual because the only difference is data
> endianess and offset of super block.
>
> I included for reference these scripts just in case one is curious.
> (chksum8-sorted.log comes from hp-ux's cksum)
>
> Regards,
> --
> Krzysztof Blaszkowski
> From 3d3b4e1ed5df014ae191e0566ff86a17d7d9ac05 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Wed, 25 May 2016 21:50:11 +0200
> Subject: [PATCH 1/7] kconfig note
>
>
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
> fs/freevxfs/Kconfig | 10 +++++++++-
> 1 files changed, 9 insertions(+), 1 deletions(-)
>
> diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig
> index 8dc1cd5..a4c9075 100644
> --- a/fs/freevxfs/Kconfig
> +++ b/fs/freevxfs/Kconfig
> @@ -5,12 +5,20 @@ config VXFS_FS
> FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
> file system format. VERITAS VxFS(TM) is the standard file system
> of SCO UnixWare (and possibly others) and optionally available
> - for Sunsoft Solaris, HP-UX and many other operating systems.
> + for Sunsoft Solaris, HP-UX and many other operating systems. However
> + these particular OS implementations of vxfs may differ in on-disk
> + data endianess and/or superblock offset. The vxfs module has been
> + tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.)
> Currently only readonly access is supported.
>
> NOTE: the file system type as used by mount(1), mount(2) and
> fstab(5) is 'vxfs' as it describes the file system format, not
> the actual driver.
>
> + There is a userspace utility for HP-UX logical volumes which makes
> + creating HP-UX logical volumes easy from HP-UX disk block device file
> + or regular file with image of the disk. See:
> + https://sourceforge.net/projects/linux-vxfs/
> +
> To compile this as a module, choose M here: the module will be
> called freevxfs. If unsure, say N.
> --
> 1.7.3.4
>
> From c617f6bceedc2f68c62e7432f12b59124bab34f7 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Wed, 25 May 2016 22:12:05 +0200
> Subject: [PATCH 2/7] cpu endian vs file system endian
>
>
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
> fs/freevxfs/vxfs.h | 25 +++++++++++-
> fs/freevxfs/vxfs_bmap.c | 24 ++++++-----
> fs/freevxfs/vxfs_fshead.c | 25 +++++++++++-
> fs/freevxfs/vxfs_inode.c | 61 +++++++++++++++++++++++++++-
> fs/freevxfs/vxfs_inode.h | 8 ++--
> fs/freevxfs/vxfs_lookup.c | 15 ++++++-
> fs/freevxfs/vxfs_olt.c | 15 ++++---
> fs/freevxfs/vxfs_super.c | 97 ++++++++++++++++++++++++++++++++-------------
> 8 files changed, 215 insertions(+), 55 deletions(-)
>
> diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> index c8a9265..5dc8949 100644
> --- a/fs/freevxfs/vxfs.h
> +++ b/fs/freevxfs/vxfs.h
> @@ -152,7 +152,7 @@ struct vxfs_sb {
> /*
> * Actually much more...
> */
> -};
> +} __packed;
>
>
> /*
> @@ -168,9 +168,32 @@ struct vxfs_sb_info {
> ino_t vsi_fshino; /* fileset header inode */
> daddr_t vsi_oltext; /* OLT extent */
> daddr_t vsi_oltsize; /* OLT size */
> + int byte_order;
> + int silent;
> +};
> +
> +enum {
> + BO_LE = 1,
> + BO_BE
> };
>
>
> +static inline u32 fs32_to_cpu(int bo, u32 a)
> +{
> + return (bo == BO_BE) ? be32_to_cpu(a) : le32_to_cpu(a);
> +}
> +
> +static inline u16 fs16_to_cpu(int bo, u16 a)
> +{
> + return (bo == BO_BE) ? be16_to_cpu(a) : le16_to_cpu(a);
> +}
> +
> +static inline u64 fs64_to_cpu(int bo, u64 a)
> +{
> + return (bo == BO_BE) ? be64_to_cpu(a) : le64_to_cpu(a);
> +}
> +
> +
> /*
> * File modes. File types above 0xf000 are vxfs internal only, they should
> * not be passed back to higher levels of the system. vxfs file types must
> diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
> index f86fd3c..95afd98 100644
> --- a/fs/freevxfs/vxfs_bmap.c
> +++ b/fs/freevxfs/vxfs_bmap.c
> @@ -92,7 +92,8 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
> goto fail_buf;
>
> indir = (u32 *)buf->b_data;
> - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
> + bno = fs32_to_cpu(VXFS_SBI(sb)->byte_order,
> + indir[(bn/indsize) % (indsize*bn)]) + (bn % indsize);
>
> brelse(buf);
> return bno;
> @@ -130,6 +131,7 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
> struct buffer_head *bp = NULL;
> daddr_t pblock = 0;
> int i;
> + int bo = VXFS_SBI(ip->i_sb)->byte_order;
>
> for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
> struct vxfs_typed *typ;
> @@ -142,24 +144,24 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
>
> typ = ((struct vxfs_typed *)bp->b_data) +
> (i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
> - off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
> + off = fs64_to_cpu(bo, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
>
> if (block < off) {
> brelse(bp);
> continue;
> }
>
> - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
> + switch ((u_int32_t)(fs64_to_cpu(bo, typ->vt_hdr) >> VXFS_TYPED_TYPESHIFT)) {
> case VXFS_TYPED_INDIRECT:
> - pblock = vxfs_bmap_indir(ip, typ->vt_block,
> - typ->vt_size, block - off);
> + pblock = vxfs_bmap_indir(ip, fs32_to_cpu(bo, typ->vt_block),
> + fs32_to_cpu(bo, typ->vt_size), block - off);
> if (pblock == -2)
> break;
> goto out;
> case VXFS_TYPED_DATA:
> - if ((block - off) >= typ->vt_size)
> + if ((block - off) >= fs32_to_cpu(bo, typ->vt_size))
> break;
> - pblock = (typ->vt_block + block - off);
> + pblock = fs32_to_cpu(bo, typ->vt_block) + block - off;
> goto out;
> case VXFS_TYPED_INDIRECT_DEV4:
> case VXFS_TYPED_DATA_DEV4: {
> @@ -168,12 +170,14 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
>
> printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
> printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
> - (unsigned long long) typ4->vd4_block,
> - (unsigned long long) typ4->vd4_size,
> - typ4->vd4_dev);
> + (unsigned long long) fs64_to_cpu(bo, typ4->vd4_block),
> + (unsigned long long) fs64_to_cpu(bo, typ4->vd4_size),
> + fs32_to_cpu(bo, typ4->vd4_dev));
> goto fail;
> }
> default:
> + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__, __LINE__,
> + fs64_to_cpu(bo, typ->vt_hdr));
> BUG();
> }
> brelse(bp);
> diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> index c9a6a94..6cbdde7 100644
> --- a/fs/freevxfs/vxfs_fshead.c
> +++ b/fs/freevxfs/vxfs_fshead.c
> @@ -60,6 +60,29 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
> }
> #endif
>
> +#define VXFS_FS32(field1, field2) fhp->field1 = fs32_to_cpu(bo, dbh->field2)
> +static inline void dbh2fhp(struct vxfs_fsh *fhp, void *_dbh, int bo)
> +{
> + struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
> +
> + VXFS_FS32(fsh_version, fsh_version);
> + VXFS_FS32(fsh_fsindex, fsh_fsindex);
> + VXFS_FS32(fsh_time, fsh_time);
> + VXFS_FS32(fsh_utime, fsh_utime);
> + VXFS_FS32(fsh_extop, fsh_extop);
> + VXFS_FS32(fsh_ninodes, fsh_ninodes);
> + VXFS_FS32(fsh_nau, fsh_nau);
> + VXFS_FS32(fsh_old_ilesize, fsh_old_ilesize);
> + VXFS_FS32(fsh_dflags, fsh_dflags);
> + VXFS_FS32(fsh_quota, fsh_quota);
> + VXFS_FS32(fsh_maxinode, fsh_maxinode);
> + VXFS_FS32(fsh_iauino, fsh_iauino);
> + VXFS_FS32(fsh_ilistino[0], fsh_ilistino[0]);
> + VXFS_FS32(fsh_ilistino[1], fsh_ilistino[1]);
> + VXFS_FS32(fsh_lctino, fsh_lctino);
> +}
> +
> +
> /**
> * vxfs_getfsh - read fileset header into memory
> * @ip: the (fake) fileset header inode
> @@ -83,7 +106,7 @@ vxfs_getfsh(struct inode *ip, int which)
>
> if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
> goto out;
> - memcpy(fhp, bp->b_data, sizeof(*fhp));
> + dbh2fhp(fhp, bp->b_data, VXFS_SBI(ip->i_sb)->byte_order);
>
> put_bh(bp);
> return (fhp);
> diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> index 363e3ae..53b8757 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -67,6 +67,63 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
> }
> #endif
>
> +#define VXFS_FS32(field1, field2) vip->field1 = fs32_to_cpu(bo, dip->field2)
> +#define VXFS_FS64(field1, field2) vip->field1 = fs64_to_cpu(bo, dip->field2)
> +#define VXFS_FS16(field1, field2) vip->field1 = fs16_to_cpu(bo, dip->field2)
> +
> +static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip, int bo)
> +{
> + int j;
> +
> + VXFS_FS32(vdi_mode, vdi_mode);
> + VXFS_FS32(vdi_nlink, vdi_nlink);
> + VXFS_FS32(vdi_uid, vdi_uid);
> + VXFS_FS32(vdi_gid, vdi_gid);
> + VXFS_FS64(vdi_size, vdi_size);
> + VXFS_FS32(vdi_atime, vdi_atime);
> + VXFS_FS32(vdi_autime, vdi_autime);
> + VXFS_FS32(vdi_mtime, vdi_mtime);
> + VXFS_FS32(vdi_mutime, vdi_mutime);
> + VXFS_FS32(vdi_ctime, vdi_ctime);
> + VXFS_FS32(vdi_cutime, vdi_cutime);
> + vip->vdi_aflags = dip->vdi_aflags;
> + vip->vdi_orgtype = dip->vdi_orgtype;
> + VXFS_FS16(vdi_eopflags, vdi_eopflags);
> + VXFS_FS32(vdi_eopdata, vdi_eopdata);
> +
> + VXFS_FS32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
> + VXFS_FS32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
> + VXFS_FS32(vdi_blocks, vdi_blocks);
> + VXFS_FS32(vdi_gen, vdi_gen);
> + VXFS_FS64(vdi_version, vdi_version);
> +
> + switch (dip->vdi_orgtype) {
> + case VXFS_ORG_EXT4:
> + VXFS_FS32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
> + VXFS_FS32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
> + for (j = 0; j < VXFS_NIADDR; j++) {
> + VXFS_FS32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
> + }
> + for (j = 0; j < VXFS_NDADDR; j++) {
> + VXFS_FS32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
> + VXFS_FS32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
> + }
> + break;
> + case VXFS_ORG_IMMED:
> + memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
> + break;
> + case VXFS_ORG_TYPED:
> + for (j = 0; j < VXFS_NTYPED; j++) {
> + VXFS_FS64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
> + VXFS_FS32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
> + VXFS_FS32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
> + }
> + break;
> + };
> +
> + VXFS_FS32(vdi_iattrino, vdi_iattrino);
> +}
> +
>
> /**
> * vxfs_blkiget - find inode based on extent #
> @@ -101,7 +158,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
> if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> goto fail;
> dip = (struct vxfs_dinode *)(bp->b_data + offset);
> - memcpy(vip, dip, sizeof(*vip));
> + dip2vip_cpy(vip, dip, VXFS_SBI(sbp)->byte_order);
> #ifdef DIAGNOSTIC
> vxfs_dumpi(vip, ino);
> #endif
> @@ -143,7 +200,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
> if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
> goto fail;
> dip = (struct vxfs_dinode *)(kaddr + offset);
> - memcpy(vip, dip, sizeof(*vip));
> + dip2vip_cpy(vip, dip, VXFS_SBI(ilistp->i_sb)->byte_order);
> #ifdef DIAGNOSTIC
> vxfs_dumpi(vip, ino);
> #endif
> diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
> index 240aeb1..9a2c376 100644
> --- a/fs/freevxfs/vxfs_inode.h
> +++ b/fs/freevxfs/vxfs_inode.h
> @@ -77,13 +77,13 @@ struct vxfs_ext4 {
> vx_daddr_t extent; /* Extent number */
> int32_t size; /* Size of extent */
> } ve4_direct[VXFS_NDADDR];
> -};
> +} __packed;
>
> struct vxfs_typed {
> u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> vx_daddr_t vt_block; /* Extent block */
> int32_t vt_size; /* Size in blocks */
> -};
> +} __packed;
>
> struct vxfs_typed_dev4 {
> u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
> @@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
> u_int64_t vd4_size; /* Size in blocks */
> int32_t vd4_dev; /* Device ID */
> u_int32_t __pad1;
> -};
> +} __packed;
>
> /*
> * The inode as contained on the physical device.
> @@ -134,7 +134,7 @@ struct vxfs_dinode {
> struct vxfs_typed typed[VXFS_NTYPED];
> } vdi_org;
> u_int32_t vdi_iattrino;
> -};
> +} __packed;
>
> #define vdi_rdev vdi_ftarea.rdev
> #define vdi_dotdot vdi_ftarea.dotdot
> diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> index 99c7f0a..cea158a 100644
> --- a/fs/freevxfs/vxfs_lookup.c
> +++ b/fs/freevxfs/vxfs_lookup.c
> @@ -96,6 +96,15 @@ vxfs_next_entry(struct vxfs_direct *de)
> return ((struct vxfs_direct *)((char*)de + de->d_reclen));
> }
>
> +/*
> + * VXFS_dirblk_ovh is the overhead of a specific dirblock.
> + */
> +static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
> +{
> + return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> +}
> +
> +
> /**
> * vxfs_find_entry - find a mathing directory entry for a dentry
> * @ip: directory inode
> @@ -242,6 +251,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
> u_long bsize = sbp->s_blocksize;
> u_long page, npages, block, pblocks, nblocks, offset;
> loff_t pos;
> + int bo = VXFS_SBI(sbp)->byte_order;
> +
>
> if (ctx->pos == 0) {
> if (!dir_emit_dot(fp, ctx))
> @@ -297,8 +308,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
>
> offset = (char *)de - kaddr;
> ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> - if (!dir_emit(ctx, de->d_name, de->d_namelen,
> - de->d_ino, DT_UNKNOWN)) {
> + if (!dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
> + fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN)) {
> vxfs_put_page(pp);
> return 0;
> }
> diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
> index 0495008..6b50188 100644
> --- a/fs/freevxfs/vxfs_olt.c
> +++ b/fs/freevxfs/vxfs_olt.c
> @@ -43,14 +43,14 @@ static inline void
> vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
> {
> BUG_ON(infp->vsi_fshino);
> - infp->vsi_fshino = fshp->olt_fsino[0];
> + infp->vsi_fshino = fs32_to_cpu(infp->byte_order, fshp->olt_fsino[0]);
> }
>
> static inline void
> vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
> {
> BUG_ON(infp->vsi_iext);
> - infp->vsi_iext = ilistp->olt_iext[0];
> + infp->vsi_iext = fs32_to_cpu(infp->byte_order, ilistp->olt_iext[0]);
> }
>
> static inline u_long
> @@ -80,6 +80,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> struct buffer_head *bp;
> struct vxfs_olt *op;
> char *oaddr, *eaddr;
> + int bo = infp->byte_order;
>
>
> bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
> @@ -87,7 +88,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> goto fail;
>
> op = (struct vxfs_olt *)bp->b_data;
> - if (op->olt_magic != VXFS_OLT_MAGIC) {
> + if (fs32_to_cpu(bo, op->olt_magic) != VXFS_OLT_MAGIC) {
> printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
> goto fail;
> }
> @@ -102,14 +103,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> goto fail;
> }
>
> - oaddr = bp->b_data + op->olt_size;
> + oaddr = bp->b_data + fs32_to_cpu(bo, op->olt_size);
> eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
>
> while (oaddr < eaddr) {
> struct vxfs_oltcommon *ocp =
> (struct vxfs_oltcommon *)oaddr;
>
> - switch (ocp->olt_type) {
> + switch (fs32_to_cpu(bo, ocp->olt_type)) {
> case VXFS_OLT_FSHEAD:
> vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
> break;
> @@ -118,11 +119,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
> break;
> }
>
> - oaddr += ocp->olt_size;
> + oaddr += fs32_to_cpu(bo, ocp->olt_size);
> }
>
> brelse(bp);
> - return 0;
> + return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
>
> fail:
> brelse(bp);
> diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> index 7ca8c75..6a19802 100644
> --- a/fs/freevxfs/vxfs_super.c
> +++ b/fs/freevxfs/vxfs_super.c
> @@ -109,14 +109,15 @@ static int
> vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
> {
> struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb);
> + struct vxfs_sb *raw_sb = infp->vsi_raw;
>
> bufp->f_type = VXFS_SUPER_MAGIC;
> bufp->f_bsize = dentry->d_sb->s_blocksize;
> - bufp->f_blocks = infp->vsi_raw->vs_dsize;
> - bufp->f_bfree = infp->vsi_raw->vs_free;
> + bufp->f_blocks = fs32_to_cpu(infp->byte_order, raw_sb->vs_dsize);
> + bufp->f_bfree = fs32_to_cpu(infp->byte_order, raw_sb->vs_free);
> bufp->f_bavail = 0;
> bufp->f_files = 0;
> - bufp->f_ffree = infp->vsi_raw->vs_ifree;
> + bufp->f_ffree = fs32_to_cpu(infp->byte_order, raw_sb->vs_ifree);
> bufp->f_namelen = VXFS_NAMELEN;
>
> return 0;
> @@ -129,6 +130,46 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
> return 0;
> }
>
> +
> +static int vxfs_try_sb_magic(struct super_block *sbp, int blk, u32 magic)
> +{
> + struct buffer_head *bp;
> + struct vxfs_sb *rsbp;
> + struct vxfs_sb_info *infp = VXFS_SBI(sbp);
> + int rc = -ENOMEM;
> +
> + bp = sb_bread(sbp, blk);
> + do {
> + if (!bp || !buffer_mapped(bp)) {
> + if (!infp->silent) {
> + printk(KERN_WARNING "vxfs: unable to read"
> + " disk superblock at %d\n", blk);
> + }
> + break;
> + }
> +
> + rc = -EINVAL;
> + rsbp = (struct vxfs_sb *)bp->b_data;
> + if (rsbp->vs_magic != magic) {
> + if (!infp->silent)
> + printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
> + break;
> + }
> +
> + rc = 0;
> + infp->vsi_raw = rsbp;
> + infp->vsi_bp = bp;
> + } while (0);
> +
> + if (rc) {
> + infp->vsi_raw = NULL;
> + infp->vsi_bp = NULL;
> + brelse(bp);
> + }
> +
> + return rc;
> +}
> +
> /**
> * vxfs_read_super - read superblock into memory and initialize filesystem
> * @sbp: VFS superblock (to fill)
> @@ -149,10 +190,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> {
> struct vxfs_sb_info *infp;
> struct vxfs_sb *rsbp;
> - struct buffer_head *bp = NULL;
> u_long bsize;
> struct inode *root;
> int ret = -EINVAL;
> + u32 j;
>
> sbp->s_flags |= MS_RDONLY;
>
> @@ -162,48 +203,47 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
> return -ENOMEM;
> }
>
> + infp->silent = silent;
> bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
> if (!bsize) {
> printk(KERN_WARNING "vxfs: unable to set blocksize\n");
> goto out;
> }
>
> - bp = sb_bread(sbp, 1);
> - if (!bp || !buffer_mapped(bp)) {
> - if (!silent) {
> - printk(KERN_WARNING
> - "vxfs: unable to read disk superblock\n");
> + sbp->s_fs_info = infp;
> + do {
> + if (!vxfs_try_sb_magic(sbp, 1, cpu_to_le32(VXFS_SUPER_MAGIC))) {
> + infp->byte_order = BO_LE; /* SCO */
> + break;
> + }
> +
> + if (!vxfs_try_sb_magic(sbp, 8, cpu_to_be32(VXFS_SUPER_MAGIC))) {
> + infp->byte_order = BO_BE; /* HP-UX pa-risc likely */
> + break;
> }
> - goto out;
> - }
>
> - rsbp = (struct vxfs_sb *)bp->b_data;
> - if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
> - if (!silent)
> - printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
> goto out;
> - }
> + } while (0);
>
> - if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
> - printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
> - rsbp->vs_version);
> + rsbp = infp->vsi_raw;
> + j = fs32_to_cpu(infp->byte_order, rsbp->vs_version);
> + if ((j < 2 || j > 4) && !silent) {
> + printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
> goto out;
> }
>
> #ifdef DIAGNOSTIC
> - printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
> + printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
> printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
> #endif
>
> - sbp->s_magic = rsbp->vs_magic;
> - sbp->s_fs_info = infp;
> + sbp->s_magic = fs32_to_cpu(infp->byte_order, rsbp->vs_magic);
>
> - infp->vsi_raw = rsbp;
> - infp->vsi_bp = bp;
> - infp->vsi_oltext = rsbp->vs_oltext[0];
> - infp->vsi_oltsize = rsbp->vs_oltsize;
> + infp->vsi_oltext = fs32_to_cpu(infp->byte_order, rsbp->vs_oltext[0]);
> + infp->vsi_oltsize = fs32_to_cpu(infp->byte_order, rsbp->vs_oltsize);
>
> - if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
> + j = fs32_to_cpu(infp->byte_order, rsbp->vs_bsize);
> + if (!sb_set_blocksize(sbp, j)) {
> printk(KERN_WARNING "vxfs: unable to set final block size\n");
> goto out;
> }
> @@ -237,7 +277,8 @@ out_free_ilist:
> vxfs_put_fake_inode(infp->vsi_ilist);
> vxfs_put_fake_inode(infp->vsi_stilist);
> out:
> - brelse(bp);
> + if (infp->vsi_bp)
> + brelse(infp->vsi_bp);
> kfree(infp);
> return ret;
> }
> --
> 1.7.3.4
>
> From b95e9b749b85be347c953ce33d2b3c5dde4e56d6 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Wed, 25 May 2016 22:13:20 +0200
> Subject: [PATCH 3/7] missing kfree and kfree on kmem_cache obj
>
>
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
> fs/freevxfs/vxfs_extern.h | 1 +
> fs/freevxfs/vxfs_fshead.c | 8 +++++---
> fs/freevxfs/vxfs_inode.c | 5 +++++
> 3 files changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> index 881aa3d..0a3ff86 100644
> --- a/fs/freevxfs/vxfs_extern.h
> +++ b/fs/freevxfs/vxfs_extern.h
> @@ -64,6 +64,7 @@ extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t
> extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
> extern struct inode * vxfs_iget(struct super_block *, ino_t);
> extern void vxfs_evict_inode(struct inode *);
> +extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
>
> /* vxfs_lookup.c */
> extern const struct inode_operations vxfs_dir_inode_ops;
> diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> index 6cbdde7..67ca2f9 100644
> --- a/fs/freevxfs/vxfs_fshead.c
> +++ b/fs/freevxfs/vxfs_fshead.c
> @@ -183,7 +183,7 @@ vxfs_read_fshead(struct super_block *sbp)
> infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
> if (!infp->vsi_stilist) {
> printk(KERN_ERR "vxfs: unable to get structural list inode\n");
> - kfree(tip);
> + vxfs_inode_info_free(tip);
> goto out_free_pfp;
> }
> if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
> @@ -198,7 +198,7 @@ vxfs_read_fshead(struct super_block *sbp)
> infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
> if (!infp->vsi_ilist) {
> printk(KERN_ERR "vxfs: unable to get inode list inode\n");
> - kfree(tip);
> + vxfs_inode_info_free(tip);
> goto out_iput_stilist;
> }
> if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
> @@ -206,6 +206,8 @@ vxfs_read_fshead(struct super_block *sbp)
> VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
> goto out_iput_ilist;
> }
> + kfree(pfp);
> + kfree(sfp);
>
> return 0;
>
> @@ -221,6 +223,6 @@ vxfs_read_fshead(struct super_block *sbp)
> iput(infp->vsi_fship);
> return -EINVAL;
> out_free_fship:
> - kfree(vip);
> + vxfs_inode_info_free(vip);
> return -EINVAL;
> }
> diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> index 53b8757..16d8d27 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -415,3 +415,8 @@ vxfs_evict_inode(struct inode *ip)
> clear_inode(ip);
> call_rcu(&ip->i_rcu, vxfs_i_callback);
> }
> +
> +void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> +{
> + kmem_cache_free(vxfs_inode_cachep, vip);
> +}
> --
> 1.7.3.4
>
> From e4979c6a29eb79d59d8bc2eca9acc0d2b416780f Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Wed, 25 May 2016 22:15:20 +0200
> Subject: [PATCH 4/7] super_operations.destroy_inode
>
>
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
> fs/freevxfs/vxfs_extern.h | 1 +
> fs/freevxfs/vxfs_inode.c | 16 ++++++++++++----
> fs/freevxfs/vxfs_super.c | 1 +
> 3 files changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> index 0a3ff86..4d8298b 100644
> --- a/fs/freevxfs/vxfs_extern.h
> +++ b/fs/freevxfs/vxfs_extern.h
> @@ -65,6 +65,7 @@ extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
> extern struct inode * vxfs_iget(struct super_block *, ino_t);
> extern void vxfs_evict_inode(struct inode *);
> extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
> +extern void vxfs_destroy_inode(struct inode *ip);
>
> /* vxfs_lookup.c */
> extern const struct inode_operations vxfs_dir_inode_ops;
> diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> index 16d8d27..9b45ad7 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -397,7 +397,15 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
> static void vxfs_i_callback(struct rcu_head *head)
> {
> struct inode *inode = container_of(head, struct inode, i_rcu);
> - kmem_cache_free(vxfs_inode_cachep, inode->i_private);
> + void *priv = inode->i_private;
> +
> + inode->i_private = NULL;
> + kmem_cache_free(vxfs_inode_cachep, priv);
> +}
> +
> +void vxfs_destroy_inode(struct inode *ip)
> +{
> + call_rcu(&ip->i_rcu, vxfs_i_callback);
> }
>
> /**
> @@ -405,17 +413,17 @@ static void vxfs_i_callback(struct rcu_head *head)
> * @ip: inode to discard.
> *
> * Description:
> - * vxfs_evict_inode() is called on the final iput and frees the private
> - * inode area.
> + * vxfs_evict_inode() is called on the final iput
> */
> void
> vxfs_evict_inode(struct inode *ip)
> {
> truncate_inode_pages_final(&ip->i_data);
> + invalidate_inode_buffers(ip);
> clear_inode(ip);
> - call_rcu(&ip->i_rcu, vxfs_i_callback);
> }
>
> +
> void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> {
> kmem_cache_free(vxfs_inode_cachep, vip);
> diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> index 6a19802..11a535a 100644
> --- a/fs/freevxfs/vxfs_super.c
> +++ b/fs/freevxfs/vxfs_super.c
> @@ -59,6 +59,7 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *);
> static int vxfs_remount(struct super_block *, int *, char *);
>
> static const struct super_operations vxfs_super_ops = {
> + .destroy_inode = vxfs_destroy_inode,
> .evict_inode = vxfs_evict_inode,
> .put_super = vxfs_put_super,
> .statfs = vxfs_statfs,
> --
> 1.7.3.4
>
> From 4a6ae0e351b6046367bbd2939547f292ed2b6e47 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Wed, 25 May 2016 22:28:37 +0200
> Subject: [PATCH 5/7] refactoring of vxfs_readir() and find_entry()
>
>
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
> fs/freevxfs/vxfs_lookup.c | 267 +++++++++++++++++++++------------------------
> 1 files changed, 124 insertions(+), 143 deletions(-)
>
> diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> index cea158a..8eacb27 100644
> --- a/fs/freevxfs/vxfs_lookup.c
> +++ b/fs/freevxfs/vxfs_lookup.c
> @@ -61,48 +61,6 @@ const struct file_operations vxfs_dir_operations = {
> .iterate = vxfs_readdir,
> };
>
> -
> -static inline u_long
> -dir_pages(struct inode *inode)
> -{
> - return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
> -}
> -
> -static inline u_long
> -dir_blocks(struct inode *ip)
> -{
> - u_long bsize = ip->i_sb->s_blocksize;
> - return (ip->i_size + bsize - 1) & ~(bsize - 1);
> -}
> -
> -/*
> - * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
> - *
> - * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
> - */
> -static inline int
> -vxfs_match(int len, const char * const name, struct vxfs_direct *de)
> -{
> - if (len != de->d_namelen)
> - return 0;
> - if (!de->d_ino)
> - return 0;
> - return !memcmp(name, de->d_name, len);
> -}
> -
> -static inline struct vxfs_direct *
> -vxfs_next_entry(struct vxfs_direct *de)
> -{
> - return ((struct vxfs_direct *)((char*)de + de->d_reclen));
> -}
> -
> -/*
> - * VXFS_dirblk_ovh is the overhead of a specific dirblock.
> - */
> -static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
> -{
> - return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> -}
>
>
> /**
> @@ -122,50 +80,65 @@ static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
> static struct vxfs_direct *
> vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
> {
> - u_long npages, page, nblocks, pblocks, block;
> - u_long bsize = ip->i_sb->s_blocksize;
> - const char *name = dp->d_name.name;
> - int namelen = dp->d_name.len;
> -
> - npages = dir_pages(ip);
> - nblocks = dir_blocks(ip);
> - pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
> -
> - for (page = 0; page < npages; page++) {
> - caddr_t kaddr;
> - struct page *pp;
> -
> - pp = vxfs_get_page(ip->i_mapping, page);
> - if (IS_ERR(pp))
> - continue;
> - kaddr = (caddr_t)page_address(pp);
> -
> - for (block = 0; block <= nblocks && block <= pblocks; block++) {
> - caddr_t baddr, limit;
> - struct vxfs_dirblk *dbp;
> - struct vxfs_direct *de;
> -
> - baddr = kaddr + (block * bsize);
> - limit = baddr + bsize - VXFS_DIRLEN(1);
> -
> - dbp = (struct vxfs_dirblk *)baddr;
> - de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
> -
> - for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
> - if (!de->d_reclen)
> - break;
> - if (!de->d_ino)
> - continue;
> - if (vxfs_match(namelen, name, de)) {
> - *ppp = pp;
> - return (de);
> - }
> + u_long bsize = ip->i_sb->s_blocksize;
> + const char *name = dp->d_name.name;
> + int namelen = dp->d_name.len;
> + loff_t limit = VXFS_DIRROUND(ip->i_size);
> + struct vxfs_direct *de_exit = NULL;
> + loff_t pos = 0;
> + int bo = VXFS_SBI(ip->i_sb)->byte_order;
> +
> + while (pos < limit) {
> + struct page *pp;
> + char *kaddr;
> + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> +
> + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> + if (IS_ERR(pp)) {
> + return NULL;
> + }
> + kaddr = (char *)page_address(pp);
> +
> + while (pg_ofs < PAGE_SIZE && pos < limit) {
> + struct vxfs_direct *de;
> +
> + if ((pos & (bsize - 1)) < 4) {
> + struct vxfs_dirblk *dbp =
> + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
> + int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> +
> + pos += overhead;
> + pg_ofs += overhead;
> + }
> + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> +
> + if (!de->d_reclen) {
> + pos += bsize - 1;
> + pos &= ~(bsize - 1);
> + break;
> + }
> +
> + pg_ofs += fs16_to_cpu(bo, de->d_reclen);
> + pos += fs16_to_cpu(bo, de->d_reclen);
> + if (!de->d_ino) {
> + continue;
> + }
> +
> + if (namelen != fs16_to_cpu(bo, de->d_namelen))
> + continue;
> + if (!memcmp(name, de->d_name, namelen)) {
> + *ppp = pp;
> + de_exit = de;
> + break;
> }
> }
> - vxfs_put_page(pp);
> + if (!de_exit)
> + vxfs_put_page(pp);
> + else
> + break;
> }
>
> - return NULL;
> + return de_exit;
> }
>
> /**
> @@ -185,15 +158,17 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
> {
> struct vxfs_direct *de;
> struct page *pp;
> - ino_t ino = 0;
> + ino_t ino = 0;
>
> de = vxfs_find_entry(dip, dp, &pp);
> if (de) {
> - ino = de->d_ino;
> + int bo = VXFS_SBI(dip->i_sb)->byte_order;
> +
> + ino = fs32_to_cpu(bo, de->d_ino);
> kunmap(pp);
> page_cache_release(pp);
> }
> -
> +
> return (ino);
> }
>
> @@ -225,8 +200,8 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
> ip = vxfs_iget(dip->i_sb, ino);
> if (IS_ERR(ip))
> return ERR_CAST(ip);
> + d_add(dp, ip);
> }
> - d_add(dp, ip);
> return NULL;
> }
>
> @@ -249,76 +224,82 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
> struct inode *ip = file_inode(fp);
> struct super_block *sbp = ip->i_sb;
> u_long bsize = sbp->s_blocksize;
> - u_long page, npages, block, pblocks, nblocks, offset;
> - loff_t pos;
> + loff_t pos, limit;
> int bo = VXFS_SBI(sbp)->byte_order;
>
> -
> if (ctx->pos == 0) {
> if (!dir_emit_dot(fp, ctx))
> - return 0;
> - ctx->pos = 1;
> + goto out;
> + ctx->pos++;
> }
> if (ctx->pos == 1) {
> if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
> - return 0;
> - ctx->pos = 2;
> + goto out;
> + ctx->pos++;
> + }
> +
> + limit = VXFS_DIRROUND(ip->i_size);
> + if (ctx->pos > limit) {
> +#if 0
> + ctx->pos = 0;
> +#endif
> + goto out;
> }
> - pos = ctx->pos - 2;
> -
> - if (pos > VXFS_DIRROUND(ip->i_size))
> - return 0;
> -
> - npages = dir_pages(ip);
> - nblocks = dir_blocks(ip);
> - pblocks = VXFS_BLOCK_PER_PAGE(sbp);
> -
> - page = pos >> PAGE_CACHE_SHIFT;
> - offset = pos & ~PAGE_CACHE_MASK;
> - block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
> -
> - for (; page < npages; page++, block = 0) {
> - char *kaddr;
> - struct page *pp;
> -
> - pp = vxfs_get_page(ip->i_mapping, page);
> - if (IS_ERR(pp))
> - continue;
> +
> + pos = ctx->pos & ~3L;
> +
> + while (pos < limit) {
> + struct page *pp;
> + char *kaddr;
> + int pg_ofs = pos & ~PAGE_CACHE_MASK;
> + int rc = 0;
> +
> + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
> + if (IS_ERR(pp)) {
> + return -ENOMEM;
> + }
> kaddr = (char *)page_address(pp);
>
> - for (; block <= nblocks && block <= pblocks; block++) {
> - char *baddr, *limit;
> - struct vxfs_dirblk *dbp;
> - struct vxfs_direct *de;
> -
> - baddr = kaddr + (block * bsize);
> - limit = baddr + bsize - VXFS_DIRLEN(1);
> -
> - dbp = (struct vxfs_dirblk *)baddr;
> - de = (struct vxfs_direct *)
> - (offset ?
> - (kaddr + offset) :
> - (baddr + VXFS_DIRBLKOV(dbp)));
> -
> - for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
> - if (!de->d_reclen)
> - break;
> - if (!de->d_ino)
> - continue;
> -
> - offset = (char *)de - kaddr;
> - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> - if (!dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
> - fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN)) {
> - vxfs_put_page(pp);
> - return 0;
> - }
> + while (pg_ofs < PAGE_SIZE && pos < limit) {
> + struct vxfs_direct *de;
> +
> + if ((pos & (bsize - 1)) < 4) {
> + struct vxfs_dirblk *dbp =
> + (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
> + int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
> +
> + pos += overhead;
> + pg_ofs += overhead;
> + }
> + de = (struct vxfs_direct *)(kaddr + pg_ofs);
> +
> + if (!de->d_reclen) {
> + pos += bsize - 1;
> + pos &= ~(bsize - 1);
> + break;
> + }
> +
> + pg_ofs += fs16_to_cpu(bo, de->d_reclen);
> + pos += fs16_to_cpu(bo, de->d_reclen);
> + if (!de->d_ino) {
> + continue;
> + }
> +
> + rc = dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
> + fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN);
> + if (!rc) {
> + /* the dir entry was not submitted, so fix pos. */
> + pos -= fs16_to_cpu(bo, de->d_reclen);
> + break;
> }
> - offset = 0;
> }
> vxfs_put_page(pp);
> - offset = 0;
> + if (!rc)
> + break;
> }
> - ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
> +
> + ctx->pos = pos | 2;
> +
> +out:
> return 0;
> }
> --
> 1.7.3.4
>
> From e7f68291aada1535016c767a4f5a5fcfb19a1de6 Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Wed, 25 May 2016 22:41:22 +0200
> Subject: [PATCH 6/7] static cachep
>
>
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
> fs/freevxfs/vxfs_extern.h | 4 +++-
> fs/freevxfs/vxfs_inode.c | 24 +++++++++++++++++++++++-
> fs/freevxfs/vxfs_super.c | 26 ++++++++++----------------
> 3 files changed, 36 insertions(+), 18 deletions(-)
>
> diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
> index 4d8298b..cc43fd0 100644
> --- a/fs/freevxfs/vxfs_extern.h
> +++ b/fs/freevxfs/vxfs_extern.h
> @@ -55,7 +55,6 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
>
> /* vxfs_inode.c */
> extern const struct address_space_operations vxfs_immed_aops;
> -extern struct kmem_cache *vxfs_inode_cachep;
> extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
> extern struct inode * vxfs_get_fake_inode(struct super_block *,
> struct vxfs_inode_info *);
> @@ -66,6 +65,9 @@ extern struct inode * vxfs_iget(struct super_block *, ino_t);
> extern void vxfs_evict_inode(struct inode *);
> extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
> extern void vxfs_destroy_inode(struct inode *ip);
> +extern int vxfs_ii_cache_init(void);
> +extern void vxfs_ii_cache_destroy(void);
> +
>
> /* vxfs_lookup.c */
> extern const struct inode_operations vxfs_dir_inode_ops;
> diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> index 9b45ad7..73ac417 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -41,7 +41,7 @@
> #include "vxfs_extern.h"
>
>
> -struct kmem_cache *vxfs_inode_cachep;
> +static struct kmem_cache *vxfs_inode_cachep;
>
>
> #ifdef DIAGNOSTIC
> @@ -428,3 +428,25 @@ void vxfs_inode_info_free(struct vxfs_inode_info *vip)
> {
> kmem_cache_free(vxfs_inode_cachep, vip);
> }
> +
> +
> +int vxfs_ii_cache_init(void)
> +{
> + vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> + sizeof(struct vxfs_inode_info), 0,
> + SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> +
> + return vxfs_inode_cachep ? 0 : -ENOMEM;
> +}
> +
> +
> +void vxfs_ii_cache_destroy(void)
> +{
> + /*
> + * Make sure all delayed rcu free inodes are flushed before we
> + * destroy cache.
> + */
> + rcu_barrier();
> + kmem_cache_destroy(vxfs_inode_cachep);
> +}
> +
> diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> index 11a535a..7579500 100644
> --- a/fs/freevxfs/vxfs_super.c
> +++ b/fs/freevxfs/vxfs_super.c
> @@ -306,29 +306,23 @@ MODULE_ALIAS("vxfs");
> static int __init
> vxfs_init(void)
> {
> - int rv;
> + int rc = vxfs_ii_cache_init();
>
> - vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
> - sizeof(struct vxfs_inode_info), 0,
> - SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
> - if (!vxfs_inode_cachep)
> - return -ENOMEM;
> - rv = register_filesystem(&vxfs_fs_type);
> - if (rv < 0)
> - kmem_cache_destroy(vxfs_inode_cachep);
> - return rv;
> + if (!rc) {
> + rc = register_filesystem(&vxfs_fs_type);
> + if (rc < 0)
> + vxfs_ii_cache_destroy();
> + }
> + printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __func__, __DATE__, __TIME__, rc);
> +
> + return rc;
> }
>
> static void __exit
> vxfs_cleanup(void)
> {
> unregister_filesystem(&vxfs_fs_type);
> - /*
> - * Make sure all delayed rcu free inodes are flushed before we
> - * destroy cache.
> - */
> - rcu_barrier();
> - kmem_cache_destroy(vxfs_inode_cachep);
> + vxfs_ii_cache_destroy();
> }
>
> module_init(vxfs_init);
> --
> 1.7.3.4
>
> From 2c0008e9f2f4e62bb3e10eecad54e2a0140e0c4c Mon Sep 17 00:00:00 2001
> From: KB <kb@sysmikro.com.pl>
> Date: Wed, 25 May 2016 22:58:08 +0200
> Subject: [PATCH 7/7] the credits
>
>
> Signed-off-by: KB <kb@sysmikro.com.pl>
> ---
> fs/freevxfs/vxfs.h | 3 +++
> fs/freevxfs/vxfs_fshead.c | 4 ++++
> fs/freevxfs/vxfs_inode.c | 4 ++++
> fs/freevxfs/vxfs_lookup.c | 4 ++++
> fs/freevxfs/vxfs_super.c | 6 +++++-
> 5 files changed, 20 insertions(+), 1 deletions(-)
>
> diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
> index 5dc8949..35f56b7 100644
> --- a/fs/freevxfs/vxfs.h
> +++ b/fs/freevxfs/vxfs.h
> @@ -2,6 +2,9 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + * (c) 2016 Krzysztof Blaszkowski
> + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
> index 67ca2f9..44b87d0 100644
> --- a/fs/freevxfs/vxfs_fshead.c
> +++ b/fs/freevxfs/vxfs_fshead.c
> @@ -2,6 +2,10 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski
> + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
> index 73ac417..4c8a625 100644
> --- a/fs/freevxfs/vxfs_inode.c
> +++ b/fs/freevxfs/vxfs_inode.c
> @@ -2,6 +2,10 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski
> + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
> index 8eacb27..173aeea 100644
> --- a/fs/freevxfs/vxfs_lookup.c
> +++ b/fs/freevxfs/vxfs_lookup.c
> @@ -2,6 +2,10 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski
> + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
> index 7579500..bd121aa 100644
> --- a/fs/freevxfs/vxfs_super.c
> +++ b/fs/freevxfs/vxfs_super.c
> @@ -2,6 +2,10 @@
> * Copyright (c) 2000-2001 Christoph Hellwig.
> * All rights reserved.
> *
> + *
> + * (c) 2016 Krzysztof Blaszkowski
> + * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
> + *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> @@ -48,7 +52,7 @@
> #include "vxfs_inode.h"
>
>
> -MODULE_AUTHOR("Christoph Hellwig");
> +MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
> MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
> MODULE_LICENSE("Dual BSD/GPL");
>
> --
> 1.7.3.4
>
> 3531594148 32829 /usr/sprockets/bin/bw_map
> 3973234498 518896 /usr/sprockets/bin/cifslist
> 3973234498 518896 /usr/sprockets/bin/cifslogout
> 4171014129 518904 /usr/sprockets/bin/cifsmount
> 4171014129 518904 /usr/sprockets/bin/cifsumount
> 256627809 1171456 /usr/sprockets/bin/convert
> 4193697053 242843 /usr/sprockets/bin/createLicensingFiles
> 2780783712 51 /usr/sprockets/bin/createSprocFile
> 3285775584 825 /usr/sprockets/bin/dcexec
> 4073641898 94 /usr/sprockets/bin/defaultResources
> 4039074287 6610 /usr/sprockets/bin/disableNIS
> 313350104 20480 /usr/sprockets/bin/dos2ux
> 1872597524 65536 /usr/sprockets/bin/doschmod
> 1872597524 65536 /usr/sprockets/bin/doscp
> 1872597524 65536 /usr/sprockets/bin/dosdf
> 1872597524 65536 /usr/sprockets/bin/doslib
> 1872597524 65536 /usr/sprockets/bin/dosll
> 1872597524 65536 /usr/sprockets/bin/dosls
> 1872597524 65536 /usr/sprockets/bin/dosmkdir
> 1872597524 65536 /usr/sprockets/bin/dosrm
> 1872597524 65536 /usr/sprockets/bin/dosrmdir
> 1968087462 7112 /usr/sprockets/bin/enableNIS
> 3282246790 360 /usr/sprockets/bin/endexec
> 2151751185 553 /usr/sprockets/bin/endsession
> 3927613487 1115 /usr/sprockets/bin/env_var_sub
> 3738550324 157 /usr/sprockets/bin/format_dos
> 3888232633 172649 /usr/sprockets/bin/fppv
> 2279585942 466 /usr/sprockets/bin/getHostname
> 2946778792 5648 /usr/sprockets/bin/getSharedConnections
> 3306388627 20480 /usr/sprockets/bin/ibmsync
> 3041502972 28781 /usr/sprockets/bin/ipconfig700
> 3113659230 391815 /usr/sprockets/bin/kpp
> 908094753 24630 /usr/sprockets/bin/kxst
> 1329462070 36864 /usr/sprockets/bin/lanload
> 1015322628 36947 /usr/sprockets/bin/listener
> 486757159 339968 /usr/sprockets/bin/lmgrd
> 2620320940 339968 /usr/sprockets/bin/lmutil
> 951644065 243039 /usr/sprockets/bin/mattrib
> 951644065 243039 /usr/sprockets/bin/mbadblocks
> 951644065 243039 /usr/sprockets/bin/mcd
> 3650177936 951 /usr/sprockets/bin/mcheck
> 514586869 56 /usr/sprockets/bin/mcomp
> 951644065 243039 /usr/sprockets/bin/mcopy
> 951644065 243039 /usr/sprockets/bin/mdel
> 951644065 243039 /usr/sprockets/bin/mdeltree
> 951644065 243039 /usr/sprockets/bin/mdir
> 951644065 243039 /usr/sprockets/bin/mformat
> 951644065 243039 /usr/sprockets/bin/minfo
> 951644065 243039 /usr/sprockets/bin/mlabel
> 951644065 243039 /usr/sprockets/bin/mmd
> 951644065 243039 /usr/sprockets/bin/mmount
> 951644065 243039 /usr/sprockets/bin/mmove
> 951644065 243039 /usr/sprockets/bin/mpartition
> 662030829 1478557 /usr/sprockets/bin/mpv
> 951644065 243039 /usr/sprockets/bin/mrd
> 951644065 243039 /usr/sprockets/bin/mread
> 951644065 243039 /usr/sprockets/bin/mren
> 3443865238 32829 /usr/sprockets/bin/msgintcpt
> 951644065 243039 /usr/sprockets/bin/mtools
> 951644065 243039 /usr/sprockets/bin/mtoolstest
> 951644065 243039 /usr/sprockets/bin/mtype
> 951644065 243039 /usr/sprockets/bin/mwrite
> 1915353244 82 /usr/sprockets/bin/mxtar
> 951644065 243039 /usr/sprockets/bin/mzip
> 2033389047 379158 /usr/sprockets/bin/nmbd
> 1043940798 32843 /usr/sprockets/bin/nsbuild
> 421327339 32843 /usr/sprockets/bin/nsdump
> 2156955828 32843 /usr/sprockets/bin/nsquery
> 1030470949 28737 /usr/sprockets/bin/pciinfo
> 889541250 61560 /usr/sprockets/bin/pcipeek
> 1431205578 28737 /usr/sprockets/bin/pciprog
> 3351126604 126976 /usr/sprockets/bin/pkunzip
> 3351126604 126976 /usr/sprockets/bin/pkzip
> 2166142790 53390 /usr/sprockets/bin/probeload
> 694305221 41144 /usr/sprockets/bin/progflash
> 1141035887 445257 /usr/sprockets/bin/pv
> 974426301 3882 /usr/sprockets/bin/runnetscape
> 1879287959 1801 /usr/sprockets/bin/running
> 2273866242 74107 /usr/sprockets/bin/runroot
> 2616587298 79 /usr/sprockets/bin/runTouch
> 4222109660 875 /usr/sprockets/bin/samba
> 1912440105 24633 /usr/sprockets/bin/sbscrsvr
> 2558012300 3904 /usr/sprockets/bin/screensaverControl
> 4256537430 1780 /usr/sprockets/bin/sd-set_parms
> 1151924416 688 /usr/sprockets/bin/sendSignal
> 2744646624 32829 /usr/sprockets/bin/sessionDisallow
> 1227674200 1346161 /usr/sprockets/bin/sessionMgr
> 3332668870 98791 /usr/sprockets/bin/sessionWrapper
> 1477797090 82487 /usr/sprockets/bin/setlight
> 3759253613 1122 /usr/sprockets/bin/sharity
> 3313588847 3448000 /usr/sprockets/bin/sharityd
> 1569390236 24630 /usr/sprockets/bin/shmLock
> 3791448153 317300 /usr/sprockets/bin/smbclient
> 1018298877 506532 /usr/sprockets/bin/smbd
> 4009501079 45140 /usr/sprockets/bin/smtpclient
> 991996913 144424 /usr/sprockets/bin/starhw
> 3124681867 4311 /usr/sprockets/bin/startVNC
> 1468091312 919 /usr/sprockets/bin/startVNCviewer
> 304853428 1994350 /usr/sprockets/bin/sw_admin
> 304853428 1994350 /usr/sprockets/bin/sw_autoinstall
> 1455142555 123406 /usr/sprockets/bin/sw_copyfdset
> 2157175922 111102 /usr/sprockets/bin/sw_depot2bin
> 304853428 1994350 /usr/sprockets/bin/sw_install
> 304853428 1994350 /usr/sprockets/bin/sw_list
> 1842505403 7100 /usr/sprockets/bin/sw_makefdset
> 304853428 1994350 /usr/sprockets/bin/sw_remove
> 1743298644 2342 /usr/sprockets/bin/sw_rmprevious
> 1582083858 20548 /usr/sprockets/bin/sw_vendorfdset
> 178332129 1794 /usr/sprockets/bin/sysInfo
> 3657811479 1574 /usr/sprockets/bin/tgz
> 4018370132 36951 /usr/sprockets/bin/tp_license
> 1649141155 11843 /usr/sprockets/bin/updsharitycfg
> 2980018004 20480 /usr/sprockets/bin/ux2dos
> 3745508150 1318 /usr/sprockets/bin/uz
> 1348652714 32864 /usr/sprockets/bin/vncpasswd
> 4059637159 12757 /usr/sprockets/bin/vncserver
> 4128771573 366263 /usr/sprockets/bin/vncviewer
> 285011189 1526819 /usr/sprockets/bin/vp
> 589630079 387 /usr/sprockets/bin/vpexit
> 528762950 1132 /usr/sprockets/bin/xcopy
> 1793380080 521816 /usr/sprockets/bin/xscreensaver
> 24739470 145832 /usr/sprockets/bin/xscreensaver-command
> 4079099643 2167483 /usr/sprockets/bin/Xvnc
> 49651643 41091 /usr/sprockets/bin/yakdebug
> 2578809639 127914 /usr/sprockets/bin/yakhw
> 306877946 189649 /usr/sprockets/bin/yakserver
--
Carlos
^ permalink raw reply [flat|nested] 8+ messages in thread
* freevxfs
@ 2016-05-25 21:27 Krzysztof Błaszkowski
2016-05-26 11:50 ` freevxfs Carlos Maiolino
0 siblings, 1 reply; 8+ messages in thread
From: Krzysztof Błaszkowski @ 2016-05-25 21:27 UTC (permalink / raw)
To: Christoph Hellwig, Carlos Maiolino; +Cc: linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 593 bytes --]
Hi,
Please find included patchset which addresses all major features we have
discussed (unless I forgot about something).
I verified correctness of operation with my regression tests and HP-UX's
vxfs image. No difference spotted. However I can't do this with SCO
image because I do not have such. I reckon that it is highly possible
that SCO image will work as usual because the only difference is data
endianess and offset of super block.
I included for reference these scripts just in case one is curious.
(chksum8-sorted.log comes from hp-ux's cksum)
Regards,
--
Krzysztof Blaszkowski
[-- Attachment #2: 0001-kconfig-note.patch --]
[-- Type: text/x-patch, Size: 1615 bytes --]
>From 3d3b4e1ed5df014ae191e0566ff86a17d7d9ac05 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 21:50:11 +0200
Subject: [PATCH 1/7] kconfig note
Signed-off-by: KB <kb@sysmikro.com.pl>
---
fs/freevxfs/Kconfig | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig
index 8dc1cd5..a4c9075 100644
--- a/fs/freevxfs/Kconfig
+++ b/fs/freevxfs/Kconfig
@@ -5,12 +5,20 @@ config VXFS_FS
FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
file system format. VERITAS VxFS(TM) is the standard file system
of SCO UnixWare (and possibly others) and optionally available
- for Sunsoft Solaris, HP-UX and many other operating systems.
+ for Sunsoft Solaris, HP-UX and many other operating systems. However
+ these particular OS implementations of vxfs may differ in on-disk
+ data endianess and/or superblock offset. The vxfs module has been
+ tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.)
Currently only readonly access is supported.
NOTE: the file system type as used by mount(1), mount(2) and
fstab(5) is 'vxfs' as it describes the file system format, not
the actual driver.
+ There is a userspace utility for HP-UX logical volumes which makes
+ creating HP-UX logical volumes easy from HP-UX disk block device file
+ or regular file with image of the disk. See:
+ https://sourceforge.net/projects/linux-vxfs/
+
To compile this as a module, choose M here: the module will be
called freevxfs. If unsure, say N.
--
1.7.3.4
[-- Attachment #3: 0002-cpu-endian-vs-file-system-endian.patch --]
[-- Type: text/x-patch, Size: 17532 bytes --]
>From c617f6bceedc2f68c62e7432f12b59124bab34f7 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:12:05 +0200
Subject: [PATCH 2/7] cpu endian vs file system endian
Signed-off-by: KB <kb@sysmikro.com.pl>
---
fs/freevxfs/vxfs.h | 25 +++++++++++-
fs/freevxfs/vxfs_bmap.c | 24 ++++++-----
fs/freevxfs/vxfs_fshead.c | 25 +++++++++++-
fs/freevxfs/vxfs_inode.c | 61 +++++++++++++++++++++++++++-
fs/freevxfs/vxfs_inode.h | 8 ++--
fs/freevxfs/vxfs_lookup.c | 15 ++++++-
fs/freevxfs/vxfs_olt.c | 15 ++++---
fs/freevxfs/vxfs_super.c | 97 ++++++++++++++++++++++++++++++++-------------
8 files changed, 215 insertions(+), 55 deletions(-)
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index c8a9265..5dc8949 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -152,7 +152,7 @@ struct vxfs_sb {
/*
* Actually much more...
*/
-};
+} __packed;
/*
@@ -168,9 +168,32 @@ struct vxfs_sb_info {
ino_t vsi_fshino; /* fileset header inode */
daddr_t vsi_oltext; /* OLT extent */
daddr_t vsi_oltsize; /* OLT size */
+ int byte_order;
+ int silent;
+};
+
+enum {
+ BO_LE = 1,
+ BO_BE
};
+static inline u32 fs32_to_cpu(int bo, u32 a)
+{
+ return (bo == BO_BE) ? be32_to_cpu(a) : le32_to_cpu(a);
+}
+
+static inline u16 fs16_to_cpu(int bo, u16 a)
+{
+ return (bo == BO_BE) ? be16_to_cpu(a) : le16_to_cpu(a);
+}
+
+static inline u64 fs64_to_cpu(int bo, u64 a)
+{
+ return (bo == BO_BE) ? be64_to_cpu(a) : le64_to_cpu(a);
+}
+
+
/*
* File modes. File types above 0xf000 are vxfs internal only, they should
* not be passed back to higher levels of the system. vxfs file types must
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index f86fd3c..95afd98 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -92,7 +92,8 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
goto fail_buf;
indir = (u32 *)buf->b_data;
- bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
+ bno = fs32_to_cpu(VXFS_SBI(sb)->byte_order,
+ indir[(bn/indsize) % (indsize*bn)]) + (bn % indsize);
brelse(buf);
return bno;
@@ -130,6 +131,7 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
struct buffer_head *bp = NULL;
daddr_t pblock = 0;
int i;
+ int bo = VXFS_SBI(ip->i_sb)->byte_order;
for (i = 0; i < size * VXFS_TYPED_PER_BLOCK(ip->i_sb); i++) {
struct vxfs_typed *typ;
@@ -142,24 +144,24 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
typ = ((struct vxfs_typed *)bp->b_data) +
(i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
- off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+ off = fs64_to_cpu(bo, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
if (block < off) {
brelse(bp);
continue;
}
- switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+ switch ((u_int32_t)(fs64_to_cpu(bo, typ->vt_hdr) >> VXFS_TYPED_TYPESHIFT)) {
case VXFS_TYPED_INDIRECT:
- pblock = vxfs_bmap_indir(ip, typ->vt_block,
- typ->vt_size, block - off);
+ pblock = vxfs_bmap_indir(ip, fs32_to_cpu(bo, typ->vt_block),
+ fs32_to_cpu(bo, typ->vt_size), block - off);
if (pblock == -2)
break;
goto out;
case VXFS_TYPED_DATA:
- if ((block - off) >= typ->vt_size)
+ if ((block - off) >= fs32_to_cpu(bo, typ->vt_size))
break;
- pblock = (typ->vt_block + block - off);
+ pblock = fs32_to_cpu(bo, typ->vt_block) + block - off;
goto out;
case VXFS_TYPED_INDIRECT_DEV4:
case VXFS_TYPED_DATA_DEV4: {
@@ -168,12 +170,14 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
- (unsigned long long) typ4->vd4_block,
- (unsigned long long) typ4->vd4_size,
- typ4->vd4_dev);
+ (unsigned long long) fs64_to_cpu(bo, typ4->vd4_block),
+ (unsigned long long) fs64_to_cpu(bo, typ4->vd4_size),
+ fs32_to_cpu(bo, typ4->vd4_dev));
goto fail;
}
default:
+ printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__, __LINE__,
+ fs64_to_cpu(bo, typ->vt_hdr));
BUG();
}
brelse(bp);
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c9a6a94..6cbdde7 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -60,6 +60,29 @@ vxfs_dumpfsh(struct vxfs_fsh *fhp)
}
#endif
+#define VXFS_FS32(field1, field2) fhp->field1 = fs32_to_cpu(bo, dbh->field2)
+static inline void dbh2fhp(struct vxfs_fsh *fhp, void *_dbh, int bo)
+{
+ struct vxfs_fsh *dbh = (struct vxfs_fsh *)_dbh;
+
+ VXFS_FS32(fsh_version, fsh_version);
+ VXFS_FS32(fsh_fsindex, fsh_fsindex);
+ VXFS_FS32(fsh_time, fsh_time);
+ VXFS_FS32(fsh_utime, fsh_utime);
+ VXFS_FS32(fsh_extop, fsh_extop);
+ VXFS_FS32(fsh_ninodes, fsh_ninodes);
+ VXFS_FS32(fsh_nau, fsh_nau);
+ VXFS_FS32(fsh_old_ilesize, fsh_old_ilesize);
+ VXFS_FS32(fsh_dflags, fsh_dflags);
+ VXFS_FS32(fsh_quota, fsh_quota);
+ VXFS_FS32(fsh_maxinode, fsh_maxinode);
+ VXFS_FS32(fsh_iauino, fsh_iauino);
+ VXFS_FS32(fsh_ilistino[0], fsh_ilistino[0]);
+ VXFS_FS32(fsh_ilistino[1], fsh_ilistino[1]);
+ VXFS_FS32(fsh_lctino, fsh_lctino);
+}
+
+
/**
* vxfs_getfsh - read fileset header into memory
* @ip: the (fake) fileset header inode
@@ -83,7 +106,7 @@ vxfs_getfsh(struct inode *ip, int which)
if (!(fhp = kmalloc(sizeof(*fhp), GFP_KERNEL)))
goto out;
- memcpy(fhp, bp->b_data, sizeof(*fhp));
+ dbh2fhp(fhp, bp->b_data, VXFS_SBI(ip->i_sb)->byte_order);
put_bh(bp);
return (fhp);
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 363e3ae..53b8757 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -67,6 +67,63 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
}
#endif
+#define VXFS_FS32(field1, field2) vip->field1 = fs32_to_cpu(bo, dip->field2)
+#define VXFS_FS64(field1, field2) vip->field1 = fs64_to_cpu(bo, dip->field2)
+#define VXFS_FS16(field1, field2) vip->field1 = fs16_to_cpu(bo, dip->field2)
+
+static inline void dip2vip_cpy(struct vxfs_inode_info *vip, struct vxfs_dinode *dip, int bo)
+{
+ int j;
+
+ VXFS_FS32(vdi_mode, vdi_mode);
+ VXFS_FS32(vdi_nlink, vdi_nlink);
+ VXFS_FS32(vdi_uid, vdi_uid);
+ VXFS_FS32(vdi_gid, vdi_gid);
+ VXFS_FS64(vdi_size, vdi_size);
+ VXFS_FS32(vdi_atime, vdi_atime);
+ VXFS_FS32(vdi_autime, vdi_autime);
+ VXFS_FS32(vdi_mtime, vdi_mtime);
+ VXFS_FS32(vdi_mutime, vdi_mutime);
+ VXFS_FS32(vdi_ctime, vdi_ctime);
+ VXFS_FS32(vdi_cutime, vdi_cutime);
+ vip->vdi_aflags = dip->vdi_aflags;
+ vip->vdi_orgtype = dip->vdi_orgtype;
+ VXFS_FS16(vdi_eopflags, vdi_eopflags);
+ VXFS_FS32(vdi_eopdata, vdi_eopdata);
+
+ VXFS_FS32(vdi_ftarea.i_regular.reserved, vdi_ftarea.i_regular.reserved);
+ VXFS_FS32(vdi_ftarea.i_regular.fixextsize, vdi_ftarea.i_regular.fixextsize);
+ VXFS_FS32(vdi_blocks, vdi_blocks);
+ VXFS_FS32(vdi_gen, vdi_gen);
+ VXFS_FS64(vdi_version, vdi_version);
+
+ switch (dip->vdi_orgtype) {
+ case VXFS_ORG_EXT4:
+ VXFS_FS32(vdi_org.ext4.ve4_spare, vdi_org.ext4.ve4_spare);
+ VXFS_FS32(vdi_org.ext4.ve4_indsize, vdi_org.ext4.ve4_indsize);
+ for (j = 0; j < VXFS_NIADDR; j++) {
+ VXFS_FS32(vdi_org.ext4.ve4_indir[j], vdi_org.ext4.ve4_indir[j]);
+ }
+ for (j = 0; j < VXFS_NDADDR; j++) {
+ VXFS_FS32(vdi_org.ext4.ve4_direct[j].extent, vdi_org.ext4.ve4_direct[j].extent);
+ VXFS_FS32(vdi_org.ext4.ve4_direct[j].size, vdi_org.ext4.ve4_direct[j].size);
+ }
+ break;
+ case VXFS_ORG_IMMED:
+ memcpy(&vip->vdi_org.immed, &dip->vdi_org.immed, sizeof(vip->vdi_org.immed));
+ break;
+ case VXFS_ORG_TYPED:
+ for (j = 0; j < VXFS_NTYPED; j++) {
+ VXFS_FS64(vdi_org.typed[j].vt_hdr, vdi_org.typed[j].vt_hdr);
+ VXFS_FS32(vdi_org.typed[j].vt_block, vdi_org.typed[j].vt_block);
+ VXFS_FS32(vdi_org.typed[j].vt_size, vdi_org.typed[j].vt_size);
+ }
+ break;
+ };
+
+ VXFS_FS32(vdi_iattrino, vdi_iattrino);
+}
+
/**
* vxfs_blkiget - find inode based on extent #
@@ -101,7 +158,7 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
goto fail;
dip = (struct vxfs_dinode *)(bp->b_data + offset);
- memcpy(vip, dip, sizeof(*vip));
+ dip2vip_cpy(vip, dip, VXFS_SBI(sbp)->byte_order);
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
@@ -143,7 +200,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
goto fail;
dip = (struct vxfs_dinode *)(kaddr + offset);
- memcpy(vip, dip, sizeof(*vip));
+ dip2vip_cpy(vip, dip, VXFS_SBI(ilistp->i_sb)->byte_order);
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 240aeb1..9a2c376 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -77,13 +77,13 @@ struct vxfs_ext4 {
vx_daddr_t extent; /* Extent number */
int32_t size; /* Size of extent */
} ve4_direct[VXFS_NDADDR];
-};
+} __packed;
struct vxfs_typed {
u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
vx_daddr_t vt_block; /* Extent block */
int32_t vt_size; /* Size in blocks */
-};
+} __packed;
struct vxfs_typed_dev4 {
u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
@@ -91,7 +91,7 @@ struct vxfs_typed_dev4 {
u_int64_t vd4_size; /* Size in blocks */
int32_t vd4_dev; /* Device ID */
u_int32_t __pad1;
-};
+} __packed;
/*
* The inode as contained on the physical device.
@@ -134,7 +134,7 @@ struct vxfs_dinode {
struct vxfs_typed typed[VXFS_NTYPED];
} vdi_org;
u_int32_t vdi_iattrino;
-};
+} __packed;
#define vdi_rdev vdi_ftarea.rdev
#define vdi_dotdot vdi_ftarea.dotdot
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 99c7f0a..cea158a 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -96,6 +96,15 @@ vxfs_next_entry(struct vxfs_direct *de)
return ((struct vxfs_direct *)((char*)de + de->d_reclen));
}
+/*
+ * VXFS_dirblk_ovh is the overhead of a specific dirblock.
+ */
+static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
+{
+ return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
+}
+
+
/**
* vxfs_find_entry - find a mathing directory entry for a dentry
* @ip: directory inode
@@ -242,6 +251,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
u_long bsize = sbp->s_blocksize;
u_long page, npages, block, pblocks, nblocks, offset;
loff_t pos;
+ int bo = VXFS_SBI(sbp)->byte_order;
+
if (ctx->pos == 0) {
if (!dir_emit_dot(fp, ctx))
@@ -297,8 +308,8 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
offset = (char *)de - kaddr;
ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
- if (!dir_emit(ctx, de->d_name, de->d_namelen,
- de->d_ino, DT_UNKNOWN)) {
+ if (!dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
+ fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN)) {
vxfs_put_page(pp);
return 0;
}
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 0495008..6b50188 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -43,14 +43,14 @@ static inline void
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
{
BUG_ON(infp->vsi_fshino);
- infp->vsi_fshino = fshp->olt_fsino[0];
+ infp->vsi_fshino = fs32_to_cpu(infp->byte_order, fshp->olt_fsino[0]);
}
static inline void
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
{
BUG_ON(infp->vsi_iext);
- infp->vsi_iext = ilistp->olt_iext[0];
+ infp->vsi_iext = fs32_to_cpu(infp->byte_order, ilistp->olt_iext[0]);
}
static inline u_long
@@ -80,6 +80,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
struct buffer_head *bp;
struct vxfs_olt *op;
char *oaddr, *eaddr;
+ int bo = infp->byte_order;
bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
@@ -87,7 +88,7 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
goto fail;
op = (struct vxfs_olt *)bp->b_data;
- if (op->olt_magic != VXFS_OLT_MAGIC) {
+ if (fs32_to_cpu(bo, op->olt_magic) != VXFS_OLT_MAGIC) {
printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
goto fail;
}
@@ -102,14 +103,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
goto fail;
}
- oaddr = bp->b_data + op->olt_size;
+ oaddr = bp->b_data + fs32_to_cpu(bo, op->olt_size);
eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
while (oaddr < eaddr) {
struct vxfs_oltcommon *ocp =
(struct vxfs_oltcommon *)oaddr;
- switch (ocp->olt_type) {
+ switch (fs32_to_cpu(bo, ocp->olt_type)) {
case VXFS_OLT_FSHEAD:
vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
break;
@@ -118,11 +119,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
break;
}
- oaddr += ocp->olt_size;
+ oaddr += fs32_to_cpu(bo, ocp->olt_size);
}
brelse(bp);
- return 0;
+ return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
fail:
brelse(bp);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7ca8c75..6a19802 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -109,14 +109,15 @@ static int
vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
{
struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb);
+ struct vxfs_sb *raw_sb = infp->vsi_raw;
bufp->f_type = VXFS_SUPER_MAGIC;
bufp->f_bsize = dentry->d_sb->s_blocksize;
- bufp->f_blocks = infp->vsi_raw->vs_dsize;
- bufp->f_bfree = infp->vsi_raw->vs_free;
+ bufp->f_blocks = fs32_to_cpu(infp->byte_order, raw_sb->vs_dsize);
+ bufp->f_bfree = fs32_to_cpu(infp->byte_order, raw_sb->vs_free);
bufp->f_bavail = 0;
bufp->f_files = 0;
- bufp->f_ffree = infp->vsi_raw->vs_ifree;
+ bufp->f_ffree = fs32_to_cpu(infp->byte_order, raw_sb->vs_ifree);
bufp->f_namelen = VXFS_NAMELEN;
return 0;
@@ -129,6 +130,46 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
+
+static int vxfs_try_sb_magic(struct super_block *sbp, int blk, u32 magic)
+{
+ struct buffer_head *bp;
+ struct vxfs_sb *rsbp;
+ struct vxfs_sb_info *infp = VXFS_SBI(sbp);
+ int rc = -ENOMEM;
+
+ bp = sb_bread(sbp, blk);
+ do {
+ if (!bp || !buffer_mapped(bp)) {
+ if (!infp->silent) {
+ printk(KERN_WARNING "vxfs: unable to read"
+ " disk superblock at %d\n", blk);
+ }
+ break;
+ }
+
+ rc = -EINVAL;
+ rsbp = (struct vxfs_sb *)bp->b_data;
+ if (rsbp->vs_magic != magic) {
+ if (!infp->silent)
+ printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
+ break;
+ }
+
+ rc = 0;
+ infp->vsi_raw = rsbp;
+ infp->vsi_bp = bp;
+ } while (0);
+
+ if (rc) {
+ infp->vsi_raw = NULL;
+ infp->vsi_bp = NULL;
+ brelse(bp);
+ }
+
+ return rc;
+}
+
/**
* vxfs_read_super - read superblock into memory and initialize filesystem
* @sbp: VFS superblock (to fill)
@@ -149,10 +190,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
{
struct vxfs_sb_info *infp;
struct vxfs_sb *rsbp;
- struct buffer_head *bp = NULL;
u_long bsize;
struct inode *root;
int ret = -EINVAL;
+ u32 j;
sbp->s_flags |= MS_RDONLY;
@@ -162,48 +203,47 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
return -ENOMEM;
}
+ infp->silent = silent;
bsize = sb_min_blocksize(sbp, BLOCK_SIZE);
if (!bsize) {
printk(KERN_WARNING "vxfs: unable to set blocksize\n");
goto out;
}
- bp = sb_bread(sbp, 1);
- if (!bp || !buffer_mapped(bp)) {
- if (!silent) {
- printk(KERN_WARNING
- "vxfs: unable to read disk superblock\n");
+ sbp->s_fs_info = infp;
+ do {
+ if (!vxfs_try_sb_magic(sbp, 1, cpu_to_le32(VXFS_SUPER_MAGIC))) {
+ infp->byte_order = BO_LE; /* SCO */
+ break;
+ }
+
+ if (!vxfs_try_sb_magic(sbp, 8, cpu_to_be32(VXFS_SUPER_MAGIC))) {
+ infp->byte_order = BO_BE; /* HP-UX pa-risc likely */
+ break;
}
- goto out;
- }
- rsbp = (struct vxfs_sb *)bp->b_data;
- if (rsbp->vs_magic != VXFS_SUPER_MAGIC) {
- if (!silent)
- printk(KERN_NOTICE "vxfs: WRONG superblock magic\n");
goto out;
- }
+ } while (0);
- if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) {
- printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n",
- rsbp->vs_version);
+ rsbp = infp->vsi_raw;
+ j = fs32_to_cpu(infp->byte_order, rsbp->vs_version);
+ if ((j < 2 || j > 4) && !silent) {
+ printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
goto out;
}
#ifdef DIAGNOSTIC
- printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version);
+ printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize);
#endif
- sbp->s_magic = rsbp->vs_magic;
- sbp->s_fs_info = infp;
+ sbp->s_magic = fs32_to_cpu(infp->byte_order, rsbp->vs_magic);
- infp->vsi_raw = rsbp;
- infp->vsi_bp = bp;
- infp->vsi_oltext = rsbp->vs_oltext[0];
- infp->vsi_oltsize = rsbp->vs_oltsize;
+ infp->vsi_oltext = fs32_to_cpu(infp->byte_order, rsbp->vs_oltext[0]);
+ infp->vsi_oltsize = fs32_to_cpu(infp->byte_order, rsbp->vs_oltsize);
- if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) {
+ j = fs32_to_cpu(infp->byte_order, rsbp->vs_bsize);
+ if (!sb_set_blocksize(sbp, j)) {
printk(KERN_WARNING "vxfs: unable to set final block size\n");
goto out;
}
@@ -237,7 +277,8 @@ out_free_ilist:
vxfs_put_fake_inode(infp->vsi_ilist);
vxfs_put_fake_inode(infp->vsi_stilist);
out:
- brelse(bp);
+ if (infp->vsi_bp)
+ brelse(infp->vsi_bp);
kfree(infp);
return ret;
}
--
1.7.3.4
[-- Attachment #4: 0003-missing-kfree-and-kfree-on-kmem_cache-obj.patch --]
[-- Type: text/x-patch, Size: 2605 bytes --]
>From b95e9b749b85be347c953ce33d2b3c5dde4e56d6 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:13:20 +0200
Subject: [PATCH 3/7] missing kfree and kfree on kmem_cache obj
Signed-off-by: KB <kb@sysmikro.com.pl>
---
fs/freevxfs/vxfs_extern.h | 1 +
fs/freevxfs/vxfs_fshead.c | 8 +++++---
fs/freevxfs/vxfs_inode.c | 5 +++++
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 881aa3d..0a3ff86 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -64,6 +64,7 @@ extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t
extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
extern struct inode * vxfs_iget(struct super_block *, ino_t);
extern void vxfs_evict_inode(struct inode *);
+extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
/* vxfs_lookup.c */
extern const struct inode_operations vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index 6cbdde7..67ca2f9 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -183,7 +183,7 @@ vxfs_read_fshead(struct super_block *sbp)
infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
if (!infp->vsi_stilist) {
printk(KERN_ERR "vxfs: unable to get structural list inode\n");
- kfree(tip);
+ vxfs_inode_info_free(tip);
goto out_free_pfp;
}
if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
@@ -198,7 +198,7 @@ vxfs_read_fshead(struct super_block *sbp)
infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
if (!infp->vsi_ilist) {
printk(KERN_ERR "vxfs: unable to get inode list inode\n");
- kfree(tip);
+ vxfs_inode_info_free(tip);
goto out_iput_stilist;
}
if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
@@ -206,6 +206,8 @@ vxfs_read_fshead(struct super_block *sbp)
VXFS_INO(infp->vsi_ilist)->vii_mode & VXFS_TYPE_MASK);
goto out_iput_ilist;
}
+ kfree(pfp);
+ kfree(sfp);
return 0;
@@ -221,6 +223,6 @@ vxfs_read_fshead(struct super_block *sbp)
iput(infp->vsi_fship);
return -EINVAL;
out_free_fship:
- kfree(vip);
+ vxfs_inode_info_free(vip);
return -EINVAL;
}
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 53b8757..16d8d27 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -415,3 +415,8 @@ vxfs_evict_inode(struct inode *ip)
clear_inode(ip);
call_rcu(&ip->i_rcu, vxfs_i_callback);
}
+
+void vxfs_inode_info_free(struct vxfs_inode_info *vip)
+{
+ kmem_cache_free(vxfs_inode_cachep, vip);
+}
--
1.7.3.4
[-- Attachment #5: 0004-super_operations.destroy_inode.patch --]
[-- Type: text/x-patch, Size: 2645 bytes --]
>From e4979c6a29eb79d59d8bc2eca9acc0d2b416780f Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:15:20 +0200
Subject: [PATCH 4/7] super_operations.destroy_inode
Signed-off-by: KB <kb@sysmikro.com.pl>
---
fs/freevxfs/vxfs_extern.h | 1 +
fs/freevxfs/vxfs_inode.c | 16 ++++++++++++----
fs/freevxfs/vxfs_super.c | 1 +
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 0a3ff86..4d8298b 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -65,6 +65,7 @@ extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
extern struct inode * vxfs_iget(struct super_block *, ino_t);
extern void vxfs_evict_inode(struct inode *);
extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
+extern void vxfs_destroy_inode(struct inode *ip);
/* vxfs_lookup.c */
extern const struct inode_operations vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 16d8d27..9b45ad7 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -397,7 +397,15 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
static void vxfs_i_callback(struct rcu_head *head)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
- kmem_cache_free(vxfs_inode_cachep, inode->i_private);
+ void *priv = inode->i_private;
+
+ inode->i_private = NULL;
+ kmem_cache_free(vxfs_inode_cachep, priv);
+}
+
+void vxfs_destroy_inode(struct inode *ip)
+{
+ call_rcu(&ip->i_rcu, vxfs_i_callback);
}
/**
@@ -405,17 +413,17 @@ static void vxfs_i_callback(struct rcu_head *head)
* @ip: inode to discard.
*
* Description:
- * vxfs_evict_inode() is called on the final iput and frees the private
- * inode area.
+ * vxfs_evict_inode() is called on the final iput
*/
void
vxfs_evict_inode(struct inode *ip)
{
truncate_inode_pages_final(&ip->i_data);
+ invalidate_inode_buffers(ip);
clear_inode(ip);
- call_rcu(&ip->i_rcu, vxfs_i_callback);
}
+
void vxfs_inode_info_free(struct vxfs_inode_info *vip)
{
kmem_cache_free(vxfs_inode_cachep, vip);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 6a19802..11a535a 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -59,6 +59,7 @@ static int vxfs_statfs(struct dentry *, struct kstatfs *);
static int vxfs_remount(struct super_block *, int *, char *);
static const struct super_operations vxfs_super_ops = {
+ .destroy_inode = vxfs_destroy_inode,
.evict_inode = vxfs_evict_inode,
.put_super = vxfs_put_super,
.statfs = vxfs_statfs,
--
1.7.3.4
[-- Attachment #6: 0005-refactoring-of-vxfs_readir-and-find_entry.patch --]
[-- Type: text/x-patch, Size: 8246 bytes --]
>From 4a6ae0e351b6046367bbd2939547f292ed2b6e47 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:28:37 +0200
Subject: [PATCH 5/7] refactoring of vxfs_readir() and find_entry()
Signed-off-by: KB <kb@sysmikro.com.pl>
---
fs/freevxfs/vxfs_lookup.c | 267 +++++++++++++++++++++------------------------
1 files changed, 124 insertions(+), 143 deletions(-)
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index cea158a..8eacb27 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -61,48 +61,6 @@ const struct file_operations vxfs_dir_operations = {
.iterate = vxfs_readdir,
};
-
-static inline u_long
-dir_pages(struct inode *inode)
-{
- return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-}
-
-static inline u_long
-dir_blocks(struct inode *ip)
-{
- u_long bsize = ip->i_sb->s_blocksize;
- return (ip->i_size + bsize - 1) & ~(bsize - 1);
-}
-
-/*
- * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
- *
- * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
- */
-static inline int
-vxfs_match(int len, const char * const name, struct vxfs_direct *de)
-{
- if (len != de->d_namelen)
- return 0;
- if (!de->d_ino)
- return 0;
- return !memcmp(name, de->d_name, len);
-}
-
-static inline struct vxfs_direct *
-vxfs_next_entry(struct vxfs_direct *de)
-{
- return ((struct vxfs_direct *)((char*)de + de->d_reclen));
-}
-
-/*
- * VXFS_dirblk_ovh is the overhead of a specific dirblock.
- */
-static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
-{
- return (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
-}
/**
@@ -122,50 +80,65 @@ static inline u_long VXFS_dirblk_ovh(struct vxfs_dirblk *dbp, int bo)
static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
{
- u_long npages, page, nblocks, pblocks, block;
- u_long bsize = ip->i_sb->s_blocksize;
- const char *name = dp->d_name.name;
- int namelen = dp->d_name.len;
-
- npages = dir_pages(ip);
- nblocks = dir_blocks(ip);
- pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
-
- for (page = 0; page < npages; page++) {
- caddr_t kaddr;
- struct page *pp;
-
- pp = vxfs_get_page(ip->i_mapping, page);
- if (IS_ERR(pp))
- continue;
- kaddr = (caddr_t)page_address(pp);
-
- for (block = 0; block <= nblocks && block <= pblocks; block++) {
- caddr_t baddr, limit;
- struct vxfs_dirblk *dbp;
- struct vxfs_direct *de;
-
- baddr = kaddr + (block * bsize);
- limit = baddr + bsize - VXFS_DIRLEN(1);
-
- dbp = (struct vxfs_dirblk *)baddr;
- de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
-
- for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
- if (!de->d_reclen)
- break;
- if (!de->d_ino)
- continue;
- if (vxfs_match(namelen, name, de)) {
- *ppp = pp;
- return (de);
- }
+ u_long bsize = ip->i_sb->s_blocksize;
+ const char *name = dp->d_name.name;
+ int namelen = dp->d_name.len;
+ loff_t limit = VXFS_DIRROUND(ip->i_size);
+ struct vxfs_direct *de_exit = NULL;
+ loff_t pos = 0;
+ int bo = VXFS_SBI(ip->i_sb)->byte_order;
+
+ while (pos < limit) {
+ struct page *pp;
+ char *kaddr;
+ int pg_ofs = pos & ~PAGE_CACHE_MASK;
+
+ pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+ if (IS_ERR(pp)) {
+ return NULL;
+ }
+ kaddr = (char *)page_address(pp);
+
+ while (pg_ofs < PAGE_SIZE && pos < limit) {
+ struct vxfs_direct *de;
+
+ if ((pos & (bsize - 1)) < 4) {
+ struct vxfs_dirblk *dbp =
+ (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
+ int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
+
+ pos += overhead;
+ pg_ofs += overhead;
+ }
+ de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+ if (!de->d_reclen) {
+ pos += bsize - 1;
+ pos &= ~(bsize - 1);
+ break;
+ }
+
+ pg_ofs += fs16_to_cpu(bo, de->d_reclen);
+ pos += fs16_to_cpu(bo, de->d_reclen);
+ if (!de->d_ino) {
+ continue;
+ }
+
+ if (namelen != fs16_to_cpu(bo, de->d_namelen))
+ continue;
+ if (!memcmp(name, de->d_name, namelen)) {
+ *ppp = pp;
+ de_exit = de;
+ break;
}
}
- vxfs_put_page(pp);
+ if (!de_exit)
+ vxfs_put_page(pp);
+ else
+ break;
}
- return NULL;
+ return de_exit;
}
/**
@@ -185,15 +158,17 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
{
struct vxfs_direct *de;
struct page *pp;
- ino_t ino = 0;
+ ino_t ino = 0;
de = vxfs_find_entry(dip, dp, &pp);
if (de) {
- ino = de->d_ino;
+ int bo = VXFS_SBI(dip->i_sb)->byte_order;
+
+ ino = fs32_to_cpu(bo, de->d_ino);
kunmap(pp);
page_cache_release(pp);
}
-
+
return (ino);
}
@@ -225,8 +200,8 @@ vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
ip = vxfs_iget(dip->i_sb, ino);
if (IS_ERR(ip))
return ERR_CAST(ip);
+ d_add(dp, ip);
}
- d_add(dp, ip);
return NULL;
}
@@ -249,76 +224,82 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
struct inode *ip = file_inode(fp);
struct super_block *sbp = ip->i_sb;
u_long bsize = sbp->s_blocksize;
- u_long page, npages, block, pblocks, nblocks, offset;
- loff_t pos;
+ loff_t pos, limit;
int bo = VXFS_SBI(sbp)->byte_order;
-
if (ctx->pos == 0) {
if (!dir_emit_dot(fp, ctx))
- return 0;
- ctx->pos = 1;
+ goto out;
+ ctx->pos++;
}
if (ctx->pos == 1) {
if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
- return 0;
- ctx->pos = 2;
+ goto out;
+ ctx->pos++;
+ }
+
+ limit = VXFS_DIRROUND(ip->i_size);
+ if (ctx->pos > limit) {
+#if 0
+ ctx->pos = 0;
+#endif
+ goto out;
}
- pos = ctx->pos - 2;
-
- if (pos > VXFS_DIRROUND(ip->i_size))
- return 0;
-
- npages = dir_pages(ip);
- nblocks = dir_blocks(ip);
- pblocks = VXFS_BLOCK_PER_PAGE(sbp);
-
- page = pos >> PAGE_CACHE_SHIFT;
- offset = pos & ~PAGE_CACHE_MASK;
- block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
-
- for (; page < npages; page++, block = 0) {
- char *kaddr;
- struct page *pp;
-
- pp = vxfs_get_page(ip->i_mapping, page);
- if (IS_ERR(pp))
- continue;
+
+ pos = ctx->pos & ~3L;
+
+ while (pos < limit) {
+ struct page *pp;
+ char *kaddr;
+ int pg_ofs = pos & ~PAGE_CACHE_MASK;
+ int rc = 0;
+
+ pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_CACHE_SHIFT);
+ if (IS_ERR(pp)) {
+ return -ENOMEM;
+ }
kaddr = (char *)page_address(pp);
- for (; block <= nblocks && block <= pblocks; block++) {
- char *baddr, *limit;
- struct vxfs_dirblk *dbp;
- struct vxfs_direct *de;
-
- baddr = kaddr + (block * bsize);
- limit = baddr + bsize - VXFS_DIRLEN(1);
-
- dbp = (struct vxfs_dirblk *)baddr;
- de = (struct vxfs_direct *)
- (offset ?
- (kaddr + offset) :
- (baddr + VXFS_DIRBLKOV(dbp)));
-
- for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
- if (!de->d_reclen)
- break;
- if (!de->d_ino)
- continue;
-
- offset = (char *)de - kaddr;
- ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
- if (!dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
- fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN)) {
- vxfs_put_page(pp);
- return 0;
- }
+ while (pg_ofs < PAGE_SIZE && pos < limit) {
+ struct vxfs_direct *de;
+
+ if ((pos & (bsize - 1)) < 4) {
+ struct vxfs_dirblk *dbp =
+ (struct vxfs_dirblk *)(kaddr + (pos & ~PAGE_CACHE_MASK));
+ int overhead = (sizeof(short) * fs16_to_cpu(bo, dbp->d_nhash)) + 4;
+
+ pos += overhead;
+ pg_ofs += overhead;
+ }
+ de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+ if (!de->d_reclen) {
+ pos += bsize - 1;
+ pos &= ~(bsize - 1);
+ break;
+ }
+
+ pg_ofs += fs16_to_cpu(bo, de->d_reclen);
+ pos += fs16_to_cpu(bo, de->d_reclen);
+ if (!de->d_ino) {
+ continue;
+ }
+
+ rc = dir_emit(ctx, de->d_name, fs16_to_cpu(bo, de->d_namelen),
+ fs32_to_cpu(bo, de->d_ino), DT_UNKNOWN);
+ if (!rc) {
+ /* the dir entry was not submitted, so fix pos. */
+ pos -= fs16_to_cpu(bo, de->d_reclen);
+ break;
}
- offset = 0;
}
vxfs_put_page(pp);
- offset = 0;
+ if (!rc)
+ break;
}
- ctx->pos = ((page << PAGE_CACHE_SHIFT) | offset) + 2;
+
+ ctx->pos = pos | 2;
+
+out:
return 0;
}
--
1.7.3.4
[-- Attachment #7: 0006-static-cachep.patch --]
[-- Type: text/x-patch, Size: 3331 bytes --]
>From e7f68291aada1535016c767a4f5a5fcfb19a1de6 Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:41:22 +0200
Subject: [PATCH 6/7] static cachep
Signed-off-by: KB <kb@sysmikro.com.pl>
---
fs/freevxfs/vxfs_extern.h | 4 +++-
fs/freevxfs/vxfs_inode.c | 24 +++++++++++++++++++++++-
fs/freevxfs/vxfs_super.c | 26 ++++++++++----------------
3 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 4d8298b..cc43fd0 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -55,7 +55,6 @@ extern const struct inode_operations vxfs_immed_symlink_iops;
/* vxfs_inode.c */
extern const struct address_space_operations vxfs_immed_aops;
-extern struct kmem_cache *vxfs_inode_cachep;
extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
extern struct inode * vxfs_get_fake_inode(struct super_block *,
struct vxfs_inode_info *);
@@ -66,6 +65,9 @@ extern struct inode * vxfs_iget(struct super_block *, ino_t);
extern void vxfs_evict_inode(struct inode *);
extern void vxfs_inode_info_free(struct vxfs_inode_info *vip);
extern void vxfs_destroy_inode(struct inode *ip);
+extern int vxfs_ii_cache_init(void);
+extern void vxfs_ii_cache_destroy(void);
+
/* vxfs_lookup.c */
extern const struct inode_operations vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 9b45ad7..73ac417 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -41,7 +41,7 @@
#include "vxfs_extern.h"
-struct kmem_cache *vxfs_inode_cachep;
+static struct kmem_cache *vxfs_inode_cachep;
#ifdef DIAGNOSTIC
@@ -428,3 +428,25 @@ void vxfs_inode_info_free(struct vxfs_inode_info *vip)
{
kmem_cache_free(vxfs_inode_cachep, vip);
}
+
+
+int vxfs_ii_cache_init(void)
+{
+ vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
+ sizeof(struct vxfs_inode_info), 0,
+ SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
+
+ return vxfs_inode_cachep ? 0 : -ENOMEM;
+}
+
+
+void vxfs_ii_cache_destroy(void)
+{
+ /*
+ * Make sure all delayed rcu free inodes are flushed before we
+ * destroy cache.
+ */
+ rcu_barrier();
+ kmem_cache_destroy(vxfs_inode_cachep);
+}
+
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 11a535a..7579500 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -306,29 +306,23 @@ MODULE_ALIAS("vxfs");
static int __init
vxfs_init(void)
{
- int rv;
+ int rc = vxfs_ii_cache_init();
- vxfs_inode_cachep = kmem_cache_create("vxfs_inode",
- sizeof(struct vxfs_inode_info), 0,
- SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, NULL);
- if (!vxfs_inode_cachep)
- return -ENOMEM;
- rv = register_filesystem(&vxfs_fs_type);
- if (rv < 0)
- kmem_cache_destroy(vxfs_inode_cachep);
- return rv;
+ if (!rc) {
+ rc = register_filesystem(&vxfs_fs_type);
+ if (rc < 0)
+ vxfs_ii_cache_destroy();
+ }
+ printk(KERN_DEBUG "%s: **** %s %s rc %d\n", __func__, __DATE__, __TIME__, rc);
+
+ return rc;
}
static void __exit
vxfs_cleanup(void)
{
unregister_filesystem(&vxfs_fs_type);
- /*
- * Make sure all delayed rcu free inodes are flushed before we
- * destroy cache.
- */
- rcu_barrier();
- kmem_cache_destroy(vxfs_inode_cachep);
+ vxfs_ii_cache_destroy();
}
module_init(vxfs_init);
--
1.7.3.4
[-- Attachment #8: 0007-the-credits.patch --]
[-- Type: text/x-patch, Size: 3314 bytes --]
>From 2c0008e9f2f4e62bb3e10eecad54e2a0140e0c4c Mon Sep 17 00:00:00 2001
From: KB <kb@sysmikro.com.pl>
Date: Wed, 25 May 2016 22:58:08 +0200
Subject: [PATCH 7/7] the credits
Signed-off-by: KB <kb@sysmikro.com.pl>
---
fs/freevxfs/vxfs.h | 3 +++
fs/freevxfs/vxfs_fshead.c | 4 ++++
fs/freevxfs/vxfs_inode.c | 4 ++++
fs/freevxfs/vxfs_lookup.c | 4 ++++
fs/freevxfs/vxfs_super.c | 6 +++++-
5 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 5dc8949..35f56b7 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -2,6 +2,9 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ * (c) 2016 Krzysztof Blaszkowski
+ * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index 67ca2f9..44b87d0 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -2,6 +2,10 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 73ac417..4c8a625 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -2,6 +2,10 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 8eacb27..173aeea 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -2,6 +2,10 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7579500..bd121aa 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -2,6 +2,10 @@
* Copyright (c) 2000-2001 Christoph Hellwig.
* All rights reserved.
*
+ *
+ * (c) 2016 Krzysztof Blaszkowski
+ * Many bug fixes, improvements & tests with HP-UX B.10.20 (pa-risc)
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -48,7 +52,7 @@
#include "vxfs_inode.h"
-MODULE_AUTHOR("Christoph Hellwig");
+MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
MODULE_LICENSE("Dual BSD/GPL");
--
1.7.3.4
[-- Attachment #9: Check.sh --]
[-- Type: application/x-shellscript, Size: 180 bytes --]
[-- Attachment #10: cksum8-sorted.log --]
[-- Type: text/x-log, Size: 5629 bytes --]
3531594148 32829 /usr/sprockets/bin/bw_map
3973234498 518896 /usr/sprockets/bin/cifslist
3973234498 518896 /usr/sprockets/bin/cifslogout
4171014129 518904 /usr/sprockets/bin/cifsmount
4171014129 518904 /usr/sprockets/bin/cifsumount
256627809 1171456 /usr/sprockets/bin/convert
4193697053 242843 /usr/sprockets/bin/createLicensingFiles
2780783712 51 /usr/sprockets/bin/createSprocFile
3285775584 825 /usr/sprockets/bin/dcexec
4073641898 94 /usr/sprockets/bin/defaultResources
4039074287 6610 /usr/sprockets/bin/disableNIS
313350104 20480 /usr/sprockets/bin/dos2ux
1872597524 65536 /usr/sprockets/bin/doschmod
1872597524 65536 /usr/sprockets/bin/doscp
1872597524 65536 /usr/sprockets/bin/dosdf
1872597524 65536 /usr/sprockets/bin/doslib
1872597524 65536 /usr/sprockets/bin/dosll
1872597524 65536 /usr/sprockets/bin/dosls
1872597524 65536 /usr/sprockets/bin/dosmkdir
1872597524 65536 /usr/sprockets/bin/dosrm
1872597524 65536 /usr/sprockets/bin/dosrmdir
1968087462 7112 /usr/sprockets/bin/enableNIS
3282246790 360 /usr/sprockets/bin/endexec
2151751185 553 /usr/sprockets/bin/endsession
3927613487 1115 /usr/sprockets/bin/env_var_sub
3738550324 157 /usr/sprockets/bin/format_dos
3888232633 172649 /usr/sprockets/bin/fppv
2279585942 466 /usr/sprockets/bin/getHostname
2946778792 5648 /usr/sprockets/bin/getSharedConnections
3306388627 20480 /usr/sprockets/bin/ibmsync
3041502972 28781 /usr/sprockets/bin/ipconfig700
3113659230 391815 /usr/sprockets/bin/kpp
908094753 24630 /usr/sprockets/bin/kxst
1329462070 36864 /usr/sprockets/bin/lanload
1015322628 36947 /usr/sprockets/bin/listener
486757159 339968 /usr/sprockets/bin/lmgrd
2620320940 339968 /usr/sprockets/bin/lmutil
951644065 243039 /usr/sprockets/bin/mattrib
951644065 243039 /usr/sprockets/bin/mbadblocks
951644065 243039 /usr/sprockets/bin/mcd
3650177936 951 /usr/sprockets/bin/mcheck
514586869 56 /usr/sprockets/bin/mcomp
951644065 243039 /usr/sprockets/bin/mcopy
951644065 243039 /usr/sprockets/bin/mdel
951644065 243039 /usr/sprockets/bin/mdeltree
951644065 243039 /usr/sprockets/bin/mdir
951644065 243039 /usr/sprockets/bin/mformat
951644065 243039 /usr/sprockets/bin/minfo
951644065 243039 /usr/sprockets/bin/mlabel
951644065 243039 /usr/sprockets/bin/mmd
951644065 243039 /usr/sprockets/bin/mmount
951644065 243039 /usr/sprockets/bin/mmove
951644065 243039 /usr/sprockets/bin/mpartition
662030829 1478557 /usr/sprockets/bin/mpv
951644065 243039 /usr/sprockets/bin/mrd
951644065 243039 /usr/sprockets/bin/mread
951644065 243039 /usr/sprockets/bin/mren
3443865238 32829 /usr/sprockets/bin/msgintcpt
951644065 243039 /usr/sprockets/bin/mtools
951644065 243039 /usr/sprockets/bin/mtoolstest
951644065 243039 /usr/sprockets/bin/mtype
951644065 243039 /usr/sprockets/bin/mwrite
1915353244 82 /usr/sprockets/bin/mxtar
951644065 243039 /usr/sprockets/bin/mzip
2033389047 379158 /usr/sprockets/bin/nmbd
1043940798 32843 /usr/sprockets/bin/nsbuild
421327339 32843 /usr/sprockets/bin/nsdump
2156955828 32843 /usr/sprockets/bin/nsquery
1030470949 28737 /usr/sprockets/bin/pciinfo
889541250 61560 /usr/sprockets/bin/pcipeek
1431205578 28737 /usr/sprockets/bin/pciprog
3351126604 126976 /usr/sprockets/bin/pkunzip
3351126604 126976 /usr/sprockets/bin/pkzip
2166142790 53390 /usr/sprockets/bin/probeload
694305221 41144 /usr/sprockets/bin/progflash
1141035887 445257 /usr/sprockets/bin/pv
974426301 3882 /usr/sprockets/bin/runnetscape
1879287959 1801 /usr/sprockets/bin/running
2273866242 74107 /usr/sprockets/bin/runroot
2616587298 79 /usr/sprockets/bin/runTouch
4222109660 875 /usr/sprockets/bin/samba
1912440105 24633 /usr/sprockets/bin/sbscrsvr
2558012300 3904 /usr/sprockets/bin/screensaverControl
4256537430 1780 /usr/sprockets/bin/sd-set_parms
1151924416 688 /usr/sprockets/bin/sendSignal
2744646624 32829 /usr/sprockets/bin/sessionDisallow
1227674200 1346161 /usr/sprockets/bin/sessionMgr
3332668870 98791 /usr/sprockets/bin/sessionWrapper
1477797090 82487 /usr/sprockets/bin/setlight
3759253613 1122 /usr/sprockets/bin/sharity
3313588847 3448000 /usr/sprockets/bin/sharityd
1569390236 24630 /usr/sprockets/bin/shmLock
3791448153 317300 /usr/sprockets/bin/smbclient
1018298877 506532 /usr/sprockets/bin/smbd
4009501079 45140 /usr/sprockets/bin/smtpclient
991996913 144424 /usr/sprockets/bin/starhw
3124681867 4311 /usr/sprockets/bin/startVNC
1468091312 919 /usr/sprockets/bin/startVNCviewer
304853428 1994350 /usr/sprockets/bin/sw_admin
304853428 1994350 /usr/sprockets/bin/sw_autoinstall
1455142555 123406 /usr/sprockets/bin/sw_copyfdset
2157175922 111102 /usr/sprockets/bin/sw_depot2bin
304853428 1994350 /usr/sprockets/bin/sw_install
304853428 1994350 /usr/sprockets/bin/sw_list
1842505403 7100 /usr/sprockets/bin/sw_makefdset
304853428 1994350 /usr/sprockets/bin/sw_remove
1743298644 2342 /usr/sprockets/bin/sw_rmprevious
1582083858 20548 /usr/sprockets/bin/sw_vendorfdset
178332129 1794 /usr/sprockets/bin/sysInfo
3657811479 1574 /usr/sprockets/bin/tgz
4018370132 36951 /usr/sprockets/bin/tp_license
1649141155 11843 /usr/sprockets/bin/updsharitycfg
2980018004 20480 /usr/sprockets/bin/ux2dos
3745508150 1318 /usr/sprockets/bin/uz
1348652714 32864 /usr/sprockets/bin/vncpasswd
4059637159 12757 /usr/sprockets/bin/vncserver
4128771573 366263 /usr/sprockets/bin/vncviewer
285011189 1526819 /usr/sprockets/bin/vp
589630079 387 /usr/sprockets/bin/vpexit
528762950 1132 /usr/sprockets/bin/xcopy
1793380080 521816 /usr/sprockets/bin/xscreensaver
24739470 145832 /usr/sprockets/bin/xscreensaver-command
4079099643 2167483 /usr/sprockets/bin/Xvnc
49651643 41091 /usr/sprockets/bin/yakdebug
2578809639 127914 /usr/sprockets/bin/yakhw
306877946 189649 /usr/sprockets/bin/yakserver
[-- Attachment #11: Test3d.sh --]
[-- Type: application/x-shellscript, Size: 923 bytes --]
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-05-26 14:44 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-22 15:13 freevxfs Krzysztof Błaszkowski
2016-05-23 8:23 ` freevxfs Carlos Maiolino
2016-05-24 11:50 ` freevxfs Krzysztof Błaszkowski
2016-05-23 8:36 ` freevxfs Christoph Hellwig
2016-05-24 8:48 ` freevxfs Krzysztof Błaszkowski
2016-05-25 21:27 freevxfs Krzysztof Błaszkowski
2016-05-26 11:50 ` freevxfs Carlos Maiolino
2016-05-26 14:44 ` freevxfs Krzysztof Błaszkowski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.