db28ad35fcfc1a4af39fc998ae1f89b9cfa958fb
[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         qlock_init(&p->nsh);
62         return p;
63 }
64
65 void pgrpinsert(struct mount **order, struct mount *m)
66 {
67         struct mount *f;
68
69         m->order = 0;
70         if (*order == 0) {
71                 *order = m;
72                 return;
73         }
74         for (f = *order; f; f = f->order) {
75                 if (m->mountid < f->mountid) {
76                         m->order = f;
77                         *order = m;
78                         return;
79                 }
80                 order = &f->order;
81         }
82         *order = m;
83 }
84
85 /*
86  * pgrpcpy MUST preserve the mountid allocation order of the parent group
87  */
88 void pgrpcpy(struct pgrp *to, struct pgrp *from)
89 {
90         ERRSTACK(2);
91         int i;
92         struct mount *n, *m, **link, *order;
93         struct mhead *f, **tom, **l, *mh;
94
95         wlock(&from->ns);
96         if (waserror()) {
97                 wunlock(&from->ns);
98                 nexterror();
99         }
100         order = 0;
101         tom = to->mnthash;
102         for (i = 0; i < MNTHASH; i++) {
103                 l = tom++;
104                 for (f = from->mnthash[i]; f; f = f->hash) {
105                         rlock(&f->lock);
106                         if (waserror()) {
107                                 runlock(&f->lock);
108                                 nexterror();
109                         }
110                         mh = newmhead(f->from);
111                         if (!mh)
112                                 error(Enomem);
113                         *l = mh;
114                         l = &mh->hash;
115                         link = &mh->mount;
116                         for (m = f->mount; m; m = m->next) {
117                                 n = newmount(mh, m->to, m->mflag, m->spec);
118                                 m->copy = n;
119                                 pgrpinsert(&order, m);
120                                 *link = n;
121                                 link = &n->next;
122                         }
123                         poperror();
124                         runlock(&f->lock);
125                 }
126         }
127         /*
128          * Allocate mount ids in the same sequence as the parent group
129          */
130         /* should probably protect with a spinlock and be done with it */
131         for (m = order; m; m = m->order) {
132                 m->copy->mountid = NEXT_ID(mountid);
133         }
134
135         to->progmode = from->progmode;
136         to->slash = cclone(from->slash);
137         to->dot = cclone(from->dot);
138         to->nodevs = from->nodevs;
139
140         poperror();
141         wunlock(&from->ns);
142 }
143
144 struct mount *newmount(struct mhead *mh, struct chan *to, int flag, char *spec)
145 {
146         struct mount *m;
147
148         m = kzmalloc(sizeof(struct mount), 0);
149         m->to = to;
150         m->head = mh;
151         chan_incref(to);
152         m->mountid = NEXT_ID(mountid);
153         m->mflag = flag;
154         if (spec != 0)
155                 kstrdup(&m->spec, spec);
156
157         return m;
158 }
159
160 void mountfree(struct mount *m)
161 {
162         struct mount *f;
163
164         while (m) {
165                 f = m->next;
166                 cclose(m->to);
167                 m->mountid = 0;
168                 kfree(m->spec);
169                 kfree(m);
170                 m = f;
171         }
172 }
173
174 #if 0
175 almost certainly not needed.void resrcwait(char *reason)
176 {
177         char *p;
178
179         if (current == 0)
180                 panic("resrcwait");
181
182         p = up->psstate;
183         if (reason) {
184                 up->psstate = reason;
185                 printd("%s\n", reason);
186         }
187
188         kthread_usleep(300 * 1000);
189         up->psstate = p;
190 }
191 #endif
192
193 /* TODO: We don't have any alloc / initializer methods for skeyset or signerkey
194  * yet.  When we do, use these releases for their kref_init. */
195 static void __sigs_release(struct kref *kref)
196 {
197         struct skeyset *s = container_of(kref, struct skeyset, ref);
198         int i;
199         for (i = 0; i < s->nkey; i++)
200                 freeskey(s->keys[i]);
201         kfree(s);
202 }
203
204 void closesigs(struct skeyset *s)
205 {
206         if (!s)
207                 return;
208         kref_put(&s->ref);
209 }
210
211 static void __key_release(struct kref *kref)
212 {
213         struct signerkey *key = container_of(kref, struct signerkey, ref);
214         kfree(key->owner);
215         (*key->pkfree) (key->pk);
216         kfree(key);
217 }
218
219 void freeskey(struct signerkey *key)
220 {
221         if (!key)
222                 return;
223         kref_put(&key->ref);
224 }