All qlocks are initialized
[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
22 closepgrp(struct pgrp *p)
23 {
24         struct mhead **h, **e, *f, *next;
25         
26         wlock(&p->ns);
27         p->pgrpid = -1;
28
29         e = &p->mnthash[MNTHASH];
30         for(h = p->mnthash; h < e; h++) {
31                 for(f = *h; f; f = next) {
32                         wlock(&f->lock);
33                         cclose(f->from);
34                         mountfree(f->mount);
35                         f->mount = NULL;
36                         next = f->hash;
37                         wunlock(&f->lock);
38                         putmhead(f);
39                 }
40         }
41         wunlock(&p->ns);
42         cclose(p->dot);
43         cclose(p->slash);
44         kfree(p);
45 }
46
47 static void
48 freepgrp(struct kref *k)
49 {
50         struct pgrp *p = container_of(k, struct pgrp, ref);
51         closepgrp(p);
52 }
53
54 struct pgrp*
55 newpgrp(void)
56 {
57         struct pgrp *p;
58
59         p = kzmalloc(sizeof(struct pgrp), KMALLOC_WAIT);
60         kref_init(&p->ref, freepgrp, 1);
61         p->pgrpid = NEXT_ID(pgrpid);
62         p->progmode = 0644;
63         qlock_init(&p->debug);
64         qlock_init(&p->nsh);
65         return p;
66 }
67
68 void
69 pgrpinsert(struct mount **order, struct mount *m)
70 {
71         struct mount *f;
72
73         m->order = 0;
74         if(*order == 0) {
75                 *order = m;
76                 return;
77         }
78         for(f = *order; f; f = f->order) {
79                 if(m->mountid < f->mountid) {
80                         m->order = f;
81                         *order = m;
82                         return;
83                 }
84                 order = &f->order;
85         }
86         *order = m;
87 }
88
89 /*
90  * pgrpcpy MUST preserve the mountid allocation order of the parent group
91  */
92 void
93 pgrpcpy(struct pgrp *to, struct pgrp *from)
94 {
95         ERRSTACK(2);
96         int i;
97         struct mount *n, *m, **link, *order;
98         struct mhead *f, **tom, **l, *mh;
99
100         wlock(&from->ns);
101         if(waserror()){
102                 wunlock(&from->ns);
103                 nexterror();
104         }
105         order = 0;
106         tom = to->mnthash;
107         for(i = 0; i < MNTHASH; i++) {
108                 l = tom++;
109                 for(f = from->mnthash[i]; f; f = f->hash) {
110                         rlock(&f->lock);
111                         if(waserror()){
112                                 runlock(&f->lock);
113                                 nexterror();
114                         }
115                         mh = newmhead(f->from);
116                         if (!mh)
117                                 error(Enomem);
118                         *l = mh;
119                         l = &mh->hash;
120                         link = &mh->mount;
121                         for(m = f->mount; m; m = m->next) {
122                                 n = newmount(mh, m->to, m->mflag, m->spec);
123                                 m->copy = n;
124                                 pgrpinsert(&order, m);
125                                 *link = n;
126                                 link = &n->next;
127                         }
128                         poperror();
129                         runlock(&f->lock);
130                 }
131         }
132         /*
133          * Allocate mount ids in the same sequence as the parent group
134          */
135         /* should probably protect with a spinlock and be done with it */
136         for(m = order; m; m = m->order){
137                 m->copy->mountid = NEXT_ID(mountid);
138         }
139
140         to->progmode = from->progmode;
141         to->slash = cclone(from->slash);
142         to->dot = cclone(from->dot);
143         to->nodevs = from->nodevs;
144
145         poperror();
146         wunlock(&from->ns);
147 }
148
149 void
150 closefgrp(struct fgrp *f)
151 {
152         /* TODO: look at this more carefully.  sharing fgrps might be unnecessary,
153          * due to our parallelism style. */
154         /* closefgrp can't be called from proc_destroy, due to races on the fgrp.
155          * current->fgrp is a kref source, and we'd need some form of external sync
156          * to remove it, since multiple kthreads could be accessing current->fgrp.
157          * proc_free is synchronized, for instance.  we could put some sync in the
158          * fgrp, but that would require splitting the deallocation (which we do
159          * manually), and would require not having multiple procs per fgrp (which we
160          * also require).  another option would be to use RCU: clear current->fgrp,
161          * then closefgrp after a grace period. */
162         warn("Don't call closefgrp()");
163
164         if (!f)
165                 return;
166         kref_put(&f->ref);
167 }
168
169 static void
170 freefgrp(struct kref *k)
171 {
172         struct fgrp *f = container_of(k, struct fgrp, ref);
173         struct chan *c;
174         for(int i = 0; i <= f->maxfd; i++)
175                 if((c = f->fd[i]))
176                         cclose(c);
177
178         kfree(f->fd);
179         kfree(f);
180 }
181
182 struct fgrp*
183 newfgrp(void)
184 {
185         struct fgrp *new;
186         int n;
187
188         new = kzmalloc(sizeof(struct fgrp), 0);
189         kref_init(&new->ref, freefgrp, 1);
190         spinlock_init(&new->lock);
191         n = DELTAFD;
192         new->nfd = n;
193         new->fd = kzmalloc(n * sizeof(struct chan *), 0);
194         return new;
195 }
196
197 struct fgrp*
198 dupfgrp(struct fgrp *f)
199 {
200         int i;
201         struct chan *c;
202         struct fgrp *new;
203         int n;
204
205         new = kzmalloc(sizeof(struct fgrp), KMALLOC_WAIT);
206         kref_init(&new->ref, freefgrp, 1);
207         spin_lock(&f->lock);
208         if (f->closed) {
209                 spin_unlock(&f->lock);
210                 kfree(new);
211                 error("File group closed");
212         }
213         n = DELTAFD;
214         if(f->maxfd >= n)
215                 n = (f->maxfd+1 + DELTAFD-1)/DELTAFD * DELTAFD;
216         new->nfd = n;
217         new->fd = kzmalloc(n * sizeof(struct chan *), 0);
218         if(new->fd == NULL){
219                 spin_unlock(&f->lock);
220                 kfree(new);
221                 error(Enomem);
222         }
223         new->maxfd = f->maxfd;
224         new->minfd = f->minfd;
225         for(i = 0; i <= f->maxfd; i++) {
226                 if((c = f->fd[i])){
227                         kref_get(&c->ref, 1);
228                         new->fd[i] = c;
229                 }
230         }
231         spin_unlock(&f->lock);
232
233         return new;
234 }
235
236 struct mount*
237 newmount(struct mhead *mh, struct chan *to, int flag, char *spec)
238 {
239         struct mount *m;
240
241         m = kzmalloc(sizeof(struct mount), 0);
242         m->to = to;
243         m->head = mh;
244         kref_get(&to->ref, 1);
245         m->mountid = NEXT_ID(mountid);
246         m->mflag = flag;
247         if(spec != 0)
248                 kstrdup(&m->spec, spec);
249
250         return m;
251 }
252
253 void
254 mountfree(struct mount *m)
255 {
256         struct mount *f;
257
258         while(m) {
259                 f = m->next;
260                 cclose(m->to);
261                 m->mountid = 0;
262                 kfree(m->spec);
263                 kfree(m);
264                 m = f;
265         }
266 }
267
268 #if 0
269 almost certainly not needed.
270 void
271 resrcwait(char *reason)
272 {
273         char *p;
274
275         if(current == 0)
276                 panic("resrcwait");
277
278         p = up->psstate;
279         if(reason) {
280                 up->psstate = reason;
281                 printd("%s\n", reason);
282         }
283
284         udelay_sched(300 * 1000);
285         up->psstate = p;
286 }
287 #endif
288
289 /* TODO: We don't have any alloc / initializer methods for skeyset or signerkey
290  * yet.  When we do, use these releases for their kref_init. */
291 static void __sigs_release(struct kref *kref)
292 {
293         struct skeyset *s = container_of(kref, struct skeyset, ref);
294         int i;
295         for (i = 0; i < s->nkey; i++)
296                 freeskey(s->keys[i]);
297         kfree(s);
298 }
299
300 void
301 closesigs(struct skeyset *s)
302 {
303         if (!s)
304                 return;
305         kref_put(&s->ref);
306 }
307
308 static void __key_release(struct kref *kref)
309 {
310         struct signerkey *key = container_of(kref, struct signerkey, ref);
311         kfree(key->owner);
312         (*key->pkfree)(key->pk);
313         kfree(key);
314 }
315
316 void
317 freeskey(struct signerkey *key)
318 {
319         if (!key)
320                 return;
321         kref_put(&key->ref);
322 }