Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a7736d0 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents a54809f1 bf1bb4b4
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -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.
+102 −83
Original line number Diff line number Diff line
/*
 * 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.
 */
+42 −28
Original line number Diff line number Diff line
@@ -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:
+9 −8
Original line number Diff line number Diff line
@@ -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_ */
+3 −7
Original line number Diff line number Diff line
@@ -52,13 +52,9 @@ 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_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 *);

Loading