Page MenuHomeFreeBSD

D39713.id54425.diff
No OneTemporary

D39713.id54425.diff

diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1289,6 +1289,11 @@
if (rc != 0)
return (rc);
+ /*
+ * Release old unit number or accquire a new one.
+ */
+ ifc_reassign_unit_vnet(ifp, new_vnet);
+
/*
* Perform interface-specific reassignment tasks, if provided by
* the driver.
@@ -2762,12 +2767,21 @@
* ifunit() checks not being atomic with namespace
* changes (renames, vmoves, if_attach, etc).
*/
+ /* FIXME atomic bit flag */
+ if (ifp->if_flags & IFF_RENAMING)
+ return (EBUSY);
ifp->if_flags |= IFF_RENAMING;
-
+
EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
if_printf(ifp, "changing name to '%s'\n", new_name);
+ if ((error = ifc_reassign_unit(ifp, new_name)) != 0) {
+ EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp);
+
+ ifp->if_flags &= ~IFF_RENAMING;
+ return (error);
+ }
IF_ADDR_WLOCK(ifp);
strlcpy(old_name, ifp->if_xname, sizeof(old_name));
strlcpy(ifp->if_xname, new_name, sizeof(ifp->if_xname));
diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h
--- a/sys/net/if_clone.h
+++ b/sys/net/if_clone.h
@@ -119,6 +119,8 @@
int if_clone_destroy(const char *);
int if_clone_list(struct if_clonereq *);
void if_clone_restoregroup(struct ifnet *);
+int ifc_reassign_unit(struct ifnet *, char *);
+void ifc_reassign_unit_vnet(struct ifnet *, struct vnet *);
/* The below interfaces are used only by epair(4). */
void if_clone_addif(struct if_clone *, struct ifnet *);
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -381,8 +381,11 @@
if (err != 0)
ifc_link_ifp(ifc, ifp);
- else if (ifc->ifc_flags & IFC_F_AUTOUNIT)
- ifc_free_unit(ifc, unit);
+ else if (ifc->ifc_flags & IFC_F_AUTOUNIT) {
+ if (unit != IF_DUNIT_NONE)
+ free_unr(ifc->ifc_unrhdr, unit);
+ IF_CLONE_REMREF(ifc);
+ }
CURVNET_RESTORE();
return (err);
}
@@ -517,7 +520,9 @@
static int
ifc_simple_destroy_wrapper(struct if_clone *ifc, struct ifnet *ifp, uint32_t flags)
{
- if (ifp->if_dunit < ifc->ifcs_minifs && (flags & IFC_F_FORCE) == 0)
+ if (ifp->if_dunit != IF_DUNIT_NONE &&
+ ifp->if_dunit < ifc->ifcs_minifs &&
+ (flags & IFC_F_FORCE) == 0)
return (EINVAL);
ifc->ifcs_destroy(ifp);
@@ -781,6 +786,7 @@
ifc_free_unit(struct if_clone *ifc, int unit)
{
+ KASSERT(unit != IF_DUNIT_NONE, ("Invalid unit"));
free_unr(ifc->ifc_unrhdr, unit);
IF_CLONE_REMREF(ifc);
}
@@ -872,3 +878,86 @@
{
return (ifc->ifc_flags);
}
+
+/*
+ * Reassign unit number from new name.
+ */
+int
+ifc_reassign_unit(struct ifnet *ifp, char *new_name)
+{
+ struct if_clone *ifc, *nifc;
+
+ KASSERT(new_name[0] != '\0', ("Invalid interface name"));
+
+ if (ifp->if_vnet != ifp->if_home_vnet)
+ return (0);
+ /* XXX lock cloners ??? */
+ ifc = ifc_find_cloner_in_vnet(ifp->if_dname, ifp->if_home_vnet);
+ /* Physical interfaces do not have cloner */
+ if (ifc == NULL || (ifc->ifc_flags & IFC_F_AUTOUNIT) == 0)
+ return (0);
+
+ CURVNET_SET_QUIET(ifp->if_home_vnet);
+ nifc = ifc_find_cloner_match(new_name);
+ CURVNET_RESTORE();
+ if (nifc == ifc) {
+ int unit = -1;
+ ifc_name2unit(new_name, &unit);
+ if (unit >= 0) {
+ if (unit > ifc->ifc_maxunit)
+ return (ENOSPC);
+ if (alloc_unr_specific(ifc->ifc_unrhdr, unit) == -1)
+ return (EEXIST);
+ if (ifp->if_dunit != IF_DUNIT_NONE)
+ free_unr(ifc->ifc_unrhdr, ifp->if_dunit);
+ /* FIXME need lock ??? */
+ ifp->if_dunit = unit;
+ return (0);
+ }
+ }
+ if (ifp->if_dunit != IF_DUNIT_NONE) {
+ free_unr(ifc->ifc_unrhdr, ifp->if_dunit);
+ /* FIXME need lock ??? */
+ ifp->if_dunit = IF_DUNIT_NONE;
+ }
+ return (0);
+}
+
+void
+ifc_reassign_unit_vnet(struct ifnet *ifp, struct vnet *new_vnet)
+{
+ struct if_clone *ifc;
+ KASSERT(ifp->if_vnet != new_vnet, ("Require different vnet"));
+
+ ifc = ifc_find_cloner_in_vnet(ifp->if_dname, ifp->if_home_vnet);
+ if (ifc == NULL || (ifc->ifc_flags & IFC_F_AUTOUNIT) == 0)
+ return;
+
+ if (new_vnet != ifp->if_home_vnet) {
+ if (ifp->if_vnet == ifp->if_home_vnet &&
+ ifp->if_dunit != IF_DUNIT_NONE) {
+ free_unr(ifc->ifc_unrhdr, ifp->if_dunit);
+ /* FIXME need lock ??? */
+ ifp->if_dunit = IF_DUNIT_NONE;
+ }
+ } else {
+ KASSERT(ifp->if_dunit == IF_DUNIT_NONE, ("Unit number is not released"));
+
+ struct if_clone *nifc;
+ CURVNET_SET_QUIET(ifp->if_home_vnet);
+ nifc = ifc_find_cloner_match(ifp->if_xname);
+ CURVNET_RESTORE();
+ if (nifc != ifc)
+ return;
+
+ int unit = -1;
+ ifc_name2unit(ifp->if_xname, &unit);
+ if (unit < 0 || unit > ifc->ifc_maxunit)
+ return;
+ if (alloc_unr_specific(ifc->ifc_unrhdr, unit) == -1)
+ return;
+
+ /* FIXME need lock ??? */
+ ifp->if_dunit = unit;
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 27, 3:24 AM (6 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26241705
Default Alt Text
D39713.id54425.diff (4 KB)

Event Timeline