From 0d83f7fc83f77d1cc8395b9e851325d8cc1892e3 Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Tue, 31 May 2016 08:45:13 +0200 Subject: freevxfs: handle big endian HP-UX file systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To support VxFS filesystems from HP-UX on x86 systems we need to implement byte swapping, and to keep support for Unixware filesystems it needs to be the complicated dual-endian kind ala sysvfs. To do this properly we have to split the on disk and in-core inode so that we can keep the in-core one in native endianness. All other structures are byteswapped on demand. Signed-off-by: Krzysztof Błaszkowski [hch: make spare happy] Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs.h | 177 ++++++++++++++++++++++++++-------------------- fs/freevxfs/vxfs_bmap.c | 70 ++++++++++-------- fs/freevxfs/vxfs_dir.h | 17 ++--- fs/freevxfs/vxfs_fshead.c | 5 +- fs/freevxfs/vxfs_fshead.h | 28 ++++---- fs/freevxfs/vxfs_inode.c | 31 +++++++- fs/freevxfs/vxfs_inode.h | 138 +++++++++++++++++++----------------- fs/freevxfs/vxfs_lookup.c | 34 +++++---- fs/freevxfs/vxfs_olt.c | 15 ++-- fs/freevxfs/vxfs_olt.h | 70 +++++++++--------- fs/freevxfs/vxfs_super.c | 101 ++++++++++++++++++-------- 11 files changed, 407 insertions(+), 279 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h index c8a92652612a..4b561ded5eb1 100644 --- a/fs/freevxfs/vxfs.h +++ b/fs/freevxfs/vxfs.h @@ -38,13 +38,6 @@ */ #include - -/* - * Data types for use with the VxFS ondisk format. - */ -typedef int32_t vx_daddr_t; -typedef int32_t vx_ino_t; - /* * Superblock magic number (vxfs_super->vs_magic). */ @@ -60,6 +53,14 @@ typedef int32_t vx_ino_t; */ #define VXFS_NEFREE 32 +enum vxfs_byte_order { + VXFS_BO_LE, + VXFS_BO_BE, +}; + +typedef __u16 __bitwise __fs16; +typedef __u32 __bitwise __fs32; +typedef __u64 __bitwise __fs64; /* * VxFS superblock (disk). @@ -71,83 +72,83 @@ struct vxfs_sb { * Lots of this fields are no more used by version 2 * and never filesystems. */ - u_int32_t vs_magic; /* Magic number */ - int32_t vs_version; /* VxFS version */ - u_int32_t vs_ctime; /* create time - secs */ - u_int32_t vs_cutime; /* create time - usecs */ - int32_t __unused1; /* unused */ - int32_t __unused2; /* unused */ - vx_daddr_t vs_old_logstart; /* obsolete */ - vx_daddr_t vs_old_logend; /* obsolete */ - int32_t vs_bsize; /* block size */ - int32_t vs_size; /* number of blocks */ - int32_t vs_dsize; /* number of data blocks */ - u_int32_t vs_old_ninode; /* obsolete */ - int32_t vs_old_nau; /* obsolete */ - int32_t __unused3; /* unused */ - int32_t vs_old_defiextsize; /* obsolete */ - int32_t vs_old_ilbsize; /* obsolete */ - int32_t vs_immedlen; /* size of immediate data area */ - int32_t vs_ndaddr; /* number of direct extentes */ - vx_daddr_t vs_firstau; /* address of first AU */ - vx_daddr_t vs_emap; /* offset of extent map in AU */ - vx_daddr_t vs_imap; /* offset of inode map in AU */ - vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */ - vx_daddr_t vs_istart; /* offset of inode list in AU */ - vx_daddr_t vs_bstart; /* offset of fdblock in AU */ - vx_daddr_t vs_femap; /* aufirst + emap */ - vx_daddr_t vs_fimap; /* aufirst + imap */ - vx_daddr_t vs_fiextop; /* aufirst + iextop */ - vx_daddr_t vs_fistart; /* aufirst + istart */ - vx_daddr_t vs_fbstart; /* aufirst + bstart */ - int32_t vs_nindir; /* number of entries in indir */ - int32_t vs_aulen; /* length of AU in blocks */ - int32_t vs_auimlen; /* length of imap in blocks */ - int32_t vs_auemlen; /* length of emap in blocks */ - int32_t vs_auilen; /* length of ilist in blocks */ - int32_t vs_aupad; /* length of pad in blocks */ - int32_t vs_aublocks; /* data blocks in AU */ - int32_t vs_maxtier; /* log base 2 of aublocks */ - int32_t vs_inopb; /* number of inodes per blk */ - int32_t vs_old_inopau; /* obsolete */ - int32_t vs_old_inopilb; /* obsolete */ - int32_t vs_old_ndiripau; /* obsolete */ - int32_t vs_iaddrlen; /* size of indirect addr ext. */ - int32_t vs_bshift; /* log base 2 of bsize */ - int32_t vs_inoshift; /* log base 2 of inobp */ - int32_t vs_bmask; /* ~( bsize - 1 ) */ - int32_t vs_boffmask; /* bsize - 1 */ - int32_t vs_old_inomask; /* old_inopilb - 1 */ - int32_t vs_checksum; /* checksum of V1 data */ + __fs32 vs_magic; /* Magic number */ + __fs32 vs_version; /* VxFS version */ + __fs32 vs_ctime; /* create time - secs */ + __fs32 vs_cutime; /* create time - usecs */ + __fs32 __unused1; /* unused */ + __fs32 __unused2; /* unused */ + __fs32 vs_old_logstart; /* obsolete */ + __fs32 vs_old_logend; /* obsolete */ + __fs32 vs_bsize; /* block size */ + __fs32 vs_size; /* number of blocks */ + __fs32 vs_dsize; /* number of data blocks */ + __fs32 vs_old_ninode; /* obsolete */ + __fs32 vs_old_nau; /* obsolete */ + __fs32 __unused3; /* unused */ + __fs32 vs_old_defiextsize; /* obsolete */ + __fs32 vs_old_ilbsize; /* obsolete */ + __fs32 vs_immedlen; /* size of immediate data area */ + __fs32 vs_ndaddr; /* number of direct extentes */ + __fs32 vs_firstau; /* address of first AU */ + __fs32 vs_emap; /* offset of extent map in AU */ + __fs32 vs_imap; /* offset of inode map in AU */ + __fs32 vs_iextop; /* offset of ExtOp. map in AU */ + __fs32 vs_istart; /* offset of inode list in AU */ + __fs32 vs_bstart; /* offset of fdblock in AU */ + __fs32 vs_femap; /* aufirst + emap */ + __fs32 vs_fimap; /* aufirst + imap */ + __fs32 vs_fiextop; /* aufirst + iextop */ + __fs32 vs_fistart; /* aufirst + istart */ + __fs32 vs_fbstart; /* aufirst + bstart */ + __fs32 vs_nindir; /* number of entries in indir */ + __fs32 vs_aulen; /* length of AU in blocks */ + __fs32 vs_auimlen; /* length of imap in blocks */ + __fs32 vs_auemlen; /* length of emap in blocks */ + __fs32 vs_auilen; /* length of ilist in blocks */ + __fs32 vs_aupad; /* length of pad in blocks */ + __fs32 vs_aublocks; /* data blocks in AU */ + __fs32 vs_maxtier; /* log base 2 of aublocks */ + __fs32 vs_inopb; /* number of inodes per blk */ + __fs32 vs_old_inopau; /* obsolete */ + __fs32 vs_old_inopilb; /* obsolete */ + __fs32 vs_old_ndiripau; /* obsolete */ + __fs32 vs_iaddrlen; /* size of indirect addr ext. */ + __fs32 vs_bshift; /* log base 2 of bsize */ + __fs32 vs_inoshift; /* log base 2 of inobp */ + __fs32 vs_bmask; /* ~( bsize - 1 ) */ + __fs32 vs_boffmask; /* bsize - 1 */ + __fs32 vs_old_inomask; /* old_inopilb - 1 */ + __fs32 vs_checksum; /* checksum of V1 data */ /* * Version 1, writable */ - int32_t vs_free; /* number of free blocks */ - int32_t vs_ifree; /* number of free inodes */ - int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */ - int32_t vs_flags; /* flags ?!? */ - u_int8_t vs_mod; /* filesystem has been changed */ - u_int8_t vs_clean; /* clean FS */ - u_int16_t __unused4; /* unused */ - u_int32_t vs_firstlogid; /* mount time log ID */ - u_int32_t vs_wtime; /* last time written - sec */ - u_int32_t vs_wutime; /* last time written - usec */ - u_int8_t vs_fname[6]; /* FS name */ - u_int8_t vs_fpack[6]; /* FS pack name */ - int32_t vs_logversion; /* log format version */ - int32_t __unused5; /* unused */ + __fs32 vs_free; /* number of free blocks */ + __fs32 vs_ifree; /* number of free inodes */ + __fs32 vs_efree[VXFS_NEFREE]; /* number of free extents by size */ + __fs32 vs_flags; /* flags ?!? */ + __u8 vs_mod; /* filesystem has been changed */ + __u8 vs_clean; /* clean FS */ + __fs16 __unused4; /* unused */ + __fs32 vs_firstlogid; /* mount time log ID */ + __fs32 vs_wtime; /* last time written - sec */ + __fs32 vs_wutime; /* last time written - usec */ + __u8 vs_fname[6]; /* FS name */ + __u8 vs_fpack[6]; /* FS pack name */ + __fs32 vs_logversion; /* log format version */ + __u32 __unused5; /* unused */ /* * Version 2, Read-only */ - vx_daddr_t vs_oltext[2]; /* OLT extent and replica */ - int32_t vs_oltsize; /* OLT extent size */ - int32_t vs_iauimlen; /* size of inode map */ - int32_t vs_iausize; /* size of IAU in blocks */ - int32_t vs_dinosize; /* size of inode in bytes */ - int32_t vs_old_dniaddr; /* indir levels per inode */ - int32_t vs_checksum2; /* checksum of V2 RO */ + __fs32 vs_oltext[2]; /* OLT extent and replica */ + __fs32 vs_oltsize; /* OLT extent size */ + __fs32 vs_iauimlen; /* size of inode map */ + __fs32 vs_iausize; /* size of IAU in blocks */ + __fs32 vs_dinosize; /* size of inode in bytes */ + __fs32 vs_old_dniaddr; /* indir levels per inode */ + __fs32 vs_checksum2; /* checksum of V2 RO */ /* * Actually much more... @@ -168,8 +169,32 @@ struct vxfs_sb_info { ino_t vsi_fshino; /* fileset header inode */ daddr_t vsi_oltext; /* OLT extent */ daddr_t vsi_oltsize; /* OLT size */ + enum vxfs_byte_order byte_order; }; +static inline u16 fs16_to_cpu(struct vxfs_sb_info *sbi, __fs16 a) +{ + if (sbi->byte_order == VXFS_BO_BE) + return be16_to_cpu((__force __be16)a); + else + return le16_to_cpu((__force __le16)a); +} + +static inline u32 fs32_to_cpu(struct vxfs_sb_info *sbi, __fs32 a) +{ + if (sbi->byte_order == VXFS_BO_BE) + return be32_to_cpu((__force __be32)a); + else + return le32_to_cpu((__force __le32)a); +} + +static inline u64 fs64_to_cpu(struct vxfs_sb_info *sbi, __fs64 a) +{ + if (sbi->byte_order == VXFS_BO_BE) + return be64_to_cpu((__force __be64)a); + else + return le64_to_cpu((__force __le64)a); +} /* * File modes. File types above 0xf000 are vxfs internal only, they should diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c index f86fd3cacd5a..1fd41cf98b9f 100644 --- a/fs/freevxfs/vxfs_bmap.c +++ b/fs/freevxfs/vxfs_bmap.c @@ -68,8 +68,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn) { struct super_block *sb = ip->i_sb; struct vxfs_inode_info *vip = VXFS_INO(ip); + struct vxfs_sb_info *sbi = VXFS_SBI(sb); unsigned long bsize = sb->s_blocksize; - u32 indsize = vip->vii_ext4.ve4_indsize; + u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize); int i; if (indsize > sb->s_blocksize) @@ -77,22 +78,24 @@ vxfs_bmap_ext4(struct inode *ip, long bn) for (i = 0; i < VXFS_NDADDR; i++) { struct direct *d = vip->vii_ext4.ve4_direct + i; - if (bn >= 0 && bn < d->size) - return (bn + d->extent); - bn -= d->size; + if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size)) + return (bn + fs32_to_cpu(sbi, d->extent)); + bn -= fs32_to_cpu(sbi, d->size); } if ((bn / (indsize * indsize * bsize / 4)) == 0) { struct buffer_head *buf; daddr_t bno; - u32 *indir; + __fs32 *indir; - buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]); + buf = sb_bread(sb, + fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0])); if (!buf || !buffer_mapped(buf)) goto fail_buf; - indir = (u32 *)buf->b_data; - bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize); + indir = (__fs32 *)buf->b_data; + bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) + + (bn % indsize); brelse(buf); return bno; @@ -127,6 +130,7 @@ fail_buf: static daddr_t vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) { + struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); struct buffer_head *bp = NULL; daddr_t pblock = 0; int i; @@ -142,24 +146,27 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) typ = ((struct vxfs_typed *)bp->b_data) + (i % VXFS_TYPED_PER_BLOCK(ip->i_sb)); - off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); + off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK; if (block < off) { brelse(bp); continue; } - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { + switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >> + VXFS_TYPED_TYPESHIFT)) { case VXFS_TYPED_INDIRECT: - pblock = vxfs_bmap_indir(ip, typ->vt_block, - typ->vt_size, block - off); + pblock = vxfs_bmap_indir(ip, + fs32_to_cpu(sbi, typ->vt_block), + fs32_to_cpu(sbi, typ->vt_size), + block - off); if (pblock == -2) break; goto out; case VXFS_TYPED_DATA: - if ((block - off) >= typ->vt_size) + if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size)) break; - pblock = (typ->vt_block + block - off); + pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off; goto out; case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_DATA_DEV4: { @@ -167,13 +174,15 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) (struct vxfs_typed_dev4 *)typ; printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", - (unsigned long long) typ4->vd4_block, - (unsigned long long) typ4->vd4_size, - typ4->vd4_dev); + printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n", + fs64_to_cpu(sbi, typ4->vd4_block), + fs64_to_cpu(sbi, typ4->vd4_size), + fs32_to_cpu(sbi, typ4->vd4_dev)); goto fail; } default: + printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__, + __LINE__, fs64_to_cpu(sbi, typ->vt_hdr)); BUG(); } brelse(bp); @@ -201,28 +210,33 @@ static daddr_t vxfs_bmap_typed(struct inode *ip, long iblock) { struct vxfs_inode_info *vip = VXFS_INO(ip); + struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); daddr_t pblock = 0; int i; for (i = 0; i < VXFS_NTYPED; i++) { struct vxfs_typed *typ = vip->vii_org.typed + i; - int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK); + u64 hdr = fs64_to_cpu(sbi, typ->vt_hdr); + int64_t off = (hdr & VXFS_TYPED_OFFSETMASK); #ifdef DIAGNOSTIC vxfs_typdump(typ); #endif if (iblock < off) continue; - switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { + switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) { case VXFS_TYPED_INDIRECT: - pblock = vxfs_bmap_indir(ip, typ->vt_block, - typ->vt_size, iblock - off); + pblock = vxfs_bmap_indir(ip, + fs32_to_cpu(sbi, typ->vt_block), + fs32_to_cpu(sbi, typ->vt_size), + iblock - off); if (pblock == -2) break; return (pblock); case VXFS_TYPED_DATA: - if ((iblock - off) < typ->vt_size) - return (typ->vt_block + iblock - off); + if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size)) + return (fs32_to_cpu(sbi, typ->vt_block) + + iblock - off); break; case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_DATA_DEV4: { @@ -230,10 +244,10 @@ vxfs_bmap_typed(struct inode *ip, long iblock) (struct vxfs_typed_dev4 *)typ; printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); - printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", - (unsigned long long) typ4->vd4_block, - (unsigned long long) typ4->vd4_size, - typ4->vd4_dev); + printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n", + fs64_to_cpu(sbi, typ4->vd4_block), + fs64_to_cpu(sbi, typ4->vd4_size), + fs32_to_cpu(sbi, typ4->vd4_dev)); return 0; } default: diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h index aaf1fb098639..acc5477b3f23 100644 --- a/fs/freevxfs/vxfs_dir.h +++ b/fs/freevxfs/vxfs_dir.h @@ -48,9 +48,9 @@ * Linux driver for now. */ struct vxfs_dirblk { - u_int16_t d_free; /* free space in dirblock */ - u_int16_t d_nhash; /* no of hash chains */ - u_int16_t d_hash[1]; /* hash chain */ + __fs16 d_free; /* free space in dirblock */ + __fs16 d_nhash; /* no of hash chains */ + __fs16 d_hash[1]; /* hash chain */ }; /* @@ -63,10 +63,10 @@ struct vxfs_dirblk { * VxFS directory entry. */ struct vxfs_direct { - vx_ino_t d_ino; /* inode number */ - u_int16_t d_reclen; /* record length */ - u_int16_t d_namelen; /* d_name length */ - u_int16_t d_hashnext; /* next hash entry */ + __fs32 d_ino; /* inode number */ + __fs16 d_reclen; /* record length */ + __fs16 d_namelen; /* d_name length */ + __fs16 d_hashnext; /* next hash entry */ char d_name[VXFS_NAMELEN]; /* name */ }; @@ -87,6 +87,7 @@ struct vxfs_direct { /* * VXFS_DIRBLKOV is the overhead of a specific dirblock. */ -#define VXFS_DIRBLKOV(dbp) ((sizeof(short) * dbp->d_nhash) + 4) +#define VXFS_DIRBLKOV(sbi, dbp) \ + ((sizeof(short) * fs16_to_cpu(sbi, dbp->d_nhash)) + 4) #endif /* _VXFS_DIR_H_ */ diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c index c9a6a94e58e9..e7501cb85321 100644 --- a/fs/freevxfs/vxfs_fshead.c +++ b/fs/freevxfs/vxfs_fshead.c @@ -153,7 +153,8 @@ vxfs_read_fshead(struct super_block *sbp) vxfs_dumpfsh(pfp); #endif - tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]); + tip = vxfs_blkiget(sbp, infp->vsi_iext, + fs32_to_cpu(infp, sfp->fsh_ilistino[0])); if (!tip) goto out_free_pfp; @@ -169,7 +170,7 @@ vxfs_read_fshead(struct super_block *sbp) goto out_iput_stilist; } - tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]); + tip = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0])); if (!tip) goto out_iput_stilist; infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); diff --git a/fs/freevxfs/vxfs_fshead.h b/fs/freevxfs/vxfs_fshead.h index ead0d640c181..a786cc55509c 100644 --- a/fs/freevxfs/vxfs_fshead.h +++ b/fs/freevxfs/vxfs_fshead.h @@ -42,20 +42,20 @@ * Fileset header */ struct vxfs_fsh { - u_int32_t fsh_version; /* fileset header version */ - u_int32_t fsh_fsindex; /* fileset index */ - u_int32_t fsh_time; /* modification time - sec */ - u_int32_t fsh_utime; /* modification time - usec */ - u_int32_t fsh_extop; /* extop flags */ - vx_ino_t fsh_ninodes; /* allocated inodes */ - u_int32_t fsh_nau; /* number of IAUs */ - u_int32_t fsh_old_ilesize; /* old size of ilist */ - u_int32_t fsh_dflags; /* flags */ - u_int32_t fsh_quota; /* quota limit */ - vx_ino_t fsh_maxinode; /* maximum inode number */ - vx_ino_t fsh_iauino; /* IAU inode */ - vx_ino_t fsh_ilistino[2]; /* ilist inodes */ - vx_ino_t fsh_lctino; /* link count table inode */ + __fs32 fsh_version; /* fileset header version */ + __fs32 fsh_fsindex; /* fileset index */ + __fs32 fsh_time; /* modification time - sec */ + __fs32 fsh_utime; /* modification time - usec */ + __fs32 fsh_extop; /* extop flags */ + __fs32 fsh_ninodes; /* allocated inodes */ + __fs32 fsh_nau; /* number of IAUs */ + __fs32 fsh_old_ilesize; /* old size of ilist */ + __fs32 fsh_dflags; /* flags */ + __fs32 fsh_quota; /* quota limit */ + __fs32 fsh_maxinode; /* maximum inode number */ + __fs32 fsh_iauino; /* IAU inode */ + __fs32 fsh_ilistino[2]; /* ilist inodes */ + __fs32 fsh_lctino; /* link count table inode */ /* * Slightly more fields follow, but they diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 3e2ccade61ed..15de300a3ac6 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -68,6 +68,33 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) } #endif +static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, + struct vxfs_inode_info *vip, struct vxfs_dinode *dip) +{ + vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode); + vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink); + vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid); + vip->vii_gid = fs32_to_cpu(sbi, dip->vdi_gid); + vip->vii_size = fs64_to_cpu(sbi, dip->vdi_size); + vip->vii_atime = fs32_to_cpu(sbi, dip->vdi_atime); + vip->vii_autime = fs32_to_cpu(sbi, dip->vdi_autime); + vip->vii_mtime = fs32_to_cpu(sbi, dip->vdi_mtime); + vip->vii_mutime = fs32_to_cpu(sbi, dip->vdi_mutime); + vip->vii_ctime = fs32_to_cpu(sbi, dip->vdi_ctime); + vip->vii_cutime = fs32_to_cpu(sbi, dip->vdi_cutime); + vip->vii_orgtype = dip->vdi_orgtype; + + vip->vii_blocks = fs32_to_cpu(sbi, dip->vdi_blocks); + vip->vii_gen = fs32_to_cpu(sbi, dip->vdi_gen); + + if (VXFS_ISDIR(vip)) + vip->vii_dotdot = fs32_to_cpu(sbi, dip->vdi_dotdot); + else if (!VXFS_ISREG(vip) && !VXFS_ISLNK(vip)) + vip->vii_rdev = fs32_to_cpu(sbi, dip->vdi_rdev); + + /* don't endian swap the fields that differ by orgtype */ + memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org)); +} /** * vxfs_blkiget - find inode based on extent # @@ -102,7 +129,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(VXFS_SBI(sbp), vip, dip); #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif @@ -144,7 +171,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(VXFS_SBI(ilistp->i_sb), vip, dip); #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h index 240aeb11263f..93d01148e5db 100644 --- a/fs/freevxfs/vxfs_inode.h +++ b/fs/freevxfs/vxfs_inode.h @@ -66,74 +66,74 @@ enum { * Data stored immediately in the inode. */ struct vxfs_immed { - u_int8_t vi_immed[VXFS_NIMMED]; + __u8 vi_immed[VXFS_NIMMED]; }; struct vxfs_ext4 { - u_int32_t ve4_spare; /* ?? */ - u_int32_t ve4_indsize; /* Indirect extent size */ - vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */ + __fs32 ve4_spare; /* ?? */ + __fs32 ve4_indsize; /* Indirect extent size */ + __fs32 ve4_indir[VXFS_NIADDR]; /* Indirect extents */ struct direct { /* Direct extents */ - vx_daddr_t extent; /* Extent number */ - int32_t size; /* Size of extent */ + __fs32 extent; /* Extent number */ + __fs32 size; /* Size of extent */ } ve4_direct[VXFS_NDADDR]; }; struct vxfs_typed { - u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ - vx_daddr_t vt_block; /* Extent block */ - int32_t vt_size; /* Size in blocks */ + __fs64 vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ + __fs32 vt_block; /* Extent block */ + __fs32 vt_size; /* Size in blocks */ }; struct vxfs_typed_dev4 { - u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ - u_int64_t vd4_block; /* Extent block */ - u_int64_t vd4_size; /* Size in blocks */ - int32_t vd4_dev; /* Device ID */ - u_int32_t __pad1; + __fs64 vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ + __fs64 vd4_block; /* Extent block */ + __fs64 vd4_size; /* Size in blocks */ + __fs32 vd4_dev; /* Device ID */ + __u8 __pad1; }; /* * The inode as contained on the physical device. */ struct vxfs_dinode { - int32_t vdi_mode; - u_int32_t vdi_nlink; /* Link count */ - u_int32_t vdi_uid; /* UID */ - u_int32_t vdi_gid; /* GID */ - u_int64_t vdi_size; /* Inode size in bytes */ - u_int32_t vdi_atime; /* Last time accessed - sec */ - u_int32_t vdi_autime; /* Last time accessed - usec */ - u_int32_t vdi_mtime; /* Last modify time - sec */ - u_int32_t vdi_mutime; /* Last modify time - usec */ - u_int32_t vdi_ctime; /* Create time - sec */ - u_int32_t vdi_cutime; /* Create time - usec */ - u_int8_t vdi_aflags; /* Allocation flags */ - u_int8_t vdi_orgtype; /* Organisation type */ - u_int16_t vdi_eopflags; - u_int32_t vdi_eopdata; + __fs32 vdi_mode; + __fs32 vdi_nlink; /* Link count */ + __fs32 vdi_uid; /* UID */ + __fs32 vdi_gid; /* GID */ + __fs64 vdi_size; /* Inode size in bytes */ + __fs32 vdi_atime; /* Last time accessed - sec */ + __fs32 vdi_autime; /* Last time accessed - usec */ + __fs32 vdi_mtime; /* Last modify time - sec */ + __fs32 vdi_mutime; /* Last modify time - usec */ + __fs32 vdi_ctime; /* Create time - sec */ + __fs32 vdi_cutime; /* Create time - usec */ + __u8 vdi_aflags; /* Allocation flags */ + __u8 vdi_orgtype; /* Organisation type */ + __fs16 vdi_eopflags; + __fs32 vdi_eopdata; union { - u_int32_t rdev; - u_int32_t dotdot; + __fs32 rdev; + __fs32 dotdot; struct { - u_int32_t reserved; - u_int32_t fixextsize; + __u32 reserved; + __fs32 fixextsize; } i_regular; struct { - u_int32_t matchino; - u_int32_t fsetindex; + __fs32 matchino; + __fs32 fsetindex; } i_vxspec; - u_int64_t align; + __u64 align; } vdi_ftarea; - u_int32_t vdi_blocks; /* How much blocks does inode occupy */ - u_int32_t vdi_gen; /* Inode generation */ - u_int64_t vdi_version; /* Version */ + __fs32 vdi_blocks; /* How much blocks does inode occupy */ + __fs32 vdi_gen; /* Inode generation */ + __fs64 vdi_version; /* Version */ union { struct vxfs_immed immed; struct vxfs_ext4 ext4; struct vxfs_typed typed[VXFS_NTYPED]; } vdi_org; - u_int32_t vdi_iattrino; + __fs32 vdi_iattrino; }; #define vdi_rdev vdi_ftarea.rdev @@ -149,32 +149,38 @@ struct vxfs_dinode { /* * The inode as represented in the main memory. - * - * TBD: This should become a separate structure... */ -#define vxfs_inode_info vxfs_dinode - -#define vii_mode vdi_mode -#define vii_uid vdi_uid -#define vii_gid vdi_gid -#define vii_nlink vdi_nlink -#define vii_size vdi_size -#define vii_atime vdi_atime -#define vii_ctime vdi_ctime -#define vii_mtime vdi_mtime -#define vii_blocks vdi_blocks -#define vii_org vdi_org -#define vii_orgtype vdi_orgtype -#define vii_gen vdi_gen - -#define vii_rdev vdi_ftarea.rdev -#define vii_dotdot vdi_ftarea.dotdot -#define vii_fixextsize vdi_ftarea.regular.fixextsize -#define vii_matchino vdi_ftarea.vxspec.matchino -#define vii_fsetindex vdi_ftarea.vxspec.fsetindex - -#define vii_immed vdi_org.immed -#define vii_ext4 vdi_org.ext4 -#define vii_typed vdi_org.typed +struct vxfs_inode_info { + __u32 vii_mode; + __u32 vii_nlink; /* Link count */ + __u32 vii_uid; /* UID */ + __u32 vii_gid; /* GID */ + __u64 vii_size; /* Inode size in bytes */ + __u32 vii_atime; /* Last time accessed - sec */ + __u32 vii_autime; /* Last time accessed - usec */ + __u32 vii_mtime; /* Last modify time - sec */ + __u32 vii_mutime; /* Last modify time - usec */ + __u32 vii_ctime; /* Create time - sec */ + __u32 vii_cutime; /* Create time - usec */ + __u8 vii_orgtype; /* Organisation type */ + union { + __u32 rdev; + __u32 dotdot; + } vii_ftarea; + __u32 vii_blocks; /* How much blocks does inode occupy */ + __u32 vii_gen; /* Inode generation */ + union { + struct vxfs_immed immed; + struct vxfs_ext4 ext4; + struct vxfs_typed typed[VXFS_NTYPED]; + } vii_org; +}; + +#define vii_rdev vii_ftarea.rdev +#define vii_dotdot vii_ftarea.dotdot + +#define vii_immed vii_org.immed +#define vii_ext4 vii_org.ext4 +#define vii_typed vii_org.typed #endif /* _VXFS_INODE_H_ */ diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 6d576b97f2c8..09e93b3a1582 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -74,9 +74,10 @@ dir_blocks(struct inode *ip) * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller. */ static inline int -vxfs_match(int len, const char * const name, struct vxfs_direct *de) +vxfs_match(struct vxfs_sb_info *sbi, int len, const char *const name, + struct vxfs_direct *de) { - if (len != de->d_namelen) + if (len != fs16_to_cpu(sbi, de->d_namelen)) return 0; if (!de->d_ino) return 0; @@ -84,9 +85,10 @@ vxfs_match(int len, const char * const name, struct vxfs_direct *de) } static inline struct vxfs_direct * -vxfs_next_entry(struct vxfs_direct *de) +vxfs_next_entry(struct vxfs_sb_info *sbi, struct vxfs_direct *de) { - return ((struct vxfs_direct *)((char*)de + de->d_reclen)); + return ((struct vxfs_direct *) + ((char *)de + fs16_to_cpu(sbi, de->d_reclen))); } /** @@ -106,6 +108,7 @@ vxfs_next_entry(struct vxfs_direct *de) static struct vxfs_direct * vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) { + struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); u_long npages, page, nblocks, pblocks, block; u_long bsize = ip->i_sb->s_blocksize; const char *name = dp->d_name.name; @@ -133,14 +136,16 @@ vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) limit = baddr + bsize - VXFS_DIRLEN(1); dbp = (struct vxfs_dirblk *)baddr; - de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp)); + de = (struct vxfs_direct *) + (baddr + VXFS_DIRBLKOV(sbi, dbp)); - for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) { + for (; (caddr_t)de <= limit; + de = vxfs_next_entry(sbi, de)) { if (!de->d_reclen) break; if (!de->d_ino) continue; - if (vxfs_match(namelen, name, de)) { + if (vxfs_match(sbi, namelen, name, de)) { *ppp = pp; return (de); } @@ -173,7 +178,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp) de = vxfs_find_entry(dip, dp, &pp); if (de) { - ino = de->d_ino; + ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino); kunmap(pp); put_page(pp); } @@ -232,10 +237,12 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx) { struct inode *ip = file_inode(fp); struct super_block *sbp = ip->i_sb; + struct vxfs_sb_info *sbi = VXFS_SBI(sbp); u_long bsize = sbp->s_blocksize; u_long page, npages, block, pblocks, nblocks, offset; loff_t pos; + if (ctx->pos == 0) { if (!dir_emit_dot(fp, ctx)) return 0; @@ -280,9 +287,10 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx) de = (struct vxfs_direct *) (offset ? (kaddr + offset) : - (baddr + VXFS_DIRBLKOV(dbp))); + (baddr + VXFS_DIRBLKOV(sbi, dbp))); - for (; (char *)de <= limit; de = vxfs_next_entry(de)) { + for (; (char *)de <= limit; + de = vxfs_next_entry(sbi, de)) { if (!de->d_reclen) break; if (!de->d_ino) @@ -290,8 +298,10 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx) offset = (char *)de - kaddr; ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; - if (!dir_emit(ctx, de->d_name, de->d_namelen, - de->d_ino, DT_UNKNOWN)) { + if (!dir_emit(ctx, de->d_name, + fs16_to_cpu(sbi, de->d_namelen), + fs32_to_cpu(sbi, de->d_ino), + DT_UNKNOWN)) { vxfs_put_page(pp); return 0; } diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c index 049500847903..813da6685151 100644 --- a/fs/freevxfs/vxfs_olt.c +++ b/fs/freevxfs/vxfs_olt.c @@ -43,14 +43,14 @@ static inline void vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) { BUG_ON(infp->vsi_fshino); - infp->vsi_fshino = fshp->olt_fsino[0]; + infp->vsi_fshino = fs32_to_cpu(infp, fshp->olt_fsino[0]); } static inline void vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) { BUG_ON(infp->vsi_iext); - infp->vsi_iext = ilistp->olt_iext[0]; + infp->vsi_iext = fs32_to_cpu(infp, ilistp->olt_iext[0]); } static inline u_long @@ -81,13 +81,12 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize) struct vxfs_olt *op; char *oaddr, *eaddr; - bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize)); if (!bp || !bp->b_data) goto fail; op = (struct vxfs_olt *)bp->b_data; - if (op->olt_magic != VXFS_OLT_MAGIC) { + if (fs32_to_cpu(infp, op->olt_magic) != VXFS_OLT_MAGIC) { printk(KERN_NOTICE "vxfs: ivalid olt magic number\n"); goto fail; } @@ -102,14 +101,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize) goto fail; } - oaddr = bp->b_data + op->olt_size; + oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size); eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize); while (oaddr < eaddr) { struct vxfs_oltcommon *ocp = (struct vxfs_oltcommon *)oaddr; - switch (ocp->olt_type) { + switch (fs32_to_cpu(infp, ocp->olt_type)) { case VXFS_OLT_FSHEAD: vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp); break; @@ -118,11 +117,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize) break; } - oaddr += ocp->olt_size; + oaddr += fs32_to_cpu(infp, ocp->olt_size); } brelse(bp); - return 0; + return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL; fail: brelse(bp); diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h index b7b3af502615..0c0b0c9fa557 100644 --- a/fs/freevxfs/vxfs_olt.h +++ b/fs/freevxfs/vxfs_olt.h @@ -63,83 +63,83 @@ enum { * the initial inode list, the fileset header or the device configuration. */ struct vxfs_olt { - u_int32_t olt_magic; /* magic number */ - u_int32_t olt_size; /* size of this entry */ - u_int32_t olt_checksum; /* checksum of extent */ - u_int32_t __unused1; /* ??? */ - u_int32_t olt_mtime; /* time of last mod. (sec) */ - u_int32_t olt_mutime; /* time of last mod. (usec) */ - u_int32_t olt_totfree; /* free space in OLT extent */ - vx_daddr_t olt_extents[2]; /* addr of this extent, replica */ - u_int32_t olt_esize; /* size of this extent */ - vx_daddr_t olt_next[2]; /* addr of next extent, replica */ - u_int32_t olt_nsize; /* size of next extent */ - u_int32_t __unused2; /* align to 8 byte boundary */ + __fs32 olt_magic; /* magic number */ + __fs32 olt_size; /* size of this entry */ + __fs32 olt_checksum; /* checksum of extent */ + __u32 __unused1; /* ??? */ + __fs32 olt_mtime; /* time of last mod. (sec) */ + __fs32 olt_mutime; /* time of last mod. (usec) */ + __fs32 olt_totfree; /* free space in OLT extent */ + __fs32 olt_extents[2]; /* addr of this extent, replica */ + __fs32 olt_esize; /* size of this extent */ + __fs32 olt_next[2]; /* addr of next extent, replica */ + __fs32 olt_nsize; /* size of next extent */ + __u32 __unused2; /* align to 8 byte boundary */ }; /* * VxFS common OLT entry (on disk). */ struct vxfs_oltcommon { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ }; /* * VxFS free OLT entry (on disk). */ struct vxfs_oltfree { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_fsize; /* size of this free record */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_fsize; /* size of this free record */ }; /* * VxFS initial-inode list (on disk). */ struct vxfs_oltilist { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_iext[2]; /* initial inode list, replica */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_iext[2]; /* initial inode list, replica */ }; /* * Current Usage Table */ struct vxfs_oltcut { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_cutino; /* inode of current usage table */ - u_int32_t __pad; /* unused, 8 byte align */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_cutino; /* inode of current usage table */ + __u8 __pad; /* unused, 8 byte align */ }; /* * Inodes containing Superblock, Intent log and OLTs */ struct vxfs_oltsb { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_sbino; /* inode of superblock file */ - u_int32_t __unused1; /* ??? */ - vx_ino_t olt_logino[2]; /* inode of log file,replica */ - vx_ino_t olt_oltino[2]; /* inode of OLT, replica */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_sbino; /* inode of superblock file */ + __u32 __unused1; /* ??? */ + __fs32 olt_logino[2]; /* inode of log file,replica */ + __fs32 olt_oltino[2]; /* inode of OLT, replica */ }; /* * Inode containing device configuration + it's replica */ struct vxfs_oltdev { - u_int32_t olt_type; /* type of this record */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_devino[2]; /* inode of device config files */ + __fs32 olt_type; /* type of this record */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_devino[2]; /* inode of device config files */ }; /* * Fileset header */ struct vxfs_oltfshead { - u_int32_t olt_type; /* type number */ - u_int32_t olt_size; /* size of this record */ - vx_ino_t olt_fsino[2]; /* inodes of fileset header */ + __fs32 olt_type; /* type number */ + __fs32 olt_size; /* size of this record */ + __fs32 olt_fsino[2]; /* inodes of fileset header */ }; #endif /* _VXFS_OLT_H_ */ diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 7ca8c75d50d3..6124091b4fdb 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -109,14 +109,15 @@ static int vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) { struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb); + struct vxfs_sb *raw_sb = infp->vsi_raw; bufp->f_type = VXFS_SUPER_MAGIC; bufp->f_bsize = dentry->d_sb->s_blocksize; - bufp->f_blocks = infp->vsi_raw->vs_dsize; - bufp->f_bfree = infp->vsi_raw->vs_free; + bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize); + bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free); bufp->f_bavail = 0; bufp->f_files = 0; - bufp->f_ffree = infp->vsi_raw->vs_ifree; + bufp->f_ffree = fs32_to_cpu(infp, raw_sb->vs_ifree); bufp->f_namelen = VXFS_NAMELEN; return 0; @@ -129,6 +130,50 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) return 0; } + +static int vxfs_try_sb_magic(struct super_block *sbp, int silent, + unsigned blk, __fs32 magic) +{ + struct buffer_head *bp; + struct vxfs_sb *rsbp; + struct vxfs_sb_info *infp = VXFS_SBI(sbp); + int rc = -ENOMEM; + + bp = sb_bread(sbp, blk); + do { + if (!bp || !buffer_mapped(bp)) { + if (!silent) { + printk(KERN_WARNING + "vxfs: unable to read disk superblock at %u\n", + blk); + } + break; + } + + rc = -EINVAL; + rsbp = (struct vxfs_sb *)bp->b_data; + if (rsbp->vs_magic != magic) { + if (!silent) + printk(KERN_NOTICE + "vxfs: WRONG superblock magic %08x at %u\n", + rsbp->vs_magic, blk); + break; + } + + rc = 0; + infp->vsi_raw = rsbp; + infp->vsi_bp = bp; + } while (0); + + if (rc) { + infp->vsi_raw = NULL; + infp->vsi_bp = NULL; + brelse(bp); + } + + return rc; +} + /** * vxfs_read_super - read superblock into memory and initialize filesystem * @sbp: VFS superblock (to fill) @@ -149,10 +194,10 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) { struct vxfs_sb_info *infp; struct vxfs_sb *rsbp; - struct buffer_head *bp = NULL; u_long bsize; struct inode *root; int ret = -EINVAL; + u32 j; sbp->s_flags |= MS_RDONLY; @@ -168,42 +213,42 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) goto out; } - bp = sb_bread(sbp, 1); - if (!bp || !buffer_mapped(bp)) { - if (!silent) { - printk(KERN_WARNING - "vxfs: unable to read disk superblock\n"); - } - goto out; - } + sbp->s_fs_info = infp; - rsbp = (struct vxfs_sb *)bp->b_data; - if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { + if (!vxfs_try_sb_magic(sbp, silent, 1, + (__force __fs32)cpu_to_le32(VXFS_SUPER_MAGIC))) { + /* Unixware, x86 */ + infp->byte_order = VXFS_BO_LE; + } else if (!vxfs_try_sb_magic(sbp, silent, 8, + (__force __fs32)cpu_to_be32(VXFS_SUPER_MAGIC))) { + /* HP-UX, parisc */ + infp->byte_order = VXFS_BO_BE; + } else { if (!silent) - printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); + printk(KERN_NOTICE "vxfs: can't find superblock.\n"); goto out; } - if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) { - printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", - rsbp->vs_version); + rsbp = infp->vsi_raw; + j = fs32_to_cpu(infp, rsbp->vs_version); + if ((j < 2 || j > 4) && !silent) { + printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j); goto out; } #ifdef DIAGNOSTIC - printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version); - printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize); + printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j); + printk(KERN_DEBUG "vxfs: blocksize: %d\n", + fs32_to_cpu(infp, rsbp->vs_bsize)); #endif - sbp->s_magic = rsbp->vs_magic; - sbp->s_fs_info = infp; + sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic); - infp->vsi_raw = rsbp; - infp->vsi_bp = bp; - infp->vsi_oltext = rsbp->vs_oltext[0]; - infp->vsi_oltsize = rsbp->vs_oltsize; + infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]); + infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize); - if (!sb_set_blocksize(sbp, rsbp->vs_bsize)) { + j = fs32_to_cpu(infp, rsbp->vs_bsize); + if (!sb_set_blocksize(sbp, j)) { printk(KERN_WARNING "vxfs: unable to set final block size\n"); goto out; } @@ -237,7 +282,7 @@ out_free_ilist: vxfs_put_fake_inode(infp->vsi_ilist); vxfs_put_fake_inode(infp->vsi_stilist); out: - brelse(bp); + brelse(infp->vsi_bp); kfree(infp); return ret; } -- cgit v1.2.3 From 0e481d3c0964ef00ff3dc9f25508980619e28752 Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Wed, 1 Jun 2016 08:41:11 +0200 Subject: freevxfs: remove vxfs_put_fake_inode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Błaszkowski [hch: split from a larget patch] Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs_extern.h | 1 - fs/freevxfs/vxfs_inode.c | 13 ------------- fs/freevxfs/vxfs_super.c | 12 ++++++------ 3 files changed, 6 insertions(+), 20 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index e3dcb4467d92..b59df797665f 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -56,7 +56,6 @@ extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); extern struct inode * vxfs_get_fake_inode(struct super_block *, struct vxfs_inode_info *); -extern void vxfs_put_fake_inode(struct inode *); extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t); extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t); extern struct inode * vxfs_iget(struct super_block *, ino_t); diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 15de300a3ac6..6087ca703f12 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -295,19 +295,6 @@ vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) return (ip); } -/** - * vxfs_put_fake_inode - free faked inode - * *ip: VFS inode - * - * Description: - * vxfs_put_fake_inode frees all data associated with @ip. - */ -void -vxfs_put_fake_inode(struct inode *ip) -{ - iput(ip); -} - /** * vxfs_iget - get an inode * @sbp: the superblock to get the inode for diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 6124091b4fdb..daf58a9fae70 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -79,9 +79,9 @@ vxfs_put_super(struct super_block *sbp) { struct vxfs_sb_info *infp = VXFS_SBI(sbp); - vxfs_put_fake_inode(infp->vsi_fship); - vxfs_put_fake_inode(infp->vsi_ilist); - vxfs_put_fake_inode(infp->vsi_stilist); + iput(infp->vsi_fship); + iput(infp->vsi_ilist); + iput(infp->vsi_stilist); brelse(infp->vsi_bp); kfree(infp); @@ -278,9 +278,9 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) return 0; out_free_ilist: - vxfs_put_fake_inode(infp->vsi_fship); - vxfs_put_fake_inode(infp->vsi_ilist); - vxfs_put_fake_inode(infp->vsi_stilist); + iput(infp->vsi_fship); + iput(infp->vsi_ilist); + iput(infp->vsi_stilist); out: brelse(infp->vsi_bp); kfree(infp); -- cgit v1.2.3 From 8985f53ee2eaa503c22e2fc90e81b1fb8e547ab4 Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Wed, 1 Jun 2016 08:56:04 +0200 Subject: freevxfs: move VFS inode allocation into vxfs_blkiget and vxfs_stiget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Błaszkowski [hch: split from a larger patch] Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs_extern.h | 8 +++----- fs/freevxfs/vxfs_fshead.c | 33 ++++++++------------------------- fs/freevxfs/vxfs_inode.c | 27 ++++++++++++++++++++------- 3 files changed, 31 insertions(+), 37 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index b59df797665f..2ec8c0f27865 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -54,11 +54,9 @@ extern int vxfs_read_fshead(struct super_block *); extern const struct address_space_operations vxfs_immed_aops; extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); -extern struct inode * vxfs_get_fake_inode(struct super_block *, - struct vxfs_inode_info *); -extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t); -extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t); -extern struct inode * vxfs_iget(struct super_block *, ino_t); +extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t); +extern struct inode *vxfs_stiget(struct super_block *, ino_t); +extern struct inode *vxfs_iget(struct super_block *, ino_t); extern void vxfs_evict_inode(struct inode *); /* vxfs_lookup.c */ diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c index e7501cb85321..2651b4238eb2 100644 --- a/fs/freevxfs/vxfs_fshead.c +++ b/fs/freevxfs/vxfs_fshead.c @@ -108,31 +108,26 @@ vxfs_read_fshead(struct super_block *sbp) { struct vxfs_sb_info *infp = VXFS_SBI(sbp); struct vxfs_fsh *pfp, *sfp; - struct vxfs_inode_info *vip, *tip; + struct vxfs_inode_info *vip; - vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); - if (!vip) { + infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino); + if (!infp->vsi_fship) { printk(KERN_ERR "vxfs: unable to read fsh inode\n"); return -EINVAL; } + + vip = VXFS_INO(infp->vsi_fship); if (!VXFS_ISFSH(vip)) { printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n", vip->vii_mode & VXFS_TYPE_MASK); - goto out_free_fship; + goto out_iput_fship; } - #ifdef DIAGNOSTIC printk("vxfs: fsh inode dump:\n"); vxfs_dumpi(vip, infp->vsi_fshino); #endif - infp->vsi_fship = vxfs_get_fake_inode(sbp, vip); - if (!infp->vsi_fship) { - printk(KERN_ERR "vxfs: unable to get fsh inode\n"); - goto out_free_fship; - } - sfp = vxfs_getfsh(infp->vsi_fship, 0); if (!sfp) { printk(KERN_ERR "vxfs: unable to get structural fsh\n"); @@ -153,15 +148,10 @@ vxfs_read_fshead(struct super_block *sbp) vxfs_dumpfsh(pfp); #endif - tip = vxfs_blkiget(sbp, infp->vsi_iext, + infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext, fs32_to_cpu(infp, sfp->fsh_ilistino[0])); - if (!tip) - goto out_free_pfp; - - 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); goto out_free_pfp; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) { @@ -170,13 +160,9 @@ vxfs_read_fshead(struct super_block *sbp) goto out_iput_stilist; } - tip = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0])); - if (!tip) - goto out_iput_stilist; - infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); + infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0])); if (!infp->vsi_ilist) { printk(KERN_ERR "vxfs: unable to get inode list inode\n"); - kfree(tip); goto out_iput_stilist; } if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) { @@ -198,7 +184,4 @@ vxfs_read_fshead(struct super_block *sbp) out_iput_fship: iput(infp->vsi_fship); return -EINVAL; - out_free_fship: - kfree(vip); - return -EINVAL; } diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 6087ca703f12..7b5de83405f2 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -44,6 +44,8 @@ struct kmem_cache *vxfs_inode_cachep; +static struct inode * vxfs_get_fake_inode(struct super_block *, + struct vxfs_inode_info *); #ifdef DIAGNOSTIC /* @@ -112,10 +114,11 @@ static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, * buffercache. This function should not be used outside the * read_super() method, otherwise the data may be incoherent. */ -struct vxfs_inode_info * +struct inode * vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) { struct buffer_head *bp; + struct inode *inode; u_long block, offset; block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); @@ -134,7 +137,11 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) vxfs_dumpi(vip, ino); #endif brelse(bp); - return (vip); + + inode = vxfs_get_fake_inode(sbp, vip); + if (!inode) + kmem_cache_free(vxfs_inode_cachep, vip); + return inode; } fail: @@ -152,7 +159,7 @@ fail: * Description: * Search the for inode number @ino in the filesystem * described by @sbp. Use the specified inode table (@ilistp). - * Returns the matching VxFS inode on success, else an error code. + * Returns the matching inode on success, else an error code. */ static struct vxfs_inode_info * __vxfs_iget(ino_t ino, struct inode *ilistp) @@ -196,15 +203,21 @@ fail: * Description: * Find inode @ino in the filesystem described by @sbp using * the structural inode list. - * Returns the matching VxFS inode on success, else a NULL pointer. + * Returns the matching inode on success, else a NULL pointer. */ -struct vxfs_inode_info * +struct inode * vxfs_stiget(struct super_block *sbp, ino_t ino) { struct vxfs_inode_info *vip; + struct inode *inode; vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); - return IS_ERR(vip) ? NULL : vip; + if (IS_ERR(vip)) + return NULL; + inode = vxfs_get_fake_inode(sbp, vip); + if (!inode) + kmem_cache_free(vxfs_inode_cachep, vip); + return inode; } /** @@ -282,7 +295,7 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) * superblock, vxfs_inode pair. * Returns the filled VFS inode. */ -struct inode * +static struct inode * vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) { struct inode *ip = NULL; -- cgit v1.2.3 From f2bf2c70488145c961306b873c75147048db743d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 1 Jun 2016 09:18:21 +0200 Subject: freevxfs: avoid the need for forward declaring the super operations Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs_super.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index daf58a9fae70..40125cc825f2 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -52,19 +52,6 @@ MODULE_AUTHOR("Christoph Hellwig"); MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); MODULE_LICENSE("Dual BSD/GPL"); - - -static void vxfs_put_super(struct super_block *); -static int vxfs_statfs(struct dentry *, struct kstatfs *); -static int vxfs_remount(struct super_block *, int *, char *); - -static const struct super_operations vxfs_super_ops = { - .evict_inode = vxfs_evict_inode, - .put_super = vxfs_put_super, - .statfs = vxfs_statfs, - .remount_fs = vxfs_remount, -}; - /** * vxfs_put_super - free superblock resources * @sbp: VFS superblock. @@ -130,6 +117,12 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) return 0; } +static const struct super_operations vxfs_super_ops = { + .evict_inode = vxfs_evict_inode, + .put_super = vxfs_put_super, + .statfs = vxfs_statfs, + .remount_fs = vxfs_remount, +}; static int vxfs_try_sb_magic(struct super_block *sbp, int silent, unsigned blk, __fs32 magic) -- cgit v1.2.3 From 2f137e31e07118bead0d17ccc89b0e71aec74732 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 1 Jun 2016 08:44:45 +0200 Subject: freevxfs: implement ->alloc_inode and ->destroy_inode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver predates those methods and was trying to be clever allocating it's own private data. Switch to the generic scheme used by other file systems. Based on an earlier patch from Krzysztof Błaszkowski . Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs.h | 7 -- fs/freevxfs/vxfs_extern.h | 1 - fs/freevxfs/vxfs_inode.c | 215 ++++++++++++++++++---------------------------- fs/freevxfs/vxfs_inode.h | 7 ++ fs/freevxfs/vxfs_super.c | 28 +++++- 5 files changed, 116 insertions(+), 142 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h index 4b561ded5eb1..f52f259aacb3 100644 --- a/fs/freevxfs/vxfs.h +++ b/fs/freevxfs/vxfs.h @@ -272,13 +272,6 @@ enum { #define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED) #define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED) - -/* - * Get filesystem private data from VFS inode. - */ -#define VXFS_INO(ip) \ - ((struct vxfs_inode_info *)(ip)->i_private) - /* * Get filesystem private data from VFS superblock. */ diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 2ec8c0f27865..f5c428e21024 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -52,7 +52,6 @@ extern int vxfs_read_fshead(struct super_block *); /* vxfs_inode.c */ extern const struct address_space_operations vxfs_immed_aops; -extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t); extern struct inode *vxfs_stiget(struct super_block *, ino_t); diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 7b5de83405f2..b718d0ff2e45 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -42,11 +42,6 @@ #include "vxfs_extern.h" -struct kmem_cache *vxfs_inode_cachep; - -static struct inode * vxfs_get_fake_inode(struct super_block *, - struct vxfs_inode_info *); - #ifdef DIAGNOSTIC /* * Dump inode contents (partially). @@ -70,9 +65,42 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) } #endif +/** + * vxfs_transmod - mode for a VxFS inode + * @vip: VxFS inode + * + * Description: + * vxfs_transmod returns a Linux mode_t for a given + * VxFS inode structure. + */ +static __inline__ umode_t +vxfs_transmod(struct vxfs_inode_info *vip) +{ + umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; + + if (VXFS_ISFIFO(vip)) + ret |= S_IFIFO; + if (VXFS_ISCHR(vip)) + ret |= S_IFCHR; + if (VXFS_ISDIR(vip)) + ret |= S_IFDIR; + if (VXFS_ISBLK(vip)) + ret |= S_IFBLK; + if (VXFS_ISLNK(vip)) + ret |= S_IFLNK; + if (VXFS_ISREG(vip)) + ret |= S_IFREG; + if (VXFS_ISSOC(vip)) + ret |= S_IFSOCK; + + return (ret); +} + static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, struct vxfs_inode_info *vip, struct vxfs_dinode *dip) { + struct inode *inode = &vip->vfs_inode; + vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode); vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink); vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid); @@ -96,6 +124,23 @@ static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, /* don't endian swap the fields that differ by orgtype */ memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org)); + + inode->i_mode = vxfs_transmod(vip); + i_uid_write(inode, (uid_t)vip->vii_uid); + i_gid_write(inode, (gid_t)vip->vii_gid); + + set_nlink(inode, vip->vii_nlink); + inode->i_size = vip->vii_size; + + inode->i_atime.tv_sec = vip->vii_atime; + inode->i_ctime.tv_sec = vip->vii_ctime; + inode->i_mtime.tv_sec = vip->vii_mtime; + inode->i_atime.tv_nsec = 0; + inode->i_ctime.tv_nsec = 0; + inode->i_mtime.tv_nsec = 0; + + inode->i_blocks = vip->vii_blocks; + inode->i_generation = vip->vii_gen; } /** @@ -121,48 +166,48 @@ vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) struct inode *inode; u_long block, offset; + inode = new_inode(sbp); + if (!inode) + return NULL; + inode->i_ino = get_next_ino(); + block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); bp = sb_bread(sbp, block); if (bp && buffer_mapped(bp)) { - struct vxfs_inode_info *vip; + struct vxfs_inode_info *vip = VXFS_INO(inode); struct vxfs_dinode *dip; - if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) - goto fail; dip = (struct vxfs_dinode *)(bp->b_data + offset); dip2vip_cpy(VXFS_SBI(sbp), vip, dip); + vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif brelse(bp); - - inode = vxfs_get_fake_inode(sbp, vip); - if (!inode) - kmem_cache_free(vxfs_inode_cachep, vip); return inode; } -fail: printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); brelse(bp); + iput(inode); return NULL; } /** * __vxfs_iget - generic find inode facility - * @sbp: VFS superblock - * @ino: inode number * @ilistp: inode list + * @vip: VxFS inode to fill in + * @ino: inode number * * Description: * Search the for inode number @ino in the filesystem * described by @sbp. Use the specified inode table (@ilistp). * Returns the matching inode on success, else an error code. */ -static struct vxfs_inode_info * -__vxfs_iget(ino_t ino, struct inode *ilistp) +static int +__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino) { struct page *pp; u_long offset; @@ -171,28 +216,22 @@ __vxfs_iget(ino_t ino, struct inode *ilistp) pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); if (!IS_ERR(pp)) { - struct vxfs_inode_info *vip; struct vxfs_dinode *dip; caddr_t kaddr = (char *)page_address(pp); - if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) - goto fail; dip = (struct vxfs_dinode *)(kaddr + offset); dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip); + vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; #ifdef DIAGNOSTIC vxfs_dumpi(vip, ino); #endif vxfs_put_page(pp); - return (vip); + return 0; } - printk(KERN_WARNING "vxfs: error on page %p\n", pp); - return ERR_CAST(pp); - -fail: - printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino); - vxfs_put_page(pp); - return ERR_PTR(-ENOMEM); + printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n", + pp, (unsigned long)ino); + return PTR_ERR(pp); } /** @@ -208,104 +247,21 @@ fail: struct inode * vxfs_stiget(struct super_block *sbp, ino_t ino) { - struct vxfs_inode_info *vip; struct inode *inode; + int error; - vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); - if (IS_ERR(vip)) - return NULL; - inode = vxfs_get_fake_inode(sbp, vip); + inode = new_inode(sbp); if (!inode) - kmem_cache_free(vxfs_inode_cachep, vip); - return inode; -} - -/** - * vxfs_transmod - mode for a VxFS inode - * @vip: VxFS inode - * - * Description: - * vxfs_transmod returns a Linux mode_t for a given - * VxFS inode structure. - */ -static __inline__ umode_t -vxfs_transmod(struct vxfs_inode_info *vip) -{ - umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; - - if (VXFS_ISFIFO(vip)) - ret |= S_IFIFO; - if (VXFS_ISCHR(vip)) - ret |= S_IFCHR; - if (VXFS_ISDIR(vip)) - ret |= S_IFDIR; - if (VXFS_ISBLK(vip)) - ret |= S_IFBLK; - if (VXFS_ISLNK(vip)) - ret |= S_IFLNK; - if (VXFS_ISREG(vip)) - ret |= S_IFREG; - if (VXFS_ISSOC(vip)) - ret |= S_IFSOCK; - - return (ret); -} - -/** - * vxfs_iinit- helper to fill inode fields - * @ip: VFS inode - * @vip: VxFS inode - * - * Description: - * vxfs_instino is a helper function to fill in all relevant - * fields in @ip from @vip. - */ -static void -vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) -{ - - ip->i_mode = vxfs_transmod(vip); - i_uid_write(ip, (uid_t)vip->vii_uid); - i_gid_write(ip, (gid_t)vip->vii_gid); - - set_nlink(ip, vip->vii_nlink); - ip->i_size = vip->vii_size; - - ip->i_atime.tv_sec = vip->vii_atime; - ip->i_ctime.tv_sec = vip->vii_ctime; - ip->i_mtime.tv_sec = vip->vii_mtime; - ip->i_atime.tv_nsec = 0; - ip->i_ctime.tv_nsec = 0; - ip->i_mtime.tv_nsec = 0; - - ip->i_blocks = vip->vii_blocks; - ip->i_generation = vip->vii_gen; - - ip->i_private = vip; - -} - -/** - * vxfs_get_fake_inode - get fake inode structure - * @sbp: filesystem superblock - * @vip: fspriv inode - * - * Description: - * vxfs_fake_inode gets a fake inode (not in the inode hash) for a - * superblock, vxfs_inode pair. - * Returns the filled VFS inode. - */ -static struct inode * -vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) -{ - struct inode *ip = NULL; + return NULL; + inode->i_ino = get_next_ino(); - if ((ip = new_inode(sbp))) { - ip->i_ino = get_next_ino(); - vxfs_iinit(ip, vip); - ip->i_mapping->a_ops = &vxfs_aops; + error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino); + if (error) { + iput(inode); + return NULL; } - return (ip); + + return inode; } /** @@ -323,6 +279,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino) struct vxfs_inode_info *vip; const struct address_space_operations *aops; struct inode *ip; + int error; ip = iget_locked(sbp, ino); if (!ip) @@ -330,14 +287,13 @@ vxfs_iget(struct super_block *sbp, ino_t ino) if (!(ip->i_state & I_NEW)) return ip; - vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist); - if (IS_ERR(vip)) { + vip = VXFS_INO(ip); + error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino); + if (error) { iget_failed(ip); - return ERR_CAST(vip); + return ERR_PTR(error); } - vxfs_iinit(ip, vip); - if (VXFS_ISIMMED(vip)) aops = &vxfs_immed_aops; else @@ -368,12 +324,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino) return ip; } -static void vxfs_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - kmem_cache_free(vxfs_inode_cachep, inode->i_private); -} - /** * vxfs_evict_inode - remove inode from main memory * @ip: inode to discard. @@ -387,5 +337,4 @@ vxfs_evict_inode(struct inode *ip) { truncate_inode_pages_final(&ip->i_data); clear_inode(ip); - call_rcu(&ip->i_rcu, vxfs_i_callback); } diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h index 93d01148e5db..ad6b77c0ebcc 100644 --- a/fs/freevxfs/vxfs_inode.h +++ b/fs/freevxfs/vxfs_inode.h @@ -151,6 +151,8 @@ struct vxfs_dinode { * The inode as represented in the main memory. */ struct vxfs_inode_info { + struct inode vfs_inode; + __u32 vii_mode; __u32 vii_nlink; /* Link count */ __u32 vii_uid; /* UID */ @@ -183,4 +185,9 @@ struct vxfs_inode_info { #define vii_ext4 vii_org.ext4 #define vii_typed vii_org.typed +static inline struct vxfs_inode_info *VXFS_INO(struct inode *inode) +{ + return container_of(inode, struct vxfs_inode_info, vfs_inode); +} + #endif /* _VXFS_INODE_H_ */ diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 40125cc825f2..dfa775ef4d1d 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -52,6 +52,8 @@ MODULE_AUTHOR("Christoph Hellwig"); MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver"); MODULE_LICENSE("Dual BSD/GPL"); +static struct kmem_cache *vxfs_inode_cachep; + /** * vxfs_put_super - free superblock resources * @sbp: VFS superblock. @@ -117,7 +119,31 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) return 0; } +static struct inode *vxfs_alloc_inode(struct super_block *sb) +{ + struct vxfs_inode_info *vi; + + vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL); + if (!vi) + return NULL; + return &vi->vfs_inode; +} + +static void vxfs_i_callback(struct rcu_head *head) +{ + struct inode *inode = container_of(head, struct inode, i_rcu); + + kmem_cache_free(vxfs_inode_cachep, VXFS_INO(inode)); +} + +static void vxfs_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, vxfs_i_callback); +} + static const struct super_operations vxfs_super_ops = { + .alloc_inode = vxfs_alloc_inode, + .destroy_inode = vxfs_destroy_inode, .evict_inode = vxfs_evict_inode, .put_super = vxfs_put_super, .statfs = vxfs_statfs, @@ -206,6 +232,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) goto out; } + sbp->s_op = &vxfs_super_ops; sbp->s_fs_info = infp; if (!vxfs_try_sb_magic(sbp, silent, 1, @@ -256,7 +283,6 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent) goto out; } - sbp->s_op = &vxfs_super_ops; root = vxfs_iget(sbp, VXFS_ROOT_INO); if (IS_ERR(root)) { ret = PTR_ERR(root); -- cgit v1.2.3 From 1cce17017970c0797943e069cc520e17d068ca4b Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Wed, 1 Jun 2016 09:25:12 +0200 Subject: freevxfs: update documentation and cresdits for HP-UX support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Błaszkowski [hch: cosmetic updates] Signed-off-by: Christoph Hellwig --- fs/freevxfs/Kconfig | 10 +++++++++- fs/freevxfs/vxfs.h | 1 + fs/freevxfs/vxfs_fshead.c | 1 + fs/freevxfs/vxfs_fshead.h | 1 + fs/freevxfs/vxfs_inode.c | 1 + fs/freevxfs/vxfs_inode.h | 1 + fs/freevxfs/vxfs_lookup.c | 1 + fs/freevxfs/vxfs_super.c | 3 ++- 8 files changed, 17 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig index 8dc1cd5c1efe..4cc1dd80c3da 100644 --- a/fs/freevxfs/Kconfig +++ b/fs/freevxfs/Kconfig @@ -5,12 +5,20 @@ config VXFS_FS FreeVxFS is a file system driver that support the VERITAS VxFS(TM) file system format. VERITAS VxFS(TM) is the standard file system of SCO UnixWare (and possibly others) and optionally available - for Sunsoft Solaris, HP-UX and many other operating systems. + for Sunsoft Solaris, HP-UX and many other operating systems. However + these particular OS implementations of vxfs may differ in on-disk + data endianess and/or superblock offset. The vxfs module has been + tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.) Currently only readonly access is supported. NOTE: the file system type as used by mount(1), mount(2) and fstab(5) is 'vxfs' as it describes the file system format, not the actual driver. + There is a userspace utility for HP-UX logical volumes which makes + creating HP-UX logical volumes easy from HP-UX disk block device file + or regular file with image of the disk. See: + https://sourceforge.net/projects/linux-vxfs/ + To compile this as a module, choose M here: the module will be called freevxfs. If unsure, say N. diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h index f52f259aacb3..a41ea0ba6943 100644 --- a/fs/freevxfs/vxfs.h +++ b/fs/freevxfs/vxfs.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c index 2651b4238eb2..69a10d62b375 100644 --- a/fs/freevxfs/vxfs_fshead.c +++ b/fs/freevxfs/vxfs_fshead.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/fs/freevxfs/vxfs_fshead.h b/fs/freevxfs/vxfs_fshead.h index a786cc55509c..e026f0c49159 100644 --- a/fs/freevxfs/vxfs_fshead.h +++ b/fs/freevxfs/vxfs_fshead.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index b718d0ff2e45..1f41b25ef38b 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h index ad6b77c0ebcc..f012abed125d 100644 --- a/fs/freevxfs/vxfs_inode.h +++ b/fs/freevxfs/vxfs_inode.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 09e93b3a1582..f042cafbb85f 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index dfa775ef4d1d..e5eef1400d67 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2000-2001 Christoph Hellwig. + * Copyright (c) 2016 Krzysztof Blaszkowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,7 +49,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"); -- cgit v1.2.3 From 263040a1e7cefa9fb916d6328fc045fdb30ed268 Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Sun, 12 Jun 2016 19:25:23 +0200 Subject: freevxfs: fix memory leak in vxfs_read_fshead() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every successful mount two structs vxfs_fsh were not released. Signed-off-by: Krzysztof Błaszkowski Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs_fshead.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c index 69a10d62b375..a4610a77649e 100644 --- a/fs/freevxfs/vxfs_fshead.c +++ b/fs/freevxfs/vxfs_fshead.c @@ -172,6 +172,8 @@ vxfs_read_fshead(struct super_block *sbp) goto out_iput_ilist; } + kfree(pfp); + kfree(sfp); return 0; out_iput_ilist: -- cgit v1.2.3 From f2fe2fa1fbad72e469f49da3716f176a9b53fb75 Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Sun, 12 Jun 2016 19:26:04 +0200 Subject: freevxfs: fix lack of inode initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is nothing worse than just allocated inode without being initialized _once(). Signed-off-by: Krzysztof Błaszkowski Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs_super.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index e5eef1400d67..455ce5b77e9b 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -127,6 +127,7 @@ static struct inode *vxfs_alloc_inode(struct super_block *sb) vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL); if (!vi) return NULL; + inode_init_once(&vi->vfs_inode); return &vi->vfs_inode; } -- cgit v1.2.3 From 12495ea3ac47ec5b53611e0d68ba3222a09784d1 Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Sun, 12 Jun 2016 19:26:45 +0200 Subject: freevxfs: refactor readdir and lookup code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change fixes also a buffer overflow which was caused by accessing address space beyond mapped page Signed-off-by: Krzysztof Błaszkowski Signed-off-by: Christoph Hellwig --- fs/freevxfs/vxfs_lookup.c | 233 +++++++++++++++++++++------------------------- 1 file changed, 108 insertions(+), 125 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index f042cafbb85f..ce4785fd81c6 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c @@ -62,35 +62,6 @@ const struct file_operations vxfs_dir_operations = { .iterate_shared = vxfs_readdir, }; -static inline u_long -dir_blocks(struct inode *ip) -{ - u_long bsize = ip->i_sb->s_blocksize; - return (ip->i_size + bsize - 1) & ~(bsize - 1); -} - -/* - * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure. - * - * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller. - */ -static inline int -vxfs_match(struct vxfs_sb_info *sbi, int len, const char *const name, - struct vxfs_direct *de) -{ - if (len != fs16_to_cpu(sbi, 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_sb_info *sbi, struct vxfs_direct *de) -{ - return ((struct vxfs_direct *) - ((char *)de + fs16_to_cpu(sbi, de->d_reclen))); -} /** * vxfs_find_entry - find a mathing directory entry for a dentry @@ -109,53 +80,64 @@ vxfs_next_entry(struct vxfs_sb_info *sbi, struct vxfs_direct *de) static struct vxfs_direct * vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) { - struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); - u_long npages, page, nblocks, pblocks, block; - u_long bsize = ip->i_sb->s_blocksize; - const char *name = dp->d_name.name; - int namelen = dp->d_name.len; - - npages = dir_pages(ip); - nblocks = dir_blocks(ip); - pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb); - - for (page = 0; page < npages; page++) { - caddr_t kaddr; - struct page *pp; + u_long bsize = ip->i_sb->s_blocksize; + const char *name = dp->d_name.name; + int namelen = dp->d_name.len; + loff_t limit = VXFS_DIRROUND(ip->i_size); + struct vxfs_direct *de_exit = NULL; + loff_t pos = 0; + struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb); + + while (pos < limit) { + struct page *pp; + char *kaddr; + int pg_ofs = pos & ~PAGE_MASK; - pp = vxfs_get_page(ip->i_mapping, page); + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT); if (IS_ERR(pp)) - continue; - kaddr = (caddr_t)page_address(pp); - - for (block = 0; block <= nblocks && block <= pblocks; block++) { - caddr_t baddr, limit; - struct vxfs_dirblk *dbp; - struct vxfs_direct *de; - - baddr = kaddr + (block * bsize); - limit = baddr + bsize - VXFS_DIRLEN(1); - - dbp = (struct vxfs_dirblk *)baddr; - de = (struct vxfs_direct *) - (baddr + VXFS_DIRBLKOV(sbi, dbp)); - - for (; (caddr_t)de <= limit; - de = vxfs_next_entry(sbi, de)) { - if (!de->d_reclen) - break; - if (!de->d_ino) - continue; - if (vxfs_match(sbi, namelen, name, de)) { - *ppp = pp; - return (de); - } + return NULL; + kaddr = (char *)page_address(pp); + + while (pg_ofs < PAGE_SIZE && pos < limit) { + struct vxfs_direct *de; + + if ((pos & (bsize - 1)) < 4) { + struct vxfs_dirblk *dbp = + (struct vxfs_dirblk *) + (kaddr + (pos & ~PAGE_MASK)); + int overhead = VXFS_DIRBLKOV(sbi, dbp); + + pos += overhead; + pg_ofs += overhead; + } + de = (struct vxfs_direct *)(kaddr + pg_ofs); + + if (!de->d_reclen) { + pos += bsize - 1; + pos &= ~(bsize - 1); + break; + } + + pg_ofs += fs16_to_cpu(sbi, de->d_reclen); + pos += fs16_to_cpu(sbi, de->d_reclen); + if (!de->d_ino) + continue; + + if (namelen != fs16_to_cpu(sbi, de->d_namelen)) + continue; + if (!memcmp(name, de->d_name, namelen)) { + *ppp = pp; + de_exit = de; + break; } } - vxfs_put_page(pp); + if (!de_exit) + vxfs_put_page(pp); + else + break; } - return NULL; + return de_exit; } /** @@ -238,80 +220,81 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx) { struct inode *ip = file_inode(fp); struct super_block *sbp = ip->i_sb; - struct vxfs_sb_info *sbi = VXFS_SBI(sbp); u_long bsize = sbp->s_blocksize; - u_long page, npages, block, pblocks, nblocks, offset; - loff_t pos; - + loff_t pos, limit; + struct vxfs_sb_info *sbi = VXFS_SBI(sbp); if (ctx->pos == 0) { if (!dir_emit_dot(fp, ctx)) - return 0; - ctx->pos = 1; + goto out; + ctx->pos++; } if (ctx->pos == 1) { if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR)) - return 0; - ctx->pos = 2; + goto out; + ctx->pos++; } - pos = ctx->pos - 2; - - if (pos > VXFS_DIRROUND(ip->i_size)) - return 0; - npages = dir_pages(ip); - nblocks = dir_blocks(ip); - pblocks = VXFS_BLOCK_PER_PAGE(sbp); + limit = VXFS_DIRROUND(ip->i_size); + if (ctx->pos > limit) + goto out; - page = pos >> PAGE_SHIFT; - offset = pos & ~PAGE_MASK; - block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks; + pos = ctx->pos & ~3L; - for (; page < npages; page++, block = 0) { - char *kaddr; - struct page *pp; + while (pos < limit) { + struct page *pp; + char *kaddr; + int pg_ofs = pos & ~PAGE_MASK; + int rc = 0; - pp = vxfs_get_page(ip->i_mapping, page); + pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT); if (IS_ERR(pp)) - continue; + return -ENOMEM; + kaddr = (char *)page_address(pp); - for (; block <= nblocks && block <= pblocks; block++) { - char *baddr, *limit; - struct vxfs_dirblk *dbp; - struct vxfs_direct *de; + while (pg_ofs < PAGE_SIZE && pos < limit) { + struct vxfs_direct *de; - baddr = kaddr + (block * bsize); - limit = baddr + bsize - VXFS_DIRLEN(1); - - dbp = (struct vxfs_dirblk *)baddr; - de = (struct vxfs_direct *) - (offset ? - (kaddr + offset) : - (baddr + VXFS_DIRBLKOV(sbi, dbp))); - - for (; (char *)de <= limit; - de = vxfs_next_entry(sbi, de)) { - if (!de->d_reclen) - break; - if (!de->d_ino) - continue; - - offset = (char *)de - kaddr; - ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; - if (!dir_emit(ctx, de->d_name, - fs16_to_cpu(sbi, de->d_namelen), - fs32_to_cpu(sbi, de->d_ino), - DT_UNKNOWN)) { - vxfs_put_page(pp); - return 0; - } + if ((pos & (bsize - 1)) < 4) { + struct vxfs_dirblk *dbp = + (struct vxfs_dirblk *) + (kaddr + (pos & ~PAGE_MASK)); + int overhead = VXFS_DIRBLKOV(sbi, dbp); + + pos += overhead; + pg_ofs += overhead; + } + de = (struct vxfs_direct *)(kaddr + pg_ofs); + + if (!de->d_reclen) { + pos += bsize - 1; + pos &= ~(bsize - 1); + break; + } + + pg_ofs += fs16_to_cpu(sbi, de->d_reclen); + pos += fs16_to_cpu(sbi, de->d_reclen); + if (!de->d_ino) + continue; + + rc = dir_emit(ctx, de->d_name, + fs16_to_cpu(sbi, de->d_namelen), + fs32_to_cpu(sbi, de->d_ino), + DT_UNKNOWN); + if (!rc) { + /* the dir entry was not read, fix pos. */ + pos -= fs16_to_cpu(sbi, de->d_reclen); + break; } - offset = 0; } vxfs_put_page(pp); - offset = 0; + if (!rc) + break; } - ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; + + ctx->pos = pos | 2; + +out: return 0; } -- cgit v1.2.3 From bf1bb4b460c8dc3a33793bff21464a9d816697ad Mon Sep 17 00:00:00 2001 From: Krzysztof Błaszkowski Date: Fri, 10 Jun 2016 13:35:40 +0200 Subject: freevxfs: update Kconfig information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Krzysztof Błaszkowski Signed-off-by: Christoph Hellwig --- fs/freevxfs/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig index 4cc1dd80c3da..ce49df1020dd 100644 --- a/fs/freevxfs/Kconfig +++ b/fs/freevxfs/Kconfig @@ -9,7 +9,8 @@ config VXFS_FS these particular OS implementations of vxfs may differ in on-disk data endianess and/or superblock offset. The vxfs module has been tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.) - Currently only readonly access is supported. + Currently only readonly access is supported and VxFX versions + 2, 3 and 4. Tests were performed with HP-UX VxFS version 3. NOTE: the file system type as used by mount(1), mount(2) and fstab(5) is 'vxfs' as it describes the file system format, not -- cgit v1.2.3