From owner-p4-projects@FreeBSD.ORG Tue Oct 23 00:15:22 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D582316A418; Tue, 23 Oct 2007 00:15:21 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE39E16A41A for ; Tue, 23 Oct 2007 00:15:20 +0000 (UTC) (envelope-from zec@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id BCE2A13C4A5 for ; Tue, 23 Oct 2007 00:15:20 +0000 (UTC) (envelope-from zec@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l9N0FKEY020590 for ; Tue, 23 Oct 2007 00:15:20 GMT (envelope-from zec@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l9N0FKJd020587 for perforce@freebsd.org; Tue, 23 Oct 2007 00:15:20 GMT (envelope-from zec@FreeBSD.org) Date: Tue, 23 Oct 2007 00:15:20 GMT Message-Id: <200710230015.l9N0FKJd020587@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to zec@FreeBSD.org using -f From: Marko Zec To: Perforce Change Reviews Cc: Subject: PERFORCE change 127941 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Oct 2007 00:15:22 -0000 http://perforce.freebsd.org/chv.cgi?CH=127941 Change 127941 by zec@zec_tpx32 on 2007/10/23 00:14:43 Replace a flat vimage naming scheme with a hierarchical one. "default" as a vimage name is deprecated. "." always corresponds to the current vimage. Naming of direct child vimages hasn't changed, however each level in vimage hierarchy now has an independent naming scope. For example, a vimage named "x" can have a child named "x", which was impossible with the old flat naming model. Direct addressing of vimages deeper in the hierarchy is possible using "." as a delimeter, for example "x.x" corresponds to child "x" of vimage "x". It is also possible to instantiate new vimages at arbitrary levels bellow current position in the hierarchy, for example "vimage -c x.y" would create a vimage "y" as a child of "x". Command "vimage x vimage -c y" would have the same effect. Affected files ... .. //depot/projects/vimage/src/sys/kern/kern_vimage.c#50 edit Differences ... ==== //depot/projects/vimage/src/sys/kern/kern_vimage.c#50 (text+ko) ==== @@ -64,7 +64,7 @@ MALLOC_DEFINE(M_VPROCG, "vprocg", "process group control block"); MALLOC_DEFINE(M_VCPU, "vcpu", "cpu resource control block"); -static struct vimage *vi_alloc(char *, int); +static struct vimage *vi_alloc(struct vimage *, char *); static int vi_destroy(struct vimage *); static void vnet_mod_complete_registration(struct vnet_modlink *); static int vnet_mod_constructor(struct vnet_modlink *); @@ -444,6 +444,76 @@ } +static struct vimage * +vimage_by_name(struct vimage *top, char *name) +{ + struct vimage *vip; + char *next_name; + int namelen; + + next_name = strchr(name, '.'); + if (next_name != NULL) { + namelen = next_name - name; + next_name++; + if (namelen == 0) { + if (strlen(next_name) == 0) + return(top); /* '.' == this vimage */ + else + return(NULL); + } + } else + namelen = strlen(name); + if (namelen == 0) + return(NULL); + LIST_FOREACH(vip, &top->vi_child_head, vi_sibilings) + if (strncmp(name, vip->vi_name, namelen) == 0) { + if (next_name != NULL) + return(vimage_by_name(vip, next_name)); + else + return(vip); + } + return(NULL); +} + + +static int +vimage_relative_name(struct vimage *top, struct vimage *where, + char *buffer, int bufflen) +{ + if (where == top) { + sprintf(buffer, "."); + return(1); + } + + if (where->vi_parent != top) { + int len; + + len = vimage_relative_name(top, where->vi_parent, + buffer, bufflen); + bufflen -= (len + 1); + buffer += len; + sprintf(buffer++, "."); + } + + sprintf(buffer, "%s", where->vi_name); + return(strlen(where->vi_name)); +} + + +static struct vimage * +vimage_get_next(struct vimage *top, struct vimage *where) +{ + do { + where = LIST_NEXT(where, vi_le); + if (where == NULL) + where = LIST_FIRST(&vimage_head); + if (vi_child_of(top, where)) + return(where); + } while (where != top); + return(NULL); +} + + int vi_td_ioctl(cmd, vi_req, td) u_long cmd; @@ -453,44 +523,23 @@ int error; struct vimage *vip = TD_TO_VIMAGE(td); struct vimage *vip_r = NULL; - struct vimage *tvip; error = suser(td); /* XXX replace with priv(9) */ if (error) return (error); - VNET_LIST_LOCK(); /* XXX should lock vimage list... */ - if (strlen(vi_req->vi_name)) { - LIST_FOREACH(tvip, &vimage_head, vi_le) - if (strcmp(vi_req->vi_name, tvip->vi_name)==0) { - vip_r = tvip; - break; - } - if (vip_r == NULL && !(vi_req->req_action & VI_CREATE)) { - VNET_LIST_UNLOCK(); /* XXX */ + vip_r = vimage_by_name(vip, vi_req->vi_name); + if (vip_r == NULL && !(vi_req->req_action & VI_CREATE)) + return (ESRCH); + if (vip_r != NULL && vi_req->req_action & VI_CREATE) + return (EADDRINUSE); + if (vi_req->req_action == VI_GETNEXT) { + vip_r = vimage_get_next(vip, vip_r); + if (vip_r == NULL) return (ESRCH); - } - if (vip_r != NULL && vi_req->req_action & VI_CREATE) { - VNET_LIST_UNLOCK(); /* XXX */ - return (EADDRINUSE); - } - if (vi_req->req_action == VI_GETNEXT) { -vi_getnext_loop: - if ((vip_r = LIST_NEXT(vip_r, vi_le)) == 0) - vip_r = LIST_FIRST(&vimage_head); - if (vip_r == vip) { - VNET_LIST_UNLOCK(); /* XXX */ - return (ESRCH); - } - if (!vi_child_of(vip, vip_r)) - goto vi_getnext_loop; - } + } - } else - vip_r = vip; - VNET_LIST_UNLOCK(); /* XXX */ - - if (vip_r && !vi_child_of(vip, vip_r) && + if (vip_r && !vi_child_of(vip, vip_r) && /* XXX delete the rest! */ vi_req->req_action != VI_GET && vi_req->req_action != VI_GETNEXT) return (EPERM); @@ -498,7 +547,7 @@ case SIOCGPVIMAGE: vi_req->vi_id = vip_r->vi_id; - bcopy(&vip_r->vi_name, &vi_req->vi_name, + vimage_relative_name(vip, vip_r, vi_req->vi_name, sizeof (vi_req->vi_name)); bcopy(&vip_r->v_procg->_averunnable, &vi_req->averunnable, sizeof (vi_req->averunnable)); @@ -520,7 +569,6 @@ /* * XXX priv_check()? - * XXX refcounting ucred -> vimage ? * XXX allow only a single td per proc here? */ newcred = crget(); @@ -545,14 +593,23 @@ } if (vi_req->req_action & VI_CREATE) { - vip_r = vi_alloc(vi_req->vi_name, - vi_req->vi_maxsockets); + char *dotpos; + + dotpos = strrchr(vi_req->vi_name, '.'); + if (dotpos != NULL) { + *dotpos = 0; + vip = vimage_by_name(vip, vi_req->vi_name); + if (vip == NULL) + return (ESRCH); + dotpos++; + vip_r = vi_alloc(vip, dotpos); + } else + vip_r = vi_alloc(vip, vi_req->vi_name); if (vip_r == NULL) return (ENOMEM); - - vip_r->vi_parent = vip; } + /* XXX What the hell is this doing here? */ if (vip == vip_r && !IS_DEFAULT_VIMAGE(vip)) return (EPERM); } @@ -591,7 +648,7 @@ struct vimage * -vi_alloc(char *name, int maxsock) +vi_alloc(struct vimage *parent, char *name) { struct vimage *vip; struct vnet *vnet; @@ -613,6 +670,15 @@ if (vip == NULL) panic("vi_alloc: malloc failed for vimage \"%s\"\n", name); vip->vi_id = last_vi_id++; + LIST_INIT(&vip->vi_child_head); + sprintf(vip->vi_name, "%s", name); + vip->vi_parent = parent; + /* XXX locking */ + if (parent != NULL) + LIST_INSERT_HEAD(&parent->vi_child_head, vip, vi_sibilings); + else if (!LIST_EMPTY(&vimage_head)) + panic("there can be only one default vimage!"); + LIST_INSERT_HEAD(&vimage_head, vip, vi_le); vnet = vi_malloc(sizeof(struct vnet), M_VNET, M_NOWAIT | M_ZERO); if (vnet == NULL) @@ -633,9 +699,6 @@ vip->v_cpu = vcpu; vcpu->vcpu_id = last_vcpu_id++; - /* Struct vimage initialization */ - sprintf(vip->vi_name, "%s", name); - /* Struct vprocg initialization - perhaps move to anther place? */ V_averunnable.fscale = FSCALE; @@ -656,9 +719,6 @@ LIST_INSERT_HEAD(&vcpu_head, vcpu, vcpu_le); mtx_unlock_spin(&vcpu_list_mtx); - /* XXX locking */ - LIST_INSERT_HEAD(&vimage_head, vip, vi_le); - vi_alloc_done: return (vip); } @@ -679,6 +739,9 @@ struct vnet_modlink *vml; /* XXX Beware of races -> more locking to be done... */ + if (!LIST_EMPTY(&vip->vi_child_head)) + return (EBUSY); + if (vprocg->nprocs != 0) return (EBUSY); @@ -689,6 +752,18 @@ printf("vi_destroy: %s ucredrefc %d\n", vip->vi_name, vip->vi_ucredrefc); + /* Point with no return - cleanup MUST succeed! */ + /* XXX locking */ + LIST_REMOVE(vip, vi_le); + LIST_REMOVE(vip, vi_sibilings); + + /* XXX locking */ + LIST_REMOVE(vprocg, vprocg_le); + + mtx_lock_spin(&vcpu_list_mtx); + LIST_REMOVE(vcpu, vcpu_le); + mtx_unlock_spin(&vcpu_list_mtx); + VNET_LIST_LOCK(); LIST_REMOVE(vnet, vnet_le); VNET_LIST_UNLOCK(); @@ -720,19 +795,10 @@ CURVNET_RESTORE(); /* hopefully, we are finally OK to free the vnet container itself! */ - vnet->vnet_magic_n = -1; + vnet->vnet_magic_n = 0xdeadbeef; vi_free(vnet, M_VNET); - - /* XXX lock those bellow... */ - LIST_REMOVE(vprocg, vprocg_le); vi_free(vprocg, M_VPROCG); - - mtx_lock_spin(&vcpu_list_mtx); - LIST_REMOVE(vcpu, vcpu_le); - mtx_unlock_spin(&vcpu_list_mtx); vi_free(vcpu, M_VCPU); - - LIST_REMOVE(vip, vi_le); vi_free(vip, M_VIMAGE); return (0); @@ -830,7 +896,7 @@ mtx_init(&vcpu_list_mtx, "vcpu_list_mtx", NULL, MTX_SPIN); - vi_alloc("default", 0); + vi_alloc(NULL, ""); /* Default vimage has no name */ /* We MUST clear curvnet in vi_init_done before going SMP. */ curvnet = LIST_FIRST(&vnet_head);