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:
parent
6b15d6650c
commit
0d83f7fc83
|
@ -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
|
||||
|
|
|
@ -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 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
|
|||
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:
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 @@ 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_stilist);
|
||||
out:
|
||||
brelse(bp);
|
||||
brelse(infp->vsi_bp);
|
||||
kfree(infp);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue