ref: f00b8cacec187ab539b5cbbaaa3583051f0ad8e6
parent: 016441e84b12c4b48304ac0ab814a802bf60516e
author: kvik <kvik@a-b.xyz>
date: Wed May 15 23:08:36 EDT 2019
store directory contents in a dynamic array instead of a linked list this fixes a problem with reading big directories, where a directory entry got skipped per read response because of the weird way the walking was done in tandem with dirread9p(2). it should be a bit memory friendlier and faster, too.
--- a/unionfs.c
+++ b/unionfs.c
@@ -6,7 +6,7 @@
typedef struct Union Union;
typedef struct Fil Fil;
-typedef struct Flist Flist;
+typedef struct List List;
typedef struct Fstate Fstate;
typedef struct Qidmap Qidmap;
@@ -38,15 +38,15 @@
char *fspath; /* internal path */
};
-struct Flist {
- Fil *file;
- Flist *next;
+struct List {
+ long n, sz;
+ Fil **l;
};
struct Fstate {
int fd;
Fil *file;
- Flist *dir, *idx;
+ List *flist;
};
Union u0 = {.next = &u0, .prev = &u0};
@@ -63,11 +63,20 @@
if((v = malloc(sz)) == nil)
sysfatal("emalloc: %r");
memset(v, 0, sz);
-
setmalloctag(v, getcallerpc(&sz));
+
return v;
}
+void*
+erealloc(void *v, ulong sz)
+{
+ if((v = realloc(v, sz)) == nil && sz != 0)
+ sysfatal("realloc: %r");
+ setrealloctag(v, getcallerpc(&v));
+ return v;
+}
+
char*
estrdup(char *s)
{
@@ -233,34 +242,47 @@
free(f);
}
-void
-flistadd(Flist **list, Fil *f)
+List*
+lnew(void)
{
- Flist *p;
+ List *l;
- p = emalloc(sizeof(*p));
- p->file = f;
- p->next = *list;
- *list = p;
+ l = emalloc(sizeof *l);
+ l->n = 0;
+ l->sz = 256;
+ l->l = emalloc(l->sz*sizeof(*l->l));
+
+ return l;
}
void
-flistfree(Flist *l)
+lfree(List *l)
{
- Flist *lp;
+ int i;
- for(lp = l; lp != nil; l = lp){
- lp = lp->next;
- filefree(l->file);
- free(l);
+ for(i = 0; i < l->n; i++)
+ filefree(l->l[i]);
+}
+
+int
+ladd(List *l, Fil *f)
+{
+ if(l->n == l->sz){
+ l->sz *= 2;
+ l->l = erealloc(l->l, l->sz*sizeof(*l->l));
}
+ l->l[l->n++] = f;
+
+ return l->n;
}
int
-flisthas(Flist *list, char *name)
+lhas(List *l, char *name)
{
- for(; list != nil; list = list->next)
- if(strcmp(list->file->name, name) == 0)
+ int i;
+
+ for(i = 0; i < l->n; i++)
+ if(strcmp(l->l[i]->name, name) == 0)
return 1;
return 0;
}
@@ -281,8 +303,8 @@
{
if(st->file)
filefree(st->file);
- if(st->dir)
- flistfree(st->dir);
+ if(st->flist)
+ lfree(st->flist);
close(st->fd);
free(st);
}
@@ -397,7 +419,7 @@
walkandclone(r, walk1, clone, nil);
}
-Flist*
+List*
filereaddir(Fil *p)
{
int fd;
@@ -406,9 +428,9 @@
char *path;
Union *u;
Fil *f;
- Flist *list;
+ List *list;
- list = nil;
+ list = lnew();
for(u = unionlist->next; u != unionlist; u = u->next){
path = mkpath(u->root, p->fspath, nil);
if((d = dirstat(path)) == nil){
@@ -425,10 +447,10 @@
if(n < 0)
continue;
for(i = 0; i < n; i++){
- if(flisthas(list, dir[i].name))
+ if(lhas(list, dir[i].name))
continue;
f = filenew(&dir[i]);
- flistadd(&list, f);
+ ladd(list, f);
}
free(dir);
}
@@ -447,10 +469,9 @@
st = r->fid->aux;
f = st->file;
- if(f->mode&DMDIR){
- st->dir = filereaddir(f);
- st->idx = st->dir;
- }else{
+ if(f->mode&DMDIR)
+ st->flist = filereaddir(f);
+ else{
if((st->fd = open(f->path, i->mode)) < 0){
responderror(r);
return;
@@ -567,17 +588,16 @@
}
int
-dirgen(int, Dir *dir, void *aux)
+dirgen(int i, Dir *dir, void *aux)
{
Fstate *fs;
- Flist *l;
+ List *l;
fs = aux;
- l = fs->idx;
- if(l == nil)
+ l = fs->flist;
+ if(i == l->n)
return -1;
- dirfill(dir, l->file);
- fs->idx = l->next;
+ dirfill(dir, l->l[i]);
return 0;
}