1*fd34ea77Schs /* $NetBSD: subr_specificdata.c,v 1.14 2017/06/01 02:45:13 chs Exp $ */
231adc576Sthorpej
331adc576Sthorpej /*-
49abeea58Sad * Copyright (c) 2006, 2007 The NetBSD Foundation, Inc.
531adc576Sthorpej * All rights reserved.
631adc576Sthorpej *
731adc576Sthorpej * This code is derived from software contributed to The NetBSD Foundation
831adc576Sthorpej * by Jason R. Thorpe.
931adc576Sthorpej *
1031adc576Sthorpej * Redistribution and use in source and binary forms, with or without
1131adc576Sthorpej * modification, are permitted provided that the following conditions
1231adc576Sthorpej * are met:
1331adc576Sthorpej * 1. Redistributions of source code must retain the above copyright
1431adc576Sthorpej * notice, this list of conditions and the following disclaimer.
1531adc576Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
1631adc576Sthorpej * notice, this list of conditions and the following disclaimer in the
1731adc576Sthorpej * documentation and/or other materials provided with the distribution.
1831adc576Sthorpej *
1931adc576Sthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2031adc576Sthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2131adc576Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2231adc576Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2331adc576Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2431adc576Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2531adc576Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2631adc576Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2731adc576Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2831adc576Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2931adc576Sthorpej * POSSIBILITY OF SUCH DAMAGE.
3031adc576Sthorpej */
3131adc576Sthorpej
3231adc576Sthorpej /*-
3331adc576Sthorpej * Copyright (c) 2006 YAMAMOTO Takashi.
3431adc576Sthorpej * All rights reserved.
3531adc576Sthorpej *
3631adc576Sthorpej * Redistribution and use in source and binary forms, with or without
3731adc576Sthorpej * modification, are permitted provided that the following conditions
3831adc576Sthorpej * are met:
3931adc576Sthorpej * 1. Redistributions of source code must retain the above copyright
4031adc576Sthorpej * notice, this list of conditions and the following disclaimer.
4131adc576Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
4231adc576Sthorpej * notice, this list of conditions and the following disclaimer in the
4331adc576Sthorpej * documentation and/or other materials provided with the distribution.
4431adc576Sthorpej *
4531adc576Sthorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4631adc576Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4731adc576Sthorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4831adc576Sthorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4931adc576Sthorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5031adc576Sthorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5131adc576Sthorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5231adc576Sthorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5331adc576Sthorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5431adc576Sthorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5531adc576Sthorpej * SUCH DAMAGE.
5631adc576Sthorpej */
5731adc576Sthorpej
5831adc576Sthorpej #include <sys/cdefs.h>
59*fd34ea77Schs __KERNEL_RCSID(0, "$NetBSD: subr_specificdata.c,v 1.14 2017/06/01 02:45:13 chs Exp $");
6031adc576Sthorpej
6131adc576Sthorpej #include <sys/param.h>
6231adc576Sthorpej #include <sys/kmem.h>
6331adc576Sthorpej #include <sys/specificdata.h>
6431adc576Sthorpej #include <sys/queue.h>
659abeea58Sad #include <sys/mutex.h>
6631adc576Sthorpej
6731adc576Sthorpej /*
6831adc576Sthorpej * Locking notes:
6931adc576Sthorpej *
7031adc576Sthorpej * The specdataref_container pointer in the specificdata_reference
7131adc576Sthorpej * is volatile. To read it, you must hold EITHER the domain lock
7231adc576Sthorpej * or the ref lock. To write it, you must hold BOTH the domain lock
7331adc576Sthorpej * and the ref lock. The locks must be acquired in the following
7431adc576Sthorpej * order:
7531adc576Sthorpej * domain -> ref
7631adc576Sthorpej */
7731adc576Sthorpej
7831adc576Sthorpej typedef struct {
7931adc576Sthorpej specificdata_dtor_t ski_dtor;
8031adc576Sthorpej } specificdata_key_impl;
8131adc576Sthorpej
8231adc576Sthorpej struct specificdata_container {
8331adc576Sthorpej size_t sc_nkey;
8431adc576Sthorpej LIST_ENTRY(specificdata_container) sc_list;
8531adc576Sthorpej void * sc_data[]; /* variable length */
8631adc576Sthorpej };
8731adc576Sthorpej
8831adc576Sthorpej #define SPECIFICDATA_CONTAINER_BYTESIZE(n) \
8931adc576Sthorpej (sizeof(struct specificdata_container) + ((n) * sizeof(void *)))
9031adc576Sthorpej
9131adc576Sthorpej struct specificdata_domain {
929abeea58Sad kmutex_t sd_lock;
9331adc576Sthorpej unsigned int sd_nkey;
9431adc576Sthorpej LIST_HEAD(, specificdata_container) sd_list;
9531adc576Sthorpej specificdata_key_impl *sd_keys;
9631adc576Sthorpej };
9731adc576Sthorpej
9831adc576Sthorpej static void
specificdata_container_link(specificdata_domain_t sd,specificdata_container_t sc)9931adc576Sthorpej specificdata_container_link(specificdata_domain_t sd,
10031adc576Sthorpej specificdata_container_t sc)
10131adc576Sthorpej {
10231adc576Sthorpej
10331adc576Sthorpej LIST_INSERT_HEAD(&sd->sd_list, sc, sc_list);
10431adc576Sthorpej }
10531adc576Sthorpej
10631adc576Sthorpej static void
specificdata_container_unlink(specificdata_domain_t sd,specificdata_container_t sc)1071a7bc55dSyamt specificdata_container_unlink(specificdata_domain_t sd,
10831adc576Sthorpej specificdata_container_t sc)
10931adc576Sthorpej {
11031adc576Sthorpej
11131adc576Sthorpej LIST_REMOVE(sc, sc_list);
11231adc576Sthorpej }
11331adc576Sthorpej
11431adc576Sthorpej static void
specificdata_destroy_datum(specificdata_domain_t sd,specificdata_container_t sc,specificdata_key_t key)11531adc576Sthorpej specificdata_destroy_datum(specificdata_domain_t sd,
11631adc576Sthorpej specificdata_container_t sc, specificdata_key_t key)
11731adc576Sthorpej {
11831adc576Sthorpej specificdata_dtor_t dtor;
11931adc576Sthorpej void *data;
12031adc576Sthorpej
12131adc576Sthorpej if (key >= sc->sc_nkey)
12231adc576Sthorpej return;
12331adc576Sthorpej
12431adc576Sthorpej KASSERT(key < sd->sd_nkey);
12531adc576Sthorpej
12631adc576Sthorpej data = sc->sc_data[key];
12731adc576Sthorpej dtor = sd->sd_keys[key].ski_dtor;
12831adc576Sthorpej
12931adc576Sthorpej if (dtor != NULL) {
13031adc576Sthorpej if (data != NULL) {
13131adc576Sthorpej sc->sc_data[key] = NULL;
13231adc576Sthorpej (*dtor)(data);
13331adc576Sthorpej }
13431adc576Sthorpej } else {
13531adc576Sthorpej KASSERT(data == NULL);
13631adc576Sthorpej }
13731adc576Sthorpej }
13831adc576Sthorpej
13931adc576Sthorpej static void
specificdata_noop_dtor(void * data)1401a7bc55dSyamt specificdata_noop_dtor(void *data)
14131adc576Sthorpej {
14231adc576Sthorpej
14331adc576Sthorpej /* nothing */
14431adc576Sthorpej }
14531adc576Sthorpej
14631adc576Sthorpej /*
14731adc576Sthorpej * specificdata_domain_create --
148fe9f141dSelad * Create a specificdata domain.
14931adc576Sthorpej */
15031adc576Sthorpej specificdata_domain_t
specificdata_domain_create(void)15131adc576Sthorpej specificdata_domain_create(void)
15231adc576Sthorpej {
15331adc576Sthorpej specificdata_domain_t sd;
15431adc576Sthorpej
15531adc576Sthorpej sd = kmem_zalloc(sizeof(*sd), KM_SLEEP);
1569abeea58Sad mutex_init(&sd->sd_lock, MUTEX_DEFAULT, IPL_NONE);
15731adc576Sthorpej LIST_INIT(&sd->sd_list);
15831adc576Sthorpej
15931adc576Sthorpej return (sd);
16031adc576Sthorpej }
16131adc576Sthorpej
16231adc576Sthorpej /*
16331adc576Sthorpej * specificdata_domain_delete --
164fe9f141dSelad * Destroy a specificdata domain.
16531adc576Sthorpej */
16631adc576Sthorpej void
specificdata_domain_delete(specificdata_domain_t sd)1671a7bc55dSyamt specificdata_domain_delete(specificdata_domain_t sd)
16831adc576Sthorpej {
16931adc576Sthorpej
17031adc576Sthorpej panic("specificdata_domain_delete: not implemented");
17131adc576Sthorpej }
17231adc576Sthorpej
17331adc576Sthorpej /*
17431adc576Sthorpej * specificdata_key_create --
17531adc576Sthorpej * Create a specificdata key for a domain.
17631adc576Sthorpej *
17731adc576Sthorpej * Note: This is a rare operation.
17831adc576Sthorpej */
17931adc576Sthorpej int
specificdata_key_create(specificdata_domain_t sd,specificdata_key_t * keyp,specificdata_dtor_t dtor)18031adc576Sthorpej specificdata_key_create(specificdata_domain_t sd, specificdata_key_t *keyp,
18131adc576Sthorpej specificdata_dtor_t dtor)
18231adc576Sthorpej {
18331adc576Sthorpej specificdata_key_impl *newkeys;
18431adc576Sthorpej specificdata_key_t key = 0;
18531adc576Sthorpej size_t nsz;
18631adc576Sthorpej
187a67bae0bSyamt ASSERT_SLEEPABLE();
18831adc576Sthorpej
18931adc576Sthorpej if (dtor == NULL)
19031adc576Sthorpej dtor = specificdata_noop_dtor;
19131adc576Sthorpej
1929abeea58Sad mutex_enter(&sd->sd_lock);
19331adc576Sthorpej
19431adc576Sthorpej if (sd->sd_keys == NULL)
19531adc576Sthorpej goto needalloc;
19631adc576Sthorpej
19731adc576Sthorpej for (; key < sd->sd_nkey; key++) {
19831adc576Sthorpej if (sd->sd_keys[key].ski_dtor == NULL)
19931adc576Sthorpej goto gotit;
20031adc576Sthorpej }
20131adc576Sthorpej
20231adc576Sthorpej needalloc:
20331adc576Sthorpej nsz = (sd->sd_nkey + 1) * sizeof(*newkeys);
2049abeea58Sad /* XXXSMP allocating memory while holding a lock. */
20531adc576Sthorpej newkeys = kmem_zalloc(nsz, KM_SLEEP);
20631adc576Sthorpej if (sd->sd_keys != NULL) {
20731adc576Sthorpej size_t osz = sd->sd_nkey * sizeof(*newkeys);
20831adc576Sthorpej memcpy(newkeys, sd->sd_keys, osz);
20931adc576Sthorpej kmem_free(sd->sd_keys, osz);
21031adc576Sthorpej }
21131adc576Sthorpej sd->sd_keys = newkeys;
21231adc576Sthorpej sd->sd_nkey++;
21331adc576Sthorpej gotit:
21431adc576Sthorpej sd->sd_keys[key].ski_dtor = dtor;
21531adc576Sthorpej
2169abeea58Sad mutex_exit(&sd->sd_lock);
21731adc576Sthorpej
21831adc576Sthorpej *keyp = key;
21931adc576Sthorpej return (0);
22031adc576Sthorpej }
22131adc576Sthorpej
22231adc576Sthorpej /*
22331adc576Sthorpej * specificdata_key_delete --
22431adc576Sthorpej * Destroy a specificdata key for a domain.
22531adc576Sthorpej *
22631adc576Sthorpej * Note: This is a rare operation.
22731adc576Sthorpej */
22831adc576Sthorpej void
specificdata_key_delete(specificdata_domain_t sd,specificdata_key_t key)22931adc576Sthorpej specificdata_key_delete(specificdata_domain_t sd, specificdata_key_t key)
23031adc576Sthorpej {
23131adc576Sthorpej specificdata_container_t sc;
23231adc576Sthorpej
2339abeea58Sad mutex_enter(&sd->sd_lock);
23431adc576Sthorpej
23531adc576Sthorpej if (key >= sd->sd_nkey)
23631adc576Sthorpej goto out;
23731adc576Sthorpej
23831adc576Sthorpej /*
23931adc576Sthorpej * Traverse all of the specificdata containers in the domain
24031adc576Sthorpej * and the destroy the datum for the dying key.
24131adc576Sthorpej */
24231adc576Sthorpej LIST_FOREACH(sc, &sd->sd_list, sc_list) {
24331adc576Sthorpej specificdata_destroy_datum(sd, sc, key);
24431adc576Sthorpej }
24531adc576Sthorpej
24631adc576Sthorpej sd->sd_keys[key].ski_dtor = NULL;
24731adc576Sthorpej
24831adc576Sthorpej out:
2499abeea58Sad mutex_exit(&sd->sd_lock);
25031adc576Sthorpej }
25131adc576Sthorpej
25231adc576Sthorpej /*
25331adc576Sthorpej * specificdata_init --
25431adc576Sthorpej * Initialize a specificdata container for operation in the
25531adc576Sthorpej * specified domain.
25631adc576Sthorpej */
25731adc576Sthorpej int
specificdata_init(specificdata_domain_t sd,specificdata_reference * ref)2581a7bc55dSyamt specificdata_init(specificdata_domain_t sd, specificdata_reference *ref)
25931adc576Sthorpej {
26031adc576Sthorpej
26131adc576Sthorpej /*
26231adc576Sthorpej * Just NULL-out the container pointer; we'll allocate the
26331adc576Sthorpej * container the first time specificdata is put into it.
26431adc576Sthorpej */
26531adc576Sthorpej ref->specdataref_container = NULL;
266d18c6ca4Sad mutex_init(&ref->specdataref_lock, MUTEX_DEFAULT, IPL_NONE);
26731adc576Sthorpej
26831adc576Sthorpej return (0);
26931adc576Sthorpej }
27031adc576Sthorpej
27131adc576Sthorpej /*
27231adc576Sthorpej * specificdata_fini --
27331adc576Sthorpej * Destroy a specificdata container. We destroy all of the datums
27431adc576Sthorpej * stuffed into the container just as if the key were destroyed.
27531adc576Sthorpej */
27631adc576Sthorpej void
specificdata_fini(specificdata_domain_t sd,specificdata_reference * ref)27731adc576Sthorpej specificdata_fini(specificdata_domain_t sd, specificdata_reference *ref)
27831adc576Sthorpej {
27931adc576Sthorpej specificdata_container_t sc;
28031adc576Sthorpej specificdata_key_t key;
28131adc576Sthorpej
282a67bae0bSyamt ASSERT_SLEEPABLE();
28331adc576Sthorpej
284d18c6ca4Sad mutex_destroy(&ref->specdataref_lock);
285d18c6ca4Sad
28631adc576Sthorpej sc = ref->specdataref_container;
28731adc576Sthorpej if (sc == NULL)
28831adc576Sthorpej return;
28931adc576Sthorpej ref->specdataref_container = NULL;
29031adc576Sthorpej
2919abeea58Sad mutex_enter(&sd->sd_lock);
29231adc576Sthorpej
29331adc576Sthorpej specificdata_container_unlink(sd, sc);
29431adc576Sthorpej for (key = 0; key < sc->sc_nkey; key++) {
29531adc576Sthorpej specificdata_destroy_datum(sd, sc, key);
29631adc576Sthorpej }
29731adc576Sthorpej
2989abeea58Sad mutex_exit(&sd->sd_lock);
29931adc576Sthorpej
30031adc576Sthorpej kmem_free(sc, SPECIFICDATA_CONTAINER_BYTESIZE(sc->sc_nkey));
30131adc576Sthorpej }
30231adc576Sthorpej
30331adc576Sthorpej /*
30431adc576Sthorpej * specificdata_getspecific --
30531adc576Sthorpej * Get a datum from a container.
30631adc576Sthorpej */
30731adc576Sthorpej void *
specificdata_getspecific(specificdata_domain_t sd,specificdata_reference * ref,specificdata_key_t key)3081a7bc55dSyamt specificdata_getspecific(specificdata_domain_t sd, specificdata_reference *ref,
3091a7bc55dSyamt specificdata_key_t key)
31031adc576Sthorpej {
31131adc576Sthorpej specificdata_container_t sc;
31231adc576Sthorpej void *data = NULL;
31331adc576Sthorpej
314d18c6ca4Sad mutex_enter(&ref->specdataref_lock);
31531adc576Sthorpej
31631adc576Sthorpej sc = ref->specdataref_container;
31731adc576Sthorpej if (sc != NULL && key < sc->sc_nkey)
31831adc576Sthorpej data = sc->sc_data[key];
31931adc576Sthorpej
320d18c6ca4Sad mutex_exit(&ref->specdataref_lock);
32131adc576Sthorpej
32231adc576Sthorpej return (data);
32331adc576Sthorpej }
32431adc576Sthorpej
32531adc576Sthorpej /*
32631adc576Sthorpej * specificdata_getspecific_unlocked --
32731adc576Sthorpej * Get a datum from a container in a lockless fashion.
32831adc576Sthorpej *
32931adc576Sthorpej * Note: When using this routine, care must be taken to ensure
33031adc576Sthorpej * that no other thread could cause the specificdata_reference
33131adc576Sthorpej * to become invalid (i.e. point at the wrong container) by
33231adc576Sthorpej * issuing a setspecific call or destroying the container.
33331adc576Sthorpej */
33431adc576Sthorpej void *
specificdata_getspecific_unlocked(specificdata_domain_t sd,specificdata_reference * ref,specificdata_key_t key)3351a7bc55dSyamt specificdata_getspecific_unlocked(specificdata_domain_t sd,
33631adc576Sthorpej specificdata_reference *ref,
33731adc576Sthorpej specificdata_key_t key)
33831adc576Sthorpej {
33931adc576Sthorpej specificdata_container_t sc;
34031adc576Sthorpej
34131adc576Sthorpej sc = ref->specdataref_container;
34231adc576Sthorpej if (sc != NULL && key < sc->sc_nkey)
34331adc576Sthorpej return (sc->sc_data[key]);
34431adc576Sthorpej
34531adc576Sthorpej return (NULL);
34631adc576Sthorpej }
34731adc576Sthorpej
3488ea60a7fShannken /*
3498ea60a7fShannken * specificdata_setspecific --
3508ea60a7fShannken * Put a datum into a container.
3518ea60a7fShannken */
3528ea60a7fShannken void
specificdata_setspecific(specificdata_domain_t sd,specificdata_reference * ref,specificdata_key_t key,void * data)3538ea60a7fShannken specificdata_setspecific(specificdata_domain_t sd,
354e160c7cdSthorpej specificdata_reference *ref,
3558ea60a7fShannken specificdata_key_t key, void *data)
35631adc576Sthorpej {
35731adc576Sthorpej specificdata_container_t sc, newsc;
35831adc576Sthorpej size_t newnkey, sz;
35931adc576Sthorpej
360a67bae0bSyamt ASSERT_SLEEPABLE();
36131adc576Sthorpej
362d18c6ca4Sad mutex_enter(&ref->specdataref_lock);
36331adc576Sthorpej
36431adc576Sthorpej sc = ref->specdataref_container;
36531adc576Sthorpej if (__predict_true(sc != NULL && key < sc->sc_nkey)) {
36631adc576Sthorpej sc->sc_data[key] = data;
367d18c6ca4Sad mutex_exit(&ref->specdataref_lock);
3688ea60a7fShannken return;
36931adc576Sthorpej }
37031adc576Sthorpej
371d18c6ca4Sad mutex_exit(&ref->specdataref_lock);
37231adc576Sthorpej
37331adc576Sthorpej /*
37431adc576Sthorpej * Slow path: need to resize.
37531adc576Sthorpej */
37631adc576Sthorpej
3779abeea58Sad mutex_enter(&sd->sd_lock);
37831adc576Sthorpej newnkey = sd->sd_nkey;
37931adc576Sthorpej if (key >= newnkey) {
3809abeea58Sad mutex_exit(&sd->sd_lock);
38131adc576Sthorpej panic("specificdata_setspecific");
38231adc576Sthorpej }
38331adc576Sthorpej sz = SPECIFICDATA_CONTAINER_BYTESIZE(newnkey);
3848ea60a7fShannken newsc = kmem_zalloc(sz, KM_SLEEP);
38531adc576Sthorpej newsc->sc_nkey = newnkey;
38631adc576Sthorpej
387d18c6ca4Sad mutex_enter(&ref->specdataref_lock);
38831adc576Sthorpej
38931adc576Sthorpej sc = ref->specdataref_container;
39031adc576Sthorpej if (sc != NULL) {
39131adc576Sthorpej if (key < sc->sc_nkey) {
39231adc576Sthorpej /*
39331adc576Sthorpej * Someone beat us to the punch. Unwind and put
39431adc576Sthorpej * the object into the now large enough container.
39531adc576Sthorpej */
39631adc576Sthorpej sc->sc_data[key] = data;
397d18c6ca4Sad mutex_exit(&ref->specdataref_lock);
3989abeea58Sad mutex_exit(&sd->sd_lock);
39931adc576Sthorpej kmem_free(newsc, sz);
4008ea60a7fShannken return;
40131adc576Sthorpej }
40231adc576Sthorpej specificdata_container_unlink(sd, sc);
40331adc576Sthorpej memcpy(newsc->sc_data, sc->sc_data,
40431adc576Sthorpej sc->sc_nkey * sizeof(void *));
40531adc576Sthorpej }
40631adc576Sthorpej newsc->sc_data[key] = data;
40731adc576Sthorpej specificdata_container_link(sd, newsc);
40831adc576Sthorpej ref->specdataref_container = newsc;
40931adc576Sthorpej
410d18c6ca4Sad mutex_exit(&ref->specdataref_lock);
4119abeea58Sad mutex_exit(&sd->sd_lock);
41231adc576Sthorpej
41331adc576Sthorpej if (sc != NULL)
41431adc576Sthorpej kmem_free(sc, SPECIFICDATA_CONTAINER_BYTESIZE(sc->sc_nkey));
41531adc576Sthorpej }
416