PERFORCE change 163194 for review
Marko Zec
zec at FreeBSD.org
Sun May 31 19:28:59 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=163194
Change 163194 by zec at zec_tpx32 on 2009/05/31 19:28:20
Fix misintegrations and hopefully unbreak kernel build.
Affected files ...
.. //depot/projects/vimage/src/sys/kern/kern_vimage.c#92 edit
Differences ...
==== //depot/projects/vimage/src/sys/kern/kern_vimage.c#92 (text+ko) ====
@@ -38,14 +38,12 @@
#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/priv.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sx.h>
#include <sys/priv.h>
#include <sys/refcount.h>
#include <sys/vimage.h>
-
#ifdef DDB
#include <ddb/ddb.h>
#endif
@@ -54,34 +52,19 @@
#include <net/route.h>
#include <net/vnet.h>
-#include <net/if_clone.h>
-#include <net/route.h>
-#include <net/vnet.h>
+#ifndef VIMAGE_GLOBALS
-struct vnet_modlink;
-
MALLOC_DEFINE(M_VIMAGE, "vimage", "vimage resource container");
MALLOC_DEFINE(M_VNET, "vnet", "network stack control block");
MALLOC_DEFINE(M_VPROCG, "vprocg", "process group control block");
-#ifdef VIMAGE
-static struct vimage *vi_alloc(struct vimage *, char *);
-static int vi_destroy(struct vimage *);
-#endif
-
-#ifndef VIMAGE
-#ifndef VIMAGE_GLOBALS
-struct vprocg vprocg_0;
-#endif
-#endif
-
-#ifndef VIMAGE_GLOBALS
static TAILQ_HEAD(vnet_modlink_head, vnet_modlink) vnet_modlink_head;
static TAILQ_HEAD(vnet_modpending_head, vnet_modlink) vnet_modpending_head;
static void vnet_mod_complete_registration(struct vnet_modlink *);
static int vnet_mod_constructor(struct vnet_modlink *);
static int vnet_mod_destructor(struct vnet_modlink *);
+#ifdef VIMAGE
static struct vimage *vimage_by_name(struct vimage *, char *);
static struct vimage *vi_alloc(struct vimage *, char *);
static struct vimage *vimage_get_next(struct vimage *, struct vimage *, int);
@@ -625,400 +608,16 @@
}
return (ENOENT);
}
-#endif /* !VIMAGE_GLOBALS */
#ifdef VIMAGE
-struct vimage_list_head vimage_head;
-struct vnet_list_head vnet_head;
-struct vprocg_list_head vprocg_head;
-
-struct cv vnet_list_condvar;
-struct mtx vnet_list_refc_mtx;
-int vnet_list_refc = 0;
-
-#define VNET_LIST_LOCK() \
- mtx_lock(&vnet_list_refc_mtx); \
- while (vnet_list_refc != 0) \
- cv_wait(&vnet_list_condvar, &vnet_list_refc_mtx);
-
-#define VNET_LIST_UNLOCK() \
- mtx_unlock(&vnet_list_refc_mtx);
-
-static u_int last_vi_id = 0;
-static u_int last_vnet_id = 0;
-static u_int last_vprocg_id = 0;
-
-struct vimage *
-vnet2vimage(struct vnet *vnet)
-{
- struct vimage *vip;
-
- LIST_FOREACH(vip, &vimage_head, vi_le)
- if (vip->v_net == vnet)
- return(vip);
-
- panic("vnet2vimage"); /* must never happen */
-}
-
-char *
-vnet_name(struct vnet *vnet)
-{
- return(vnet2vimage(vnet)->vi_name);
-}
-
-
-int
-vi_child_of(struct vimage *parent, struct vimage *child)
-{
- if (child == parent)
- return (0);
- for (; child; child = child->vi_parent)
- if (child == parent)
- return (1);
- return (0);
-}
-
-/*
- * if_reassign_common() should be called by all device specific
- * ifnet reassignment routines after the interface is detached from
- * current vnet and before the interface gets attached to the target
- * vnet. This routine attempts to shrink if_index in current vnet,
- * find an unused if_index in target vnet and calls if_grow() if
- * necessary, and finally finds an unused if_xname for the target
- * vnet.
- *
- * XXX this routine should hold a lock over if_index and return with
- * such a lock held, and the caller should release that lock
- * after ifattach completes!
- */
-void
-if_reassign_common(struct ifnet *ifp, struct vnet *new_vnet, const char *dname)
-{
- /* do/while construct needed to confine scope of INIT_VNET_NET() */
- do {
- INIT_VNET_NET(curvnet);
-
- IFNET_WLOCK();
- ifnet_setbyindex(ifp->if_index, NULL);
- while (V_if_index > 0 &&
- ifnet_byindex_locked(V_if_index) == NULL)
- V_if_index--;
- IFNET_WUNLOCK();
- } while (0);
-
- CURVNET_SET_QUIET(new_vnet);
- INIT_VNET_NET(new_vnet);
- /*
- * Try to find an empty slot below if_index. If we fail, take
- * the next slot.
- */
- IFNET_WLOCK();
- for (ifp->if_index = 1; ifp->if_index <= V_if_index; ifp->if_index++) {
- if (ifnet_byindex_locked(ifp->if_index) == NULL)
- break;
- }
- /* Catch if_index overflow. */
- if (ifp->if_index < 1)
- panic("vi_if_move: if_index overflow");
-
- if (ifp->if_index > V_if_index)
- V_if_index = ifp->if_index;
- if (V_if_index >= V_if_indexlim)
- if_grow();
- ifnet_setbyindex(ifp->if_index, ifp);
- IFNET_WUNLOCK();
-
- /* Rename the ifnet */
- if (new_vnet == ifp->if_home_vnet) {
- /* always restore the original name on return to home vnet */
- if_initname(ifp, ifp->if_dname, ifp->if_dunit);
- } else {
- int unit = 0;
- struct ifnet *iter;
-
- do {
- snprintf(ifp->if_xname, IFNAMSIZ, "%s%d", dname, unit);
- TAILQ_FOREACH(iter, &V_ifnet, if_link)
- if (strcmp(ifp->if_xname, iter->if_xname) == 0)
- break;
- unit++;
- } while (iter);
- }
- CURVNET_RESTORE();
-}
-
-/*
- * Move the interface to another vnet. The interface can be specified either
- * by ifp argument, or by name contained in vi_req->vi_chroot if NULL is
- * passed as ifp. The interface will be renamed to vi_req->vi_parent_name
- * if vi_req->vi_parent_name is not an empty string (uff ugly ugly)...
- * Similary, the target vnet can be specified either by vnet argument or
- * by name. If vnet name equals to ".." or vi_req is set to NULL the
- * interface is moved to the parent vnet.
- */
-int
-vi_if_move(struct vi_req *vi_req, struct ifnet *ifp, struct vimage *vip)
-{
- struct vimage *new_vip;
- struct vnet *new_vnet = NULL;
-
- if (vi_req == NULL || strcmp(vi_req->vi_name, "..") == 0) {
- if (IS_DEFAULT_VIMAGE(vip))
- return (ENXIO);
- new_vnet = vip->vi_parent->v_net;
- } else {
- new_vip = vimage_by_name(vip, vi_req->vi_name);
- if (new_vip == NULL)
- return (ENXIO);
- new_vnet = new_vip->v_net;
- }
-
- if (ifp == NULL)
- ifp = ifunit(vi_req->vi_chroot);
- if (ifp == NULL)
- return (ENXIO);
-
- /* Abort if driver did not provide a if_reassign() method */
- if (ifp->if_reassign == NULL)
- return (ENODEV);
-
- if (vi_req != NULL) {
- struct ifnet *t_ifp;
-
- CURVNET_SET_QUIET(new_vnet);
- t_ifp = ifunit(vi_req->vi_if_xname);
- CURVNET_RESTORE();
- if (t_ifp != NULL)
- return (EEXIST);
- }
-
- if (vi_req && strlen(vi_req->vi_if_xname) > 0)
- ifp->if_reassign(ifp, new_vnet, vi_req->vi_if_xname);
- else
- ifp->if_reassign(ifp, new_vnet, NULL);
- getmicrotime(&ifp->if_lastchange);
-
- /* Report the new if_xname back to the userland */
- if (vi_req != NULL)
- sprintf(vi_req->vi_chroot, "%s", ifp->if_xname);
-
- return (0);
-}
-
-
-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_sibling)
- if (strlen(vip->vi_name) == namelen &&
- strncmp(name, vip->vi_name, namelen) == 0) {
- if (next_name != NULL)
- return(vimage_by_name(vip, next_name));
- else
- return(vip);
- }
- return(NULL);
-}
-
-
-vimage_relative_name(struct vimage *top, struct vimage *where,
- char *buffer, int bufflen)
-{
- int used = 1;
-
- if (where == top) {
- sprintf(buffer, ".");
- return;
- } else
- *buffer = 0;
-
- do {
- int namelen = strlen(where->vi_name);
-
- if (namelen + used + 1 >= bufflen)
- panic("buffer overflow");
-
- if (used > 1) {
- bcopy(buffer, &buffer[namelen + 1], used);
- buffer[namelen] = '.';
- used++;
- } else
- bcopy(buffer, &buffer[namelen], used);
- bcopy(where->vi_name, buffer, namelen);
- used += namelen;
- where = where->vi_parent;
- } while (where != top);
-}
-
-
static struct vimage *
-vimage_get_next(struct vimage *top, struct vimage *where, int recurse)
-{
- struct vimage *next;
-
- if (recurse) {
- /* Try to go deeper in the hierarchy */
- next = LIST_FIRST(&where->vi_child_head);
- if (next != NULL)
- return(next);
- }
-
- do {
- /* Try to find next sibling */
- next = LIST_NEXT(where, vi_sibling);
- if (!recurse || next != NULL)
- return(next);
-
- /* Nothing left on this level, go one level up */
- where = where->vi_parent;
- } while (where != top->vi_parent);
-
- /* Nothing left to be visited, we are done */
- return(NULL);
-}
-
-
-int
-vi_td_ioctl(u_long cmd, struct vi_req *vi_req, struct thread *td)
-{
- int error;
- struct vimage *vip = TD_TO_VIMAGE(td);
- struct vimage *vip_r = NULL;
-
- error = priv_check(td, PRIV_REBOOT); /* XXX fixme MARKO */
- if (error)
- return (error);
-
- 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, 0);
- if (vip_r == NULL)
- return (ESRCH);
- }
- if (vi_req->req_action == VI_GETNEXT_RECURSE) {
- vip_r = vimage_get_next(vip, vip_r, 1);
- if (vip_r == NULL)
- return (ESRCH);
- }
-
- 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);
-
- switch (cmd) {
-
- case SIOCGPVIMAGE:
- vimage_relative_name(vip, vip_r, vi_req->vi_name,
- sizeof (vi_req->vi_name));
- vi_req->vi_proc_count = vip_r->v_procg->nprocs;
- vi_req->vi_if_count = vip_r->v_net->ifccnt;
- vi_req->vi_sock_count = vip_r->v_net->sockcnt;
- break;
-
- case SIOCSPVIMAGE:
- if (vi_req->req_action == VI_DESTROY) {
- error = vi_destroy(vip_r);
- break;
- }
-
- if (vi_req->req_action == VI_SWITCHTO) {
- struct proc *p = td->td_proc;
- struct ucred *oldcred, *newcred;
-
- /*
- * XXX priv_check()?
- * XXX allow only a single td per proc here?
- */
- newcred = crget();
- PROC_LOCK(p);
- oldcred = p->p_ucred;
- setsugid(p);
- crcopy(newcred, oldcred);
- refcount_release(&newcred->cr_vimage->vi_ucredrefc);
- newcred->cr_vimage = vip_r;
- refcount_acquire(&newcred->cr_vimage->vi_ucredrefc);
- p->p_ucred = newcred;
- PROC_UNLOCK(p);
- sx_xlock(&allproc_lock);
- oldcred->cr_vimage->v_procg->nprocs--;
- refcount_release(&oldcred->cr_vimage->vi_ucredrefc);
- P_TO_VPROCG(p)->nprocs++;
-#if 0
- sched_load_reassign(oldcred->cr_vimage->v_procg,
- newcred->cr_vimage->v_procg);
-#endif
- sx_xunlock(&allproc_lock);
- crfree(oldcred);
- break;
- }
-
- if (vi_req->req_action & VI_CREATE) {
- 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);
- }
-
- /* XXX What the hell is this doing here? */
- if (vip == vip_r && !IS_DEFAULT_VIMAGE(vip))
- return (EPERM);
- }
-
- return (error);
-}
-
-
-struct vimage *
vi_alloc(struct vimage *parent, char *name)
{
struct vimage *vip;
struct vprocg *vprocg;
struct vnet *vnet;
- struct vprocg *vprocg;
struct vnet_modlink *vml;
- /*
- * XXX don't forget the locking
- */
-
- /* A brute force check whether there's enough mem for a new vimage */
- vip = malloc(512*1024, M_VIMAGE, M_NOWAIT); /* XXX aaaargh... */
- if (vip == NULL)
- goto vi_alloc_done;
- free(vip, M_VIMAGE);
-
vip = malloc(sizeof(struct vimage), M_VIMAGE, M_NOWAIT | M_ZERO);
if (vip == NULL)
panic("vi_alloc: malloc failed for vimage \"%s\"\n", name);
@@ -1061,11 +660,9 @@
/* XXX locking */
LIST_INSERT_HEAD(&vprocg_head, vprocg, vprocg_le);
-vi_alloc_done:
return (vip);
}
-
/*
* Destroy a vnet - unlink all linked lists, free all the memory, stop all
* the timers... How can one ever be sure to have done *all* the necessary
@@ -1124,10 +721,6 @@
vnet_modlink_head, vml_mod_le)
vnet_mod_destructor(vml);
-#if 0
- free((caddr_t)vnet->ifnet_addrs, M_IFADDR);
- free((caddr_t)vnet->ifindex2ifnet, M_IFADDR);
-
CURVNET_RESTORE();
/* hopefully, we are finally OK to free the vnet container itself! */
@@ -1140,7 +733,6 @@
}
#endif /* VIMAGE */
-#ifndef VIMAGE_GLOBALS
static void
vi_init(void *unused)
{
More information about the p4-projects
mailing list