/*static char *SCCSID = "@(#)eaa.c	6.3 92/01/31";*/
#define BSWAP0 BSWAP0
#include <os2def.h>
#include <bse.h>

#include "heap.h"
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "storage.h"
#include "ea.h"
#include "fnode.h"
#include "volume.h"
#include "tables.h"
#include "pbmacros.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"

#include "pr_debug.h"
#include "pr_alloc.h"
#include "pr_bitmp.h"
#include "pr_ea.h"
#include "pr_cache.h"
#include "pr_heap.h"
#include "pr_misc.h"
#include "pr_read.h"

/*
 ***	EAA - Extend Auxiliary Allocation
 *
 *	EAA is called to extend the non-fnode disk space allocated
 *	to an auxiliary item (EAs and ACLs).  It's much like EFA
 *	except that EFA is heavily used and is optimized for file I/O.
 *	Instead of folding the two together and slowing down EFA
 *	we'll have parallel routines.
 *
 *	Note that as currently implimented, EAA doesn't EXTEND
 *	an allocation, it establishes one.  Upon call, the
 *	supplied ALBLK structure should be empty.
 *
 *	ENTRY	palb = ALBLK structure
 *		lsnFNode = fnode sector #
 *		cbAlloc = # of bytes to allocate
 *
 *	RETURNS (BOOL)
 *		    FALSE if no space
 *
 *	HISTORY
 *	    24-Apr-1989 by John Rogers [JohnRo@Microsoft]
 *		- Changed names of rounding macros in <pbmacros.h>.
 */

BOOL
EAA (PALBLK palb, LSN lsnFNode, USHORT cbAlloc, PFRAME pfrm)
{
    PLRP   plrpEAA;		 /* address of an OFT_LRP format record */
    USHORT csecAlloc;		 /* # of sectors allocated so far */

    USHORT usTry;	    /* run length to try to allocate */
    USHORT usRunLen;	    /* run length which was found */
    USHORT usNewLen;	    /* length left to allocate */
    LSN	   lsnPhys;	    /* physical lsn of the newly found run */

    /*
     * Init local variables
     */

    csecAlloc = 0;
    if ((plrpEAA = (PLRP) GHS(sizeof(LRP),pfrm)) == NULL) {
      return (FALSE);
    }

    /*
     * figure out how many sectors to grow
     */
    usNewLen = SAFE_ROUND_UP_DIV( cbAlloc, SECSIZE );

    if( (pfrm->pvol->csecSpace -= usNewLen) < 0 )
	{
	/*
	 * no space.  Return with error
	 */
/* eaa900: */
	pfrm->pvol->csecSpace += usNewLen;
	RetHeap( plrpEAA );
	return FALSE;
	}

    /*
     * usNewLen (eax) = sectors to grow
     */

/* eaa50: */
    usTry = usNewLen;

    /*
     * usTry	  (eax) = try_amount
     * usNewLen	  (esi) = amount_left
     */

/* eaa62: */
#ifdef DEBUG
    if( usTry == 0 )
	INTERR( "eaa: Ran out of victims before starting!" );
#endif

    for( ; ; )	/* middle logic loop */
	{

/* eaa64: */
	if (!AFB ((ULONG)usTry, lsnFNode, &lsnPhys, pfrm) )
	    {
	    /* Halve try amount and try again */
	    usTry /= 2;
#ifdef DEBUG
	    if( usTry == 0 )
		INTERR( "eaa: Ran out of victims!!!" );
#endif

	    continue;	/* jump back to top of loop */
	    }


	/*
	 * We have an allocation.  If it's not as big as our requested
	 * amount, see how big it can be made.  Its possible, due to
	 * blocks to create new SIBs, that the whole amount is now available.
	 *
	 * usTry    (eax) = size of allocation
	 * lsnPhys  (ebx) = first sector allocated
	 * usNewLen ((TOS)) = request amount
	 */

	if ((usRunLen = usTry) != usNewLen )
	    {
	    ULONG ulTemp;   /* CBR may return a count > 0xffff ? (no!) */
	    if( (ulTemp = CBR(lsnPhys,pfrm)) >= (ULONG) usNewLen )
		{
		usRunLen = usNewLen;
		}
	    else
		{
		usRunLen = (USHORT) ulTemp;
		}
	    }

	/*
	 * We have the size of this block of sectors.  Claim the maps
	 * and then add an extent record
	 *
	 * usRunLen (eax) = size of allocation
	 * lsnPhys  (ebx) = first sector of allocation
	 * usTry    ((TOS)) = try amount
	 * usNewLen ((TOS)+4) = request amount
	 */

/* eaa85: */
	/* subtract amount we got from amount we need */
	usNewLen -= usRunLen;

	/* add sectors back into csecSpace so ClrBit can sub them out again */
	pfrm->pvol->csecSpace += usRunLen;

	/* Clear the bits and mark the bitmap as belonging to this file */
                                                           //#85759
	if (!ClrBit( lsnPhys, (ULONG) usRunLen, TRUE, pfrm ))
     return FALSE;

	LOCKSWAP(&swapASWAP0);
	AddExt( lsnFNode, palb, plrpEAA, pfrm->u.fWrtThru,
		lsnPhys, (LSN) csecAlloc, (ULONG) usRunLen, pfrm );
	UNLOCKSWAP(&swapASWAP0);

	csecAlloc += usRunLen;

	if( usNewLen == 0 )
	    {
	    /* all done */
	    break;
	    }

	/* don't ask for more than needed */
	if( usTry > usNewLen )	     /* or if( be ) continue; */
	    {
	    usTry = usNewLen;
	    }
	}


/* eaa100: */
    /*
     * Completed our allocation.
     *
     * poft (edi) = OFT pointer
     */

    RetHeap( plrpEAA );

    return  TRUE;
}
