Date: Sun, 31 May 2009 19:28:57 GMT From: Marko Zec <zec@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 163194 for review Message-ID: <200905311928.n4VJSvoL025140@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=163194 Change 163194 by zec@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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905311928.n4VJSvoL025140>