static char rcsid[] = "$Header: dfs_agent.c,v 820.1 86/12/04 19:44:01 root Exp $";
static char 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.				*
*									*
************************************************************************/

/*
 * DFS agent inode manager
 *
 *	Bakul Shah
 *
 * bvs 840313 -- original version
 * jht 841115,16,26-29 -- complete conversion to use prpc.
 * jht 850215 -- invalidate local cached texts when host goes down.
 */

#include "../h/param.h"
#include "../h/ioctl.h"
#include "../h/dir.h"
#ifdef	QUOTA
#include "../h/quota.h"
#endif	QUOTA
#include "../h/user.h"

#include "../vnet/vnet.h"
#include "../conn/conn.h"
#include "../rpc/rpc.h"
#include "../dfs/dfs.h"

#include "../h/inode.h"
#include "../h/socket.h"
#include "../h/kernel.h"
#include "../net/if.h"
#include "../h/mbuf.h"


/*
 * Create an agent inode for a remote inode
 * A copy of the (locked) remote inode
 * has already been obtained;
 * Returns a ptr to the agent inode for the remote inode.
 */
struct inode *
dfs_mkagent(conn, rp, remote_ip)     /* Ptr to (local) agent for remote inode */
	connection_t	* conn;
	struct	inode	* rp;		/* Ptr to our copy of the remote inode*/
	caddr_t		  remote_ip;	/* Adr of remote inode on remote host */
{
	register struct inode *	ip;
	register dev_t		dev;
	register ino_t		ino;

	dev = *(dev_t *)m_field(rp, &rp->i_dev);
	ino = *(ino_t *)m_field(rp, &rp->i_number);
	ip = iget(dev, NULL, ino, conn);
	if (!ip)
		return NULL;		/* Say "no agent built" */
#ifdef	QUOTA
	/*
	 * Assume that all quotas will be handled
	 * by the kernel where this inode resides.
	 */
	ip->i_dquot = NODQUOT;
#endif	QUOTA
#ifdef	DFS_LOCAL_CACHED_TEXT
	/*
	 * If we have a local cached text and
	 * the remote inode doesn't have the sticky bit turned on,
	 * try to release the cached text.
	 */
	if (ip->i_flag&ITEXT && ip->i_mode&ISVTX) {
		register u_short mode = *(u_short *)m_field(rp, &rp->i_mode);
		if (!(mode&ISVTX))
			xrele(ip);
	}
#endif	DFS_LOCAL_CACHED_TEXT

	/*
	 * Always refresh the agent with
	 * data from the remote inode
	 */
	mbuftoinode(ip, rp);
	ip->i_rmt_ip = remote_ip;
	return ip;
}

/*
 * Release the agent.
 *
 * BUG: dfs_irele() really belongs in ../sys/ufs_inode.c
 * But we dare not put it there until
 * DFS design is cleaned up and fully integrated.
 * Sorry!
 */
dfs_irele(ip)
	register struct inode *ip;
{
	int mode;
	extern struct inode * ifreeh;
	extern struct inode * * ifreet;

	if (ip->i_count == 1) {
		ip->i_flag |= ILOCKED;
		IUNLOCK(ip);
		ip->i_flag = 0;

		if (ip->i_host)	/* "Oh, ye of little faith..." */
		   conn_free(ip->i_host);  /* Undo the conn_link() in iget() */
		/*
		 * Put the inode on the end of the free list.
		 * Possibly in some cases it would be better to
		 * put the inode at the head of the free list,
		 * (eg: where i_mode == 0 || i_number == 0)
		 * but I will think about that later .. kre
		 * (i_number is rarely 0 - only after an i/o error in iget,
		 * where i_mode == 0, the inode will probably be wanted
		 * again soon for an ialloc, so possibly we should keep it)
		 */
		if (ifreeh) {
			*ifreet = ip;
			ip->i_freeb = ifreet;
		} else {
			ifreeh = ip;
			ip->i_freeb = &ifreeh;
		}
		ip->i_freef = NULL;
		ifreet = &ip->i_freef;
	}
	ip->i_count--;
}
