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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 32c2c8f was 3e6a98c5, checked in by Jiri Svoboda <jiri@…>, 13 years ago

Standards-compliant boolean type.

  • Property mode set to 100644
File size: 17.2 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>
41#include <malloc.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>
[852b801]47#include <sys/stat.h>
[1313ee9]48#include <libfs.h>
49#include <assert.h>
[15f3c3f]50#include "locfs.h"
51#include "locfs_ops.h"
[a095d20]52
[1313ee9]53typedef struct {
[15f3c3f]54 loc_object_type_t type;
55 service_id_t service_id;
56} locfs_node_t;
[a095d20]57
[15f3c3f]58/** Opened services structure */
[17fd1d4]59typedef struct {
[15f3c3f]60 service_id_t service_id;
[79ae36dd]61 async_sess_t *sess; /**< If NULL, the structure is incomplete. */
[17fd1d4]62 size_t refcount;
[062d900]63 ht_link_t link;
[79ae36dd]64 fibril_condvar_t cv; /**< Broadcast when completed. */
[15f3c3f]65} service_t;
[17fd1d4]66
[15f3c3f]67/** Hash table of opened services */
68static hash_table_t services;
[17fd1d4]69
[2dfd9fa]70/** Hash table mutex */
[15f3c3f]71static FIBRIL_MUTEX_INITIALIZE(services_mutex);
[2dfd9fa]72
[17fd1d4]73/* Implementation of hash table interface for the nodes hash table. */
[062d900]74
75static size_t services_key_hash(void *key)
76{
77 return *(service_id_t*)key;
78}
79
80static size_t services_hash(const ht_link_t *item)
[17fd1d4]81{
[062d900]82 service_t *dev = hash_table_get_inst(item, service_t, link);
83 return dev->service_id;
[17fd1d4]84}
85
[062d900]86static bool services_key_equal(void *key, const ht_link_t *item)
[17fd1d4]87{
[062d900]88 service_t *dev = hash_table_get_inst(item, service_t, link);
89 return (dev->service_id == *(service_id_t*)key);
[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,
[4e00f87]101 .equal = NULL,
[15f3c3f]102 .remove_callback = services_remove_callback
[17fd1d4]103};
104
[15f3c3f]105static int locfs_node_get_internal(fs_node_t **rfn, loc_object_type_t type,
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 }
[17fd1d4]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 }
[a095d20]120
[1313ee9]121 fs_node_initialize(*rfn);
122 node->type = type;
[15f3c3f]123 node->service_id = service_id;
[1313ee9]124
125 (*rfn)->data = node;
126 return EOK;
[a095d20]127}
128
[15f3c3f]129static int 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
[15f3c3f]134static int 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;
[b366a1bc]137 int ret;
[a095d20]138
[15f3c3f]139 if (node->service_id == 0) {
[1313ee9]140 /* Root directory */
141
[15f3c3f]142 loc_sdesc_t *nspaces;
143 size_t count = loc_get_namespaces(&nspaces);
[1313ee9]144
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;
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 }
158
[15f3c3f]159 free(nspaces);
[1313ee9]160 }
161
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);
[1313ee9]167
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 }
177
[15f3c3f]178 free(svcs);
[1313ee9]179 }
180 }
181
182 *rfn = NULL;
183 return EOK;
[a095d20]184 }
185
[15f3c3f]186 if (node->type == LOC_OBJECT_NAMESPACE) {
[1313ee9]187 /* Namespace directory */
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 }
200
[15f3c3f]201 free(svcs);
[1313ee9]202 }
203
204 *rfn = NULL;
205 return EOK;
[a095d20]206 }
207
[1313ee9]208 *rfn = NULL;
209 return EOK;
[a095d20]210}
211
[15f3c3f]212static int 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
[15f3c3f]217static int locfs_node_open(fs_node_t *fn)
[a095d20]218{
[15f3c3f]219 locfs_node_t *node = (locfs_node_t *) fn->data;
[a095d20]220
[15f3c3f]221 if (node->service_id == 0) {
[1313ee9]222 /* Root directory */
223 return EOK;
[a095d20]224 }
225
[15f3c3f]226 loc_object_type_t type = loc_id_probe(node->service_id);
[a095d20]227
[15f3c3f]228 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]229 /* Namespace directory */
230 return EOK;
[a095d20]231 }
232
[15f3c3f]233 if (type == LOC_OBJECT_SERVICE) {
[1313ee9]234 /* Device node */
235
[15f3c3f]236 fibril_mutex_lock(&services_mutex);
[062d900]237 ht_link_t *lnk;
[a7e04d16]238restart:
[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 }
246
[15f3c3f]247 dev->service_id = node->service_id;
[79ae36dd]248
249 /* Mark as incomplete */
250 dev->sess = NULL;
[a7e04d16]251 dev->refcount = 1;
252 fibril_condvar_initialize(&dev->cv);
[79ae36dd]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);
[79ae36dd]260
[a7e04d16]261 /*
[15f3c3f]262 * Drop the mutex to allow recursive locfs requests.
[a7e04d16]263 */
[15f3c3f]264 fibril_mutex_unlock(&services_mutex);
[79ae36dd]265
[15f3c3f]266 async_sess_t *sess = loc_service_connect(
267 EXCHANGE_SERIALIZE, node->service_id, 0);
[79ae36dd]268
[15f3c3f]269 fibril_mutex_lock(&services_mutex);
[79ae36dd]270
[a7e04d16]271 /*
272 * Notify possible waiters about this device structure
273 * being completed (or destroyed).
274 */
275 fibril_condvar_broadcast(&dev->cv);
[79ae36dd]276
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);
[79ae36dd]284
[1313ee9]285 return ENOENT;
[17fd1d4]286 }
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);
[79ae36dd]292
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 }
307
[15f3c3f]308 fibril_mutex_unlock(&services_mutex);
[1313ee9]309
310 return EOK;
[a095d20]311 }
[1313ee9]312
313 return ENOENT;
[a095d20]314}
315
[15f3c3f]316static int locfs_node_put(fs_node_t *fn)
[a095d20]317{
[1313ee9]318 free(fn->data);
319 free(fn);
320 return EOK;
321}
322
[15f3c3f]323static int locfs_create_node(fs_node_t **rfn, service_id_t service_id, int lflag)
[1313ee9]324{
325 assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
[a095d20]326
[1313ee9]327 *rfn = NULL;
328 return ENOTSUP;
329}
330
[15f3c3f]331static int locfs_destroy_node(fs_node_t *fn)
[1313ee9]332{
333 return ENOTSUP;
334}
335
[15f3c3f]336static int locfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
[1313ee9]337{
338 return ENOTSUP;
339}
340
[15f3c3f]341static int locfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
[1313ee9]342{
343 return ENOTSUP;
344}
345
[15f3c3f]346static int locfs_has_children(bool *has_children, fs_node_t *fn)
[1313ee9]347{
[15f3c3f]348 locfs_node_t *node = (locfs_node_t *) fn->data;
[a095d20]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 }
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 }
366
[1313ee9]367 *has_children = false;
368 return EOK;
369 }
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 }
[17fd1d4]377
[1313ee9]378 *has_children = false;
379 return EOK;
[a095d20]380 }
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;
[17fd1d4]400
[15f3c3f]401 if (node->service_id == 0)
[1313ee9]402 return 0;
403
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;
[852b801]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;
[1313ee9]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;
[1313ee9]424
[15f3c3f]425 if (node->type == LOC_OBJECT_SERVICE)
426 return node->service_id;
[1313ee9]427
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;
455
456 return true;
457}
458
[86ffa27f]459static int locfs_mounted(service_id_t service_id, const char *opts,
[efcebe1]460 fs_index_t *index, aoff64_t *size, unsigned *lnkcnt)
[3c11713]461{
[efcebe1]462 *index = 0;
463 *size = 0;
464 *lnkcnt = 0;
465 return EOK;
[1313ee9]466}
467
[86ffa27f]468static int locfs_unmounted(service_id_t service_id)
[1313ee9]469{
[efcebe1]470 return ENOTSUP;
[17fd1d4]471}
472
[efcebe1]473static int
[86ffa27f]474locfs_read(service_id_t service_id, fs_index_t index, aoff64_t pos,
[efcebe1]475 size_t *rbytes)
[17fd1d4]476{
[1313ee9]477 if (index == 0) {
478 ipc_callid_t callid;
479 size_t size;
480 if (!async_data_read_receive(&callid, &size)) {
[ffa2c8ef]481 async_answer_0(callid, EINVAL);
[efcebe1]482 return EINVAL;
[1313ee9]483 }
484
[15f3c3f]485 loc_sdesc_t *desc;
486 size_t count = loc_get_namespaces(&desc);
[1313ee9]487
488 /* Get rid of root namespace */
489 size_t i;
490 for (i = 0; i < count; i++) {
491 if (str_cmp(desc[i].name, "") == 0) {
492 if (pos >= i)
493 pos++;
494
495 break;
496 }
497 }
498
499 if (pos < count) {
500 async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
501 free(desc);
[efcebe1]502 *rbytes = 1;
503 return EOK;
[1313ee9]504 }
505
506 free(desc);
507 pos -= count;
508
509 /* Search root namespace */
[15f3c3f]510 service_id_t namespace;
511 if (loc_namespace_get_id("", &namespace, 0) == EOK) {
512 count = loc_get_services(namespace, &desc);
[1313ee9]513
514 if (pos < count) {
515 async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
516 free(desc);
[efcebe1]517 *rbytes = 1;
518 return EOK;
[1313ee9]519 }
520
521 free(desc);
522 }
523
[ffa2c8ef]524 async_answer_0(callid, ENOENT);
[efcebe1]525 return ENOENT;
[1313ee9]526 }
527
[15f3c3f]528 loc_object_type_t type = loc_id_probe(index);
[1313ee9]529
[15f3c3f]530 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]531 /* Namespace directory */
532 ipc_callid_t callid;
533 size_t size;
534 if (!async_data_read_receive(&callid, &size)) {
[ffa2c8ef]535 async_answer_0(callid, EINVAL);
[efcebe1]536 return EINVAL;
[1313ee9]537 }
538
[15f3c3f]539 loc_sdesc_t *desc;
540 size_t count = loc_get_services(index, &desc);
[1313ee9]541
542 if (pos < count) {
543 async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
544 free(desc);
[efcebe1]545 *rbytes = 1;
546 return EOK;
[1313ee9]547 }
548
549 free(desc);
[ffa2c8ef]550 async_answer_0(callid, ENOENT);
[efcebe1]551 return ENOENT;
[1313ee9]552 }
553
[15f3c3f]554 if (type == LOC_OBJECT_SERVICE) {
[1313ee9]555 /* Device node */
556
[15f3c3f]557 fibril_mutex_lock(&services_mutex);
[062d900]558 service_id_t service_index = index;
559 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]560 if (lnk == NULL) {
[15f3c3f]561 fibril_mutex_unlock(&services_mutex);
[efcebe1]562 return ENOENT;
[17fd1d4]563 }
564
[062d900]565 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]566 assert(dev->sess);
[17fd1d4]567
568 ipc_callid_t callid;
[0da4e41]569 if (!async_data_read_receive(&callid, NULL)) {
[15f3c3f]570 fibril_mutex_unlock(&services_mutex);
[ffa2c8ef]571 async_answer_0(callid, EINVAL);
[efcebe1]572 return EINVAL;
[17fd1d4]573 }
574
575 /* Make a request at the driver */
[79ae36dd]576 async_exch_t *exch = async_exchange_begin(dev->sess);
577
[17fd1d4]578 ipc_call_t answer;
[86ffa27f]579 aid_t msg = async_send_4(exch, VFS_OUT_READ, service_id,
[efcebe1]580 index, LOWER32(pos), UPPER32(pos), &answer);
[17fd1d4]581
582 /* Forward the IPC_M_DATA_READ request to the driver */
[79ae36dd]583 async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
584
585 async_exchange_end(exch);
586
[15f3c3f]587 fibril_mutex_unlock(&services_mutex);
[17fd1d4]588
589 /* Wait for reply from the driver. */
[96b02eb9]590 sysarg_t rc;
[17fd1d4]591 async_wait_for(msg, &rc);
[086290d]592
593 /* Do not propagate EHANGUP back to VFS. */
594 if ((int) rc == EHANGUP)
595 rc = ENOTSUP;
[17fd1d4]596
[efcebe1]597 *rbytes = IPC_GET_ARG1(answer);
598 return rc;
[a095d20]599 }
[1313ee9]600
[efcebe1]601 return ENOENT;
[a095d20]602}
603
[efcebe1]604static int
[86ffa27f]605locfs_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
[efcebe1]606 size_t *wbytes, aoff64_t *nsize)
[a095d20]607{
[efcebe1]608 if (index == 0)
609 return ENOTSUP;
[1313ee9]610
[15f3c3f]611 loc_object_type_t type = loc_id_probe(index);
[1313ee9]612
[15f3c3f]613 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]614 /* Namespace directory */
[efcebe1]615 return ENOTSUP;
[1313ee9]616 }
617
[15f3c3f]618 if (type == LOC_OBJECT_SERVICE) {
[1313ee9]619 /* Device node */
[17fd1d4]620
[15f3c3f]621 fibril_mutex_lock(&services_mutex);
[062d900]622 service_id_t service_index = index;
623 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]624 if (lnk == NULL) {
[15f3c3f]625 fibril_mutex_unlock(&services_mutex);
[efcebe1]626 return ENOENT;
[17fd1d4]627 }
628
[062d900]629 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]630 assert(dev->sess);
[17fd1d4]631
632 ipc_callid_t callid;
[0da4e41]633 if (!async_data_write_receive(&callid, NULL)) {
[15f3c3f]634 fibril_mutex_unlock(&services_mutex);
[ffa2c8ef]635 async_answer_0(callid, EINVAL);
[efcebe1]636 return EINVAL;
[17fd1d4]637 }
638
639 /* Make a request at the driver */
[79ae36dd]640 async_exch_t *exch = async_exchange_begin(dev->sess);
641
[17fd1d4]642 ipc_call_t answer;
[86ffa27f]643 aid_t msg = async_send_4(exch, VFS_OUT_WRITE, service_id,
[efcebe1]644 index, LOWER32(pos), UPPER32(pos), &answer);
[17fd1d4]645
646 /* Forward the IPC_M_DATA_WRITE request to the driver */
[79ae36dd]647 async_forward_fast(callid, exch, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
648
649 async_exchange_end(exch);
[17fd1d4]650
[15f3c3f]651 fibril_mutex_unlock(&services_mutex);
[2dfd9fa]652
[17fd1d4]653 /* Wait for reply from the driver. */
[96b02eb9]654 sysarg_t rc;
[17fd1d4]655 async_wait_for(msg, &rc);
[086290d]656
657 /* Do not propagate EHANGUP back to VFS. */
658 if ((int) rc == EHANGUP)
659 rc = ENOTSUP;
[17fd1d4]660
[efcebe1]661 *wbytes = IPC_GET_ARG1(answer);
662 *nsize = 0;
663 return rc;
[a095d20]664 }
[1313ee9]665
[efcebe1]666 return ENOENT;
[a095d20]667}
668
[efcebe1]669static int
[86ffa27f]670locfs_truncate(service_id_t service_id, fs_index_t index, aoff64_t size)
[a095d20]671{
[efcebe1]672 return ENOTSUP;
[a095d20]673}
674
[86ffa27f]675static int locfs_close(service_id_t service_id, fs_index_t index)
[17fd1d4]676{
[efcebe1]677 if (index == 0)
678 return EOK;
[1313ee9]679
[15f3c3f]680 loc_object_type_t type = loc_id_probe(index);
[1313ee9]681
[15f3c3f]682 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]683 /* Namespace directory */
[efcebe1]684 return EOK;
[1313ee9]685 }
686
[15f3c3f]687 if (type == LOC_OBJECT_SERVICE) {
[17fd1d4]688
[15f3c3f]689 fibril_mutex_lock(&services_mutex);
[062d900]690 service_id_t service_index = index;
691 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]692 if (lnk == NULL) {
[15f3c3f]693 fibril_mutex_unlock(&services_mutex);
[efcebe1]694 return ENOENT;
[17fd1d4]695 }
696
[062d900]697 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]698 assert(dev->sess);
[17fd1d4]699 dev->refcount--;
700
701 if (dev->refcount == 0) {
[79ae36dd]702 async_hangup(dev->sess);
[062d900]703 service_id_t service_index = index;
704 hash_table_remove(&services, &service_index);
[17fd1d4]705 }
706
[15f3c3f]707 fibril_mutex_unlock(&services_mutex);
[2dfd9fa]708
[efcebe1]709 return EOK;
[1313ee9]710 }
711
[efcebe1]712 return ENOENT;
[17fd1d4]713}
714
[86ffa27f]715static int locfs_sync(service_id_t service_id, fs_index_t index)
[17fd1d4]716{
[efcebe1]717 if (index == 0)
718 return EOK;
[1313ee9]719
[15f3c3f]720 loc_object_type_t type = loc_id_probe(index);
[1313ee9]721
[15f3c3f]722 if (type == LOC_OBJECT_NAMESPACE) {
[1313ee9]723 /* Namespace directory */
[efcebe1]724 return EOK;
[1313ee9]725 }
726
[15f3c3f]727 if (type == LOC_OBJECT_SERVICE) {
[062d900]728
[15f3c3f]729 fibril_mutex_lock(&services_mutex);
[062d900]730 service_id_t service_index = index;
731 ht_link_t *lnk = hash_table_find(&services, &service_index);
[17fd1d4]732 if (lnk == NULL) {
[15f3c3f]733 fibril_mutex_unlock(&services_mutex);
[efcebe1]734 return ENOENT;
[17fd1d4]735 }
736
[062d900]737 service_t *dev = hash_table_get_inst(lnk, service_t, link);
[79ae36dd]738 assert(dev->sess);
[17fd1d4]739
740 /* Make a request at the driver */
[79ae36dd]741 async_exch_t *exch = async_exchange_begin(dev->sess);
742
[17fd1d4]743 ipc_call_t answer;
[86ffa27f]744 aid_t msg = async_send_2(exch, VFS_OUT_SYNC, service_id,
[efcebe1]745 index, &answer);
[17fd1d4]746
[79ae36dd]747 async_exchange_end(exch);
748
[15f3c3f]749 fibril_mutex_unlock(&services_mutex);
[2dfd9fa]750
[17fd1d4]751 /* Wait for reply from the driver */
[96b02eb9]752 sysarg_t rc;
[17fd1d4]753 async_wait_for(msg, &rc);
754
[efcebe1]755 return rc;
[1313ee9]756 }
757
[efcebe1]758 return ENOENT;
[17fd1d4]759}
760
[86ffa27f]761static int locfs_destroy(service_id_t service_id, fs_index_t index)
[a095d20]762{
[efcebe1]763 return ENOTSUP;
[a095d20]764}
765
[86ffa27f]766vfs_out_ops_t locfs_ops = {
767 .mounted = locfs_mounted,
768 .unmounted = locfs_unmounted,
769 .read = locfs_read,
770 .write = locfs_write,
771 .truncate = locfs_truncate,
772 .close = locfs_close,
773 .destroy = locfs_destroy,
774 .sync = locfs_sync,
[efcebe1]775};
776
[a095d20]777/**
778 * @}
[17fd1d4]779 */
Note: See TracBrowser for help on using the repository browser.