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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6c089a9 was 984a9ba, checked in by Martin Decky <martin@…>, 7 years ago

do not expose the call capability handler from the async framework

Keep the call capability handler encapsulated within the async framework
and do not expose it explicitly via its API. Use the pointer to
ipc_call_t as the sole object identifying an IPC call in the code that
uses the async framework.

This plugs a major leak in the abstraction and also simplifies both the
async framework (slightly) and all IPC servers.

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