/* @(#)src/common/kernel/base/vx_mlink.h	3.16 07/16/98 14:04:47 -  */
/* #ident "@(#)vxfs:src/common/kernel/base/vx_mlink.h	3.16" */

/*
 * 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_MLINK_H
#define	_FS_VXFS_VX_MLINK_H

/*
 * The mlink structure links asynchronous updates to transactions.
 * The mlinkhd structure is used as a list header, it must match
 * the start of the mlink structure.
 */

struct vx_mlinkhd {
	struct vx_mlink	*ml_forw;	/* forw link of inode/map list */
	struct vx_mlink	*ml_back;	/* back link of inode/map list */
};

struct vx_mlink {
	struct vx_mlink	*ml_forw;	/* forw link of inode/map list */
	struct vx_mlink	*ml_back;	/* back link of inode/map list */
	struct vx_mlink *ml_fsforw;	/* forw link on fs_mlink queue */
	struct vx_mlink *ml_fsback;	/* back link on fs_mlink queue */
	struct vx_tran	*ml_tranp;	/* pointer to tran for mlink */
	vx_u32_t	ml_flag;	/* flag */
	struct vx_fs	*ml_fs;		/* file system structure */
	vx_u32_t	ml_pad;		/* compiler added padding */
	union vx_mlspec {		/* type specific info */
		struct vx_mli {		/* used for VX_MLINODE mlinks */
			struct vx_inode	*mi_ip;	    /* pointer to inode */
		} ml_mli;
		struct vx_mlm {		/* used for VX_MLMAP mlinks */
			struct vx_map	*mm_map;    /* pointer to map */
			struct vx_ctran	*mm_tcp;    /* pointer to ctran */
			struct vx_emtran *mm_emp;   /* pointer to emtran */
		} ml_mlm;
		struct vx_mld {		/* VX_MLDATA and VX_MLNODATA mlinks */
			struct vx_mlinkhd md_link;  /* mlinks for buf */
			struct vx_inode	*md_ip;     /* pointer to inode */
			vx_u32_t	md_len;     /* length of write */
			vx_off_t	md_off;     /* offset of write */
			vx_daddr_t	md_bno;     /* bno of buffer */
			struct vnode	*md_iovp;   /* ptr to io vnode */
		} ml_mld;
		struct vx_mlbh {	/* used for VX_MLBUFHEAD mlinks */
			struct vx_mlinkhd mh_link;  /* mlinks for buf */
			struct vx_inode	*mh_ip;     /* pointer to inode */
			vx_u32_t	mh_len;     /* length of buffer */
			vx_daddr_t	mh_bno;     /* bno of buffer */
			struct vnode	*mh_iovp;   /* ptr to io vnode */
		} ml_mlbh;
		struct vx_mlc {		/* used for VX_MLCUT mlinks */
			struct vx_fset	*mc_fset;   /* pointer to fset */
			struct vx_mlink	*mc_link;   /* mlinks for fset */
			vx_hyper_t	mc_vers;    /* version logged */
			struct vx_cut	*mc_cutp;   /* pointer to cut */
		} ml_mlc;
		struct vx_mll {		/* used for VX_MLLCT mlinks */
			struct vx_lct	*ml_lctp;   /* pointer to lct */
		} ml_mll;
		struct vx_mldq {	/* used for VX_MLDQUOT mlinks */
			struct vx_dquot	*mdq_dquotp; /* ptr to vx_dquot */
		} ml_mldq;
	} ml_ml;
};

#define	mli_ip		ml_ml.ml_mli.mi_ip
#define	mlm_map		ml_ml.ml_mlm.mm_map
#define	mlm_tcp		ml_ml.ml_mlm.mm_tcp
#define	mlm_emp		ml_ml.ml_mlm.mm_emp
#define	mld_link	ml_ml.ml_mld.md_link
#define	mld_ip		ml_ml.ml_mld.md_ip
#define	mld_off		ml_ml.ml_mld.md_off
#define	mld_len		ml_ml.ml_mld.md_len
#define	mld_bno		ml_ml.ml_mld.md_bno
#define	mld_iovp	ml_ml.ml_mld.md_iovp
#define	mlbh_link	ml_ml.ml_mlbh.mh_link
#define	mlbh_ip		ml_ml.ml_mlbh.mh_ip
#define	mlbh_bno	ml_ml.ml_mlbh.mh_bno
#define	mlbh_iovp	ml_ml.ml_mlbh.mh_iovp
#define	mlbh_len	ml_ml.ml_mlbh.mh_len
#define	mlc_fset	ml_ml.ml_mlc.mc_fset
#define	mlc_link	ml_ml.ml_mlc.mc_link
#define	mlc_cutp	ml_ml.ml_mlc.mc_cutp
#define	mlc_vers	ml_ml.ml_mlc.mc_vers
#define	mll_lctp	ml_ml.ml_mll.ml_lctp
#define	mldq_dquotp	ml_ml.ml_mldq.mdq_dquotp

/*
 * values for ml_flag
 */

#define	VX_MLTYPEMASK	0x80ff		/* mask of mlink types */
#define	VX_MLMAP	0x0001		/* mlink is for a map */
#define	VX_MLINODE	0x0002		/* mlink is for an inode */
#define	VX_MLBUFFER	0x0004		/* mlink is for async buffer */
#define	VX_MLBUFHEAD	0x0008		/* mlink is header for async buffer */
#define	VX_MLCUT	0x0010		/* mlink is for a cut structure */
#define	VX_MLLCT	0x0020		/* mlink is for an lct structure */
#define	VX_MLDATA	0x0040		/* mlink is for a logged write */
#define	VX_MLNODATA	0x8000		/* mlink is for a nodata clone write */
#define	VX_MLDQUOT	0x0080		/* mlink is for a vx_dquot structure */
#define	VX_MLAFLUSHED	0x0100		/* async flush attempted on mlink */
#define	VX_MLSFLUSHED	0x0200		/* sync flush attempted on mlink */
#define	VX_MLBFLUSHED	0x0400		/* delbuf flush attempted on mlink */
#define	VX_MLDELAYED	0x1000		/* map changes delayed until log done */
#define	VX_MLFSLIST	0x2000		/* mlink is on fsq list */
#define	VX_MLERROR	0x4000		/* update failed */

/*
 * Add/remove an entry to/from an mlink ml_forw/back list
 */

#define	VX_MLINK_ADD(mlink, nlink) { \
	XTED_MLINK_ADD((mlink), (nlink)); \
	(nlink)->ml_forw = (mlink)->ml_forw; \
	(nlink)->ml_back = (mlink); \
	(mlink)->ml_forw = (nlink); \
	(nlink)->ml_forw->ml_back = (nlink); \
}

#define	VX_MLINK_REM(mlink) { \
	XTED_MLINK_REM(mlink); \
	(mlink)->ml_forw->ml_back = (mlink)->ml_back; \
	(mlink)->ml_back->ml_forw = (mlink)->ml_forw; \
	(mlink)->ml_forw = (mlink); \
	(mlink)->ml_back = (mlink); \
}

#define	VX_MLINK_FSADD(mlink, nlink) { \
	XTED_MLINK_FSADD((mlink), (nlink)); \
	(nlink)->ml_fsforw = (mlink)->ml_fsforw; \
	(nlink)->ml_fsback = (mlink); \
	(mlink)->ml_fsforw = (nlink); \
	(nlink)->ml_fsforw->ml_fsback = (nlink); \
	(nlink)->ml_flag |= VX_MLFSLIST; \
}

#define	VX_MLINK_FSREM(mlink) { \
	XTED_MLINK_FSREM(mlink); \
	(mlink)->ml_fsforw->ml_fsback = (mlink)->ml_fsback; \
	(mlink)->ml_fsback->ml_fsforw = (mlink)->ml_fsforw; \
	(mlink)->ml_fsforw = (mlink); \
	(mlink)->ml_fsback = (mlink); \
	(mlink)->ml_flag &= ~VX_MLFSLIST; \
}

/*
 * Move an mlink chain from one mlinkhd to another.
 */

#define	VX_MLINK_MOVE(ohd, nhd) { \
	XTED_MLINK_MOVE((struct vx_mlink *)&(nhd)); \
	(nhd) = (ohd); \
	(nhd).ml_forw->ml_back = (struct vx_mlink *)&(nhd); \
	(nhd).ml_back->ml_forw = (struct vx_mlink *)&(nhd); \
	(ohd).ml_forw = (struct vx_mlink *)&(ohd); \
	(ohd).ml_back = (struct vx_mlink *)&(ohd); \
}

#endif	/* _FS_VXFS_VX_MLINK_H */
