PERFORCE change 127941 for review
Marko Zec
zec at FreeBSD.org
Mon Oct 22 17:15:22 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=127941
Change 127941 by zec at 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);
More information about the p4-projects
mailing list