xref: /aosp_15_r20/external/libnl/lib/cache_mngt.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2003-2012 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup core
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup cache_mngt Caching System
9*4dc78e53SAndroid Build Coastguard Worker  *
10*4dc78e53SAndroid Build Coastguard Worker  * Related sections in the development guide:
11*4dc78e53SAndroid Build Coastguard Worker  * - @core_doc{core_cache, Caching System}
12*4dc78e53SAndroid Build Coastguard Worker  *
13*4dc78e53SAndroid Build Coastguard Worker  * @{
14*4dc78e53SAndroid Build Coastguard Worker  *
15*4dc78e53SAndroid Build Coastguard Worker  * Header
16*4dc78e53SAndroid Build Coastguard Worker  * ------
17*4dc78e53SAndroid Build Coastguard Worker  * ~~~~{.c}
18*4dc78e53SAndroid Build Coastguard Worker  * #include <netlink/cache.h>
19*4dc78e53SAndroid Build Coastguard Worker  * ~~~~
20*4dc78e53SAndroid Build Coastguard Worker  */
21*4dc78e53SAndroid Build Coastguard Worker 
22*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
23*4dc78e53SAndroid Build Coastguard Worker 
24*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
25*4dc78e53SAndroid Build Coastguard Worker #include <netlink/cache.h>
26*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
27*4dc78e53SAndroid Build Coastguard Worker 
28*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
29*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/object-api.h"
30*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/cache-api.h"
31*4dc78e53SAndroid Build Coastguard Worker #include "nl-aux-core/nl-core.h"
32*4dc78e53SAndroid Build Coastguard Worker 
33*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops *cache_ops;
34*4dc78e53SAndroid Build Coastguard Worker static NL_RW_LOCK(cache_ops_lock);
35*4dc78e53SAndroid Build Coastguard Worker 
36*4dc78e53SAndroid Build Coastguard Worker /**
37*4dc78e53SAndroid Build Coastguard Worker  * @name Cache Operations Sets
38*4dc78e53SAndroid Build Coastguard Worker  * @{
39*4dc78e53SAndroid Build Coastguard Worker  */
40*4dc78e53SAndroid Build Coastguard Worker 
__nl_cache_ops_lookup(const char * name)41*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops *__nl_cache_ops_lookup(const char *name)
42*4dc78e53SAndroid Build Coastguard Worker {
43*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
44*4dc78e53SAndroid Build Coastguard Worker 
45*4dc78e53SAndroid Build Coastguard Worker 	for (ops = cache_ops; ops; ops = ops->co_next)
46*4dc78e53SAndroid Build Coastguard Worker 		if (!strcmp(ops->co_name, name))
47*4dc78e53SAndroid Build Coastguard Worker 			return ops;
48*4dc78e53SAndroid Build Coastguard Worker 
49*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
50*4dc78e53SAndroid Build Coastguard Worker }
51*4dc78e53SAndroid Build Coastguard Worker 
52*4dc78e53SAndroid Build Coastguard Worker /**
53*4dc78e53SAndroid Build Coastguard Worker  * Increment reference counter
54*4dc78e53SAndroid Build Coastguard Worker  * @arg ops		Cache operations
55*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_get(struct nl_cache_ops * ops)56*4dc78e53SAndroid Build Coastguard Worker void nl_cache_ops_get(struct nl_cache_ops *ops)
57*4dc78e53SAndroid Build Coastguard Worker {
58*4dc78e53SAndroid Build Coastguard Worker 	ops->co_refcnt++;
59*4dc78e53SAndroid Build Coastguard Worker }
60*4dc78e53SAndroid Build Coastguard Worker 
61*4dc78e53SAndroid Build Coastguard Worker /**
62*4dc78e53SAndroid Build Coastguard Worker  * Decrement reference counter
63*4dc78e53SAndroid Build Coastguard Worker  * @arg ops		Cache operations
64*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_put(struct nl_cache_ops * ops)65*4dc78e53SAndroid Build Coastguard Worker void nl_cache_ops_put(struct nl_cache_ops *ops)
66*4dc78e53SAndroid Build Coastguard Worker {
67*4dc78e53SAndroid Build Coastguard Worker 	ops->co_refcnt--;
68*4dc78e53SAndroid Build Coastguard Worker }
69*4dc78e53SAndroid Build Coastguard Worker 
70*4dc78e53SAndroid Build Coastguard Worker /**
71*4dc78e53SAndroid Build Coastguard Worker  * Lookup cache operations by name
72*4dc78e53SAndroid Build Coastguard Worker  * @arg name		name of the cache type
73*4dc78e53SAndroid Build Coastguard Worker  *
74*4dc78e53SAndroid Build Coastguard Worker  * @attention This function is not safe, it does not increment the reference
75*4dc78e53SAndroid Build Coastguard Worker  *            counter. Please use nl_cache_ops_lookup_safe().
76*4dc78e53SAndroid Build Coastguard Worker  *
77*4dc78e53SAndroid Build Coastguard Worker  * @return The cache operations or NULL if not found.
78*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_lookup(const char * name)79*4dc78e53SAndroid Build Coastguard Worker struct nl_cache_ops *nl_cache_ops_lookup(const char *name)
80*4dc78e53SAndroid Build Coastguard Worker {
81*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
82*4dc78e53SAndroid Build Coastguard Worker 
83*4dc78e53SAndroid Build Coastguard Worker 	nl_read_lock(&cache_ops_lock);
84*4dc78e53SAndroid Build Coastguard Worker 	ops = __nl_cache_ops_lookup(name);
85*4dc78e53SAndroid Build Coastguard Worker 	nl_read_unlock(&cache_ops_lock);
86*4dc78e53SAndroid Build Coastguard Worker 
87*4dc78e53SAndroid Build Coastguard Worker 	return ops;
88*4dc78e53SAndroid Build Coastguard Worker }
89*4dc78e53SAndroid Build Coastguard Worker 
90*4dc78e53SAndroid Build Coastguard Worker /**
91*4dc78e53SAndroid Build Coastguard Worker  * Lookup cache operations by name
92*4dc78e53SAndroid Build Coastguard Worker  * @arg name		name of the cache type
93*4dc78e53SAndroid Build Coastguard Worker  *
94*4dc78e53SAndroid Build Coastguard Worker  * @note The reference counter of the returned cache operation is incremented
95*4dc78e53SAndroid Build Coastguard Worker  *       and must be decremented after use with nl_cache_ops_put().
96*4dc78e53SAndroid Build Coastguard Worker  *
97*4dc78e53SAndroid Build Coastguard Worker  * @return The cache operations or NULL if not found.
98*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_lookup_safe(const char * name)99*4dc78e53SAndroid Build Coastguard Worker struct nl_cache_ops *nl_cache_ops_lookup_safe(const char *name)
100*4dc78e53SAndroid Build Coastguard Worker {
101*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
102*4dc78e53SAndroid Build Coastguard Worker 
103*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&cache_ops_lock);
104*4dc78e53SAndroid Build Coastguard Worker 	if ((ops = __nl_cache_ops_lookup(name)))
105*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_ops_get(ops);
106*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&cache_ops_lock);
107*4dc78e53SAndroid Build Coastguard Worker 
108*4dc78e53SAndroid Build Coastguard Worker 	return ops;
109*4dc78e53SAndroid Build Coastguard Worker }
110*4dc78e53SAndroid Build Coastguard Worker 
__cache_ops_associate(int protocol,int msgtype)111*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops *__cache_ops_associate(int protocol, int msgtype)
112*4dc78e53SAndroid Build Coastguard Worker {
113*4dc78e53SAndroid Build Coastguard Worker 	int i;
114*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
115*4dc78e53SAndroid Build Coastguard Worker 
116*4dc78e53SAndroid Build Coastguard Worker 	for (ops = cache_ops; ops; ops = ops->co_next) {
117*4dc78e53SAndroid Build Coastguard Worker 		if (ops->co_protocol != protocol)
118*4dc78e53SAndroid Build Coastguard Worker 			continue;
119*4dc78e53SAndroid Build Coastguard Worker 
120*4dc78e53SAndroid Build Coastguard Worker 		for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
121*4dc78e53SAndroid Build Coastguard Worker 			if (ops->co_msgtypes[i].mt_id == msgtype)
122*4dc78e53SAndroid Build Coastguard Worker 				return ops;
123*4dc78e53SAndroid Build Coastguard Worker 	}
124*4dc78e53SAndroid Build Coastguard Worker 
125*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
126*4dc78e53SAndroid Build Coastguard Worker }
127*4dc78e53SAndroid Build Coastguard Worker 
128*4dc78e53SAndroid Build Coastguard Worker /**
129*4dc78e53SAndroid Build Coastguard Worker  * Associate protocol and message type to cache operations
130*4dc78e53SAndroid Build Coastguard Worker  * @arg protocol		netlink protocol
131*4dc78e53SAndroid Build Coastguard Worker  * @arg msgtype			netlink message type
132*4dc78e53SAndroid Build Coastguard Worker  *
133*4dc78e53SAndroid Build Coastguard Worker  * @attention This function is not safe, it does not increment the reference
134*4dc78e53SAndroid Build Coastguard Worker  *            counter. Please use nl_cache_ops_associate_safe().
135*4dc78e53SAndroid Build Coastguard Worker  *
136*4dc78e53SAndroid Build Coastguard Worker  * @see nl_cache_ops_associate_safe()
137*4dc78e53SAndroid Build Coastguard Worker  *
138*4dc78e53SAndroid Build Coastguard Worker  * @return The cache operations or NULL if no match found.
139*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_associate(int protocol,int msgtype)140*4dc78e53SAndroid Build Coastguard Worker struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype)
141*4dc78e53SAndroid Build Coastguard Worker {
142*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
143*4dc78e53SAndroid Build Coastguard Worker 
144*4dc78e53SAndroid Build Coastguard Worker 	nl_read_lock(&cache_ops_lock);
145*4dc78e53SAndroid Build Coastguard Worker 	ops = __cache_ops_associate(protocol, msgtype);
146*4dc78e53SAndroid Build Coastguard Worker 	nl_read_unlock(&cache_ops_lock);
147*4dc78e53SAndroid Build Coastguard Worker 
148*4dc78e53SAndroid Build Coastguard Worker 	return ops;
149*4dc78e53SAndroid Build Coastguard Worker }
150*4dc78e53SAndroid Build Coastguard Worker 
151*4dc78e53SAndroid Build Coastguard Worker /**
152*4dc78e53SAndroid Build Coastguard Worker  * Associate protocol and message type to cache operations
153*4dc78e53SAndroid Build Coastguard Worker  * @arg protocol		netlink protocol
154*4dc78e53SAndroid Build Coastguard Worker  * @arg msgtype			netlink message type
155*4dc78e53SAndroid Build Coastguard Worker  *
156*4dc78e53SAndroid Build Coastguard Worker  * Searches the registered cache operations for a matching protocol
157*4dc78e53SAndroid Build Coastguard Worker  * and message type.
158*4dc78e53SAndroid Build Coastguard Worker  *
159*4dc78e53SAndroid Build Coastguard Worker  * @note The reference counter of the returned cache operation is incremented
160*4dc78e53SAndroid Build Coastguard Worker  *       and must be decremented after use with nl_cache_ops_put().
161*4dc78e53SAndroid Build Coastguard Worker  *
162*4dc78e53SAndroid Build Coastguard Worker  * @return The cache operations or NULL if no no match was found.
163*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_associate_safe(int protocol,int msgtype)164*4dc78e53SAndroid Build Coastguard Worker struct nl_cache_ops *nl_cache_ops_associate_safe(int protocol, int msgtype)
165*4dc78e53SAndroid Build Coastguard Worker {
166*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
167*4dc78e53SAndroid Build Coastguard Worker 
168*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&cache_ops_lock);
169*4dc78e53SAndroid Build Coastguard Worker 	if ((ops = __cache_ops_associate(protocol, msgtype)))
170*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_ops_get(ops);
171*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&cache_ops_lock);
172*4dc78e53SAndroid Build Coastguard Worker 
173*4dc78e53SAndroid Build Coastguard Worker 	return ops;
174*4dc78e53SAndroid Build Coastguard Worker }
175*4dc78e53SAndroid Build Coastguard Worker 
176*4dc78e53SAndroid Build Coastguard Worker /**
177*4dc78e53SAndroid Build Coastguard Worker  * Lookup message type cache association
178*4dc78e53SAndroid Build Coastguard Worker  * @arg ops			cache operations
179*4dc78e53SAndroid Build Coastguard Worker  * @arg msgtype			netlink message type
180*4dc78e53SAndroid Build Coastguard Worker  *
181*4dc78e53SAndroid Build Coastguard Worker  * Searches for a matching message type association ing the specified
182*4dc78e53SAndroid Build Coastguard Worker  * cache operations.
183*4dc78e53SAndroid Build Coastguard Worker  *
184*4dc78e53SAndroid Build Coastguard Worker  * @attention The guranteed lifetime of the returned message type is bound
185*4dc78e53SAndroid Build Coastguard Worker  *            to the lifetime of the underlying cache operations.
186*4dc78e53SAndroid Build Coastguard Worker  *
187*4dc78e53SAndroid Build Coastguard Worker  * @return A message type association or NULL.
188*4dc78e53SAndroid Build Coastguard Worker  */
nl_msgtype_lookup(struct nl_cache_ops * ops,int msgtype)189*4dc78e53SAndroid Build Coastguard Worker struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype)
190*4dc78e53SAndroid Build Coastguard Worker {
191*4dc78e53SAndroid Build Coastguard Worker 	int i;
192*4dc78e53SAndroid Build Coastguard Worker 
193*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
194*4dc78e53SAndroid Build Coastguard Worker 		if (ops->co_msgtypes[i].mt_id == msgtype)
195*4dc78e53SAndroid Build Coastguard Worker 			return &ops->co_msgtypes[i];
196*4dc78e53SAndroid Build Coastguard Worker 
197*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
198*4dc78e53SAndroid Build Coastguard Worker }
199*4dc78e53SAndroid Build Coastguard Worker 
200*4dc78e53SAndroid Build Coastguard Worker /* Must hold cache_ops_lock */
cache_ops_lookup_for_obj(struct nl_object_ops * obj_ops)201*4dc78e53SAndroid Build Coastguard Worker static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops)
202*4dc78e53SAndroid Build Coastguard Worker {
203*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
204*4dc78e53SAndroid Build Coastguard Worker 
205*4dc78e53SAndroid Build Coastguard Worker 	for (ops = cache_ops; ops; ops = ops->co_next)
206*4dc78e53SAndroid Build Coastguard Worker 		if (ops->co_obj_ops == obj_ops)
207*4dc78e53SAndroid Build Coastguard Worker 			return ops;
208*4dc78e53SAndroid Build Coastguard Worker 
209*4dc78e53SAndroid Build Coastguard Worker 	return NULL;
210*4dc78e53SAndroid Build Coastguard Worker 
211*4dc78e53SAndroid Build Coastguard Worker }
212*4dc78e53SAndroid Build Coastguard Worker 
213*4dc78e53SAndroid Build Coastguard Worker /**
214*4dc78e53SAndroid Build Coastguard Worker  * Call a function for each registered cache operation
215*4dc78e53SAndroid Build Coastguard Worker  * @arg cb		Callback function to be called
216*4dc78e53SAndroid Build Coastguard Worker  * @arg arg		User specific argument.
217*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_foreach(void (* cb)(struct nl_cache_ops *,void *),void * arg)218*4dc78e53SAndroid Build Coastguard Worker void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg)
219*4dc78e53SAndroid Build Coastguard Worker {
220*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
221*4dc78e53SAndroid Build Coastguard Worker 
222*4dc78e53SAndroid Build Coastguard Worker 	nl_read_lock(&cache_ops_lock);
223*4dc78e53SAndroid Build Coastguard Worker 	for (ops = cache_ops; ops; ops = ops->co_next)
224*4dc78e53SAndroid Build Coastguard Worker 		cb(ops, arg);
225*4dc78e53SAndroid Build Coastguard Worker 	nl_read_unlock(&cache_ops_lock);
226*4dc78e53SAndroid Build Coastguard Worker }
227*4dc78e53SAndroid Build Coastguard Worker 
228*4dc78e53SAndroid Build Coastguard Worker /**
229*4dc78e53SAndroid Build Coastguard Worker  * Set default flags for caches of this type
230*4dc78e53SAndroid Build Coastguard Worker  * @arg ops		Cache ops
231*4dc78e53SAndroid Build Coastguard Worker  * @arg flags		Flags to set
232*4dc78e53SAndroid Build Coastguard Worker  *
233*4dc78e53SAndroid Build Coastguard Worker  * The cache operation flags will be derived to all caches allocates
234*4dc78e53SAndroid Build Coastguard Worker  * based on this set of cache operations.
235*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_ops_set_flags(struct nl_cache_ops * ops,unsigned int flags)236*4dc78e53SAndroid Build Coastguard Worker void nl_cache_ops_set_flags(struct nl_cache_ops *ops, unsigned int flags)
237*4dc78e53SAndroid Build Coastguard Worker {
238*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&cache_ops_lock);
239*4dc78e53SAndroid Build Coastguard Worker 	ops->co_flags |= flags;
240*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&cache_ops_lock);
241*4dc78e53SAndroid Build Coastguard Worker }
242*4dc78e53SAndroid Build Coastguard Worker 
243*4dc78e53SAndroid Build Coastguard Worker /**
244*4dc78e53SAndroid Build Coastguard Worker  * Register a set of cache operations
245*4dc78e53SAndroid Build Coastguard Worker  * @arg ops		cache operations
246*4dc78e53SAndroid Build Coastguard Worker  *
247*4dc78e53SAndroid Build Coastguard Worker  * Called by users of caches to announce the avaibility of
248*4dc78e53SAndroid Build Coastguard Worker  * a certain cache type.
249*4dc78e53SAndroid Build Coastguard Worker  *
250*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
251*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_mngt_register(struct nl_cache_ops * ops)252*4dc78e53SAndroid Build Coastguard Worker int nl_cache_mngt_register(struct nl_cache_ops *ops)
253*4dc78e53SAndroid Build Coastguard Worker {
254*4dc78e53SAndroid Build Coastguard Worker 	if (!ops->co_name || !ops->co_obj_ops)
255*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
256*4dc78e53SAndroid Build Coastguard Worker 
257*4dc78e53SAndroid Build Coastguard Worker 	/* oo_keygen() also needs oo_compare() */
258*4dc78e53SAndroid Build Coastguard Worker 	BUG_ON (ops->co_obj_ops->oo_keygen && !ops->co_obj_ops->oo_compare);
259*4dc78e53SAndroid Build Coastguard Worker 
260*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&cache_ops_lock);
261*4dc78e53SAndroid Build Coastguard Worker 	if (__nl_cache_ops_lookup(ops->co_name)) {
262*4dc78e53SAndroid Build Coastguard Worker 		nl_write_unlock(&cache_ops_lock);
263*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_EXIST;
264*4dc78e53SAndroid Build Coastguard Worker 	}
265*4dc78e53SAndroid Build Coastguard Worker 
266*4dc78e53SAndroid Build Coastguard Worker 	ops->co_refcnt = 0;
267*4dc78e53SAndroid Build Coastguard Worker 	ops->co_next = cache_ops;
268*4dc78e53SAndroid Build Coastguard Worker 	cache_ops = ops;
269*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&cache_ops_lock);
270*4dc78e53SAndroid Build Coastguard Worker 
271*4dc78e53SAndroid Build Coastguard Worker 	NL_DBG(1, "Registered cache operations %s\n", ops->co_name);
272*4dc78e53SAndroid Build Coastguard Worker 
273*4dc78e53SAndroid Build Coastguard Worker 	return 0;
274*4dc78e53SAndroid Build Coastguard Worker }
275*4dc78e53SAndroid Build Coastguard Worker 
276*4dc78e53SAndroid Build Coastguard Worker /**
277*4dc78e53SAndroid Build Coastguard Worker  * Unregister a set of cache operations
278*4dc78e53SAndroid Build Coastguard Worker  * @arg ops		cache operations
279*4dc78e53SAndroid Build Coastguard Worker  *
280*4dc78e53SAndroid Build Coastguard Worker  * Called by users of caches to announce a set of
281*4dc78e53SAndroid Build Coastguard Worker  * cache operations is no longer available. The
282*4dc78e53SAndroid Build Coastguard Worker  * specified cache operations must have been registered
283*4dc78e53SAndroid Build Coastguard Worker  * previously using nl_cache_mngt_register()
284*4dc78e53SAndroid Build Coastguard Worker  *
285*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code
286*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_mngt_unregister(struct nl_cache_ops * ops)287*4dc78e53SAndroid Build Coastguard Worker int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
288*4dc78e53SAndroid Build Coastguard Worker {
289*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *t, **tp;
290*4dc78e53SAndroid Build Coastguard Worker 	int err = 0;
291*4dc78e53SAndroid Build Coastguard Worker 
292*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&cache_ops_lock);
293*4dc78e53SAndroid Build Coastguard Worker 
294*4dc78e53SAndroid Build Coastguard Worker 	if (ops->co_refcnt > 0) {
295*4dc78e53SAndroid Build Coastguard Worker 		err = -NLE_BUSY;
296*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
297*4dc78e53SAndroid Build Coastguard Worker 	}
298*4dc78e53SAndroid Build Coastguard Worker 
299*4dc78e53SAndroid Build Coastguard Worker 	for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next)
300*4dc78e53SAndroid Build Coastguard Worker 		if (t == ops)
301*4dc78e53SAndroid Build Coastguard Worker 			break;
302*4dc78e53SAndroid Build Coastguard Worker 
303*4dc78e53SAndroid Build Coastguard Worker 	if (!t) {
304*4dc78e53SAndroid Build Coastguard Worker 		err = -NLE_NOCACHE;
305*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
306*4dc78e53SAndroid Build Coastguard Worker 	}
307*4dc78e53SAndroid Build Coastguard Worker 
308*4dc78e53SAndroid Build Coastguard Worker 	NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name);
309*4dc78e53SAndroid Build Coastguard Worker 
310*4dc78e53SAndroid Build Coastguard Worker 	*tp = t->co_next;
311*4dc78e53SAndroid Build Coastguard Worker errout:
312*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&cache_ops_lock);
313*4dc78e53SAndroid Build Coastguard Worker 
314*4dc78e53SAndroid Build Coastguard Worker 	return err;
315*4dc78e53SAndroid Build Coastguard Worker }
316*4dc78e53SAndroid Build Coastguard Worker 
317*4dc78e53SAndroid Build Coastguard Worker /** @} */
318*4dc78e53SAndroid Build Coastguard Worker 
319*4dc78e53SAndroid Build Coastguard Worker /**
320*4dc78e53SAndroid Build Coastguard Worker  * @name Global Cache Provisioning/Requiring
321*4dc78e53SAndroid Build Coastguard Worker  * @{
322*4dc78e53SAndroid Build Coastguard Worker  */
323*4dc78e53SAndroid Build Coastguard Worker 
324*4dc78e53SAndroid Build Coastguard Worker /**
325*4dc78e53SAndroid Build Coastguard Worker  * Provide a cache for global use
326*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		cache to provide
327*4dc78e53SAndroid Build Coastguard Worker  *
328*4dc78e53SAndroid Build Coastguard Worker  * Offers the specified cache to be used by other modules.
329*4dc78e53SAndroid Build Coastguard Worker  * Only one cache per type may be shared at a time,
330*4dc78e53SAndroid Build Coastguard Worker  * a previsouly provided caches will be overwritten.
331*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_mngt_provide(struct nl_cache * cache)332*4dc78e53SAndroid Build Coastguard Worker void nl_cache_mngt_provide(struct nl_cache *cache)
333*4dc78e53SAndroid Build Coastguard Worker {
334*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
335*4dc78e53SAndroid Build Coastguard Worker 
336*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&cache_ops_lock);
337*4dc78e53SAndroid Build Coastguard Worker 
338*4dc78e53SAndroid Build Coastguard Worker 	ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
339*4dc78e53SAndroid Build Coastguard Worker 	if (!ops)
340*4dc78e53SAndroid Build Coastguard Worker 		BUG();
341*4dc78e53SAndroid Build Coastguard Worker 	else {
342*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_get(cache);
343*4dc78e53SAndroid Build Coastguard Worker 
344*4dc78e53SAndroid Build Coastguard Worker 		/*
345*4dc78e53SAndroid Build Coastguard Worker 		 * Hold a reference to the cache operations to ensure the
346*4dc78e53SAndroid Build Coastguard Worker 		 * ops don't go away while we use it to store the cache pointer.
347*4dc78e53SAndroid Build Coastguard Worker 		 */
348*4dc78e53SAndroid Build Coastguard Worker 		if (!ops->co_major_cache)
349*4dc78e53SAndroid Build Coastguard Worker 			nl_cache_ops_get(ops);
350*4dc78e53SAndroid Build Coastguard Worker 
351*4dc78e53SAndroid Build Coastguard Worker 		ops->co_major_cache = cache;
352*4dc78e53SAndroid Build Coastguard Worker 	}
353*4dc78e53SAndroid Build Coastguard Worker 
354*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&cache_ops_lock);
355*4dc78e53SAndroid Build Coastguard Worker }
356*4dc78e53SAndroid Build Coastguard Worker 
357*4dc78e53SAndroid Build Coastguard Worker /**
358*4dc78e53SAndroid Build Coastguard Worker  * Unprovide a cache for global use
359*4dc78e53SAndroid Build Coastguard Worker  * @arg cache		cache to unprovide
360*4dc78e53SAndroid Build Coastguard Worker  *
361*4dc78e53SAndroid Build Coastguard Worker  * Cancels the offer to use a cache globally. The
362*4dc78e53SAndroid Build Coastguard Worker  * cache will no longer be returned via lookups but
363*4dc78e53SAndroid Build Coastguard Worker  * may still be in use.
364*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_mngt_unprovide(struct nl_cache * cache)365*4dc78e53SAndroid Build Coastguard Worker void nl_cache_mngt_unprovide(struct nl_cache *cache)
366*4dc78e53SAndroid Build Coastguard Worker {
367*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
368*4dc78e53SAndroid Build Coastguard Worker 
369*4dc78e53SAndroid Build Coastguard Worker 	nl_write_lock(&cache_ops_lock);
370*4dc78e53SAndroid Build Coastguard Worker 
371*4dc78e53SAndroid Build Coastguard Worker 	ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops);
372*4dc78e53SAndroid Build Coastguard Worker 	if (!ops)
373*4dc78e53SAndroid Build Coastguard Worker 		BUG();
374*4dc78e53SAndroid Build Coastguard Worker 	else if (ops->co_major_cache == cache) {
375*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_free(ops->co_major_cache);
376*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_ops_put(ops);
377*4dc78e53SAndroid Build Coastguard Worker 		ops->co_major_cache = NULL;
378*4dc78e53SAndroid Build Coastguard Worker 	}
379*4dc78e53SAndroid Build Coastguard Worker 
380*4dc78e53SAndroid Build Coastguard Worker 	nl_write_unlock(&cache_ops_lock);
381*4dc78e53SAndroid Build Coastguard Worker }
382*4dc78e53SAndroid Build Coastguard Worker 
__nl_cache_mngt_require(const char * name)383*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *__nl_cache_mngt_require(const char *name)
384*4dc78e53SAndroid Build Coastguard Worker {
385*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache_ops *ops;
386*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache = NULL;
387*4dc78e53SAndroid Build Coastguard Worker 
388*4dc78e53SAndroid Build Coastguard Worker 	ops = nl_cache_ops_lookup_safe(name);
389*4dc78e53SAndroid Build Coastguard Worker 	if (ops) {
390*4dc78e53SAndroid Build Coastguard Worker 		cache = ops->co_major_cache;
391*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_ops_put(ops);
392*4dc78e53SAndroid Build Coastguard Worker 	}
393*4dc78e53SAndroid Build Coastguard Worker 
394*4dc78e53SAndroid Build Coastguard Worker 	return cache;
395*4dc78e53SAndroid Build Coastguard Worker }
396*4dc78e53SAndroid Build Coastguard Worker 
397*4dc78e53SAndroid Build Coastguard Worker /**
398*4dc78e53SAndroid Build Coastguard Worker  * Return cache previously provided via nl_cache_mngt_provide()
399*4dc78e53SAndroid Build Coastguard Worker  * @arg name		Name of cache to lookup
400*4dc78e53SAndroid Build Coastguard Worker  *
401*4dc78e53SAndroid Build Coastguard Worker  * @attention This function is not safe, it does not increment the reference
402*4dc78e53SAndroid Build Coastguard Worker  *            counter. Please use nl_cache_mngt_require_safe().
403*4dc78e53SAndroid Build Coastguard Worker  *
404*4dc78e53SAndroid Build Coastguard Worker  * @see nl_cache_mngt_require_safe()
405*4dc78e53SAndroid Build Coastguard Worker  *
406*4dc78e53SAndroid Build Coastguard Worker  * @return Pointer to cache or NULL if none registered
407*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_mngt_require(const char * name)408*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *nl_cache_mngt_require(const char *name)
409*4dc78e53SAndroid Build Coastguard Worker {
410*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache;
411*4dc78e53SAndroid Build Coastguard Worker 
412*4dc78e53SAndroid Build Coastguard Worker 	if (!(cache = __nl_cache_mngt_require(name)))
413*4dc78e53SAndroid Build Coastguard Worker 		NL_DBG(1, "Application BUG: Your application must "
414*4dc78e53SAndroid Build Coastguard Worker 		       "call nl_cache_mngt_provide() and\nprovide a valid "
415*4dc78e53SAndroid Build Coastguard Worker 		       "%s cache to be used for internal lookups.\nSee the "
416*4dc78e53SAndroid Build Coastguard Worker 		       " API documentation for more details.\n", name);
417*4dc78e53SAndroid Build Coastguard Worker 
418*4dc78e53SAndroid Build Coastguard Worker 	return cache;
419*4dc78e53SAndroid Build Coastguard Worker }
420*4dc78e53SAndroid Build Coastguard Worker 
421*4dc78e53SAndroid Build Coastguard Worker /**
422*4dc78e53SAndroid Build Coastguard Worker  * Return cache previously provided via nl_cache_mngt_provide()
423*4dc78e53SAndroid Build Coastguard Worker  * @arg name		Name of cache to lookup
424*4dc78e53SAndroid Build Coastguard Worker  *
425*4dc78e53SAndroid Build Coastguard Worker  * @note The reference counter of the returned cache is incremented
426*4dc78e53SAndroid Build Coastguard Worker  *       and must be decremented after use with nl_cache_put().
427*4dc78e53SAndroid Build Coastguard Worker  *
428*4dc78e53SAndroid Build Coastguard Worker  * @return Pointer to cache or NULL if none registered
429*4dc78e53SAndroid Build Coastguard Worker  */
nl_cache_mngt_require_safe(const char * name)430*4dc78e53SAndroid Build Coastguard Worker struct nl_cache *nl_cache_mngt_require_safe(const char *name)
431*4dc78e53SAndroid Build Coastguard Worker {
432*4dc78e53SAndroid Build Coastguard Worker 	struct nl_cache *cache;
433*4dc78e53SAndroid Build Coastguard Worker 
434*4dc78e53SAndroid Build Coastguard Worker 	if ((cache = nl_cache_mngt_require(name)))
435*4dc78e53SAndroid Build Coastguard Worker 		nl_cache_get(cache);
436*4dc78e53SAndroid Build Coastguard Worker 
437*4dc78e53SAndroid Build Coastguard Worker 	return cache;
438*4dc78e53SAndroid Build Coastguard Worker }
439*4dc78e53SAndroid Build Coastguard Worker 
440*4dc78e53SAndroid Build Coastguard Worker /** @} */
441*4dc78e53SAndroid Build Coastguard Worker 
442*4dc78e53SAndroid Build Coastguard Worker /** @} */
443