source: mainline/uspace/srv/fs/udf/udf_idx.c@ 48e3190

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 48e3190 was 48e3190, checked in by Martin Decky <martin@…>, 13 years ago

cherrypick UDF file system driver implementation (originally by Julia Medvedeva)
with coding style improvements and minor changes

  • Property mode set to 100644
File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 2012 Julia Medvedeva
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup fs
30 * @{
31 */
32/**
33 * @file udf_idx.c
34 * @brief Very simple UDF hashtable for nodes
35 */
36
37#include "../../vfs/vfs.h"
38#include <errno.h>
39#include <str.h>
40#include <assert.h>
41#include <fibril_synch.h>
42#include <malloc.h>
43#include <adt/hash_table.h>
44#include <adt/list.h>
45#include "udf_idx.h"
46#include "udf.h"
47
48#define UDF_IDX_KEYS 2
49#define UDF_IDX_KEY 1
50
51#define UDF_IDX_SERVICE_ID_KEY 0
52#define UDF_IDX_BUCKETS 1024
53
54static FIBRIL_MUTEX_INITIALIZE(udf_idx_lock);
55
56static hash_table_t udf_idx;
57
58/** Calculate value of hash by key
59 *
60 * @param Key for calculation of function
61 *
62 * @return Value of hash function
63 *
64 */
65static hash_index_t udf_idx_hash(unsigned long key[])
66{
67 /* TODO: This is very simple and probably can be improved */
68 return key[UDF_IDX_KEY] % UDF_IDX_BUCKETS;
69}
70
71/** Compare two items of hash table
72 *
73 * @param key Key of hash table item. Include several items.
74 * @param keys Number of parts of key.
75 * @param item Item of hash table
76 *
77 * @return True if input value of key equivalent key of node from hash table
78 *
79 */
80static int udf_idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
81{
82 assert(keys > 0);
83
84 udf_node_t *node = hash_table_get_instance(item, udf_node_t, link);
85
86 if (node->instance->service_id !=
87 ((service_id_t) key[UDF_IDX_SERVICE_ID_KEY]))
88 return false;
89
90 assert(keys == 2);
91 return (node->index == key[UDF_IDX_KEY]);
92}
93
94/** Remove callback
95 *
96 */
97static void udf_idx_remove_cb(link_t *link)
98{
99 /* We don't use remove callback for this hash table */
100}
101
102static hash_table_operations_t udf_idx_ops = {
103 .hash = udf_idx_hash,
104 .compare = udf_idx_compare,
105 .remove_callback = udf_idx_remove_cb,
106};
107
108/** Initialization of hash table
109 *
110 * @return EOK on success or a negative error code.
111 *
112 */
113int udf_idx_init(void)
114{
115 if (!hash_table_create(&udf_idx, UDF_IDX_BUCKETS, UDF_IDX_KEYS,
116 &udf_idx_ops))
117 return ENOMEM;
118
119 return EOK;
120}
121
122/** Delete hash table
123 *
124 * @return EOK on success or a negative error code.
125 *
126 */
127int udf_idx_fini(void)
128{
129 hash_table_destroy(&udf_idx);
130 return EOK;
131}
132
133/** Get node from hash table
134 *
135 * @param udfn Returned value - UDF node
136 * @param instance UDF instance
137 * @param index Absolute position of ICB (sector)
138 *
139 * @return EOK on success or a negative error code.
140 *
141 */
142int udf_idx_get(udf_node_t **udfn, udf_instance_t *instance, fs_index_t index)
143{
144 fibril_mutex_lock(&udf_idx_lock);
145
146 unsigned long key[] = {
147 [UDF_IDX_SERVICE_ID_KEY] = instance->service_id,
148 [UDF_IDX_KEY] = index
149 };
150
151 link_t *already_open = hash_table_find(&udf_idx, key);
152 if (already_open) {
153 udf_node_t *node = hash_table_get_instance(already_open,
154 udf_node_t, link);
155 node->ref_cnt++;
156
157 *udfn = node;
158
159 fibril_mutex_unlock(&udf_idx_lock);
160 return EOK;
161 }
162
163 fibril_mutex_unlock(&udf_idx_lock);
164 return ENOENT;
165}
166
167/** Create new node in hash table
168 *
169 * @param udfn Returned value - new UDF node
170 * @param instance UDF instance
171 * @param index Absolute position of ICB (sector)
172 *
173 * @return EOK on success or a negative error code.
174 *
175 */
176int udf_idx_add(udf_node_t **udfn, udf_instance_t *instance, fs_index_t index)
177{
178 fibril_mutex_lock(&udf_idx_lock);
179
180 udf_node_t *udf_node = malloc(sizeof(udf_node_t));
181 if (udf_node == NULL) {
182 fibril_mutex_unlock(&udf_idx_lock);
183 return ENOMEM;
184 }
185
186 fs_node_t *fs_node = malloc(sizeof(fs_node_t));
187 if (fs_node == NULL) {
188 free(udf_node);
189 fibril_mutex_unlock(&udf_idx_lock);
190 return ENOMEM;
191 }
192
193 fs_node_initialize(fs_node);
194
195 udf_node->index = index;
196 udf_node->instance = instance;
197 udf_node->ref_cnt = 1;
198 udf_node->link_cnt = 0;
199 udf_node->fs_node = fs_node;
200 udf_node->data = NULL;
201 udf_node->allocators = NULL;
202
203 fibril_mutex_initialize(&udf_node->lock);
204 link_initialize(&udf_node->link);
205 fs_node->data = udf_node;
206
207 unsigned long key[] = {
208 [UDF_IDX_SERVICE_ID_KEY] = instance->service_id,
209 [UDF_IDX_KEY] = index
210 };
211
212 hash_table_insert(&udf_idx, key, &udf_node->link);
213 instance->open_nodes_count++;
214
215 *udfn = udf_node;
216
217 fibril_mutex_unlock(&udf_idx_lock);
218 return EOK;
219}
220
221/** Delete node from hash table
222 *
223 * @param node UDF node
224 *
225 * @return EOK on success or a negative error code.
226 *
227 */
228int udf_idx_del(udf_node_t *node)
229{
230 assert(node->ref_cnt == 0);
231
232 fibril_mutex_lock(&udf_idx_lock);
233
234 unsigned long key[] = {
235 [UDF_IDX_SERVICE_ID_KEY] = node->instance->service_id,
236 [UDF_IDX_KEY] = node->index
237 };
238
239 hash_table_remove(&udf_idx, key, UDF_IDX_KEYS);
240
241 assert(node->instance->open_nodes_count > 0);
242 node->instance->open_nodes_count--;
243
244 free(node->fs_node);
245 free(node);
246
247 fibril_mutex_unlock(&udf_idx_lock);
248 return EOK;
249}
250
251/**
252 * @}
253 */
Note: See TracBrowser for help on using the repository browser.