rtfsprorelease/rtfscommon/source/rtleakcheck.c
2016-06-05 16:09:54 -04:00

565 lines
19 KiB
C

/*
* rtleakcheck.c - Check for leaks
*
* ERTFS portable process management and other functions.
* This file is portable but it requires interaction with the
* porting layer functions in portrtfs.c.
*
* Copyright EBS Inc. 1987-2003
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*
*/
#include "rtfs.h"
#if (INCLUDE_DEBUG_LEAK_CHECKING)
static void pc_lk_print_check(struct mem_report *preport);
#define ARGTYPE_DROBJ 1
#define ARGTYPE_FINODE 2
#define ARGTYPE_FILEBUFFER 3
#define ARGTYPE_REGION 4
#define ARGTYPE_FINODE_UEX 5
static BOOLEAN pc_lk_drive_in_freelist(DDRIVE *pdr);
static BOOLEAN pc_lk_drive_in_map(DDRIVE *pdr);
static BOOLEAN pc_lk_drobj_in_freelist(DROBJ *pobj);
static BOOLEAN pc_lk_drobj_in_file(DROBJ *pobj);
static BOOLEAN pc_lk_drobj_in_user(DROBJ *pobj);
static BOOLEAN pc_lk_finode_in_list(FINODE *plist, FINODE *p);
static BOOLEAN pc_lk_finode_in_freelist(FINODE *p);
static BOOLEAN pc_lk_finode_in_pool(FINODE *p);
static BOOLEAN pc_lk_finode_in_finode(FINODE *finode, void *p, int argtype);
static int pc_lk_finode_in_drobj(void *p, int argtype);
#if (INCLUDE_RTFS_PROPLUS) /* config structure: ProPlus specific element*/
static BOOLEAN pc_lk_finode_uex_in_freelist(FINODE_EXTENSION_MEMORY *p);
#endif
static BOOLEAN pc_lk_blkbuff_inlist(BLKBUFF *plist, BLKBUFF *pbuff);
static BOOLEAN pc_lk_blkbuff_in_freelist(BLKBUFFCNTXT *pbuffcntxt, BLKBUFF *pbuff);
static BOOLEAN pc_lk_blkbuff_in_filebuffer(BLKBUFF *pbuff);
static BOOLEAN pc_lk_blkbuff_in_dirbuffer(BLKBUFFCNTXT *pbuffcntxt, BLKBUFF *pbuff);
static BOOLEAN pc_lk_blkbuff_in_scratchbuffer(BLKBUFFCNTXT *pbuffcntxt, BLKBUFF *pbuff);
static BOOLEAN pc_lk_rgnbuff_in_list(struct region_fragment *plist, struct region_fragment *prgnbuff);
static BOOLEAN pc_lk_rgnbuff_in_freelist(struct region_fragment *prgnbuff);
static BOOLEAN pc_lk_rgnbuff_in_file(struct region_fragment *prgnbuff);
static BOOLEAN pc_lk_rgnbuff_in_freemap(struct region_fragment *prgnbuff);
static BOOLEAN pc_lk_rgnbuff_in_failsafe(struct region_fragment *prgnbuff);
static void pc_lk_fatbuff_check(DDRIVE *pdrive,struct mem_report *preport);
void pc_leak_test(struct mem_report * preport);
/* Check drive structures should either be on free list or in drive map */
void pc_leak_test(struct mem_report * preport)
{
rtfs_memset((byte *)preport, 0, sizeof(struct mem_report));
/* Check drive structures */
{
int i;
DDRIVE *pdr;
pdr = prtfs_cfg->mem_drive_pool;
preport->ndrives_configured = prtfs_cfg->cfg_NDRIVES;
for (i = 0; i < prtfs_cfg->cfg_NDRIVES; i++, pdr++)
{
if (pc_lk_drive_in_freelist(pdr))
preport->ndrives_free += 1;
else if (pc_lk_drive_in_map(pdr))
preport->ndrives_mapped += 1;
else
preport->ndrives_lost += 1;
}
}
/* Check drobj structures, should be in file pool, free list or in current working directories */
{
int i;
DROBJ *pobj;
pobj = prtfs_cfg->mem_drobj_pool;
preport->ndrobjs_configured = prtfs_cfg->cfg_NDROBJS;
for (i = 0; i < prtfs_cfg->cfg_NDROBJS; i++, pobj++)
{
if (pc_lk_drobj_in_freelist(pobj))
preport->ndrobjs_free +=1;
else if (pc_lk_drobj_in_file(pobj))
preport->ndrobjs_in_files +=1;
else if (pc_lk_drobj_in_user(pobj))
preport->ndrobjs_in_users +=1;
else
preport->ndrobjs_lost += 1;
}
}
/* Check finodes structures, DROBJ structures, on free list or in the inode pool. If in the INODE pool and not
In a DROBJ it should have a zero open count */
{
int i,finode_reference_count;
FINODE *pfinode;
pfinode = prtfs_cfg->mem_finode_pool;
preport->nfinodes_configured = prtfs_cfg->cfg_NFINODES;
for (i = 0; i < prtfs_cfg->cfg_NFINODES; i++, pfinode++)
{
if (pc_lk_finode_in_freelist(pfinode))
preport->nfinodes_free += 1;
else if (pc_lk_finode_in_pool(pfinode))
{
preport->nfinodes_in_pool += 1;
finode_reference_count = pc_lk_finode_in_drobj((void *)pfinode,ARGTYPE_FINODE);
if (finode_reference_count)
preport->nfinodes_in_drobj += 1;
if (pfinode->opencount != finode_reference_count)
preport->nfinodes_reference_errors += 1;
}
else
preport->nfinodes_lost += 1;
}
}
#if (INCLUDE_RTFS_PROPLUS) /* config structure: ProPlus specific element*/
/* Check extended finodes structures */
{
int i;
FINODE_EXTENSION_MEMORY *pfiuex;
pfiuex = prtfs_cfg->mem_finode_uex_pool;
preport->nfinodeex64_configured = 0;
preport->nfinodeex_configured = prtfs_cfg->cfg_NFINODES_UEX;
for (i = 0; i < prtfs_cfg->cfg_NFINODES_UEX; i++, pfiuex++)
{
if (pc_lk_finode_uex_in_freelist(pfiuex))
preport->nfinodeex_free += 1;
else if (pc_lk_finode_in_drobj((void *)pfiuex,ARGTYPE_FINODE_UEX) == 0)
preport->nfinodeex_lost += 1;
}
}
#endif /* #if (INCLUDE_RTFS_PROPLUS) */
/* Check shared block buffer pool */
{
int i;
BLKBUFF *pbuff;
pbuff = prtfs_cfg->mem_block_pool;
preport->nglblkbuff_configured = prtfs_cfg->cfg_NBLKBUFFS;
for (i = 0; i < prtfs_cfg->cfg_NBLKBUFFS; i++, pbuff++)
{
if (pc_lk_blkbuff_in_freelist(&prtfs_cfg->buffcntxt, pbuff))
preport->nglblkbuff_free += 1;
else if (pc_lk_blkbuff_in_filebuffer(pbuff)) /* Must be called before scratch */
preport->nglblkbuff_in_filebuff += 1;
else if (pc_lk_blkbuff_in_dirbuffer(&prtfs_cfg->buffcntxt, pbuff))
preport->nglblkbuff_in_dirbuff += 1;
else if (pc_lk_blkbuff_in_scratchbuffer(&prtfs_cfg->buffcntxt, pbuff))
preport->nglblkbuff_in_scratchbuff += 1;
else
preport->nglblkbuff_lost += 1;
}
}
/* Check region structures */
{
int i;
struct region_fragment *prgnbuff;
prgnbuff = prtfs_cfg->mem_region_pool;
preport->nrgnbuff_configured = prtfs_cfg->cfg_NREGIONS;
for (i = 0; i < prtfs_cfg->cfg_NREGIONS; i++, prgnbuff++)
{
if (pc_lk_rgnbuff_in_freelist(prgnbuff))
preport->nrgnbuff_free += 1;
else if (pc_lk_rgnbuff_in_file(prgnbuff))
preport->nrgnbuff_in_files += 1;
else if (pc_lk_rgnbuff_in_freemap(prgnbuff))
preport->nrgnbuff_in_freemap += 1;
else if (pc_lk_rgnbuff_in_failsafe(prgnbuff))
preport->nrgnbuff_in_failsafe += 1;
else
preport->nrgnbuff_lost += 1;
}
}
/* Check user structures */
{
int i;
preport->nusers_configured = prtfs_cfg->cfg_NUM_USERS;
for (i = 0; i < prtfs_cfg->cfg_NUM_USERS; i++)
{
if (prtfs_cfg->rtfs_user_table[i].task_handle==0)
preport->nusers_free += 1;
}
}
/* Check files structures */
{
int i;
preport->nfiles_configured = prtfs_cfg->cfg_NUSERFILES;
for (i = 0; i < prtfs_cfg->cfg_NUSERFILES; i++)
{
if (prtfs_cfg->mem_file_pool[i].is_free)
preport->nfiles_free += 1;
}
}
/* Check fat buffer structures */
{
int i;
DDRIVE *pdr;
pdr = prtfs_cfg->mem_drive_pool;
for (i = 0; i < prtfs_cfg->cfg_NDRIVES; i++, pdr++)
{
if (pc_lk_drive_in_map(pdr))
pc_lk_fatbuff_check(pdr, preport);
}
}
/* Add up all lost fields, will be zero if none lost */
preport->lost_count =
preport->ndrives_lost +
preport->ndrobjs_lost +
preport->nfinodes_lost +
preport->nfinodeex_lost +
preport->nfinodeex64_lost +
preport->nglblkbuff_lost +
preport->nfatbuff_lost +
preport->nrgnbuff_lost;
pc_lk_print_check(preport);
}
static BOOLEAN pc_lk_drive_in_freelist(DDRIVE *pdr)
{
DDRIVE *lpdr;
int i = 0;
lpdr = prtfs_cfg->mem_drive_freelist;
while (lpdr && i++ <= prtfs_cfg->cfg_NDRIVES)
{
if (lpdr == pdr)
return(TRUE);
lpdr = lpdr->pnext_free;
}
return(FALSE);
}
static BOOLEAN pc_lk_drive_in_map(DDRIVE *pdr)
{
int i;
for (i = 0; i < 26; i++)
if (pdr == prtfs_cfg->drno_to_dr_map[i])
return(TRUE);
return(FALSE);
}
static BOOLEAN pc_lk_drobj_in_freelist(DROBJ *pobj)
{
DROBJ *scanobj;
int i = 0;
scanobj = prtfs_cfg->mem_drobj_freelist;
while (scanobj)
{
if (scanobj == pobj)
return(TRUE);
scanobj = (DROBJ *) scanobj->pdrive; /* Acts as pnext on the free list */
if (i++ > prtfs_cfg->cfg_NDROBJS)
return(FALSE);
}
return(FALSE);
}
static BOOLEAN pc_lk_drobj_in_file(DROBJ *pobj)
{
int i;
for (i = 0; i < prtfs_cfg->cfg_NUSERFILES; i++)
{
if (!prtfs_cfg->mem_file_pool[i].is_free)
{
if (prtfs_cfg->mem_file_pool[i].pobj == pobj)
return(TRUE);
}
}
return(FALSE);
}
static BOOLEAN pc_lk_drobj_in_user(DROBJ *pobj)
{
int i,j;
for (i = 0; i < prtfs_cfg->cfg_NUM_USERS; i++)
{
if (prtfs_cfg->rtfs_user_table[i].task_handle)
{
for (j = 0; j < 26; j++)
{
if (pobj == rtfs_get_user_pwd(&prtfs_cfg->rtfs_user_table[i], j, FALSE))
return(TRUE);
}
}
}
return(FALSE);
}
static BOOLEAN pc_lk_finode_in_list(FINODE *plist, FINODE *p)
{
int i = 0;
FINODE *scannode;
scannode = plist;
while (scannode)
{
if (scannode == p)
return(TRUE);
scannode = scannode->pnext;
if (i++ > prtfs_cfg->cfg_NFINODES)
return(FALSE);
}
return(FALSE);
}
static BOOLEAN pc_lk_finode_in_freelist(FINODE *p)
{
return(pc_lk_finode_in_list(prtfs_cfg->mem_finode_freelist, p));
}
static BOOLEAN pc_lk_finode_in_pool(FINODE *p)
{
return(pc_lk_finode_in_list(prtfs_cfg->inoroot, p));
}
static BOOLEAN pc_lk_rgnbuff_in_list(struct region_fragment *plist, struct region_fragment *prgnbuff);
static BOOLEAN pc_lk_finode_in_finode(FINODE *finode, void *p, int argtype)
{
if (argtype == ARGTYPE_FINODE && finode == (FINODE *) p)
return(TRUE);
#if (INCLUDE_RTFS_PROPLUS)
if (argtype == ARGTYPE_FINODE_UEX && finode->e.x == (FINODE_EXTENDED *) p)
return(TRUE);
if (argtype == ARGTYPE_REGION && finode->e.x)
{
if (pc_lk_rgnbuff_in_list(finode->e.x->pfirst_fragment, (struct region_fragment *)p))
return(TRUE);
if (pc_lk_rgnbuff_in_list(finode->e.x->ptofree_fragment, (struct region_fragment *)p))
return(TRUE);
}
#endif
return(FALSE);
}
static int pc_lk_finode_in_drobj(void *p, int argtype)
{
int i, hit_count;
DROBJ *pobj;
pobj = prtfs_cfg->mem_drobj_pool;
hit_count = 0;
for (i = 0; i < prtfs_cfg->cfg_NDROBJS; i++, pobj++)
{
if (!pc_lk_drobj_in_freelist(pobj))
{
if (argtype == ARGTYPE_FINODE && pobj->finode == (FINODE *)p) /* See if it is the finode linked to a drobj for a directory entry or file */
hit_count += 1;
else if (pc_lk_finode_in_finode(pobj->finode, p, argtype)) /* See if it is a child of the finode */
hit_count += 1;
}
}
return(hit_count);
}
#if (INCLUDE_RTFS_PROPLUS) /* config structure: ProPlus specific element*/
static BOOLEAN pc_lk_finode_uex_in_freelist(FINODE_EXTENSION_MEMORY *p)
{
int i = 0;
FINODE_EXTENSION_MEMORY *scannode;
scannode = prtfs_cfg->mem_finode_uex_freelist;
while (scannode)
{
if (scannode == p)
return(TRUE);
scannode = scannode->pnext_freelist;
if (i++ > prtfs_cfg->cfg_NFINODES_UEX)
return(FALSE);
}
return(FALSE);
}
#endif /* INCLUDE_RTFS_PROPLUS */
static BOOLEAN pc_lk_blkbuff_inlist(BLKBUFF *plist, BLKBUFF *pbuff)
{
while (plist)
{
if (plist == pbuff)
return(TRUE);
plist = plist->pnext;
}
return(FALSE);
}
static BOOLEAN pc_lk_blkbuff_in_freelist(BLKBUFFCNTXT *pbuffcntxt, BLKBUFF *pbuff)
{
return(pc_lk_blkbuff_inlist(pbuffcntxt->pfree_blocks , pbuff));
}
static BOOLEAN pc_lk_blkbuff_in_filebuffer(BLKBUFF *pbuff)
{
int i;
for (i = 0; i < prtfs_cfg->cfg_NUSERFILES; i++)
{
if (!prtfs_cfg->mem_file_pool[i].is_free)
{
if (prtfs_cfg->mem_file_pool[i].pobj &&
prtfs_cfg->mem_file_pool[i].pobj->finode->pfile_buffer == pbuff)
return(TRUE);
}
}
return(FALSE);
}
static BOOLEAN pc_lk_blkbuff_in_dirbuffer(BLKBUFFCNTXT *pbuffcntxt, BLKBUFF *pbuff)
{
return(pc_lk_blkbuff_inlist(pbuffcntxt->ppopulated_blocks , pbuff));
}
static BOOLEAN pc_lk_blkbuff_in_scratchbuffer(BLKBUFFCNTXT *pbuffcntxt, BLKBUFF *pbuff)
{
return(pc_lk_blkbuff_inlist(pbuffcntxt->pscratch_blocks , pbuff));
}
static BOOLEAN pc_lk_rgnbuff_in_list(struct region_fragment *plist, struct region_fragment *prgnbuff)
{
struct region_fragment *p;
int i = 0;
p = plist;
while (p)
{
if (p == prgnbuff)
return(TRUE);
p = p->pnext;
if (i++ > prtfs_cfg->cfg_NREGIONS)
return(FALSE);
}
return(FALSE);
}
static BOOLEAN pc_lk_rgnbuff_in_freelist(struct region_fragment *prgnbuff)
{
return(pc_lk_rgnbuff_in_list(prtfs_cfg->mem_region_freelist, prgnbuff));
}
static BOOLEAN pc_lk_rgnbuff_in_file(struct region_fragment *prgnbuff)
{
if (pc_lk_finode_in_drobj((void *)prgnbuff, ARGTYPE_REGION) == 0)
return(FALSE);
else
return(TRUE);
}
static BOOLEAN pc_lk_rgnbuff_in_freemap(struct region_fragment *prgnbuff)
{
#if (INCLUDE_RTFS_FREEMANAGER)
DDRIVE *pdr;
int i,j;
pdr = prtfs_cfg->mem_drive_pool;
for (i = 0; i < prtfs_cfg->cfg_NDRIVES; i++, pdr++)
{
if (pc_lk_drive_in_map(pdr))
{
if (pdr->drive_state.free_ctxt_cluster_shifter)
{
for (j = 0; j < RTFS_FREE_MANAGER_HASHSIZE; j++)
{
if (pc_lk_rgnbuff_in_list(pdr->drive_state.free_ctxt_hash_tbl[j], prgnbuff))
return(TRUE);
}
}
}
}
#endif
RTFS_ARGSUSED_PVOID((void *) prgnbuff);
return(FALSE);
}
static BOOLEAN pc_lk_rgnbuff_in_failsafe(struct region_fragment *prgnbuff)
{
#if (INCLUDE_FAILSAFE_CODE)
int i;
DDRIVE *pdr;
FAILSAFECONTEXT *pfscntxt;
pdr = prtfs_cfg->mem_drive_pool;
for (i = 0; i < prtfs_cfg->cfg_NDRIVES; i++, pdr++)
{
if (pc_lk_drive_in_map(pdr))
{
pfscntxt = (FAILSAFECONTEXT *) pdr->drive_state.failsafe_context;
if (pfscntxt)
{
if (pc_lk_rgnbuff_in_list(pfscntxt->fs_journal.open_free_fragments, prgnbuff))
return(TRUE);
if (pc_lk_rgnbuff_in_list(pfscntxt->fs_journal.flushed_free_fragments, prgnbuff))
return(TRUE);
if (pc_lk_rgnbuff_in_list(pfscntxt->fs_journal.restoring_free_fragments, prgnbuff))
return(TRUE);
}
}
}
#endif
RTFS_ARGSUSED_PVOID((void *) prgnbuff);
return(FALSE);
}
static void pc_lk_fatbuff_check(DDRIVE *pdrive,struct mem_report *preport)
{
RTFS_ARGSUSED_PVOID((void *) pdrive);
RTFS_ARGSUSED_PVOID((void *) preport);
return;
}
static void pc_lk_print_two(char *p1, int v1, char *p2, int v2)
{
/* printf("%-30.30s %6d %-30.30s %6d \n", p1, v1, p2, v2); */
rtfs_print_one_string((byte *)p1, 0);
rtfs_print_one_string((byte *)" == ", 0);
rtfs_print_long_1(v1, 0);
rtfs_print_one_string((byte *)". ", 0);
rtfs_print_one_string((byte *)p2, 0);
rtfs_print_one_string((byte *)" == ", 0);
rtfs_print_long_1(v2, PRFLG_NL);
}
static void pc_lk_print_one(char *p1, int v1)
{
/* printf("%-30.30s %6d\n", p1, v1); */
rtfs_print_one_string((byte *)p1, 0);
rtfs_print_one_string((byte *)" == ", 0);
rtfs_print_long_1(v1, PRFLG_NL);
}
static void pc_lk_print_check(struct mem_report *preport)
{
pc_lk_print_two("nusers_free ", preport->nusers_free, "nusers_configured", preport->nusers_configured);
pc_lk_print_two("nfiles_configured", preport->nfiles_configured, "nfiles_free ", preport->nfiles_free);
pc_lk_print_two("ndrives_configure", preport->ndrives_configured, "ndrives_free ", preport->ndrives_free);
pc_lk_print_two("ndrives_mapped ", preport->ndrives_mapped, "ndrives_lost ", preport->ndrives_lost);
pc_lk_print_two("ndrobjs_configure", preport->ndrobjs_configured, "ndrobjs_free ", preport->ndrobjs_free);
pc_lk_print_two("ndrobjs_in_files ", preport->ndrobjs_in_files, "ndrobjs_in_users ", preport->ndrobjs_in_users);
pc_lk_print_one("ndrobjs_lost ", preport->ndrobjs_lost);
pc_lk_print_two("nfinodes_configured", preport->nfinodes_configured, "nfinodes_free ", preport->nfinodes_free);
pc_lk_print_two("nfinodes_in_drobj", preport->nfinodes_in_drobj, "nfinodes_in_pool ", preport->nfinodes_in_pool);
pc_lk_print_two("nfinodes_reference_errors ", preport->nfinodes_reference_errors, "nfinodes_lost ", preport->nfinodes_lost);
pc_lk_print_two("nfinodeex_configuredn", preport->nfinodeex_configured, "nfinodeex_free ", preport->nfinodeex_free);
pc_lk_print_one("nfinodeex_lost ", preport->nfinodeex_lost);
pc_lk_print_one("nfinodeex64_configured ", preport->nfinodeex64_configured);
pc_lk_print_two("nfinodeex64_free ", preport->nfinodeex64_free, "nfinodeex64_lost ", preport->nfinodeex64_lost);
pc_lk_print_two("nblkbuff_configured ", preport->nglblkbuff_configured, "nblkbuff_free ", preport->nglblkbuff_free);
pc_lk_print_two("nblkbuff_in_files ", preport->nglblkbuff_in_filebuff, "nblkbuff_in_dirbuff ", preport->nglblkbuff_in_dirbuff);
pc_lk_print_two("nblkbuff_in_scratch ", preport->nglblkbuff_in_scratchbuff, "nblkbuff_lost ", preport->nglblkbuff_lost);
pc_lk_print_two("nrgnbuff_configured ", preport->nrgnbuff_configured, "nrgnbuff_free ", preport->nrgnbuff_free);
pc_lk_print_two("nrgnbuff_in_files ", preport->nrgnbuff_in_files, "nrgnbuff_in_freemap ", preport->nrgnbuff_in_freemap);
pc_lk_print_two("nrgnbuff_in_failsafe", preport->nrgnbuff_in_failsafe, "nrgnbuff_lost ", preport->nrgnbuff_lost);
pc_lk_print_two("nfatbuff_free ", preport->nfatbuff_free, "fatbuff_committed ", preport->nfatbuff_committed);
pc_lk_print_two("fatbuff_uncommitted ", preport->nfatbuff_uncommitted, "fatbuff_lost ", preport->nfatbuff_lost);
pc_lk_print_one("lost_count", preport->lost_count);
}
#endif