diff options
author | Krzysztof Błaszkowski <kb@sysmikro.com.pl> | 2016-05-31 09:45:13 +0300 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2016-06-01 10:01:28 +0300 |
commit | 0d83f7fc83f77d1cc8395b9e851325d8cc1892e3 (patch) | |
tree | 9cfc6aef0a098884097fd37bb413639e8e76f461 /fs/freevxfs/vxfs_bmap.c | |
parent | 6b15d6650c5301ce023d8df0cc3a60b1a76d377e (diff) | |
download | linux-0d83f7fc83f77d1cc8395b9e851325d8cc1892e3.tar.xz |
freevxfs: handle big endian HP-UX file systems
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 <kb@sysmikro.com.pl>
[hch: make spare happy]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/freevxfs/vxfs_bmap.c')
-rw-r--r-- | fs/freevxfs/vxfs_bmap.c | 70 |
1 files changed, 42 insertions, 28 deletions
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: |