/*static char *SCCSID = "@(#)delsbdir.c	6.2 92/01/31";*/
#define BSWAP1 BSWAP1
#include <os2def.h>

#include "heap.h"
#include "api.h"
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "volume.h"
#include "storage.h"
#include "fnode.h"
#include "tables.h"
#include "pb_ifs.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "find.h"
#include "notify.h"
#include "pbmacros.h"
#include "log.h"
#include "pbmsg.h"
#include "pr_debug.h"
#include "pr_DEL.h"
#include "pr_HEAP.h"
#include "pr_MISC.h"


/*
 ***	DelSBDIR - Delete an SBDIR Entry from the TREE
 *
 *	DelSBDIR is called to delete an SBDIR entry.  The entry must have
 *	no descendants.
 *	It's not enough that we just lock it, since there may be folks
 *	waiting on it and we guarantee that anyone blocking on an SBDIR
 *	finds it still there when they get back!  We must wait on it until
 *	no one else has it held, locked, or is waiting on it.
 *
 *	If the SD_FNDCNT field is non-zero that means that we're in a
 *	find record somewhere.  We gotta locate that record and edit it to
 *	show our absense.
 *
 *	Our caller must have locked a parent directory so that there's no
 *	chance of anyone else editing the entry that we're working on.
 *
 *	Note that DelSBDIR does nothing about the lookaside entries; the
 *	caller should have purged these after locking the parent directory
 *	and before calling DelSBDIR.
 *
 *	ENTRY	psbdDelete (ebx) = address of SBDIR
 *		psbdParent (esi) = address of parent SBDIR
 *
 *	EXIT	None
 *
 *	HISTORY
 *	    19-Sep-89 by JR (John Rogers, JohnRo@Microsoft)
 *		- Avoid warnings from Microsoft C 5.2 (on slash-slash comments).
 *	    14-Oct-1988 17:10 by Bill McJohn [t-billm]
 *					translated from Oct 13 assembly code
 */

void
DelSBDIR (psbdDelete, psbdParent, pfrm)
PSUBDIR psbdDelete;	/*  ptr to SUBDIR to delete	*/
PSUBDIR psbdParent;	/*  ptr to its parent		*/
PFRAME	pfrm;
{
    PFWORK pfwCur;

    if (psbdDelete->bFlags & SDF_PSO) {
	PANIC(PBMSG_DELSBDIR_SDF_PSO);
    }

    if ( (psbdDelete->cusWaiters != 0) ||
	 (psbdDelete->cusHolds != 0) ||
	 (psbdDelete->bFlags != 0) ) {

	/*  The SUBDIR we want to delete is locked or held
	 *  or something.  We set the flags to indicate a
	 *  pending solo lock and block retrying it.
	 *
	 *  We don't have to worry about someone else coming
	 *  in here and grabbing it because the parent is locked.
	 *
	 */

#ifdef DEBUG
	if ( psbdDelete->bFlags & SDF_PSO ) {

	    INTERR ("DelSBDIR:  Two pending solo requests");
	}
#endif

	SetFlagsSBD(psbdDelete, SDF_PSO | SDF_PND);

	do {

	    BlockOnSBD( psbdDelete,pfrm );

	} while ( (psbdDelete->cusHolds != 0) ||
		  (psbdDelete->bFlags != (SDF_PSO | SDF_PND) ) );
    }



    /*	Check to see if there are any finds open against
     *	this SUBDIR.
     */
    if ( psbdDelete->cusFinds != 0 ) {

	/*  There is an active find on this SUBDIR.  Go through
	 *  the find list pruning searches in this directory
	 *  until there are no more to prune.
	 *
	 */
	pfwCur = (PFWORK)(dcpFindListHead.pFwd);

	while ( psbdDelete->cusFinds != 0 ) {

	    if (pfwCur->psbd == psbdDelete) {

		pfwCur->psbd = NULL;
		psbdDelete->cusFinds -= 1;
	    }

#ifdef DEBUG
	    if ( (PVOID)pfwCur == &dcpFindListHead )
		INTERR ("RemSBDIR:  Didn't find all active finds.");
#endif

	    pfwCur = (PFWORK)(pfwCur->dcpWorkList.pFwd);
	}

    }

#ifndef MINIFSD
    NotifyChkRmdir(psbdDelete);
#endif

    /*	psdbDelete has been stripped from the SUBDIR tree.
     *	Unchained it from LRU and return its space to the heap.
     */
    FreeSubdir (psbdDelete);

    return;
    psbdParent; /* Just to satisfy compiler. */

}
