/* @(#)src/sol/2.7/kernel/base/vx_solaris.h	3.15.19.4 04/20/00 00:44:48 -  */
/* #ident "@(#)vxfs:src/sol/2.7/kernel/base/vx_solaris.h	3.15.19.4" */

/*
 * 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_SOLARIS_H
#define	_FS_VXFS_VX_SOLARIS_H

#include <sys/flock.h>

/*
 * On solaris 2.6 NFS calls VOP_FSYNC at the end of operations which need
 * to be synchronous.
 */

#define	VX_NFS_NEEDSSYNCVOPS		0

typedef	struct dirent64		vx_dirent_t;
typedef struct flock64		vx_flock_t;
typedef struct statvfs64	vx_statvfs_t;
typedef unsigned long long	vx_u64_t;	/* 64 bit arithmetic (if any) */
typedef long long		vx_s64_t;	/* 64 bit signed math  */
typedef unsigned long long	vx_off_t;
typedef long long		vx_soff_t;
typedef int			vx_rval_t;	/* syscall return value */
typedef timeout_id_t		vx_timeoutid_t;
typedef size_t			vx_size_t;
typedef intptr_t		vx_iocarg_t;
typedef long			vx_syscallarg_t;
typedef dev_t			vx_dev_t;	/* system device id */
typedef uint_t			vx_sar_metric_t;/* system sar metrics */

/*
 * The processor level (ipl) data type, and values used by vxfs routines.
 * These are not passed on to OS, we don't change priority levels on
 * Solaris. Just define dummies for all the priority levels that are
 * used in the file system code.
 */

typedef int		vx_pl_t;

#define	VX_SPL0		1
#define	VX_SPLBASE	1
#define	VX_SPLBIO	1
#define	VX_SPL7		1
#define	VX_SPLHI	1
#define	VX_BADSPL	-1

#ifndef _KERNEL

/*
 * Backwards compatibility for commands.
 */

typedef vx_off_t	vxoff_t;
struct segvn_crargs;

#endif /* _KERNEL */

#define	_VXFS_BIG_OFFSETS	12345678
#define	_VXFS_LITTLE_OFFSETS	1234

#define	_VXFS_OFFSET_TYPE	_VXFS_BIG_OFFSETS

#define VA_LIST		va_list
#define VA_START	va_start
#define VA_ARG		va_arg

/*
 * With big offsets, version 3 file systems are limited to file
 * sizes of 2^31 device blocks (sectors), to avoid overflowing the
 * dbd field in the vm code (limit is 2^28 pages).
 *
 * The file system size is limited to 2^31 - 1 blocks because
 * daddr_t is signed.
 */

#define	VX_MAX_OFF		(((vx_off_t)1 << (31 + VX_MINBSHIFT)) - 1)
#define	VX_MAX_BLKOFF(fs)	(vx_off_t)((VX_MAX_OFF + 1) >> (fs)->fs_bshift)
#define VX_MAX_BLOCKS(fs)	(vx_daddr_t)VX_MAXFS_BLOCKS(fs)

#define	VX_MAXFS_SECTOFF	(daddr_t)(((vx_off_t)1 << 31) - 1)
#define	VX_MAXFS_BLKOFF(fs)	(vx_off_t)(VX_MAXFS_SECTOFF >> \
					  ((fs)->fs_bshift - DEV_BSHIFT))
#define VX_MAXFS_BLOCKS(fs)	(vx_daddr_t)(VX_MAXFS_BLKOFF(fs))

#define	VX_SYS_MAX_OFF(uiop, ioflag)	\
	(vx_off_t)((VX_UIO_FMODE(uiop) & FOFFMAX) ? MAXOFFSET_T : MAXOFF_T)

#define VX_PAGE_IS_FREE(pp)	PP_ISFREE(pp)

#define FLARGEFILE	FOFFMAX

/*
 * Solaris 2.6 seems to have done away with "HZ".
 * O/S code uses extern int hz now, but applications can get HZ from param.h
 */

#ifdef _KERNEL
#define HZ	hz
#endif

#define VX_VSOCK	VSOCK

#define VX_FOFFMAX_CHK(lfflag)	((lfflag & FOFFMAX) ? 0 : EOVERFLOW)

/*
 * The maximum number of inodes supported on version 3 file systems
 * and beyond.  Version 1 file systems are limited by their geometry
 * and version 2 by VX_MAX_SMALLOFF.
 *
 * This limit of 2^30 inode is somewhat arbitrary and based on the
 * scalability of our algorithms.  The real limit is probably close
 * to (2^32 - fs_bsize).
 */

#define	VX_MAX_NINODE	(1024 * 1024 * 1024)

/*
 * Set up definitions for accessing an 8 byte data type.
 */

typedef struct vx_hyper {
	union vh_hyper {
		unsigned char		vh_bytes[8];
		unsigned int		vh_words[2];
		unsigned long long	vh_64bits;
	} vh_hyper;
} vx_hyper_t;

#ifndef _KERNEL

typedef struct {
	union {
		unsigned char		vh_bytes[8];
		unsigned int		vh_words[2];
		unsigned long long	vh_64bits;
	} vh_hyper;
} vxhyper_t;

#endif /* _KERNEL */

#if #machine(i386)
#define	vh_low		vh_hyper.vh_words[0]
#define vh_high		vh_hyper.vh_words[1]
#define vh_highbyte	vh_hyper.vh_bytes[7]
#else
#define vh_low		vh_hyper.vh_words[1]
#define vh_high		vh_hyper.vh_words[0]
#define vh_highbyte	vh_hyper.vh_bytes[0]
#endif

#define vh_value	vh_hyper.vh_64bits

#define VX_HYPER_LOWMASK	0x00ffffffffffffffLL
#define VX_HYPER_HIGHMASK	0xff00000000000000LL
#define VX_HYPER_GETOFF(hy)	((hy).vh_hyper.vh_64bits & VX_HYPER_LOWMASK)
#define VX_HYPER_GETTYP(hy)	((hy).vh_highbyte)
#define VX_HYPER_SETTYP(hy, val)					\
	((hy).vh_highbyte = (val))
#define VX_HYPER_SETOFF(hy, val)					\
	(hy).vh_hyper.vh_64bits = (((hy).vh_hyper.vh_64bits &		\
				     VX_HYPER_HIGHMASK) |		\
				    ((unsigned long long)(val) &	\
				     VX_HYPER_LOWMASK))
/*
 * Determine if two hypers are equal.
 */

#define VX_HYPER_EQ(h1, h2)	((h1)->vh_value == (h2)->vh_value)

/*
 * Determine if a hyper is zero.
 */

#define VX_HYPER_ZERO(h)	((h).vh_value == (unsigned long long)0)

/*
 * Non-zero iff h1 < h2.
 */

#define VX_HYPER_LT(h1, h2)	((h1)->vh_value < (h2)->vh_value)

/*
 * Non-zero iff h1 <= h2.
 */

#define VX_HYPER_LTE(h1, h2)	((h1)->vh_value <= (h2)->vh_value)

/*
 * Math operations on hypers
 */

#define VX_HYPER_ADD(h1, h2, i)	(h1)->vh_value = (h2)->vh_value + (i)
#define VX_HYPER_SUB(h1, h2, i)	(h1)->vh_value = (h2)->vh_value - (i)
#define VX_HYPER_INC(h)		(++(h)->vh_value)
#define VX_HYPER_DEC(h)		(--(h)->vh_value)

/*
 * Convert a hyper to a disk address type.
 */

#define VX_HYPER_TO_DADDR(fs, h, d)					\
	((d) = (h).vh_value >> (fs)->fs_bshift)

/*
 * macros for rwlocks
 */

#define VX_RW_WRITE_HELD(rwlkp)	rw_write_held(rwlkp)
#define VX_RW_LOCK_HELD(rwlkp)	rw_lock_held(rwlkp)

/*
 * Defines for page cache interfaces
 */

#define VX_PAGE_IS_WRLOCKED(pp)		PAGE_LOCKED_SE(pp, SE_EXCL)
#define VX_PAGE_IS_RDLOCKED(pp)		PAGE_LOCKED_SE(pp, SE_SHARED)
#define VX_SEGMAP_PAGEUNLOCK(seg, addr, len, rw)			\
		((void) segmap_fault(kas.a_hat, (seg), (addr),		\
                                     (len), F_SOFTUNLOCK, (rw)))

#define VX_BP_LOCK_PAGES(bp, bflag, as, addr, len, ppplist)		\
		vx_bp_lock_pages((bp), (bflag), (as), (addr), (len), (ppplist))

#define VX_BP_UNLOCK_PAGES(bp, bflag, as, addr, len, pplist)		\
		as_pageunlock((as), (pplist), (addr), (u_int)(len),	\
			      (bflag) == B_READ ? S_WRITE : S_READ)

#define VX_AIODONE_SETUP(aio, uiop, procp, bflag)			\
		(aio)->aio_req_flags |= AIO_ZEROLEN;

/*
 * In 2.7, fs_vcode changed to take a uint instead of a ulong. It's
 * a nop here, but is cast in prior revs.
 */
#define VX_FS_VCODE(v, a)	fs_vcode((v), (a))

/*
 * VX_NBDA: Number of Bytes for Dirent Alignment
 */

#define VX_NBDA	(8 - 1)

/*
 * Lock the list of chained vfs structures.
 */

#define VX_VFSLIST_LOCK()	vfs_list_lock()
#define VX_VFSLIST_UNLOCK()	vfs_list_unlock()

/*
 * Tear down a VFS structure. We do this in our context view code.
 */

#define VX_VFS_DEINIT(vfsp)	sema_destroy(&(vfsp)->vfs_reflock)
#define VX_VFS_REMOVE(vfsp)	vfs_remove(vfsp)

/*
 * Set timeout/untimeout for VX_FREEZE/VX_THAW ioctls.
 */

#define VX_TIMEOUT(fsext, time) {					\
	fsext->fse_timeout = timeout((void (*)(void *))vx_timethaw,	\
				     (void *)fsext, time);		\
}

#define VX_UNTIMEOUT(fsext) {						\
	untimeout(fsext->fse_timeout);					\
}

/*
 * Indirect sysbase and syslimit for x86. For sparc, we get the values
 * from the variables exported by sys/systm.h.
 */

#if #machine(i386)
#define VX_SYSBASE *(u_int *)kobj_getsymvalue("Sysbase", 1)
#define VX_SYSLIMIT *(u_int *)kobj_getsymvalue("Syslimit", 1)
#else
#define VX_SYSBASE kernelheap
#define VX_SYSLIMIT ekernelheap
#endif /* i386 */

#define VX_CMPLDEV(dev, dev32)	(cmpldev(&(dev32), dev))
#define VX_EXPLDEV(dev32, dev)	((dev) = expldev(dev32), 1)

#define VX_MAKE_FSID(fsid, dev, fset_index)				\
		vfs_make_fsid(&(fsid), dev, (int)fset_index)

#define VX_PAGEIO_INIT()
#define VX_PAGEIO_DEINIT()

#define	VX_HAT_PROBE(hat, as, addr)	hat_probe((hat), (addr))
#define VX_HAT_PAGEUNLOAD(pp)		hat_pageunload((pp), HAT_FORCE_PGUNLOAD)
#define VX_HAT_UNLOCK(hat, addr, len)	hat_unlock((hat), (addr), (len))
#define VX_HAT_GETPFNUM(as, addr)	hat_getpfnum((as)->a_hat, (addr))

struct vx_dirdot {
	ino64_t		d_ino;
	off64_t		d_off;
	unsigned short	d_reclen;
	char		d_name[6];
};

struct vx_dirdotdot {
	ino64_t		d_ino;
	off64_t		d_off;
	unsigned short	d_reclen;
	char		d_name[6];
};

extern struct vx_dirdot		vx_dirdot;
extern struct vx_dirdotdot	vx_dirdotdot;

#define VX_LENDIRDOT (sizeof (struct vx_dirdot))
#define VX_LENDIRDOTDOT (sizeof (struct vx_dirdotdot))
#define DIRENTPAD  ((int)((vx_dirent_t *)0)->d_name)

/*
 * VOP_GETATTR on Solaris 2.6 gets an additional flag called as
 * ATTR_REAL.
 */

#define VX_ATTR_REAL	ATTR_REAL

/*
 * OS version specific function prototypes
 */

typedef struct cred	vx_cred_t;

#ifdef _KERNEL

#ifndef __P
#ifdef __STDC__
#define __P(x) x
#else
#define __P(x) ()
#endif
#endif /* __P */

/*
 * functions from vx_solaris.c
 */

extern int	vx_mount __P((struct vfs *, struct vnode *, struct mounta *,
			      struct cred *));
extern int	vx_unmount __P((struct vfs *, struct cred *));
extern int	vx_cview_vunmount __P((struct vfs *, struct cred *));
extern struct vfs	*vx_vfs_devsearch __P((dev_t));
extern int	vx_close __P((struct vnode *, int, int, offset_t,
			      struct cred *));
extern int	vx_create __P((struct vnode *, char *, struct vattr *,
			       enum vcexcl, int, struct vnode **, vx_cred_t *,
			       int));
extern int	vx_mkdir __P((struct vnode *, char *, struct vattr *,
			      struct vnode **, vx_cred_t *));
extern int	vx_frlock __P((struct vnode *, int, struct flock64 *, int,
			       offset_t, struct cred *));
extern int	vx_space __P((struct vnode *, int, struct flock64 *, int,
			      offset_t, struct cred *));
extern int	vx_ioctl __P((struct vnode *, int, intptr_t, int, struct cred *,
			      vx_rval_t *));
extern struct page	*vx_page_find __P((struct vnode *, vx_off_t));
extern struct page	*vx_page_lookup __P((struct vnode *, vx_off_t, int));
extern struct page	*vx_page_lookup_nowait __P((struct vnode *, vx_off_t,
						    int));
extern struct page	*vx_page_create __P((struct vnode *, vx_off_t, u_int,
					     u_int, struct seg *, caddr_t));
extern void	vx_pvn_vplist_dirty __P((struct vnode *, vx_off_t,
					 int (*putapage) (), int,
					 struct cred *));
extern caddr_t	vx_segmap_getmapflt __P((struct vnode *, vx_off_t, vx_size_t,
					 int, int));
extern void	vx_map_addr __P((caddr_t *, vx_size_t, vx_off_t, int));
extern void	vx_set_segvn_args __P((struct segvn_crargs *, struct vnode *,
				       vx_off_t, u_int, u_int, u_int,
				       vx_cred_t *));
extern int	vx_chklock __P((struct vnode *, int, vx_off_t, vx_size_t, int));
extern int	vx_convoff __P((struct vnode *, struct flock64 *, int,
				vx_off_t));
extern int	vx_pageio __P((struct vnode *, struct page *, u_offset_t,
			       size_t, int, vx_cred_t *));
extern struct vx_buf	*vx_pageio_getbp __P((void));
extern void	vx_pageio_freebp __P((struct vx_buf *));
extern int	vx_putinval __P((struct vnode *, struct page *, u_offset_t *,
				 u_int *, int, vx_cred_t *));
extern int	vx_putapage __P((struct vnode *, struct page *, u_offset_t *,
				 vx_size_t *, int, vx_cred_t *));
extern int	vx_pathconf __P((struct vnode *, int, u_long *, struct cred *));
extern int	vx_dumpctl __P((vnode_t *, int));
extern int	vx_bp_lock_pages __P((struct buf *, u_int, struct as *,
				      caddr_t, size_t, struct page ***));

typedef int	(*vx_creatfptr_t)(struct vnode *, char *, struct vattr *,
				   vcexcl_t, int, struct vnode **, vx_cred_t *,
				   int);

#endif /* _KERNEL */

#endif /* _FS_VXFS_VX_SOLARIS_H */
