source: mainline/uspace/srv/fs/ext2fs/ext2fs_ops.c@ 4dc6a32

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4dc6a32 was 4dc6a32, checked in by Martin Sucha <sucha14@…>, 14 years ago

ext2fs server now (almost, as it is not synchronized yet) supports mounting and basic reading of directories

  • Property mode set to 100644
File size: 16.9 KB
Line 
1/*
2 * Copyright (c) 2008 Jakub Jermar
3 * Copyright (c) 2011 Martin Sucha
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup fs
31 * @{
32 */
33
34/**
35 * @file ext2fs_ops.c
36 * @brief Implementation of VFS operations for the EXT2 file system server.
37 */
38
39#include "ext2fs.h"
40#include "../../vfs/vfs.h"
41#include <libfs.h>
42#include <libblock.h>
43#include <libext2.h>
44#include <ipc/services.h>
45#include <ipc/devmap.h>
46#include <macros.h>
47#include <async.h>
48#include <errno.h>
49#include <str.h>
50#include <byteorder.h>
51#include <adt/hash_table.h>
52#include <adt/list.h>
53#include <assert.h>
54#include <fibril_synch.h>
55#include <sys/mman.h>
56#include <align.h>
57#include <adt/hash_table.h>
58
59#define EXT2FS_NODE(node) ((node) ? (ext2fs_node_t *) (node)->data : NULL)
60#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
61
62typedef struct ext2fs_instance {
63 link_t link;
64 devmap_handle_t devmap_handle;
65 ext2_filesystem_t *filesystem;
66} ext2fs_instance_t;
67
68typedef struct ext2fs_node {
69 ext2fs_instance_t *instance;
70 ext2_inode_ref_t *inode_ref;
71} ext2fs_node_t;
72
73static int ext2fs_instance_get(devmap_handle_t, ext2fs_instance_t **);
74
75/*
76 * Forward declarations of EXT2 libfs operations.
77 */
78static int ext2fs_root_get(fs_node_t **, devmap_handle_t);
79static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
80static int ext2fs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
81static int ext2fs_node_open(fs_node_t *);
82static int ext2fs_node_put(fs_node_t *);
83static int ext2fs_create_node(fs_node_t **, devmap_handle_t, int);
84static int ext2fs_destroy_node(fs_node_t *);
85static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
86static int ext2fs_unlink(fs_node_t *, fs_node_t *, const char *);
87static int ext2fs_has_children(bool *, fs_node_t *);
88static fs_index_t ext2fs_index_get(fs_node_t *);
89static aoff64_t ext2fs_size_get(fs_node_t *);
90static unsigned ext2fs_lnkcnt_get(fs_node_t *);
91static char ext2fs_plb_get_char(unsigned);
92static bool ext2fs_is_directory(fs_node_t *);
93static bool ext2fs_is_file(fs_node_t *node);
94static devmap_handle_t ext2fs_device_get(fs_node_t *node);
95
96/*
97 * Static variables
98 */
99static LIST_INITIALIZE(instance_list);
100
101/**
102 *
103 */
104int ext2fs_global_init(void)
105{
106 return EOK;
107}
108
109int ext2fs_global_fini(void)
110{
111 return EOK;
112}
113
114
115
116/*
117 * EXT2 libfs operations.
118 */
119
120/**
121 * Find an instance of filesystem for the given devmap_handle
122 */
123int ext2fs_instance_get(devmap_handle_t devmap_handle, ext2fs_instance_t **inst)
124{
125 EXT2FS_DBG("(%u, -)", devmap_handle);
126 link_t *link;
127 ext2fs_instance_t *tmp;
128
129 if (list_empty(&instance_list)) {
130 EXT2FS_DBG("list empty");
131 return EINVAL;
132 }
133
134 for (link = instance_list.next; link != &instance_list; link = link->next) {
135 tmp = list_get_instance(link, ext2fs_instance_t, link);
136
137 if (tmp->devmap_handle == devmap_handle) {
138 *inst = tmp;
139 return EOK;
140 }
141 }
142
143 EXT2FS_DBG("not found");
144 return EINVAL;
145}
146
147
148
149int ext2fs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
150{
151 EXT2FS_DBG("(-, %u)", devmap_handle);
152 return ext2fs_node_get(rfn, devmap_handle, EXT2_INODE_ROOT_INDEX);
153}
154
155int ext2fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
156{
157 EXT2FS_DBG("(-,-,%s)", component);
158 ext2fs_node_t *eparent = EXT2FS_NODE(pfn);
159 ext2_filesystem_t *fs;
160 ext2_directory_iterator_t it;
161 int rc;
162 size_t name_size;
163 size_t component_size;
164 bool found = false;
165
166 fs = eparent->instance->filesystem;
167
168 if (!ext2_inode_is_type(fs->superblock, eparent->inode_ref->inode,
169 EXT2_INODE_MODE_DIRECTORY)) {
170 return ENOTDIR;
171 }
172
173 rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref);
174 if (rc != EOK) {
175 return rc;
176 }
177
178 // Find length of component in bytes
179 // TODO: check for library function call that does this
180 component_size = 0;
181 while (*(component+component_size) != 0) {
182 component_size++;
183 }
184
185 while (it.current != NULL) {
186 // ignore empty directory entries
187 if (it.current->inode != 0) {
188 name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
189 it.current);
190
191 if (name_size == component_size && bcmp(component, &it.current->name,
192 name_size) == 0) {
193 // FIXME: this may be done better (give instance as param)
194 rc = ext2fs_node_get(rfn, eparent->instance->devmap_handle,
195 it.current->inode);
196 if (rc != EOK) {
197 ext2_directory_iterator_fini(&it);
198 return rc;
199 }
200 found = true;
201 break;
202 }
203 }
204
205 rc = ext2_directory_iterator_next(&it);
206 if (rc != EOK) {
207 ext2_directory_iterator_fini(&it);
208 return rc;
209 }
210 }
211
212 ext2_directory_iterator_fini(&it);
213
214 if (!found) {
215 return ENOENT;
216 }
217
218 return EOK;
219}
220
221/** Instantiate a EXT2 in-core node. */
222int ext2fs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
223{
224 EXT2FS_DBG("(-,%u,%u)", devmap_handle, index);
225 int rc;
226 fs_node_t *node = NULL;
227 ext2fs_node_t *enode = NULL;
228 ext2fs_instance_t *inst = NULL;
229 ext2_inode_ref_t *inode_ref = NULL;
230
231 enode = malloc(sizeof(ext2fs_node_t));
232 if (enode == NULL) {
233 return ENOMEM;
234 }
235
236 node = malloc(sizeof(fs_node_t));
237 if (node == NULL) {
238 free(enode);
239 return ENOMEM;
240 }
241
242 fs_node_initialize(node);
243
244 rc = ext2fs_instance_get(devmap_handle, &inst);
245 if (rc != EOK) {
246 free(enode);
247 free(node);
248 return rc;
249 }
250
251 rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
252 if (rc != EOK) {
253 free(enode);
254 free(node);
255 return rc;
256 }
257
258 enode->inode_ref = inode_ref;
259 enode->instance = inst;
260 node->data = enode;
261 *rfn = node;
262
263 EXT2FS_DBG("inode: %u", inode_ref->index);
264
265 EXT2FS_DBG("EOK");
266
267 return EOK;
268}
269
270int ext2fs_node_open(fs_node_t *fn)
271{
272 EXT2FS_DBG("");
273 /*
274 * Opening a file is stateless, nothing
275 * to be done here.
276 */
277 return EOK;
278}
279
280int ext2fs_node_put(fs_node_t *fn)
281{
282 EXT2FS_DBG("");
283 int rc;
284 ext2fs_node_t *enode = EXT2FS_NODE(fn);
285 rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
286 if (rc != EOK) {
287 EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
288 }
289 return rc;
290}
291
292int ext2fs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
293{
294 EXT2FS_DBG("");
295 // TODO
296 return ENOTSUP;
297}
298
299int ext2fs_destroy_node(fs_node_t *fn)
300{
301 EXT2FS_DBG("");
302 // TODO
303 return ENOTSUP;
304}
305
306int ext2fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
307{
308 EXT2FS_DBG("");
309 // TODO
310 return ENOTSUP;
311}
312
313int ext2fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
314{
315 EXT2FS_DBG("");
316 // TODO
317 return ENOTSUP;
318}
319
320int ext2fs_has_children(bool *has_children, fs_node_t *fn)
321{
322 EXT2FS_DBG("");
323 ext2fs_node_t *enode = EXT2FS_NODE(fn);
324 ext2_directory_iterator_t it;
325 ext2_filesystem_t *fs;
326 int rc;
327 bool found = false;
328
329 fs = enode->instance->filesystem;
330
331 if (!ext2_inode_is_type(fs->superblock, enode->inode_ref->inode,
332 EXT2_INODE_MODE_DIRECTORY)) {
333 *has_children = false;
334 EXT2FS_DBG("EOK - false");
335 return EOK;
336 }
337
338 rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref);
339 if (rc != EOK) {
340 EXT2FS_DBG("error %u", rc);
341 return rc;
342 }
343
344 // Find a non-empty directory entry
345 while (it.current != NULL) {
346 if (it.current->inode != 0) {
347 found = true;
348 break;
349 }
350
351 rc = ext2_directory_iterator_next(&it);
352 if (rc != EOK) {
353 ext2_directory_iterator_fini(&it);
354 EXT2FS_DBG("error %u", rc);
355 return rc;
356 }
357 }
358
359 rc = ext2_directory_iterator_fini(&it);
360 if (rc != EOK) {
361 EXT2FS_DBG("error %u", rc);
362 return rc;
363 }
364
365 *has_children = found;
366 EXT2FS_DBG("EOK");
367
368 return EOK;
369}
370
371
372fs_index_t ext2fs_index_get(fs_node_t *fn)
373{
374 ext2fs_node_t *enode = EXT2FS_NODE(fn);
375 EXT2FS_DBG("%u", enode->inode_ref->index);
376 return enode->inode_ref->index;
377}
378
379aoff64_t ext2fs_size_get(fs_node_t *fn)
380{
381 ext2fs_node_t *enode = EXT2FS_NODE(fn);
382 aoff64_t size = ext2_inode_get_size(enode->instance->filesystem->superblock,
383 enode->inode_ref->inode);
384 EXT2FS_DBG("%" PRIu64, size);
385 return size;
386}
387
388unsigned ext2fs_lnkcnt_get(fs_node_t *fn)
389{
390 ext2fs_node_t *enode = EXT2FS_NODE(fn);
391 unsigned count = ext2_inode_get_usage_count(enode->inode_ref->inode);
392 EXT2FS_DBG("%u", count);
393 return count;
394}
395
396char ext2fs_plb_get_char(unsigned pos)
397{
398 return ext2fs_reg.plb_ro[pos % PLB_SIZE];
399}
400
401bool ext2fs_is_directory(fs_node_t *fn)
402{
403 ext2fs_node_t *enode = EXT2FS_NODE(fn);
404 bool is_dir = ext2_inode_is_type(enode->instance->filesystem->superblock,
405 enode->inode_ref->inode, EXT2_INODE_MODE_DIRECTORY);
406 EXT2FS_DBG("%s", is_dir ? "true" : "false");
407 EXT2FS_DBG("%u", enode->inode_ref->index);
408 return is_dir;
409}
410
411bool ext2fs_is_file(fs_node_t *fn)
412{
413 ext2fs_node_t *enode = EXT2FS_NODE(fn);
414 bool is_file = ext2_inode_is_type(enode->instance->filesystem->superblock,
415 enode->inode_ref->inode, EXT2_INODE_MODE_FILE);
416 EXT2FS_DBG("%s", is_file ? "true" : "false");
417 return is_file;
418}
419
420devmap_handle_t ext2fs_device_get(fs_node_t *fn)
421{
422 EXT2FS_DBG("");
423 ext2fs_node_t *enode = EXT2FS_NODE(fn);
424 return enode->instance->devmap_handle;
425}
426
427/** libfs operations */
428libfs_ops_t ext2fs_libfs_ops = {
429 .root_get = ext2fs_root_get,
430 .match = ext2fs_match,
431 .node_get = ext2fs_node_get,
432 .node_open = ext2fs_node_open,
433 .node_put = ext2fs_node_put,
434 .create = ext2fs_create_node,
435 .destroy = ext2fs_destroy_node,
436 .link = ext2fs_link,
437 .unlink = ext2fs_unlink,
438 .has_children = ext2fs_has_children,
439 .index_get = ext2fs_index_get,
440 .size_get = ext2fs_size_get,
441 .lnkcnt_get = ext2fs_lnkcnt_get,
442 .plb_get_char = ext2fs_plb_get_char,
443 .is_directory = ext2fs_is_directory,
444 .is_file = ext2fs_is_file,
445 .device_get = ext2fs_device_get
446};
447
448/*
449 * VFS operations.
450 */
451
452void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request)
453{
454 EXT2FS_DBG("");
455 int rc;
456 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
457 ext2_filesystem_t *fs;
458 ext2fs_instance_t *inst;
459
460
461
462 /* Accept the mount options */
463 char *opts;
464 rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
465
466 if (rc != EOK) {
467 async_answer_0(rid, rc);
468 return;
469 }
470
471 free(opts);
472
473 /* Allocate libext2 filesystem structure */
474 fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
475 if (fs == NULL) {
476 async_answer_0(rid, ENOMEM);
477 return;
478 }
479
480 /* Allocate instance structure */
481 inst = (ext2fs_instance_t *) malloc(sizeof(ext2fs_instance_t));
482 if (inst == NULL) {
483 free(fs);
484 async_answer_0(rid, ENOMEM);
485 return;
486 }
487
488 /* Initialize the filesystem */
489 rc = ext2_filesystem_init(fs, devmap_handle);
490 if (rc != EOK) {
491 free(fs);
492 free(inst);
493 async_answer_0(rid, rc);
494 return;
495 }
496
497 /* Do some sanity checking */
498 rc = ext2_filesystem_check_sanity(fs);
499 if (rc != EOK) {
500 ext2_filesystem_fini(fs);
501 free(fs);
502 free(inst);
503 async_answer_0(rid, rc);
504 return;
505 }
506
507 /* Initialize instance and add to the list */
508 link_initialize(&inst->link);
509 inst->devmap_handle = devmap_handle;
510 inst->filesystem = fs;
511 list_append(&inst->link, &instance_list);
512
513 async_answer_0(rid, EOK);
514}
515
516void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request)
517{
518 EXT2FS_DBG("");
519 libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
520}
521
522void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request)
523{
524 EXT2FS_DBG("");
525 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
526 ext2fs_instance_t *inst;
527 int rc;
528
529 rc = ext2fs_instance_get(devmap_handle, &inst);
530
531 if (rc != EOK) {
532 async_answer_0(rid, rc);
533 return;
534 }
535
536 // TODO: check if the fs is busy
537
538 // Remove the instance from list
539 list_remove(&inst->link);
540 ext2_filesystem_fini(inst->filesystem);
541
542 async_answer_0(rid, EOK);
543}
544
545void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request)
546{
547 EXT2FS_DBG("");
548 libfs_unmount(&ext2fs_libfs_ops, rid, request);
549}
550
551void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request)
552{
553 EXT2FS_DBG("");
554 libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
555}
556
557void ext2fs_read(ipc_callid_t rid, ipc_call_t *request)
558{
559 EXT2FS_DBG("");
560 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
561 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
562 aoff64_t pos =
563 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
564
565 ext2fs_instance_t *inst;
566 ext2_inode_ref_t *inode_ref;
567 int rc;
568 ext2_directory_iterator_t it;
569 aoff64_t cur;
570 uint8_t *buf;
571 size_t name_size;
572
573 /*
574 * Receive the read request.
575 */
576 ipc_callid_t callid;
577 size_t size;
578 if (!async_data_read_receive(&callid, &size)) {
579 async_answer_0(callid, EINVAL);
580 async_answer_0(rid, EINVAL);
581 return;
582 }
583
584 rc = ext2fs_instance_get(devmap_handle, &inst);
585 if (rc != EOK) {
586 async_answer_0(callid, rc);
587 async_answer_0(rid, rc);
588 return;
589 }
590
591 rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
592 if (rc != EOK) {
593 async_answer_0(callid, rc);
594 async_answer_0(rid, rc);
595 return;
596 }
597
598 if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
599 EXT2_INODE_MODE_FILE)) {
600 async_answer_0(callid, ENOTSUP);
601 async_answer_0(rid, ENOTSUP);
602 }
603 else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
604 EXT2_INODE_MODE_DIRECTORY)) {
605 rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref);
606 if (rc != EOK) {
607 async_answer_0(callid, rc);
608 async_answer_0(rid, rc);
609 return;
610 }
611
612 cur = 0;
613 while (it.current != NULL) {
614 if (it.current->inode != 0) {
615 if (cur == pos) {
616 // This is the dir entry we want to read
617 name_size = ext2_directory_entry_ll_get_name_length(
618 inst->filesystem->superblock, it.current);
619 // The on-disk entry does not contain \0 at the end
620 // end of entry name, so we copy it to new buffer
621 // and the \0 at the end
622 buf = malloc(name_size+1);
623 if (buf == NULL) {
624 ext2_directory_iterator_fini(&it);
625 async_answer_0(callid, ENOMEM);
626 async_answer_0(rid, ENOMEM);
627 return;
628 }
629 memcpy(buf, &it.current->name, name_size);
630 *(buf+name_size) = 0;
631 (void) async_data_read_finalize(callid, buf, name_size+1);
632 break;
633 }
634 cur++;
635 }
636
637 rc = ext2_directory_iterator_next(&it);
638 if (rc != EOK) {
639 ext2_directory_iterator_fini(&it);
640 async_answer_0(callid, rc);
641 async_answer_0(rid, rc);
642 return;
643 }
644 }
645
646 rc = ext2_directory_iterator_fini(&it);
647 if (rc != EOK) {
648 async_answer_0(rid, ENOMEM);
649 return;
650 }
651
652 async_answer_1(rid, EOK, 1);
653 }
654
655 // Other inode types not supported
656 async_answer_0(callid, ENOTSUP);
657 async_answer_0(rid, ENOTSUP);
658}
659
660void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
661{
662 EXT2FS_DBG("");
663// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
664// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
665// aoff64_t pos =
666// (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
667
668 // TODO
669 async_answer_0(rid, ENOTSUP);
670}
671
672void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request)
673{
674 EXT2FS_DBG("");
675// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
676// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
677// aoff64_t size =
678// (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
679
680 // TODO
681 async_answer_0(rid, ENOTSUP);
682}
683
684void ext2fs_close(ipc_callid_t rid, ipc_call_t *request)
685{
686 EXT2FS_DBG("");
687 async_answer_0(rid, EOK);
688}
689
690void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request)
691{
692 EXT2FS_DBG("");
693// devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
694// fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
695
696 // TODO
697 async_answer_0(rid, ENOTSUP);
698}
699
700void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request)
701{
702 EXT2FS_DBG("");
703 libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
704}
705
706void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request)
707{
708 EXT2FS_DBG("");
709 libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
710}
711
712void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request)
713{
714 EXT2FS_DBG("");
715// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
716// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
717
718 // TODO
719 async_answer_0(rid, ENOTSUP);
720}
721
722/**
723 * @}
724 */
Note: See TracBrowser for help on using the repository browser.