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

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

Remove duplicate includes

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