tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: RFC: PERCPU_LIST to fix PR kern/52515
On Tue, Sep 19, 2017 at 1:38 PM, Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost> wrote:
> Hi,
>
> To fix PR kern/52515(*), in particular psref(9), I implement PERCPU_LIST which
> is dedicated for percpu_alloc'ed percpu struct. Here is the patch which consists
> of PERCULI_LIST implementation and applying to subr_psref.c.
> http://www.NetBSD.org/~knakahara/percpu-list/percpu-list.patch
>
> (*) http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=52515
>
> The details are following.
>
> As written in PR/52515, the root of the problem is back-pointer to
> percpu_alloc'ed struct. At first, I tried generic solution to let
> percpu_alloc'ed struct use a pointer instead of itself. Here is a part of the
> PoC patch.
> ========== bad patch ==========
> @@ -103,9 +103,18 @@ struct psref_class {
> * Not exposed by the API.
> */
> struct psref_cpu {
> - struct psref_head pcpu_head;
> + struct psref_head *pcpu_head;
> };
>
> +static void
> +psref_class_pcpu_init_p(void *p, void *cookie, struct cpu_info *ci)
> +{
> + struct psref_cpu *pcpu = p;
> +
> + pcpu->pcpu_head = kmem_alloc(sizeof(*(pcpu->pcpu_head)), KM_SLEEP);
> + LIST_INIT(pcpu->pcpu_head);
> +}
> +
> /*
> * psref_class_create(name, ipl)
> *
> @@ -121,6 +130,7 @@ psref_class_create(const char *name, int ipl)
>
> class = kmem_alloc(sizeof(*class), KM_SLEEP);
> class->prc_percpu = percpu_alloc(sizeof(struct psref_cpu));
> + percpu_foreach(class->prc_percpu, &psref_class_pcpu_init_p, NULL);
> mutex_init(&class->prc_lock, MUTEX_DEFAULT, ipl);
> cv_init(&class->prc_cv, name);
> class->prc_iplcookie = makeiplcookie(ipl);
> ========== bad patch ==========
>
> Howerver, it causes initialization dependency problems to apply this
> modification to psref(9). That result from that percpu_foreach() must be called
> after ncpu is fixed, that is,
> (A) psref_class_create() for "ifnet_psref_class" must be called after ncpu
> is fixed
> - as psref_class_create() use percpu_foreach() in this modification
> (B) "ifnet_psref_class" must be initialized before any (real and pseudo)
> network interfaces are attached
>
> To satisfy both (A) and (B), it is required the MI hook called immediately
> after ncpu is fixed, yes, that hook is not implemented yet. Furthermore,
> the modification is too large even if that hook is already implemented.
> So, I gave up to use this generic solution.
>
> After that, I decide to use list specific solution to use PERCPU_LIST
> implemented for percpu_alloc'ed struct. The key design is an omission of the
> back-pointer to list head in the first list element, that is, when it wants
> to access list head, it always call percpu_getref() and then use the returned
> pointer.
> # There are some PR kern/52515 problems which cannot be fix by percpu list,
> # such as ipforward_rt_percpu. They can be fixed by using a pointer instead
> # of itself because they don't have complicated initialization dependency.
For rtcaches, I recommend that we stop manipulating rtcaches by global lists
(dom->dom_rtcache) for cache invalidation and instead use a global generation
counter for cache invalidation (inspired by IPsec SP cache). By doing so we
can remove LIST_ENTRY from struct route and avoid the issue.
This is a patch:
http://www.netbsd.org/~ozaki-r/rtcache-gen.diff
Thanks,
ozaki-r
Home |
Main Index |
Thread Index |
Old Index