add pgrp/fgrp support
[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 static struct kref pgrpid;
17 static struct kref mountid;
18
19 void
20 closepgrp(struct pgrp *p)
21 {
22         struct mhead **h, **e, *f, *next;
23         
24         wlock(&p->ns);
25         p->pgrpid = -1;
26
27         e = &p->mnthash[MNTHASH];
28         for(h = p->mnthash; h < e; h++) {
29                 for(f = *h; f; f = next) {
30                         wlock(&f->lock);
31                         cclose(f->from);
32                         mountfree(f->mount);
33                         f->mount = NULL;
34                         next = f->hash;
35                         wunlock(&f->lock);
36                         putmhead(f);
37                 }
38         }
39         wunlock(&p->ns);
40         cclose(p->dot);
41         cclose(p->slash);
42         kfree(p);
43 }
44
45 static void
46 freepgrp(struct kref *k)
47 {
48         struct pgrp *p = container_of(k, struct pgrp, ref);
49         closepgrp(p);
50 }
51
52 struct pgrp*
53 newpgrp(void)
54 {
55         struct pgrp *p;
56
57         p = kzmalloc(sizeof(struct pgrp), 0);
58         kref_init(&p->ref, freepgrp, 1);
59         kref_get(&pgrpid, 1);
60         p->pgrpid = kref_refcnt(&pgrpid);
61         p->progmode = 0644;
62         return p;
63 }
64
65 void
66 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
90 pgrpcpy(struct pgrp *to, struct pgrp *from)
91 {
92         ERRSTACK(2);
93         int i;
94         struct mount *n, *m, **link, *order;
95         struct mhead *f, **tom, **l, *mh;
96
97         wlock(&from->ns);
98         if(waserror()){
99                 wunlock(&from->ns);
100                 nexterror();
101         }
102         order = 0;
103         tom = to->mnthash;
104         for(i = 0; i < MNTHASH; i++) {
105                 l = tom++;
106                 for(f = from->mnthash[i]; f; f = f->hash) {
107                         rlock(&f->lock);
108                         if(waserror()){
109                                 runlock(&f->lock);
110                                 nexterror();
111                         }
112                         mh = kzmalloc(sizeof(struct mhead), 0);
113                         if(mh == NULL)
114                                 error(Enomem);
115                         mh->from = f->from;
116                         kref_init(&mh->ref, fake_release, 1);
117                         kref_get(&mh->from->ref, 1);
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                 kref_get(&mountid, 1);
138                 m->copy->mountid = kref_refcnt(&mountid);
139         }
140
141         to->progmode = from->progmode;
142         to->slash = cclone(from->slash);
143         to->dot = cclone(from->dot);
144         to->nodevs = from->nodevs;
145
146         poperror();
147         wunlock(&from->ns);
148 }
149
150 void
151 closefgrp(struct fgrp *f)
152 {
153         int i;
154         struct chan *c;
155
156         if(f == NULL || kref_put(&f->ref) != 0)
157                 return;
158
159         for(i = 0; i <= f->maxfd; i++)
160                 if((c = f->fd[i]))
161                         cclose(c);
162
163         kfree(f->fd);
164         kfree(f);
165 }
166
167 static void
168 freefgrp(struct kref *k)
169 {
170         struct fgrp *f = container_of(k, struct fgrp, ref);
171         closefgrp(f);
172 }
173
174 struct fgrp*
175 newfgrp(struct fgrp *old)
176 {
177         struct fgrp *new;
178         int n;
179
180         new = kzmalloc(sizeof(struct fgrp), 0);
181         kref_init(&new->ref, freefgrp, 1);
182         n = DELTAFD;
183         if(old != NULL){
184                 spin_lock(&old->lock);
185                 if(old->maxfd >= n)
186                         n = (old->maxfd+1 + DELTAFD-1)/DELTAFD * DELTAFD;
187                 new->maxfd = old->maxfd;
188                 spin_unlock(&old->lock);
189         }
190         new->nfd = n;
191         new->fd = kzmalloc(n * sizeof(struct chan *), 0);
192         return new;
193 }
194
195 struct fgrp*
196 dupfgrp(struct fgrp *f)
197 {
198         int i;
199         struct chan *c;
200         struct fgrp *new;
201         int n;
202
203         new = kzmalloc(sizeof(struct fgrp), 0);
204         kref_init(&new->ref, freefgrp, 1);
205         spin_lock(&f->lock);
206         n = DELTAFD;
207         if(f->maxfd >= n)
208                 n = (f->maxfd+1 + DELTAFD-1)/DELTAFD * DELTAFD;
209         new->nfd = n;
210         new->fd = kzmalloc(n * sizeof(struct chan *), 0);
211         if(new->fd == NULL){
212                 spin_unlock(&f->lock);
213                 kfree(new);
214                 error(Enomem);
215         }
216         new->maxfd = f->maxfd;
217         new->minfd = f->minfd;
218         for(i = 0; i <= f->maxfd; i++) {
219                 if((c = f->fd[i])){
220                         kref_get(&c->ref, 1);
221                         new->fd[i] = c;
222                 }
223         }
224         spin_unlock(&f->lock);
225
226         return new;
227 }
228
229 struct mount*
230 newmount(struct mhead *mh, struct chan *to, int flag, char *spec)
231 {
232         struct mount *m;
233
234         m = kzmalloc(sizeof(struct mount), 0);
235         m->to = to;
236         m->head = mh;
237         kref_get(&to->ref, 1);
238         kref_get(&mountid, 1);
239         m->mountid = kref_refcnt(&mountid);
240         m->mflag = flag;
241         if(spec != 0)
242                 kstrdup(&m->spec, spec);
243
244         return m;
245 }
246
247 void
248 mountfree(struct mount *m)
249 {
250         struct mount *f;
251
252         while(m) {
253                 f = m->next;
254                 cclose(m->to);
255                 m->mountid = 0;
256                 kfree(m->spec);
257                 kfree(m);
258                 m = f;
259         }
260 }
261
262 #if 0
263 almost certainly not needed.
264 void
265 resrcwait(char *reason)
266 {
267         char *p;
268
269         if(current == 0)
270                 panic("resrcwait");
271
272         p = up->psstate;
273         if(reason) {
274                 up->psstate = reason;
275                 printd("%s\n", reason);
276         }
277
278         udelay_sched(300 * 1000);
279         up->psstate = p;
280 }
281 #endif
282
283 void
284 closesigs(struct skeyset *s)
285 {
286         int i;
287
288         if(s == NULL || kref_put(&s->ref) != 0)
289                 return;
290         for(i=0; i<s->nkey; i++)
291                 freeskey(s->keys[i]);
292         kfree(s);
293 }
294
295 void
296 freeskey(struct signerkey *key)
297 {
298         if(key == NULL || kref_put(&key->ref) != 0)
299                 return;
300         kfree(key->owner);
301         (*key->pkfree)(key->pk);
302         kfree(key);
303 }