ref: 1edcad42b69b0deddf8befff489682cf94c2376d
parent: 39d119309f93dedbcd10f9004633c7a69c1f891d
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Oct 22 00:28:30 EDT 2023
fs: stop leaking blocks when truncating files
--- a/dat.h
+++ b/dat.h
@@ -378,7 +378,9 @@
};
struct { /* AOclear */
Mount *mnt;
+ Dent *dent;
vlong qpath;
+ vlong off;
vlong length;
};
};
--- a/fs.c
+++ b/fs.c
@@ -1203,11 +1203,11 @@
}
static void
-fswstat(Fmsg *m)
+fswstat(Fmsg *m, Amsg **ao)
{
char rnbuf[Kvmax], opbuf[Kvmax], upbuf[Upksz];
char *p, *e, strs[65535];
- int op, nm, rename;
+ int op, nm, rename, truncate;
vlong oldlen;
Qid old;
Fcall r;
@@ -1220,6 +1220,7 @@
User *u;
rename = 0;
+ truncate = 0;
if((f = getfid(m->conn, m->fid)) == nil){
rerror(m, Enofid);
return;
@@ -1275,6 +1276,20 @@
goto Out;
}
if(d.length != de->length){
+ if(d.length < de->length){
+ if((*ao = malloc(sizeof(Amsg))) == nil){
+ rerror(m, Enomem);
+ goto Out;
+ }
+ aincl(&f->mnt->ref, 1);
+ (*ao)->op = AOclear;
+ (*ao)->mnt = f->mnt;
+ (*ao)->qpath = f->qpath;
+ (*ao)->off = d.length;
+ (*ao)->length = f->dent->length;
+ (*ao)->dent = de;
+ truncate = 1;
+ }
n.length = d.length;
op |= Owsize;
PACK64(p, n.length);
@@ -1425,7 +1440,8 @@
respond(m, &r);
Out:
- wunlock(de);
+ if(!truncate)
+ wunlock(de);
putfid(f);
}
@@ -1637,7 +1653,9 @@
(*ao)->op = AOclear;
(*ao)->mnt = f->mnt;
(*ao)->qpath = f->qpath;
+ (*ao)->off = 0;
(*ao)->length = f->dent->length;
+ (*ao)->dent = nil;
}
f->dent->gone = 1;
wunlock(f->dent);
@@ -1742,7 +1760,9 @@
(*ao)->op = AOclear;
(*ao)->mnt = f->mnt;
(*ao)->qpath = f->qpath;
+ (*ao)->off = 0;
(*ao)->length = f->dent->length;
+ (*ao)->dent = nil;
if((e = upsert(f->mnt, &mb, 1)) != nil){
Error:
wunlock(f->dent);
@@ -2182,7 +2202,7 @@
switch(m->type){
case Tcreate: fscreate(m); break;
case Twrite: fswrite(m); break;
- case Twstat: fswstat(m); break;
+ case Twstat: fswstat(m, &a); break;
case Tremove: fsremove(m,&a); break;
case Topen: fsopen(m, &a); break;
default: abort(); break;
@@ -2246,7 +2266,7 @@
qunlock(&fs->mutlk);
break;
case AOclear:
- for(off = 0; off < a->length; off += Blksz){
+ for(off = a->off; off < a->length; off += Blksz){
qlock(&fs->mutlk);
epochstart(id);
m.k = buf;
@@ -2264,6 +2284,10 @@
epochend(id);
qunlock(&fs->mutlk);
epochclean();
+ }
+ if(a->dent != nil){
+ wunlock(a->dent);
+ clunkdent(a->dent);
}
clunkmount(a->mnt);
break;