Subversion Repositories HelenOS

Rev

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.