mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-30 23:41:13 +02:00
1. Fix md memory leak:
mdunlink() and mdclose() (too !!!) now free MdfdVec for relation and add it to free list, so it may be re-used for another relation later. 2. Fix VFD-manager memory leak (found by Massimo ... and me): mdunlink() has to call FileUnlink() to free allocation for fileName and add the Vfd slot to the free list.
This commit is contained in:
parent
ff8ce5230d
commit
19269069dc
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.12 1997/05/06 02:03:20 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.13 1997/05/22 17:08:33 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -43,24 +43,28 @@
|
||||
|
||||
typedef struct _MdfdVec {
|
||||
int mdfd_vfd; /* fd number in vfd pool */
|
||||
uint16 mdfd_flags; /* clean, dirty */
|
||||
uint16 mdfd_flags; /* clean, dirty, free */
|
||||
int mdfd_lstbcnt; /* most recent block count */
|
||||
int mdfd_nextFree; /* next free vector */
|
||||
struct _MdfdVec *mdfd_chain; /* for large relations */
|
||||
} MdfdVec;
|
||||
|
||||
static int Nfds = 100;
|
||||
static MdfdVec *Md_fdvec = (MdfdVec *) NULL;
|
||||
static int Md_Free = -1;
|
||||
static int CurFd = 0;
|
||||
static MemoryContext MdCxt;
|
||||
|
||||
#define MDFD_DIRTY (uint16) 0x01
|
||||
#define MDFD_FREE (uint16) 0x02
|
||||
|
||||
#define RELSEG_SIZE 262144 /* (2 ** 31) / 8192 -- 2GB file */
|
||||
|
||||
/* routines declared here */
|
||||
static MdfdVec *_mdfd_openseg(Relation reln, int segno, int oflags);
|
||||
static MdfdVec *_mdfd_getseg(Relation reln, int blkno, int oflag);
|
||||
static int _fdvec_ext(void);
|
||||
static int _fdvec_alloc (void);
|
||||
static void _fdvec_free (int);
|
||||
static BlockNumber _mdnblocks(File file, Size blcksz);
|
||||
|
||||
/*
|
||||
@ -78,6 +82,7 @@ int
|
||||
mdinit()
|
||||
{
|
||||
MemoryContext oldcxt;
|
||||
int i;
|
||||
|
||||
MdCxt = (MemoryContext) CreateGlobalMemory("MdSmgr");
|
||||
if (MdCxt == (MemoryContext) NULL)
|
||||
@ -92,6 +97,15 @@ mdinit()
|
||||
|
||||
memset(Md_fdvec, 0, Nfds * sizeof(MdfdVec));
|
||||
|
||||
/* Set free list */
|
||||
for (i = 0; i < Nfds; i++ )
|
||||
{
|
||||
Md_fdvec[i].mdfd_nextFree = i + 1;
|
||||
Md_fdvec[i].mdfd_flags = MDFD_FREE;
|
||||
}
|
||||
Md_Free = 0;
|
||||
Md_fdvec[Nfds - 1].mdfd_nextFree = -1;
|
||||
|
||||
return (SM_SUCCESS);
|
||||
}
|
||||
|
||||
@ -125,17 +139,14 @@ mdcreate(Relation reln)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (CurFd >= Nfds) {
|
||||
if (_fdvec_ext() == SM_FAIL)
|
||||
vfd = _fdvec_alloc ();
|
||||
if ( vfd < 0 )
|
||||
return (-1);
|
||||
}
|
||||
|
||||
Md_fdvec[CurFd].mdfd_vfd = fd;
|
||||
Md_fdvec[CurFd].mdfd_flags = (uint16) 0;
|
||||
Md_fdvec[CurFd].mdfd_chain = (MdfdVec *) NULL;
|
||||
Md_fdvec[CurFd].mdfd_lstbcnt = 0;
|
||||
|
||||
vfd = CurFd++;
|
||||
Md_fdvec[vfd].mdfd_vfd = fd;
|
||||
Md_fdvec[vfd].mdfd_flags = (uint16) 0;
|
||||
Md_fdvec[vfd].mdfd_chain = (MdfdVec *) NULL;
|
||||
Md_fdvec[vfd].mdfd_lstbcnt = 0;
|
||||
|
||||
return (vfd);
|
||||
}
|
||||
@ -175,7 +186,9 @@ mdunlink(Relation reln)
|
||||
Md_fdvec[fd].mdfd_flags = (uint16) 0;
|
||||
|
||||
oldcxt = MemoryContextSwitchTo(MdCxt);
|
||||
for (v = &Md_fdvec[fd]; v != (MdfdVec *) NULL; ) {
|
||||
for (v = &Md_fdvec[fd]; v != (MdfdVec *) NULL; )
|
||||
{
|
||||
FileUnlink(v->mdfd_vfd);
|
||||
ov = v;
|
||||
v = v->mdfd_chain;
|
||||
if (ov != &Md_fdvec[fd])
|
||||
@ -184,6 +197,8 @@ mdunlink(Relation reln)
|
||||
Md_fdvec[fd].mdfd_chain = (MdfdVec *) NULL;
|
||||
(void) MemoryContextSwitchTo(oldcxt);
|
||||
|
||||
_fdvec_free (fd);
|
||||
|
||||
return (SM_SUCCESS);
|
||||
}
|
||||
|
||||
@ -235,11 +250,6 @@ mdopen(Relation reln)
|
||||
int fd;
|
||||
int vfd;
|
||||
|
||||
if (CurFd >= Nfds) {
|
||||
if (_fdvec_ext() == SM_FAIL)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
path = relpath(&(reln->rd_rel->relname.data[0]));
|
||||
|
||||
fd = FileNameOpenFile(path, O_RDWR, 0600);
|
||||
@ -248,23 +258,28 @@ mdopen(Relation reln)
|
||||
if (fd < 0)
|
||||
fd = FileNameOpenFile(path, O_RDWR|O_CREAT|O_EXCL, 0600);
|
||||
|
||||
Md_fdvec[CurFd].mdfd_vfd = fd;
|
||||
Md_fdvec[CurFd].mdfd_flags = (uint16) 0;
|
||||
Md_fdvec[CurFd].mdfd_chain = (MdfdVec *) NULL;
|
||||
Md_fdvec[CurFd].mdfd_lstbcnt = _mdnblocks(fd, BLCKSZ);
|
||||
vfd = _fdvec_alloc ();
|
||||
if ( vfd < 0 )
|
||||
return (-1);
|
||||
|
||||
Md_fdvec[vfd].mdfd_vfd = fd;
|
||||
Md_fdvec[vfd].mdfd_flags = (uint16) 0;
|
||||
Md_fdvec[vfd].mdfd_chain = (MdfdVec *) NULL;
|
||||
Md_fdvec[vfd].mdfd_lstbcnt = _mdnblocks(fd, BLCKSZ);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (Md_fdvec[CurFd].mdfd_lstbcnt > RELSEG_SIZE)
|
||||
if (Md_fdvec[vfd].mdfd_lstbcnt > RELSEG_SIZE)
|
||||
elog(FATAL, "segment too big on relopen!");
|
||||
#endif
|
||||
|
||||
vfd = CurFd++;
|
||||
|
||||
return (vfd);
|
||||
}
|
||||
|
||||
/*
|
||||
* mdclose() -- Close the specified relation.
|
||||
* mdclose() -- Close the specified relation
|
||||
*
|
||||
* AND FREE fd vector! It may be re-used for other relation!
|
||||
* reln should be flushed from cache after closing !..
|
||||
*
|
||||
* Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
|
||||
*/
|
||||
@ -272,16 +287,17 @@ int
|
||||
mdclose(Relation reln)
|
||||
{
|
||||
int fd;
|
||||
MdfdVec *v;
|
||||
MdfdVec *v, *ov;
|
||||
MemoryContext oldcxt;
|
||||
|
||||
fd = RelationGetFile(reln);
|
||||
|
||||
for (v = &Md_fdvec[fd]; v != (MdfdVec *) NULL; v = v->mdfd_chain) {
|
||||
|
||||
/* may be closed already */
|
||||
if (v->mdfd_vfd < 0)
|
||||
continue;
|
||||
|
||||
oldcxt = MemoryContextSwitchTo(MdCxt);
|
||||
for (v = &Md_fdvec[fd]; v != (MdfdVec *) NULL; )
|
||||
{
|
||||
/* if not closed already */
|
||||
if ( v->mdfd_vfd >= 0 )
|
||||
{
|
||||
/*
|
||||
* We sync the file descriptor so that we don't need to reopen it at
|
||||
* transaction commit to force changes to disk.
|
||||
@ -293,6 +309,17 @@ mdclose(Relation reln)
|
||||
/* mark this file descriptor as clean in our private table */
|
||||
v->mdfd_flags &= ~MDFD_DIRTY;
|
||||
}
|
||||
/* Now free vector */
|
||||
ov = v;
|
||||
v = v->mdfd_chain;
|
||||
if (ov != &Md_fdvec[fd])
|
||||
pfree(ov);
|
||||
}
|
||||
|
||||
(void) MemoryContextSwitchTo(oldcxt);
|
||||
Md_fdvec[fd].mdfd_chain = (MdfdVec *) NULL;
|
||||
|
||||
_fdvec_free (fd);
|
||||
|
||||
return (SM_SUCCESS);
|
||||
}
|
||||
@ -605,31 +632,77 @@ mdabort()
|
||||
}
|
||||
|
||||
/*
|
||||
* _fdvec_ext() -- Extend the md file descriptor vector.
|
||||
* _fdvec_alloc () -- grab a free (or new) md file descriptor vector.
|
||||
*
|
||||
* The file descriptor vector must be large enough to hold at least
|
||||
* 'fd' entries.
|
||||
*/
|
||||
static
|
||||
int _fdvec_ext()
|
||||
int _fdvec_alloc ()
|
||||
{
|
||||
MdfdVec *nvec;
|
||||
int fdvec, i;
|
||||
MemoryContext oldcxt;
|
||||
|
||||
if ( Md_Free >= 0 ) /* get from free list */
|
||||
{
|
||||
fdvec = Md_Free;
|
||||
Md_Free = Md_fdvec[fdvec].mdfd_nextFree;
|
||||
Assert ( Md_fdvec[fdvec].mdfd_flags == MDFD_FREE );
|
||||
Md_fdvec[fdvec].mdfd_flags = 0;
|
||||
if ( fdvec >= CurFd )
|
||||
{
|
||||
Assert ( fdvec == CurFd );
|
||||
CurFd++;
|
||||
}
|
||||
return (fdvec);
|
||||
}
|
||||
|
||||
/* Must allocate more room */
|
||||
|
||||
if ( Nfds != CurFd )
|
||||
elog (FATAL, "_fdvec_alloc error");
|
||||
|
||||
Nfds *= 2;
|
||||
|
||||
oldcxt = MemoryContextSwitchTo(MdCxt);
|
||||
|
||||
nvec = (MdfdVec *) palloc(Nfds * sizeof(MdfdVec));
|
||||
memset(nvec, 0, Nfds * sizeof(MdfdVec));
|
||||
memmove(nvec, (char *) Md_fdvec, (Nfds / 2) * sizeof(MdfdVec));
|
||||
memmove(nvec, (char *) Md_fdvec, CurFd * sizeof(MdfdVec));
|
||||
pfree(Md_fdvec);
|
||||
|
||||
(void) MemoryContextSwitchTo(oldcxt);
|
||||
|
||||
Md_fdvec = nvec;
|
||||
|
||||
return (SM_SUCCESS);
|
||||
/* Set new free list */
|
||||
for (i = CurFd; i < Nfds; i++ )
|
||||
{
|
||||
Md_fdvec[i].mdfd_nextFree = i + 1;
|
||||
Md_fdvec[i].mdfd_flags = MDFD_FREE;
|
||||
}
|
||||
Md_fdvec[Nfds - 1].mdfd_nextFree = -1;
|
||||
Md_Free = CurFd + 1;
|
||||
|
||||
fdvec = CurFd;
|
||||
CurFd++;
|
||||
Md_fdvec[fdvec].mdfd_flags = 0;
|
||||
|
||||
return (fdvec);
|
||||
}
|
||||
|
||||
/*
|
||||
* _fdvec_free () -- free md file descriptor vector.
|
||||
*
|
||||
*/
|
||||
static
|
||||
void _fdvec_free (int fdvec)
|
||||
{
|
||||
|
||||
Assert ( Md_Free < 0 || Md_fdvec[Md_Free].mdfd_flags == MDFD_FREE );
|
||||
Md_fdvec[fdvec].mdfd_nextFree = Md_Free;
|
||||
Md_fdvec[fdvec].mdfd_flags = MDFD_FREE;
|
||||
Md_Free = fdvec;
|
||||
|
||||
}
|
||||
|
||||
static MdfdVec *
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.5 1996/11/27 07:25:52 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.6 1997/05/22 17:08:35 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -189,6 +189,13 @@ smgropen(int16 which, Relation reln)
|
||||
/*
|
||||
* smgrclose() -- Close a relation.
|
||||
*
|
||||
* NOTE: mdclose frees fd vector! It may be re-used for other relation!
|
||||
* reln should be flushed from cache after closing !..
|
||||
* Currently, smgrclose is calling by
|
||||
* relcache.c:RelationPurgeLocalRelation() only.
|
||||
* It would be nice to have smgrfree(), but because of
|
||||
* smgrclose is called from single place... - vadim 05/22/97
|
||||
*
|
||||
* Returns SM_SUCCESS on success, aborts on failure.
|
||||
*/
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user