/*
 * Copyright (c) 1989-1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _SYS_FS_TMPNODE_H
#define	_SYS_FS_TMPNODE_H

#pragma ident	"@(#)tmpnode.h	1.26	98/02/04 SMI"

#include <sys/t_lock.h>
#include <vm/seg.h>
#include <vm/seg_vn.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * tmpnode is the file system dependent node for tmpfs.
 *
 *	tn_rwlock protects access of the directory list at tn_dir
 *	as well as syncronizing read and writes to the tmpnode
 *
 *	tn_contents protects growing, shrinking, reading and writing
 *	the file along with tn_rwlock (see below).
 *
 *	tn_tlock protects updates to tn_mode and tn_nlink
 *
 *	tm_contents in the tmount filesystem data structure protects
 *	tn_forw and tn_back which are used to maintain a linked
 *	list of all tmpfs files associated with that file system
 *
 *	The anon array represents the secondary store for tmpfs.
 * 	To grow or shrink the file or fill in holes requires
 *	manipulation of the anon array. These operations are protected
 *	by a combination of tn_rwlock and tn_contents. Growing or shrinking
 * 	the array requires the write lock on tn_rwlock and tn_contents.
 *	Filling in a slot in the array requires the write lock on tn_contents.
 *	Reading the array requires the read lock on tn_contents.
 *
 *	The ordering of the locking is:
 *	tn_rwlock -> tn_contents -> page locks on pages in file
 *
 *	tn_tlock doesn't require any tmpnode locks
 */

struct tmpnode {
	struct tmpnode	*tn_back;		/* linked list of tmpnodes */
	struct tmpnode	*tn_forw;		/* linked list of tmpnodes */
	union {
		struct {
			struct tdirent	*un_dirlist; /* dirent list */
			uint_t	un_dirents;	/* number of dirents */
		} un_dirstruct;
		char 		*un_symlink;	/* pointer to symlink */
		struct {
			struct anon_hdr	*un_anon; /* anon backing for file */
			size_t	un_size;	/* size repres. by array */
		} un_anonstruct;
	} un_tmpnode;
	struct vnode 	tn_vnode;		/* vnode for this tmpnode */
	int 		tn_gen;			/* pseudo gen number for tfid */
	struct vattr	tn_attr;		/* attributes */
	krwlock_t	tn_contents;		/* vm side -serialize mods */
	krwlock_t	tn_rwlock;		/* rw,trunc size - serialize */
						/* mods and directory updates */
	kmutex_t	tn_tlock;		/* time, flag, and nlink lock */
};

#define	tn_dir		un_tmpnode.un_dirstruct.un_dirlist
#define	tn_dirents	un_tmpnode.un_dirstruct.un_dirents
#define	tn_symlink	un_tmpnode.un_symlink
#define	tn_anon		un_tmpnode.un_anonstruct.un_anon
#define	tn_asize	un_tmpnode.un_anonstruct.un_size

/*
 * Attributes
 */
#define	tn_mask		tn_attr.va_mask
#define	tn_type		tn_attr.va_type
#define	tn_mode		tn_attr.va_mode
#define	tn_uid		tn_attr.va_uid
#define	tn_gid		tn_attr.va_gid
#define	tn_fsid		tn_attr.va_fsid
#define	tn_nodeid	tn_attr.va_nodeid
#define	tn_nlink	tn_attr.va_nlink
#define	tn_size		tn_attr.va_size
#define	tn_atime	tn_attr.va_atime
#define	tn_mtime	tn_attr.va_mtime
#define	tn_ctime	tn_attr.va_ctime
#define	tn_rdev		tn_attr.va_rdev
#define	tn_blksize	tn_attr.va_blksize
#define	tn_nblocks	tn_attr.va_nblocks
#define	tn_vcode	tn_attr.va_vcode

/*
 * tmpfs directories are made up of a linked list of tdirent structures
 * hanging off directory tmpnodes.  File names are not fixed length,
 * but are null terminated.
 */
struct tdirent {
	struct tmpnode	*td_tmpnode;		/* tnode for this file */
	struct tdirent	*td_next;		/* next directory entry */
	struct tdirent	*td_prev;		/* prev directory entry */
	uint_t		td_offset;		/* "offset" of dir entry */
	uint_t		td_hash;		/* a hash of td_name */
	struct tdirent	*td_link;		/* linked via the hash table */
	struct tmpnode	*td_parent;		/* parent, dir we are in */
	char		*td_name;		/* must be null terminated */
						/* max length is MAXNAMELEN */
};

/*
 * tfid overlays the fid structure (for VFS_VGET)
 */
struct tfid {
	uint16_t tfid_len;
	ino32_t	tfid_ino;
	int32_t	tfid_gen;
};

#define	ESAME	(-1)		/* trying to rename linked files (special) */

extern struct vnodeops tmp_vnodeops;

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_FS_TMPNODE_H */
