/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:afs.h 12.0$ */
/* $ACIS:afs.h 12.0$ */
/* $Source: /ibm/acis/usr/sys/afs/RCS/afs.h,v $ */

#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsidafs = "$Header:afs.h 12.0$";
#endif

/*
  * AFS system call opcodes
  */
#define	AFSOP_START_R		  0	/* no aux parms */
#define	AFSOP_START_CALLBACK	  1	/* no aux parms */
#define	AFSOP_START_RFTP	  2	/* no aux parms */
#define	AFSOP_START_AFS		  3	/* no aux parms */
#define	AFSOP_START_BKG		  4	/* no aux parms */
#define	AFSOP_ADDCELL		  5	/* parm 2 = cell str */
#define	AFSOP_CACHEINIT		  6	/* parms 2-4 -> cache sizes */
#define	AFSOP_CACHEINFO		  7	/* the cacheinfo file */
#define	AFSOP_VOLUMEINFO	  8	/* the volumeinfo file */
#define	AFSOP_CACHEFILE		  9	/* a random cache file (V*) */
#define	AFSOP_CACHEINODE	 10	/* random cache file by inode */
#define	AFSOP_AFSLOG		 11	/* output log file */
#define	AFSOP_ROOTVOLUME	 12	/* non-standard root volume name */
#define	AFSOP_STARTLOG		 14	/* temporary: Start afs logging */
#define	AFSOP_ENDLOG		 15	/* temporary: End afs logging */
#define	AFSOP_GO		100	/* whether settime is being done */
/* not for initialization: debugging assist */
#define	AFSOP_CHECKLOCKS	200	/* dump lock state */
#define AFSCALL			181

/* generic undefined vice id */
#define	UNDEFVID	    (-1)

/* The basic defines for the Andrew file system
    better keep things powers of two so "& (foo-1)" hack works for masking bits */
#define	VCBS		16	    /* max callbacks per server to queue */
#define	MAXHOSTS	8	    /* max hosts per single volume */
#define	NBRS		10	    /* max number of queued daemon requests */
#define	NUSERS		16	    /* hash table size for unixuser table */
#define	NSERVERS	16	    /* hash table size for server table */
#define	NVOLS		64	    /* hash table size for volume table */
#define	NFENTRIES	256	    /* hash table size for disk volume table */
#define	VCSIZE		128	    /* stat cache hash table size */
#define	DCSIZE		64	    /* disk cache hash table size */
#define	PIGGYSIZE	1350	    /* max piggyback size */
#define	MAXVOLS		50	    /* max vols we can store */
#define	MAXMULTI	3	    /* max conns per single user/fs pair */
#define	TOKENTIMEOUT	(26*3600)   /* time after which to timeout conns with tokens */
#define	NOTOKTIMEOUT	(2*3600)    /* time after which to timeout conns sans tokens */

/* below here used only for kernel procedures */
#ifdef KERNEL
/* background request structure */
#define	BPARMS		4

#define	BOP_NOOP	0	    /* leave 0 unused */
#define	BOP_FETCH	1	    /* parm1 is chunk to get */
#define	BOP_STORE	2	    /* parm1 is chunk to store */

/* protocol is: refCount is incremented by user to take block out of free pool.
    Next, BSTARTED is set when daemon finds request.  This prevents
    other daemons from picking up the same request.  Finally, when
    request is done, refCount is zeroed.  BDONE and BWAIT are used by
    dudes waiting for operation to proceed to a certain point before returning.
*/
#define	BSTARTED	1	    /* request picked up by a daemon */
#define	BUVALID		2	    /* code is valid (store) */
#define	BUWAIT		4	    /* someone is waiting for BUVALID */
struct brequest {
    struct vcache *vnode;	    /* vnode to use, with vrefcount bumped */
    struct ucred *cred;		    /* credentials to use for operation */
    long parm[BPARMS];		    /* random parameters */
    long code;			    /* return code */
    short refCount;		    /* use counter for this structure */
    char opcode;		    /* what to do (store, fetch, etc) */
    char flags;			    /* free, etc */
};

struct SecretToken {
    char data[56];
};

struct ClearToken {
	long AuthHandle;
	char HandShakeKey[8];
	long ViceId;
	long BeginTimestamp;
	long EndTimestamp;
};

struct VenusFid {
    long Cell;			    /* better sun packing if at end of structure */
    struct ViceFid Fid;
};

struct vrequest {
    long uid;			/* user id making the request */
    long busyCount;		/* how many busies we've seen so far */
    char initd;			/* if non-zero, non-uid fields meaningful */
    char accessError;		/* flags for overriding error return code */
    char volumeError;		/* encountered a missing volume */
    char networkError;		/* encountered network problems */
};

#define	LOCALCELL	    1	/* local cell's number is always 1 */

#define	CPrimary	    1	    /* on if this is the primary cell */
struct cell {
    struct cell *next;
    long cell;				    /* unique id assigned by venus */
    char *cellName;			    /* char string name of cell */
    struct server *cellHosts[MAXHOSTS];	    /* volume *location* hosts for this cell */
    short states;			    /* state flags */
};

/* the unixuser flag bit definitions */
#define	UHasTokens	1	    /* are the st and ct fields valid (ever set)? */
#define	UTokensBad	2	    /* are tokens bad? */

struct unixuser {
    struct unixuser *next;	    /* next hash pointer */
    long uid;			    /* search based on uid and cell */
    long cell;
    long vid;			    /* corresponding vice id in specified cell */
    short refCount;		    /* reference count for allocation */
    char states;		    /* flag info */
    char primary;		    /* true iff primary identity */
    long tokenTime;		    /* last time tokens were set, used for timing out conn data */
    struct SecretToken st;	    /* the tokens */
    struct ClearToken ct;
};

struct conn {
    /* Per-connection block. */
    struct conn	*next;		    /* Next dude same server. */
    struct lock	lock;		    /* lock */
    struct unixuser *user;	    /* user validated with respect to. */
    struct r_connection	*id;	    /* RPC connid. */
    struct server *server;	    /* server associated with this conn */
    short refCount;		    /* reference count for allocation */
    char tag;			    /* which conn for this this is */
    char forceConnectFS;	    /* Should we try again with these tokens? */
};

/*
  * Queues implemented with both pointers and short offsets into a disk file.
  */
struct afs_q {
    struct afs_q *next;
    struct afs_q *prev;
};

struct afs_sq {
    short next;
    short prev;
};

#define SQNULL -1

/* Fid comparison routines */
#define	FidCmp(a,b) ((a)->Fid.Unique != (b)->Fid.Unique \
    || (a)->Fid.Vnode != (b)->Fid.Vnode \
    || (a)->Fid.Volume != (b)->Fid.Volume \
    || (a)->Cell != (b)->Cell)

/*
  * Operations on circular queues implemented with pointers.  Note: these queue objects are
  * always located at the beginning of the structures they are linking.
  */
#define	QInit(q)    ((q)->prev = (q)->next = (q))
#define	QAdd(q,e)   ((e)->next = (q)->next, (e)->prev = (q), \
			(q)->next->prev = (e), (q)->next = (e))
#define	QRemove(e)  ((e)->next->prev = (e)->prev, (e)->prev->next = (e)->next)
#define	QNext(e)    ((e)->next)
#define QPrev(e)    ((e)->prev)
/* do lots of address arithmetic to go from lruq to the base of the vcache structure.
      Don't move struct vnode, since we think of a struct vcache as a specialization
      of a struct vnode */
#define	QTOV(e)	    ((struct vcache *)(((char *) (e)) - (((char *)(&(((struct vcache *)(e))->lruq))) - ((char *)(e)))))

/*
  * Operations on circular dcache queues implemented with short file offsets.  Note: these queue
  * objects are never located at the beginning of the structures they are linking, so we always
  * need to provide the queue's name in the dcache record.
  */
#define	sQInit(q)		((q).next = (q).prev = SQNULL)
#define	sQAdd(q, qname, eidx)	(Fill this in)
#define	sQRemove(q, qname, eidx)	(Fill this in)
#define	sQNext(qname, eidx, nextidx)	(Fill this in)
#define	sQPrev(qname, eidx, previdx)	(Fill this in)

struct server {
    struct server *next;
    struct cell	*cell;		    /* cell in which this host resides */
    struct conn	*conns;		    /* all user connections to this server */
    struct ViceFid vcbs[VCBS];
    long host;			    /* in network byte order, except subsys */
    long portal;		    /* in network byte order */
    long subsys;		    /* in host order */
    long creatingVol;		    /* vol whose reference created this struct */
    char isDown;		    /* result of decision if server is down. */
    char vcbCount;		    /* count of vcbs */
};

/* state bits for volume */
#define VRO			1		/* volume is readonly */
#define VRecheck		2		/* recheck volume info with server */
#define	VBackup			4		/* is this a backup volume? */
#define	VSearched		8		/* checked fvol table for .. info yet? */

struct volume {
    /* One structure per volume, describing where the volume is located
	  and where its mount points are. */
    struct volume *next;	/* Next volume in hash list. */
    long cell;			/* the cell in which the volume resides */
    struct lock	lock;		/* the lock for this structure */
    long volume;		/* This volume's ID number. */
    char *name;			/* This volume's name, or 0 if unknown */
    struct server *serverHost[MAXHOSTS];    /* servers serving this volume */
    struct VenusFid dotdot;	/* dir to access as .. */
    struct VenusFid mtpoint;	/* The mount point for this volume. */
    long roVol;
    long backVol;
    long rwVol;			/* For r/o vols, original read/write volume. */
    long accessTime;		/* last time we used it */
    long vtix;			/* volume table index */
    short refCount;		/* reference count for allocation */
    char states;		/* snuck here for alignment reasons */
};

/* format of an entry in volume info file */
struct fvolume {
    long cell;			/* cell for this entry */
    long volume;		/* volume */
    long next;			/* has index */
    struct VenusFid dotdot;	/* .. value */
    struct VenusFid mtpoint;	/* mt point's fid */
};

/* vcache state bits */
#define	CStatd	    1		/* has this file ever been stat'd? */
#define	CDeleted    2		/* has this file been deleted? (UNUSED) */
#define	CRO	    4		/* is it on a read-only volume */
#define	CMValid	    8		/* is the mount point info valid? */
#define	CCore	    0x10	/* storing a core file, needed since we don't get an open */
#define	CDataMod    0x20	/* data was modified >= 1 time after fetched into this vnode */
#define	CSafeStore  0x40	/* close must wait for store to finish (should be in fd) */

#define	CPSIZE	    2
#define	vrefCount   v.v_count

struct vcache {
    struct vnode v;			/* Has reference count in v.v_count */
    struct afs_q lruq;			/* lru q next and prev */
    struct vcache *hnext;		/* Hash next */
    struct VenusFid fid;
    struct mstat {
        long Length;
        long DataVersion;
        long Date;
        long Owner;
        short Mode;
        unsigned char LinkCount;
	/* vnode type is in v.v_type */
    } m;
    struct lock	lock;			/* The lock on the vcache contents. */
    long parentVnode;			/* Parent dir, if a file. */
    long parentUnique;
    struct VenusFid *mvid;		/* Either parent dir (if root) or root (if mt pt) */
    char *linkData;			/* Link data if a symlink. */
    long randomUid[CPSIZE];		/* random users' ids and access rights. */
    long callback;			/* The callback host, if any */
    long cbExpires;			/* time the callback expires */
    short opens;			/* The numbers of opens, read or write, on this file. */
    short execsOrWriters;		/* The number of execs (if < 0) or writers (if > 0) of
					 this file. */
    short flockCount;			/* count of flock readers, or -1 if writer */
    unsigned char chunkShift;		/* log chunksize in bytes */
    char randomAccess[CPSIZE];		/* watch for more rights in prs_fs.h */
    char anyAccess;			/* System:AnyUser's access to this. */
    char mvstat;			/* 0->normal, 1->mt pt, 2->root. */
    char states;			/* state bits */
};

/*----------------------------------------------------------------------
 * AFS Data cache definitions
 *
 * Each entry describes a Unix file on the local disk that is
 * is serving as a cached copy of all or part of a Vice file.
 * Entries live in circular queues for each hash table slot
 *
 * Which queue is this thing in?  Good question.
 * A struct dcache entry is in the freeDSlot queue when not associated with a cache slot (file).
 * Otherwise, it is in the DLRU queue.  The freeDSlot queue uses the lruq.next field as
 * its "next" pointer.
 *
 * Cache entries in the DLRU queue are either associated with vice files, in which case
 * they are hashed by hvNextp and hcNextp pointers, or they are in the freeDCList
 * and are not associated with any vice file.  This last list uses the hvNextp pointer for
 * its "next" pointer.
 *
 * Note that the DLRU and freeDSlot queues are *memory* queues, while the hvNextp and
 * hcNextp hash lists and the freeDCList all go through the disk elements.  Think of the
 * memory queues as lower-level queues caching a number of the disk entries.
 *----------------------------------------------------------------------*/

#define	NULLIDX	    (-1)	/* null index definition */
/* struct dcache states bits */
#define	DDataMod    1		/* Data modified */
#define	DEntryMod   2		/* Entry itself modified */
#define	DHeadChunk  4		/* entry is head chunk; in hvNextp list */
#define	DWriting    8		/* file being written (used for cache validation) */
#define	DFetching   0x10	/* file is currently being fetched */
#define	DWaiting    0x20	/* someone waiting for file */
#define	DFetchReq   0x40	/* someone is waiting for DFetching to go on */

/* flags in afs_indexFlags array */
#define	IFEverUsed	1		/* index entry has >= 1 byte of data */
#define	IFFree		2		/* index entry in freeDCList */
#define	IFDataMod	4		/* file needs to be written out */

struct afs_ioctl {
	caddr_t in, out;	/* Data to be transferred in, or out */
	short in_size;		/* Size of input buffer <= 2K */
	short out_size;		/* Maximum size of output buffer, <= 2K */
};

struct fcache {
    short hvNextp;		/* Next in vnode hash table, or freeDCList */
    short hcNextp;		/* Next index in [fid, chunk] hash table */
    short chunkNextp;		/* File queue of all chunks for a single vnode */
    struct VenusFid fid;	/* Fid for this file */
    long modTime;		/* last time this entry was modified */
    long versionNo;		/* Associated data version number */
    long chunk;			/* Relative chunk number */
    long inode;			/* Unix inode for this chunk */
    long chunkBytes;		/* Num bytes in this chunk */
    char states;		/* Has this chunk been modified? */
};

struct dcache {
    struct afs_q lruq;		/* Free queue for in-memory images */
    short refCount;		/* Associated reference count. */
    short index;		/* The index in the CacheInfo file*/
    long validPos;		/* number of valid bytes during fetch */
    struct fcache f;		/* disk image */
};

#define DCHASHSIZE 1024
#define DVHASHSIZE 1024
/* The PFlush algorithm makes use of the fact that Fid.Unique is not used in
  below hash algorithms.  Change it if need be so that flushing algorithm
  doesn't move things from one hash chain to another
*/
#define	DCHash(v, c)	((((v)->Fid.Vnode + (v)->Fid.Volume + (c))) & (DCHASHSIZE-1))
	/*Vnode, Chunk -> Hash table index*/
#define	DVHash(v)	((((v)->Fid.Vnode + (v)->Fid.Volume )) & (DVHASHSIZE-1))
	/*Vnode -> Other hash table index*/
/* don't hash on the cell, our callback-breaking code sometimes fails to compute
    the cell correctly, and only scans one hash bucket */
#define	VCHash(fid)	(((fid)->Fid.Volume + (fid)->Fid.Vnode) & (VCSIZE-1))

extern short afs_dvhashTable[DVHASHSIZE];	/*Data cache hash table (on vnodes)*/
extern short afs_dchashTable[DCHASHSIZE];	/*Ditto, on [fid, chunk]*/
extern struct dcache **afs_indexTable;		/*Pointers to in-memory dcache entries*/
extern long afs_cacheFiles;			/*Size of afs_indexTable*/
extern long afs_cacheBlocks;			/*1K blocks in cache*/
extern long afs_cacheStats;			/*Stat entries in cache*/
extern struct vcache *afs_vhashTable[VCSIZE];	/*Stat cache hash table*/
extern long afs_initState;			/*Initialization state*/
extern struct VenusFid afs_rootFid;		/*Root for whole file system*/
extern long afs_missedCBs;			/*Count of missed callbacks*/
extern struct brequest afs_brs[NBRS];		/* request structures */

#define	UHash(auid)	((auid) & (NUSERS-1))
#define	VHash(avol)	((avol)&(NVOLS-1))
#define	SHash(aserv)	((aserv) & (NSERVERS-1))
#define	FVHash(acell,avol)  (((avol)+(acell)) & (NFENTRIES-1))

extern long dc_sync();
    /* Args:
         *	    vnode *vp		vnode whose pages must be flushed
         *
         */

extern long dc_init();
    /*
        * Args:
        *	None.
        */

extern long dc_xfer();
    /*
         * Args:
         *	vnode *vp		Ptr to vnode involved.
         *	struct uio *uio		transfer info cntg positions and lengths of buffer and file
         *	enum uio_rw reading	UIO_READ and UIO_WRITE
         */

extern struct cell	    *afs_GetCell();
extern struct cell	    *afs_GetCellByName();
extern struct unixuser	    *afs_GetUser();
extern struct volume	    *afs_GetVolume();
extern struct volume	    *afs_GetVolumeByName();
extern struct conn	    *afs_Conn();
extern struct conn	    *afs_ConnByHost();
extern struct conn	    *afs_ConnByMHosts();
extern struct server	    *afs_GetServer();
extern struct cell	    *afs_NewCell();
extern struct dcache	    *afs_GetDCache();
extern struct dcache	    *afs_FindDCache();
extern struct dcache	    *afs_NewDCache();
extern struct dcache	    *afs_GetDSlot();
extern struct vcache	    *afs_GetVCache();
extern struct brequest	    *afs_BQueue();
#endif KERNEL
