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>
这个提交包含在:

提交者
Christoph Hellwig

父节点
6b15d6650c
当前提交
0d83f7fc83
@@ -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:
|
||||
|
在新工单中引用
屏蔽一个用户