akaros/kern/src/ns/pgrp.c
<<
>>
Prefs
   1/* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
   2 * Portions Copyright © 1997-1999 Vita Nuova Limited
   3 * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
   4 *                                (www.vitanuova.com)
   5 * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
   6 *
   7 * Modified for the Akaros operating system:
   8 * Copyright (c) 2013-2014 The Regents of the University of California
   9 * Copyright (c) 2013-2015 Google Inc.
  10 *
  11 * Permission is hereby granted, free of charge, to any person obtaining a copy
  12 * of this software and associated documentation files (the "Software"), to deal
  13 * in the Software without restriction, including without limitation the rights
  14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15 * copies of the Software, and to permit persons to whom the Software is
  16 * furnished to do so, subject to the following conditions:
  17 *
  18 * The above copyright notice and this permission notice shall be included in
  19 * all copies or substantial portions of the Software.
  20 *
  21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  27 * SOFTWARE. */
  28
  29#include <slab.h>
  30#include <kmalloc.h>
  31#include <kref.h>
  32#include <string.h>
  33#include <stdio.h>
  34#include <assert.h>
  35#include <error.h>
  36#include <cpio.h>
  37#include <pmap.h>
  38#include <smp.h>
  39#include <net/ip.h>
  40
  41/* TODO: (ID) need a unique ID service.  These will loop around... */
  42static int pgrpid;
  43static int mountid;
  44#define NEXT_ID(x) (__sync_add_and_fetch(&(x), 1))
  45
  46void closepgrp(struct pgrp *p)
  47{
  48        struct mhead **h, **e, *f, *next;
  49
  50        wlock(&p->ns);
  51        p->pgrpid = -1;
  52
  53        e = &p->mnthash[MNTHASH];
  54        for (h = p->mnthash; h < e; h++) {
  55                for (f = *h; f; f = next) {
  56                        wlock(&f->lock);
  57                        cclose(f->from);
  58                        mountfree(f->mount);
  59                        f->mount = NULL;
  60                        next = f->hash;
  61                        wunlock(&f->lock);
  62                        putmhead(f);
  63                }
  64        }
  65        wunlock(&p->ns);
  66        kfree(p);
  67}
  68
  69static void freepgrp(struct kref *k)
  70{
  71        struct pgrp *p = container_of(k, struct pgrp, ref);
  72        closepgrp(p);
  73}
  74
  75struct pgrp *newpgrp(void)
  76{
  77        struct pgrp *p;
  78
  79        p = kzmalloc(sizeof(struct pgrp), MEM_WAIT);
  80        kref_init(&p->ref, freepgrp, 1);
  81        p->pgrpid = NEXT_ID(pgrpid);
  82        p->progmode = 0644;
  83        qlock_init(&p->debug);
  84        rwinit(&p->ns);
  85        qlock_init(&p->nsh);
  86        return p;
  87}
  88
  89void pgrpinsert(struct mount **order, struct mount *m)
  90{
  91        struct mount *f;
  92
  93        m->order = 0;
  94        if (*order == 0) {
  95                *order = m;
  96                return;
  97        }
  98        for (f = *order; f; f = f->order) {
  99                if (m->mountid < f->mountid) {
 100                        m->order = f;
 101                        *order = m;
 102                        return;
 103                }
 104                order = &f->order;
 105        }
 106        *order = m;
 107}
 108
 109/*
 110 * pgrpcpy MUST preserve the mountid allocation order of the parent group
 111 */
 112void pgrpcpy(struct pgrp *to, struct pgrp *from)
 113{
 114        ERRSTACK(2);
 115        int i;
 116        struct mount *n, *m, **link, *order;
 117        struct mhead *f, **tom, **l, *mh;
 118
 119        wlock(&from->ns);
 120        if (waserror()) {
 121                wunlock(&from->ns);
 122                nexterror();
 123        }
 124        order = 0;
 125        tom = to->mnthash;
 126        for (i = 0; i < MNTHASH; i++) {
 127                l = tom++;
 128                for (f = from->mnthash[i]; f; f = f->hash) {
 129                        rlock(&f->lock);
 130                        if (waserror()) {
 131                                runlock(&f->lock);
 132                                nexterror();
 133                        }
 134                        mh = newmhead(f->from);
 135                        if (!mh)
 136                                error(ENOMEM, ERROR_FIXME);
 137                        *l = mh;
 138                        l = &mh->hash;
 139                        link = &mh->mount;
 140                        for (m = f->mount; m; m = m->next) {
 141                                n = newmount(mh, m->to, m->mflag, m->spec);
 142                                m->copy = n;
 143                                pgrpinsert(&order, m);
 144                                *link = n;
 145                                link = &n->next;
 146                        }
 147                        poperror();
 148                        runlock(&f->lock);
 149                }
 150        }
 151        /*
 152         * Allocate mount ids in the same sequence as the parent group
 153         */
 154        /* should probably protect with a spinlock and be done with it */
 155        for (m = order; m; m = m->order) {
 156                m->copy->mountid = NEXT_ID(mountid);
 157        }
 158
 159        to->progmode = from->progmode;
 160        to->nodevs = from->nodevs;
 161
 162        poperror();
 163        wunlock(&from->ns);
 164}
 165
 166struct mount *newmount(struct mhead *mh, struct chan *to, int flag, char *spec)
 167{
 168        struct mount *m;
 169
 170        m = kzmalloc(sizeof(struct mount), 0);
 171        m->to = to;
 172        m->head = mh;
 173        chan_incref(to);
 174        m->mountid = NEXT_ID(mountid);
 175        m->mflag = flag;
 176        if (spec != 0)
 177                kstrdup(&m->spec, spec);
 178
 179        return m;
 180}
 181
 182void mountfree(struct mount *m)
 183{
 184        struct mount *f;
 185
 186        while (m) {
 187                f = m->next;
 188                cclose(m->to);
 189                m->mountid = 0;
 190                kfree(m->spec);
 191                kfree(m);
 192                m = f;
 193        }
 194}
 195
 196#if 0
 197almost certainly not needed.void resrcwait(char *reason)
 198{
 199        char *p;
 200
 201        if (current == 0)
 202                panic("resrcwait");
 203
 204        p = up->psstate;
 205        if (reason) {
 206                up->psstate = reason;
 207                printd("%s\n", reason);
 208        }
 209
 210        kthread_usleep(300 * 1000);
 211        up->psstate = p;
 212}
 213#endif
 214
 215/* TODO: We don't have any alloc / initializer methods for skeyset or signerkey
 216 * yet.  When we do, use these releases for their kref_init. */
 217static void __sigs_release(struct kref *kref)
 218{
 219        struct skeyset *s = container_of(kref, struct skeyset, ref);
 220        int i;
 221        for (i = 0; i < s->nkey; i++)
 222                freeskey(s->keys[i]);
 223        kfree(s);
 224}
 225
 226void closesigs(struct skeyset *s)
 227{
 228        if (!s)
 229                return;
 230        kref_put(&s->ref);
 231}
 232
 233static void __key_release(struct kref *kref)
 234{
 235        struct signerkey *key = container_of(kref, struct signerkey, ref);
 236        kfree(key->owner);
 237        (*key->pkfree) (key->pk);
 238        kfree(key);
 239}
 240
 241void freeskey(struct signerkey *key)
 242{
 243        if (!key)
 244                return;
 245        kref_put(&key->ref);
 246}
 247