summaryrefslogtreecommitdiff
path: root/emu/port/uqid.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /emu/port/uqid.c
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'emu/port/uqid.c')
-rw-r--r--emu/port/uqid.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/emu/port/uqid.c b/emu/port/uqid.c
new file mode 100644
index 00000000..bd43db3d
--- /dev/null
+++ b/emu/port/uqid.c
@@ -0,0 +1,114 @@
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+
+/*
+ * unique Qid path generation,
+ * for exportfs.c and various devfs-*
+ */
+
+#define QIDMASK (((vlong)1<<48)-1)
+
+void
+uqidinit(Uqidtab *tab)
+{
+ memset(tab, 0, sizeof(*tab));
+}
+
+static int
+uqidhash(vlong path)
+{
+ ulong p;
+ p = (ulong)path;
+ return ((p>>16) ^ (p>>8) ^ p) & (Nqidhash-1);
+}
+
+static Uqid **
+uqidlook(Uqid **tab, Chan *c, vlong path)
+{
+ Uqid **hp, *q;
+
+ for(hp = &tab[uqidhash(path)]; (q = *hp) != nil; hp = &q->next)
+ if(q->type == c->type && q->dev == c->dev && q->oldpath == path)
+ break;
+ return hp;
+}
+
+static int
+uqidexists(Uqid **tab, vlong path)
+{
+ int i;
+ Uqid *q;
+
+ for(i=0; i<Nqidhash; i++)
+ for(q = tab[i]; q != nil; q = q->next)
+ if(q->newpath == path)
+ return 1;
+ return 0;
+}
+
+Uqid *
+uqidalloc(Uqidtab *tab, Chan *c)
+{
+ Uqid **hp, *q;
+
+ qlock(&tab->l);
+ hp = uqidlook(tab->qids, c, c->qid.path);
+ if((q = *hp) != nil){
+ incref(&q->r);
+ qunlock(&tab->l);
+ return q;
+ }
+ q = mallocz(sizeof(*q), 1);
+ if(q == nil){
+ qunlock(&tab->l);
+ error(Enomem);
+ }
+ q->r.ref = 1;
+ q->type = c->type;
+ q->dev = c->dev;
+ q->oldpath = c->qid.path;
+ q->newpath = c->qid.path;
+ while(uqidexists(tab->qids, q->newpath)){
+ if(++tab->pathgen >= (1<<16))
+ tab->pathgen = 1;
+ q->newpath = ((vlong)tab->pathgen<<48) | (q->newpath & QIDMASK);
+ }
+ q->next = nil;
+ *hp = q;
+ qunlock(&tab->l);
+ return q;
+}
+
+void
+freeuqid(Uqidtab *tab, Uqid *q)
+{
+ Uqid **hp;
+
+ if(q == nil)
+ return;
+ qlock(&tab->l);
+ if(decref(&q->r) == 0){
+ hp = &tab->qids[uqidhash(q->oldpath)];
+ for(; *hp != nil; hp = &(*hp)->next)
+ if(*hp == q){
+ *hp = q->next;
+ free(q);
+ break;
+ }
+ }
+ qunlock(&tab->l);
+}
+
+Qid
+mkuqid(Chan *c, Uqid *qid)
+{
+ Qid q;
+
+ if(qid == nil)
+ return c->qid;
+ q.path = qid->newpath;
+ q.vers = c->qid.vers;
+ q.type = c->qid.type;
+ return q;
+}