19ca40936STijl Coosemans /* $NetBSD: citrus_mapper.c,v 1.10 2012/06/08 07:49:42 martin Exp $ */
2ad30f8e7SGabor Kovesdan
3ad30f8e7SGabor Kovesdan /*-
4*d915a14eSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause
5*d915a14eSPedro F. Giffuni *
6ad30f8e7SGabor Kovesdan * Copyright (c)2003 Citrus Project,
7ad30f8e7SGabor Kovesdan * All rights reserved.
8ad30f8e7SGabor Kovesdan *
9ad30f8e7SGabor Kovesdan * Redistribution and use in source and binary forms, with or without
10ad30f8e7SGabor Kovesdan * modification, are permitted provided that the following conditions
11ad30f8e7SGabor Kovesdan * are met:
12ad30f8e7SGabor Kovesdan * 1. Redistributions of source code must retain the above copyright
13ad30f8e7SGabor Kovesdan * notice, this list of conditions and the following disclaimer.
14ad30f8e7SGabor Kovesdan * 2. Redistributions in binary form must reproduce the above copyright
15ad30f8e7SGabor Kovesdan * notice, this list of conditions and the following disclaimer in the
16ad30f8e7SGabor Kovesdan * documentation and/or other materials provided with the distribution.
17ad30f8e7SGabor Kovesdan *
18ad30f8e7SGabor Kovesdan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19ad30f8e7SGabor Kovesdan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ad30f8e7SGabor Kovesdan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ad30f8e7SGabor Kovesdan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22ad30f8e7SGabor Kovesdan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ad30f8e7SGabor Kovesdan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ad30f8e7SGabor Kovesdan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ad30f8e7SGabor Kovesdan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26ad30f8e7SGabor Kovesdan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27ad30f8e7SGabor Kovesdan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28ad30f8e7SGabor Kovesdan * SUCH DAMAGE.
29ad30f8e7SGabor Kovesdan */
30ad30f8e7SGabor Kovesdan
31ad30f8e7SGabor Kovesdan #include <sys/types.h>
32ad30f8e7SGabor Kovesdan #include <sys/stat.h>
33ad30f8e7SGabor Kovesdan #include <sys/queue.h>
34ad30f8e7SGabor Kovesdan
35ad30f8e7SGabor Kovesdan #include <assert.h>
36ad30f8e7SGabor Kovesdan #include <errno.h>
37ad30f8e7SGabor Kovesdan #include <limits.h>
38ad30f8e7SGabor Kovesdan #include <stdio.h>
39ad30f8e7SGabor Kovesdan #include <stdlib.h>
40ad30f8e7SGabor Kovesdan #include <string.h>
41ad30f8e7SGabor Kovesdan
42ad30f8e7SGabor Kovesdan #include "citrus_namespace.h"
43ad30f8e7SGabor Kovesdan #include "citrus_types.h"
44ad30f8e7SGabor Kovesdan #include "citrus_region.h"
45ad30f8e7SGabor Kovesdan #include "citrus_lock.h"
46ad30f8e7SGabor Kovesdan #include "citrus_memstream.h"
47ad30f8e7SGabor Kovesdan #include "citrus_bcs.h"
48ad30f8e7SGabor Kovesdan #include "citrus_mmap.h"
49ad30f8e7SGabor Kovesdan #include "citrus_module.h"
50ad30f8e7SGabor Kovesdan #include "citrus_hash.h"
51ad30f8e7SGabor Kovesdan #include "citrus_mapper.h"
52ad30f8e7SGabor Kovesdan
53ad30f8e7SGabor Kovesdan #define _CITRUS_MAPPER_DIR "mapper.dir"
54ad30f8e7SGabor Kovesdan
55ad30f8e7SGabor Kovesdan #define CM_HASH_SIZE 101
56ad30f8e7SGabor Kovesdan #define REFCOUNT_PERSISTENT -1
57ad30f8e7SGabor Kovesdan
58ff0b75b8SPeter Wemm static pthread_rwlock_t cm_lock = PTHREAD_RWLOCK_INITIALIZER;
59ff0b75b8SPeter Wemm
60ad30f8e7SGabor Kovesdan struct _citrus_mapper_area {
61ad30f8e7SGabor Kovesdan _CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE) ma_cache;
62ad30f8e7SGabor Kovesdan char *ma_dir;
63ad30f8e7SGabor Kovesdan };
64ad30f8e7SGabor Kovesdan
65ad30f8e7SGabor Kovesdan /*
66ad30f8e7SGabor Kovesdan * _citrus_mapper_create_area:
67ad30f8e7SGabor Kovesdan * create mapper area
68ad30f8e7SGabor Kovesdan */
69ad30f8e7SGabor Kovesdan
70ad30f8e7SGabor Kovesdan int
_citrus_mapper_create_area(struct _citrus_mapper_area * __restrict * __restrict rma,const char * __restrict area)71ad30f8e7SGabor Kovesdan _citrus_mapper_create_area(
72ad30f8e7SGabor Kovesdan struct _citrus_mapper_area *__restrict *__restrict rma,
73ad30f8e7SGabor Kovesdan const char *__restrict area)
74ad30f8e7SGabor Kovesdan {
75ad30f8e7SGabor Kovesdan struct _citrus_mapper_area *ma;
76ad30f8e7SGabor Kovesdan struct stat st;
77ad30f8e7SGabor Kovesdan char path[PATH_MAX];
78ad30f8e7SGabor Kovesdan int ret;
79ad30f8e7SGabor Kovesdan
80ff0b75b8SPeter Wemm WLOCK(&cm_lock);
81ad30f8e7SGabor Kovesdan
82ad30f8e7SGabor Kovesdan if (*rma != NULL) {
83ad30f8e7SGabor Kovesdan ret = 0;
84ad30f8e7SGabor Kovesdan goto quit;
85ad30f8e7SGabor Kovesdan }
86ad30f8e7SGabor Kovesdan
87ad30f8e7SGabor Kovesdan snprintf(path, (size_t)PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR);
88ad30f8e7SGabor Kovesdan
89ad30f8e7SGabor Kovesdan ret = stat(path, &st);
90ad30f8e7SGabor Kovesdan if (ret)
91ad30f8e7SGabor Kovesdan goto quit;
92ad30f8e7SGabor Kovesdan
93ad30f8e7SGabor Kovesdan ma = malloc(sizeof(*ma));
94ad30f8e7SGabor Kovesdan if (ma == NULL) {
95ad30f8e7SGabor Kovesdan ret = errno;
96ad30f8e7SGabor Kovesdan goto quit;
97ad30f8e7SGabor Kovesdan }
98ad30f8e7SGabor Kovesdan ma->ma_dir = strdup(area);
99ad30f8e7SGabor Kovesdan if (ma->ma_dir == NULL) {
100ad30f8e7SGabor Kovesdan ret = errno;
1017c5cb6beSPeter Wemm free(ma);
102ad30f8e7SGabor Kovesdan goto quit;
103ad30f8e7SGabor Kovesdan }
104ad30f8e7SGabor Kovesdan _CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE);
105ad30f8e7SGabor Kovesdan
106ad30f8e7SGabor Kovesdan *rma = ma;
107ad30f8e7SGabor Kovesdan ret = 0;
108ad30f8e7SGabor Kovesdan quit:
109ff0b75b8SPeter Wemm UNLOCK(&cm_lock);
110ad30f8e7SGabor Kovesdan
111ad30f8e7SGabor Kovesdan return (ret);
112ad30f8e7SGabor Kovesdan }
113ad30f8e7SGabor Kovesdan
114ad30f8e7SGabor Kovesdan
115ad30f8e7SGabor Kovesdan /*
116ad30f8e7SGabor Kovesdan * lookup_mapper_entry:
117ad30f8e7SGabor Kovesdan * lookup mapper.dir entry in the specified directory.
118ad30f8e7SGabor Kovesdan *
119ad30f8e7SGabor Kovesdan * line format of iconv.dir file:
120ad30f8e7SGabor Kovesdan * mapper module arg
121ad30f8e7SGabor Kovesdan * mapper : mapper name.
122ad30f8e7SGabor Kovesdan * module : mapper module name.
123ad30f8e7SGabor Kovesdan * arg : argument for the module (generally, description file name)
124ad30f8e7SGabor Kovesdan */
125ad30f8e7SGabor Kovesdan
126ad30f8e7SGabor Kovesdan static int
lookup_mapper_entry(const char * dir,const char * mapname,void * linebuf,size_t linebufsize,const char ** module,const char ** variable)127ad30f8e7SGabor Kovesdan lookup_mapper_entry(const char *dir, const char *mapname, void *linebuf,
128ad30f8e7SGabor Kovesdan size_t linebufsize, const char **module, const char **variable)
129ad30f8e7SGabor Kovesdan {
130ad30f8e7SGabor Kovesdan struct _region r;
131ad30f8e7SGabor Kovesdan struct _memstream ms;
132ad30f8e7SGabor Kovesdan const char *cp, *cq;
133ad30f8e7SGabor Kovesdan char *p;
134ad30f8e7SGabor Kovesdan char path[PATH_MAX];
135ad30f8e7SGabor Kovesdan size_t len;
136ad30f8e7SGabor Kovesdan int ret;
137ad30f8e7SGabor Kovesdan
138ad30f8e7SGabor Kovesdan /* create mapper.dir path */
139ad30f8e7SGabor Kovesdan snprintf(path, (size_t)PATH_MAX, "%s/%s", dir, _CITRUS_MAPPER_DIR);
140ad30f8e7SGabor Kovesdan
141ad30f8e7SGabor Kovesdan /* open read stream */
142ad30f8e7SGabor Kovesdan ret = _map_file(&r, path);
143ad30f8e7SGabor Kovesdan if (ret)
144ad30f8e7SGabor Kovesdan return (ret);
145ad30f8e7SGabor Kovesdan
146ad30f8e7SGabor Kovesdan _memstream_bind(&ms, &r);
147ad30f8e7SGabor Kovesdan
148ad30f8e7SGabor Kovesdan /* search the line matching to the map name */
149ad30f8e7SGabor Kovesdan cp = _memstream_matchline(&ms, mapname, &len, 0);
150ad30f8e7SGabor Kovesdan if (!cp) {
151ad30f8e7SGabor Kovesdan ret = ENOENT;
152ad30f8e7SGabor Kovesdan goto quit;
153ad30f8e7SGabor Kovesdan }
154ad30f8e7SGabor Kovesdan if (!len || len > linebufsize - 1) {
155ad30f8e7SGabor Kovesdan ret = EINVAL;
156ad30f8e7SGabor Kovesdan goto quit;
157ad30f8e7SGabor Kovesdan }
158ad30f8e7SGabor Kovesdan
159ad30f8e7SGabor Kovesdan p = linebuf;
160ad30f8e7SGabor Kovesdan /* get module name */
161ad30f8e7SGabor Kovesdan *module = p;
162ad30f8e7SGabor Kovesdan cq = _bcs_skip_nonws_len(cp, &len);
163ad30f8e7SGabor Kovesdan strlcpy(p, cp, (size_t)(cq - cp + 1));
164ad30f8e7SGabor Kovesdan p += cq - cp + 1;
165ad30f8e7SGabor Kovesdan
166ad30f8e7SGabor Kovesdan /* get variable */
167ad30f8e7SGabor Kovesdan *variable = p;
168ad30f8e7SGabor Kovesdan cp = _bcs_skip_ws_len(cq, &len);
169ad30f8e7SGabor Kovesdan strlcpy(p, cp, len + 1);
170ad30f8e7SGabor Kovesdan
171ad30f8e7SGabor Kovesdan ret = 0;
172ad30f8e7SGabor Kovesdan
173ad30f8e7SGabor Kovesdan quit:
174ad30f8e7SGabor Kovesdan _unmap_file(&r);
175ad30f8e7SGabor Kovesdan return (ret);
176ad30f8e7SGabor Kovesdan }
177ad30f8e7SGabor Kovesdan
178ad30f8e7SGabor Kovesdan /*
179ad30f8e7SGabor Kovesdan * mapper_close:
180ad30f8e7SGabor Kovesdan * simply close a mapper. (without handling hash)
181ad30f8e7SGabor Kovesdan */
182ad30f8e7SGabor Kovesdan static void
mapper_close(struct _citrus_mapper * cm)183ad30f8e7SGabor Kovesdan mapper_close(struct _citrus_mapper *cm)
184ad30f8e7SGabor Kovesdan {
185ad30f8e7SGabor Kovesdan if (cm->cm_module) {
186ad30f8e7SGabor Kovesdan if (cm->cm_ops) {
187ad30f8e7SGabor Kovesdan if (cm->cm_closure)
188ad30f8e7SGabor Kovesdan (*cm->cm_ops->mo_uninit)(cm);
189ad30f8e7SGabor Kovesdan free(cm->cm_ops);
190ad30f8e7SGabor Kovesdan }
191ad30f8e7SGabor Kovesdan _citrus_unload_module(cm->cm_module);
192ad30f8e7SGabor Kovesdan }
193ad30f8e7SGabor Kovesdan free(cm->cm_traits);
194ad30f8e7SGabor Kovesdan free(cm);
195ad30f8e7SGabor Kovesdan }
196ad30f8e7SGabor Kovesdan
197ad30f8e7SGabor Kovesdan /*
198ad30f8e7SGabor Kovesdan * mapper_open:
199ad30f8e7SGabor Kovesdan * simply open a mapper. (without handling hash)
200ad30f8e7SGabor Kovesdan */
201ad30f8e7SGabor Kovesdan static int
mapper_open(struct _citrus_mapper_area * __restrict ma,struct _citrus_mapper * __restrict * __restrict rcm,const char * __restrict module,const char * __restrict variable)202ad30f8e7SGabor Kovesdan mapper_open(struct _citrus_mapper_area *__restrict ma,
203ad30f8e7SGabor Kovesdan struct _citrus_mapper * __restrict * __restrict rcm,
204ad30f8e7SGabor Kovesdan const char * __restrict module,
205ad30f8e7SGabor Kovesdan const char * __restrict variable)
206ad30f8e7SGabor Kovesdan {
207ad30f8e7SGabor Kovesdan struct _citrus_mapper *cm;
208ad30f8e7SGabor Kovesdan _citrus_mapper_getops_t getops;
209ad30f8e7SGabor Kovesdan int ret;
210ad30f8e7SGabor Kovesdan
211ad30f8e7SGabor Kovesdan /* initialize mapper handle */
212ad30f8e7SGabor Kovesdan cm = malloc(sizeof(*cm));
213ad30f8e7SGabor Kovesdan if (!cm)
214ad30f8e7SGabor Kovesdan return (errno);
215ad30f8e7SGabor Kovesdan
216ad30f8e7SGabor Kovesdan cm->cm_module = NULL;
217ad30f8e7SGabor Kovesdan cm->cm_ops = NULL;
218ad30f8e7SGabor Kovesdan cm->cm_closure = NULL;
219ad30f8e7SGabor Kovesdan cm->cm_traits = NULL;
220ad30f8e7SGabor Kovesdan cm->cm_refcount = 0;
221ad30f8e7SGabor Kovesdan cm->cm_key = NULL;
222ad30f8e7SGabor Kovesdan
223ad30f8e7SGabor Kovesdan /* load module */
224ad30f8e7SGabor Kovesdan ret = _citrus_load_module(&cm->cm_module, module);
225ad30f8e7SGabor Kovesdan if (ret)
226ad30f8e7SGabor Kovesdan goto err;
227ad30f8e7SGabor Kovesdan
228ad30f8e7SGabor Kovesdan /* get operators */
229ad30f8e7SGabor Kovesdan getops = (_citrus_mapper_getops_t)
230ad30f8e7SGabor Kovesdan _citrus_find_getops(cm->cm_module, module, "mapper");
231ad30f8e7SGabor Kovesdan if (!getops) {
232ad30f8e7SGabor Kovesdan ret = EOPNOTSUPP;
233ad30f8e7SGabor Kovesdan goto err;
234ad30f8e7SGabor Kovesdan }
235ad30f8e7SGabor Kovesdan cm->cm_ops = malloc(sizeof(*cm->cm_ops));
236ad30f8e7SGabor Kovesdan if (!cm->cm_ops) {
237ad30f8e7SGabor Kovesdan ret = errno;
238ad30f8e7SGabor Kovesdan goto err;
239ad30f8e7SGabor Kovesdan }
240ad30f8e7SGabor Kovesdan ret = (*getops)(cm->cm_ops);
241ad30f8e7SGabor Kovesdan if (ret)
242ad30f8e7SGabor Kovesdan goto err;
243ad30f8e7SGabor Kovesdan
244ad30f8e7SGabor Kovesdan if (!cm->cm_ops->mo_init ||
245ad30f8e7SGabor Kovesdan !cm->cm_ops->mo_uninit ||
246ad30f8e7SGabor Kovesdan !cm->cm_ops->mo_convert ||
2479ca40936STijl Coosemans !cm->cm_ops->mo_init_state) {
2489ca40936STijl Coosemans ret = EINVAL;
249ad30f8e7SGabor Kovesdan goto err;
2509ca40936STijl Coosemans }
251ad30f8e7SGabor Kovesdan
252ad30f8e7SGabor Kovesdan /* allocate traits structure */
253ad30f8e7SGabor Kovesdan cm->cm_traits = malloc(sizeof(*cm->cm_traits));
254ad30f8e7SGabor Kovesdan if (cm->cm_traits == NULL) {
255ad30f8e7SGabor Kovesdan ret = errno;
256ad30f8e7SGabor Kovesdan goto err;
257ad30f8e7SGabor Kovesdan }
258ad30f8e7SGabor Kovesdan /* initialize the mapper */
259ad30f8e7SGabor Kovesdan ret = (*cm->cm_ops->mo_init)(ma, cm, ma->ma_dir,
260ad30f8e7SGabor Kovesdan (const void *)variable, strlen(variable) + 1,
261ad30f8e7SGabor Kovesdan cm->cm_traits, sizeof(*cm->cm_traits));
262ad30f8e7SGabor Kovesdan if (ret)
263ad30f8e7SGabor Kovesdan goto err;
264ad30f8e7SGabor Kovesdan
265ad30f8e7SGabor Kovesdan *rcm = cm;
266ad30f8e7SGabor Kovesdan
267ad30f8e7SGabor Kovesdan return (0);
268ad30f8e7SGabor Kovesdan
269ad30f8e7SGabor Kovesdan err:
270ad30f8e7SGabor Kovesdan mapper_close(cm);
271ad30f8e7SGabor Kovesdan return (ret);
272ad30f8e7SGabor Kovesdan }
273ad30f8e7SGabor Kovesdan
274ad30f8e7SGabor Kovesdan /*
275ad30f8e7SGabor Kovesdan * _citrus_mapper_open_direct:
276ad30f8e7SGabor Kovesdan * open a mapper.
277ad30f8e7SGabor Kovesdan */
278ad30f8e7SGabor Kovesdan int
_citrus_mapper_open_direct(struct _citrus_mapper_area * __restrict ma,struct _citrus_mapper * __restrict * __restrict rcm,const char * __restrict module,const char * __restrict variable)279ad30f8e7SGabor Kovesdan _citrus_mapper_open_direct(struct _citrus_mapper_area *__restrict ma,
280ad30f8e7SGabor Kovesdan struct _citrus_mapper * __restrict * __restrict rcm,
281ad30f8e7SGabor Kovesdan const char * __restrict module, const char * __restrict variable)
282ad30f8e7SGabor Kovesdan {
283ad30f8e7SGabor Kovesdan
284ad30f8e7SGabor Kovesdan return (mapper_open(ma, rcm, module, variable));
285ad30f8e7SGabor Kovesdan }
286ad30f8e7SGabor Kovesdan
287ad30f8e7SGabor Kovesdan /*
288ad30f8e7SGabor Kovesdan * hash_func
289ad30f8e7SGabor Kovesdan */
290ad30f8e7SGabor Kovesdan static __inline int
hash_func(const char * key)291ad30f8e7SGabor Kovesdan hash_func(const char *key)
292ad30f8e7SGabor Kovesdan {
293ad30f8e7SGabor Kovesdan
294ad30f8e7SGabor Kovesdan return (_string_hash_func(key, CM_HASH_SIZE));
295ad30f8e7SGabor Kovesdan }
296ad30f8e7SGabor Kovesdan
297ad30f8e7SGabor Kovesdan /*
298ad30f8e7SGabor Kovesdan * match_func
299ad30f8e7SGabor Kovesdan */
300ad30f8e7SGabor Kovesdan static __inline int
match_func(struct _citrus_mapper * cm,const char * key)301ad30f8e7SGabor Kovesdan match_func(struct _citrus_mapper *cm, const char *key)
302ad30f8e7SGabor Kovesdan {
303ad30f8e7SGabor Kovesdan
304ad30f8e7SGabor Kovesdan return (strcmp(cm->cm_key, key));
305ad30f8e7SGabor Kovesdan }
306ad30f8e7SGabor Kovesdan
307ad30f8e7SGabor Kovesdan /*
308ad30f8e7SGabor Kovesdan * _citrus_mapper_open:
309ad30f8e7SGabor Kovesdan * open a mapper with looking up "mapper.dir".
310ad30f8e7SGabor Kovesdan */
311ad30f8e7SGabor Kovesdan int
_citrus_mapper_open(struct _citrus_mapper_area * __restrict ma,struct _citrus_mapper * __restrict * __restrict rcm,const char * __restrict mapname)312ad30f8e7SGabor Kovesdan _citrus_mapper_open(struct _citrus_mapper_area *__restrict ma,
313ad30f8e7SGabor Kovesdan struct _citrus_mapper * __restrict * __restrict rcm,
314ad30f8e7SGabor Kovesdan const char * __restrict mapname)
315ad30f8e7SGabor Kovesdan {
316ad30f8e7SGabor Kovesdan struct _citrus_mapper *cm;
317ad30f8e7SGabor Kovesdan char linebuf[PATH_MAX];
318ad30f8e7SGabor Kovesdan const char *module, *variable;
319ad30f8e7SGabor Kovesdan int hashval, ret;
320ad30f8e7SGabor Kovesdan
321ad30f8e7SGabor Kovesdan variable = NULL;
322ad30f8e7SGabor Kovesdan
323ff0b75b8SPeter Wemm WLOCK(&cm_lock);
324ad30f8e7SGabor Kovesdan
325ad30f8e7SGabor Kovesdan /* search in the cache */
326ad30f8e7SGabor Kovesdan hashval = hash_func(mapname);
327ad30f8e7SGabor Kovesdan _CITRUS_HASH_SEARCH(&ma->ma_cache, cm, cm_entry, match_func, mapname,
328ad30f8e7SGabor Kovesdan hashval);
329ad30f8e7SGabor Kovesdan if (cm) {
330ad30f8e7SGabor Kovesdan /* found */
331ad30f8e7SGabor Kovesdan cm->cm_refcount++;
332ad30f8e7SGabor Kovesdan *rcm = cm;
333ad30f8e7SGabor Kovesdan ret = 0;
334ad30f8e7SGabor Kovesdan goto quit;
335ad30f8e7SGabor Kovesdan }
336ad30f8e7SGabor Kovesdan
337ad30f8e7SGabor Kovesdan /* search mapper entry */
338ad30f8e7SGabor Kovesdan ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf,
339ad30f8e7SGabor Kovesdan (size_t)PATH_MAX, &module, &variable);
340ad30f8e7SGabor Kovesdan if (ret)
341ad30f8e7SGabor Kovesdan goto quit;
342ad30f8e7SGabor Kovesdan
343ad30f8e7SGabor Kovesdan /* open mapper */
344ff0b75b8SPeter Wemm UNLOCK(&cm_lock);
345ad30f8e7SGabor Kovesdan ret = mapper_open(ma, &cm, module, variable);
346ff0b75b8SPeter Wemm WLOCK(&cm_lock);
347ad30f8e7SGabor Kovesdan if (ret)
348ad30f8e7SGabor Kovesdan goto quit;
349ad30f8e7SGabor Kovesdan cm->cm_key = strdup(mapname);
350ad30f8e7SGabor Kovesdan if (cm->cm_key == NULL) {
351ad30f8e7SGabor Kovesdan ret = errno;
352ad30f8e7SGabor Kovesdan _mapper_close(cm);
353ad30f8e7SGabor Kovesdan goto quit;
354ad30f8e7SGabor Kovesdan }
355ad30f8e7SGabor Kovesdan
356ad30f8e7SGabor Kovesdan /* insert to the cache */
357ad30f8e7SGabor Kovesdan cm->cm_refcount = 1;
358ad30f8e7SGabor Kovesdan _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
359ad30f8e7SGabor Kovesdan
360ad30f8e7SGabor Kovesdan *rcm = cm;
361ad30f8e7SGabor Kovesdan ret = 0;
362ad30f8e7SGabor Kovesdan quit:
363ff0b75b8SPeter Wemm UNLOCK(&cm_lock);
364ad30f8e7SGabor Kovesdan
365ad30f8e7SGabor Kovesdan return (ret);
366ad30f8e7SGabor Kovesdan }
367ad30f8e7SGabor Kovesdan
368ad30f8e7SGabor Kovesdan /*
369ad30f8e7SGabor Kovesdan * _citrus_mapper_close:
370ad30f8e7SGabor Kovesdan * close the specified mapper.
371ad30f8e7SGabor Kovesdan */
372ad30f8e7SGabor Kovesdan void
_citrus_mapper_close(struct _citrus_mapper * cm)373ad30f8e7SGabor Kovesdan _citrus_mapper_close(struct _citrus_mapper *cm)
374ad30f8e7SGabor Kovesdan {
375ad30f8e7SGabor Kovesdan
376ad30f8e7SGabor Kovesdan if (cm) {
377ff0b75b8SPeter Wemm WLOCK(&cm_lock);
378ad30f8e7SGabor Kovesdan if (cm->cm_refcount == REFCOUNT_PERSISTENT)
379ad30f8e7SGabor Kovesdan goto quit;
380ad30f8e7SGabor Kovesdan if (cm->cm_refcount > 0) {
381ad30f8e7SGabor Kovesdan if (--cm->cm_refcount > 0)
382ad30f8e7SGabor Kovesdan goto quit;
383ad30f8e7SGabor Kovesdan _CITRUS_HASH_REMOVE(cm, cm_entry);
384ad30f8e7SGabor Kovesdan free(cm->cm_key);
385ad30f8e7SGabor Kovesdan }
3865e9a119cSXin LI UNLOCK(&cm_lock);
387ad30f8e7SGabor Kovesdan mapper_close(cm);
3885e9a119cSXin LI return;
389ad30f8e7SGabor Kovesdan quit:
390ff0b75b8SPeter Wemm UNLOCK(&cm_lock);
391ad30f8e7SGabor Kovesdan }
392ad30f8e7SGabor Kovesdan }
393ad30f8e7SGabor Kovesdan
394ad30f8e7SGabor Kovesdan /*
395ad30f8e7SGabor Kovesdan * _citrus_mapper_set_persistent:
396ad30f8e7SGabor Kovesdan * set persistent count.
397ad30f8e7SGabor Kovesdan */
398ad30f8e7SGabor Kovesdan void
_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)399ad30f8e7SGabor Kovesdan _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
400ad30f8e7SGabor Kovesdan {
401ad30f8e7SGabor Kovesdan
402ff0b75b8SPeter Wemm WLOCK(&cm_lock);
403ad30f8e7SGabor Kovesdan cm->cm_refcount = REFCOUNT_PERSISTENT;
404ff0b75b8SPeter Wemm UNLOCK(&cm_lock);
405ad30f8e7SGabor Kovesdan }
406