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

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

File system probing groundwork. Only MFS can do it for now.

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