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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a46e56b was a46e56b, checked in by Jakub Jermar <jakub@…>, 7 years ago

Prefer handle over ID in naming handle variables

  • 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{
75 return *(service_id_t*)key;
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);
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;
[a7e04d16]236restart:
[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) {
[a46e56b]480 cap_call_handle_t chandle;
[1313ee9]481 size_t size;
[a46e56b]482 if (!async_data_read_receive(&chandle, &size)) {
483 async_answer_0(chandle, 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) {
[a46e56b]502 async_data_read_finalize(chandle, 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) {
[a46e56b]517 async_data_read_finalize(chandle, 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
[a46e56b]526 async_answer_0(chandle, 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 */
[a46e56b]534 cap_call_handle_t chandle;
[1313ee9]535 size_t size;
[a46e56b]536 if (!async_data_read_receive(&chandle, &size)) {
537 async_answer_0(chandle, 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) {
[a46e56b]545 async_data_read_finalize(chandle, 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);
[a46e56b]552 async_answer_0(chandle, 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
[a46e56b]570 cap_call_handle_t chandle;
571 if (!async_data_read_receive(&chandle, NULL)) {
[15f3c3f]572 fibril_mutex_unlock(&services_mutex);
[a46e56b]573 async_answer_0(chandle, 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 */
[a46e56b]585 async_forward_fast(chandle, 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
[a46e56b]634 cap_call_handle_t chandle;
635 if (!async_data_write_receive(&chandle, NULL)) {
[15f3c3f]636 fibril_mutex_unlock(&services_mutex);
[a46e56b]637 async_answer_0(chandle, 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 */
[a46e56b]649 async_forward_fast(chandle, 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.