62
63
#define EXT2FS_NODE(node) ((node) ? (ext2fs_node_t *) (node)->data : NULL)
63
64
#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
64
#define OPEN_NODES_KEYS 2
65
#define OPEN_NODES_DEV_HANDLE_KEY 0
66
#define OPEN_NODES_INODE_KEY 1
67
#define OPEN_NODES_BUCKETS 256
69
66
typedef struct ext2fs_instance {
121
118
static hash_table_t open_nodes;
122
119
static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
124
/* Hash table interface for open nodes hash table */
125
static hash_index_t open_nodes_hash(unsigned long key[])
127
/* TODO: This is very simple and probably can be improved */
128
return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
131
static int open_nodes_compare(unsigned long key[], hash_count_t keys,
134
ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
136
if (enode->instance->service_id !=
137
((service_id_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
144
return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
147
static void open_nodes_remove_cb(link_t *link)
149
/* We don't use remove callback for this hash table */
152
static hash_table_operations_t open_nodes_ops = {
122
* Hash table interface for open nodes hash table
126
service_id_t service_id;
130
static size_t open_nodes_key_hash(void *key)
132
node_key_t *node_key = (node_key_t*)key;
133
return hash_combine(node_key->service_id, node_key->index);
136
static size_t open_nodes_hash(const ht_link_t *item)
138
ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
140
assert(enode->instance);
141
assert(enode->inode_ref);
143
return hash_combine(enode->instance->service_id, enode->inode_ref->index);
146
static bool open_nodes_key_equal(void *key, const ht_link_t *item)
148
node_key_t *node_key = (node_key_t*)key;
149
ext2fs_node_t *enode = hash_table_get_inst(item, ext2fs_node_t, link);
151
return node_key->service_id == enode->instance->service_id
152
&& node_key->index == enode->inode_ref->index;
155
static hash_table_ops_t open_nodes_ops = {
153
156
.hash = open_nodes_hash,
154
.compare = open_nodes_compare,
155
.remove_callback = open_nodes_remove_cb,
157
.key_hash = open_nodes_key_hash,
158
.key_equal = open_nodes_key_equal,
160
.remove_callback = NULL,
161
166
int ext2fs_global_init(void)
163
if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
164
OPEN_NODES_KEYS, &open_nodes_ops)) {
168
if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops)) {
315
319
fibril_mutex_lock(&open_nodes_lock);
317
321
/* Check if the node is not already open */
318
unsigned long key[] = {
319
[OPEN_NODES_DEV_HANDLE_KEY] = inst->service_id,
320
[OPEN_NODES_INODE_KEY] = index,
323
.service_id = inst->service_id,
322
link_t *already_open = hash_table_find(&open_nodes, key);
326
ht_link_t *already_open = hash_table_find(&open_nodes, &key);
324
328
if (already_open) {
325
enode = hash_table_get_instance(already_open, ext2fs_node_t, link);
329
enode = hash_table_get_inst(already_open, ext2fs_node_t, link);
326
330
*rfn = enode->fs_node;
327
331
enode->references++;
356
360
enode->instance = inst;
357
361
enode->references = 1;
358
362
enode->fs_node = node;
359
link_initialize(&enode->link);
361
364
node->data = enode;
364
hash_table_insert(&open_nodes, key, &enode->link);
367
hash_table_insert(&open_nodes, &enode->link);
365
368
inst->open_nodes_count++;
367
370
EXT2FS_DBG("inode: %u", inode_ref->index);
408
411
int ext2fs_node_put_core(ext2fs_node_t *enode)
414
.service_id = enode->instance->service_id,
415
.index = enode->inode_ref->index
412
unsigned long key[] = {
413
[OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id,
414
[OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
416
hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
418
hash_table_remove(&open_nodes, &key);
417
420
assert(enode->instance->open_nodes_count > 0);
418
421
enode->instance->open_nodes_count--;
420
rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
423
int rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
422
425
EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");