Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137821176
D39713.id54425.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D39713.id54425.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D39713: ifnet: Release unit number on renaming interfaces
Attached
Detach File
Event Timeline
Log In to Comment