/* sccsid[]="%W% %Y% %Q% %G%" */

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

/*
 * Definitions for the Valid Logic Systems
 * Extended File System.
 *
 * jam 840207-21-22-23-28-0409
 * jht 850522 -- rpc, efs, dfs now autoconfigured pseudo-device subsystems.
 * jht 841204-05,07 -- augment EFS with chmod/fchmod, chown/fchown, flock.
 */

#ifndef	NRPC			/* EFS depends directly upon RPC */
#include "../DOT/rpc.h"
#endif

#if	NRPC > 0

#ifndef	VALID_RPC
#define	VALID_RPC		/* Enable the RPC facilities */
#endif

#ifndef	NEFS
#include "../DOT/efs.h"
#endif

#if	NEFS > 0
#ifndef	VALID_EFS
#define	VALID_EFS		/* Enable the EFS facilities */
#endif
#endif	NEFS > 0

#include "../conn/conn.h"	/* For connection_t */

#define EFS_MAXREMOTES	64		/* Maximum remote files open */
#define EFS_MAXLOCALS	64		/* Maximum local files open */

	/* Call request types */

#define EFS_NULL	0
#define EFS_OPEN	1
#define EFS_CLOSE	2
#define EFS_READ	3
#define EFS_WRITE	4
#define EFS_STAT	5
#define EFS_FSTAT	6
#define EFS_CHMOD	7
#define EFS_FCHMOD	8
#define EFS_CHOWN	9
#define EFS_FCHOWN	10
#define EFS_FLOCK	11
#define EFS_BULKREAD	12
#define EFS_BULKWRITE	13
#define EFS_SENDENV	14

#define EFS_PATHSIZE	400		/* Maximum path name length */
#define EFS_WRITESIZE	1024		/* Maximum write data size */
#define EFS_READSIZE	1024		/* Maximum read data size */

	/* Current way to handle network super user */

#define EFS_SU_MOST	1		/* Most nodes are allowed netsu */
#define EFS_SU_FEW	2		/* Only a few nodes are alloes netsu */

#define EFS_SU_TYPE	EFS_SU_FEW	/* Default type of access */
#define EFS_SU_UID	11		/* Default uid for a remote superuser */

/*
 * An efs_localFile structure exists for each
 * file on the local node which has been opened
 * by a remote node.  There is one efs_localFile
 * structure on a network for each efs_remoteFile
 * structure.
 */
typedef struct efs_localFile {
	char		state;		/* Current state of this descriptor */
	connection_t	*conn;		/* Connection to client */
	struct file 	*fp;		/* UNIX file pointer */
	u_long		rfd;		/* Remote file descriptor */
	struct proc	*procp;		/* Process using bulkdata transfer */
	caddr_t		addr;		/* Address of next bulk transfer */
	int		resid;		/* Bytes left in a bulk transfer */
	int		procflags;	/* Flags to set in p_flag */
} efs_localFile_t;

/*
 * An efs_remoteFile structure exists for each
 * file open on a remote node.
 */
typedef struct efs_remoteFile {
	char		state;		/* Current state of this descriptor */
	connection_t	*conn;		/* Connection to server */
	u_long		rfd;		/* Remote file descriptor */
	struct proc	*procp;		/* Process using bulkdata transfer */
	caddr_t		addr;		/* Address of next bulk transfer */
	int		resid;		/* Bytes left in a bulk transfer */
	int		nobulk;		/* Server does not support bulkdata */
	int		procflags;	/* Flags to set in p_flag */
} efs_remoteFile_t;

	/* Values for efs_remoteFile.state and efs_localFile.state */

#define EFS_FILE_FREE		0	/* Descriptor is free */
#define EFS_FILE_OPEN		1	/* File is open on the server */
#define EFS_FILE_CRASHED	2	/* Server for this file has crashed */

typedef struct {
	long	current;	/* Current count for this statistic */
	long	total;		/* Total counts */
	long	maximum;	/* Maximum at any time */
} EFSSTAT;

typedef struct {
	long	server;		/* Number of these calls serviced */
	long	client;		/* Number of these calls requested remotely */
} EFSCALL;

#define efs_incStat(stat) \
	++efs_stats.stat.total; \
	if (++efs_stats.stat.current > efs_stats.stat.maximum) \
		efs_stats.stat.maximum = efs_stats.stat.current;
#define efs_decStat(stat)  --efs_stats.stat.current
#define efs_incServer(stat) ++efs_stats.stat.server
#define efs_incClient(stat) ++efs_stats.stat.client
#define efs_incTotal(stat) ++efs_stats.stat

typedef struct efs_stats {
	EFSSTAT	localFiles;	/* Local files open */
	EFSSTAT	remoteFiles;	/* Remote files open */
	long	localFull;	/* Local file table full */
	long	remoteFull;	/* Local file table full */
	long	remoteCrashes;	/* Remote nodes crashed */
	long	localDropped;	/* Local files dropped due to a crash */
	long	remoteDropped;	/* Remote files dropped due to a crash */
	EFSCALL	opens;		/* Open calls */
	EFSCALL	closes;		/* Close calls */
	EFSCALL	reads;		/* Read calls */
	EFSCALL	writes;		/* Write calls */
	EFSCALL	stats;		/* Stat calls */
	EFSCALL	fstats;		/* Fstat calls */
	EFSCALL	readBytes;	/* Bytes read */
	EFSCALL	writeBytes;	/* Bytes written */
	EFSCALL	chmods;		/* Chmod calls */
	EFSCALL	fchmods;	/* Fchmod calls */
	EFSCALL	chowns;		/* Chown calls */
	EFSCALL	fchowns;	/* Fchown calls */
	EFSCALL	flocks;		/* Flock calls */
} efs_stats_t;

#define efs_isRemoteInode(ip) \
	(((ip)->i_mode & IFMT) == IFCHR && (ip)->i_rdev == efs_dev)
#define efs_isRemoteFile(fp) (efs_isRemoteInode((struct inode *)(fp)->f_data) && (fp)->f_remote)
#define efs_freeRemoteFile(remote)	((remote->conn ? conn_free(remote->conn) : 0), \
					 remote->conn = NULL, \
					 remote->state = EFS_FILE_FREE, \
					 efs_decStat(remoteFiles))
#define efs_freeLocalFile(local)	((local->conn ? conn_free(local->conn) : 0), \
					 local->conn = NULL, \
					 local->state = EFS_FILE_FREE, \
					 efs_decStat(localFiles))
#define efs_makePacket(type,extra) \
	(struct efs_/**/type/**/Call *) \
	    rpc_allocParams(sizeof(struct efs_/**/type/**/Call) + (extra))

#define efs_makeReturnPacket(callPacket,type, extra) \
	(struct efs_/**/type/**/Return *) \
	rpc_allocResults(sizeof(struct efs_/**/type/**/Return) + (extra))

#define efs_call(conn,op,params) \
	prpc_call(&efsClientClass,conn,RPC_CLASS_EFS,op,params)
#define efs_hostLookup(name)	conn_addr(name)

#define efs_data(packet)	((char *)&(packet)[1])

#define EFS_SETJMP() \
	{ \
		label_t efsoldqsave; \
		efsoldqsave = u.u_qsave; \
		if (setjmp(&u.u_qsave)) \
			results->interrupted = 1; \
		else { \
			u.u_eosys = JUSTRETURN;

			/*
			 * The code specific to the function
			 * would go in here, between the SETJMP
			 * and the UNSETJMP.
			 */

#define EFS_UNSETJMP() \
			results->interrupted = 0; \
		} \
		results->junk = 0; \
		results->error = u.u_error; \
		results->eosys = u.u_eosys; \
		u.u_qsave = efsoldqsave; \
	}

#ifdef KERNEL

dev_t	efs_dev;		/* Character device number of the EFS driver */
efs_stats_t efs_stats;		/* Statistics for the EFS */
int	efs_netsutype;		/* Method in which we handle super user */
int	efs_netsuuid;		/* UID to use instead of super user */

extern connection_t *efs_uhostLookup();
extern struct efs_remoteFile *efs_allocRemoteFile();
extern struct efs_localFile *efs_allocLocalFile();
extern struct efs_localFile *efs_rfdToLocal();
extern connection_t *conn_addr();
#ifdef ETERNITY
extern rpc_clientClass_t efsClientClass;
#endif ETERNITY

#endif KERNEL

#else	NRPC > 0

#ifdef	VALID_RPC
#undef	VALID_RPC		/* Disable the RPC facilities */
#endif

#ifdef	VALID_EFS
#undef	VALID_EFS		/* Disable the EFS facilities */
#endif

#endif	NRPC > 0
