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> #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). * Superblock magic number (vxfs_super->vs_magic).
*/ */
@ -60,6 +53,14 @@ typedef int32_t vx_ino_t;
*/ */
#define VXFS_NEFREE 32 #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). * VxFS superblock (disk).
@ -71,83 +72,83 @@ struct vxfs_sb {
* Lots of this fields are no more used by version 2 * Lots of this fields are no more used by version 2
* and never filesystems. * and never filesystems.
*/ */
u_int32_t vs_magic; /* Magic number */ __fs32 vs_magic; /* Magic number */
int32_t vs_version; /* VxFS version */ __fs32 vs_version; /* VxFS version */
u_int32_t vs_ctime; /* create time - secs */ __fs32 vs_ctime; /* create time - secs */
u_int32_t vs_cutime; /* create time - usecs */ __fs32 vs_cutime; /* create time - usecs */
int32_t __unused1; /* unused */ __fs32 __unused1; /* unused */
int32_t __unused2; /* unused */ __fs32 __unused2; /* unused */
vx_daddr_t vs_old_logstart; /* obsolete */ __fs32 vs_old_logstart; /* obsolete */
vx_daddr_t vs_old_logend; /* obsolete */ __fs32 vs_old_logend; /* obsolete */
int32_t vs_bsize; /* block size */ __fs32 vs_bsize; /* block size */
int32_t vs_size; /* number of blocks */ __fs32 vs_size; /* number of blocks */
int32_t vs_dsize; /* number of data blocks */ __fs32 vs_dsize; /* number of data blocks */
u_int32_t vs_old_ninode; /* obsolete */ __fs32 vs_old_ninode; /* obsolete */
int32_t vs_old_nau; /* obsolete */ __fs32 vs_old_nau; /* obsolete */
int32_t __unused3; /* unused */ __fs32 __unused3; /* unused */
int32_t vs_old_defiextsize; /* obsolete */ __fs32 vs_old_defiextsize; /* obsolete */
int32_t vs_old_ilbsize; /* obsolete */ __fs32 vs_old_ilbsize; /* obsolete */
int32_t vs_immedlen; /* size of immediate data area */ __fs32 vs_immedlen; /* size of immediate data area */
int32_t vs_ndaddr; /* number of direct extentes */ __fs32 vs_ndaddr; /* number of direct extentes */
vx_daddr_t vs_firstau; /* address of first AU */ __fs32 vs_firstau; /* address of first AU */
vx_daddr_t vs_emap; /* offset of extent map in AU */ __fs32 vs_emap; /* offset of extent map in AU */
vx_daddr_t vs_imap; /* offset of inode map in AU */ __fs32 vs_imap; /* offset of inode map in AU */
vx_daddr_t vs_iextop; /* offset of ExtOp. map in AU */ __fs32 vs_iextop; /* offset of ExtOp. map in AU */
vx_daddr_t vs_istart; /* offset of inode list in AU */ __fs32 vs_istart; /* offset of inode list in AU */
vx_daddr_t vs_bstart; /* offset of fdblock in AU */ __fs32 vs_bstart; /* offset of fdblock in AU */
vx_daddr_t vs_femap; /* aufirst + emap */ __fs32 vs_femap; /* aufirst + emap */
vx_daddr_t vs_fimap; /* aufirst + imap */ __fs32 vs_fimap; /* aufirst + imap */
vx_daddr_t vs_fiextop; /* aufirst + iextop */ __fs32 vs_fiextop; /* aufirst + iextop */
vx_daddr_t vs_fistart; /* aufirst + istart */ __fs32 vs_fistart; /* aufirst + istart */
vx_daddr_t vs_fbstart; /* aufirst + bstart */ __fs32 vs_fbstart; /* aufirst + bstart */
int32_t vs_nindir; /* number of entries in indir */ __fs32 vs_nindir; /* number of entries in indir */
int32_t vs_aulen; /* length of AU in blocks */ __fs32 vs_aulen; /* length of AU in blocks */
int32_t vs_auimlen; /* length of imap in blocks */ __fs32 vs_auimlen; /* length of imap in blocks */
int32_t vs_auemlen; /* length of emap in blocks */ __fs32 vs_auemlen; /* length of emap in blocks */
int32_t vs_auilen; /* length of ilist in blocks */ __fs32 vs_auilen; /* length of ilist in blocks */
int32_t vs_aupad; /* length of pad in blocks */ __fs32 vs_aupad; /* length of pad in blocks */
int32_t vs_aublocks; /* data blocks in AU */ __fs32 vs_aublocks; /* data blocks in AU */
int32_t vs_maxtier; /* log base 2 of aublocks */ __fs32 vs_maxtier; /* log base 2 of aublocks */
int32_t vs_inopb; /* number of inodes per blk */ __fs32 vs_inopb; /* number of inodes per blk */
int32_t vs_old_inopau; /* obsolete */ __fs32 vs_old_inopau; /* obsolete */
int32_t vs_old_inopilb; /* obsolete */ __fs32 vs_old_inopilb; /* obsolete */
int32_t vs_old_ndiripau; /* obsolete */ __fs32 vs_old_ndiripau; /* obsolete */
int32_t vs_iaddrlen; /* size of indirect addr ext. */ __fs32 vs_iaddrlen; /* size of indirect addr ext. */
int32_t vs_bshift; /* log base 2 of bsize */ __fs32 vs_bshift; /* log base 2 of bsize */
int32_t vs_inoshift; /* log base 2 of inobp */ __fs32 vs_inoshift; /* log base 2 of inobp */
int32_t vs_bmask; /* ~( bsize - 1 ) */ __fs32 vs_bmask; /* ~( bsize - 1 ) */
int32_t vs_boffmask; /* bsize - 1 */ __fs32 vs_boffmask; /* bsize - 1 */
int32_t vs_old_inomask; /* old_inopilb - 1 */ __fs32 vs_old_inomask; /* old_inopilb - 1 */
int32_t vs_checksum; /* checksum of V1 data */ __fs32 vs_checksum; /* checksum of V1 data */
/* /*
* Version 1, writable * Version 1, writable
*/ */
int32_t vs_free; /* number of free blocks */ __fs32 vs_free; /* number of free blocks */
int32_t vs_ifree; /* number of free inodes */ __fs32 vs_ifree; /* number of free inodes */
int32_t vs_efree[VXFS_NEFREE]; /* number of free extents by size */ __fs32 vs_efree[VXFS_NEFREE]; /* number of free extents by size */
int32_t vs_flags; /* flags ?!? */ __fs32 vs_flags; /* flags ?!? */
u_int8_t vs_mod; /* filesystem has been changed */ __u8 vs_mod; /* filesystem has been changed */
u_int8_t vs_clean; /* clean FS */ __u8 vs_clean; /* clean FS */
u_int16_t __unused4; /* unused */ __fs16 __unused4; /* unused */
u_int32_t vs_firstlogid; /* mount time log ID */ __fs32 vs_firstlogid; /* mount time log ID */
u_int32_t vs_wtime; /* last time written - sec */ __fs32 vs_wtime; /* last time written - sec */
u_int32_t vs_wutime; /* last time written - usec */ __fs32 vs_wutime; /* last time written - usec */
u_int8_t vs_fname[6]; /* FS name */ __u8 vs_fname[6]; /* FS name */
u_int8_t vs_fpack[6]; /* FS pack name */ __u8 vs_fpack[6]; /* FS pack name */
int32_t vs_logversion; /* log format version */ __fs32 vs_logversion; /* log format version */
int32_t __unused5; /* unused */ __u32 __unused5; /* unused */
/* /*
* Version 2, Read-only * Version 2, Read-only
*/ */
vx_daddr_t vs_oltext[2]; /* OLT extent and replica */ __fs32 vs_oltext[2]; /* OLT extent and replica */
int32_t vs_oltsize; /* OLT extent size */ __fs32 vs_oltsize; /* OLT extent size */
int32_t vs_iauimlen; /* size of inode map */ __fs32 vs_iauimlen; /* size of inode map */
int32_t vs_iausize; /* size of IAU in blocks */ __fs32 vs_iausize; /* size of IAU in blocks */
int32_t vs_dinosize; /* size of inode in bytes */ __fs32 vs_dinosize; /* size of inode in bytes */
int32_t vs_old_dniaddr; /* indir levels per inode */ __fs32 vs_old_dniaddr; /* indir levels per inode */
int32_t vs_checksum2; /* checksum of V2 RO */ __fs32 vs_checksum2; /* checksum of V2 RO */
/* /*
* Actually much more... * Actually much more...
@ -168,8 +169,32 @@ struct vxfs_sb_info {
ino_t vsi_fshino; /* fileset header inode */ ino_t vsi_fshino; /* fileset header inode */
daddr_t vsi_oltext; /* OLT extent */ daddr_t vsi_oltext; /* OLT extent */
daddr_t vsi_oltsize; /* OLT size */ 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 * 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 super_block *sb = ip->i_sb;
struct vxfs_inode_info *vip = VXFS_INO(ip); struct vxfs_inode_info *vip = VXFS_INO(ip);
struct vxfs_sb_info *sbi = VXFS_SBI(sb);
unsigned long bsize = sb->s_blocksize; 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; int i;
if (indsize > sb->s_blocksize) if (indsize > sb->s_blocksize)
@ -77,22 +78,24 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
for (i = 0; i < VXFS_NDADDR; i++) { for (i = 0; i < VXFS_NDADDR; i++) {
struct direct *d = vip->vii_ext4.ve4_direct + i; struct direct *d = vip->vii_ext4.ve4_direct + i;
if (bn >= 0 && bn < d->size) if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
return (bn + d->extent); return (bn + fs32_to_cpu(sbi, d->extent));
bn -= d->size; bn -= fs32_to_cpu(sbi, d->size);
} }
if ((bn / (indsize * indsize * bsize / 4)) == 0) { if ((bn / (indsize * indsize * bsize / 4)) == 0) {
struct buffer_head *buf; struct buffer_head *buf;
daddr_t bno; 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)) if (!buf || !buffer_mapped(buf))
goto fail_buf; goto fail_buf;
indir = (u32 *)buf->b_data; indir = (__fs32 *)buf->b_data;
bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize); bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
(bn % indsize);
brelse(buf); brelse(buf);
return bno; return bno;
@ -127,6 +130,7 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
static daddr_t static daddr_t
vxfs_bmap_indir(struct inode *ip, long indir, int size, long block) 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; struct buffer_head *bp = NULL;
daddr_t pblock = 0; daddr_t pblock = 0;
int i; 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) + typ = ((struct vxfs_typed *)bp->b_data) +
(i % VXFS_TYPED_PER_BLOCK(ip->i_sb)); (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) { if (block < off) {
brelse(bp); brelse(bp);
continue; 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: case VXFS_TYPED_INDIRECT:
pblock = vxfs_bmap_indir(ip, typ->vt_block, pblock = vxfs_bmap_indir(ip,
typ->vt_size, block - off); fs32_to_cpu(sbi, typ->vt_block),
fs32_to_cpu(sbi, typ->vt_size),
block - off);
if (pblock == -2) if (pblock == -2)
break; break;
goto out; goto out;
case VXFS_TYPED_DATA: case VXFS_TYPED_DATA:
if ((block - off) >= typ->vt_size) if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
break; break;
pblock = (typ->vt_block + block - off); pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
goto out; goto out;
case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_INDIRECT_DEV4:
case VXFS_TYPED_DATA_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; (struct vxfs_typed_dev4 *)typ;
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
(unsigned long long) typ4->vd4_block, fs64_to_cpu(sbi, typ4->vd4_block),
(unsigned long long) typ4->vd4_size, fs64_to_cpu(sbi, typ4->vd4_size),
typ4->vd4_dev); fs32_to_cpu(sbi, typ4->vd4_dev));
goto fail; goto fail;
} }
default: default:
printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
__LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
BUG(); BUG();
} }
brelse(bp); brelse(bp);
@ -201,28 +210,33 @@ static daddr_t
vxfs_bmap_typed(struct inode *ip, long iblock) vxfs_bmap_typed(struct inode *ip, long iblock)
{ {
struct vxfs_inode_info *vip = VXFS_INO(ip); struct vxfs_inode_info *vip = VXFS_INO(ip);
struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
daddr_t pblock = 0; daddr_t pblock = 0;
int i; int i;
for (i = 0; i < VXFS_NTYPED; i++) { for (i = 0; i < VXFS_NTYPED; i++) {
struct vxfs_typed *typ = vip->vii_org.typed + i; struct vxfs_typed *typ = vip->vii_org.typed + i;
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 #ifdef DIAGNOSTIC
vxfs_typdump(typ); vxfs_typdump(typ);
#endif #endif
if (iblock < off) if (iblock < off)
continue; continue;
switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) { switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
case VXFS_TYPED_INDIRECT: case VXFS_TYPED_INDIRECT:
pblock = vxfs_bmap_indir(ip, typ->vt_block, pblock = vxfs_bmap_indir(ip,
typ->vt_size, iblock - off); fs32_to_cpu(sbi, typ->vt_block),
fs32_to_cpu(sbi, typ->vt_size),
iblock - off);
if (pblock == -2) if (pblock == -2)
break; break;
return (pblock); return (pblock);
case VXFS_TYPED_DATA: case VXFS_TYPED_DATA:
if ((iblock - off) < typ->vt_size) if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
return (typ->vt_block + iblock - off); return (fs32_to_cpu(sbi, typ->vt_block) +
iblock - off);
break; break;
case VXFS_TYPED_INDIRECT_DEV4: case VXFS_TYPED_INDIRECT_DEV4:
case VXFS_TYPED_DATA_DEV4: { case VXFS_TYPED_DATA_DEV4: {
@ -230,10 +244,10 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
(struct vxfs_typed_dev4 *)typ; (struct vxfs_typed_dev4 *)typ;
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n"); printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n", printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
(unsigned long long) typ4->vd4_block, fs64_to_cpu(sbi, typ4->vd4_block),
(unsigned long long) typ4->vd4_size, fs64_to_cpu(sbi, typ4->vd4_size),
typ4->vd4_dev); fs32_to_cpu(sbi, typ4->vd4_dev));
return 0; return 0;
} }
default: default:

View File

@ -48,9 +48,9 @@
* Linux driver for now. * Linux driver for now.
*/ */
struct vxfs_dirblk { struct vxfs_dirblk {
u_int16_t d_free; /* free space in dirblock */ __fs16 d_free; /* free space in dirblock */
u_int16_t d_nhash; /* no of hash chains */ __fs16 d_nhash; /* no of hash chains */
u_int16_t d_hash[1]; /* hash chain */ __fs16 d_hash[1]; /* hash chain */
}; };
/* /*
@ -63,10 +63,10 @@ struct vxfs_dirblk {
* VxFS directory entry. * VxFS directory entry.
*/ */
struct vxfs_direct { struct vxfs_direct {
vx_ino_t d_ino; /* inode number */ __fs32 d_ino; /* inode number */
u_int16_t d_reclen; /* record length */ __fs16 d_reclen; /* record length */
u_int16_t d_namelen; /* d_name length */ __fs16 d_namelen; /* d_name length */
u_int16_t d_hashnext; /* next hash entry */ __fs16 d_hashnext; /* next hash entry */
char d_name[VXFS_NAMELEN]; /* name */ char d_name[VXFS_NAMELEN]; /* name */
}; };
@ -87,6 +87,7 @@ struct vxfs_direct {
/* /*
* VXFS_DIRBLKOV is the overhead of a specific dirblock. * 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_ */ #endif /* _VXFS_DIR_H_ */

View File

@ -153,7 +153,8 @@ vxfs_read_fshead(struct super_block *sbp)
vxfs_dumpfsh(pfp); vxfs_dumpfsh(pfp);
#endif #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) if (!tip)
goto out_free_pfp; goto out_free_pfp;
@ -169,7 +170,7 @@ vxfs_read_fshead(struct super_block *sbp)
goto out_iput_stilist; 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) if (!tip)
goto out_iput_stilist; goto out_iput_stilist;
infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip); infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);

View File

@ -42,20 +42,20 @@
* Fileset header * Fileset header
*/ */
struct vxfs_fsh { struct vxfs_fsh {
u_int32_t fsh_version; /* fileset header version */ __fs32 fsh_version; /* fileset header version */
u_int32_t fsh_fsindex; /* fileset index */ __fs32 fsh_fsindex; /* fileset index */
u_int32_t fsh_time; /* modification time - sec */ __fs32 fsh_time; /* modification time - sec */
u_int32_t fsh_utime; /* modification time - usec */ __fs32 fsh_utime; /* modification time - usec */
u_int32_t fsh_extop; /* extop flags */ __fs32 fsh_extop; /* extop flags */
vx_ino_t fsh_ninodes; /* allocated inodes */ __fs32 fsh_ninodes; /* allocated inodes */
u_int32_t fsh_nau; /* number of IAUs */ __fs32 fsh_nau; /* number of IAUs */
u_int32_t fsh_old_ilesize; /* old size of ilist */ __fs32 fsh_old_ilesize; /* old size of ilist */
u_int32_t fsh_dflags; /* flags */ __fs32 fsh_dflags; /* flags */
u_int32_t fsh_quota; /* quota limit */ __fs32 fsh_quota; /* quota limit */
vx_ino_t fsh_maxinode; /* maximum inode number */ __fs32 fsh_maxinode; /* maximum inode number */
vx_ino_t fsh_iauino; /* IAU inode */ __fs32 fsh_iauino; /* IAU inode */
vx_ino_t fsh_ilistino[2]; /* ilist inodes */ __fs32 fsh_ilistino[2]; /* ilist inodes */
vx_ino_t fsh_lctino; /* link count table inode */ __fs32 fsh_lctino; /* link count table inode */
/* /*
* Slightly more fields follow, but they * Slightly more fields follow, but they

View File

@ -68,6 +68,33 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
} }
#endif #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 # * 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))) if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
goto fail; goto fail;
dip = (struct vxfs_dinode *)(bp->b_data + offset); dip = (struct vxfs_dinode *)(bp->b_data + offset);
memcpy(vip, dip, sizeof(*vip)); dip2vip_cpy(VXFS_SBI(sbp), vip, dip);
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino); vxfs_dumpi(vip, ino);
#endif #endif
@ -144,7 +171,7 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL)))
goto fail; goto fail;
dip = (struct vxfs_dinode *)(kaddr + offset); dip = (struct vxfs_dinode *)(kaddr + offset);
memcpy(vip, dip, sizeof(*vip)); dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip);
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino); vxfs_dumpi(vip, ino);
#endif #endif

View File

@ -66,74 +66,74 @@ enum {
* Data stored immediately in the inode. * Data stored immediately in the inode.
*/ */
struct vxfs_immed { struct vxfs_immed {
u_int8_t vi_immed[VXFS_NIMMED]; __u8 vi_immed[VXFS_NIMMED];
}; };
struct vxfs_ext4 { struct vxfs_ext4 {
u_int32_t ve4_spare; /* ?? */ __fs32 ve4_spare; /* ?? */
u_int32_t ve4_indsize; /* Indirect extent size */ __fs32 ve4_indsize; /* Indirect extent size */
vx_daddr_t ve4_indir[VXFS_NIADDR]; /* Indirect extents */ __fs32 ve4_indir[VXFS_NIADDR]; /* Indirect extents */
struct direct { /* Direct extents */ struct direct { /* Direct extents */
vx_daddr_t extent; /* Extent number */ __fs32 extent; /* Extent number */
int32_t size; /* Size of extent */ __fs32 size; /* Size of extent */
} ve4_direct[VXFS_NDADDR]; } ve4_direct[VXFS_NDADDR];
}; };
struct vxfs_typed { struct vxfs_typed {
u_int64_t vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ __fs64 vt_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
vx_daddr_t vt_block; /* Extent block */ __fs32 vt_block; /* Extent block */
int32_t vt_size; /* Size in blocks */ __fs32 vt_size; /* Size in blocks */
}; };
struct vxfs_typed_dev4 { struct vxfs_typed_dev4 {
u_int64_t vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */ __fs64 vd4_hdr; /* Header, 0xTTOOOOOOOOOOOOOO; T=type,O=offs */
u_int64_t vd4_block; /* Extent block */ __fs64 vd4_block; /* Extent block */
u_int64_t vd4_size; /* Size in blocks */ __fs64 vd4_size; /* Size in blocks */
int32_t vd4_dev; /* Device ID */ __fs32 vd4_dev; /* Device ID */
u_int32_t __pad1; __u8 __pad1;
}; };
/* /*
* The inode as contained on the physical device. * The inode as contained on the physical device.
*/ */
struct vxfs_dinode { struct vxfs_dinode {
int32_t vdi_mode; __fs32 vdi_mode;
u_int32_t vdi_nlink; /* Link count */ __fs32 vdi_nlink; /* Link count */
u_int32_t vdi_uid; /* UID */ __fs32 vdi_uid; /* UID */
u_int32_t vdi_gid; /* GID */ __fs32 vdi_gid; /* GID */
u_int64_t vdi_size; /* Inode size in bytes */ __fs64 vdi_size; /* Inode size in bytes */
u_int32_t vdi_atime; /* Last time accessed - sec */ __fs32 vdi_atime; /* Last time accessed - sec */
u_int32_t vdi_autime; /* Last time accessed - usec */ __fs32 vdi_autime; /* Last time accessed - usec */
u_int32_t vdi_mtime; /* Last modify time - sec */ __fs32 vdi_mtime; /* Last modify time - sec */
u_int32_t vdi_mutime; /* Last modify time - usec */ __fs32 vdi_mutime; /* Last modify time - usec */
u_int32_t vdi_ctime; /* Create time - sec */ __fs32 vdi_ctime; /* Create time - sec */
u_int32_t vdi_cutime; /* Create time - usec */ __fs32 vdi_cutime; /* Create time - usec */
u_int8_t vdi_aflags; /* Allocation flags */ __u8 vdi_aflags; /* Allocation flags */
u_int8_t vdi_orgtype; /* Organisation type */ __u8 vdi_orgtype; /* Organisation type */
u_int16_t vdi_eopflags; __fs16 vdi_eopflags;
u_int32_t vdi_eopdata; __fs32 vdi_eopdata;
union { union {
u_int32_t rdev; __fs32 rdev;
u_int32_t dotdot; __fs32 dotdot;
struct { struct {
u_int32_t reserved; __u32 reserved;
u_int32_t fixextsize; __fs32 fixextsize;
} i_regular; } i_regular;
struct { struct {
u_int32_t matchino; __fs32 matchino;
u_int32_t fsetindex; __fs32 fsetindex;
} i_vxspec; } i_vxspec;
u_int64_t align; __u64 align;
} vdi_ftarea; } vdi_ftarea;
u_int32_t vdi_blocks; /* How much blocks does inode occupy */ __fs32 vdi_blocks; /* How much blocks does inode occupy */
u_int32_t vdi_gen; /* Inode generation */ __fs32 vdi_gen; /* Inode generation */
u_int64_t vdi_version; /* Version */ __fs64 vdi_version; /* Version */
union { union {
struct vxfs_immed immed; struct vxfs_immed immed;
struct vxfs_ext4 ext4; struct vxfs_ext4 ext4;
struct vxfs_typed typed[VXFS_NTYPED]; struct vxfs_typed typed[VXFS_NTYPED];
} vdi_org; } vdi_org;
u_int32_t vdi_iattrino; __fs32 vdi_iattrino;
}; };
#define vdi_rdev vdi_ftarea.rdev #define vdi_rdev vdi_ftarea.rdev
@ -149,32 +149,38 @@ struct vxfs_dinode {
/* /*
* The inode as represented in the main memory. * 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_rdev vii_ftarea.rdev
#define vii_uid vdi_uid #define vii_dotdot vii_ftarea.dotdot
#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_immed vii_org.immed
#define vii_dotdot vdi_ftarea.dotdot #define vii_ext4 vii_org.ext4
#define vii_fixextsize vdi_ftarea.regular.fixextsize #define vii_typed vii_org.typed
#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
#endif /* _VXFS_INODE_H_ */ #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. * len <= VXFS_NAMELEN and de != NULL are guaranteed by caller.
*/ */
static inline int 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; return 0;
if (!de->d_ino) if (!de->d_ino)
return 0; return 0;
@ -84,9 +85,10 @@ vxfs_match(int len, const char * const name, struct vxfs_direct *de)
} }
static inline struct vxfs_direct * 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 * static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp) 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 npages, page, nblocks, pblocks, block;
u_long bsize = ip->i_sb->s_blocksize; u_long bsize = ip->i_sb->s_blocksize;
const char *name = dp->d_name.name; 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); limit = baddr + bsize - VXFS_DIRLEN(1);
dbp = (struct vxfs_dirblk *)baddr; 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) if (!de->d_reclen)
break; break;
if (!de->d_ino) if (!de->d_ino)
continue; continue;
if (vxfs_match(namelen, name, de)) { if (vxfs_match(sbi, namelen, name, de)) {
*ppp = pp; *ppp = pp;
return (de); return (de);
} }
@ -173,7 +178,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
de = vxfs_find_entry(dip, dp, &pp); de = vxfs_find_entry(dip, dp, &pp);
if (de) { if (de) {
ino = de->d_ino; ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
kunmap(pp); kunmap(pp);
put_page(pp); put_page(pp);
} }
@ -232,10 +237,12 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
{ {
struct inode *ip = file_inode(fp); struct inode *ip = file_inode(fp);
struct super_block *sbp = ip->i_sb; struct super_block *sbp = ip->i_sb;
struct vxfs_sb_info *sbi = VXFS_SBI(sbp);
u_long bsize = sbp->s_blocksize; u_long bsize = sbp->s_blocksize;
u_long page, npages, block, pblocks, nblocks, offset; u_long page, npages, block, pblocks, nblocks, offset;
loff_t pos; loff_t pos;
if (ctx->pos == 0) { if (ctx->pos == 0) {
if (!dir_emit_dot(fp, ctx)) if (!dir_emit_dot(fp, ctx))
return 0; return 0;
@ -280,9 +287,10 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
de = (struct vxfs_direct *) de = (struct vxfs_direct *)
(offset ? (offset ?
(kaddr + 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) if (!de->d_reclen)
break; break;
if (!de->d_ino) if (!de->d_ino)
@ -290,8 +298,10 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
offset = (char *)de - kaddr; offset = (char *)de - kaddr;
ctx->pos = ((page << PAGE_SHIFT) | offset) + 2; ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
if (!dir_emit(ctx, de->d_name, de->d_namelen, if (!dir_emit(ctx, de->d_name,
de->d_ino, DT_UNKNOWN)) { fs16_to_cpu(sbi, de->d_namelen),
fs32_to_cpu(sbi, de->d_ino),
DT_UNKNOWN)) {
vxfs_put_page(pp); vxfs_put_page(pp);
return 0; return 0;
} }

View File

@ -43,14 +43,14 @@ static inline void
vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp) vxfs_get_fshead(struct vxfs_oltfshead *fshp, struct vxfs_sb_info *infp)
{ {
BUG_ON(infp->vsi_fshino); 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 static inline void
vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp) vxfs_get_ilist(struct vxfs_oltilist *ilistp, struct vxfs_sb_info *infp)
{ {
BUG_ON(infp->vsi_iext); 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 static inline u_long
@ -81,13 +81,12 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
struct vxfs_olt *op; struct vxfs_olt *op;
char *oaddr, *eaddr; char *oaddr, *eaddr;
bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize)); bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
if (!bp || !bp->b_data) if (!bp || !bp->b_data)
goto fail; goto fail;
op = (struct vxfs_olt *)bp->b_data; 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"); printk(KERN_NOTICE "vxfs: ivalid olt magic number\n");
goto fail; goto fail;
} }
@ -102,14 +101,14 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
goto fail; 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); eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
while (oaddr < eaddr) { while (oaddr < eaddr) {
struct vxfs_oltcommon *ocp = struct vxfs_oltcommon *ocp =
(struct vxfs_oltcommon *)oaddr; (struct vxfs_oltcommon *)oaddr;
switch (ocp->olt_type) { switch (fs32_to_cpu(infp, ocp->olt_type)) {
case VXFS_OLT_FSHEAD: case VXFS_OLT_FSHEAD:
vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp); vxfs_get_fshead((struct vxfs_oltfshead *)oaddr, infp);
break; break;
@ -118,11 +117,11 @@ vxfs_read_olt(struct super_block *sbp, u_long bsize)
break; break;
} }
oaddr += ocp->olt_size; oaddr += fs32_to_cpu(infp, ocp->olt_size);
} }
brelse(bp); brelse(bp);
return 0; return (infp->vsi_fshino && infp->vsi_iext) ? 0 : -EINVAL;
fail: fail:
brelse(bp); brelse(bp);

View File

@ -63,83 +63,83 @@ enum {
* the initial inode list, the fileset header or the device configuration. * the initial inode list, the fileset header or the device configuration.
*/ */
struct vxfs_olt { struct vxfs_olt {
u_int32_t olt_magic; /* magic number */ __fs32 olt_magic; /* magic number */
u_int32_t olt_size; /* size of this entry */ __fs32 olt_size; /* size of this entry */
u_int32_t olt_checksum; /* checksum of extent */ __fs32 olt_checksum; /* checksum of extent */
u_int32_t __unused1; /* ??? */ __u32 __unused1; /* ??? */
u_int32_t olt_mtime; /* time of last mod. (sec) */ __fs32 olt_mtime; /* time of last mod. (sec) */
u_int32_t olt_mutime; /* time of last mod. (usec) */ __fs32 olt_mutime; /* time of last mod. (usec) */
u_int32_t olt_totfree; /* free space in OLT extent */ __fs32 olt_totfree; /* free space in OLT extent */
vx_daddr_t olt_extents[2]; /* addr of this extent, replica */ __fs32 olt_extents[2]; /* addr of this extent, replica */
u_int32_t olt_esize; /* size of this extent */ __fs32 olt_esize; /* size of this extent */
vx_daddr_t olt_next[2]; /* addr of next extent, replica */ __fs32 olt_next[2]; /* addr of next extent, replica */
u_int32_t olt_nsize; /* size of next extent */ __fs32 olt_nsize; /* size of next extent */
u_int32_t __unused2; /* align to 8 byte boundary */ __u32 __unused2; /* align to 8 byte boundary */
}; };
/* /*
* VxFS common OLT entry (on disk). * VxFS common OLT entry (on disk).
*/ */
struct vxfs_oltcommon { struct vxfs_oltcommon {
u_int32_t olt_type; /* type of this record */ __fs32 olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */ __fs32 olt_size; /* size of this record */
}; };
/* /*
* VxFS free OLT entry (on disk). * VxFS free OLT entry (on disk).
*/ */
struct vxfs_oltfree { struct vxfs_oltfree {
u_int32_t olt_type; /* type of this record */ __fs32 olt_type; /* type of this record */
u_int32_t olt_fsize; /* size of this free record */ __fs32 olt_fsize; /* size of this free record */
}; };
/* /*
* VxFS initial-inode list (on disk). * VxFS initial-inode list (on disk).
*/ */
struct vxfs_oltilist { struct vxfs_oltilist {
u_int32_t olt_type; /* type of this record */ __fs32 olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */ __fs32 olt_size; /* size of this record */
vx_ino_t olt_iext[2]; /* initial inode list, replica */ __fs32 olt_iext[2]; /* initial inode list, replica */
}; };
/* /*
* Current Usage Table * Current Usage Table
*/ */
struct vxfs_oltcut { struct vxfs_oltcut {
u_int32_t olt_type; /* type of this record */ __fs32 olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */ __fs32 olt_size; /* size of this record */
vx_ino_t olt_cutino; /* inode of current usage table */ __fs32 olt_cutino; /* inode of current usage table */
u_int32_t __pad; /* unused, 8 byte align */ __u8 __pad; /* unused, 8 byte align */
}; };
/* /*
* Inodes containing Superblock, Intent log and OLTs * Inodes containing Superblock, Intent log and OLTs
*/ */
struct vxfs_oltsb { struct vxfs_oltsb {
u_int32_t olt_type; /* type of this record */ __fs32 olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */ __fs32 olt_size; /* size of this record */
vx_ino_t olt_sbino; /* inode of superblock file */ __fs32 olt_sbino; /* inode of superblock file */
u_int32_t __unused1; /* ??? */ __u32 __unused1; /* ??? */
vx_ino_t olt_logino[2]; /* inode of log file,replica */ __fs32 olt_logino[2]; /* inode of log file,replica */
vx_ino_t olt_oltino[2]; /* inode of OLT, replica */ __fs32 olt_oltino[2]; /* inode of OLT, replica */
}; };
/* /*
* Inode containing device configuration + it's replica * Inode containing device configuration + it's replica
*/ */
struct vxfs_oltdev { struct vxfs_oltdev {
u_int32_t olt_type; /* type of this record */ __fs32 olt_type; /* type of this record */
u_int32_t olt_size; /* size of this record */ __fs32 olt_size; /* size of this record */
vx_ino_t olt_devino[2]; /* inode of device config files */ __fs32 olt_devino[2]; /* inode of device config files */
}; };
/* /*
* Fileset header * Fileset header
*/ */
struct vxfs_oltfshead { struct vxfs_oltfshead {
u_int32_t olt_type; /* type number */ __fs32 olt_type; /* type number */
u_int32_t olt_size; /* size of this record */ __fs32 olt_size; /* size of this record */
vx_ino_t olt_fsino[2]; /* inodes of fileset header */ __fs32 olt_fsino[2]; /* inodes of fileset header */
}; };
#endif /* _VXFS_OLT_H_ */ #endif /* _VXFS_OLT_H_ */

View File

@ -109,14 +109,15 @@ static int
vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
{ {
struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb); 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_type = VXFS_SUPER_MAGIC;
bufp->f_bsize = dentry->d_sb->s_blocksize; bufp->f_bsize = dentry->d_sb->s_blocksize;
bufp->f_blocks = infp->vsi_raw->vs_dsize; bufp->f_blocks = fs32_to_cpu(infp, raw_sb->vs_dsize);
bufp->f_bfree = infp->vsi_raw->vs_free; bufp->f_bfree = fs32_to_cpu(infp, raw_sb->vs_free);
bufp->f_bavail = 0; bufp->f_bavail = 0;
bufp->f_files = 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; bufp->f_namelen = VXFS_NAMELEN;
return 0; return 0;
@ -129,6 +130,50 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
return 0; 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 * vxfs_read_super - read superblock into memory and initialize filesystem
* @sbp: VFS superblock (to fill) * @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_info *infp;
struct vxfs_sb *rsbp; struct vxfs_sb *rsbp;
struct buffer_head *bp = NULL;
u_long bsize; u_long bsize;
struct inode *root; struct inode *root;
int ret = -EINVAL; int ret = -EINVAL;
u32 j;
sbp->s_flags |= MS_RDONLY; sbp->s_flags |= MS_RDONLY;
@ -168,42 +213,42 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
goto out; goto out;
} }
bp = sb_bread(sbp, 1); sbp->s_fs_info = infp;
if (!bp || !buffer_mapped(bp)) {
if (!silent) {
printk(KERN_WARNING
"vxfs: unable to read disk superblock\n");
}
goto out;
}
rsbp = (struct vxfs_sb *)bp->b_data; if (!vxfs_try_sb_magic(sbp, silent, 1,
if (rsbp->vs_magic != VXFS_SUPER_MAGIC) { (__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) if (!silent)
printk(KERN_NOTICE "vxfs: WRONG superblock magic\n"); printk(KERN_NOTICE "vxfs: can't find superblock.\n");
goto out; goto out;
} }
if ((rsbp->vs_version < 2 || rsbp->vs_version > 4) && !silent) { rsbp = infp->vsi_raw;
printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j = fs32_to_cpu(infp, rsbp->vs_version);
rsbp->vs_version); if ((j < 2 || j > 4) && !silent) {
printk(KERN_NOTICE "vxfs: unsupported VxFS version (%d)\n", j);
goto out; goto out;
} }
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", rsbp->vs_version); printk(KERN_DEBUG "vxfs: supported VxFS version (%d)\n", j);
printk(KERN_DEBUG "vxfs: blocksize: %d\n", rsbp->vs_bsize); printk(KERN_DEBUG "vxfs: blocksize: %d\n",
fs32_to_cpu(infp, rsbp->vs_bsize));
#endif #endif
sbp->s_magic = rsbp->vs_magic; sbp->s_magic = fs32_to_cpu(infp, rsbp->vs_magic);
sbp->s_fs_info = infp;
infp->vsi_raw = rsbp; infp->vsi_oltext = fs32_to_cpu(infp, rsbp->vs_oltext[0]);
infp->vsi_bp = bp; infp->vsi_oltsize = fs32_to_cpu(infp, rsbp->vs_oltsize);
infp->vsi_oltext = rsbp->vs_oltext[0];
infp->vsi_oltsize = 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"); printk(KERN_WARNING "vxfs: unable to set final block size\n");
goto out; goto out;
} }
@ -237,7 +282,7 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
vxfs_put_fake_inode(infp->vsi_ilist); vxfs_put_fake_inode(infp->vsi_ilist);
vxfs_put_fake_inode(infp->vsi_stilist); vxfs_put_fake_inode(infp->vsi_stilist);
out: out:
brelse(bp); brelse(infp->vsi_bp);
kfree(infp); kfree(infp);
return ret; return ret;
} }