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

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f783081 was 5e801dc, checked in by GitHub <noreply@…>, 6 years ago

Indicate and enforce constness of hash table key in certain functions (#158)

The assumption here is that modifying key in the hash/equal functions in something completely unexpected, and not something you would ever want to do intentionally, so it makes sense to disallow it entirely to get that extra level of checking.

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