aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 11:56:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 11:56:29 -0700
commit0a7736d03720a450727c6ab906e13b60d4d34e42 (patch)
treec3ddbf0e3dc9ac7273a2cf8d639d83bdf20481d4 /fs
parentMerge tag 'configfs-for-4.8' of git://git.infradead.org/users/hch/configfs (diff)
parentfreevxfs: update Kconfig information (diff)
downloadlinux-dev-0a7736d03720a450727c6ab906e13b60d4d34e42.tar.xz
linux-dev-0a7736d03720a450727c6ab906e13b60d4d34e42.zip
Merge tag 'freevxfs-for-4.8' of git://git.infradead.org/users/hch/freevxfs
Pull freevxfs updates from Christoph Hellwig: "Support for foreign endianess and HP-UP superblocks from Krzysztof Błaszkowski" * tag 'freevxfs-for-4.8' of git://git.infradead.org/users/hch/freevxfs: freevxfs: update Kconfig information freevxfs: refactor readdir and lookup code freevxfs: fix lack of inode initialization freevxfs: fix memory leak in vxfs_read_fshead() freevxfs: update documentation and cresdits for HP-UX support freevxfs: implement ->alloc_inode and ->destroy_inode freevxfs: avoid the need for forward declaring the super operations freevxfs: move VFS inode allocation into vxfs_blkiget and vxfs_stiget freevxfs: remove vxfs_put_fake_inode freevxfs: handle big endian HP-UX file systems
Diffstat (limited to 'fs')
-rw-r--r--fs/freevxfs/Kconfig13
-rw-r--r--fs/freevxfs/vxfs.h185
-rw-r--r--fs/freevxfs/vxfs_bmap.c70
-rw-r--r--fs/freevxfs/vxfs_dir.h17
-rw-r--r--fs/freevxfs/vxfs_extern.h10
-rw-r--r--fs/freevxfs/vxfs_fshead.c37
-rw-r--r--fs/freevxfs/vxfs_fshead.h29
-rw-r--r--fs/freevxfs/vxfs_inode.c265
-rw-r--r--fs/freevxfs/vxfs_inode.h146
-rw-r--r--fs/freevxfs/vxfs_lookup.c226
-rw-r--r--fs/freevxfs/vxfs_olt.c15
-rw-r--r--fs/freevxfs/vxfs_olt.h70
-rw-r--r--fs/freevxfs/vxfs_super.c162
13 files changed, 661 insertions, 584 deletions
diff --git a/fs/freevxfs/Kconfig b/fs/freevxfs/Kconfig
index 8dc1cd5c1efe..ce49df1020dd 100644
--- a/fs/freevxfs/Kconfig
+++ b/fs/freevxfs/Kconfig
@@ -5,12 +5,21 @@ config VXFS_FS
FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
file system format. VERITAS VxFS(TM) is the standard file system
of SCO UnixWare (and possibly others) and optionally available
- for Sunsoft Solaris, HP-UX and many other operating systems.
- Currently only readonly access is supported.
+ for Sunsoft Solaris, HP-UX and many other operating systems. However
+ these particular OS implementations of vxfs may differ in on-disk
+ data endianess and/or superblock offset. The vxfs module has been
+ tested with SCO UnixWare and HP-UX B.10.20 (pa-risc 1.1 arch.)
+ Currently only readonly access is supported and VxFX versions
+ 2, 3 and 4. Tests were performed with HP-UX VxFS version 3.
NOTE: the file system type as used by mount(1), mount(2) and
fstab(5) is 'vxfs' as it describes the file system format, not
the actual driver.
+ There is a userspace utility for HP-UX logical volumes which makes
+ creating HP-UX logical volumes easy from HP-UX disk block device file
+ or regular file with image of the disk. See:
+ https://sourceforge.net/projects/linux-vxfs/
+
To compile this as a module, choose M here: the module will be
called freevxfs. If unsure, say N.
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index c8a92652612a..a41ea0ba6943 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,13 +39,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 +54,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 +73,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 +170,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
@@ -247,13 +273,6 @@ enum {
#define VXFS_ISIMMED(ip) VXFS_IS_ORG((ip), VXFS_ORG_IMMED)
#define VXFS_ISTYPED(ip) VXFS_IS_ORG((ip), VXFS_ORG_TYPED)
-
-/*
- * Get filesystem private data from VFS inode.
- */
-#define VXFS_INO(ip) \
- ((struct vxfs_inode_info *)(ip)->i_private)
-
/*
* Get filesystem private data from VFS superblock.
*/
diff --git a/fs/freevxfs/vxfs_bmap.c b/fs/freevxfs/vxfs_bmap.c
index f86fd3cacd5a..1fd41cf98b9f 100644
--- a/fs/freevxfs/vxfs_bmap.c
+++ b/fs/freevxfs/vxfs_bmap.c
@@ -68,8 +68,9 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
{
struct super_block *sb = ip->i_sb;
struct vxfs_inode_info *vip = VXFS_INO(ip);
+ struct vxfs_sb_info *sbi = VXFS_SBI(sb);
unsigned long bsize = sb->s_blocksize;
- u32 indsize = vip->vii_ext4.ve4_indsize;
+ u32 indsize = fs32_to_cpu(sbi, vip->vii_ext4.ve4_indsize);
int i;
if (indsize > sb->s_blocksize)
@@ -77,22 +78,24 @@ vxfs_bmap_ext4(struct inode *ip, long bn)
for (i = 0; i < VXFS_NDADDR; i++) {
struct direct *d = vip->vii_ext4.ve4_direct + i;
- if (bn >= 0 && bn < d->size)
- return (bn + d->extent);
- bn -= d->size;
+ if (bn >= 0 && bn < fs32_to_cpu(sbi, d->size))
+ return (bn + fs32_to_cpu(sbi, d->extent));
+ bn -= fs32_to_cpu(sbi, d->size);
}
if ((bn / (indsize * indsize * bsize / 4)) == 0) {
struct buffer_head *buf;
daddr_t bno;
- u32 *indir;
+ __fs32 *indir;
- buf = sb_bread(sb, vip->vii_ext4.ve4_indir[0]);
+ buf = sb_bread(sb,
+ fs32_to_cpu(sbi, vip->vii_ext4.ve4_indir[0]));
if (!buf || !buffer_mapped(buf))
goto fail_buf;
- indir = (u32 *)buf->b_data;
- bno = indir[(bn/indsize) % (indsize*bn)] + (bn%indsize);
+ indir = (__fs32 *)buf->b_data;
+ bno = fs32_to_cpu(sbi, indir[(bn / indsize) % (indsize * bn)]) +
+ (bn % indsize);
brelse(buf);
return bno;
@@ -127,6 +130,7 @@ fail_buf:
static daddr_t
vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
{
+ struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
struct buffer_head *bp = NULL;
daddr_t pblock = 0;
int i;
@@ -142,24 +146,27 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
typ = ((struct vxfs_typed *)bp->b_data) +
(i % VXFS_TYPED_PER_BLOCK(ip->i_sb));
- off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+ off = fs64_to_cpu(sbi, typ->vt_hdr) & VXFS_TYPED_OFFSETMASK;
if (block < off) {
brelse(bp);
continue;
}
- switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+ switch ((u_int32_t)(fs64_to_cpu(sbi, typ->vt_hdr) >>
+ VXFS_TYPED_TYPESHIFT)) {
case VXFS_TYPED_INDIRECT:
- pblock = vxfs_bmap_indir(ip, typ->vt_block,
- typ->vt_size, block - off);
+ pblock = vxfs_bmap_indir(ip,
+ fs32_to_cpu(sbi, typ->vt_block),
+ fs32_to_cpu(sbi, typ->vt_size),
+ block - off);
if (pblock == -2)
break;
goto out;
case VXFS_TYPED_DATA:
- if ((block - off) >= typ->vt_size)
+ if ((block - off) >= fs32_to_cpu(sbi, typ->vt_size))
break;
- pblock = (typ->vt_block + block - off);
+ pblock = fs32_to_cpu(sbi, typ->vt_block) + block - off;
goto out;
case VXFS_TYPED_INDIRECT_DEV4:
case VXFS_TYPED_DATA_DEV4: {
@@ -167,13 +174,15 @@ vxfs_bmap_indir(struct inode *ip, long indir, int size, long block)
(struct vxfs_typed_dev4 *)typ;
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
- printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
- (unsigned long long) typ4->vd4_block,
- (unsigned long long) typ4->vd4_size,
- typ4->vd4_dev);
+ printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
+ fs64_to_cpu(sbi, typ4->vd4_block),
+ fs64_to_cpu(sbi, typ4->vd4_size),
+ fs32_to_cpu(sbi, typ4->vd4_dev));
goto fail;
}
default:
+ printk(KERN_ERR "%s:%d vt_hdr %llu\n", __func__,
+ __LINE__, fs64_to_cpu(sbi, typ->vt_hdr));
BUG();
}
brelse(bp);
@@ -201,28 +210,33 @@ static daddr_t
vxfs_bmap_typed(struct inode *ip, long iblock)
{
struct vxfs_inode_info *vip = VXFS_INO(ip);
+ struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
daddr_t pblock = 0;
int i;
for (i = 0; i < VXFS_NTYPED; i++) {
struct vxfs_typed *typ = vip->vii_org.typed + i;
- int64_t off = (typ->vt_hdr & VXFS_TYPED_OFFSETMASK);
+ u64 hdr = fs64_to_cpu(sbi, typ->vt_hdr);
+ int64_t off = (hdr & VXFS_TYPED_OFFSETMASK);
#ifdef DIAGNOSTIC
vxfs_typdump(typ);
#endif
if (iblock < off)
continue;
- switch ((u_int32_t)(typ->vt_hdr >> VXFS_TYPED_TYPESHIFT)) {
+ switch ((u32)(hdr >> VXFS_TYPED_TYPESHIFT)) {
case VXFS_TYPED_INDIRECT:
- pblock = vxfs_bmap_indir(ip, typ->vt_block,
- typ->vt_size, iblock - off);
+ pblock = vxfs_bmap_indir(ip,
+ fs32_to_cpu(sbi, typ->vt_block),
+ fs32_to_cpu(sbi, typ->vt_size),
+ iblock - off);
if (pblock == -2)
break;
return (pblock);
case VXFS_TYPED_DATA:
- if ((iblock - off) < typ->vt_size)
- return (typ->vt_block + iblock - off);
+ if ((iblock - off) < fs32_to_cpu(sbi, typ->vt_size))
+ return (fs32_to_cpu(sbi, typ->vt_block) +
+ iblock - off);
break;
case VXFS_TYPED_INDIRECT_DEV4:
case VXFS_TYPED_DATA_DEV4: {
@@ -230,10 +244,10 @@ vxfs_bmap_typed(struct inode *ip, long iblock)
(struct vxfs_typed_dev4 *)typ;
printk(KERN_INFO "\n\nTYPED_DEV4 detected!\n");
- printk(KERN_INFO "block: %Lu\tsize: %Ld\tdev: %d\n",
- (unsigned long long) typ4->vd4_block,
- (unsigned long long) typ4->vd4_size,
- typ4->vd4_dev);
+ printk(KERN_INFO "block: %llu\tsize: %lld\tdev: %d\n",
+ fs64_to_cpu(sbi, typ4->vd4_block),
+ fs64_to_cpu(sbi, typ4->vd4_size),
+ fs32_to_cpu(sbi, typ4->vd4_dev));
return 0;
}
default:
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
index aaf1fb098639..acc5477b3f23 100644
--- a/fs/freevxfs/vxfs_dir.h
+++ b/fs/freevxfs/vxfs_dir.h
@@ -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_ */
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index e3dcb4467d92..f5c428e21024 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -52,14 +52,10 @@ extern int vxfs_read_fshead(struct super_block *);
/* vxfs_inode.c */
extern const struct address_space_operations vxfs_immed_aops;
-extern struct kmem_cache *vxfs_inode_cachep;
extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
-extern struct inode * vxfs_get_fake_inode(struct super_block *,
- struct vxfs_inode_info *);
-extern void vxfs_put_fake_inode(struct inode *);
-extern struct vxfs_inode_info * vxfs_blkiget(struct super_block *, u_long, ino_t);
-extern struct vxfs_inode_info * vxfs_stiget(struct super_block *, ino_t);
-extern struct inode * vxfs_iget(struct super_block *, ino_t);
+extern struct inode *vxfs_blkiget(struct super_block *, u_long, ino_t);
+extern struct inode *vxfs_stiget(struct super_block *, ino_t);
+extern struct inode *vxfs_iget(struct super_block *, ino_t);
extern void vxfs_evict_inode(struct inode *);
/* vxfs_lookup.c */
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index c9a6a94e58e9..a4610a77649e 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -108,31 +109,26 @@ vxfs_read_fshead(struct super_block *sbp)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
struct vxfs_fsh *pfp, *sfp;
- struct vxfs_inode_info *vip, *tip;
+ struct vxfs_inode_info *vip;
- vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
- if (!vip) {
+ infp->vsi_fship = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
+ if (!infp->vsi_fship) {
printk(KERN_ERR "vxfs: unable to read fsh inode\n");
return -EINVAL;
}
+
+ vip = VXFS_INO(infp->vsi_fship);
if (!VXFS_ISFSH(vip)) {
printk(KERN_ERR "vxfs: fsh list inode is of wrong type (%x)\n",
vip->vii_mode & VXFS_TYPE_MASK);
- goto out_free_fship;
+ goto out_iput_fship;
}
-
#ifdef DIAGNOSTIC
printk("vxfs: fsh inode dump:\n");
vxfs_dumpi(vip, infp->vsi_fshino);
#endif
- infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
- if (!infp->vsi_fship) {
- printk(KERN_ERR "vxfs: unable to get fsh inode\n");
- goto out_free_fship;
- }
-
sfp = vxfs_getfsh(infp->vsi_fship, 0);
if (!sfp) {
printk(KERN_ERR "vxfs: unable to get structural fsh\n");
@@ -153,14 +149,10 @@ vxfs_read_fshead(struct super_block *sbp)
vxfs_dumpfsh(pfp);
#endif
- tip = vxfs_blkiget(sbp, infp->vsi_iext, sfp->fsh_ilistino[0]);
- if (!tip)
- goto out_free_pfp;
-
- infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
+ infp->vsi_stilist = vxfs_blkiget(sbp, infp->vsi_iext,
+ fs32_to_cpu(infp, sfp->fsh_ilistino[0]));
if (!infp->vsi_stilist) {
printk(KERN_ERR "vxfs: unable to get structural list inode\n");
- kfree(tip);
goto out_free_pfp;
}
if (!VXFS_ISILT(VXFS_INO(infp->vsi_stilist))) {
@@ -169,13 +161,9 @@ vxfs_read_fshead(struct super_block *sbp)
goto out_iput_stilist;
}
- tip = vxfs_stiget(sbp, pfp->fsh_ilistino[0]);
- if (!tip)
- goto out_iput_stilist;
- infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
+ infp->vsi_ilist = vxfs_stiget(sbp, fs32_to_cpu(infp, pfp->fsh_ilistino[0]));
if (!infp->vsi_ilist) {
printk(KERN_ERR "vxfs: unable to get inode list inode\n");
- kfree(tip);
goto out_iput_stilist;
}
if (!VXFS_ISILT(VXFS_INO(infp->vsi_ilist))) {
@@ -184,6 +172,8 @@ vxfs_read_fshead(struct super_block *sbp)
goto out_iput_ilist;
}
+ kfree(pfp);
+ kfree(sfp);
return 0;
out_iput_ilist:
@@ -197,7 +187,4 @@ vxfs_read_fshead(struct super_block *sbp)
out_iput_fship:
iput(infp->vsi_fship);
return -EINVAL;
- out_free_fship:
- kfree(vip);
- return -EINVAL;
}
diff --git a/fs/freevxfs/vxfs_fshead.h b/fs/freevxfs/vxfs_fshead.h
index ead0d640c181..e026f0c49159 100644
--- a/fs/freevxfs/vxfs_fshead.h
+++ b/fs/freevxfs/vxfs_fshead.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,20 +43,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
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 3e2ccade61ed..1f41b25ef38b 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,9 +43,6 @@
#include "vxfs_extern.h"
-struct kmem_cache *vxfs_inode_cachep;
-
-
#ifdef DIAGNOSTIC
/*
* Dump inode contents (partially).
@@ -68,6 +66,83 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
}
#endif
+/**
+ * vxfs_transmod - mode for a VxFS inode
+ * @vip: VxFS inode
+ *
+ * Description:
+ * vxfs_transmod returns a Linux mode_t for a given
+ * VxFS inode structure.
+ */
+static __inline__ umode_t
+vxfs_transmod(struct vxfs_inode_info *vip)
+{
+ umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
+
+ if (VXFS_ISFIFO(vip))
+ ret |= S_IFIFO;
+ if (VXFS_ISCHR(vip))
+ ret |= S_IFCHR;
+ if (VXFS_ISDIR(vip))
+ ret |= S_IFDIR;
+ if (VXFS_ISBLK(vip))
+ ret |= S_IFBLK;
+ if (VXFS_ISLNK(vip))
+ ret |= S_IFLNK;
+ if (VXFS_ISREG(vip))
+ ret |= S_IFREG;
+ if (VXFS_ISSOC(vip))
+ ret |= S_IFSOCK;
+
+ return (ret);
+}
+
+static inline void dip2vip_cpy(struct vxfs_sb_info *sbi,
+ struct vxfs_inode_info *vip, struct vxfs_dinode *dip)
+{
+ struct inode *inode = &vip->vfs_inode;
+
+ 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));
+
+ inode->i_mode = vxfs_transmod(vip);
+ i_uid_write(inode, (uid_t)vip->vii_uid);
+ i_gid_write(inode, (gid_t)vip->vii_gid);
+
+ set_nlink(inode, vip->vii_nlink);
+ inode->i_size = vip->vii_size;
+
+ inode->i_atime.tv_sec = vip->vii_atime;
+ inode->i_ctime.tv_sec = vip->vii_ctime;
+ inode->i_mtime.tv_sec = vip->vii_mtime;
+ inode->i_atime.tv_nsec = 0;
+ inode->i_ctime.tv_nsec = 0;
+ inode->i_mtime.tv_nsec = 0;
+
+ inode->i_blocks = vip->vii_blocks;
+ inode->i_generation = vip->vii_gen;
+}
/**
* vxfs_blkiget - find inode based on extent #
@@ -85,50 +160,55 @@ vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino)
* buffercache. This function should not be used outside the
* read_super() method, otherwise the data may be incoherent.
*/
-struct vxfs_inode_info *
+struct inode *
vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino)
{
struct buffer_head *bp;
+ struct inode *inode;
u_long block, offset;
+ inode = new_inode(sbp);
+ if (!inode)
+ return NULL;
+ inode->i_ino = get_next_ino();
+
block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize);
offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE);
bp = sb_bread(sbp, block);
if (bp && buffer_mapped(bp)) {
- struct vxfs_inode_info *vip;
+ struct vxfs_inode_info *vip = VXFS_INO(inode);
struct vxfs_dinode *dip;
- 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);
+ vip->vfs_inode.i_mapping->a_ops = &vxfs_aops;
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
brelse(bp);
- return (vip);
+ return inode;
}
-fail:
printk(KERN_WARNING "vxfs: unable to read block %ld\n", block);
brelse(bp);
+ iput(inode);
return NULL;
}
/**
* __vxfs_iget - generic find inode facility
- * @sbp: VFS superblock
- * @ino: inode number
* @ilistp: inode list
+ * @vip: VxFS inode to fill in
+ * @ino: inode number
*
* Description:
* Search the for inode number @ino in the filesystem
* described by @sbp. Use the specified inode table (@ilistp).
- * Returns the matching VxFS inode on success, else an error code.
+ * Returns the matching inode on success, else an error code.
*/
-static struct vxfs_inode_info *
-__vxfs_iget(ino_t ino, struct inode *ilistp)
+static int
+__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino)
{
struct page *pp;
u_long offset;
@@ -137,28 +217,22 @@ __vxfs_iget(ino_t ino, struct inode *ilistp)
pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE);
if (!IS_ERR(pp)) {
- struct vxfs_inode_info *vip;
struct vxfs_dinode *dip;
caddr_t kaddr = (char *)page_address(pp);
- 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);
+ vip->vfs_inode.i_mapping->a_ops = &vxfs_aops;
#ifdef DIAGNOSTIC
vxfs_dumpi(vip, ino);
#endif
vxfs_put_page(pp);
- return (vip);
+ return 0;
}
- printk(KERN_WARNING "vxfs: error on page %p\n", pp);
- return ERR_CAST(pp);
-
-fail:
- printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino);
- vxfs_put_page(pp);
- return ERR_PTR(-ENOMEM);
+ printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n",
+ pp, (unsigned long)ino);
+ return PTR_ERR(pp);
}
/**
@@ -169,116 +243,26 @@ fail:
* Description:
* Find inode @ino in the filesystem described by @sbp using
* the structural inode list.
- * Returns the matching VxFS inode on success, else a NULL pointer.
- */
-struct vxfs_inode_info *
-vxfs_stiget(struct super_block *sbp, ino_t ino)
-{
- struct vxfs_inode_info *vip;
-
- vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist);
- return IS_ERR(vip) ? NULL : vip;
-}
-
-/**
- * vxfs_transmod - mode for a VxFS inode
- * @vip: VxFS inode
- *
- * Description:
- * vxfs_transmod returns a Linux mode_t for a given
- * VxFS inode structure.
- */
-static __inline__ umode_t
-vxfs_transmod(struct vxfs_inode_info *vip)
-{
- umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK;
-
- if (VXFS_ISFIFO(vip))
- ret |= S_IFIFO;
- if (VXFS_ISCHR(vip))
- ret |= S_IFCHR;
- if (VXFS_ISDIR(vip))
- ret |= S_IFDIR;
- if (VXFS_ISBLK(vip))
- ret |= S_IFBLK;
- if (VXFS_ISLNK(vip))
- ret |= S_IFLNK;
- if (VXFS_ISREG(vip))
- ret |= S_IFREG;
- if (VXFS_ISSOC(vip))
- ret |= S_IFSOCK;
-
- return (ret);
-}
-
-/**
- * vxfs_iinit- helper to fill inode fields
- * @ip: VFS inode
- * @vip: VxFS inode
- *
- * Description:
- * vxfs_instino is a helper function to fill in all relevant
- * fields in @ip from @vip.
- */
-static void
-vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
-{
-
- ip->i_mode = vxfs_transmod(vip);
- i_uid_write(ip, (uid_t)vip->vii_uid);
- i_gid_write(ip, (gid_t)vip->vii_gid);
-
- set_nlink(ip, vip->vii_nlink);
- ip->i_size = vip->vii_size;
-
- ip->i_atime.tv_sec = vip->vii_atime;
- ip->i_ctime.tv_sec = vip->vii_ctime;
- ip->i_mtime.tv_sec = vip->vii_mtime;
- ip->i_atime.tv_nsec = 0;
- ip->i_ctime.tv_nsec = 0;
- ip->i_mtime.tv_nsec = 0;
-
- ip->i_blocks = vip->vii_blocks;
- ip->i_generation = vip->vii_gen;
-
- ip->i_private = vip;
-
-}
-
-/**
- * vxfs_get_fake_inode - get fake inode structure
- * @sbp: filesystem superblock
- * @vip: fspriv inode
- *
- * Description:
- * vxfs_fake_inode gets a fake inode (not in the inode hash) for a
- * superblock, vxfs_inode pair.
- * Returns the filled VFS inode.
+ * Returns the matching inode on success, else a NULL pointer.
*/
struct inode *
-vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip)
+vxfs_stiget(struct super_block *sbp, ino_t ino)
{
- struct inode *ip = NULL;
-
- if ((ip = new_inode(sbp))) {
- ip->i_ino = get_next_ino();
- vxfs_iinit(ip, vip);
- ip->i_mapping->a_ops = &vxfs_aops;
+ struct inode *inode;
+ int error;
+
+ inode = new_inode(sbp);
+ if (!inode)
+ return NULL;
+ inode->i_ino = get_next_ino();
+
+ error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino);
+ if (error) {
+ iput(inode);
+ return NULL;
}
- return (ip);
-}
-/**
- * vxfs_put_fake_inode - free faked inode
- * *ip: VFS inode
- *
- * Description:
- * vxfs_put_fake_inode frees all data associated with @ip.
- */
-void
-vxfs_put_fake_inode(struct inode *ip)
-{
- iput(ip);
+ return inode;
}
/**
@@ -296,6 +280,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
struct vxfs_inode_info *vip;
const struct address_space_operations *aops;
struct inode *ip;
+ int error;
ip = iget_locked(sbp, ino);
if (!ip)
@@ -303,14 +288,13 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
if (!(ip->i_state & I_NEW))
return ip;
- vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist);
- if (IS_ERR(vip)) {
+ vip = VXFS_INO(ip);
+ error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino);
+ if (error) {
iget_failed(ip);
- return ERR_CAST(vip);
+ return ERR_PTR(error);
}
- vxfs_iinit(ip, vip);
-
if (VXFS_ISIMMED(vip))
aops = &vxfs_immed_aops;
else
@@ -341,12 +325,6 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
return ip;
}
-static void vxfs_i_callback(struct rcu_head *head)
-{
- struct inode *inode = container_of(head, struct inode, i_rcu);
- kmem_cache_free(vxfs_inode_cachep, inode->i_private);
-}
-
/**
* vxfs_evict_inode - remove inode from main memory
* @ip: inode to discard.
@@ -360,5 +338,4 @@ vxfs_evict_inode(struct inode *ip)
{
truncate_inode_pages_final(&ip->i_data);
clear_inode(ip);
- call_rcu(&ip->i_rcu, vxfs_i_callback);
}
diff --git a/fs/freevxfs/vxfs_inode.h b/fs/freevxfs/vxfs_inode.h
index 240aeb11263f..f012abed125d 100644
--- a/fs/freevxfs/vxfs_inode.h
+++ b/fs/freevxfs/vxfs_inode.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -66,74 +67,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 +150,45 @@ struct vxfs_dinode {
/*
* The inode as represented in the main memory.
- *
- * TBD: This should become a separate structure...
*/
-#define vxfs_inode_info vxfs_dinode
-
-#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 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
+struct vxfs_inode_info {
+ struct inode vfs_inode;
+
+ __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_rdev vii_ftarea.rdev
+#define vii_dotdot vii_ftarea.dotdot
+
+#define vii_immed vii_org.immed
+#define vii_ext4 vii_org.ext4
+#define vii_typed vii_org.typed
+
+static inline struct vxfs_inode_info *VXFS_INO(struct inode *inode)
+{
+ return container_of(inode, struct vxfs_inode_info, vfs_inode);
+}
#endif /* _VXFS_INODE_H_ */
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 6d576b97f2c8..ce4785fd81c6 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -61,33 +62,6 @@ const struct file_operations vxfs_dir_operations = {
.iterate_shared = vxfs_readdir,
};
-static inline u_long
-dir_blocks(struct inode *ip)
-{
- u_long bsize = ip->i_sb->s_blocksize;
- return (ip->i_size + bsize - 1) & ~(bsize - 1);
-}
-
-/*
- * NOTE! unlike strncmp, vxfs_match returns 1 for success, 0 for failure.
- *
- * 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)
-{
- if (len != de->d_namelen)
- return 0;
- if (!de->d_ino)
- return 0;
- return !memcmp(name, de->d_name, len);
-}
-
-static inline struct vxfs_direct *
-vxfs_next_entry(struct vxfs_direct *de)
-{
- return ((struct vxfs_direct *)((char*)de + de->d_reclen));
-}
/**
* vxfs_find_entry - find a mathing directory entry for a dentry
@@ -106,50 +80,64 @@ vxfs_next_entry(struct vxfs_direct *de)
static struct vxfs_direct *
vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
{
- u_long npages, page, nblocks, pblocks, block;
- u_long bsize = ip->i_sb->s_blocksize;
- const char *name = dp->d_name.name;
- int namelen = dp->d_name.len;
-
- npages = dir_pages(ip);
- nblocks = dir_blocks(ip);
- pblocks = VXFS_BLOCK_PER_PAGE(ip->i_sb);
-
- for (page = 0; page < npages; page++) {
- caddr_t kaddr;
- struct page *pp;
+ u_long bsize = ip->i_sb->s_blocksize;
+ const char *name = dp->d_name.name;
+ int namelen = dp->d_name.len;
+ loff_t limit = VXFS_DIRROUND(ip->i_size);
+ struct vxfs_direct *de_exit = NULL;
+ loff_t pos = 0;
+ struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
- pp = vxfs_get_page(ip->i_mapping, page);
+ while (pos < limit) {
+ struct page *pp;
+ char *kaddr;
+ int pg_ofs = pos & ~PAGE_MASK;
+
+ pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
if (IS_ERR(pp))
- continue;
- kaddr = (caddr_t)page_address(pp);
-
- for (block = 0; block <= nblocks && block <= pblocks; block++) {
- caddr_t baddr, limit;
- struct vxfs_dirblk *dbp;
- struct vxfs_direct *de;
-
- baddr = kaddr + (block * bsize);
- limit = baddr + bsize - VXFS_DIRLEN(1);
-
- dbp = (struct vxfs_dirblk *)baddr;
- de = (struct vxfs_direct *)(baddr + VXFS_DIRBLKOV(dbp));
-
- for (; (caddr_t)de <= limit; de = vxfs_next_entry(de)) {
- if (!de->d_reclen)
- break;
- if (!de->d_ino)
- continue;
- if (vxfs_match(namelen, name, de)) {
- *ppp = pp;
- return (de);
- }
+ return NULL;
+ kaddr = (char *)page_address(pp);
+
+ while (pg_ofs < PAGE_SIZE && pos < limit) {
+ struct vxfs_direct *de;
+
+ if ((pos & (bsize - 1)) < 4) {
+ struct vxfs_dirblk *dbp =
+ (struct vxfs_dirblk *)
+ (kaddr + (pos & ~PAGE_MASK));
+ int overhead = VXFS_DIRBLKOV(sbi, dbp);
+
+ pos += overhead;
+ pg_ofs += overhead;
+ }
+ de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+ if (!de->d_reclen) {
+ pos += bsize - 1;
+ pos &= ~(bsize - 1);
+ break;
+ }
+
+ pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
+ pos += fs16_to_cpu(sbi, de->d_reclen);
+ if (!de->d_ino)
+ continue;
+
+ if (namelen != fs16_to_cpu(sbi, de->d_namelen))
+ continue;
+ if (!memcmp(name, de->d_name, namelen)) {
+ *ppp = pp;
+ de_exit = de;
+ break;
}
}
- vxfs_put_page(pp);
+ if (!de_exit)
+ vxfs_put_page(pp);
+ else
+ break;
}
- return NULL;
+ return de_exit;
}
/**
@@ -173,7 +161,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);
}
@@ -233,74 +221,80 @@ vxfs_readdir(struct file *fp, struct dir_context *ctx)
struct inode *ip = file_inode(fp);
struct super_block *sbp = ip->i_sb;
u_long bsize = sbp->s_blocksize;
- u_long page, npages, block, pblocks, nblocks, offset;
- loff_t pos;
+ loff_t pos, limit;
+ struct vxfs_sb_info *sbi = VXFS_SBI(sbp);
if (ctx->pos == 0) {
if (!dir_emit_dot(fp, ctx))
- return 0;
- ctx->pos = 1;
+ goto out;
+ ctx->pos++;
}
if (ctx->pos == 1) {
if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
- return 0;
- ctx->pos = 2;
+ goto out;
+ ctx->pos++;
}
- pos = ctx->pos - 2;
-
- if (pos > VXFS_DIRROUND(ip->i_size))
- return 0;
- npages = dir_pages(ip);
- nblocks = dir_blocks(ip);
- pblocks = VXFS_BLOCK_PER_PAGE(sbp);
+ limit = VXFS_DIRROUND(ip->i_size);
+ if (ctx->pos > limit)
+ goto out;
- page = pos >> PAGE_SHIFT;
- offset = pos & ~PAGE_MASK;
- block = (u_long)(pos >> sbp->s_blocksize_bits) % pblocks;
+ pos = ctx->pos & ~3L;
- for (; page < npages; page++, block = 0) {
- char *kaddr;
- struct page *pp;
+ while (pos < limit) {
+ struct page *pp;
+ char *kaddr;
+ int pg_ofs = pos & ~PAGE_MASK;
+ int rc = 0;
- pp = vxfs_get_page(ip->i_mapping, page);
+ pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
if (IS_ERR(pp))
- continue;
+ return -ENOMEM;
+
kaddr = (char *)page_address(pp);
- for (; block <= nblocks && block <= pblocks; block++) {
- char *baddr, *limit;
- struct vxfs_dirblk *dbp;
- struct vxfs_direct *de;
+ while (pg_ofs < PAGE_SIZE && pos < limit) {
+ struct vxfs_direct *de;
- baddr = kaddr + (block * bsize);
- limit = baddr + bsize - VXFS_DIRLEN(1);
-
- dbp = (struct vxfs_dirblk *)baddr;
- de = (struct vxfs_direct *)
- (offset ?
- (kaddr + offset) :
- (baddr + VXFS_DIRBLKOV(dbp)));
-
- for (; (char *)de <= limit; de = vxfs_next_entry(de)) {
- if (!de->d_reclen)
- break;
- if (!de->d_ino)
- continue;
-
- 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)) {
- vxfs_put_page(pp);
- return 0;
- }
+ if ((pos & (bsize - 1)) < 4) {
+ struct vxfs_dirblk *dbp =
+ (struct vxfs_dirblk *)
+ (kaddr + (pos & ~PAGE_MASK));
+ int overhead = VXFS_DIRBLKOV(sbi, dbp);
+
+ pos += overhead;
+ pg_ofs += overhead;
+ }
+ de = (struct vxfs_direct *)(kaddr + pg_ofs);
+
+ if (!de->d_reclen) {
+ pos += bsize - 1;
+ pos &= ~(bsize - 1);
+ break;
+ }
+
+ pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
+ pos += fs16_to_cpu(sbi, de->d_reclen);
+ if (!de->d_ino)
+ continue;
+
+ rc = dir_emit(ctx, de->d_name,
+ fs16_to_cpu(sbi, de->d_namelen),
+ fs32_to_cpu(sbi, de->d_ino),
+ DT_UNKNOWN);
+ if (!rc) {
+ /* the dir entry was not read, fix pos. */
+ pos -= fs16_to_cpu(sbi, de->d_reclen);
+ break;
}
- offset = 0;
}
vxfs_put_page(pp);
- offset = 0;
+ if (!rc)
+ break;
}
- ctx->pos = ((page << PAGE_SHIFT) | offset) + 2;
+
+ ctx->pos = pos | 2;
+
+out:
return 0;
}
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 049500847903..813da6685151 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -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);
diff --git a/fs/freevxfs/vxfs_olt.h b/fs/freevxfs/vxfs_olt.h
index b7b3af502615..0c0b0c9fa557 100644
--- a/fs/freevxfs/vxfs_olt.h
+++ b/fs/freevxfs/vxfs_olt.h
@@ -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_ */
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 7ca8c75d50d3..455ce5b77e9b 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2001 Christoph Hellwig.
+ * Copyright (c) 2016 Krzysztof Blaszkowski
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -48,22 +49,11 @@
#include "vxfs_inode.h"
-MODULE_AUTHOR("Christoph Hellwig");
+MODULE_AUTHOR("Christoph Hellwig, Krzysztof Blaszkowski");
MODULE_DESCRIPTION("Veritas Filesystem (VxFS) driver");
MODULE_LICENSE("Dual BSD/GPL");
-
-
-static void vxfs_put_super(struct super_block *);
-static int vxfs_statfs(struct dentry *, struct kstatfs *);
-static int vxfs_remount(struct super_block *, int *, char *);
-
-static const struct super_operations vxfs_super_ops = {
- .evict_inode = vxfs_evict_inode,
- .put_super = vxfs_put_super,
- .statfs = vxfs_statfs,
- .remount_fs = vxfs_remount,
-};
+static struct kmem_cache *vxfs_inode_cachep;
/**
* vxfs_put_super - free superblock resources
@@ -79,9 +69,9 @@ vxfs_put_super(struct super_block *sbp)
{
struct vxfs_sb_info *infp = VXFS_SBI(sbp);
- vxfs_put_fake_inode(infp->vsi_fship);
- vxfs_put_fake_inode(infp->vsi_ilist);
- vxfs_put_fake_inode(infp->vsi_stilist);
+ iput(infp->vsi_fship);
+ iput(infp->vsi_ilist);
+ iput(infp->vsi_stilist);
brelse(infp->vsi_bp);
kfree(infp);
@@ -109,14 +99,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 +120,81 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
+static struct inode *vxfs_alloc_inode(struct super_block *sb)
+{
+ struct vxfs_inode_info *vi;
+
+ vi = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL);
+ if (!vi)
+ return NULL;
+ inode_init_once(&vi->vfs_inode);
+ return &vi->vfs_inode;
+}
+
+static void vxfs_i_callback(struct rcu_head *head)
+{
+ struct inode *inode = container_of(head, struct inode, i_rcu);
+
+ kmem_cache_free(vxfs_inode_cachep, VXFS_INO(inode));
+}
+
+static void vxfs_destroy_inode(struct inode *inode)
+{
+ call_rcu(&inode->i_rcu, vxfs_i_callback);
+}
+
+static const struct super_operations vxfs_super_ops = {
+ .alloc_inode = vxfs_alloc_inode,
+ .destroy_inode = vxfs_destroy_inode,
+ .evict_inode = vxfs_evict_inode,
+ .put_super = vxfs_put_super,
+ .statfs = vxfs_statfs,
+ .remount_fs = vxfs_remount,
+};
+
+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 +215,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 +234,43 @@ 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_op = &vxfs_super_ops;
+ 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;
}
@@ -218,7 +285,6 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
goto out;
}
- sbp->s_op = &vxfs_super_ops;
root = vxfs_iget(sbp, VXFS_ROOT_INO);
if (IS_ERR(root)) {
ret = PTR_ERR(root);
@@ -233,11 +299,11 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
return 0;
out_free_ilist:
- vxfs_put_fake_inode(infp->vsi_fship);
- vxfs_put_fake_inode(infp->vsi_ilist);
- vxfs_put_fake_inode(infp->vsi_stilist);
+ iput(infp->vsi_fship);
+ iput(infp->vsi_ilist);
+ iput(infp->vsi_stilist);
out:
- brelse(bp);
+ brelse(infp->vsi_bp);
kfree(infp);
return ret;
}