On 28. Nov 2011, at 14:44 , Gleb Smirnoff wrote:

> Author: glebius
> Date: Mon Nov 28 14:44:59 2011
> New Revision: 228071
> URL: http://svn.freebsd.org/changeset/base/228071
> 
> Log:
>  - Use generic alloc_unr(9) allocator for if_clone, instead
>    of hand-made.
>  - When registering new cloner, check whether a cloner with
>    same name already exist.
>  - When allocating unit, also check with help of ifunit()
>    whether such interface already exist or not. [1]
This forces packages to be recompiled;  they might like to have a 
__FreeBSD_version for that?
It's not MFCable, at least I think - don't see a MFC after, just want to be 
sure.

See one more comment inline?

> 
>  PR:          kern/162789 [1]
> 
> Modified:
>  head/sys/net/if_clone.c
>  head/sys/net/if_clone.h
> 
> Modified: head/sys/net/if_clone.c
> ==============================================================================
> --- head/sys/net/if_clone.c   Mon Nov 28 14:39:56 2011        (r228070)
> +++ head/sys/net/if_clone.c   Mon Nov 28 14:44:59 2011        (r228071)
> @@ -282,33 +282,34 @@ if_clone_destroyif(struct if_clone *ifc,
> /*
>  * Register a network interface cloner.
>  */
> -void
> +int
> if_clone_attach(struct if_clone *ifc)
> {
> -     int len, maxclone;
> +     struct if_clone *ifc1;
> +
> +     KASSERT(ifc->ifc_name != NULL, ("%s: no name\n", __func__));
> 
> -     /*
> -      * Compute bitmap size and allocate it.
> -      */
> -     maxclone = ifc->ifc_maxunit + 1;
> -     len = maxclone >> 3;
> -     if ((len << 3) < maxclone)
> -             len++;
> -     ifc->ifc_units = malloc(len, M_CLONE, M_WAITOK | M_ZERO);
> -     ifc->ifc_bmlen = len;
>       IF_CLONE_LOCK_INIT(ifc);
>       IF_CLONE_ADDREF(ifc);
> +     ifc->ifc_unrhdr = new_unrhdr(0, ifc->ifc_maxunit, &ifc->ifc_mtx);
> +     LIST_INIT(&ifc->ifc_iflist);
> 
>       IF_CLONERS_LOCK();
> +     LIST_FOREACH(ifc1, &V_if_cloners, ifc_list)
> +             if (strcmp(ifc->ifc_name, ifc1->ifc_name) == 0) {
> +                     IF_CLONERS_UNLOCK();
> +                     IF_CLONE_REMREF(ifc);
> +                     return (EEXIST);

At this point you may have a problem not freeing the unr?


> +             }
>       LIST_INSERT_HEAD(&V_if_cloners, ifc, ifc_list);
>       V_if_cloners_count++;
>       IF_CLONERS_UNLOCK();
> 
> -     LIST_INIT(&ifc->ifc_iflist);
> -
>       if (ifc->ifc_attach != NULL)
>               (*ifc->ifc_attach)(ifc);
>       EVENTHANDLER_INVOKE(if_clone_event, ifc);
> +
> +     return (0);
> }
> 
> /*
> @@ -338,16 +339,12 @@ if_clone_detach(struct if_clone *ifc)
> static void
> if_clone_free(struct if_clone *ifc)
> {
> -     for (int bytoff = 0; bytoff < ifc->ifc_bmlen; bytoff++) {
> -             KASSERT(ifc->ifc_units[bytoff] == 0x00,
> -                 ("ifc_units[%d] is not empty", bytoff));
> -     }
> 
>       KASSERT(LIST_EMPTY(&ifc->ifc_iflist),
>           ("%s: ifc_iflist not empty", __func__));
> 
>       IF_CLONE_LOCK_DESTROY(ifc);
> -     free(ifc->ifc_units, M_CLONE);
> +     delete_unrhdr(ifc->ifc_unrhdr);
> }
> 
> /*
> @@ -441,73 +438,40 @@ ifc_name2unit(const char *name, int *uni
> int
> ifc_alloc_unit(struct if_clone *ifc, int *unit)
> {
> -     int wildcard, bytoff, bitoff;
> -     int err = 0;
> -
> -     IF_CLONE_LOCK(ifc);
> +     char name[IFNAMSIZ];
> +     int wildcard;
> 
> -     bytoff = bitoff = 0;
>       wildcard = (*unit < 0);
> -     /*
> -      * Find a free unit if none was given.
> -      */
> +retry:
>       if (wildcard) {
> -             while ((bytoff < ifc->ifc_bmlen)
> -                 && (ifc->ifc_units[bytoff] == 0xff))
> -                     bytoff++;
> -             if (bytoff >= ifc->ifc_bmlen) {
> -                     err = ENOSPC;
> -                     goto done;
> -             }
> -             while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
> -                     bitoff++;
> -             *unit = (bytoff << 3) + bitoff;
> -     }
> -
> -     if (*unit > ifc->ifc_maxunit) {
> -             err = ENOSPC;
> -             goto done;
> +             *unit = alloc_unr(ifc->ifc_unrhdr);
> +             if (*unit == -1)
> +                     return (ENOSPC);
> +     } else {
> +             *unit = alloc_unr_specific(ifc->ifc_unrhdr, *unit);
> +             if (*unit == -1)
> +                     return (EEXIST);
>       }
> 
> -     if (!wildcard) {
> -             bytoff = *unit >> 3;
> -             bitoff = *unit - (bytoff << 3);
> +     snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, *unit);
> +     if (ifunit(name) != NULL) {
> +             if (wildcard)
> +                     goto retry;     /* XXXGL: yep, it's a unit leak */
> +             else
> +                     return (EEXIST);
>       }
> 
> -     if((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0) {
> -             err = EEXIST;
> -             goto done;
> -     }
> -     /*
> -      * Allocate the unit in the bitmap.
> -      */
> -     KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
> -         ("%s: bit is already set", __func__));
> -     ifc->ifc_units[bytoff] |= (1 << bitoff);
> -     IF_CLONE_ADDREF_LOCKED(ifc);
> +     IF_CLONE_ADDREF(ifc);
> 
> -done:
> -     IF_CLONE_UNLOCK(ifc);
> -     return (err);
> +     return (0);
> }
> 
> void
> ifc_free_unit(struct if_clone *ifc, int unit)
> {
> -     int bytoff, bitoff;
> -
> 
> -     /*
> -      * Compute offset in the bitmap and deallocate the unit.
> -      */
> -     bytoff = unit >> 3;
> -     bitoff = unit - (bytoff << 3);
> -
> -     IF_CLONE_LOCK(ifc);
> -     KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
> -         ("%s: bit is already cleared", __func__));
> -     ifc->ifc_units[bytoff] &= ~(1 << bitoff);
> -     IF_CLONE_REMREF_LOCKED(ifc);    /* releases lock */
> +     free_unr(ifc->ifc_unrhdr, unit);
> +     IF_CLONE_REMREF(ifc);
> }
> 
> void
> 
> Modified: head/sys/net/if_clone.h
> ==============================================================================
> --- head/sys/net/if_clone.h   Mon Nov 28 14:39:56 2011        (r228070)
> +++ head/sys/net/if_clone.h   Mon Nov 28 14:44:59 2011        (r228071)
> @@ -37,7 +37,15 @@
> 
> #define IFC_CLONE_INITIALIZER(name, data, maxunit,                    \
>     attach, match, create, destroy)                                   \
> -    { { 0 }, name, maxunit, NULL, 0, data, attach, match, create, destroy }
> +    {                                                                        
> \
> +     .ifc_name = name,                                               \
> +     .ifc_maxunit = maxunit,                                         \
> +     .ifc_data = data,                                               \
> +     .ifc_attach = attach,                                           \
> +     .ifc_match = match,                                             \
> +     .ifc_create = create,                                           \
> +     .ifc_destroy = destroy,                                         \
> +    }
> 
> /*
>  * Structure describing a `cloning' interface.
> @@ -52,10 +60,7 @@ struct if_clone {
>       LIST_ENTRY(if_clone) ifc_list;  /* (e) On list of cloners */
>       const char *ifc_name;           /* (c) Name of device, e.g. `gif' */
>       int ifc_maxunit;                /* (c) Maximum unit number */
> -     unsigned char *ifc_units;       /* (i) Bitmap to handle units. */
> -                                     /*     Considered private, access */
> -                                     /*     via ifc_(alloc|free)_unit(). */
> -     int ifc_bmlen;                  /* (c) Bitmap length. */
> +     struct unrhdr *ifc_unrhdr;      /* (c) alloc_unr(9) header */
>       void *ifc_data;                 /* (*) Data for ifc_* functions. */
> 
>       /* (c) Driver specific cloning functions.  Called with no locks held. */
> @@ -65,12 +70,12 @@ struct if_clone {
>       int     (*ifc_destroy)(struct if_clone *, struct ifnet *);
> 
>       long ifc_refcnt;                /* (i) Refrence count. */
> -     struct mtx ifc_mtx;             /* Muted to protect members. */
> +     struct mtx ifc_mtx;             /* Mutex to protect members. */
>       LIST_HEAD(, ifnet) ifc_iflist;  /* (i) List of cloned interfaces */
> };
> 
> void  if_clone_init(void);
> -void if_clone_attach(struct if_clone *);
> +int  if_clone_attach(struct if_clone *);
> void  if_clone_detach(struct if_clone *);
> void  vnet_if_clone_init(void);
> 

-- 
Bjoern A. Zeeb                                 You have to have visions!
         Stop bit received. Insert coin for new address family.

_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to