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>
This commit is contained in:
Krzysztof Błaszkowski 2016-05-31 08:45:13 +02:00 committed by Christoph Hellwig
parent 6b15d6650c
commit 0d83f7fc83
11 changed files with 405 additions and 277 deletions

View File

@ -38,13 +38,6 @@
*/
#include <linux/types.h>
/*
* 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

View File

@ -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:

View File

@ -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_ */

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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
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_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 vii_ftarea.rdev
#define vii_dotdot vii_ftarea.dotdot
#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
#define vii_immed vii_org.immed
#define vii_ext4 vii_org.ext4
#define vii_typed vii_org.typed
#endif /* _VXFS_INODE_H_ */

View File

@ -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;
}

View File

@ -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);

View File

@ -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_ */

View File

@ -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;
}