/*	@(#)inode.h	13.5 (RC International) 91/12/06	*/

#ifndef _INODE_

#define _INODE_

/*
 *  inode.h -- primary file control block
 *
 *	The I node is the focus of all file activity in UNIX.
 *	There is a unique inode allocated for each active file, each
 *	current directory, each mounted-on file, text file, and the root.
 *	An inode is "named" by its volume/inumber pair.  (iget/iget.c)
 *	Data in icommon is read in from permanent inode on volume.
 *
 *	Not all fields are valid in connection inodes.  The following are
 *	and copied from the original:  i_flag (some fields), i_number, i_UID
 *	i_type, i_timevalid, i_rawdev, i_uid, i_gid, i_mode.  The following 
 *	are valid ONLY in connection inodes: i_fsquid, i_sbbid, i_fcbaddr.  The 
 *	following are valid in the connection inode but are used for its 
 *	local management, not copied from the original: i_flag (some fields), 
 *	i_count, i_forw, i_last_blkno, i_semlock.  All other fileds are invalid.
 */

#include <sys/device.h>
#include <sys/txqueue.h>

#define	NDADDR	8		/* direct addresses in inode */
#define	NIADDR	3		/* indirect addresses in inode */

#define IMAGIC	0x544f5247

/*
 *  inode -- in-memory file control block
 *
 *	access to information in unions is made via "i_xxx" #defines below
 */

struct inode
{
    struct inode	*i_chain[2];	/* must be first */
    struct semaphore 	i_semlock;	/* used for inode locking */
    u_short		i_flag;		/* flags (see below) */
    u_short		i_count;	/* reference count */
    u_short		i_control;	/* no of tr mode opened */
    u_short		i_write;	/* no of normal && write mode opened */
    u_short		i_execute;	/* no of execs on this file */
    ino_t		i_number;	/* i number, 1-to-1 with device addr */
    struct fx		*i_fx;		/* file sys associated with inode */
    struct dquot	*i_dquot;	/* quota struct controlling this file */
    struct fcb		*i_fcbhead;	/* list of connnected remote files */
    UID_T		i_fsuid;	/* recoverable fs id */

    union	/* union of fields not kept when inode is in free list */
    {
    /* if socket: */
	struct socket		*is_socket;
    /* if txipc: */
	struct solicitation	*is_sol;	/* head of lonely hearts list */
    /* if in free list: */
	struct {
	    struct inode  	*if_freef;	/* free list forward */
	    struct inode 	**if_freeb;	/* free list back */
	} i_fr;
    /* if file or logical volume: */
	struct {
	    struct bufhdr	*if_wrlist[6];	/* buffers to write 
							   (see buflinksonly) */
	    daddr_t		if_last_blkno;	/* last accessed */
	    daddr_t		if_last_mapped;	/* last look ahead */
	    short		if_wrlistcount; /* # seq. entries */
	    struct lock		*if_lock;	/*  */
	    struct lock		*if_bytelock;	/*  */
	    int			if_timevalid;	/* validity timestamp */
	    struct fs_blocks	*if_fs_blocks;	/* lv and dir types ONLY */
	} i_flv;
    /* if console message device (/dev/console_message): */
	struct {
	    UID_T		ic_conmsguid;	/* Service queue uid */
	} i_conmsgr;
    /* if communication device (tty, etc.): */
	struct {
	    UID_T		ic_subpuuid;	/* subpu service queue uid */
	} i_commr;
    /* if MXIPC file */
	struct {
	    struct mxipc_info	*im_mxipc;	/* pointer to MXIPC info */
	    u_long		im_states;	/* states */
	    long		im_bytes;	/* # bytes written */
	    long		im_max_bytes;	/* max # bytes written */
	} i_mx;
    /* if FIFO file */
	struct {
	    struct fifo_info	*fi_fifo;	/* Pointer to fifo info */
	    u_short		fi_read;	/* no read mode opened */
	} i_fi;
    } i_un;

    union	/* union of fields kept until inode is reallocated */
    {
    /* if logical volume: */
	struct {
	    struct lv_entry		*il_lep;
	    struct log_status		*il_log;
	    struct intent_buf_hdr	*il_ibhead;	/* intent record buf */
	    struct rwlock		*il_dirlock;	/* dir lock */
	    UID_T			 il_mnt_fsuid;	/* uid of mount point */
	    ino_t			 il_mnt_ino;	/* ino of mount point */
	    ino_t			 il_mnt_dotdot;	/* dotdot */
	    struct mxipc_info		*il_mxipc_head;	/* MXIPC list */
	    logsn_t			 il_lsn;	/* log seq number */
	} ic_lvonly;
    /* if file: */
	struct {
	    struct inode	*if_lvp;	/* ptr to logical vol inode */
	    logsn_t		if_lsn;		/* pre-image log seq number */
	} ic_fonly;
    /* if connection inode */
	struct {
	    UID_T		ic_fsquid;	/* service uid */
	    u_int		ic_sbbid;	/* sbbid of file server */
	    char		*ic_fcbaddr;	/* address of file connection */
	} ic_conly;
    } i_un2;

    struct icommon	/* information present in memory and on disk */
    {
	u_short	ic_mode;	/*  0: mode and type of file */
	short	ic_nlink;	/*  2: number of links to file */
	short	ic_uid;		/*  4: owner's user id */
	short	ic_gid;		/*  6: owner's group id */
	quad	ic_size;	/*  8: number of bytes in file */
	time_t	ic_atime;	/* 16: time last accessed */
	long	ic_atspare;
	time_t	ic_mtime;	/* 24: time last modified */
	long	ic_mtspare;
	time_t	ic_ctime;	/* 32: last time inode changed */
	long	ic_ctspare;
	union {
	    daddr_t	ic_db[NDADDR];	/* 40: disk block addresses */
	    dev_t	ic_rdev;	/* look at raw devices as a whole */
	    struct rawdev
			ic_rawdev;	/* raw devices (disk, tape) */
	    UID_T	ic_UIDval;	/* that which node points to */
	    struct rcomm
	      		ic_comm;	/* communication device */
	    struct rsubpu
			ic_subpu;	/* subpu */
 	    short	ic_unit;	/* rlogin: unit (was minor(dev)) */
	} ic_un;
	daddr_t	ic_ib[NIADDR];	/* 72: indirect blocks */
	long	ic_flags;	/* 84: status */
	long	ic_blocks;	/* 88: blocks actually held */
	UID_T	ic_UID;		/* 92: unique i.d. */
	u_short	ic_type;	/* 100: real type of file */
	u_char	ic_ptier;	/* 102: tier of primary extent */
	u_char	ic_stier;	/* 103: tier of secondary extents */
	long	ic_fnct;	/* 104: find_name count */
	long	ic_fwonct;	/* 108: find_without_name count */
	long	ic_fdsct;	/* 112: fd service count */
	long	ic_spare[2];	/* 116: reserved, currently unused */
	long    ic_magic;	/* 124: inode magic */
    } i_ic;
    u_int	i_syncresult;	/* used to collect errors from async pushes
				 * which accured after last inode sync
				 * (only file and logical vol).
				 */
};

/*
 *  dinode -- inode as it appears on disk
 *
 *	access to components is done via "di_xxx" #defines below
 */

struct dinode
{	
    union
    {
	struct icommon	di_icom;	/* data (see above) */
	char		di_size[128];	/* ensure correct total size */
    } di_un;
};

/* flags */
#define	IUPD		0x0002		/* file has been modified */
#define	IACC		0x0004		/* inode access time to be updated */
#define	IWRT		0x0010		/* inode to be written (no timestamp)*/
#define	IXTND		0x0008		/* file has been extended */
#define	ITEXT		0x0020		/* inode is pure text prototype */
#define	ICHG		0x0040		/* inode has been changed */
#define	ISHLOCK		0x0080		/* file has shared lock */
#define	IEXLOCK		0x0100		/* file has exclusive lock */
#define	ILWAIT		0x0200		/* someone waiting on file lock */
#define	IMORECOMING	0x0400		/* last io indicated more to come */
#define	ISEQ		0x0800		/* last io seemed to be sequential */
#define	IRO		0x1000		/* file not updated since open */
#define	ICONNECTION	0x2000		/* this is connection inode */
#define	ISETTINGUP	0x4000		/* inode being set up */
#define	IAWAITFLUSH	0x8000		/* irele() after dirty */
					/*   block write(s) */

/* types: stored in ic_type */
#define	IFFIFO		0x0001		/* fifo */
#define	IFCHR		0x0002		/* character special */
#define	IFDIR		0x0004		/* directory */
#define	IFBLK		0x0006		/* block special */
#define	IFREG		0x0008		/* regular */
#define	IFLNK		0x000a		/* symbolic link */
#define	IFSOCK		0x000c		/* socket */
#define IFEXT		0x000f		/* extended type (i_mode only) */
/* types added for TX */
#define IFLV		0x0010		/* logical volume (UID-only) */
#define IFFS		0x0011		/* file system mount point */
#define IFIPC		0x0012		/* IPC endpoint */
#define IFDSK		0x0013		/* disk (unbuffered, physical) */
#define IFMT		0x0014		/* mag tape (physical) */
#define IFCOMM		0x0015		/* communication device. */
#define IFLVI		0x0016		/* logical volume (kernel-internal) */
#define	IFCONMSG	0x0017		/* console message device */
#define	IFSUBPU		0x0018		/* subpu */
#define	IFITTY		0x0019		/* indirect tty (for /dev/tty) */
#define	IFINVAL		0x001a		/* not valid (being set up) */
#define	IFERR		0x001b		/* error file (/dev/error) */
#define	IFNULL		0x001c		/* null file (/dev/null) */
#define	IFCONS		0x001d		/* console */
#define	IFPTC		0x001e		/* rlogin: controller (/dev/ptyp?) */
#define	IFPTS		0x001f		/* rlogin: server (/dev/ttyp?) */
#define	IFMIPC		0x0020		/* MXIPC endpoint */

/* modes */
#define	ISUID		0x0800		/* set user id on execution */
#define	IEXECG		0x0008		/* execute permission, group */
#define	ISGID		0x0400		/* set group id on execution */
#define	ISVTX		0x0200		/* save swapped text even after use */
#define	IREAD		0x0100		/* read, write, execute permissions */
#define	IWRITE		0x0080
#define	IEXEC		0x0040

/* extended modes: in ic_flags */
#define ISECURE		0x0001		/* prohibit ordinary UNIX writes */
#define IHISTORY	0x0002		/* maintain a history of data changes */
#define IUNLOCKBLK	0x0004		/* allow release of block locks in
					     a transaction */
#define IENFMT		0x0008		/* enable byte lock enforcement mode */

/* internal flags:  in ic_flags, 16 left-most bits */
#define	IVMCACHE	0x10000		/* may have blks cached by vm system */
#define	IRAWTYPE	0x40000		/* raw type (if on) */

#define	raw_type(ip)	((ip)->i_flags & IRAWTYPE)

/* make access to unionized fields easier (?!?) */
#define	i_mode		i_ic.ic_mode
#define	i_nlink		i_ic.ic_nlink
#define	i_uid		i_ic.ic_uid
#define	i_gid		i_ic.ic_gid
/* ugh! -- must be fixed */
#define	i_size		i_ic.ic_size.val[0]
#define	i_db		i_ic.ic_un.ic_db
#define	i_ib		i_ic.ic_ib
#define	i_atime		i_ic.ic_atime
#define	i_mtime		i_ic.ic_mtime
#define	i_ctime		i_ic.ic_ctime
#define i_flags		i_ic.ic_flags
#define i_blocks	i_ic.ic_blocks
#define i_magic		i_ic.ic_magic
#define	i_rdev		i_ic.ic_un.ic_rdev
#define i_rawdev	i_ic.ic_un.ic_rawdev
#define i_UIDval	i_ic.ic_un.ic_UIDval
#define	i_comm		i_ic.ic_un.ic_comm
#define	i_subpu		i_ic.ic_un.ic_subpu
#define	i_unit		i_ic.ic_un.ic_unit
#define i_lep		i_un2.ic_lvonly.il_lep
#define i_log		i_un2.ic_lvonly.il_log
#define i_ibhead	i_un2.ic_lvonly.il_ibhead
#define i_dirlock	i_un2.ic_lvonly.il_dirlock
#define i_mnt_fsuid	i_un2.ic_lvonly.il_mnt_fsuid
#define i_mnt_ino	i_un2.ic_lvonly.il_mnt_ino
#define i_mnt_dotdot	i_un2.ic_lvonly.il_mnt_dotdot
#define i_mxipc_head	i_un2.ic_lvonly.il_mxipc_head
#define i_llsn		i_un2.ic_lvonly.il_lsn
#define i_mnt		i_mnt_ino
#define i_lvp		i_un2.ic_fonly.if_lvp
#define i_lsn		i_un2.ic_fonly.if_lsn
#define i_fsquid        i_un2.ic_conly.ic_fsquid
#define i_fcbaddr       i_un2.ic_conly.ic_fcbaddr
#define i_sbbid		i_un2.ic_conly.ic_sbbid
#define i_UID		i_ic.ic_UID
#define i_type		i_ic.ic_type
#define i_ptier		i_ic.ic_ptier
#define i_stier		i_ic.ic_stier
#define i_fnct		i_ic.ic_fnct
#define i_fwonct	i_ic.ic_fwonct
#define i_fdsct		i_ic.ic_fdsct
#define	i_last_blkno	i_un.i_flv.if_last_blkno
#define	i_last_mapped	i_un.i_flv.if_last_mapped
#define i_bytelock	i_un.i_flv.if_bytelock
#define	i_wrlist	i_un.i_flv.if_wrlist
#define	i_wrlistcount	i_un.i_flv.if_wrlistcount
#define i_lock		i_un.i_flv.if_lock
#define i_timevalid	i_un.i_flv.if_timevalid
#define i_fs_blocks	i_un.i_flv.if_fs_blocks
#define	i_socket	i_un.is_socket
#define	i_txpcb		i_un.it_txpcb
#define	i_sol		i_un.is_sol
#define	i_forw		i_chain[0]
#define	i_back		i_chain[1]
#define	i_freef		i_un.i_fr.if_freef
#define	i_freeb		i_un.i_fr.if_freeb
#define i_subpuuid	i_un.i_commr.ic_subpuuid
#define i_conmsguid	i_un.i_conmsgr.ic_conmsguid
#define i_mxipc		i_un.i_mx.im_mxipc
#define	i_mxstates	i_un.i_mx.im_states
#define	i_mxbytes	i_un.i_mx.im_bytes
#define	i_mxmax_bytes	i_un.i_mx.im_max_bytes
#define i_fifo		i_un.i_fi.fi_fifo
#define i_read		i_un.i_fi.fi_read

#define di_ic		di_un.di_icom
#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.val[0]
#define	di_db		di_ic.ic_un.ic_db
#define	di_ib		di_ic.ic_ib
#define	di_atime	di_ic.ic_atime
#define	di_mtime	di_ic.ic_mtime
#define	di_ctime	di_ic.ic_ctime
#define	di_rdev		di_ic.ic_un.ic_rdev
#define di_rawdev	di_ic.ic_un.ic_rawdev
#define	di_comm		di_ic.ic_un.ic_comm
#define	di_subpu	di_ic.ic_un.ic_subpu
#define di_UIDval	di_ic.ic_un.ic_UIDval
#define di_ib		di_ic.ic_ib
#define	di_blocks	di_ic.ic_blocks
#define di_flags	di_ic.ic_flags
#define di_type		di_ic.ic_type
#define di_ptier	di_ic.ic_ptier
#define di_stier	di_ic.ic_stier
#define di_UID		di_ic.ic_UID
#define di_fnct		di_ic.ic_fnct
#define di_fwonct	di_ic.ic_fwonct
#define di_fdsct	di_ic.ic_fdsct
#define di_magic	di_ic.ic_magic


#endif _INODE_
