Rev 4153 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4153 | Rev 4581 | ||
|---|---|---|---|
| Line 36... | Line 36... | ||
| 36 | */ |
36 | */ |
| 37 | 37 | ||
| 38 | #include "vfs.h" |
38 | #include "vfs.h" |
| 39 | #include <stdlib.h> |
39 | #include <stdlib.h> |
| 40 | #include <string.h> |
40 | #include <string.h> |
| 41 | #include <futex.h> |
- | |
| 42 | #include <rwlock.h> |
41 | #include <fibril_sync.h> |
| 43 | #include <libadt/hash_table.h> |
42 | #include <adt/hash_table.h> |
| 44 | #include <assert.h> |
43 | #include <assert.h> |
| 45 | #include <async.h> |
44 | #include <async.h> |
| 46 | #include <errno.h> |
45 | #include <errno.h> |
| 47 | 46 | ||
| 48 | /** Futex protecting the VFS node hash table. */ |
47 | /** Mutex protecting the VFS node hash table. */ |
| 49 | futex_t nodes_futex = FUTEX_INITIALIZER; |
48 | FIBRIL_MUTEX_INITIALIZE(nodes_mutex); |
| 50 | 49 | ||
| 51 | #define NODES_BUCKETS_LOG 8 |
50 | #define NODES_BUCKETS_LOG 8 |
| 52 | #define NODES_BUCKETS (1 << NODES_BUCKETS_LOG) |
51 | #define NODES_BUCKETS (1 << NODES_BUCKETS_LOG) |
| 53 | 52 | ||
| 54 | /** VFS node hash table containing all active, in-memory VFS nodes. */ |
53 | /** VFS node hash table containing all active, in-memory VFS nodes. */ |
| Line 87... | Line 86... | ||
| 87 | * |
86 | * |
| 88 | * @param node VFS node that will have its refcnt incremented. |
87 | * @param node VFS node that will have its refcnt incremented. |
| 89 | */ |
88 | */ |
| 90 | void vfs_node_addref(vfs_node_t *node) |
89 | void vfs_node_addref(vfs_node_t *node) |
| 91 | { |
90 | { |
| 92 | futex_down(&nodes_futex); |
91 | fibril_mutex_lock(&nodes_mutex); |
| 93 | _vfs_node_addref(node); |
92 | _vfs_node_addref(node); |
| 94 | futex_up(&nodes_futex); |
93 | fibril_mutex_unlock(&nodes_mutex); |
| 95 | } |
94 | } |
| 96 | 95 | ||
| 97 | /** Decrement reference count of a VFS node. |
96 | /** Decrement reference count of a VFS node. |
| 98 | * |
97 | * |
| 99 | * This function handles the case when the reference count drops to zero. |
98 | * This function handles the case when the reference count drops to zero. |
| Line 103... | Line 102... | ||
| 103 | void vfs_node_delref(vfs_node_t *node) |
102 | void vfs_node_delref(vfs_node_t *node) |
| 104 | { |
103 | { |
| 105 | bool free_vfs_node = false; |
104 | bool free_vfs_node = false; |
| 106 | bool free_fs_node = false; |
105 | bool free_fs_node = false; |
| 107 | 106 | ||
| 108 | futex_down(&nodes_futex); |
107 | fibril_mutex_lock(&nodes_mutex); |
| 109 | if (node->refcnt-- == 1) { |
108 | if (node->refcnt-- == 1) { |
| 110 | /* |
109 | /* |
| 111 | * We are dropping the last reference to this node. |
110 | * We are dropping the last reference to this node. |
| 112 | * Remove it from the VFS node hash table. |
111 | * Remove it from the VFS node hash table. |
| 113 | */ |
112 | */ |
| Line 119... | Line 118... | ||
| 119 | hash_table_remove(&nodes, key, 3); |
118 | hash_table_remove(&nodes, key, 3); |
| 120 | free_vfs_node = true; |
119 | free_vfs_node = true; |
| 121 | if (!node->lnkcnt) |
120 | if (!node->lnkcnt) |
| 122 | free_fs_node = true; |
121 | free_fs_node = true; |
| 123 | } |
122 | } |
| 124 | futex_up(&nodes_futex); |
123 | fibril_mutex_unlock(&nodes_mutex); |
| 125 | 124 | ||
| 126 | if (free_fs_node) { |
125 | if (free_fs_node) { |
| 127 | /* |
126 | /* |
| 128 | * The node is not visible in the file system namespace. |
127 | * The node is not visible in the file system namespace. |
| 129 | * Free up its resources. |
128 | * Free up its resources. |
| Line 159... | Line 158... | ||
| 159 | [KEY_INDEX] = result->triplet.index |
158 | [KEY_INDEX] = result->triplet.index |
| 160 | }; |
159 | }; |
| 161 | link_t *tmp; |
160 | link_t *tmp; |
| 162 | vfs_node_t *node; |
161 | vfs_node_t *node; |
| 163 | 162 | ||
| 164 | futex_down(&nodes_futex); |
163 | fibril_mutex_lock(&nodes_mutex); |
| 165 | tmp = hash_table_find(&nodes, key); |
164 | tmp = hash_table_find(&nodes, key); |
| 166 | if (!tmp) { |
165 | if (!tmp) { |
| 167 | node = (vfs_node_t *) malloc(sizeof(vfs_node_t)); |
166 | node = (vfs_node_t *) malloc(sizeof(vfs_node_t)); |
| 168 | if (!node) { |
167 | if (!node) { |
| 169 | futex_up(&nodes_futex); |
168 | fibril_mutex_unlock(&nodes_mutex); |
| 170 | return NULL; |
169 | return NULL; |
| 171 | } |
170 | } |
| 172 | memset(node, 0, sizeof(vfs_node_t)); |
171 | memset(node, 0, sizeof(vfs_node_t)); |
| 173 | node->fs_handle = result->triplet.fs_handle; |
172 | node->fs_handle = result->triplet.fs_handle; |
| 174 | node->dev_handle = result->triplet.dev_handle; |
173 | node->dev_handle = result->triplet.dev_handle; |
| 175 | node->index = result->triplet.index; |
174 | node->index = result->triplet.index; |
| 176 | node->size = result->size; |
175 | node->size = result->size; |
| 177 | node->lnkcnt = result->lnkcnt; |
176 | node->lnkcnt = result->lnkcnt; |
| 178 | node->type = result->type; |
177 | node->type = result->type; |
| 179 | link_initialize(&node->nh_link); |
178 | link_initialize(&node->nh_link); |
| 180 | rwlock_initialize(&node->contents_rwlock); |
179 | fibril_rwlock_initialize(&node->contents_rwlock); |
| 181 | hash_table_insert(&nodes, key, &node->nh_link); |
180 | hash_table_insert(&nodes, key, &node->nh_link); |
| 182 | } else { |
181 | } else { |
| 183 | node = hash_table_get_instance(tmp, vfs_node_t, nh_link); |
182 | node = hash_table_get_instance(tmp, vfs_node_t, nh_link); |
| 184 | if (node->type == VFS_NODE_UNKNOWN && |
183 | if (node->type == VFS_NODE_UNKNOWN && |
| 185 | result->type != VFS_NODE_UNKNOWN) { |
184 | result->type != VFS_NODE_UNKNOWN) { |
| 186 | /* Upgrade the node type. */ |
185 | /* Upgrade the node type. */ |
| 187 | node->type = result->type; |
186 | node->type = result->type; |
| 188 | } |
187 | } |
| Line 191... | Line 190... | ||
| 191 | assert(node->size == result->size); |
190 | assert(node->size == result->size); |
| 192 | assert(node->lnkcnt == result->lnkcnt); |
191 | assert(node->lnkcnt == result->lnkcnt); |
| 193 | assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN); |
192 | assert(node->type == result->type || result->type == VFS_NODE_UNKNOWN); |
| 194 | 193 | ||
| 195 | _vfs_node_addref(node); |
194 | _vfs_node_addref(node); |
| 196 | futex_up(&nodes_futex); |
195 | fibril_mutex_unlock(&nodes_mutex); |
| 197 | 196 | ||
| 198 | return node; |
197 | return node; |
| 199 | } |
198 | } |
| 200 | 199 | ||
| 201 | /** Return VFS node when no longer needed by the caller. |
200 | /** Return VFS node when no longer needed by the caller. |
| Line 231... | Line 230... | ||
| 231 | { |
230 | { |
| 232 | } |
231 | } |
| 233 | 232 | ||
| 234 | /** |
233 | /** |
| 235 | * @} |
234 | * @} |
| 236 | */ |
235 | */ |