Message ID | 1463929994.6136.9.camel@linux-q3cb.site (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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);
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. -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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.
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); > >
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);