Fix a handful of small one-time memory leaks in vbackup,
and one per-package memory leak (in writethread).
This commit is contained in:
parent
067d852abe
commit
6fc7da3c52
17 changed files with 94 additions and 13 deletions
|
|
@ -348,6 +348,8 @@ Packet *vtrecv(VtConn*);
|
||||||
int vtversion(VtConn *z);
|
int vtversion(VtConn *z);
|
||||||
void vtdebug(VtConn *z, char*, ...);
|
void vtdebug(VtConn *z, char*, ...);
|
||||||
void vthangup(VtConn *z);
|
void vthangup(VtConn *z);
|
||||||
|
int vtgoodbye(VtConn *z);
|
||||||
|
|
||||||
/* #pragma varargck argpos vtdebug 2 */
|
/* #pragma varargck argpos vtdebug 2 */
|
||||||
|
|
||||||
/* server */
|
/* server */
|
||||||
|
|
@ -412,6 +414,7 @@ struct VtBlock
|
||||||
u32int used;
|
u32int used;
|
||||||
u32int used2;
|
u32int used2;
|
||||||
u32int addr;
|
u32int addr;
|
||||||
|
uintptr pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32int vtglobaltolocal(uchar[VtScoreSize]);
|
u32int vtglobaltolocal(uchar[VtScoreSize]);
|
||||||
|
|
|
||||||
|
|
@ -62,3 +62,9 @@ qclose(Queue *q)
|
||||||
rwakeup(&q->r);
|
rwakeup(&q->r);
|
||||||
qunlock(&q->lk);
|
qunlock(&q->lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
qfree(Queue *q)
|
||||||
|
{
|
||||||
|
vtfree(q);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,4 @@ Queue *qalloc(void);
|
||||||
void qclose(Queue*);
|
void qclose(Queue*);
|
||||||
Block *qread(Queue*, u32int*);
|
Block *qread(Queue*, u32int*);
|
||||||
void qwrite(Queue*, Block*, u32int);
|
void qwrite(Queue*, Block*, u32int);
|
||||||
|
void qfree(Queue*);
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,9 @@ threadmain(int argc, char **argv)
|
||||||
* wait for processes to finish
|
* wait for processes to finish
|
||||||
*/
|
*/
|
||||||
wlock(&endlk);
|
wlock(&endlk);
|
||||||
|
|
||||||
|
qfree(qcmp);
|
||||||
|
qfree(qventi);
|
||||||
|
|
||||||
if(statustime)
|
if(statustime)
|
||||||
print("# %T procs exited: %d blocks changed, %d read, %d written, %d skipped, %d copied\n",
|
print("# %T procs exited: %d blocks changed, %d read, %d written, %d skipped, %d copied\n",
|
||||||
|
|
@ -297,6 +300,8 @@ threadmain(int argc, char **argv)
|
||||||
sysfatal("vtfileflush: %r");
|
sysfatal("vtfileflush: %r");
|
||||||
if(vtfilegetentry(vfile, &e) < 0)
|
if(vtfilegetentry(vfile, &e) < 0)
|
||||||
sysfatal("vtfilegetentry: %r");
|
sysfatal("vtfilegetentry: %r");
|
||||||
|
vtfileunlock(vfile);
|
||||||
|
vtfileclose(vfile);
|
||||||
|
|
||||||
b = vtcacheallocblock(c, VtDirType);
|
b = vtcacheallocblock(c, VtDirType);
|
||||||
if(b == nil)
|
if(b == nil)
|
||||||
|
|
@ -336,6 +341,19 @@ threadmain(int argc, char **argv)
|
||||||
sysfatal("vtsync: %r");
|
sysfatal("vtsync: %r");
|
||||||
if(statustime)
|
if(statustime)
|
||||||
print("# %T synced\n");
|
print("# %T synced\n");
|
||||||
|
|
||||||
|
fsysclose(fsys);
|
||||||
|
diskclose(disk);
|
||||||
|
vtcachefree(zcache);
|
||||||
|
vtgoodbye(z);
|
||||||
|
// Leak here, because I can't seem to make
|
||||||
|
// the vtrecvproc exit.
|
||||||
|
// vtfreeconn(z);
|
||||||
|
free(tmpnam);
|
||||||
|
z = nil;
|
||||||
|
zcache = nil;
|
||||||
|
fsys = nil;
|
||||||
|
disk = nil;
|
||||||
threadexitsall(nil);
|
threadexitsall(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -416,6 +434,7 @@ writethread(void *v)
|
||||||
}
|
}
|
||||||
if(vtwritepacket(z, wr.score, wr.type, wr.p) < 0)
|
if(vtwritepacket(z, wr.score, wr.type, wr.p) < 0)
|
||||||
sysfatal("vtwritepacket: %r");
|
sysfatal("vtwritepacket: %r");
|
||||||
|
packetfree(wr.p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,6 +491,7 @@ ventiproc(void *dummy)
|
||||||
vtcachesetwrite(zcache, nil);
|
vtcachesetwrite(zcache, nil);
|
||||||
for(i=0; i<nwritethread; i++)
|
for(i=0; i<nwritethread; i++)
|
||||||
send(writechan, nil);
|
send(writechan, nil);
|
||||||
|
chanfree(writechan);
|
||||||
if(statustime)
|
if(statustime)
|
||||||
print("# %T venti proc exiting - nsend %d nrecv %d\n", nsend, nrecv);
|
print("# %T venti proc exiting - nsend %d nrecv %d\n", nsend, nrecv);
|
||||||
runlock(&endlk);
|
runlock(&endlk);
|
||||||
|
|
@ -534,6 +554,7 @@ mountplace(char *dev)
|
||||||
if(threadspawnl(fd, "sh", "sh", "-c", cmd, nil) < 0)
|
if(threadspawnl(fd, "sh", "sh", "-c", cmd, nil) < 0)
|
||||||
sysfatal("exec mount|awk (to find mtpt of %s): %r", dev);
|
sysfatal("exec mount|awk (to find mtpt of %s): %r", dev);
|
||||||
/* threadspawnl closed p[1] */
|
/* threadspawnl closed p[1] */
|
||||||
|
free(cmd);
|
||||||
n = readn(p[0], buf, sizeof buf-1);
|
n = readn(p[0], buf, sizeof buf-1);
|
||||||
close(p[0]);
|
close(p[0]);
|
||||||
if(n <= 0)
|
if(n <= 0)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
/*
|
/*
|
||||||
* Disk cache. Caches by offset, so higher levels have
|
* Disk cache. Caches by offset, so higher levels have
|
||||||
* to deal with alignment issues (if we get asked for the
|
* to deal with alignment issues (if we get asked for the
|
||||||
* blocks at offsets 0 and 1, we'll do two reads.
|
* blocks at offsets 0 and 1, we'll do two reads).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct DiskCache DiskCache;
|
typedef struct DiskCache DiskCache;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ fsysopenffs(Disk *disk)
|
||||||
fsys->_readfile = ffsreadfile;
|
fsys->_readfile = ffsreadfile;
|
||||||
fsys->_readlink = ffsreadlink;
|
fsys->_readlink = ffsreadlink;
|
||||||
fsys->_readdir = ffsreaddir;
|
fsys->_readdir = ffsreaddir;
|
||||||
|
fsys->_close = ffsclose;
|
||||||
fsys->fileblock = ffsxfileblock;
|
fsys->fileblock = ffsxfileblock;
|
||||||
|
|
||||||
if(ffssync(fsys) < 0)
|
if(ffssync(fsys) < 0)
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ fprint(2, "cachecheck: nheap %d refed %d nblocks %d\n", c->nheap, refed, c->nblo
|
||||||
for(i = 0; i < c->nblock; i++){
|
for(i = 0; i < c->nblock; i++){
|
||||||
b = &c->block[i];
|
b = &c->block[i];
|
||||||
if(b->ref){
|
if(b->ref){
|
||||||
if(1)fprint(2, "a=%ud %V ref=%d\n", b->addr, b->score, b->ref);
|
if(1)fprint(2, "a=%ud %V ref=%d pc=%#lux\n", b->addr, b->score, b->ref, (ulong)b->pc);
|
||||||
refed++;
|
refed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -333,6 +333,7 @@ vtcachelocal(VtCache *c, u32int addr, int type)
|
||||||
|
|
||||||
qlock(&b->lk);
|
qlock(&b->lk);
|
||||||
b->nlock = 1;
|
b->nlock = 1;
|
||||||
|
b->pc = getcallerpc(&c);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,7 +353,7 @@ vtcacheallocblock(VtCache *c, int type)
|
||||||
|
|
||||||
qlock(&b->lk);
|
qlock(&b->lk);
|
||||||
b->nlock = 1;
|
b->nlock = 1;
|
||||||
|
b->pc = getcallerpc(&b);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,7 +375,10 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type)
|
||||||
if(addr != NilBlock){
|
if(addr != NilBlock){
|
||||||
if(vttracelevel)
|
if(vttracelevel)
|
||||||
fprint(2, "vtcacheglobal %V %d => local\n", score, type);
|
fprint(2, "vtcacheglobal %V %d => local\n", score, type);
|
||||||
return vtcachelocal(c, addr, type);
|
b = vtcachelocal(c, addr, type);
|
||||||
|
if(b)
|
||||||
|
b->pc = getcallerpc(&c);
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
h = (u32int)(score[0]|(score[1]<<8)|(score[2]<<16)|(score[3]<<24)) % c->nhash;
|
h = (u32int)(score[0]|(score[1]<<8)|(score[2]<<16)|(score[3]<<24)) % c->nhash;
|
||||||
|
|
@ -404,6 +408,7 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type)
|
||||||
}
|
}
|
||||||
if(vttracelevel)
|
if(vttracelevel)
|
||||||
fprint(2, "vtcacheglobal %V %d => found in cache; returning\n", score, type);
|
fprint(2, "vtcacheglobal %V %d => found in cache; returning\n", score, type);
|
||||||
|
b->pc = getcallerpc(&c);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -451,6 +456,7 @@ vtcacheglobal(VtCache *c, uchar score[VtScoreSize], int type)
|
||||||
b->nlock = 1;
|
b->nlock = 1;
|
||||||
if(vttracelevel)
|
if(vttracelevel)
|
||||||
fprint(2, "vtcacheglobal %V %d => loaded into cache; returning\n", score, type);
|
fprint(2, "vtcacheglobal %V %d => loaded into cache; returning\n", score, type);
|
||||||
|
b->pc = getcallerpc(&b);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -573,6 +579,7 @@ vtblockcopy(VtBlock *b)
|
||||||
}
|
}
|
||||||
memmove(bb->data, b->data, b->c->blocksize);
|
memmove(bb->data, b->data, b->c->blocksize);
|
||||||
vtblockput(b);
|
vtblockput(b);
|
||||||
|
bb->pc = getcallerpc(&b);
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,3 +169,12 @@ vtconnect(VtConn *z)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vtgoodbye(VtConn *z)
|
||||||
|
{
|
||||||
|
VtFcall tx, rx;
|
||||||
|
|
||||||
|
tx.msgtype = VtTgoodbye;
|
||||||
|
vtfcallrpc(z, &tx, &rx); /* always fails: no VtRgoodbye */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,15 +32,19 @@ vtfreeconn(VtConn *z)
|
||||||
{
|
{
|
||||||
vthangup(z);
|
vthangup(z);
|
||||||
qlock(&z->lk);
|
qlock(&z->lk);
|
||||||
for(;;){
|
/*
|
||||||
|
* Wait for send and recv procs to notice
|
||||||
|
* the hangup and clear out the queues.
|
||||||
|
*/
|
||||||
|
while(z->readq || z->writeq){
|
||||||
if(z->readq)
|
if(z->readq)
|
||||||
_vtqhangup(z->readq);
|
_vtqhangup(z->readq);
|
||||||
else if(z->writeq)
|
if(z->writeq)
|
||||||
_vtqhangup(z->writeq);
|
_vtqhangup(z->writeq);
|
||||||
else
|
|
||||||
break;
|
|
||||||
rsleep(&z->rpcfork);
|
rsleep(&z->rpcfork);
|
||||||
}
|
}
|
||||||
packetfree(z->part);
|
packetfree(z->part);
|
||||||
|
vtfree(z->version);
|
||||||
|
vtfree(z->sid);
|
||||||
vtfree(z);
|
vtfree(z);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,7 @@ vtfcallunpack(VtFcall *f, Packet *p)
|
||||||
|
|
||||||
Err:
|
Err:
|
||||||
werrstr("bad packet");
|
werrstr("bad packet");
|
||||||
|
vtfcallclear(f);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -699,7 +699,7 @@ vtfileblock(VtFile *r, u32int bn, int mode)
|
||||||
|
|
||||||
i = mkindices(&e, bn, index);
|
i = mkindices(&e, bn, index);
|
||||||
if(i < 0)
|
if(i < 0)
|
||||||
return nil;
|
goto Err;
|
||||||
if(i > DEPTH(e.type)){
|
if(i > DEPTH(e.type)){
|
||||||
if(mode == VtOREAD){
|
if(mode == VtOREAD){
|
||||||
werrstr("bad address 0x%lux", (ulong)bn);
|
werrstr("bad address 0x%lux", (ulong)bn);
|
||||||
|
|
@ -726,6 +726,7 @@ assert(b->type == VtDirType);
|
||||||
vtblockput(b);
|
vtblockput(b);
|
||||||
b = bb;
|
b = bb;
|
||||||
}
|
}
|
||||||
|
b->pc = getcallerpc(&r);
|
||||||
return b;
|
return b;
|
||||||
Err:
|
Err:
|
||||||
vtblockput(b);
|
vtblockput(b);
|
||||||
|
|
@ -833,6 +834,7 @@ fileloadblock(VtFile *r, int mode)
|
||||||
b = vtcacheglobal(r->c, r->score, VtDirType);
|
b = vtcacheglobal(r->c, r->score, VtDirType);
|
||||||
if(b == nil)
|
if(b == nil)
|
||||||
return nil;
|
return nil;
|
||||||
|
b->pc = getcallerpc(&r);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
assert(r->parent != nil);
|
assert(r->parent != nil);
|
||||||
|
|
@ -902,6 +904,7 @@ vtfilelock(VtFile *r, int mode)
|
||||||
*/
|
*/
|
||||||
assert(r->b == nil);
|
assert(r->b == nil);
|
||||||
r->b = b;
|
r->b = b;
|
||||||
|
b->pc = getcallerpc(&r);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -948,6 +951,8 @@ vtfilelock2(VtFile *r, VtFile *rr, int mode)
|
||||||
*/
|
*/
|
||||||
r->b = b;
|
r->b = b;
|
||||||
rr->b = bb;
|
rr->b = bb;
|
||||||
|
b->pc = getcallerpc(&r);
|
||||||
|
bb->pc = getcallerpc(&r);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include <u.h>
|
#include <u.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
#include <venti.h>
|
#include <venti.h>
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
@ -8,6 +9,9 @@ vthangup(VtConn *z)
|
||||||
{
|
{
|
||||||
qlock(&z->lk);
|
qlock(&z->lk);
|
||||||
z->state = VtStateClosed;
|
z->state = VtStateClosed;
|
||||||
|
/* try to make the read in vtsendproc fail */
|
||||||
|
shutdown(SHUT_WR, z->infd);
|
||||||
|
shutdown(SHUT_WR, z->outfd);
|
||||||
if(z->infd >= 0)
|
if(z->infd >= 0)
|
||||||
close(z->infd);
|
close(z->infd);
|
||||||
if(z->outfd >= 0 && z->outfd != z->infd)
|
if(z->outfd >= 0 && z->outfd != z->infd)
|
||||||
|
|
@ -20,3 +24,4 @@ vthangup(VtConn *z)
|
||||||
_vtqhangup(z->readq);
|
_vtqhangup(z->readq);
|
||||||
qunlock(&z->lk);
|
qunlock(&z->lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -756,7 +756,6 @@ packetcmp(Packet *pkt0, Packet *pkt1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Frag *
|
static Frag *
|
||||||
fragalloc(Packet *p, int n, int pos, Frag *next)
|
fragalloc(Packet *p, int n, int pos, Frag *next)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,20 @@ _vtqalloc(void)
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_vtqfree(Queue *q)
|
||||||
|
{
|
||||||
|
Qel *e;
|
||||||
|
|
||||||
|
/* Leaks the pointers e->p! */
|
||||||
|
while(q->head){
|
||||||
|
e = q->head;
|
||||||
|
q->head = e->next;
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
free(q);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_vtqsend(Queue *q, void *p)
|
_vtqsend(Queue *q, void *p)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ int _vtqsend(Queue*, void*);
|
||||||
void *_vtqrecv(Queue*);
|
void *_vtqrecv(Queue*);
|
||||||
void _vtqhangup(Queue*);
|
void _vtqhangup(Queue*);
|
||||||
void *_vtnbqrecv(Queue*);
|
void *_vtnbqrecv(Queue*);
|
||||||
|
void _vtqfree(Queue*);
|
||||||
|
|
|
||||||
|
|
@ -59,12 +59,15 @@ _vtrpc(VtConn *z, Packet *p, VtFcall *tx)
|
||||||
if(top == buf){
|
if(top == buf){
|
||||||
werrstr("first two bytes must be in same packet fragment");
|
werrstr("first two bytes must be in same packet fragment");
|
||||||
packetfree(p);
|
packetfree(p);
|
||||||
|
vtfree(r);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
top[1] = tag;
|
top[1] = tag;
|
||||||
qunlock(&z->lk);
|
qunlock(&z->lk);
|
||||||
if(vtsend(z, p) < 0)
|
if(vtsend(z, p) < 0){
|
||||||
|
vtfree(r);
|
||||||
return nil;
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
qlock(&z->lk);
|
qlock(&z->lk);
|
||||||
/* wait for the muxer to give us our packet */
|
/* wait for the muxer to give us our packet */
|
||||||
|
|
@ -85,6 +88,7 @@ _vtrpc(VtConn *z, Packet *p, VtFcall *tx)
|
||||||
if((p = vtrecv(z)) == nil){
|
if((p = vtrecv(z)) == nil){
|
||||||
werrstr("unexpected eof on venti connection");
|
werrstr("unexpected eof on venti connection");
|
||||||
z->muxer = 0;
|
z->muxer = 0;
|
||||||
|
vtfree(r);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
qlock(&z->lk);
|
qlock(&z->lk);
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ vtrecvproc(void *v)
|
||||||
_vtqhangup(q);
|
_vtqhangup(q);
|
||||||
while((p = _vtnbqrecv(q)) != nil)
|
while((p = _vtnbqrecv(q)) != nil)
|
||||||
packetfree(p);
|
packetfree(p);
|
||||||
vtfree(q);
|
_vtqfree(q);
|
||||||
z->readq = nil;
|
z->readq = nil;
|
||||||
rwakeup(&z->rpcfork);
|
rwakeup(&z->rpcfork);
|
||||||
qunlock(&z->lk);
|
qunlock(&z->lk);
|
||||||
|
|
@ -178,7 +178,7 @@ vtsendproc(void *v)
|
||||||
_vtqhangup(q);
|
_vtqhangup(q);
|
||||||
while((p = _vtnbqrecv(q)) != nil)
|
while((p = _vtnbqrecv(q)) != nil)
|
||||||
packetfree(p);
|
packetfree(p);
|
||||||
vtfree(q);
|
_vtqfree(q);
|
||||||
z->writeq = nil;
|
z->writeq = nil;
|
||||||
rwakeup(&z->rpcfork);
|
rwakeup(&z->rpcfork);
|
||||||
qunlock(&z->lk);
|
qunlock(&z->lk);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue