From: "Krzysztof Błaszkowski" <kb@sysmikro.com.pl>
To: linux-fsdevel@vger.kernel.org, hch@infradead.org
Subject: freevxfs
Date: Sun, 22 May 2016 17:13:14 +0200 [thread overview]
Message-ID: <1463929994.6136.9.camel@linux-q3cb.site> (raw)
[-- 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);
next reply other threads:[~2016-05-22 15:20 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-22 15:13 Krzysztof Błaszkowski [this message]
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
-- strict thread matches above, loose matches on Subject: below --
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1463929994.6136.9.camel@linux-q3cb.site \
--to=kb@sysmikro.com.pl \
--cc=hch@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).