69922e9f17659c8da5eb7e733b3459819d05e329
[akaros.git] / kern / src / ns / pgrp.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 /* TODO: (ID) need a unique ID service.  These will loop around... */
17 static int pgrpid;
18 static int mountid;
19 #define NEXT_ID(x) (__sync_add_and_fetch(&(x), 1))
20
21 void closepgrp(struct pgrp *p)
22 {
23         struct mhead **h, **e, *f, *next;
24
25         wlock(&p->ns);
26         p->pgrpid = -1;
27
28         e = &p->mnthash[MNTHASH];
29         for (h = p->mnthash; h < e; h++) {
30                 for (f = *h; f; f = next) {
31                         wlock(&f->lock);
32                         cclose(f->from);
33                         mountfree(f->mount);
34                         f->mount = NULL;
35                         next = f->hash;
36                         wunlock(&f->lock);
37                         putmhead(f);
38                 }
39         }
40         wunlock(&p->ns);
41         cclose(p->dot);
42         cclose(p->slash);
43         kfree(p);
44 }
45
46 static void freepgrp(struct kref *k)
47 {
48         struct pgrp *p = container_of(k, struct pgrp, ref);
49         closepgrp(p);
50 }
51
52 struct pgrp *newpgrp(void)
53 {
54         struct pgrp *p;
55
56         p = kzmalloc(sizeof(struct pgrp), KMALLOC_WAIT);
57         kref_init(&p->ref, freepgrp, 1);
58         p->pgrpid = NEXT_ID(pgrpid);
59         p->progmode = 0644;
60         qlock_init(&p->debug);
61         rwinit(&p->ns);
62         qlock_init(&p->nsh);
63         return p;
64 }
65
66 void pgrpinsert(struct mount **order, struct mount *m)
67 {
68         struct mount *f;
69
70         m->order = 0;
71         if (*order == 0) {
72                 *order = m;
73                 return;
74         }
75         for (f = *order; f; f = f->order) {
76                 if (m->mountid < f->mountid) {
77                         m->order = f;
78                         *order = m;
79                         return;
80                 }
81                 order = &f->order;
82         }
83         *order = m;
84 }
85
86 /*
87  * pgrpcpy MUST preserve the mountid allocation order of the parent group
88  */
89 void pgrpcpy(struct pgrp *to, struct pgrp *from)
90 {
91         ERRSTACK(2);
92         int i;
93         struct mount *n, *m, **link, *order;
94         struct mhead *f, **tom, **l, *mh;
95
96         wlock(&from->ns);
97         if (waserror()) {
98                 wunlock(&from->ns);
99                 nexterror();
100         }
101         order = 0;
102         tom = to->mnthash;
103         for (i = 0; i < MNTHASH; i++) {
104                 l = tom++;
105                 for (f = from->mnthash[i]; f; f = f->hash) {
106                         rlock(&f->lock);
107                         if (waserror()) {
108                                 runlock(&f->lock);
109                                 nexterror();
110                         }
111                         mh = newmhead(f->from);
112                         if (!mh)
113                                 error(Enomem);
114                         *l = mh;
115                         l = &mh->hash;
116                         link = &mh->mount;
117                         for (m = f->mount; m; m = m->next) {
118                                 n = newmount(mh, m->to, m->mflag, m->spec);
119                                 m->copy = n;
120                                 pgrpinsert(&order, m);
121                                 *link = n;
122                                 link = &n->next;
123                         }
124                         poperror();
125                         runlock(&f->lock);
126                 }
127         }
128         /*
129          * Allocate mount ids in the same sequence as the parent group
130          */
131         /* should probably protect with a spinlock and be done with it */
132         for (m = order; m; m = m->order) {
133                 m->copy->mountid = NEXT_ID(mountid);
134         }
135
136         to->progmode = from->progmode;
137         to->slash = cclone(from->slash);
138         to->dot = cclone(from->dot);
139         to->nodevs = from->nodevs;
140
141         poperror();
142         wunlock(&from->ns);
143 }
144
145 struct mount *newmount(struct mhead *mh, struct chan *to, int flag, char *spec)
146 {
147         struct mount *m;
148
149         m = kzmalloc(sizeof(struct mount), 0);
150         m->to = to;
151         m->head = mh;
152         chan_incref(to);
153         m->mountid = NEXT_ID(mountid);
154         m->mflag = flag;
155         if (spec != 0)
156                 kstrdup(&m->spec, spec);
157
158         return m;
159 }
160
161 void mountfree(struct mount *m)
162 {
163         struct mount *f;
164
165         while (m) {
166                 f = m->next;
167                 cclose(m->to);
168                 m->mountid = 0;
169                 kfree(m->spec);
170                 kfree(m);
171                 m = f;
172         }
173 }
174
175 #if 0
176 almost certainly not needed.void resrcwait(char *reason)
177 {
178         char *p;
179
180         if (current == 0)
181                 panic("resrcwait");
182
183         p = up->psstate;
184         if (reason) {
185                 up->psstate = reason;
186                 printd("%s\n", reason);
187         }
188
189         kthread_usleep(300 * 1000);
190         up->psstate = p;
191 }
192 #endif
193
194 /* TODO: We don't have any alloc / initializer methods for skeyset or signerkey
195  * yet.  When we do, use these releases for their kref_init. */
196 static void __sigs_release(struct kref *kref)
197 {
198         struct skeyset *s = container_of(kref, struct skeyset, ref);
199         int i;
200         for (i = 0; i < s->nkey; i++)
201                 freeskey(s->keys[i]);
202         kfree(s);
203 }
204
205 void closesigs(struct skeyset *s)
206 {
207         if (!s)
208                 return;
209         kref_put(&s->ref);
210 }
211
212 static void __key_release(struct kref *kref)
213 {
214         struct signerkey *key = container_of(kref, struct signerkey, ref);
215         kfree(key->owner);
216         (*key->pkfree) (key->pk);
217         kfree(key);
218 }
219
220 void freeskey(struct signerkey *key)
221 {
222         if (!key)
223                 return;
224         kref_put(&key->ref);
225 }