123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- #include <u.h>
- #include <libc.h>
- #include <auth.h>
- #include <fcall.h>
- #include <thread.h>
- #include <9p.h>
- #include "flashfs.h"
- static int nextfnum;
- static Intmap* map;
- static Dir dirproto;
- static char user[] = "flash";
- Entry *root;
- ulong used;
- ulong limit;
- ulong maxwrite;
- enum
- {
- debug = 0,
- };
- static int
- fnum(void)
- {
- return ++nextfnum;
- }
- static void
- maxfnum(int n)
- {
- if(n > nextfnum)
- nextfnum = n;
- }
- static int
- hash(char *s)
- {
- int c, d, h;
- h = 0;
- while((c = *s++) != '\0') {
- d = c;
- c ^= c << 6;
- h += (c << 11) ^ (c >> 1);
- h ^= (d << 14) + (d << 7) + (d << 4) + d;
- }
- if(h < 0)
- return ~h;
- return h;
- }
- static void
- dirinit(Entry *e)
- {
- Entry **t;
- e->size = 0;
- t = emalloc9p(HSIZE * sizeof(Entry*));
- memset(t, 0, HSIZE * sizeof(Entry*));
- e->htab = t;
- e->files = nil;
- e->readers = nil;
- }
- static void
- fileinit(Entry *e)
- {
- e->size = 0;
- e->gen[0].head = nil;
- e->gen[0].tail = nil;
- e->gen[1].head = nil;
- e->gen[1].tail = nil;
- }
- static void
- elfree(Extent *x)
- {
- Extent *t;
- while(x != nil) {
- t = x->next;
- used -= x->size;
- free(x);
- x = t;
- }
- }
- static void
- extfree(Entry *e)
- {
- elfree(e->gen[0].head);
- elfree(e->gen[1].head);
- }
- static void
- efree(Entry *e)
- {
- if(debug)
- fprint(2, "free %s\n", e->name);
- if(e->mode & DMDIR)
- free(e->htab);
- else
- extfree(e);
- free(e->name);
- free(e);
- }
- void
- einit(void)
- {
- Entry *e;
- e = emalloc9p(sizeof(Entry));
- e->ref = 1;
- e->parent = nil;
- dirinit(e);
- e->name = estrdup9p("");
- e->fnum = 0;
- e->mode = DMDIR | 0775;
- e->mnum = 0;
- e->mtime = 0;
- root = e;
- map = allocmap(nil);
- }
- static void
- dumptree(Entry *e, int n)
- {
- Entry *l;
- if(debug)
- fprint(2, "%d %s %d\n", n, e->name, e->ref);
- if(e->mode & DMDIR) {
- n++;
- for(l = e->files; l != nil; l = l->fnext)
- dumptree(l, n);
- }
- }
- void
- edump(void)
- {
- if(debug)
- dumptree(root, 0);
- }
- Entry *
- elookup(ulong key)
- {
- if(key == 0)
- return root;
- maxfnum(key);
- return lookupkey(map, key);
- }
- Extent *
- esum(Entry *e, int sect, ulong addr, int *more)
- {
- Exts *x;
- Extent *t, *u;
- x = &e->gen[eparity];
- t = x->tail;
- if(t == nil || t->sect != sect || t->addr != addr)
- return nil;
- u = t->prev;
- if(u != nil) {
- u->next = nil;
- *more = 1;
- }
- else {
- x->head = nil;
- *more = 0;
- }
- x->tail = u;
- x = &e->gen[eparity^1];
- u = x->head;
- t->next = u;
- x->head = t;
- if(u == nil)
- x->tail = t;
- else
- u->prev = t;
- return t;
- }
- void
- edestroy(Entry *e)
- {
- e->ref--;
- if(e->ref == 0)
- efree(e);
- }
- Entry *
- ecreate(Entry *d, char *name, ulong n, ulong mode, ulong mtime, char **err)
- {
- int h;
- Entry *e, *f;
- h = hash(name) & HMASK;
- for(e = d->htab[h]; e != nil; e = e->hnext) {
- if(strcmp(e->name, name) == 0) {
- *err = Eexists;
- return nil;
- }
- }
- e = emalloc9p(sizeof(Entry));
- e->ref = 1;
- e->parent = d;
- d->ref++;
- f = d->htab[h];
- e->hnext = f;
- e->hprev = nil;
- if(f != nil)
- f->hprev = e;
- d->htab[h] = e;
- f = d->files;
- e->fnext = f;
- e->fprev = nil;
- if(f != nil)
- f->fprev = e;
- d->files = e;
- d->ref--;
- e->ref++;
- e->name = estrdup9p(name);
- if(n == 0)
- n = fnum();
- else
- maxfnum(n);
- insertkey(map, n, e);
- e->fnum = n;
- e->mode = mode & d->mode;
- e->mnum = 0;
- e->mtime = mtime;
- if(e->mode & DMDIR)
- dirinit(e);
- else
- fileinit(e);
- d->mtime = mtime;
- return e;
- }
- void
- etrunc(Entry *e, ulong n, ulong mtime)
- {
- extfree(e);
- deletekey(map, e->fnum);
- if(n == 0)
- n = fnum();
- else
- maxfnum(n);
- e->fnum = n;
- e->mnum = 0;
- e->mtime = mtime;
- insertkey(map, n, e);
- fileinit(e);
- e->parent->mtime = mtime;
- }
- char *
- eremove(Entry *e)
- {
- Dirr *r;
- Entry *d, *n, *p;
- d = e->parent;
- if(d == nil)
- return Eperm;
- if((e->mode & DMDIR) != 0 && e->files != nil)
- return Edirnotempty;
- p = e->hprev;
- n = e->hnext;
- if(n != nil)
- n->hprev = p;
- if(p != nil)
- p->hnext = n;
- else
- d->htab[hash(e->name) & HMASK] = n;
- for(r = d->readers; r != nil; r = r->next) {
- if(r->cur == e)
- r->cur = e->fnext;
- }
- p = e->fprev;
- n = e->fnext;
- if(n != nil)
- n->fprev = p;
- if(p != nil)
- p->fnext = n;
- else
- d->files = n;
- e->parent = nil;
- d->ref--;
- deletekey(map, e->fnum);
- edestroy(e);
- return nil;
- }
- Entry *
- ewalk(Entry *d, char *name, char **err)
- {
- Entry *e;
- if((d->mode & DMDIR) == 0) {
- *err = Enotdir;
- return nil;
- }
- if(strcmp(name, "..") == 0) {
- e = d->parent;
- if(e == nil)
- return d;
- edestroy(d);
- e->ref++;
- return e;
- }
- for(e = d->htab[hash(name) & HMASK]; e != nil; e = e->hnext) {
- if(strcmp(e->name, name) == 0) {
- d->ref--;
- e->ref++;
- return e;
- }
- }
- *err = Enonexist;
- return nil;
- }
- static void
- eread0(Extent *e, Extent *x, uchar *a, ulong n, ulong off)
- {
- uchar *a0, *a1;
- ulong n0, n1, o0, o1, d, z;
- for(;;) {
- while(e != nil) {
- if(off < e->off + e->size && off + n > e->off) {
- if(off >= e->off) {
- d = off - e->off;
- z = e->size - d;
- if(n <= z) {
- readdata(e->sect, a, n, e->addr + d);
- return;
- }
- readdata(e->sect, a, z, e->addr + d);
- a += z;
- n -= z;
- off += z;
- }
- else {
- a0 = a;
- n0 = e->off - off;
- o0 = off;
- a += n0;
- n -= n0;
- off += n0;
- z = e->size;
- if(n <= z) {
- readdata(e->sect, a, n, e->addr);
- a = a0;
- n = n0;
- off = o0;
- }
- else {
- readdata(e->sect, a, z, e->addr);
- a1 = a + z;
- n1 = n - z;
- o1 = off + z;
- if(n0 < n1) {
- eread0(e->next, x, a0, n0, o0);
- a = a1;
- n = n1;
- off = o1;
- }
- else {
- eread0(e->next, x, a1, n1, o1);
- a = a0;
- n = n0;
- off = o0;
- }
- }
- }
- }
- e = e->next;
- }
- if(x == nil)
- break;
- e = x;
- x = nil;
- }
- memset(a, 0, n);
- }
- ulong
- eread(Entry *e, int parity, void *a, ulong n, ulong off)
- {
- if(n + off >= e->size)
- n = e->size - off;
- if(n <= 0)
- return 0;
- eread0(e->gen[parity].head, e->gen[parity^1].head, a, n, off);
- return n;
- }
- void
- ewrite(Entry *e, Extent *x, int parity, ulong mtime)
- {
- ulong z;
- Extent *t;
- t = e->gen[parity].head;
- x->next = t;
- x->prev = nil;
- e->gen[parity].head = x;
- if(t == nil)
- e->gen[parity].tail = x;
- else
- t->prev = x;
- if(mtime != 0)
- e->mtime = mtime;
- used += x->size;
- z = x->off + x->size;
- if(z > e->size)
- e->size = z;
- }
- ulong
- echmod(Entry *e, ulong mode, ulong mnum)
- {
- if(mnum != 0)
- e->mnum = mnum;
- else
- e->mnum++;
- e->mode &= ~0777;
- e->mode |= mode;
- return e->mnum;
- }
- Qid
- eqid(Entry *e)
- {
- Qid qid;
- if(e->mode & DMDIR)
- qid.type = QTDIR;
- else
- qid.type = 0;
- qid.path = e->fnum;
- return qid;
- }
- void
- estat(Entry *e, Dir *d, int alloc)
- {
- d->type = 'z';
- d->dev = 0;
- if(alloc) {
- d->uid = estrdup9p(user);
- d->gid = estrdup9p(user);
- d->muid = estrdup9p(user);
- d->name = estrdup9p(e->name);
- }
- else {
- d->uid = user;
- d->gid = user;
- d->muid = user;
- d->name = e->name;
- }
- d->mode = e->mode;
- d->length = e->size;
- d->atime = e->mtime;
- d->mtime = e->mtime;
- d->qid = eqid(e);
- }
- Dirr *
- ediropen(Entry *e)
- {
- Dirr *d, *t;
- d = emalloc9p(sizeof(Dirr));
- d->dir = e;
- d->cur = e->files;
- t = e->readers;
- d->next = t;
- d->prev = nil;
- if(t != nil)
- t->prev = d;
- e->readers = d;
- e->ref++;
- return d;
- }
- int
- edirread(Dirr *r, char *a, long n)
- {
- Dir d;
- Entry *e;
- int m, x;
- m = 0;
- for(e = r->cur; e != nil; e = e->fnext) {
- estat(e, &d, 0);
- x = convD2M(&d, (uchar *)a, n);
- if(x <= BIT16SZ)
- break;
- a += x;
- n -= x;
- m += x;
- }
- r->cur = e;
- return m;
- }
- void
- edirclose(Dirr *d)
- {
- Entry *e;
- Dirr *p, *n;
- e = d->dir;
- p = d->prev;
- n = d->next;
- if(n != nil)
- n->prev = p;
- if(p != nil)
- p->next = n;
- else
- e->readers = n;
- edestroy(e);
- free(d);
- }
- static Renum R;
- static void
- xrenum(Extent *x)
- {
- while(x != nil) {
- if(x->sect == R.old)
- x->sect = R.new;
- x = x->next;
- }
- }
- static void
- renum(Entry *e)
- {
- if(e->mode & DMDIR) {
- for(e = e->files; e != nil; e = e->fnext)
- renum(e);
- }
- else {
- xrenum(e->gen[0].head);
- xrenum(e->gen[1].head);
- }
- }
- void
- erenum(Renum *r)
- {
- R = *r;
- renum(root);
- }
|