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