Rev 3674 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3674 | Rev 4691 | ||
---|---|---|---|
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. |
130 | */ |
129 | */ |
131 | int phone = vfs_grab_phone(node->fs_handle); |
130 | int phone = vfs_grab_phone(node->fs_handle); |
132 | ipcarg_t rc; |
131 | ipcarg_t rc; |
133 | rc = async_req_2_0(phone, VFS_DESTROY, |
132 | rc = async_req_2_0(phone, VFS_OUT_DESTROY, |
134 | (ipcarg_t)node->dev_handle, (ipcarg_t)node->index); |
133 | (ipcarg_t)node->dev_handle, (ipcarg_t)node->index); |
135 | assert(rc == EOK); |
134 | assert(rc == EOK); |
136 | vfs_release_phone(phone); |
135 | vfs_release_phone(phone); |
137 | } |
136 | } |
138 | if (free_vfs_node) |
137 | if (free_vfs_node) |
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) { |
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. |