ref: 9c12f278297212e8644ba85975f2b1ab3bd2c8b9
parent: 521bb145a502cdb04984d67336c959a2fed424fa
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Dec 26 13:31:37 EST 2023
fs; make mounts participate in deferred reclamation there was a deadlock with the mountlk, where both sides of the channel required the mountlk to be held; this could be fixed in several ways, but the most elegant is eliminating the lock entirely. The data isn't mutated often.
--- a/dat.h
+++ b/dat.h
@@ -434,6 +434,7 @@
enum {
DFblk,
+ DFmnt,
DFtree,
};
@@ -440,6 +441,7 @@
struct Bfree {
Bfree *next;
int op;
+ Mount *m;
Tree *t;
Blk *b;
Bptr bp;
@@ -507,7 +509,6 @@
QLock synclk;
Rendez syncrz;
- Lock mountlk;
Mount *mounts;
Mount *snapmnt;
Lock connlk;
--- a/fs.c
+++ b/fs.c
@@ -86,11 +86,9 @@
* can take a consistent snapshot.
*/
qlock(&fs->mutlk);
- lock(&fs->mountlk);
dlsync();
- for(mnt = fs->mounts; mnt != nil; mnt = mnt->next)
+ for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next)
updatesnap(&mnt->root, mnt->root, mnt->name);
- unlock(&fs->mountlk);
for(i = 0; i < fs->narena; i++){
a = &fs->arenas[i];
qlock(a);
@@ -174,15 +172,13 @@
Tree *t, *s;
Mount *mnt;
- lock(&fs->mountlk);
if(waserror()){
*tp = nil;
- unlock(&fs->mountlk);
nexterror();
}
t = nil;
*tp = nil;
- for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+ for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
if(strcmp(a->old, mnt->name) == 0){
updatesnap(&mnt->root, mnt->root, mnt->name);
t = agetp(&mnt->root);
@@ -193,7 +189,6 @@
if(t == nil && (t = opensnap(a->old, nil)) == nil){
if(a->fd != -1)
fprint(a->fd, "snap: open '%s': does not exist\n", a->old);
- unlock(&fs->mountlk);
poperror();
return;
}
@@ -201,7 +196,6 @@
if(mnt != nil) {
if(a->fd != -1)
fprint(a->fd, "snap: snap is mounted: '%s'\n", a->old);
- unlock(&fs->mountlk);
poperror();
return;
}
@@ -215,7 +209,6 @@
if(a->fd != -1)
fprint(a->fd, "snap: already exists '%s'\n", a->new);
closesnap(s);
- unlock(&fs->mountlk);
poperror();
return;
}
@@ -222,7 +215,6 @@
tagsnap(t, a->new, a->flag);
}
closesnap(t);
- unlock(&fs->mountlk);
poperror();
if(a->fd != -1){
if(a->delete)
@@ -593,8 +585,7 @@
return fs->snapmnt;
}
- lock(&fs->mountlk);
- for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+ for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
if(strcmp(name, mnt->name) == 0){
ainc(&mnt->ref);
goto Out;
@@ -604,7 +595,6 @@
if((mnt = mallocz(sizeof(*mnt), 1)) == nil)
error(Enomem);
if(waserror()){
- unlock(&fs->mountlk);
free(mnt);
nexterror();
}
@@ -617,11 +607,10 @@
mnt->noauto = (flg & Lnoauto) != 0;
mnt->root = t;
mnt->next = fs->mounts;
- fs->mounts = mnt;
+ asetp(&fs->mounts, mnt);
poperror();
Out:
- unlock(&fs->mountlk);
return mnt;
}
@@ -629,10 +618,10 @@
clunkmount(Mount *mnt)
{
Mount *me, **p;
+ Bfree *f;
if(mnt == nil)
return;
- lock(&fs->mountlk);
if(adec(&mnt->ref) == 0){
for(p = &fs->mounts; (me = *p) != nil; p = &me->next){
if(me == mnt)
@@ -639,10 +628,12 @@
break;
}
assert(me != nil);
+ f = emalloc(sizeof(Bfree), 0);
+ f->op = DFblk;
+ f->m = mnt;
*p = me->next;
- free(mnt);
+ limbo(f);
}
- unlock(&fs->mountlk);
}
static void
@@ -2509,8 +2500,7 @@
chsend(fs->admchan, a);
tmnow(&now, nil);
- lock(&fs->mountlk);
- for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+ for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
if(mnt->noauto)
continue;
if(now.yday != then.yday){
@@ -2533,7 +2523,6 @@
snapmsg("main", mnt->minutely[m], Lauto);
}
}
- unlock(&fs->mountlk);
if(now.hour != then.hour)
h = (h+1)%24;
if(now.min != then.min)
--- a/snap.c
+++ b/snap.c
@@ -3,9 +3,9 @@
#include <fcall.h>
#include <avl.h>
+#include "atomic.h"
#include "dat.h"
#include "fns.h"
-#include "atomic.h"
static void
dlflush(Dlist *dl)
@@ -310,7 +310,7 @@
btupsert(&fs->snap, m, nm);
reclaimblocks(t->gen, succ, t->pred);
if(deltree){
- for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
+ for(mnt = agetp(&fs->mounts); mnt != nil; mnt = mnt->next){
if(mnt->root->gen == t->succ)
mnt->root->pred = t->pred;
if(mnt->root->gen == t->pred)