if_vmove: return proper error status

if_vmove can fail if it lost a race and the vnet's already been moved. The
callers (and their callers) can generally cope with this, but right now
success is assumed. Plumb out the ENOENT from if_detach_internal if it
happens so that the error's properly reported to userland.

Reviewed by:	bz, kp
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D22780
This commit is contained in:
Kyle Evans 2020-01-09 03:52:50 +00:00
parent 4a8b575c6b
commit c7bab2a7ca
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=356536

View File

@ -274,7 +274,7 @@ static void if_attach_internal(struct ifnet *, int, struct if_clone *);
static int if_detach_internal(struct ifnet *, int, struct if_clone **);
static void if_siocaddmulti(void *, int);
#ifdef VIMAGE
static void if_vmove(struct ifnet *, struct vnet *);
static int if_vmove(struct ifnet *, struct vnet *);
#endif
#ifdef INET6
@ -1257,7 +1257,7 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
* unused if_index in target vnet and calls if_grow() if necessary,
* and finally find an unused if_xname for the target vnet.
*/
static void
static int
if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
{
struct if_clone *ifc;
@ -1283,7 +1283,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
*/
rc = if_detach_internal(ifp, 1, &ifc);
if (rc != 0)
return;
return (rc);
/*
* Unlink the ifnet from ifindex_table[] in current vnet, and shrink
@ -1327,6 +1327,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
#endif
CURVNET_RESTORE();
return (0);
}
/*
@ -1337,6 +1338,7 @@ if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid)
{
struct prison *pr;
struct ifnet *difp;
int error;
/* Try to find the prison within our visibility. */
sx_slock(&allprison_lock);
@ -1372,13 +1374,14 @@ if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid)
CURVNET_RESTORE();
/* Move the interface into the child jail/vnet. */
if_vmove(ifp, pr->pr_vnet);
error = if_vmove(ifp, pr->pr_vnet);
/* Report the new if_xname back to the userland. */
sprintf(ifname, "%s", ifp->if_xname);
/* Report the new if_xname back to the userland on success. */
if (error == 0)
sprintf(ifname, "%s", ifp->if_xname);
prison_free(pr);
return (0);
return (error);
}
static int
@ -1387,6 +1390,7 @@ if_vmove_reclaim(struct thread *td, char *ifname, int jid)
struct prison *pr;
struct vnet *vnet_dst;
struct ifnet *ifp;
int error;
/* Try to find the prison within our visibility. */
sx_slock(&allprison_lock);
@ -1422,14 +1426,15 @@ if_vmove_reclaim(struct thread *td, char *ifname, int jid)
}
/* Get interface back from child jail/vnet. */
if_vmove(ifp, vnet_dst);
error = if_vmove(ifp, vnet_dst);
CURVNET_RESTORE();
/* Report the new if_xname back to the userland. */
sprintf(ifname, "%s", ifp->if_xname);
/* Report the new if_xname back to the userland on success. */
if (error == 0)
sprintf(ifname, "%s", ifp->if_xname);
prison_free(pr);
return (0);
return (error);
}
#endif /* VIMAGE */