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

Last change on this file since 7fa8589 was 7fa8589, checked in by Matthieu Riolo <matthieu.riolo@…>, 5 years ago

Removing unneeded casts from errno_t to errno_t

  • 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. */
[7fa8589]598 if (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. */
[7fa8589]662 if (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.