/* @(#)src/common/kernel/base/vx_layout.h	3.65.19.1 08/01/00 03:23:35 -  */
/* #ident "@(#)vxfs:src/common/kernel/base/vx_layout.h	3.65.19.1" */

/*
 * Copyright (c) 1998 VERITAS Software Corporation.  ALL RIGHTS RESERVED.
 * UNPUBLISHED -- RIGHTS RESERVED UNDER THE COPYRIGHT
 * LAWS OF THE UNITED STATES.  USE OF A COPYRIGHT NOTICE
 * IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
 * OR DISCLOSURE.
 *
 * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND
 * TRADE SECRETS OF VERITAS SOFTWARE.  USE, DISCLOSURE,
 * OR REPRODUCTION IS PROHIBITED WITHOUT THE PRIOR
 * EXPRESS WRITTEN PERMISSION OF VERITAS SOFTWARE.
 *
 * 		RESTRICTED RIGHTS LEGEND
 * USE, DUPLICATION, OR DISCLOSURE BY THE GOVERNMENT IS
 * SUBJECT TO RESTRICTIONS AS SET FORTH IN SUBPARAGRAPH
 * (C) (1) (ii) OF THE RIGHTS IN TECHNICAL DATA AND
 * COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013.
 * 		VERITAS SOFTWARE
 * 1600 PLYMOUTH STREET, MOUNTAIN VIEW, CA 94043
 */

#ifndef	_FS_VXFS_VX_LAYOUT_H
#define	_FS_VXFS_VX_LAYOUT_H

/*
 * This file presents all and only the structures of the vxfs file
 * system that are part of the on-disk layout.
 *
 * The vxfs disk layout has evolved over time.  Each revision of
 * the on-disk layout is deemed a new "version" and associated with
 * each on-disk layout, in the super-block fsc_version field, is
 * the file system's version number.
 *
 * A layout version consists of all the on-disk structure and all
 * of the values possible for fields within those structures on a
 * clean file system.  Any time a structure in this file is changed,
 * or any time that the legal range of values for any field within
 * a structure changes, the file system disk layout version number
 * will also change.
 */

/*
 * Version numbers.
 */

#define	VX_VERSION1		1
#define	VX_VERSION2		2
#define	VX_VERSION3		3
#define	VX_VERSION4		4

/*
 * Magic Numbers.
 */

#define	VX_MAGIC		0xa501fcf5
#define	VX_AUMAGIC		0xa502fcf5
#define	VX_SNAPMAGIC		0xa501fcf6
#define	VX_DEVMAGIC		0xa513fcf5
#define	VX_OLTMAGIC		0xa504fcf5
#define	VX_IAUMAGIC		0xa505fcf5
#define	VX_DCMAGIC		0xa514fcf5

/*
 * Super-block size and location.
 *
 * Some porting lines have introduced restrictions on the location
 * of the super-block on a disk partition (due, e.g. to boot block
 * overhead).  The default location of the super-block is, therefore,
 * port dependent.  The 2 possible locations for the super-block are
 * VX_SUPERBOFF and VX_ALTSUPERBOFF.  Each porting line defines its
 * own preferred super-block offset with VX_SBOFFPREF in vx_machdep.h.
 *
 * A running vxfs kernel will check both offsets, in the order determined
 * by the VX_SBOFFPREF at mount time.  Whenever a super-block is written
 * back to disk, the offset at which it was previously found is used.
 *
 * mkfs will write the super-block at VX_SBOFFPREF.
 */

#define	VX_SUPERBOFF	8192
#define	VX_ALTSUPERBOFF	1024
#define	VX_SBDISKSIZE	(sizeof (struct vx_fsdisk))

/*
 * The super-block structure for vxfs.
 */

struct vx_fscommon {

	/*
	 * validation and dating info
	 */

	vx_u32_t	fsc_magic;	/* 0x00 magic number */
	vx_u32_t	fsc_version;	/* 0x04 version number */
	vx_timeval32_t	fsc_ctime;	/* 0x08 create time */

	/*
	 * fundamental sizes and offsets
	 */

	vx_u32_t	fsc_unused1;	/* 0x10 unused */
	vx_u32_t	fsc_unused2;	/* 0x14 unused */
	vx_daddr32_t	fsc_old_logstart;  /* 0x18 addr of first log block */
	vx_daddr32_t	fsc_old_logend;	/* 0x1c addr of last log block */
	vx_u32_t	fsc_bsize;	/* 0x20 size of blocks in fs */
	vx_daddr32_t	fsc_size;	/* 0x24 number of blocks in fs */
	vx_daddr32_t	fsc_dsize;	/* 0x28 number of data blocks in fs */
	vx_ino32_t	fsc_old_ninode;	/* 0x2c number of inodes in fs */
	vx_u32_t	fsc_old_nau;	/* 0x30 number of au's in fs */
	vx_u32_t	fsc_unused3;	/* 0x34 unused */
	vx_daddr32_t	fsc_old_defiextsize; /* 0x38 default indirect ext size*/
	vx_u32_t	fsc_old_ilbsize;/* 0x3c ilist block size in bytes */
	vx_u32_t	fsc_immedlen;	/* 0x40 size of immediate data area */
	vx_u32_t	fsc_ndaddr;	/* 0x44 num of dir exts per inode */

	/*
	 * derived offsets
	 */

	vx_daddr32_t	fsc_aufirst;	/* 0x48 addr of first au */
	vx_daddr32_t	fsc_emap;	/* 0x4c offset of extent map in au */
	vx_daddr32_t	fsc_imap;	/* 0x50 offset of inode map in au */
	vx_daddr32_t	fsc_iextop;	/* 0x54 offset of extop map in au */
	vx_daddr32_t	fsc_istart;	/* 0x58 offset of inode list in au */
	vx_daddr32_t	fsc_bstart;	/* 0x5c offset of data block in au*/
	vx_daddr32_t	fsc_femap;	/* 0x60 fs_aufirst + fs_emap */
	vx_daddr32_t	fsc_fimap;	/* 0x64 fs_aufirst + fs_imap */
	vx_daddr32_t	fsc_fiextop;	/* 0x68 fs_aufirst + fs_iextop */
	vx_daddr32_t	fsc_fistart;	/* 0x6c fs_aufirst + fs_istart */
	vx_daddr32_t	fsc_fbstart;	/* 0x70 fs_aufirst + fs_bstart */

	/*
	 * derived lengths and sizes
	 */

	vx_u32_t	fsc_nindir;	/* 0x74 number of entries in indir */
	vx_daddr32_t	fsc_aulen;	/* 0x78 length of au in blocks */
	vx_daddr32_t	fsc_auimlen;	/* 0x7c length of au imap in blocks */
	vx_daddr32_t	fsc_auemlen;	/* 0x80 length of au emap in blocks */
	vx_daddr32_t	fsc_auilen;	/* 0x84 length of au ilist in blocks */
	vx_daddr32_t	fsc_aupad;	/* 0x88 length of au pad in blocks */
	vx_daddr32_t	fsc_aublocks;	/* 0x8c number data blocks in an au */
	vx_u32_t	fsc_maxtier;	/* 0x90 log base 2 of fs_aublocks */
	vx_u32_t	fsc_inopb;	/* 0x94 number of inodes per block */
	vx_u32_t	fsc_old_inopau;	/* 0x98 number of inodes per au */
	vx_u32_t	fsc_old_inopilb;  /* 0x9c inodes per ilist block */
	vx_u32_t	fsc_old_ndiripau; /* 0xa0 num of directory ino per au */
	vx_daddr32_t	fsc_iaddrlen;	/* 0xa4 sz of ind addr ext in blks */

	/*
	 * derived shift values
	 */

	vx_u32_t	fsc_bshift;	/* 0xa8 log base 2 of fs_bsize */
	vx_u32_t	fsc_inoshift;	/* 0xac log base 2 of fs_inopb */

	/*
	 * derived masks
	 */

	vx_s32_t	fsc_bmask;	/* 0xb0 ~(fs_bsize - 1) */
	vx_s32_t	fsc_boffmask;	/* 0xb4 fs_bsize - 1 */
	vx_s32_t	fsc_old_inomask;  /* 0xb8 fs_old_inopilb - 1 */

	/*
	 * Checksum of all invariant fields (see FS_CHECKSUM)
	 */

	vx_u32_t	fsc_checksum;	/* 0xbc checksum */
					/* 0xc0 is length */
};

#define	VX_NEFREE		32	/* # entries in free extent array */

/*
 * writable portion of super-block
 */

struct vx_fswrite {

	/*
	 * free resources
	 */

	vx_daddr32_t	fsw_free;	/* 0x00 number of free blocks */
	vx_ino32_t	fsw_ifree;	/* 0x04 number of free inodes */
	vx_daddr32_t	fsw_efree[VX_NEFREE]; /* 0x08 free extents by size */

	/*
	 * modification and state flags
	 */

	vx_u32_t	fsw_flags;	/* 0x88 flags */
	char		fsw_mod;	/* 0x8c file system has been changed */
	char		fsw_clean;	/* 0x8d file system is clean */
	vx_u16_t	fsw_unused4;	/* 0x8e unused */
	vx_u32_t	fsw_firstlogid;	/* 0x90 mount time log id */
	vx_timeval32_t	fsw_time;	/* 0x94 time last written */

	/*
	 * labels
	 */

	char		fsw_fname[6];	/* 0x9c file system name */
	char		fsw_fpack[6];	/* 0xa2 file system pack name */
	vx_u32_t	fsw_logversion;	/* 0xa8 log format version number */
	vx_u32_t	fsw_unused5;	/* 0xac padding */
					/* 0xb0 is length */
};

/*
 * Version 2 layout super-block fields.
 */

struct vx_fscommon2 {
	vx_daddr32_t	fsd_oltext[2];		/* 0x00 olt extent and replica*/
	vx_daddr32_t	fsd_oltsize;		/* 0x08 size of olt extent */
	vx_daddr32_t	fsd_iauimlen;		/* 0x0c size of inode maps */
	vx_daddr32_t	fsd_iausize;		/* 0x10 size of iau in blocks */
	vx_u32_t	fsd_dinosize;		/* 0x14 size of inode in bytes*/
	vx_u32_t	fsd_old_dniaddr;	/* 0x18 num of indir levels per
						   inode */
	vx_u32_t	fsd_checksum2;		/* 0x1c checksum of fscommon2
						   fields */
						/* 0x20 is length */
};

/*
 * Version 3 layout super-block fields.
 */

struct vx_fscommon3 {
	vx_u32_t	fse_reserved1;		/* 0x00 was fs special feature*/
	vx_u32_t	fse_unused6[2];		/* 0x04 padding */
	vx_u32_t	fse_checksum3;		/* 0x0c checksum of fscommon3
						   fields */
};						/* 0x10 is length */

/*
 * Version 3 layout writeable super-block fields.
 */

struct vx_fswrite3 {
	vx_u32_t	fsw_unused7[4];		/* 0x00 padding only */
};

/*
 * The vx_fsdisk structure encapsulates the various pieces of
 * the on-disk super-block.
 */

struct vx_fsdisk {
	struct vx_fscommon	fs_c;	/* 0x000 fixed portion */
	struct vx_fswrite	fs_w;	/* 0x0c0 writable portion */
	struct vx_fscommon2	fs_c2;	/* 0x170 version 2 portion */
	struct vx_fscommon3	fs_c3;	/* 0x190 version 3 portion */
	struct vx_fswrite3	fs_w3;	/* 0x1a0 writable portion for V3 */
					/* 0x1b0 is length */
};

/*
 * An alias for the super-block for upgrade and commands
 */

struct vx_fsdsk {
	struct	vx_fsdisk	fs_dsk;		/* 0x000 disk portiion */
};						/* 0x1b0 is length */

/*
 * Field aliases for the vxfs super-block.
 */

#define	fs_magic	fs_dsk.fs_c.fsc_magic
#define	fs_version	fs_dsk.fs_c.fsc_version
#define	fs_ctime	fs_dsk.fs_c.fsc_ctime
#define	fs_unused1	fs_dsk.fs_c.fsc_unused1
#define	fs_unused2	fs_dsk.fs_c.fsc_unused2
#define	fs_old_logstart	fs_dsk.fs_c.fsc_old_logstart
#define	fs_old_logend	fs_dsk.fs_c.fsc_old_logend
#define	fs_bsize	fs_dsk.fs_c.fsc_bsize
#define	fs_size		fs_dsk.fs_c.fsc_size
#define	fs_dsize	fs_dsk.fs_c.fsc_dsize
#define	fs_old_ninode	fs_dsk.fs_c.fsc_old_ninode
#define	fs_old_nau	fs_dsk.fs_c.fsc_old_nau
#define	fs_unused3	fs_dsk.fs_c.fsc_unused3
#define	fs_old_defiextsize	fs_dsk.fs_c.fsc_old_defiextsize
#define	fs_old_ilbsize	fs_dsk.fs_c.fsc_old_ilbsize
#define	fs_immedlen	fs_dsk.fs_c.fsc_immedlen
#define	fs_ndaddr	fs_dsk.fs_c.fsc_ndaddr
#define	fs_aufirst	fs_dsk.fs_c.fsc_aufirst
#define	fs_emap		fs_dsk.fs_c.fsc_emap
#define	fs_imap		fs_dsk.fs_c.fsc_imap
#define	fs_iextop	fs_dsk.fs_c.fsc_iextop
#define	fs_istart	fs_dsk.fs_c.fsc_istart
#define	fs_bstart	fs_dsk.fs_c.fsc_bstart
#define	fs_femap	fs_dsk.fs_c.fsc_femap
#define	fs_fimap	fs_dsk.fs_c.fsc_fimap
#define	fs_fiextop	fs_dsk.fs_c.fsc_fiextop
#define	fs_fistart	fs_dsk.fs_c.fsc_fistart
#define	fs_fbstart	fs_dsk.fs_c.fsc_fbstart
#define	fs_nindir	fs_dsk.fs_c.fsc_nindir
#define	fs_aulen	fs_dsk.fs_c.fsc_aulen
#define	fs_auimlen	fs_dsk.fs_c.fsc_auimlen
#define	fs_auemlen	fs_dsk.fs_c.fsc_auemlen
#define	fs_auilen	fs_dsk.fs_c.fsc_auilen
#define	fs_aupad	fs_dsk.fs_c.fsc_aupad
#define	fs_aublocks	fs_dsk.fs_c.fsc_aublocks
#define	fs_maxtier	fs_dsk.fs_c.fsc_maxtier
#define	fs_inopb	fs_dsk.fs_c.fsc_inopb
#define	fs_old_inopau	fs_dsk.fs_c.fsc_old_inopau
#define	fs_old_inopilb	fs_dsk.fs_c.fsc_old_inopilb
#define	fs_old_ndiripau	fs_dsk.fs_c.fsc_old_ndiripau
#define	fs_iaddrlen	fs_dsk.fs_c.fsc_iaddrlen
#define	fs_bshift	fs_dsk.fs_c.fsc_bshift
#define	fs_inoshift	fs_dsk.fs_c.fsc_inoshift
#define	fs_bmask	fs_dsk.fs_c.fsc_bmask
#define	fs_boffmask	fs_dsk.fs_c.fsc_boffmask
#define	fs_old_inomask	fs_dsk.fs_c.fsc_old_inomask
#define	fs_checksum	fs_dsk.fs_c.fsc_checksum

#define	fs_free		fs_dsk.fs_w.fsw_free
#define	fs_ifree	fs_dsk.fs_w.fsw_ifree
#define	fs_efree	fs_dsk.fs_w.fsw_efree
#define	fs_flags	fs_dsk.fs_w.fsw_flags
#define	fs_mod		fs_dsk.fs_w.fsw_mod
#define	fs_clean	fs_dsk.fs_w.fsw_clean
#define	fs_firstlogid	fs_dsk.fs_w.fsw_firstlogid
#define	fs_time		fs_dsk.fs_w.fsw_time
#define	fs_fpack	fs_dsk.fs_w.fsw_fpack
#define	fs_fname	fs_dsk.fs_w.fsw_fname
#define	fs_logversion	fs_dsk.fs_w.fsw_logversion

#define	fs_oltext	fs_dsk.fs_c2.fsd_oltext
#define	fs_oltsize	fs_dsk.fs_c2.fsd_oltsize
#define	fs_iauimlen	fs_dsk.fs_c2.fsd_iauimlen
#define	fs_iausize	fs_dsk.fs_c2.fsd_iausize
#define	fs_dinosize	fs_dsk.fs_c2.fsd_dinosize
#define	fs_old_dniaddr	fs_dsk.fs_c2.fsd_old_dniaddr
#define	fs_checksum2	fs_dsk.fs_c2.fsd_checksum2

#define	fs_reserved1	fs_dsk.fs_c3.fse_reserved1
#define	fs_unused6	fs_dsk.fs_c3.fse_unused6
#define	fs_checksum3	fs_dsk.fs_c3.fse_checksum3

/*
 * values for fs_flags
 */

#define	VX_FLAGSMASK	0x03ff		/* mask for all values */
#define	VX_FULLFSCK	0x0001		/* full fsck required */
#define	VX_LOGBAD	0x0002		/* log is invalid, don't do replay */
#define	VX_NOLOG	0x0004		/* no logging, don't do replay */
#define	VX_RESIZE	0x0008		/* resize in progress */
#define	VX_LOGRESET	0x0010		/* log reset desired */
#define	VX_UPGRADING	0x0020		/* upgrade in progress */
#define	VX_UQUOTACHECK	0x0040		/* V2 only, moved to CUT in V3 */
#define	VX_GQUOTACHECK	0x0080		/* V2 only, moved to CUT in V3 */
#define	VX_METAIOERR	0x0100		/* file system meta-data i/o error */
#define	VX_DATAIOERR	0x0200		/* file data i/o error */

/*
 * Values for fs_clean.
 *
 * When a file system is cleanly unmounted, the kernel will mark
 * it as VX_CLEAN.  A file system not cleanly unmounted will be
 * marked VX_DIRTY.  When log replay is run out of fsck, the state
 * is changed to VX_DUSTY.
 *
 * VX_DUSTY file systems are still "slightly" dirty -- to the
 * extent that there are extended operations to be completed at
 * mount time.  Because the semantics of extended operations can
 * change without a change in VX_VERSION, they are tied to a log
 * version.
 */

#define	VX_CLEAN	0x5a		/* file system is clean */
#define	VX_DIRTY	0x3c		/* file system is active */
#define	VX_DUSTY	0x69		/* file system has pending extops */

#define VX_LOGCLEAN(fs) \
	((fs)->fs_logversion == VX_LOGVERSION && (fs)->fs_clean == VX_DUSTY)

/*
 * calculate checksum of invariant super-block fields in vx_fscommon
 */

#define	VX_FSCHECKSUM(fs)	( \
	(fs)->fs_magic + \
	(fs)->fs_version + \
	(fs)->fs_ctime.tv_sec + \
	(fs)->fs_ctime.tv_usec + \
	(fs)->fs_unused1 + \
	(fs)->fs_unused2 + \
	(fs)->fs_old_logstart + \
	(fs)->fs_old_logend + \
	(fs)->fs_bsize + \
	(fs)->fs_size + \
	(fs)->fs_dsize + \
	(fs)->fs_old_ninode + \
	(fs)->fs_old_nau + \
	(fs)->fs_unused3 + \
	(fs)->fs_old_defiextsize + \
	(fs)->fs_old_ilbsize + \
	(fs)->fs_immedlen + \
	(fs)->fs_ndaddr + \
	(fs)->fs_aufirst + \
	(fs)->fs_emap + \
	(fs)->fs_imap + \
	(fs)->fs_iextop + \
	(fs)->fs_istart + \
	(fs)->fs_bstart + \
	(fs)->fs_femap + \
	(fs)->fs_fimap + \
	(fs)->fs_fiextop + \
	(fs)->fs_fistart + \
	(fs)->fs_fbstart + \
	(fs)->fs_nindir + \
	(fs)->fs_aulen + \
	(fs)->fs_auimlen + \
	(fs)->fs_auemlen + \
	(fs)->fs_auilen + \
	(fs)->fs_aupad + \
	(fs)->fs_aublocks + \
	(fs)->fs_maxtier + \
	(fs)->fs_inopb + \
	(fs)->fs_old_inopau + \
	(fs)->fs_old_inopilb + \
	(fs)->fs_old_ndiripau + \
	(fs)->fs_iaddrlen + \
	(fs)->fs_bshift + \
	(fs)->fs_inoshift + \
	(fs)->fs_bmask + \
	(fs)->fs_boffmask + \
	(fs)->fs_old_inomask)

/*
 * calculate checksum of invariant super-block fields in vx_fscommon2
 */

#define	VX_FSCHECKSUM2(fs)	( \
	(fs)->fs_oltext[0] + \
	(fs)->fs_oltext[1] + \
	(fs)->fs_oltsize + \
	(fs)->fs_iausize + \
	(fs)->fs_iauimlen + \
	(fs)->fs_dinosize + \
	(fs)->fs_old_dniaddr)

/*
 * calculate checksum of invariant super-block fields in vx_fscommon3
 */

#define	VX_FSCHECKSUM3(fs)	( \
	(fs)->fs_reserved1 + \
	(fs)->fs_unused6[0] + \
	(fs)->fs_unused6[1])

/*
 * Structure of the Object Location Table.
 *
 * Used by Version 2 and later file system layouts.
 *
 * The OLT extents are addressed in the super-block.  The OLT is
 * used at mount time to find the structural fileset, base structural
 * inodes, and other per-file system information.
 *
 * This structure is the header of every OLT extent.  The checksum
 * is computed based on all the bytes in the OLT extent beginning
 * with the timestamp in vx_olthead.  Each vx_oltent in the OLT is
 * aligned on an 8 byte boundary.  Each OLT extent is replicated so
 * none of the data will be lost if a block fails.
 */

struct vx_olthead {
	vx_u32_t	olt_magic;	/* 0x00 magic number */
	vx_u32_t	olt_size;	/* 0x04 length of this entry */
	vx_u32_t	olt_checksum;	/* 0x08 checksum of extent */
	vx_u32_t	olt_unused1;	/* 0x0c unused */
	vx_timeval32_t	olt_time;	/* 0x10 time of last olt modification */
	vx_u32_t	olt_totfree;	/* 0x18 free space in extent */
	vx_daddr32_t	olt_extents[2];	/* 0x1c addr of this extent, replica */
	vx_u32_t	olt_esize;	/* 0x24 size of this extent */
	vx_daddr32_t	olt_next[2];	/* 0x28 addr of next extent, replica */
	vx_u32_t	olt_nsize;	/* 0x30 size of next extent */
	vx_u32_t	olt_padding1;	/* 0x34 align to 8 byte boundary */
};

/*
 * Free space in the OLT
 */

struct vx_oltfree {
	vx_u32_t	olt_type;	/* 0x00 type number */
	vx_u32_t	olt_fsize;	/* 0x04 size of this free record */
};

/*
 * Initial inode extents.  The actual number of extents may vary
 * depending on the inode size.  It should always be a multiple
 * of 2 so the next record will be 8 byte aligned.
 */

struct vx_oltilist {
	vx_u32_t	olt_type;	/* 0x00 type number */
	vx_u32_t	olt_size;	/* 0x04 size of this record */
	vx_daddr32_t	olt_iext[2];	/* 0x08 first n inode extents */
};

/*
 * inodes containing fileset header and replica
 */

struct vx_oltfshead {
	vx_u32_t	olt_type;	/* 0x00 type number */
	vx_u32_t	olt_size;	/* 0x04 size of this record */
	vx_ino32_t	olt_fsino[2];	/* 0x08 inodes of fileset headers */
};

/*
 * The inode containing the current usage table.  The current usage table
 * is used to store information about a fileset that changes frequently.
 * This includes the current number of blocks used for checking against
 * the quota, and the fileset version number that changes every time
 * any file in the fileset is changed.
 */

struct vx_oltcut {
	vx_u32_t	olt_type;	/* 0x00 type number */
	vx_u32_t	olt_size;	/* 0x04 size of this record */
	vx_ino32_t	olt_cutino;	/* 0x08 inode of current usage table */
	vx_u32_t	olt_padding;	/* 0x0c unused */
};

/*
 * inodes containing super-block, log, and OLT files
 */

struct vx_oltsb {
	vx_u32_t	olt_type;	/* 0x00 type number */
	vx_u32_t	olt_size;	/* 0x04 size of this record */
	vx_ino32_t	olt_sbino;	/* 0x08 inode of super-block file */
	vx_u32_t	olt_padding;	/* 0x0c unused */
	vx_ino32_t	olt_logino[2];	/* 0x10 inode of log file */
	vx_ino32_t	olt_oltino[2];	/* 0x18 inodes of OLT and replica */
};

/*
 * inodes containing device configuration and replica
 */

struct vx_oltdev {
	vx_u32_t	olt_type;	/* 0x00 type number */
	vx_u32_t	olt_size;	/* 0x04 size of this record */
	vx_ino32_t	olt_devino[2];	/* 0x08 inodes of device config files */
};

union vx_oltent {
	struct vx_oltcommon {
		vx_u32_t		type;
		vx_u32_t		size;
	} oltcommon;
	struct vx_olthead	olthead;
	struct vx_oltfree	oltfree;
	struct vx_oltfshead	oltfshead;
	struct vx_oltcut	oltcut;
	struct vx_oltilist	oltilist;
	struct vx_oltdev	oltdev;
	struct vx_oltsb		oltsb;
};

/*
 * Valid OLT entry types for each oltent.
 */

#define	VX_OLTFREE	1
#define	VX_OLTFSHEAD	2
#define	VX_OLTCUT	3
#define	VX_OLTILIST	4
#define	VX_OLTDEV	5
#define	VX_OLTSB	6

/*
 * The on-disk fileset structure.
 *
 * In disk layout Version 2 (VX_VERSION2) and later, each file system
 * can encompass multiple filesets.  The layout of the fileset header
 * is itself versioned.
 *
 * The vx_fsethead structure for disk layout VX_VERSION2 varies,
 * unfortunately, depending on the particular porting line.  The fileset
 * version value should have coordinated some variation across porting
 * lines, but changes were missed.
 *
 * On the original UnixWare platform for the vxfs 2.0 file system,
 * the fileset version of '1' (VX_FSET_VERSION1) was used.  When the
 * 2.0 file system was done for Solaris, the same header was used.
 * When the 2.0 file system was done for HPUX, quota inodes were
 * added to the structure and the version number should have been
 * rev'ed.  It wasn't.  The offset of the fsetname and checksum vary,
 * then in the different VX_FSET_VERSION1 vx_fsethead structures.
 *
 * The Solaris porting line added quotas in release 2.3.  The needed
 * quota inode was appended to the original Solaris version of the
 * VX_FSET_VERSION1 layout and the fileset version number was bumped
 * to VX_FSET_VERSION3 (so as not to conflict with the already-in-use
 * VX_FSET_VERSION2.)
 *
 * All Version 3 file systems and later are created by mkfs with
 * the quota inodes in place (regardless of whether the specific port
 * does or does not support quotas).  VX_FSET_VERSION2 fileset headers
 * are only on HPUX 3.0 file systems.  The common fileset header layout
 * for VX_VERSION4 file systems will be VX_FSET_VERSION4.  For HPUX,
 * then, VX_FSET_VERSION2 and VX_FSET_VERSION4 are identical.
 *
 * vx_machdep.h defines a port-specific constant indicating which type
 * of fileset header should be used for VX_VERSION2 file systems.
 */

#define	VX_FSET_VERSION1	1	/* Variable VX_VERSION2 header */
#define	VX_FSET_VERSION2	2	/* Original HPUX VX_VERSION3 header */
#define	VX_FSET_VERSION3	3	/* Solaris VX_VERSION2 with quotas */
#define	VX_FSET_VERSION4	4	/* Common VX_VERSION4 */

#define	FSETNAMESZ_SHORT	32	/* old name length */
#define	FSETNAMESZ		128	/* fileset name length */

/*
 * The common portion of the all filset header layouts.
 */

struct vx_fsh_common1 {
	vx_u32_t	fc1_version;	/* 0x00 version number */
	vx_u32_t	fc1_fsindex;	/* 0x04 index of this fileset */
	vx_timeval32_t	fc1_time;	/* 0x08 time of last modification */
	vx_u32_t	fc1_fsextop;	/* 0x10 fileset extended op flags */
	vx_ino32_t	fc1_ninode;	/* 0x14 total allocated inodes */
	vx_u32_t	fc1_nau;	/* 0x18 number of iau's in fileset */
	vx_u32_t	fc1_old_ilesize; /* 0x1c old size of ilist extent */
	vx_u32_t	fc1_dflags;	/* 0x20 flags */
	vx_daddr32_t	fc1_quota;	/* 0x24 quota limit */
	vx_ino32_t	fc1_maxinode;	/* 0x28 max inode number for fileset */
	vx_ino32_t	fc1_iauino;	/* 0x2c inode allocation unit inode */
	vx_ino32_t	fc1_ilistino[2];/* 0x30 ilist extent table inodes */
	vx_ino32_t	fc1_lctino;	/* 0x38 link count table inode */
};

/*
 * The original fileset header for UnixWare and Solaris 2.0.
 * For VX_VERSION2 and VX_FSET_VERSION1.
 */

struct vx_fsh_orig {
	struct vx_fsh_common1	fso_com;
	char			fso_orig_fsetname[FSETNAMESZ_SHORT]; /* 0x3c */
	vx_u32_t		fso_checksum;	/* 0x5c */
};						/* 0x60 size of structure */

/*
 * The Solaris 2.0-with-quotas fileset header.
 * For VX_VERSION2 and VX_FSET_VERSION3.
 */

struct vx_fsh_solquota {
	struct vx_fsh_common1	fsl_com;
	char			fsl_orig_fsetname[FSETNAMESZ_SHORT]; /* 0x3c */
	vx_u32_t		fsl_checksum;	/* 0x5c */
	vx_ino32_t		fsl_uquotino;	/* 0x60 */
};						/* 0x64 size of structure */

/*
 * The HPUX 2.0 fileset header.  Identical with first part of the
 * vx_fsh_common3 structure below.
 */

struct vx_fsh_hp2 {
	struct vx_fsh_common1	fsp_com;
	vx_ino32_t		fsp_uquotino;	/* 0x3c */
	vx_ino32_t		fsp_gquotino;	/* 0x40 */
	vx_u32_t		fsp_unused[8];	/* 0x44 */
	vx_u32_t		fsp_checksum;	/* 0x64 */
};						/* 0x68 size of structure */

/*
 * The common fileset header for all Version 3 and 4 file systems.
 * For VX_VERSION4 and VX_FSET_VERSION4 or VX_VERSION3 and VX_FSET_VERSION2.
 */

struct vx_fsh_common3 {
	struct vx_fsh_common1	fc3_com;
	vx_ino32_t		fc3_uquotino;	  /* 0x3c */
	vx_ino32_t		fc3_gquotino;	  /* 0x40 */
	char			fc3_old_fsetname[FSETNAMESZ_SHORT]; /* 0x44 */
	vx_u32_t		fc3_checksum;	  /* 0x64 */

	/*
	 * Fields added for the Version 3 file system.
	 */

	vx_ino32_t	fc3_attr_ilistino[2];	/* 0x68 attribute inodes */
	vx_ino32_t	fc3_attr_iauino;	/* 0x70 IAU for attr ilist */
	vx_ino32_t	fc3_attr_lctino;	/* 0x74 LCT inode for attr */
	vx_ino32_t	fc3_attr_ninode;	/* 0x78 allocated attr inodes */
	vx_u32_t	fc3_attr_nau;		/* 0x7c number of attr IAUs */
	vx_u32_t	fc3_cuoffset;		/* 0x80 byte offset for cuent */
	vx_u32_t	fc3_features;		/* 0x84 fileset features */

	/*
	 * Fields added for the Version 4 file system.
	 */

	vx_u32_t	fc3_reserved1[10];	/* 0x88 reserved, don't use */
	vx_timeval32_t	fc3_ctime;		/* 0xb0 creation time */
	char		fc3_fsetname[FSETNAMESZ]; /* 0xb8 fileset name */
	vx_u32_t	fc3_previx;		/* 0x138 clone prev link */
	vx_u32_t	fc3_nextix;		/* 0x13c clone next link */
	vx_timeval32_t	fc3_mtime;		/* 0x140 rw mount time */
	vx_u32_t	fc3_eopdata;		/* 0x148 extended operations */
	vx_u32_t	fc3_attr_eopdata;	/* 0x14c extended operations */
	vx_u32_t	fc3_unused1[6];		/* 0x150 unused */
	vx_u32_t	fc3_reserved2[4];	/* 0x168 reserved, don't use */
	vx_u32_t	fc3_unused2[34];	/* 0x178 unused */
};						/* 0x200 size of structure */

union vx_fsethead {
	struct vx_fsh_common1	fsh_c1;
	struct vx_fsh_orig	fsh_orig;
	struct vx_fsh_solquota	fsh_sq;
	struct vx_fsh_hp2	fsh_hp2;
	struct vx_fsh_common3	fsh_c3;
};

#define	fsh_version		fsh_c1.fc1_version
#define	fsh_fsindex		fsh_c1.fc1_fsindex
#define	fsh_time		fsh_c1.fc1_time
#define	fsh_fsextop		fsh_c1.fc1_fsextop
#define	fsh_ninode		fsh_c1.fc1_ninode
#define	fsh_nau			fsh_c1.fc1_nau
#define	fsh_old_ilesize		fsh_c1.fc1_old_ilesize
#define	fsh_dflags		fsh_c1.fc1_dflags
#define	fsh_quota		fsh_c1.fc1_quota
#define	fsh_maxinode		fsh_c1.fc1_maxinode
#define	fsh_iauino		fsh_c1.fc1_iauino
#define	fsh_ilistino		fsh_c1.fc1_ilistino
#define	fsh_lctino		fsh_c1.fc1_lctino

#define	fsh_orig_fsetname	fsh_orig.fso_orig_fsetname
#define	fsh_orig_checksum	fsh_orig.fso_checksum

#define	fsh_sol_uquotino	fsh_sq.fsl_uquotino
#define fsh_hp2_uquotino	fsh_hp2.fsp_uquotino

#define	fsh_old_fsetname	fsh_c3.fc3_old_fsetname
#define	fsh_checksum		fsh_c3.fc3_checksum

#define	fsh_uquotino		fsh_c3.fc3_uquotino
#define	fsh_gquotino		fsh_c3.fc3_gquotino
#define	fsh_attr_ilistino	fsh_c3.fc3_attr_ilistino
#define	fsh_attr_iauino		fsh_c3.fc3_attr_iauino
#define	fsh_attr_lctino		fsh_c3.fc3_attr_lctino
#define	fsh_attr_ninode		fsh_c3.fc3_attr_ninode
#define	fsh_attr_nau		fsh_c3.fc3_attr_nau
#define	fsh_cuoffset		fsh_c3.fc3_cuoffset
#define	fsh_features		fsh_c3.fc3_features
#define	fsh_ctime		fsh_c3.fc3_ctime
#define	fsh_mtime		fsh_c3.fc3_mtime
#define	fsh_eopdata		fsh_c3.fc3_eopdata
#define	fsh_attr_eopdata	fsh_c3.fc3_attr_eopdata
#define	fsh_fsetname		fsh_c3.fc3_fsetname
#define	fsh_previx		fsh_c3.fc3_previx
#define	fsh_nextix		fsh_c3.fc3_nextix

/*
 * Known fileset indices.  The indices below 1000 are reserved for
 * future use by VERITAS.
 */

#define	VX_FSET_STRUCT_INDEX	1	/* index of structural fileset */
#define	VX_FSET_UNNAMED_INDEX	999	/* index of unnamed fileset */

/*
 * Flags for fileset header fsh_dflags.
 */

#define VX_FSET_MASK		0x007f	/* fileset flags mask */
#define	VX_FSET_UNNAMED		0x0001	/* unnamed fileset */
#define	VX_FSET_STRUCTURAL	0x0002	/* structural fileset */
#define	VX_FSET_UNMOUNTABLE	0x0008	/* fileset can't be mounted */
#define	VX_FSET_ROOT		0x0010	/* default root fileset */
#define	VX_FSET_NODATA		0x0020	/* nodata clone */
#define VX_FSET_REMOVABLE	0x0040	/* clone may self-destruct */

/*
 * fileset extended operations.
 */

#define	VX_FSE_MASK		0x3	/* fileset extended operations mask */
#define	VX_FSE_REMOVE		0x1	/* remove the fileset */
#define	VX_FSE_CONVNODATA	0x2	/* convert to no-data */

/*
 * fileset feature bits for fsh_features
 */

#define	VX_FSETFBIT_MASK	0x0007	/* mask for fset feature bits */
#define	VX_FSETFBIT_LARGEFILES	0x0001	/* large files allowed */
#define	VX_FSETFBIT_RESERVED1	0x0002	/* reserved for future use */
#define	VX_FSETFBIT_RESERVED2	0x0004	/* reserved for future use */

/*
 * The Current Usage Table.
 *
 * The current usage table consists of an entry for each fileset.
 * The fileset version number is a 64 bit integer.  It is updated
 * each time a change is made to the fileset (creating, removing,
 * or changing the attributes of a file), or when the modification
 * time is changed on an inode in the fileset.  The cu_curused value
 * is a count of the total number of blocks allocated to files in the
 * fileset.  It is used to check against the fileset quota when
 * allocating blocks.
 */

union vx_cuent {

	/*
	 * Structure prior to version 3.
	 */

	struct vx_old_cuent {
		vx_u32_t	ocu_fsindex;	/* 0x00 fileset index */
		vx_daddr32_t	ocu_curused;	/* 0x04 blocks in use */
		vx_hyper_t	ocu_vversion;	/* 0x08 version number */
						/* 0x10 length in version 2 */
	} cu_ocuent;

	/*
	 * Structure in version 3
	 */

	struct vx_new_cuent {
		vx_u32_t	ncu_fsindex;	/* 0x00 fileset index */
		vx_daddr32_t	ncu_curused;	/* 0x04 blocks in use */
		vx_hyper_t	ncu_vversion;	/* 0x08 version number */
		vx_daddr32_t	ncu_dcurused;	/* 0x10 not maintained in V3 */
		vx_daddr32_t	ncu_visused;	/* 0x14 visible blocks in use */
		vx_timeval32_t	ncu_update;	/* 0x18 last update time */
		vx_u32_t	ncu_flags;	/* 0x20 flags */
		vx_u32_t	ncu_padding[7];	/* 0x24 pad to power of 2 */
						/* 0x40 length in version 3 */
	} cu_ncuent;
};

#define	cu_fsindex	cu_ocuent.ocu_fsindex
#define	cu_curused	cu_ocuent.ocu_curused
#define	cu_lversion	cu_ocuent.ocu_vversion.vh_low
#define	cu_hversion	cu_ocuent.ocu_vversion.vh_high
#define	cu_vversion	cu_ocuent.ocu_vversion
#define	cu_dcurused	cu_ncuent.ncu_dcurused
#define	cu_visused	cu_ncuent.ncu_visused
#define	cu_update	cu_ncuent.ncu_update
#define	cu_flags	cu_ncuent.ncu_flags

/*
 * Values for cu_flags
 */

#define	VX_FSET_UQUOTACHECK	0x1	/* per-user quota check required */
#define	VX_FSET_GQUOTACHECK	0x2	/* per-group quota check required */
#define	VX_FSET_DIRTY		0x4	/* fileset might have extops */

/*
 * The disk structure of the vxfs inode.
 */

#define	VX_NDADDR	10	/* direct addresses in inode */
#define	VX_NIADDR	2	/* indirect addresses in inode */
#define	VX_NIMMED	96	/* immediate data in inode */
#define	VX_NTYP4	6	/* num of 4 word typed exts in inode */
#define	VX_NTYP8	3	/* num of 8 word typed exts in inode */

/*
 * Structure of the inode ic_org area for IORG_EXT4 inodes.
 *
 * The inode can have one of several "organization types" which is specified
 * in the orgtype field.  The layout of the ic_org area of an inode varies
 * according to its orgtype.  The layout of the ic_org area of an IORG_EXT4
 * inode depends, unfortunately, on the particular porting line.
 *
 * The HPUX port was derived from other work done on OSF1 platforms where file
 * sizes larger than 2 gigabytes were supported.  To accommodate the large
 * addressing, the triple indirect was introduced.  The HPUX OS onto which
 * that 2.0 vxfs was ported had no support for >2G files, so the disk format
 * for the inode on HPUX should not have included the space for the triple
 * indirect.  HPUX remains the only active porting line derived from the OSF1
 * line of development - and therefore the only active porting line with space
 * for what was a triple indirect.
 *
 * The handling of IORG_EXT4 inodes is one of the few places where #ifdef
 * preprocessor controls are used to distinguish port-specific differences
 * in the vxfs disk layout.
 *
 * In Version 3 and later vxfs file systems, support for addressing large
 * numbers of extents in an inode (to support >2G file sizes) is through
 * the IORG_TYPED inode organization.  No IORG_EXT4 inode on any active
 * porting line of vxfs should ever be used for addressing >2G of data.
 */

#ifdef _HPUX_SOURCE

struct vx_ext4 {
	vx_u32_t	ic_ies;		/* 0x50: ind ext sz */
	vx_daddr32_t	ic_ie[VX_NIADDR]; /* 0x54: indir exts */
	vx_u32_t	ic_spare;	/* 0x5c: unused (OSF1 triple indirect)*/
	struct vx_dext {		/* 0x60: direct exts */
		vx_daddr32_t	ic_de;	/* direct ext */
		vx_daddr32_t	ic_des;	/* direct ext size */
	} ic_dext[VX_NDADDR];
};

#else	/* _HPUX_SOURCE */

struct vx_ext4 {
	vx_u32_t	ic_spare;	/* 0x50: unused */
	vx_u32_t	ic_ies;		/* 0x54: ind ext sz */
	vx_daddr32_t	ic_ie[VX_NIADDR]; /* 0x58: indir exts */
	struct vx_dext {		/* 0x60: direct exts */
		vx_daddr32_t	ic_de;	/* direct ext */
		vx_daddr32_t	ic_des;	/* direct ext size */
	} ic_dext[VX_NDADDR];
};

#endif	/* _HPUX_SOURCE */

/*
 * Special extent descriptor values for block number.  Note that VX_HOLE
 * never appears on disk, it is only incore.
 */

#define	VX_HOLE		((vx_daddr32_t)-1) /* -1 incore value used for holes */
#define	VX_OVERLAY	((vx_daddr32_t)-2) /* -2 used with overlay descriptor */
#define	VX_BLOCK0	((vx_daddr32_t)-3) /* -3 for block 0 on disk */

/*
 * Structure of extent descriptors for typed inode extent organizations.
 *
 * VX_TYPE_HOLE and VX_TYPE_NULL entry types are not valid on disk.
 * They are used incore only but are presented here for completeness.
 */

#define	VX_TYPE_IADDR_4		1	/* indirect address extent */
#define	VX_TYPE_DATA_4		2	/* data extent */
#define	VX_TYPE_IADDR_DEV4	3	/* indirect addr extent with altdev */
#define	VX_TYPE_DATA_DEV4	4	/* data extent with altdev */

#define	VX_TYPE_HOLE		98	/* hole - not valid on disk */
#define	VX_TYPE_NULL		99	/* null entry - not valid on disk */

struct vx_typed_generic {
	vx_hyper_t	te_hdr;		/* 0x00 header with type and offset */
};

struct vx_typed_4 {
	vx_hyper_t	te_hdr;		/* 0x00 header with type and offset */
	vx_daddr32_t	te_start;	/* 0x08 starting block of extent */
	vx_daddr32_t	te_size;	/* 0x0c size of extent */
					/* 0x10 is size */
};

struct vx_typed_dev4 {
	vx_hyper_t	te_hdr;		/* 0x00 header with type and offset */
	vx_daddr64_t	te_start;	/* 0x08 starting block of extent */
	vx_daddr64_t	te_size;	/* 0x10 size of extent */
	vx_u32_t	te_devid;	/* 0x18 device id */
	vx_u32_t	te_padding;	/* 0x1c pad to power of 2 size */
					/* 0x20 is size */
};

struct vx_icommon {
	vx_u32_t	ic_mode;		/* 0x00: mode and type */
	vx_u32_t	ic_nlink;		/* 0x04: number of links */
	vx_u32_t	ic_uid;			/* 0x08: owner's user id */
	vx_u32_t	ic_gid;			/* 0x0c: owner's group id */
	vx_hyper_t	ic_size;		/* 0x10: bytes in file */
	vx_timeval32_t	ic_atime;		/* 0x18: time last accessed */
	vx_timeval32_t	ic_mtime;		/* 0x20: time last modifies */
	vx_timeval32_t	ic_ctime;		/* 0x28: time inode changed */
	vx_u8_t	ic_aflags;			/* 0x30: allocation flags */
	vx_u8_t	ic_orgtype;			/* 0x31: org type */
	vx_u16_t ic_eopflags;			/* 0x32: extended operations */
	vx_u32_t ic_eopdata;			/* 0x34: extended operations */
	union vx_ftarea {			/* 0x38: type specific data */
		struct vx_ftarea_dev {		/* device files */
			vx_u32_t	ic_rdev; /* 0x38: device number */
		} ic_ftarea_dev;
		struct vx_ftarea_dir {		/* directories */
			vx_ino32_t	ic_dotdot; /* 0x38: parent directory */
		} ic_ftarea_dir;
		struct vx_ftarea_reg {		/* regular files */
			vx_daddr32_t	ic_reserve; /* 0x38: prealloc space */
			vx_daddr32_t	ic_fixextsize; /* 0x3c: fixed ext sz */
		} ic_ftarea_reg;
		struct vx_ftarea_vxspec {	/* vxfs private files */
			vx_ino32_t	ic_matchino; /* 0x38: matching inode */
			vx_u32_t	ic_fsetindex; /* 0x3c: fileset index */
		} ic_ftarea_vxspec;
	} ic_ftarea;
	vx_daddr32_t	ic_blocks;		/* 0x40: blocks held */
	vx_u32_t	ic_gen;			/* 0x44: generation number */
	vx_hyper_t ic_vversion;			/* 0x48: inode serial number */
	union vx_org {				/* 0x50: */
		struct vx_immed {		/* immediate dirs/symlinks */
			char ic_immed[VX_NIMMED];
		} ic_vx_immed;
		struct vx_ext4	     ic_vx_e4;	       /* IORG_EXT4 extents */
		struct vx_typed_4    ic_td4[VX_NTYP4]; /* typed extents */
		struct vx_typed_dev4 ic_td8[VX_NTYP8]; /* typed extents */
	} ic_org;
	vx_ino32_t	ic_iattrino;		/* 0xb0: indirect attr inode */
	vx_u32_t	ic_pad;			/* 0xb4: do not reuse */
};

struct vx_dinode {
	struct vx_icommon	di_ic;
};

/*
 * Structure for the inode extended attribute area.
 *
 * Extended attributes are only supported on Version 2 and later
 * file sytems.
 *
 * The inode attribute area is that disk space running from the end
 * of the ic_org union to the end of the inode.  The size of that
 * space is dependent on the size of the inode as specified by mkfs
 * and recorded in the vx_fscommon2 portion of the super-block.
 */

#define	VX_ATTR_IMMED		1	/* stored immediately in inode */
#define	VX_ATTR_DIRECT		2	/* attribute inum stored in inode */
#define	VX_ATTR_EXTIMDATA	3	/* reserved value currently unused */

#define	VX_ATTR_INDIRECT	100	/* direct attribute stored in an
					   indirect attribute inode */

struct vx_iattr {
	vx_u32_t	a_format;	/* format of attribute entry */
	vx_u32_t	a_length;	/* length of attribute entry */
	char		a_data[4];	/* attribute data (expandable) */
};

#define	VX_ATTROVERHEAD		(vx_offsetof(a_data, struct vx_iattr))

/*
 * Structure for immediate attributes.
 */

struct vx_attr_immed {
	vx_u32_t	aim_class;	/* class of attribute */
	vx_u32_t	aim_subclass;	/* subclass of attribute */
	char		aim_data[4];	/* immed attribute data (expandable) */
};

#define	VX_ATTR_IMMEDOVER	(vx_offsetof(aim_data, struct vx_attr_immed))

/*
 * The attributes could start at two different offsets within the on disk
 * inode. This due to the fact that the starting offset is computed by the
 * following calculation: attr = dp + sizeof (struct vx_dinode). struct
 * vx_dinode includes vx_hyper_t field. On certain platforms such as Sol2.6
 * and HP, vx_hyper_t is defined as unsigned long long which leads the
 * vx_icommon structure to be aligned at 8 byte boundary. On Sol2.5 and other
 * older versions, vx_hyper_t is defined as an array of 2 longs which leaves
 * the structure aligned at 4 byte boundary. Thus, we need to accomodate
 * the starting attribute offset at two positions within the on-disk inode.
 */
#define VX_ATTR_OFF1		180
#define VX_ATTR_OFF2		184

/*
 * Structure for directly indexed attributes.
 */

struct vx_attr_direct {
	vx_u32_t	ad_class;	/* class of attribute */
	vx_u32_t	ad_subclass;	/* subclass of attribute */
	vx_u32_t	ad_length;	/* length of attribute */
	vx_ino32_t	ad_ino;		/* inode containing attribute data */
};

/*
 * Known attributes by class and subclass.
 * Classes less than 1000 are reserved for future use by Veritas.
 */

#define	VX_FREECLASS	(vx_u32_t)-2	/* class value for free slot */

#define	VX_ACL_CLASS		1
#define	VX_ACL_SVR4_SUBCLASS	1

struct vx_aclhd {
	vx_u32_t	aclcnt;		/* total number of acl entries */
	vx_u32_t	daclcnt;	/* number of default acl entries */
};

/*
 * Aliases for inode fields.
 */

#define	di_mode		di_ic.ic_mode
#define	di_nlink	di_ic.ic_nlink
#define	di_uid		di_ic.ic_uid
#define	di_gid		di_ic.ic_gid

#define	di_size		di_ic.ic_size.vh_value

#define	di_size2	di_ic.ic_size.vh_high
#define	di_atime	di_ic.ic_atime
#define	di_mtime	di_ic.ic_mtime
#define	di_ctime	di_ic.ic_ctime
#define	di_aflags	di_ic.ic_aflags
#define	di_orgtype	di_ic.ic_orgtype
#define	di_eopflags	di_ic.ic_eopflags
#define	di_eopdata	di_ic.ic_eopdata
#define	di_rdev		di_ic.ic_ftarea.ic_ftarea_dev.ic_rdev
#define	di_dotdot	di_ic.ic_ftarea.ic_ftarea_dir.ic_dotdot
#define	di_dflags	di_ic.ic_ftarea.ic_ftarea_dir.ic_dflags
#define	di_fixextsize	di_ic.ic_ftarea.ic_ftarea_reg.ic_fixextsize
#define	di_reserve	di_ic.ic_ftarea.ic_ftarea_reg.ic_reserve
#define	di_matchino	di_ic.ic_ftarea.ic_ftarea_vxspec.ic_matchino
#define	di_fsetindex	di_ic.ic_ftarea.ic_ftarea_vxspec.ic_fsetindex
#define	di_blocks	di_ic.ic_blocks
#define	di_gen		di_ic.ic_gen
#define	di_lversion	di_ic.ic_vversion.vh_low
#define	di_hversion	di_ic.ic_vversion.vh_high
#define	di_vversion	di_ic.ic_vversion
#define	di_immed	di_ic.ic_org.ic_vx_immed.ic_immed
#define	di_ies		di_ic.ic_org.ic_vx_e4.ic_ies
#define	di_ie		di_ic.ic_org.ic_vx_e4.ic_ie
#define	di_dext		di_ic.ic_org.ic_vx_e4.ic_dext
#define	di_td4		di_ic.ic_org.ic_td4
#define	di_td8		di_ic.ic_org.ic_td8
#define	di_iattrino	di_ic.ic_iattrino

/*
 * File modes.  File types above 0xf000 are vxfs internal only, they should
 * not be passed back to higher levels of the system.  vxfs file types must
 * never have one of the regular file type bits set.
 */

#define	VX_SIFMT	0x0000f000	/* system file types */
#define	VX_VXIFMT	0xff000000	/* vxfs internal file types */
#define	IFMT		0xff00f000	/* type of file */

#define	IFIFO		0x00001000	/* 0010000 named pipe (fifo) */
#define	IFCHR		0x00002000	/* 0020000 character special */
#define	IFDIR		0x00004000	/* 0040000 directory */
#define	IFNAM		0x00005000	/* 0050000 xenix special file */
#define	IFBLK		0x00006000	/* 0060000 block special */
#define	IFREG		0x00008000	/* 0100000 regular */
#define	IFCMP		0x00009000	/* 0110000 compressed */
#define	IFLNK		0x0000a000	/* 0120000 symbolic link */
#define	IFSOC		0x0000c000	/* 0140000 socket (hp-only) */

#define	IFFSH		0x10000000	/* fileset header */
#define	IFILT		0x20000000	/* inode list */
#define	IFIAU		0x30000000	/* inode allocation unit */
#define	IFCUT		0x40000000	/* current usage table */
#define	IFATT		0x50000000	/* attribute inode */
#define	IFLCT		0x60000000	/* link count table */
#define	IFIAT		0x70000000	/* indirect attribute file */
#define	IFEMR		0x80000000	/* extent map reorg file */
#define	IFQUO		0x90000000	/* bsd quota file */
#define	IFPTI		0xa0000000	/* "pass-through" inode */

#define	IFLAB		0x11000000	/* device label file */
#define	IFOLT		0x12000000	/* object location table file */
#define	IFLOG		0x13000000	/* log file */
#define	IFEMP		0x14000000	/* extent map file */
#define	IFEAU		0x15000000	/* extent allocation unit file */
#define	IFAUS		0x16000000	/* extent au summary file */
#define	IFDEV		0x17000000	/* device configuration file */

#define	ISUID		0x0800		/* 04000 set user id on execution */
#define	ISGID		0x0400		/* 02000 set group id on execution */
#define	ISVTX		0x0200		/* 01000 sticky bit */
#define	IREAD		0x0100		/* 0400 read permission */
#define	IWRITE		0x0080		/* 0200 write permission */
#define	IEXEC		0x0040		/* 0100 execute/search permission */

#define	VX_GEMODE	(ISGID | (IEXEC >> 3))	/* setgid + group exec mode */
#define	VX_EXECMODES	(IEXEC | (IEXEC >> 3) | (IEXEC >> 6))

#define VX_ISSTRUCT(fmt)						\
	(((fmt) == IFFSH || (fmt) == IFILT || (fmt) == IFIAU ||		\
	 (fmt) == IFCUT || (fmt) == IFLCT || (fmt) == IFLAB ||		\
	 (fmt) == IFOLT || (fmt) == IFLOG || (fmt) == IFEMP ||		\
	 (fmt) == IFEAU || (fmt) == IFAUS || (fmt) == IFDEV ||		\
	 (fmt) == IFQUO) ? 1 : 0)

#define VX_ISMAPREP(fmt)						\
	(((fmt) == IFILT || (fmt) == IFEMP || (fmt) == IFLOG) ? 1 : 0)

/*
 * org types
 */

#define	IORG_NONE	0		/* inode has no format */
#define	IORG_EXT4	1		/* inode has 4 byte data block addrs */
#define	IORG_IMMED	2		/* data stored in inode */
#define	IORG_TYPED	3		/* inode has typed extent descriptors */

/*
 * allocation flags
 */

#define	VX_AF_MASK	0x002f		/* allocation flags mask */
#define	VX_AF_IBAD	0x0001		/* inode is bad */
#define	VX_AF_NOEXTEND	0x0002		/* file can't be auto extended */
#define	VX_AF_ALIGN	0x0004		/* all extents must be aligned */
#define	VX_AF_NOGROW	0x0008		/* file can't grow */
#define	VX_AF_OVERLAY	0x0020		/* file has overlay descriptors */

/*
 * extop flags
 */

#define	VX_IEMASK	0x03ff		/* extended op masks */
#define	VX_IEREMOVE	0x0001		/* deferred inode removal */
#define	VX_IETRUNC	0x0002		/* extended truncation */
#define	VX_IERTRUNC	0x0004		/* trim blocks down to i_reserve */
#define	VX_IESHORTEN	0x0008		/* shorten file to i_size */
#define	VX_IEZEROEXT	0x0010		/* zeroing an extent */
#define	VX_IETRIM	0x0020		/* trim reservation to i_size */
#define	VX_IEZLC	0x0040		/* zero link count file */
#define	VX_IEHOLETRUNC	0x0080		/* "punch hole" truncation */
#define	VX_IEREORG	0x0100		/* inode undergoing reorg */
#define	VX_IEPTTRUNC	0x0200		/* extended "pass-thru" truncation */

/*
 * The disk structure of the Link Count Table.
 *
 * The Link Count Table tracks the number of references in the
 * file system to attribute inodes.  The LCT uses bitfields
 * in its structure so it is byte order dependent.
 */

#if _VXFS_BYTE_ORDER == _VXFS_LITTLE_ENDIAN
struct vx_lctval {
	unsigned int	lcf_lowbits : 31;
	unsigned int	lcf_highbit : 1;
};
#endif

#if _VXFS_BYTE_ORDER == _VXFS_BIG_ENDIAN
struct vx_lctval {
	unsigned int	lcf_highbit : 1;
	unsigned int	lcf_lowbits : 31;
};
#endif

union vx_lctdisk {
	vx_u32_t		lcd_entry;	/* link count table entry */
	struct vx_lctval	lcd_fields;	/* fields in entry */
};

#define	lcd_free	lcd_fields.lcf_highbit
#define	lcd_count	lcd_fields.lcf_lowbits

/*
 * The disk structure of the Inode Allocation Unit.
 *
 * This structure is stored in the header block of an Inode Allocation
 * Unit.  The IAU contains a header block, followed by the iau summary
 * block, then the free inode bitmap and inode extended operation bitmap.
 */

struct vx_iauhead {
	vx_u32_t	iau_magic;	/* 0x00 magic number */
	vx_u32_t	iau_fsindex;	/* 0x04 index of fileset */
	vx_u32_t	iau_iaun;	/* 0x08 sequence number in fileset */
};

/*
 * The disk structure of the Allocation Unit header.
 */

struct vx_auheader {
	vx_u32_t		au_magic;	/* 0x00 magic number */
	vx_u32_t		au_aun;		/* 0x04 AU number */
	struct vx_fscommon	au_auxsb;	/* 0x08 copy of sblk common */
	struct vx_fscommon2	au_auxsb2;	/* 0xc8 copy of sblk common2 */
};

/*
 * allocation unit summaries
 */

#define	VX_SNEFREE	16	/* num of entries in short free extent array */

struct vx_dirtysum {		/* summary dirty */
	vx_u32_t	ausd_dirty;	/* summary dirty flag */
};

struct vx_imapsum {		/* imap summary */
	vx_ino32_t	ausd_difree;	/* free directory inodes */
	vx_ino32_t	ausd_dibfree;	/* free directory inode blocks */
	vx_ino32_t	ausd_rifree;	/* free regular file inodes */
	vx_ino32_t	ausd_ribfree;	/* free regular file inode blocks */
};

struct vx_old_emapsum {			/* old emap summary */
	vx_daddr32_t	ausd_efree[VX_NEFREE];	/* free extents by size */
};

struct vx_emapsum {			/* emap summary */
	vx_u16_t	eau_efree[VX_SNEFREE];	/* free extents by size */
};

/*
 * disk format of ausum info
 */

struct vx_old_ausumd {
	struct vx_dirtysum	ausd_dsum;
	struct vx_imapsum	ausd_isum;
	struct vx_old_emapsum	ausd_esum;
};

/*
 * Disk format of device configuration record.
 *
 * The device file contains one record of this type for each
 * device encompassed by the file system.
 */

struct vx_devconf {
	vx_u32_t	dc_magic;	/* 0x00 magic number */
	vx_u32_t	dc_checksum;	/* 0x04 checksum of rest of record */
	vx_u32_t	dc_devid;	/* 0x08 internal device id */
	vx_daddr32_t	dc_len;		/* 0x0c device len in fs_bsize blocks */
	vx_ino32_t	dc_stateino;	/* 0x10 AU state summary file inumber */
	vx_ino32_t	dc_sumino;	/* 0x14 eau summary file inumber */
	vx_ino32_t	dc_mapino[2];	/* 0x18 inum of eau bitmap file(s) */
	vx_ino32_t	dc_labelino;	/* 0x20 device label file inumber */
	vx_u32_t	dc_flags;	/* 0x24 flags */
	vx_u32_t	dc_labeltype;	/* 0x28 type of device label */
	vx_u32_t	dc_devicetype;	/* 0x2c type of device data */
					/* 0x30 is length */
};

/*
 * Device label types
 */

#define	VX_DEV_SUPERLABEL	1	/* label is a SB with VX_DEVMAGIC */
#define	VX_DEV_NOLABEL		2	/* device has no label */

/*
 * Device types
 */

#define	VX_DEV_ALLDATA		1	/* device holds complete fs */

/*
 * State values for eau state file.
 */

#define	VX_EAU_EXPANDED		0	/* AU expanded, summary clean */
#define	VX_EAU_DIRTY		1	/* AU expanded, summary dirty */
#define	VX_EAU_ALLOCATED	2	/* AU not expanded, totally allocated */
#define	VX_EAU_FREE		3	/* AU not expanded, totally free */

#define	VX_EAU_NEMASK		0x2	/* Not expanded bit mask */

#define	VX_AUEXPANDED(dv, aun)	(dv->dv_fs->fs_version < VX_VERSION3 || \
				 !(vx_austate_get(dv, aun) & VX_EAU_NEMASK))

/*
 * The vxfs directory structure.
 *
 * Directories are organized by block.  Each file-system-block sized
 * chunk of the directory is a separate vx_dirblk entity, though they
 * can be coalesced into larger extents (of up to VX_MAXBSIZE).
 *
 * Each directory block has a header which includes information for
 * free space management and fastpathing for lookup.  Free space in a
 * directory block is tracked in the d_tfree field.
 *
 * File names contained in the entries in a directory block are hashed
 * into a number of buckets and linked into hash chains.  The anchor of
 * the hash chains is in the directory block header array of d_nhash.
 * Each hash chain anchor contains the offset in the block of the first
 * directory entry whose name hashes to the corresponding value.  The
 * number of hash buckets varies by the block size used for a vx_dirblk.
 * Derivation of d_nhash is blocksize >> VX_NHASHSHIFT.
 *
 * If the entire directory can fit in the immediate data area of an inode
 * the hash chains are not used and d_nhash is 0.
 */

#define	VX_NHASHSHIFT	5

struct vx_dirblk {
	vx_u16_t	d_tfree;	/* total free space in block */
	vx_u16_t	d_nhash;	/* number of hash chains */
	vx_u16_t	d_hash[1];	/* hash chain head */
};

struct vx_immed_dirblk {
	vx_u16_t	d_tfree;	/* total free space in block */
	vx_u16_t	d_nhash;	/* number of hash chains */
};

/*
 * Each directory block contains some number of directory entry
 * structures, which are of variable length.
 *
 * Every directory entry has a 'struct vx_direct' header.  The header
 * provides the entry's inode number, the length of the entry, the
 * length of the name contained in the entry, and the hashing linkage
 * used in conjunction with the directory block's hash chains.  These
 * are followed by the name padded to a 4 byte boundary with null
 * bytes.  Names are NOT guaranteed null terminated.  The maximum
 * length of a name in a directory is VX_MAXNAMLEN.
 *
 * The amount of space consumed by an entry is based on the length of
 * the entry's name and calculated with the VX_DIRSIZ macro.  Free space
 * in directories is represented by entries which have a dp->d_reclen
 * greater than the actual size consumed.
 *
 * All data bytes in a directory block are claimed by the directory
 * entries.  This usually results in the last entry in a directory
 * having a large reclen value.  When entries are deleted from a
 * directory, the space is returned to the previous entry in the same
 * directory block by increasing that entry's reclen.
 *
 * Directory entries provide indexing to a specific inode.  If the
 * first entry of a directory block is free, then its inode field is
 * set to 0.  Entries other than the first in a directory block do not
 * normally have the inode set to 0.
 */

#define	VX_MINNAMLEN	2
#define	VX_MAXNAMLEN	256

struct vx_direct {
	vx_ino32_t	d_ino;			/* inode number of entry */
	vx_u16_t	d_reclen;		/* length of this record */
	vx_u16_t	d_namlen;		/* length of d_name string */
	vx_u16_t	d_hashnext;		/* next hash entry's offset */
	char		d_name[VX_MAXNAMLEN];	/* name */
};

struct vx_mindirect {
	vx_ino32_t	d_ino;			/* inode number of entry */
	vx_u16_t	d_reclen;		/* length of this record */
	vx_u16_t	d_namlen;		/* length of d_name string */
	vx_u16_t	d_hashnext;		/* next hash entry's offset */
	char		d_name[VX_MINNAMLEN];	/* name */
};

#define	VX_DIRPAD (vx_offsetof(d_name, struct vx_direct))

/*
 * The VX_DIRSIZ macro gives the minimum record length which will hold
 * the directory entry.  This requires the amount of space in struct
 * vx_direct without the d_name field, plus enough space for the name
 * rounded up to a 4 byte boundary.
 */

#define	VX_DIRSIZ(len)	(((VX_DIRPAD + 3) + (len)) & (~3))

/*
 * The block overhead of variable length directory block
 * (number of hash chains + 2) shorts.
 */

#define	VX_DIRBLKOVER(db) (((db)->d_nhash + 2) * sizeof (vx_u16_t))

/*
 * Macro to check that directory entry is aligned and fits inside
 * the given block.
 */

#define	VX_DIROK(dbp, boff, blen, dp) \
	(((boff) & 3) == 0 && (boff) >= VX_DIRBLKOVER((dbp)) && \
	 (boff) < ((blen) - VX_DIRPAD) && \
	 (dp)->d_namlen <= (vx_u16_t)VX_NAMEMAX && \
	 (dp)->d_namlen < (dp)->d_reclen && \
	 ((boff) + (vx_u32_t)(dp)->d_reclen) <= (blen))

/*
 * maximum number of directory entries that can be in a block
 */

#define	VX_MAXDIRENT(blen)	((blen) >> 3)

/*
 * The structure of the on-disk BSD quota record.
 * BSD quotas are only implemented in some porting lines.
 */

struct	vx_qrec {
	vx_daddr32_t	qr_bhardlimit;		/* hard limit on blocks */
	vx_daddr32_t	qr_bsoftlimit;		/* soft limit on blocks */
	vx_daddr32_t	qr_curblocks;		/* current blocks used */
	vx_ino32_t	qr_ihardlimit;		/* hard limit on files */
	vx_ino32_t	qr_isoftlimit;		/* soft limit on files */
	vx_ino32_t	qr_curinodes;		/* current files used */
	vx_u32_t	qr_btime;		/* time remaining over slimit */
	vx_u32_t	qr_itime;		/* time remaining over slimit */
};

#endif	/* _FS_VXFS_VX_LAYOUT_H */
