source: mainline/uspace/srv/fs/locfs/locfs_ops.c

Last change on this file was 0db0df2, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 4 months ago

Hash table improvements

Implement hash_table_foreach macro, analogous to list_foreach.

Remove superfluous argument to hash_table_find_next().
(If the user needs to recheck the part of the list already
checked by hash_table_find(), they can just rerun that function.)

Add hash argument to hash_table_ops_t::key_equal.
The big change here is that users with big keys can store the hash
value alongside key in their entries, and for the low low cost of
sizeof(size_t) bytes eliminate a bunch of expensive key comparisons.

Also added a hash function for strings and arbitrary data.
Found this one by asking ChatGPT, because the latency of accesses
to my book collection is currently a couple of hours.

+ Some drive-by unused #include removal.

  • Property mode set to 100644
File size: 17.1 KB
RevLine 
[a095d20]1/*
2 * Copyright (c) 2009 Martin Decky
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
[b1834a01]29/** @addtogroup locfs
[a095d20]30 * @{
31 */
32
33/**
[15f3c3f]34 * @file locfs_ops.c
35 * @brief Implementation of VFS operations for the locfs file system server.
[a095d20]36 */
37
[ed903174]38#include <macros.h>
[3e6a98c5]39#include <stdbool.h>
[a095d20]40#include <errno.h>
[38d150e]41#include <stdlib.h>
[19f857a]42#include <str.h>
[a095d20]43#include <libfs.h>
[1e4cada]44#include <fibril_synch.h>
[d9c8c81]45#include <adt/hash_table.h>
[15f3c3f]46#include <ipc/loc.h>
[1313ee9]47#include <assert.h>
[15f3c3f]48#include "locfs.h"
49#include "locfs_ops.h"
[a095d20]50
[1313ee9]51typedef struct {
[15f3c3f]52 loc_object_type_t type;
53 service_id_t service_id;
54} locfs_node_t;
[a095d20]55
[15f3c3f]56/** Opened services structure */
[17fd1d4]57typedef struct {
[15f3c3f]58 service_id_t service_id;
[79ae36dd]59 async_sess_t *sess; /**< If NULL, the structure is incomplete. */
[17fd1d4]60 size_t refcount;
[062d900]61 ht_link_t link;
[79ae36dd]62 fibril_condvar_t cv; /**< Broadcast when completed. */
[15f3c3f]63} service_t;
[17fd1d4]64
[15f3c3f]65/** Hash table of opened services */
66static hash_table_t services;
[17fd1d4]67
[2dfd9fa]68/** Hash table mutex */
[15f3c3f]69static FIBRIL_MUTEX_INITIALIZE(services_mutex);
[2dfd9fa]70
[17fd1d4]71/* Implementation of hash table interface for the nodes hash table. */
[062d900]72
[5e801dc]73static size_t services_key_hash(const void *key)
[062d900]74{
[5e801dc]75 const service_id_t *k = key;
76 return *k;
[062d900]77}
78
79static size_t services_hash(const ht_link_t *item)
[17fd1d4]80{
[062d900]81 service_t *dev = hash_table_get_inst(item, service_t, link);
82 return dev->service_id;
[17fd1d4]83}
84
[0db0df2]85static bool services_key_equal(const void *key, size_t hash,
86 const ht_link_t *item)
[17fd1d4]87{
[5e801dc]88 const service_id_t *k = key;
[062d900]89 service_t *dev = hash_table_get_inst(item, service_t, link);
[5e801dc]90 return (dev->service_id == *k);
[17fd1d4]91}
92
[062d900]93static void services_remove_callback(ht_link_t *item)
[17fd1d4]94{
[062d900]95 free(hash_table_get_inst(item, service_t, link));
[17fd1d4]96}
97
[61eb2ce2]98static const hash_table_ops_t services_ops = {
[15f3c3f]99 .hash = services_hash,
[062d900]100 .key_hash = services_key_hash,
101 .key_equal = services_key_equal,
[1b20da0]102 .equal = NULL,
[15f3c3f]103 .remove_callback = services_remove_callback
[17fd1d4]104};
105
[b7fd2a0]106static errno_t locfs_node_get_internal(fs_node_t **rfn, loc_object_type_t type,
[15f3c3f]107 service_id_t service_id)
[a095d20]108{
[15f3c3f]109 locfs_node_t *node = (locfs_node_t *) malloc(sizeof(locfs_node_t));
[1313ee9]110 if (node == NULL) {
111 *rfn = NULL;
112 return ENOMEM;
113 }
[a35b458]114
[1313ee9]115 *rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
116 if (*rfn == NULL) {
117 free(node);
118 *rfn = NULL;
119 return ENOMEM;
120 }
[a35b458]121
[1313ee9]122 fs_node_initialize(*rfn);
123 node->type = type;
[15f3c3f]124 node->service_id = service_id;
[a35b458]125
[1313ee9]126 (*rfn)->data = node;
127 return EOK;
[a095d20]128}
129
[b7fd2a0]130static errno_t locfs_root_get(fs_node_t **rfn, service_id_t service_id)
[a095d20]131{
[15f3c3f]132 return locfs_node_get_internal(rfn, LOC_OBJECT_NONE, 0);
[1313ee9]133}
134
[b7fd2a0]135static errno_t locfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
[1313ee9]136{
[15f3c3f]137 locfs_node_t *node = (locfs_node_t *) pfn->data;
[b7fd2a0]138 errno_t ret;
[a35b458]139
[15f3c3f]140 if (node->service_id == 0) {
[1313ee9]141 /* Root directory */
[a35b458]142
[15f3c3f]143 loc_sdesc_t *nspaces;
144 size_t count = loc_get_namespaces(&nspaces);
[a35b458]145
[1313ee9]146 if (count > 0) {
147 size_t pos;
148 for (pos = 0; pos < count; pos++) {
149 /* Ignore root namespace */
[15f3c3f]150 if (str_cmp(nspaces[pos].name, "") == 0)
[1313ee9]151 continue;
[a35b458]152
[15f3c3f]153 if (str_cmp(nspaces[pos].name, component) == 0) {
154 ret = locfs_node_get_internal(rfn, LOC_OBJECT_NAMESPACE, nspaces[pos].id);
155 free(nspaces);
[b366a1bc]156 return ret;
[1313ee9]157 }
158 }
[a35b458]159
[15f3c3f]160 free(nspaces);
[1313ee9]161 }
[a35b458]162
[1313ee9]163 /* Search root namespace */
[15f3c3f]164 service_id_t namespace;
165 loc_sdesc_t *svcs;
166 if (loc_namespace_get_id("", &namespace, 0) == EOK) {
167 count = loc_get_services(namespace, &svcs);
[a35b458]168
[1313ee9]169 if (count > 0) {
170 size_t pos;
171 for (pos = 0; pos < count; pos++) {
[15f3c3f]172 if (str_cmp(svcs[pos].name, component) == 0) {
173 ret = locfs_node_get_internal(rfn, LOC_OBJECT_SERVICE, svcs[pos].id);
174 free(svcs);
[b366a1bc]175 return ret;
[1313ee9]176 }
177 }
[a35b458]178
[15f3c3f]179 free(svcs);
[1313ee9]180 }
181 }
[a35b458]182
[1313ee9]183 *rfn = NULL;
184 return EOK;
[a095d20]185 }
[a35b458]186
[15f3c3f]187 if (node->type == LOC_OBJECT_NAMESPACE) {
[1313ee9]188 /* Namespace directory */
[a35b458]189
[15f3c3f]190 loc_sdesc_t *svcs;
191 size_t count = loc_get_services(node->service_id, &svcs);
[1313ee9]192 if (count > 0) {
193 size_t pos;
194 for (pos = 0; pos < count; pos++) {
[15f3c3f]195 if (str_cmp(svcs[pos].name, component) == 0) {
196 ret = locfs_node_get_internal(rfn, LOC_OBJECT_SERVICE, svcs[pos].id);
197 free(svcs);
[b366a1bc]198 return ret;
[1313ee9]199 }
200 }
[a35b458]201
[15f3c3f]202 free(svcs);
[1313ee9]203 }
[a35b458]204
[1313ee9]205 *rfn = NULL;
206 return EOK;
[a095d20]207 }
[a35b458]208
[1313ee9]209 *rfn = NULL;
210 return EOK;
[a095d20]211}
212
[b7fd2a0]213static errno_t locfs_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index)
[a095d20]214{
[15f3c3f]215 return locfs_node_get_internal(rfn, loc_id_probe(index), index);
[a095d20]216}
217
[b7fd2a0]218static errno_t locfs_node_open(fs_node_t *fn)
[a095d20]219{
[15f3c3f]220 locfs_node_t *node = (locfs_node_t *) fn->data;
[a35b458]221
[15f3c3f]222 if (node->service_id == 0) {
[1313ee9]223 /* Root directory */
224 return EOK;
[a095d20]225 }
[a35b458]226
[15f3c3f]227 loc_object_type_t type = loc_id_probe(node->service_id);
[a35b458]228
[15f3c3f]229 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]230 /* Namespace directory */
231 return EOK;
[a095d20]232 }
[a35b458]233
[15f3c3f]234 if (type == LOC_OBJECT_SERVICE) {
[1313ee9]235 /* Device node */
[a35b458]236
[15f3c3f]237 fibril_mutex_lock(&services_mutex);
[062d900]238 ht_link_t *lnk;
[18b6a88]239 restart:
[062d900]240 lnk = hash_table_find(&services, &node->service_id);
[1313ee9]241 if (lnk == NULL) {
[15f3c3f]242 service_t *dev = (service_t *) malloc(sizeof(service_t));
[1313ee9]243 if (dev == NULL) {
[15f3c3f]244 fibril_mutex_unlock(&services_mutex);
[1313ee9]245 return ENOMEM;
[a095d20]246 }
[a35b458]247
[15f3c3f]248 dev->service_id = node->service_id;
[a35b458]249
[79ae36dd]250 /* Mark as incomplete */
251 dev->sess = NULL;
[a7e04d16]252 dev->refcount = 1;
253 fibril_condvar_initialize(&dev->cv);
[a35b458]254
[a7e04d16]255 /*
256 * Insert the incomplete device structure so that other
257 * fibrils will not race with us when we drop the mutex
258 * below.
259 */
[062d900]260 hash_table_insert(&services, &dev->link);
[a35b458]261
[a7e04d16]262 /*
[15f3c3f]263 * Drop the mutex to allow recursive locfs requests.
[a7e04d16]264 */
[15f3c3f]265 fibril_mutex_unlock(&services_mutex);
[a35b458]266
[f9b2cb4c]267 async_sess_t *sess = loc_service_connect(node->service_id,
268 INTERFACE_FS, 0);
[a35b458]269
[15f3c3f]270 fibril_mutex_lock(&services_mutex);
[a35b458]271
[a7e04d16]272 /*
273 * Notify possible waiters about this device structure
274 * being completed (or destroyed).
275 */
276 fibril_condvar_broadcast(&dev->cv);
[a35b458]277
[79ae36dd]278 if (!sess) {
[a7e04d16]279 /*
280 * Connecting failed, need to remove the
281 * entry and free the device structure.
282 */
[062d900]283 hash_table_remove(&services, &node->service_id);
[15f3c3f]284 fibril_mutex_unlock(&services_mutex);
[a35b458]285
[1313ee9]286 return ENOENT;
[17fd1d4]287 }
[a35b458]288
[79ae36dd]289 /* Set the correct session. */
290 dev->sess = sess;
[1313ee9]291 } else {
[062d900]292 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[a35b458]293
[79ae36dd]294 if (!dev->sess) {
[a7e04d16]295 /*
296 * Wait until the device structure is completed
297 * and start from the beginning as the device
298 * structure might have entirely disappeared
299 * while we were not holding the mutex in
300 * fibril_condvar_wait().
301 */
[15f3c3f]302 fibril_condvar_wait(&dev->cv, &services_mutex);
[a7e04d16]303 goto restart;
304 }
305
[1313ee9]306 dev->refcount++;
307 }
[a35b458]308
[15f3c3f]309 fibril_mutex_unlock(&services_mutex);
[a35b458]310
[1313ee9]311 return EOK;
[a095d20]312 }
[a35b458]313
[1313ee9]314 return ENOENT;
[a095d20]315}
316
[b7fd2a0]317static errno_t locfs_node_put(fs_node_t *fn)
[a095d20]318{
[1313ee9]319 free(fn->data);
320 free(fn);
321 return EOK;
322}
323
[b7fd2a0]324static errno_t locfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag)
[1313ee9]325{
326 assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
[a35b458]327
[1313ee9]328 *rfn = NULL;
329 return ENOTSUP;
330}
331
[b7fd2a0]332static errno_t locfs_destroy_node(fs_node_t *fn)
[1313ee9]333{
334 return ENOTSUP;
335}
336
[b7fd2a0]337static errno_t locfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
[1313ee9]338{
339 return ENOTSUP;
340}
341
[b7fd2a0]342static errno_t locfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
[1313ee9]343{
344 return ENOTSUP;
345}
346
[b7fd2a0]347static errno_t locfs_has_children(bool *has_children, fs_node_t *fn)
[1313ee9]348{
[15f3c3f]349 locfs_node_t *node = (locfs_node_t *) fn->data;
[a35b458]350
[15f3c3f]351 if (node->service_id == 0) {
352 size_t count = loc_count_namespaces();
[1313ee9]353 if (count > 0) {
354 *has_children = true;
355 return EOK;
[17fd1d4]356 }
[a35b458]357
[1313ee9]358 /* Root namespace */
[15f3c3f]359 service_id_t namespace;
360 if (loc_namespace_get_id("", &namespace, 0) == EOK) {
361 count = loc_count_services(namespace);
[1313ee9]362 if (count > 0) {
363 *has_children = true;
364 return EOK;
365 }
[17fd1d4]366 }
[a35b458]367
[1313ee9]368 *has_children = false;
369 return EOK;
370 }
[a35b458]371
[15f3c3f]372 if (node->type == LOC_OBJECT_NAMESPACE) {
373 size_t count = loc_count_services(node->service_id);
[1313ee9]374 if (count > 0) {
375 *has_children = true;
376 return EOK;
377 }
[a35b458]378
[1313ee9]379 *has_children = false;
380 return EOK;
[a095d20]381 }
[a35b458]382
[1313ee9]383 *has_children = false;
384 return EOK;
[17fd1d4]385}
386
[15f3c3f]387static fs_index_t locfs_index_get(fs_node_t *fn)
[17fd1d4]388{
[15f3c3f]389 locfs_node_t *node = (locfs_node_t *) fn->data;
390 return node->service_id;
[1313ee9]391}
392
[15f3c3f]393static aoff64_t locfs_size_get(fs_node_t *fn)
[1313ee9]394{
395 return 0;
396}
397
[15f3c3f]398static unsigned int locfs_lnkcnt_get(fs_node_t *fn)
[1313ee9]399{
[15f3c3f]400 locfs_node_t *node = (locfs_node_t *) fn->data;
[a35b458]401
[15f3c3f]402 if (node->service_id == 0)
[1313ee9]403 return 0;
[a35b458]404
[1313ee9]405 return 1;
406}
[852b801]407
[15f3c3f]408static bool locfs_is_directory(fs_node_t *fn)
[1313ee9]409{
[15f3c3f]410 locfs_node_t *node = (locfs_node_t *) fn->data;
[a35b458]411
[15f3c3f]412 return ((node->type == LOC_OBJECT_NONE) || (node->type == LOC_OBJECT_NAMESPACE));
[1313ee9]413}
414
[15f3c3f]415static bool locfs_is_file(fs_node_t *fn)
[1313ee9]416{
[15f3c3f]417 locfs_node_t *node = (locfs_node_t *) fn->data;
[a35b458]418
[15f3c3f]419 return (node->type == LOC_OBJECT_SERVICE);
[1313ee9]420}
421
[b33870b]422static service_id_t locfs_service_get(fs_node_t *fn)
[1313ee9]423{
[15f3c3f]424 locfs_node_t *node = (locfs_node_t *) fn->data;
[a35b458]425
[15f3c3f]426 if (node->type == LOC_OBJECT_SERVICE)
427 return node->service_id;
[a35b458]428
[1313ee9]429 return 0;
430}
431
432/** libfs operations */
[15f3c3f]433libfs_ops_t locfs_libfs_ops = {
434 .root_get = locfs_root_get,
435 .match = locfs_match,
436 .node_get = locfs_node_get,
437 .node_open = locfs_node_open,
438 .node_put = locfs_node_put,
439 .create = locfs_create_node,
440 .destroy = locfs_destroy_node,
441 .link = locfs_link_node,
442 .unlink = locfs_unlink_node,
443 .has_children = locfs_has_children,
444 .index_get = locfs_index_get,
445 .size_get = locfs_size_get,
446 .lnkcnt_get = locfs_lnkcnt_get,
447 .is_directory = locfs_is_directory,
448 .is_file = locfs_is_file,
[b33870b]449 .service_get = locfs_service_get
[1313ee9]450};
451
[15f3c3f]452bool locfs_init(void)
[1313ee9]453{
[062d900]454 if (!hash_table_create(&services, 0, 0, &services_ops))
[1313ee9]455 return false;
[a35b458]456
[1313ee9]457 return true;
458}
459
[b7fd2a0]460static errno_t locfs_fsprobe(service_id_t service_id, vfs_fs_probe_info_t *info)
[d2c8533]461{
462 return ENOTSUP;
463}
464
[b7fd2a0]465static errno_t locfs_mounted(service_id_t service_id, const char *opts,
[4f30222]466 fs_index_t *index, aoff64_t *size)
[3c11713]467{
[efcebe1]468 *index = 0;
469 *size = 0;
470 return EOK;
[1313ee9]471}
472
[b7fd2a0]473static errno_t locfs_unmounted(service_id_t service_id)
[1313ee9]474{
[efcebe1]475 return ENOTSUP;
[17fd1d4]476}
477
[b7fd2a0]478static errno_t
[86ffa27f]479locfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
[efcebe1]480 size_t *rbytes)
[17fd1d4]481{
[1313ee9]482 if (index == 0) {
[984a9ba]483 ipc_call_t call;
[1313ee9]484 size_t size;
[984a9ba]485 if (!async_data_read_receive(&call, &size)) {
486 async_answer_0(&call, EINVAL);
[efcebe1]487 return EINVAL;
[1313ee9]488 }
[a35b458]489
[15f3c3f]490 loc_sdesc_t *desc;
491 size_t count = loc_get_namespaces(&desc);
[a35b458]492
[1313ee9]493 /* Get rid of root namespace */
494 size_t i;
495 for (i = 0; i < count; i++) {
496 if (str_cmp(desc[i].name, "") == 0) {
497 if (pos >= i)
498 pos++;
[a35b458]499
[1313ee9]500 break;
501 }
502 }
[a35b458]503
[1313ee9]504 if (pos < count) {
[984a9ba]505 async_data_read_finalize(&call, desc[pos].name, str_size(desc[pos].name) + 1);
[1313ee9]506 free(desc);
[efcebe1]507 *rbytes = 1;
508 return EOK;
[1313ee9]509 }
[a35b458]510
[1313ee9]511 free(desc);
512 pos -= count;
[a35b458]513
[1313ee9]514 /* Search root namespace */
[15f3c3f]515 service_id_t namespace;
516 if (loc_namespace_get_id("", &namespace, 0) == EOK) {
517 count = loc_get_services(namespace, &desc);
[a35b458]518
[1313ee9]519 if (pos < count) {
[984a9ba]520 async_data_read_finalize(&call, desc[pos].name, str_size(desc[pos].name) + 1);
[1313ee9]521 free(desc);
[efcebe1]522 *rbytes = 1;
523 return EOK;
[1313ee9]524 }
[a35b458]525
[1313ee9]526 free(desc);
527 }
[a35b458]528
[984a9ba]529 async_answer_0(&call, ENOENT);
[efcebe1]530 return ENOENT;
[1313ee9]531 }
[a35b458]532
[15f3c3f]533 loc_object_type_t type = loc_id_probe(index);
[a35b458]534
[15f3c3f]535 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]536 /* Namespace directory */
[984a9ba]537 ipc_call_t call;
[1313ee9]538 size_t size;
[984a9ba]539 if (!async_data_read_receive(&call, &size)) {
540 async_answer_0(&call, EINVAL);
[efcebe1]541 return EINVAL;
[1313ee9]542 }
[a35b458]543
[15f3c3f]544 loc_sdesc_t *desc;
545 size_t count = loc_get_services(index, &desc);
[a35b458]546
[1313ee9]547 if (pos < count) {
[984a9ba]548 async_data_read_finalize(&call, desc[pos].name, str_size(desc[pos].name) + 1);
[1313ee9]549 free(desc);
[efcebe1]550 *rbytes = 1;
551 return EOK;
[1313ee9]552 }
[a35b458]553
[1313ee9]554 free(desc);
[984a9ba]555 async_answer_0(&call, ENOENT);
[efcebe1]556 return ENOENT;
[1313ee9]557 }
[a35b458]558
[15f3c3f]559 if (type == LOC_OBJECT_SERVICE) {
[1313ee9]560 /* Device node */
[a35b458]561
[15f3c3f]562 fibril_mutex_lock(&services_mutex);
[062d900]563 service_id_t service_index = index;
564 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]565 if (lnk == NULL) {
[15f3c3f]566 fibril_mutex_unlock(&services_mutex);
[efcebe1]567 return ENOENT;
[17fd1d4]568 }
[a35b458]569
[062d900]570 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]571 assert(dev->sess);
[a35b458]572
[984a9ba]573 ipc_call_t call;
574 if (!async_data_read_receive(&call, NULL)) {
[15f3c3f]575 fibril_mutex_unlock(&services_mutex);
[984a9ba]576 async_answer_0(&call, EINVAL);
[efcebe1]577 return EINVAL;
[17fd1d4]578 }
[a35b458]579
[17fd1d4]580 /* Make a request at the driver */
[79ae36dd]581 async_exch_t *exch = async_exchange_begin(dev->sess);
[a35b458]582
[17fd1d4]583 ipc_call_t answer;
[86ffa27f]584 aid_t msg = async_send_4(exch, VFS_OUT_READ, service_id,
[efcebe1]585 index, LOWER32(pos), UPPER32(pos), &answer);
[a35b458]586
[17fd1d4]587 /* Forward the IPC_M_DATA_READ request to the driver */
[4f13e19]588 async_forward_0(&call, exch, 0, IPC_FF_ROUTE_FROM_ME);
[a35b458]589
[79ae36dd]590 async_exchange_end(exch);
[a35b458]591
[15f3c3f]592 fibril_mutex_unlock(&services_mutex);
[a35b458]593
[17fd1d4]594 /* Wait for reply from the driver. */
[b7fd2a0]595 errno_t rc;
[17fd1d4]596 async_wait_for(msg, &rc);
[086290d]597
598 /* Do not propagate EHANGUP back to VFS. */
[b7fd2a0]599 if ((errno_t) rc == EHANGUP)
[086290d]600 rc = ENOTSUP;
[a35b458]601
[fafb8e5]602 *rbytes = ipc_get_arg1(&answer);
[efcebe1]603 return rc;
[a095d20]604 }
[a35b458]605
[efcebe1]606 return ENOENT;
[a095d20]607}
608
[b7fd2a0]609static errno_t
[86ffa27f]610locfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
[efcebe1]611 size_t *wbytes, aoff64_t *nsize)
[a095d20]612{
[efcebe1]613 if (index == 0)
614 return ENOTSUP;
[a35b458]615
[15f3c3f]616 loc_object_type_t type = loc_id_probe(index);
[a35b458]617
[15f3c3f]618 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]619 /* Namespace directory */
[efcebe1]620 return ENOTSUP;
[1313ee9]621 }
[a35b458]622
[15f3c3f]623 if (type == LOC_OBJECT_SERVICE) {
[1313ee9]624 /* Device node */
[a35b458]625
[15f3c3f]626 fibril_mutex_lock(&services_mutex);
[062d900]627 service_id_t service_index = index;
628 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]629 if (lnk == NULL) {
[15f3c3f]630 fibril_mutex_unlock(&services_mutex);
[efcebe1]631 return ENOENT;
[17fd1d4]632 }
[a35b458]633
[062d900]634 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]635 assert(dev->sess);
[a35b458]636
[984a9ba]637 ipc_call_t call;
638 if (!async_data_write_receive(&call, NULL)) {
[15f3c3f]639 fibril_mutex_unlock(&services_mutex);
[984a9ba]640 async_answer_0(&call, EINVAL);
[efcebe1]641 return EINVAL;
[17fd1d4]642 }
[a35b458]643
[17fd1d4]644 /* Make a request at the driver */
[79ae36dd]645 async_exch_t *exch = async_exchange_begin(dev->sess);
[a35b458]646
[17fd1d4]647 ipc_call_t answer;
[86ffa27f]648 aid_t msg = async_send_4(exch, VFS_OUT_WRITE, service_id,
[efcebe1]649 index, LOWER32(pos), UPPER32(pos), &answer);
[a35b458]650
[17fd1d4]651 /* Forward the IPC_M_DATA_WRITE request to the driver */
[4f13e19]652 async_forward_0(&call, exch, 0, IPC_FF_ROUTE_FROM_ME);
[a35b458]653
[79ae36dd]654 async_exchange_end(exch);
[a35b458]655
[15f3c3f]656 fibril_mutex_unlock(&services_mutex);
[a35b458]657
[17fd1d4]658 /* Wait for reply from the driver. */
[b7fd2a0]659 errno_t rc;
[17fd1d4]660 async_wait_for(msg, &rc);
[086290d]661
662 /* Do not propagate EHANGUP back to VFS. */
[b7fd2a0]663 if ((errno_t) rc == EHANGUP)
[086290d]664 rc = ENOTSUP;
[a35b458]665
[fafb8e5]666 *wbytes = ipc_get_arg1(&answer);
[efcebe1]667 *nsize = 0;
668 return rc;
[a095d20]669 }
[a35b458]670
[efcebe1]671 return ENOENT;
[a095d20]672}
673
[b7fd2a0]674static errno_t
[86ffa27f]675locfs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
[a095d20]676{
[efcebe1]677 return ENOTSUP;
[a095d20]678}
679
[b7fd2a0]680static errno_t locfs_close(service_id_t service_id, fs_index_t index)
[17fd1d4]681{
[efcebe1]682 if (index == 0)
683 return EOK;
[a35b458]684
[15f3c3f]685 loc_object_type_t type = loc_id_probe(index);
[a35b458]686
[15f3c3f]687 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]688 /* Namespace directory */
[efcebe1]689 return EOK;
[1313ee9]690 }
[a35b458]691
[15f3c3f]692 if (type == LOC_OBJECT_SERVICE) {
[a35b458]693
[15f3c3f]694 fibril_mutex_lock(&services_mutex);
[062d900]695 service_id_t service_index = index;
696 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]697 if (lnk == NULL) {
[15f3c3f]698 fibril_mutex_unlock(&services_mutex);
[efcebe1]699 return ENOENT;
[17fd1d4]700 }
[a35b458]701
[062d900]702 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]703 assert(dev->sess);
[17fd1d4]704 dev->refcount--;
[a35b458]705
[17fd1d4]706 if (dev->refcount == 0) {
[79ae36dd]707 async_hangup(dev->sess);
[062d900]708 service_id_t service_index = index;
709 hash_table_remove(&services, &service_index);
[17fd1d4]710 }
[a35b458]711
[15f3c3f]712 fibril_mutex_unlock(&services_mutex);
[a35b458]713
[efcebe1]714 return EOK;
[1313ee9]715 }
[a35b458]716
[efcebe1]717 return ENOENT;
[17fd1d4]718}
719
[b7fd2a0]720static errno_t locfs_sync(service_id_t service_id, fs_index_t index)
[17fd1d4]721{
[efcebe1]722 if (index == 0)
723 return EOK;
[a35b458]724
[15f3c3f]725 loc_object_type_t type = loc_id_probe(index);
[a35b458]726
[15f3c3f]727 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]728 /* Namespace directory */
[efcebe1]729 return EOK;
[1313ee9]730 }
[a35b458]731
[15f3c3f]732 if (type == LOC_OBJECT_SERVICE) {
[062d900]733
[15f3c3f]734 fibril_mutex_lock(&services_mutex);
[062d900]735 service_id_t service_index = index;
736 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]737 if (lnk == NULL) {
[15f3c3f]738 fibril_mutex_unlock(&services_mutex);
[efcebe1]739 return ENOENT;
[17fd1d4]740 }
[a35b458]741
[062d900]742 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]743 assert(dev->sess);
[a35b458]744
[17fd1d4]745 /* Make a request at the driver */
[79ae36dd]746 async_exch_t *exch = async_exchange_begin(dev->sess);
[a35b458]747
[17fd1d4]748 ipc_call_t answer;
[86ffa27f]749 aid_t msg = async_send_2(exch, VFS_OUT_SYNC, service_id,
[efcebe1]750 index, &answer);
[a35b458]751
[79ae36dd]752 async_exchange_end(exch);
[a35b458]753
[15f3c3f]754 fibril_mutex_unlock(&services_mutex);
[a35b458]755
[17fd1d4]756 /* Wait for reply from the driver */
[b7fd2a0]757 errno_t rc;
[17fd1d4]758 async_wait_for(msg, &rc);
[a35b458]759
[efcebe1]760 return rc;
[1313ee9]761 }
[a35b458]762
[efcebe1]763 return ENOENT;
[17fd1d4]764}
765
[b7fd2a0]766static errno_t locfs_destroy(service_id_t service_id, fs_index_t index)
[a095d20]767{
[efcebe1]768 return ENOTSUP;
[a095d20]769}
770
[86ffa27f]771vfs_out_ops_t locfs_ops = {
[d2c8533]772 .fsprobe = locfs_fsprobe,
[86ffa27f]773 .mounted = locfs_mounted,
774 .unmounted = locfs_unmounted,
775 .read = locfs_read,
776 .write = locfs_write,
777 .truncate = locfs_truncate,
778 .close = locfs_close,
779 .destroy = locfs_destroy,
780 .sync = locfs_sync,
[efcebe1]781};
782
[a095d20]783/**
784 * @}
[17fd1d4]785 */
Note: See TracBrowser for help on using the repository browser.