/* @(#)src/sol/kernel/base/vx_machdep.h	3.169.19.12 02/04/00 16:13:10 -  */
/* #ident "@(#)vxfs:src/sol/kernel/base/vx_machdep.h	3.169.19.12" */

/*
 * 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_MACHDEP_H
#define	_FS_VXFS_VX_MACHDEP_H

/*
 * misc definitions for Solaris port
 */

/*
 * protos!
 */

#ifdef __STDC__
#define __P(x) x
#else
#define __P(x) ()
#endif

/*
 * Stack size for VxFS worker threads.
 */
extern int vx_thr_stk_sz;

/*
 * setup endian type
 */

#define _VXFS_BIG_ENDIAN	12345678
#define _VXFS_LITTLE_ENDIAN	43218765
#if #machine(i386)
#define _VXFS_BYTE_ORDER	_VXFS_LITTLE_ENDIAN
#else
#define _VXFS_BYTE_ORDER	_VXFS_BIG_ENDIAN
#endif

/*
 * Define basic data types.
 */

typedef char			vx_s8_t;	/* 8 bit signed int */
typedef unsigned char		vx_u8_t;	/* 8 bit unsigned int */
typedef short			vx_s16_t;	/* 16 bit signed int */
typedef unsigned short		vx_u16_t;	/* 16 bit unsigned int */
typedef int			vx_s32_t;	/* 32 bit signed int */
typedef unsigned int		vx_u32_t;	/* 32 bit unsigned int */

/*
 * Define other derived data types.
 */

typedef vx_u32_t	vx_daddr_t;		/* block or sector num */
typedef vx_u32_t	vx_daddr32_t;		/* 32 bit block or sector num */
typedef vx_u64_t	vx_daddr64_t;		/* 64 bit block address */
typedef vx_u32_t	vx_devid_t;		/* internal device id */
typedef vx_u32_t	vx_dev32_t;		/* 32bit device number */
typedef vx_u32_t	vx_tranid_t;		/* transaction log id */
typedef vx_u32_t	vx_ino_t;		/* inode number */
typedef vx_u32_t	vx_ino32_t;		/* 32 bit inode number */
typedef vx_u64_t	vx_ino64_t;		/* 64 bit inode number */
typedef vx_u32_t	vx_lbolt_t;		/* number of 'lightning bolts'*/
typedef vx_u32_t	vx_ptr32_t;		/* 32 bit user pointer */

/*
 * The following should not be used.
 */

typedef vx_s32_t	vx_uid_t;		/* user id */
typedef vx_s32_t	vx_gid_t;		/* group id */
typedef vx_u32_t	vx_pid_t;		/* process id */
typedef vx_u32_t	vx_sec_t;		/* number of seconds */

typedef struct vx_timeval32 {			/* 32 bit time value struct */
	vx_u32_t	tv_sec;
	vx_u32_t	tv_usec;
} vx_timeval32_t;

/*
 * returns the offset of a field in a structure without compiler warnings.
 */

#define vx_offsetof(field, structnm) ((size_t)(&(((structnm *)0L)->field)))

/*
 * Maximum block, block offset, and block count values for both
 * files and file systems.  These values are not necessarily
 * derivable from other constants when the four possible cases are
 * considred:  small files and small file systems, small files and
 * large file systems, large files and large file systems, and
 * large file systems with multiple devices.  VX_MAX_BLOCKS() is
 * for comparisions with fields like i_blocks, but not i_reserve.
 *
 * There is no VX_MAXFS_OFF since on some platforms (unixware) the
 * maximum file offset in bytes is not representable in any data
 * type.  Instead we have VX_MAXFS_SECTOFF.
 *
 * File system block numbers -1, -2, ..., -256 are reserved.  Block
 * numbers -1 and -2 are currently used.
 *
 * VX_MAX_SMALLOFF is the maximum offset for "small files" in
 * version 2 inodes, quota files, and elsewhere.
 *
 */

#define	VX_MAX_SMALLOFF		(((vx_off_t)1 << 31) - 1)

/*
 * Maximum i/o size transfered between vxfs and underlying driver in
 * a single io request.
 */

#define	VX_MACH_DEF_MAXTRANSFER		(1024 * 1024)

/*
 * Set qio caching flag.
 */

#define	VX_SET_QIOCACHE(value)		(value)

/*
 * Fake an aio completion.
 */

#define VX_AIO_DONE(ip, rw, aiop, ioerr)	\
		vx_aio_done(ip, rw, aiop, ioerr)

/*
 * system time for I/O stats
 */

#define	VX_SYSTEM_LBOLT()		lbolt

/*
 * Access and update uio structures.
 */

#define VX_UIO_USER			UIO_USERSPACE
#define VX_UIO_KERNEL			UIO_SYSSPACE

#define	VX_UIO_SYNC_FLAGS(ioflag)	(ioflag)
#define	VX_UIO_OFFSET(uiop)		((uiop)->uio_loffset)
#define	VX_UIO_SEG(uiop)		((uiop)->uio_segflg)
#define VX_UIO_SEGADDR(uiop)		((uiop)->uio_iov->iov_base)
#define VX_UIO_SEGCOUNT(uiop)		((uiop)->uio_iovcnt)
#define	VX_UIO_LIMIT(uiop)		((uiop)->uio_llimit)
#define	VX_UIO_FMODE(uiop)		((uiop)->uio_fmode)
#define	VX_UIO_RESID(uiop)		((size_t)(ssize_t)(uiop)->uio_resid)
#define	VX_UIO_SETOFFSET(uiop, off)	((uiop)->uio_loffset = (off))
#define	VX_UIO_SETSEG(uiop, segflg)	((uiop)->uio_segflg = (segflg))
#define	VX_UIO_SETLIMIT(uiop, lim)	((uiop)->uio_llimit = (lim))
#define	VX_UIO_SETFMODE(uiop, flags)	((uiop)->uio_fmode = (flags))
#define	VX_UIO_SETRESID(uiop, resid)	((uiop)->uio_resid = (resid))

#define	VX_APPEND			FAPPEND
#define	VX_VCURRENTCRED(cr)		(cr)
#define	VX_PM_DENIED(cr)		(cr != NOCRED && !suser(cr))

#define	VX_PNAME_PATHLEN(pn)		((size_t)(pn)->pn_pathlen)

/*
 * We put the direct and dsync advisories into the file table.  There is
 * a flag defined in file.h for dsync but not for direct.
 * This should move out to some common code.
 */

#define FDIRECT		0x20		/* overload FREVOKE flag */

/*
 * Solaris doesn't have a VFS flag for largefiles, so this ends up being a nop.
 */

#define VFS_LARGEFILES	0x00

/*
 * Defines for page cache interfaces
 */

#define	VX_PGOFF(pp)			(pp)->p_offset
#define	VX_PAGE_NIO_SET(pp, n)

#define	VX_S_CREATE		S_CREATE
#define	VX_SM_NOREUSE		(SM_FREE | SM_DONTNEED | SM_ASYNC)
#define	VX_SM_RELEASE		(SM_FREE | SM_DONTNEED | SM_ASYNC)
#define	VX_SM_NOCACHE		0

#define	VX_PFLUSH_FLAGS		B_ASYNC
#define	VX_PUT_NOCLUSTER	B_NOCACHE

#define VX_AS_LOCK(hat, as, addr, reqlen, type, rw)			\
	as_fault((hat), (as), (addr), (reqlen), (type), (rw))

#define VX_AS_UNLOCK(hat, as, addr, reqlen, type, rw)			\
	as_fault((hat), (as), (addr), (reqlen), (type), (rw))

#define VX_CLR_ASYNC(bp)	(bp)->vb_flags &= ~B_ASYNC;

/*
 * Set a hyper to a value.
 */

#define VX_HYPER_INIT(h, high, low) {					\
	(h)->vh_high = (high);						\
	(h)->vh_low = (low);						\
}

/*
 * Return true iff a hyper is less than 3/8 of its maximum value.
 */

#define	VX_HYPER_LT_3_8_MAX(h)	((h)->vh_high < (unsigned)0x60000000)

/*
 * Return true iff a hyper is less than 6/8 of it's maximum value.
 */

#define	VX_HYPER_LT_6_8_MAX(h)	((h)->vh_high < (unsigned)0xc0000000)

/*
 * Return true iff a hyper is less than 7/8 of it's maximum value.
 */

#define	VX_HYPER_LT_7_8_MAX(h)	((h)->vh_high < (unsigned)0xe0000000)

/*
 * Cache write sync macro for Solaris.
 */

#define VX_CACHE_WRITE_SYNC()	vx_cache_write_sync()
#define VX_CACHE_READ_SYNC()	/* not defined */

/*
 * The "preferred" super-block location for Solaris vxfs.
 */

#define VX_SBOFFPREF	8192

/*
 * The on-disk fileset header structure for Version 2 file systems
 * varies in its format across porting lines.  The details are in
 * vx_layout.h   VX_V2FSET_TYPE should be set to VX_V2FSET_ORIG for
 * porting lines that did not have the quota inodes in the Vesion 2
 * fileset header.  Others should set VX_V2FSET_TYPE to VX_V2FSET_NEW.
 */

#define VX_V2FSET_ORIG	1
#define VX_V2FSET_NEW	2
#define VX_V2FSET_TYPE	VX_V2FSET_ORIG

/*
 * The minimum number of inodes that will be allocated into the inode
 * table at config time.
 */

#define	VX_MINNINODE	150

/*
 * The mask needed for putpage unitizing.
 */

#define VX_PUTPAGEMASK(fs)	PAGEMASK

/*
 * define VX_KERNELSPACE for VX_LBCOPY macro
 *	flag not used on Solaris, but is in VX_LBCOPY call in vx_attr.c
 */

#define VX_KERNELSPACE	0

/*
 * We want a constant that represents the real maximum name size
 * for directory entries.
 */

#if	VX_MAXNAMLEN < MAXNAMLEN
#define	VX_NAMEMAX	VX_MAXNAMLEN
#else
#define	VX_NAMEMAX	(MAXNAMELEN - 1)
#endif

/*
 * Decide if this is an nfs request.
 */

#define	VX_ISNFS	(curthread->t_procp == &p0)

/*
 * The different types of i/o request that vxfs can generate.
 *
 * Not currently used on Solaris.  It may prove
 * useful for performance traces of vxfs running benchmarks, or even
 * to implement fast resilvering.
 */

#define	VX_IOT_SBLOCK	0	/* super block */
#define	VX_IOT_LOG	0	/* log write */
#define	VX_IOT_INODE	0	/* inode */
#define	VX_IOT_DATA	0	/* regular file data */
#define	VX_IOT_DIO	0	/* direct i/o file data */
#define	VX_IOT_INDIRECT	0	/* indirect extent */
#define	VX_IOT_DIR	0	/* directory data */
#define	VX_IOT_SYMLINK	0	/* symbolic link data */
#define	VX_IOT_ATTR	0	/* inode attribute data */
#define	VX_IOT_AUSUM	0	/* au summary (version 1 & 2) */
#define	VX_IOT_IAUSUM	0	/* iau summary (version >= 2) */
#define	VX_IOT_EAUSUM	0	/* eau summary (version 3) */
#define	VX_IOT_IMAP	0	/* inode map */
#define	VX_IOT_IEMAP	0	/* inode extended op map */
#define	VX_IOT_EMAP	0	/* extent map */
#define	VX_IOT_SMAP	0	/* eau state map */
#define	VX_IOT_CUT	0	/* current usage table */
#define	VX_IOT_LCT	0	/* link count table */
#define	VX_IOT_FSHD	0	/* file set headers */
#define	VX_IOT_OLT	0	/* object location table */
#define	VX_IOT_LAB	0	/* device label (sblock) file */
#define	VX_IOT_DEV	0	/* device config file */
#define	VX_IOT_REORG	0	/* reorg i/o for file or meta */
#define	VX_IOT_SNAP	0	/* snapshot i/o */
#define	VX_IOT_SNAPMAP	0	/* snapshot maps */
#define	VX_IOT_UNKMETA	0	/* unknown meta-data */
#define	VX_IOT_OTHER	0	/* other */

/*
 * A unique thread identifier (on Solaris, used only by XTED).
 */

typedef struct kthread *	vx_thread_id_t;

/*
 * VX_THREADNAME is defined only on UnixWare to set the name field of
 * the lwp structure which is accessed from "ps" within kdb.
 */

#define	VX_THREADNAME

/*
 * The following definitions are used by vx_common_msgprint to determine
 * whether to use printf or uprintf. vx_msgprint passes VX_PRINTF while
 * vx_umsgprint passes VX_UPRINTF.
 */

#define VX_PRINTF	0
#define VX_UPRINTF	1

#define VX_UMSGPRINT	vx_umsgprint

/*
 * We disallow ENOSPC messages going to the user's console.
 */

#define VX_NOSPACE_MSG

/*
 * System time interface in seconds.
 */

#define	vx_lbolt	((vx_u32_t)hrestime.tv_sec)

/*
 * From limits.h
 */

#ifndef INT_MAX
#define	INT_MAX		2147483647
#endif
#ifndef UINT_MAX
#define	UINT_MAX	((unsigned)4294967295)
#endif

/*
 * System parameter constants
 */

#ifndef PATH_MAX
#define	PATH_MAX	255
#endif

#define	PAGEOFFMASK	(PAGESIZE - 1)	/* mask offset within page */

/*
 * The maximum number of links.
 */

#define VX_MAXLINK	MAXLINK

/*
 * The errno when quotas are exceeded.
 */

#define VX_EDQUOT	EDQUOT

/*
 * The maximum uid and "old" maximum for systems where the size
 * of storage and imposed maximum may have changed going from
 * Version 2 to Version 3.  (c.f. checks in vx_dirop.c).
 */

#define VX_MAXUID	MAXUID
#define VX_OLD_MAXUID	MAXUID
#define OLD_UID_NOBODY	UID_NOBODY

/*
 * Different platforms have a different type for the write
 * strategy type.
 */

typedef void (* vx_wstrat_t)();

#define VX_MEMLOCK(addr, len, rw)	vx_memlock((addr), (len), (rw))
#define VX_MEMUNLOCK(addr, len)		vx_memunlock((addr), (len))

/*
 * A basic sleep lock.  It might be implemented using a single
 * spin lock per sleep lock or by using hashed spin locks with
 * a number of sleep locks mapping to one spin lock (only one of
 * sl_lock or sl_lockpool will be set).  This is determined when
 * the lock is initialized.
 */

typedef kmutex_t vx_sleep_t;

#define VX_CUT_PRI		0
#define VX_DQ_SLEEP_PRI		0
#define VX_FS_LOGCLEAN_PRI	0
#define VX_FS_SBLOCK_PRI	0
#define VX_FS_GCUT_PRI		0
#define VX_FSI_PRI		0
#define VX_FST_DIR_PRI		0
#define VX_ILOCK_PRI		0
#define VX_LCT_PRI		0
#define VX_MAP_PRI		0
#define VX_SNAP_BLK_PRI		0
#define VX_SNAP_RESBIT_PRI	0
#define VX_SYNC_PRI		0

#define VX_CUT_SLEEP_INIT(lkp)					\
		mutex_init(lkp, VX_CUT_NAME,			\
			   MUTEX_DEFAULT, NULL)

#define VX_DQ_SLEEP_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_DQ_SLEEP_NAME,		\
			   MUTEX_DEFAULT, NULL)

#define VX_FS_GCUT_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_FS_GCUT_NAME,		\
			   MUTEX_DEFAULT, NULL)

#define VX_FS_LOGCLEAN_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_FS_LOGCLEAN_NAME,		\
			MUTEX_DEFAULT, NULL)

#define VX_FS_SBLOCK_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_FS_SBLOCK_NAME,		\
			   MUTEX_DEFAULT, NULL)

#define VX_FST_DIR_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_FST_DIR_NAME,		\
			   MUTEX_DEFAULT, NULL)

#define VX_ILOCK_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_ILOCK_NAME,			\
			   MUTEX_DEFAULT, NULL)

#define VX_LCT_SLEEP_INIT(lkp)					\
		mutex_init(lkp, VX_LCT_NAME,			\
			   MUTEX_DEFAULT, NULL)

#define VX_MAP_SLEEP_INIT(lkp)					\
		mutex_init(lkp, VX_MAP_NAME,			\
			   MUTEX_DEFAULT, NULL)

#define VX_SNAP_BLK_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_SNAP_BLK_NAME,		\
			   MUTEX_DEFAULT, NULL)

#define VX_SNAP_RESBIT_SLEEP_INIT(lkp)				\
		mutex_init(lkp, VX_SNAP_RESBIT_NAME,		\
			   MUTEX_DEFAULT, NULL)

#define VX_SYNC_SLEEP_INIT(lkp)					\
		mutex_init(lkp, VX_SYNC_NAME,			\
			   MUTEX_DEFAULT, NULL)

#define VX_SLEEP_DEINIT(lkp)		mutex_destroy(lkp)
#define VX_SLEEP_LOCK(lkp, pri)		mutex_enter(lkp)
#define VX_SLEEP_TRYLOCK(lkp)		mutex_tryenter(lkp)
#define VX_SLEEP_UNLOCK(lkp)		mutex_exit(lkp)
#define VX_SLEEP_AVAIL(lkp)		vx_sleep_avail(lkp)

/*
 * A basic shared/exclusive sleep lock.  It may be implemented using
 * a single spin lock per sleep lock or by using hashed spin locks with
 * a number of locks mapping to one spin lock (only one of rw_lock or
 * rw_lockpool will be set).  This is determined when the lock is
 * initialized.
 */

/*
 * Flags for read/write locks.  We acquire some locks in shared
 * or exclusive mode.
 */

#define	VX_LOCK_SHARED		1
#define	VX_LOCK_EXCL		2

typedef krwlock_t vx_rwsleep_t;

#define VX_ATTROP_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_ATTROP_NAME,			\
			     RW_DEFAULT, NULL)

#define VX_COPYLOCK_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_COPYLOCK_NAME,			\
			     RW_DEFAULT, NULL)

#define VX_FS_RWSLEEP_INIT(lkp)					\
		rw_init(lkp, VX_FS_NAME,			\
			     RW_DEFAULT, NULL)

#define VX_IBMAP_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_IBMAP_NAME,			\
			     RW_DEFAULT, NULL)

#define VX_IGLOCK_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_IGLOCK_NAME,			\
			     RW_DEFAULT, NULL)

#define VX_IPLOCK_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_IPLOCK_NAME,			\
			     RW_DEFAULT, NULL)

#define VX_KDM_FCACHE_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_KDM_FCACHE_NAME,		\
			     RW_DEFAULT, NULL)

#define VX_KDM_GLOBAL_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_KDM_GLOBAL_NAME,		\
			     RW_DEFAULT, NULL)

#define VX_FSETOP_RWSLEEP_INIT(lkp)				\
		rw_init(lkp, VX_FSETOP_NAME,			\
			     RW_DEFAULT, NULL)

/*
 * The update lock is a sleep lock on other platforms but a rw sleep lock
 * on Solaris.  Use a name that is common to all platforms.
 */

extern	vx_rwsleep_t	vx_upd_slk;
#define VX_UPD_SLEEP_INIT(lkp)					\
		rw_init(lkp, VX_UPD_NAME,			\
			   RW_DEFAULT, NULL)

#define VX_RWSLEEP_DEINIT(lkp)		rw_destroy(lkp)
#define VX_RWSLEEP_LOCK(lkp, mode)	vx_rwsleep_lock(lkp, mode)
#define VX_RWSLEEP_TRYLOCK(lkp, mode)	vx_rwsleep_trylock(lkp, mode)
#define VX_RWSLEEP_UNLOCK(lkp)		rw_exit(lkp)
#define VX_RWSLEEP_AVAIL(lkp, mode)	vx_rwsleep_avail(lkp, mode)
#define VX_RWSLEEP_RDLOCK(lkp)		rw_enter(lkp, RW_READER)
#define VX_RWSLEEP_WRLOCK(lkp)		rw_enter(lkp, RW_WRITER)
#define VX_RWSLEEP_TRYRDLOCK(lkp)	rw_tryenter(lkp, RW_READER)
#define VX_RWSLEEP_TRYWRLOCK(lkp)	rw_tryenter(lkp, RW_WRITER)

/*
 * Swap lock and unlock.
 */

#define	VX_SWAPLOCK()		/* no lock needed */
#define	VX_SWAPUNLOCK()		/* no lock needed */

/*
 * Module lock macros.
 */

#define VX_MODULE_LOCK(iplp)					\
	VX_SPIN_LOCK(&vx_module_lk, VX_BADSPL, (iplp))
#define VX_MODULE_UNLOCK()	VX_SPIN_UNLOCK(&vx_module_lk, VX_BADSPL)
#define VX_MODULE_NAME		"FS:vxfs:module lock"

/*
 * Solaris does not provide a spin lock primitive, VxFS
 * spin locks will be mapped to a mutex lock. The priority
 * levels are not altered for mutex locks.
 */

/*
 * Values for the "pl" argument to VX_SPIN_LOCK and VX_SPIN_TRYLOCK.
 */

#define VX_ACTIVE_PL		VX_SPLBASE
#define VX_BUFSPACE_PL		VX_SPLBASE
#define VX_CURLB_PL		VX_SPLBASE
#define VX_CURUSED_PL		VX_SPLBASE
#define VX_CUT_PL		VX_SPLBASE
#define VX_DIOSPACE_PL		VX_SPLBASE
#define VX_DQLIST_PL		VX_SPLBASE
#define VX_DQSPIN_PL		VX_SPLBASE
#define VX_ESUM_PL		VX_SPLBASE
#define VX_FSLIST_PL		VX_SPLBASE
#define VX_FSQ_PL		VX_SPLBASE
#define VX_IBHASH_PL		VX_SPLBASE
#define VX_IDENT_PL		VX_SPLBASE
#define VX_IINTR_LOCK_PL	VX_SPLBASE
#define VX_ILHASH_PL		VX_SPLBASE
#define VX_WORKLIST_PL		VX_SPLBASE
#define VX_ILIST_PL		VX_SPLBASE
#define VX_IMAPLIST_PL		VX_SPLBASE
#define VX_ISPIN_LOCK_PL	VX_SPLBASE
#define VX_ISUM_PL		VX_SPLBASE
#define VX_KDM_SYS_PL		VX_SPLBASE
#define VX_LCT_LIST_PL		VX_SPLBASE
#define VX_LOGQ_PL		VX_SPLBASE
#define VX_NMSPC_PL		VX_SPLBASE
#define VX_NTRAN_PL		VX_SPLBASE
#define VX_SCHED_PL		VX_SPLBASE
#define VX_SNAPBIT_PL		VX_SPLBASE
#define VX_TRANQ_PL		VX_SPLBASE
#define VX_THREAD_PL		VX_SPLBASE
#define VX_WCHAINSPACE_PL	VX_SPLBASE

typedef kmutex_t	vx_spin_t;
typedef vx_spin_t	vx_fspin_t;

#define VX_ACTIVE_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_ACTIVE_NAME, MUTEX_DEFAULT, NULL)
#define VX_BUFSPACE_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_BUFSPACE_NAME, MUTEX_DEFAULT, NULL)
#define VX_CURLB_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_CURLB_NAME, MUTEX_DEFAULT, NULL)
#define VX_CURUSED_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_CURUSED_NAME, MUTEX_DEFAULT, NULL)
#define VX_CUT_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_CUT_NAME, MUTEX_DEFAULT, NULL)
#define VX_DIOSPACE_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_DIOSPACE_NAME, MUTEX_DEFAULT, NULL)
#define VX_DQLIST_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_DQLIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_DQSPIN_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_DQSPIN_NAME, MUTEX_DEFAULT, NULL)
#define VX_ESUM_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_ESUM_NAME, MUTEX_DEFAULT, NULL)
#define VX_FSLIST_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_FSLIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_FSQ_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_FSQ_NAME, MUTEX_DEFAULT, NULL)
#define VX_IDENT_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_IDENT_NAME, MUTEX_DEFAULT, NULL)
#define VX_IMAPLIST_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_IMAPLIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_ISUM_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_ISUM_NAME, MUTEX_DEFAULT, NULL)
#define VX_IINTR_LOCK_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_IINTR_LOCK_NAME, MUTEX_DEFAULT, NULL)
#define VX_WORKLIST_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_WORKLIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_ICACHE_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_ICACHE_NAME, MUTEX_DEFAULT, NULL)
#define VX_ILIST_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_ILIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_INACTIVE_ILIST_SPIN_INIT(lkp)				\
		mutex_init(lkp, VX_ILIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_DELXWRI_ILIST_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_ILIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_ILHASH_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_ILHASH_NAME, MUTEX_DEFAULT, NULL)
#define VX_IBHASH_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_IBHASH_NAME, MUTEX_DEFAULT, NULL)
#define VX_IRWSPIN_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_IRWSPIN_NAME, MUTEX_DEFAULT, NULL)
#define VX_ISPIN_LOCK_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_ISPIN_LOCK_NAME, MUTEX_DEFAULT, NULL)
#define VX_KDM_SYS_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_KDM_SYS_NAME, MUTEX_DEFAULT, NULL)
#define VX_LCT_LIST_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_LCT_LIST_NAME, MUTEX_DEFAULT, NULL)
#define VX_LOGQ_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_LOGQ_NAME, MUTEX_DEFAULT, NULL)
#define VX_MODULE_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_MODULE_NAME, MUTEX_DEFAULT, NULL)
#define VX_NMSPC_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_NMSPC_NAME, MUTEX_DEFAULT, NULL)
#define VX_NTRAN_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_NTRAN_NAME, MUTEX_DEFAULT, NULL)
#define VX_SCHED_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_SCHED_NAME, MUTEX_DEFAULT, NULL)
#define VX_SNAPBIT_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_SNAPBIT_NAME, MUTEX_DEFAULT, NULL)
#define VX_TRANQ_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_TRANQ_NAME, MUTEX_DEFAULT, NULL)
#define VX_WCHAINSPACE_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_WCHAINSPACE_NAME, MUTEX_DEFAULT, NULL)
#define VX_BCFREE_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_BCFREE_NAME, MUTEX_DEFAULT, NULL)
#define VX_PGIO_SPIN_INIT(lkp)						\
		mutex_init(lkp, VX_PAGEIO_KMEMLOCK_NAME,		\
			   MUTEX_DEFAULT, NULL)
extern	vx_spin_t	vx_thread_lk;
#define VX_THREAD_SPIN_INIT(lkp)					\
		mutex_init(lkp, VX_THREAD_NAME, MUTEX_DEFAULT, NULL)

#define VX_SPIN_DEINIT(lkp)		mutex_destroy((kmutex_t *)lkp)

#define VX_SPIN_LOCK(lkp, npl, oplp) {					\
	*(oplp) = VX_SPLBASE;						\
	mutex_enter((kmutex_t *)lkp);					\
}

#define VX_SPIN_TRYLOCK(lkp, npl, oplp)					\
	(*(oplp) = (mutex_tryenter(lkp) ? VX_SPLBASE : VX_BADSPL))

#define VX_SPIN_UNLOCK(lkp, opl)	mutex_exit(lkp)

#define	VX_ISPIN_LOCK(ip, iplp) {					\
	TED_SPEC_ACTION("sa:vx_ispin_delay:1", 1, 1);			\
	XTED_ISPIN_LOCK1(ip);						\
	VX_SPIN_LOCK(&(ip)->i_spinlock, VX_ISPIN_LOCK_PL, iplp);	\
	XTED_ISPIN_LOCK2(ip);						\
}

#define	VX_IINTR_LOCK(ip, iplp) {					\
	TED_SPEC_ACTION("sa:vx_iintr_delay:1", 1, 1);			\
	VX_SPIN_LOCK(&(ip)->i_intrlock, VX_IINTR_LOCK_PL, iplp);	\
	XTED_IINTR_LOCK(ip);						\
}

/*
 * Fast spinlock.  Same as spinlock on Solaris.
 */

#define VX_FSPIN_DEINIT(lkp)		VX_SPIN_DEINIT(lkp)
#define VX_FSPIN_LOCK(lkp, npl, oplp)	VX_SPIN_LOCK(lkp, npl, oplp)
#define VX_FSPIN_UNLOCK(lkp, opl)	VX_SPIN_UNLOCK(lkp, opl)

/*
 * Synchronization variables provide MP sleep/wakeup synchronization.
 * The sleep must be coordinated with a spin lock (which is released
 * when the process goes to sleep).
 */

typedef kcondvar_t	vx_svar_t;

#define VX_CURLB_MEM_PRI		0
#define VX_FS_TRANLOG_PRI		0
#define VX_FSLOGQ_PRI			0
#define VX_WORKLIST_THREAD_PRI		0
#define VX_FSBUFLIST_PRI		0
#define VX_FSPGIO_PRI			0

#define VX_SVAR_INIT(svp, namep)				\
	cv_init((svp), (namep), CV_DEFAULT, NULL)
#define VX_SVAR_DEINIT(svp)		cv_destroy(svp)
#define VX_SVAR_SLEEP_UNLOCK(svp, pri, lkp) {			\
	cv_wait((svp), (lkp));					\
	mutex_exit(lkp);					\
}
#define VX_SVAR_SLEEPONE_UNLOCK(svp, pri, lkp)			\
	VX_SVAR_SLEEP_UNLOCK((svp), (pri), (lkp))
#define VX_SVAR_WAKEALL(svp)		cv_broadcast(svp)
#define VX_SVAR_WAKEONE(svp)		cv_signal(svp)
#define VX_WORKLIST_SLEEP()	{	\
	VX_SPIN_LOCK(&vx_sched_lk, VX_SCHED_PL, &ipl); \
	VX_SVAR_SLEEP_UNLOCK(&vx_worklist_thread_sv, VX_WORKLIST_THREAD_PRI, \
			&vx_sched_lk);	\
}

/*
 * A basic event variable.
 *
 * It may be implemented using a single spin lock per sleep lock or by
 * using hashed spin locks with a number of locks mapping to one spin
 * lock (only one of ev_lockp or ev_lockpoolp will be set).  This is
 * determined when the event is initialized.
 */

typedef struct vx_event {
	vx_spin_t	*ev_lockp;
	vx_svar_t	*ev_cvp;
	char		ev_posted;
	char		ev_wait;
	u_short		ev_init;
} vx_event_t;

#define VX_ICA_EVENT_INIT(evp)					\
		vx_event_init(evp, VX_ICA_EVENT_NAME)
#define VX_CLONE_EVENT_INIT(evp)				\
		vx_event_init(evp, VX_CLONE_EVENT_NAME)
#define VX_DELAY_EVENT_INIT(evp)				\
		vx_event_init(evp, VX_DELAY_EVENT_NAME)
#define VX_DQ_EVENT_INIT(evp)					\
		vx_event_init(evp, VX_DQ_EVENT_NAME)
#define VX_KDM_EVENT_INIT(evp)					\
		vx_event_init(evp, VX_KDM_EVENT_NAME)
#define VX_KDM_USER_EVENT_INIT(evp)				\
		vx_event_init(evp, VX_KDM_USER_EVENT_NAME)
#define VX_LCT_EVENT_INIT(evp)					\
		vx_event_init(evp, VX_LCT_EVENT_NAME)

#define VX_EVENT_PL		VX_PRISLEP

#define	VX_EVENT_DEINIT(evp)		vx_event_deinit(evp)
#define	VX_EVENT_WAIT(evp)		vx_event_wait(evp)
#define	VX_EVENT_WAITSIG(evp)		vx_event_waitsig(evp)
#define	VX_EVENT_POST(evp)		vx_event_post(evp)
#define	VX_EVENT_ISPOSTED(evp)		vx_event_isposted(evp)
#define	VX_EVENT_CLEAR(evp)		vx_event_clear(evp)

/*
 * Enable and disable kernel preemption.
 */

#define	VX_DISABLE_PREEMPT()	kpreempt_disable()
#define	VX_ENABLE_PREEMPT()	kpreempt_enable()

#ifdef _KERNEL

/*
 * Protect bzero/bcopy/kmem_zalloc/clrbuf. Working around the hardware
 * memory block operations problem in Solaris. (IR#26696).
 */

#define bzero(ptr, size) {						\
	VX_DISABLE_PREEMPT();						\
	bzero(ptr, size);						\
	VX_ENABLE_PREEMPT();						\
}

#define bcopy(src, dest, size) {					\
	VX_DISABLE_PREEMPT();						\
	bcopy(src, dest, size);						\
	VX_ENABLE_PREEMPT();						\
}

#define clrbuf(buf) {							\
	VX_DISABLE_PREEMPT();						\
	clrbuf(buf);							\
	VX_ENABLE_PREEMPT();						\
}

#define kmem_zalloc(size, flags)	vx_kmem_zalloc(size, flags)

#endif /* _KERNEL */

/*
 * Find CPU of current thread.
 */

#define	VX_CPUID		(int)(CPU->cpu_id)
#define	VX_GETCPUID(cpuid)	{ (cpuid) = VX_CPUID; }

/*
 * Vnode locks.
 */

#define VX_VN_INIT(vp) {						\
		mutex_init(&vp->v_lock, VX_VNODE_LOCK_NAME,		\
			   MUTEX_DEFAULT, NULL);			\
		(vp)->v_count = 1;					\
}

#define VX_VN_DEINIT(vp)		mutex_destroy(&(vp)->v_lock);
#define	VX_VN_LOCK(vp, lkpp, contextp)	mutex_enter(&(vp)->v_lock);
#define	VX_VN_UNLOCK(vp, lkp, context)	mutex_exit(&(vp)->v_lock);

#define	VX_VN_DECR(vp) {						\
	VX_VN_LOCK((vp), 0, 0);						\
	(vp)->v_count--;						\
	VX_VN_UNLOCK((vp), 0, 0);					\
}

/*
 * File locks and conversion from file descriptor to file pointer
 */

#define VX_GETF(fd)		getf(fd)
#define VX_RELEASEF(fd)		releasef(fd)
#define VX_VNODE(fp)		(fp)->f_vnode

/*
 * Attributes of interest to the caller of setattr or getattr.
 */

#define	VX_AT_ISMODE(vap)	((vap)->va_mask & AT_MODE)
#define VX_AT_ISUID(vap)	((vap)->va_mask & AT_UID)
#define VX_AT_ISGID(vap)	((vap)->va_mask & AT_GID)
#define	VX_AT_ISSIZE(vap)	((vap)->va_mask & AT_SIZE)
#define	VX_AT_ISATIME(vap)	((vap)->va_mask & AT_ATIME)
#define	VX_AT_ISMTIME(vap)	((vap)->va_mask & AT_MTIME)
#define	VX_AT_ISCTIME(vap)	((vap)->va_mask & AT_CTIME)

#define	VX_AT_ISNOCHANGE(vap)	((vap)->va_mask & AT_NOSET)

/*
 * The routine to start a disk I/O on the device for the specified buffer.
 */

#ifdef	TED_								/*TED_*/
#define VX_DEV_STRATEGY(bp)	vx_dev_strategy(bp)			/*TED_*/
#else									/*TED_*/
#define VX_DEV_STRATEGY(bp)	bdev_strategy((struct buf *)bp)
#endif									/*TED_*/

#define VX_VALID_BUFSIZE(size)	(size == IADDREXTSIZE)

/*
 * None of the following are applicable to Solaris vnodes.
 */

#define VX_SOFTHOLD_DNLC	0
#define VX_VPSOFTCNT(vp)	0
#define VX_VPSOFT_INCR(vp)
#define VX_VPSOFT_DECR(vp)

#define	VX_DNLC_PURGE_FSET(fset) \
		dnlc_purge_vfsp((fset)->fst_vxp->vfs_vfsp, 0)
#define	VX_DNLC_PURGE_VP(vp)		dnlc_purge_vp(vp)
#define	VX_DNLC_PURGE1()		dnlc_fs_purge1(&vx_vnodeops)
#define	VX_DNLC_FS_PURGE1(vfs)		dnlc_fs_purge1(vfs)
#define	VX_DNLC_REMOVE(vp, name)	dnlc_remove((vp), (name))
#define	VX_DNLC_ENTER(dvp, name, vp, cookie, cr) \
		dnlc_enter((dvp), (name), (vp), (cr))
#define	VX_DNLC_LOOKUP(dvp, name, cr, cookie, softholdp) \
		(*(softholdp) = 0, dnlc_lookup((dvp), (name), (cr)))

#define VX_VPSETINO(vp, ino)
#define VX_VPLISTS_NULL(vp)	1		/* Always true */
#define VX_VPCLEAR(vp)
#define VX_MAP_PURGE(vp)

#define	VX_MPCNTR(tag, incr)
#define	VX_DUMMY_INODE_SETUP(ip)

/*
 * Macros to update stats in vx_info[]
 */

#define	VX_MACH_INFO()			(vx_info + VX_CPUID)
#define	VX_MACH_INFO_BUMP(tag)		(++VX_MACH_INFO()->tag)
#define	VX_MACH_INFO_ADD(tag, count)	(VX_MACH_INFO()->tag += (count))
#define	VX_MACH_INFO_SUB(tag, count)	(VX_MACH_INFO()->tag -= (count))
#define VX_MACH_INFO_TIMEP(timepp) {					\
	(*timepp) = &VX_MACH_INFO()->vxi_tmstamp;			\
}
#define	VX_MACH_INFO_GET(tag, val)	(val) = (VX_MACH_INFO())->tag
#define	VX_MACH_INFO_SET(tag, val)	(VX_MACH_INFO())->tag = (val)
#define	VX_MACH_FSET_INFO(fset)		    ((fset)->fst_info + VX_CPUID)
#define	VX_MACH_FSET_INFO_BUMP(fset, tag)   (++VX_MACH_FSET_INFO((fset))->tag)

/*
 * The acceptable count on the root vnode for an fs in the iunmount code.
 */

#define VX_ROOTVNODECNT		1

#define	vx_getmajor(dev)	major(dev)

#define	VX_DELAY2(a,t)		delay(t)
#define	VX_DELAY(t)		delay(t)
#define	VX_DELAY_INIT()

#define	VX_MNT_WAIT		1
#define	VX_MNT_NOWAIT		2

/*
 * PIPSIZ is required; we picked it up from ufs/inode.h, though
 * it should really be a system wide paramater.
 * XXX Not yet fixed for Solaris
 */

#define	PIPSIZ	8192	/* from ufs/inode.h */

/*
 * Memory allocation and deallocation.
 */

#ifdef	TED_
#define	VX_ALLOC(size, slp)	(caddr_t) xted_alloc((size), (slp))	/*TED_*/
#define	VX_ZALLOC(size, slp)	(caddr_t) xted_zalloc((size), (slp))	/*TED_*/
#define	VX_FREE(ptr, size)	xted_free((caddr_t) (ptr), (size))	/*TED_*/
#else	/* TED_ */							/*TED_*/
#define	VX_ALLOC(size, slp)	(caddr_t) kmem_alloc((size), (slp))
#define	VX_ZALLOC(size, slp)	(caddr_t) kmem_zalloc((size), (slp))
#define	VX_FREE(ptr, size)	kmem_free((ptr), (size))
#endif	/* TED_ */

#define	VX_MEMWAIT	KM_SLEEP	/* wait for memory */
#define	VX_MEMNOWAIT	KM_NOSLEEP	/* do not wait wait for memory */
#define	VX_MEMDMA	0		/* not applicable in solaris */

/*
 * Certain allocations are freed outside the file system and as
 * such cannot have a debug version.
 */

#define VX_RZALLOC(size, slp)	(caddr_t) kmem_zalloc((size), (slp))
#define VX_RALLOC(size, slp)	(caddr_t) kmem_alloc((size), (slp))

/*
 * Due to a bug (?) in solaris, large number of kmem_free()'s
 * happening together can cause the kernelmap to fragment. I/O threads
 * trying to do bp_mapin() / bp_mapout() may be seriously impacted.
 * While freeing up a lot of buffers at a shot, ensure that the
 * total memory we free up is less than VX_KMEM_FREE_LIMIT.
 */

#define	VX_KMEM_FREE_LIMIT	(500 * PAGESIZE)

/*
 * Misc Stuff
 */

#define	VX_MAX_CPU		_ncpu
#define	VX_MAX_PROCS		v.v_proc
#define	VX_SET_UERROR(errno)	set_errno(errno)

#define	VX_SYNC_ALL		0x0
#define	VX_SYNC_META		SYNC_ATTR
#define	VX_SYNC_REBOOT		SYNC_CLOSE

/*
 * Macros for vx_cred_t.
 *
 * VX_CRED_UID(cr) evaluates to a uid.
 * VX_CRED_GID(cr) evaluates to a gid.
 * VX_CRED_GROUPS(cr, i) evaluates to a group array slot.
 * VX_CRED_GET()  evaluates to a pointer to a vx_cred_t.
 */

#define VX_CRED_UID(cr)		((cr)->cr_uid)
#define VX_CRED_GID(cr)		((cr)->cr_gid)
#define VX_CRED_GROUPS(cr, i)	((cr)->cr_groups[i])
#define VX_CRED_GET()		((vx_cred_t *)CRED())
#define VX_CRED_SET(cr)		(CRED() = (cr))

#define	VX_CRED_RUID()	(CRED()->cr_ruid)	/* real user id */
#define	VX_CRED_EUID()	(CRED()->cr_uid)	/* effective user id */
#define	VX_CRED_RGID()	(CRED()->cr_rgid)	/* real group id */
#define	VX_CRED_EGID()	(CRED()->cr_gid)	/* effective group id */

/*
 * Group membership check.
 */

#define	vx_groupmember(gid,cr)		groupmember(gid, cr)

/*
 * Permission check.
 */

#define	VX_PERM_OK(cr, perm)		(cr == NOCRED || suser(cr))

#define	VX_PERM_OWN	0
#define	VX_PERM_FS	0
#define	VX_PERM_MOUNT	0
#define	VX_PERM_SU	0
#define	VX_PERM_DACRD	0
#define	VX_PERM_DACWR	0

/*
 * Macros to get various information out of the user, process, or
 * thread structure (depending).
 */

#define VX_RLIM_INFINITY	RLIM_INFINITY
#define	VX_GETU_PID()		(ttoproc(curthread)->p_pid)
#define	VX_GETU_RLIMIT_FSIZE	(u.u_rlimit[RLIMIT_FSIZE].rlim_cur)
#define	VX_SETU_RLIMIT_FSIZE(cur, max) {			\
	(u.u_rlimit[RLIMIT_FSIZE]).rlim_cur = (cur);		\
	(u.u_rlimit[RLIMIT_FSIZE]).rlim_max = (max);		\
}
#define VX_RLIMIT_OK(offset, limit) \
		((limit) == VX_RLIM_INFINITY || (offset) < (limit))

/*
 * Return a unique non-NULL identifier for the current thread.
 */

#define	VX_CURTHREAD()		(curthread)

/*
 * For "/usr" support
 */

#define IS_ROOT		1
#define IS_USR		2

/*
 * typedefs to allow wrapping vnodeops and vfsops
 */

typedef vnodeops_t	vx_vnodeops_t;
typedef vfsops_t	vx_vfsops_t;

/*
 * Write-lock for fields in a vfs structure
 */

#define VX_VFS_LOCK(vfsp, iplp)		vfs_lock_wait(vfsp)
#define VX_VFS_UNLOCK(vfsp, ipl)	vfs_unlock(vfsp)

/*
 * System VFS structure as used by the vxfs file system.
 */

#define VX_VTOS(vfsp)	(vx_vfs_t *)(vfsp)
#define VX_STOV(svfsp)	(vfs_t *)(svfsp)

/*
 * VxFS wrapper for the system VFS structure.
 */

typedef struct vx__vfs {
	struct vfs	s_vfs;
} vx_vfs_t;

/*
 * The following vx_vfs_t aliases are port-specific:
 */

#define vs_fstype	s_vfs.vfs_fstype	/* file system type */

/*
 * Define VFS interfaces on Solaris
 */

#define VX_VFS_ROOT(svfsp, rvpp, name)	VFS_ROOT(VX_STOV(svfsp), rvpp)

/*
 * VX_VFS_RELE(vfsp) release the hold on a vfs structure
 */

#define VX_VFS_RELE(vfsp)

/*
 * Platform specific fs_iosize. On solaris and UW it is DEV_BSIZE.
 * For HP-UX it is MIN(PAGESIZE, fs->fs_bsize).
 */

#define VX_FS_IOSIZE(fs)  DEV_BSIZE

/*
 * This prototype is not defined in any system header file. We need it because
 * the function returns a pointer. If we don't supply a prototyp, the compiler
 * will assume it to be returning int.
 */

extern struct vnode *common_specvp(struct vnode *vp);

/*
 * Flush and invalidate any buffers or pages holding data for the
 * device specified by bvp. Cleanup on system buffer cache as well
 * as solaris buffer cache.
 *
 * Called during cleanup in mount/unmount.
 */

#define VX_BFLUSH_INVAL(fs, bvp)	{				\
	(void) VOP_PUTPAGE(common_specvp(bvp), 0, 0, B_INVAL, NOCRED);	\
	bflush((bvp)->v_rdev);						\
	binval((bvp)->v_rdev);						\
	vx_bc_bflush((bvp)->v_rdev, 1);					\
	vx_bc_binval((bvp)->v_rdev, 0);					\
}

#define	VX_BFLUSH_SNAPINVAL(fs, bvp)	VX_BFLUSH_INVAL(fs, bvp)

/*
 * Flush / Invalidate any buffers or pages holding data for the file
 * system specified by fs_vp.
 *
 * Called during cleanup in remount.
 */

#define VX_FSFLUSH_INVAL(fs)		{			\
	bflush((fs)->fs_dev);					\
	binval((fs)->fs_dev);					\
}

#define VX_FS_BINVAL(fs)	{				\
	binval((fs)->fs_dev);					\
}

/*
 * Flush buffers associated with the file system device.
 */

#define VX_FS_DEV_FLUSH(fs_dev)	{				\
	vx_bc_bflush(fs_dev, 1);				\
}

/*
 * Predicate to determine if we might need to invalidate buffers
 * for a given inode.
 */

#define VX_SHOULD_BUFINVAL(ip) (((ip)->i_mode & IFMT) != IFREG)

/*
 * Returns the age of the oldest buffer on the freelist.
 */

#define VX_BCACHE_RECYCLEAGE()	vx_bc_recycleage()

/*
 * Deinit the buffer cache.
 */

#define VX_BCACHE_DEINIT()	vx_bc_bdeinit()

/*
 * Argument to lookupname().
 */

#define VX_FOLLOW_LINK		FOLLOW

/*
 * Common call into specvp.
 */

#define VX_SPECVP(vp, dev, type, cr)	specvp(vp, dev, type, (cred_t *)cr)

/*
 * Increment the access generation count.
 */

#define	VX_BUMP_AGEN(ip) {			\
	if (VX_ITOV(ip)->v_type == VDIR) {	\
		(ip)->i_agen++;			\
		VX_CACHE_WRITE_SYNC();		\
	}					\
}

/*
 * Test if a vnode pointer is associated with a VXFS.
 */

extern	int	vx_fstype;
#define VX_ISVXFSVP(vp)		((vp)->v_vfsp->vfs_fstype == vx_fstype)

#define WRITEALLOWED(vp, cr)	(((vp)->v_vfsp->vfs_flag & VFS_RDONLY) == 0)

/*							  TED_
 * Define whether we are on a uniprocessor, for xted.	  TED_
 */							/*TED_*/
							/*TED_*/
#ifdef UNIPROC						/*TED_*/
#define XTED_UNIPROC_SET(flagp)		(*(flagp) = 1)
#else	/* UNIPROC */					/*TED_*/
#define XTED_UNIPROC_SET(flagp)		(*(flagp) = 0)
#endif	/* UNIPROC */					/*TED_*/

/*
 * If inode has a swapmap, throw it away.
 */

#define VX_SWAPMAP_CLEAR(ip)	{					\
	if ((ip)->i_swapmap) {						\
		vx_daddr_t	*map = NULL;				\
		int		mapsz;					\
		map = (ip)->i_swapmap;					\
		mapsz = *((ip)->i_swapmap + 2);				\
		(ip)->i_swapmap = NULL;					\
		(ip)->i_swapcnt = 0;					\
		VX_FREE((caddr_t)map, mapsz);	\
	}								\
}

#define VX_FKIOCTL		FKIOCTL

#define VX_VADDR_LOCK(x)
#define VX_VADDR_UNLOCK(x)

/*
 * START DMAPI DEFINES
 */

#define VX_KDMI_FILE_BUSY(ip)						\
		((ip)->i_mapcnt > 0 || (ip)->i_swapcnt > 0)
#define VX_KDMI_PAGEALIGN(offp)						\
		(*(offp) = (*(offp) + PAGESIZE - 1) & PAGEMASK)
#define VX_KDMI_NOT_PAGEALIGN(off)	((off) % PAGESIZE)
#define VX_KDMI_DIRNAMELEN(dep)						\
		strlen((dep)->d_name)
#define VX_KDMI_READDIR(dvp, uiop, eofp)				\
		vx_readdir_int(dvp, uiop, CRED(), eofp);
#define VX_KDMI_SYNC_FLAG		(FSYNC | FDSYNC)
#define VX_KDMI_ROOTVNODE_HOLD(rvp)

/*
 * END DMAPI DEFINES
 */

/*
 * Sar data collection for Solaris
 */

#define	VX_NSYS_FIELDS	1
#define	VX_NCPU_FIELDS	8

/*
 * End sar data collection for Solaris
 */

#define VX_MAX_MEMORY		((physmem / 2) * PAGESIZE)
#define VX_MAX_RAHEAD		((physmem / 20) * PAGESIZE)

/*
 * Xenix semaphores are not implemented in Solaris.
 */

#define VX_ISVXNAM(vp)		0

/*
 * Constant checked prior to a call to vx_pvn_vplist_dirty() or
 * vx_pvn_range_dirty(). If the number of pages to be flushed is greater
 * than VX_MAX_PAGE_RANGE, we flush with a length of 0 and therefore the
 * whole file.
 */

#define VX_MAX_PAGE_RANGE	50000

#define VX_VFS_HOLDCHECK(vfsp)	(0)
#define VX_VFS_RELECHECK(vfsp)	(0)
#define VX_VFSLIST_UNLOCK1()

/*
 * Set up buffer header.
 */

#define VX_SET_CHANNEL(bp, vp)

/*
 * Upgrade 4 completion. No-op for Solaris.
 */
#define VX_UPGRADE4_FINISH(fs)	0

/*
 * Macros to do type conversions on OS functions that do not take or
 * return the correct types.  This is to get flexelint to shut up while
 * avoiding cluttering our code with casts that should be unnecessary
 * (but adding macros invocations that should be unnecessary).
 */

#define VX_BCMP(s1, s2, size)		bcmp((s1), (s2), (size))
#define VX_STRLEN(cp)			((vx_u32_t)strlen(cp))
#define VX_STRNCMP(s1, s2, size)	strncmp((s1), (s2), (size))

/*
 * ACLs initialization macro, to be called from vx_config(). On Solaris
 * vx_acl_init() is called at the driver load time so this macro translates
 * to nop when invoked from vx_config() on solaris.
 */

#define	VX_ACL_INITIALIZE()

/*
 * 64 bit portability.
 */

#ifdef _LP64
#define VX_LP64
#define VX_SYSCALL_32_BIT		(get_udatamodel() == DATAMODEL_ILP32)
#else
#define VX_SYSCALL_32_BIT		1
#endif
#define VX_PTR32_TO_PTR(ptr, type)	((type)(ptr))
#define VX_PTR_TO_PTR32(ptr)		((vx_ptr32_t)(ptr))

/*
 * AIO related macros. Mainly needed for supporting cached quick i/o.
 */

/*
 * Lot of this stuff belongs to vx_lock.h actually but since this
 * feature is only available on Solaris, we should put it in
 * platform specific files so that people reading code on other
 * platforms don't have to worry about the stuff.
 */

extern	vx_spin_t		vx_aioq_lk;
extern	struct buf		vx_aioq_hd;
extern	int			(*vx_saved_aio_done)();

#define VX_AIOQ_LOCK_NAME	"FS:vxfs:aioq_lock spin"

#define VX_AIOQ_ENQUEUE() {						\
	vx_worklist_enqueue(vx_aioq_drain, NULL, 0);			\
	vx_worklist_wakeup(vx_nworkitems_high);				\
}

#define VX_AIOQ_LOCK_INIT()						\
	mutex_init(&vx_aioq_lk, VX_AIOQ_LOCK_NAME, MUTEX_DEFAULT, NULL);

/*
 * Locks for cached quick i/o.
 */

#define VX_AIOQ_LOCK(iplp) {						\
	XTED_AIOQ_LOCK1();						\
	VX_SPIN_LOCK(&vx_aioq_lk, VX_AIOQ_PL, (iplp));			\
	XTED_AIOQ_LOCK2();						\
}

#define VX_AIOQ_UNLOCK(ipl) {						\
	XTED_AIOQ_UNLOCK();						\
	VX_SPIN_UNLOCK(&vx_aioq_lk, (ipl));				\
}

#define VX_AIOQ_INSTAIL(bp) {						\
	bp->av_forw = &vx_aioq_hd;					\
	bp->av_back = vx_aioq_hd.av_back;				\
	vx_aioq_hd.av_back->av_forw = bp;				\
	vx_aioq_hd.av_back = bp;					\
	vx_aioq_hd.b_bcount++;						\
}

#define VX_AIOQ_NOTAVAIL(bp) {						\
	bp->av_forw->av_back = bp->av_back;				\
	bp->av_back->av_forw = bp->av_forw;				\
	bp->av_back = bp->av_forw = bp;					\
	vx_aioq_hd.b_bcount--;						\
}

#define VX_THREAD_PROCESS_AIOQ(fargs)					\
	vx_thread_process(vx_aioq_drain_freeze, (fargs))

/*
 * Macros related to keeping timing stats for qio
 */
#define VX_FDD_AIO_START_TIME(aiop, clk_start) {			\
	if (aiop) {							\
		((aio_req_t *)((struct aio_req *)			\
		 (aiop))->aio_private)->aio_req_buf.b_reltime =		\
			(clk_start);					\
	}								\
}

#define VX_FDD_AIO_STOP_TIME(bp, ip) {					\
	if ((bp)->b_flags & B_READ) {					\
		(ip)->i_readtime += (vx_sec_t)(VX_SYSTEM_LBOLT() -	\
			(bp)->b_reltime);				\
	} else {							\
		(ip)->i_writetime += (vx_sec_t)(VX_SYSTEM_LBOLT() -	\
			(bp)->b_reltime);				\
	}								\
}

#define VX_FDD_SIO_STOP_TIME(syncflag, counter, clk_start) {		\
	if (syncflag) {							\
		counter += VX_SYSTEM_LBOLT() - (clk_start);		\
	}								\
}

#define VX_VNODE_VFS_UNLOCK(vp, error)		vn_vfsunlock(vp)
#define VX_VNODE_VFS_LOCK(vp, vfslocked)				\
			vx_vnode_vfslock((vp), (vfslocked))
#define VX_VFS_MOUNTED(vp)			(vp->v_vfsmountedhere != NULL)

#define	VX_SET_LICENSE(mask, error)

/*
 * Macros for fancy read ahead.  (not implemented yet on solaris)
 */

#define VX_FANCYRA_INIT(ip)
#define VX_FANCYRA_DEINIT(ip)
#define VX_FANCYRA_ACTIVE(ip) 0
#define VX_FANCYRA_PREDICT(radata, off, len)

#endif	/* _FS_VXFS_VX_MACHDEP_H */
