2
* Copyright (c) 2008 Jakub Jermar
3
* Copyright (c) 2011 Martin Sucha
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
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.
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.
36
* @brief Implementation of VFS operations for the EXT2 file system server.
40
#include "../../vfs/vfs.h"
44
#include <ipc/services.h>
45
#include <ipc/devmap.h>
50
#include <byteorder.h>
51
#include <adt/hash_table.h>
54
#include <fibril_synch.h>
57
#include <adt/hash_table.h>
58
#include <sys/typefmt.h>
63
#define EXT2FS_NODE(node) ((node) ? (ext2fs_node_t *) (node)->data : NULL)
64
#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
65
#define OPEN_NODES_KEYS 2
66
#define OPEN_NODES_DEV_HANDLE_KEY 0
67
#define OPEN_NODES_INODE_KEY 1
68
#define OPEN_NODES_BUCKETS 256
70
typedef struct ext2fs_instance {
72
devmap_handle_t devmap_handle;
73
ext2_filesystem_t *filesystem;
74
unsigned int open_nodes_count;
77
typedef struct ext2fs_node {
78
ext2fs_instance_t *instance;
79
ext2_inode_ref_t *inode_ref;
82
unsigned int references;
86
* Forward declarations of auxiliary functions
88
static int ext2fs_instance_get(devmap_handle_t, ext2fs_instance_t **);
89
static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,
90
size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
91
static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,
92
size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
93
static bool ext2fs_is_dots(const uint8_t *, size_t);
94
static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
95
static int ext2fs_node_put_core(ext2fs_node_t *);
98
* Forward declarations of EXT2 libfs operations.
100
static int ext2fs_root_get(fs_node_t **, devmap_handle_t);
101
static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
102
static int ext2fs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
103
static int ext2fs_node_open(fs_node_t *);
104
static int ext2fs_node_put(fs_node_t *);
105
static int ext2fs_create_node(fs_node_t **, devmap_handle_t, int);
106
static int ext2fs_destroy_node(fs_node_t *);
107
static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
108
static int ext2fs_unlink(fs_node_t *, fs_node_t *, const char *);
109
static int ext2fs_has_children(bool *, fs_node_t *);
110
static fs_index_t ext2fs_index_get(fs_node_t *);
111
static aoff64_t ext2fs_size_get(fs_node_t *);
112
static unsigned ext2fs_lnkcnt_get(fs_node_t *);
113
static char ext2fs_plb_get_char(unsigned);
114
static bool ext2fs_is_directory(fs_node_t *);
115
static bool ext2fs_is_file(fs_node_t *node);
116
static devmap_handle_t ext2fs_device_get(fs_node_t *node);
121
static LIST_INITIALIZE(instance_list);
122
static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex);
123
static hash_table_t open_nodes;
124
static FIBRIL_MUTEX_INITIALIZE(open_nodes_lock);
126
/* Hash table interface for open nodes hash table */
127
static hash_index_t open_nodes_hash(unsigned long key[])
129
/* TODO: This is very simple and probably can be improved */
130
return key[OPEN_NODES_INODE_KEY] % OPEN_NODES_BUCKETS;
133
static int open_nodes_compare(unsigned long key[], hash_count_t keys,
136
ext2fs_node_t *enode = hash_table_get_instance(item, ext2fs_node_t, link);
138
if (enode->instance->devmap_handle !=
139
((devmap_handle_t) key[OPEN_NODES_DEV_HANDLE_KEY])) {
146
return (enode->inode_ref->index == key[OPEN_NODES_INODE_KEY]);
149
static void open_nodes_remove_cb(link_t *link)
151
/* We don't use remove callback for this hash table */
154
static hash_table_operations_t open_nodes_ops = {
155
.hash = open_nodes_hash,
156
.compare = open_nodes_compare,
157
.remove_callback = open_nodes_remove_cb,
163
int ext2fs_global_init(void)
165
if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS,
166
OPEN_NODES_KEYS, &open_nodes_ops)) {
172
int ext2fs_global_fini(void)
174
hash_table_destroy(&open_nodes);
180
* EXT2 libfs operations.
184
* Find an instance of filesystem for the given devmap_handle
186
int ext2fs_instance_get(devmap_handle_t devmap_handle, ext2fs_instance_t **inst)
188
EXT2FS_DBG("(%" PRIun ", -)", devmap_handle);
190
ext2fs_instance_t *tmp;
192
fibril_mutex_lock(&instance_list_mutex);
194
if (list_empty(&instance_list)) {
195
EXT2FS_DBG("list empty");
196
fibril_mutex_unlock(&instance_list_mutex);
200
for (link = instance_list.next; link != &instance_list; link = link->next) {
201
tmp = list_get_instance(link, ext2fs_instance_t, link);
203
if (tmp->devmap_handle == devmap_handle) {
205
fibril_mutex_unlock(&instance_list_mutex);
210
EXT2FS_DBG("not found");
212
fibril_mutex_unlock(&instance_list_mutex);
218
int ext2fs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
220
EXT2FS_DBG("(-, %" PRIun ")", devmap_handle);
221
return ext2fs_node_get(rfn, devmap_handle, EXT2_INODE_ROOT_INDEX);
224
int ext2fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
226
EXT2FS_DBG("(-,-,%s)", component);
227
ext2fs_node_t *eparent = EXT2FS_NODE(pfn);
228
ext2_filesystem_t *fs;
229
ext2_directory_iterator_t it;
232
size_t component_size;
235
fs = eparent->instance->filesystem;
237
if (!ext2_inode_is_type(fs->superblock, eparent->inode_ref->inode,
238
EXT2_INODE_MODE_DIRECTORY)) {
242
rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref);
247
/* Find length of component in bytes
248
* TODO: check for library function call that does this
251
while (*(component+component_size) != 0) {
255
while (it.current != NULL) {
256
/* ignore empty directory entries */
257
if (it.current->inode != 0) {
258
name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
261
if (name_size == component_size && bcmp(component, &it.current->name,
263
rc = ext2fs_node_get_core(rfn, eparent->instance,
266
ext2_directory_iterator_fini(&it);
274
rc = ext2_directory_iterator_next(&it);
276
ext2_directory_iterator_fini(&it);
281
ext2_directory_iterator_fini(&it);
290
/** Instantiate a EXT2 in-core node. */
291
int ext2fs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
293
EXT2FS_DBG("(-,%" PRIun ",%u)", devmap_handle, index);
295
ext2fs_instance_t *inst = NULL;
298
rc = ext2fs_instance_get(devmap_handle, &inst);
303
return ext2fs_node_get_core(rfn, inst, index);
306
int ext2fs_node_get_core(fs_node_t **rfn, ext2fs_instance_t *inst,
310
fs_node_t *node = NULL;
311
ext2fs_node_t *enode = NULL;
313
ext2_inode_ref_t *inode_ref = NULL;
315
fibril_mutex_lock(&open_nodes_lock);
317
/* Check if the node is not already open */
318
unsigned long key[] = {
319
[OPEN_NODES_DEV_HANDLE_KEY] = inst->devmap_handle,
320
[OPEN_NODES_INODE_KEY] = index,
322
link_t *already_open = hash_table_find(&open_nodes, key);
325
enode = hash_table_get_instance(already_open, ext2fs_node_t, link);
326
*rfn = enode->fs_node;
329
fibril_mutex_unlock(&open_nodes_lock);
333
enode = malloc(sizeof(ext2fs_node_t));
335
fibril_mutex_unlock(&open_nodes_lock);
339
node = malloc(sizeof(fs_node_t));
342
fibril_mutex_unlock(&open_nodes_lock);
345
fs_node_initialize(node);
347
rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
351
fibril_mutex_unlock(&open_nodes_lock);
355
enode->inode_ref = inode_ref;
356
enode->instance = inst;
357
enode->references = 1;
358
enode->fs_node = node;
359
link_initialize(&enode->link);
364
hash_table_insert(&open_nodes, key, &enode->link);
365
inst->open_nodes_count++;
367
EXT2FS_DBG("inode: %u", inode_ref->index);
371
fibril_mutex_unlock(&open_nodes_lock);
375
int ext2fs_node_open(fs_node_t *fn)
379
* Opening a file is stateless, nothing
385
int ext2fs_node_put(fs_node_t *fn)
389
ext2fs_node_t *enode = EXT2FS_NODE(fn);
391
fibril_mutex_lock(&open_nodes_lock);
393
assert(enode->references > 0);
395
if (enode->references == 0) {
396
rc = ext2fs_node_put_core(enode);
398
fibril_mutex_unlock(&open_nodes_lock);
403
fibril_mutex_unlock(&open_nodes_lock);
408
int ext2fs_node_put_core(ext2fs_node_t *enode)
412
unsigned long key[] = {
413
[OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->devmap_handle,
414
[OPEN_NODES_INODE_KEY] = enode->inode_ref->index,
416
hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS);
417
assert(enode->instance->open_nodes_count > 0);
418
enode->instance->open_nodes_count--;
420
rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
422
EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
426
free(enode->fs_node);
431
int ext2fs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
438
int ext2fs_destroy_node(fs_node_t *fn)
445
int ext2fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
452
int ext2fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
459
int ext2fs_has_children(bool *has_children, fs_node_t *fn)
462
ext2fs_node_t *enode = EXT2FS_NODE(fn);
463
ext2_directory_iterator_t it;
464
ext2_filesystem_t *fs;
469
fs = enode->instance->filesystem;
471
if (!ext2_inode_is_type(fs->superblock, enode->inode_ref->inode,
472
EXT2_INODE_MODE_DIRECTORY)) {
473
*has_children = false;
474
EXT2FS_DBG("EOK - false");
478
rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref);
480
EXT2FS_DBG("error %u", rc);
484
/* Find a non-empty directory entry */
485
while (it.current != NULL) {
486
if (it.current->inode != 0) {
487
name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
489
if (!ext2fs_is_dots(&it.current->name, name_size)) {
495
rc = ext2_directory_iterator_next(&it);
497
ext2_directory_iterator_fini(&it);
498
EXT2FS_DBG("error %u", rc);
503
rc = ext2_directory_iterator_fini(&it);
505
EXT2FS_DBG("error %u", rc);
509
*has_children = found;
516
fs_index_t ext2fs_index_get(fs_node_t *fn)
518
ext2fs_node_t *enode = EXT2FS_NODE(fn);
519
EXT2FS_DBG("%u", enode->inode_ref->index);
520
return enode->inode_ref->index;
523
aoff64_t ext2fs_size_get(fs_node_t *fn)
525
ext2fs_node_t *enode = EXT2FS_NODE(fn);
526
aoff64_t size = ext2_inode_get_size(enode->instance->filesystem->superblock,
527
enode->inode_ref->inode);
528
EXT2FS_DBG("%" PRIu64, size);
532
unsigned ext2fs_lnkcnt_get(fs_node_t *fn)
534
ext2fs_node_t *enode = EXT2FS_NODE(fn);
535
unsigned count = ext2_inode_get_usage_count(enode->inode_ref->inode);
536
EXT2FS_DBG("%u", count);
540
char ext2fs_plb_get_char(unsigned pos)
542
return ext2fs_reg.plb_ro[pos % PLB_SIZE];
545
bool ext2fs_is_directory(fs_node_t *fn)
547
ext2fs_node_t *enode = EXT2FS_NODE(fn);
548
bool is_dir = ext2_inode_is_type(enode->instance->filesystem->superblock,
549
enode->inode_ref->inode, EXT2_INODE_MODE_DIRECTORY);
550
EXT2FS_DBG("%s", is_dir ? "true" : "false");
551
EXT2FS_DBG("%u", enode->inode_ref->index);
555
bool ext2fs_is_file(fs_node_t *fn)
557
ext2fs_node_t *enode = EXT2FS_NODE(fn);
558
bool is_file = ext2_inode_is_type(enode->instance->filesystem->superblock,
559
enode->inode_ref->inode, EXT2_INODE_MODE_FILE);
560
EXT2FS_DBG("%s", is_file ? "true" : "false");
564
devmap_handle_t ext2fs_device_get(fs_node_t *fn)
567
ext2fs_node_t *enode = EXT2FS_NODE(fn);
568
return enode->instance->devmap_handle;
571
/** libfs operations */
572
libfs_ops_t ext2fs_libfs_ops = {
573
.root_get = ext2fs_root_get,
574
.match = ext2fs_match,
575
.node_get = ext2fs_node_get,
576
.node_open = ext2fs_node_open,
577
.node_put = ext2fs_node_put,
578
.create = ext2fs_create_node,
579
.destroy = ext2fs_destroy_node,
581
.unlink = ext2fs_unlink,
582
.has_children = ext2fs_has_children,
583
.index_get = ext2fs_index_get,
584
.size_get = ext2fs_size_get,
585
.lnkcnt_get = ext2fs_lnkcnt_get,
586
.plb_get_char = ext2fs_plb_get_char,
587
.is_directory = ext2fs_is_directory,
588
.is_file = ext2fs_is_file,
589
.device_get = ext2fs_device_get
596
void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request)
600
devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
601
ext2_filesystem_t *fs;
602
ext2fs_instance_t *inst;
605
/* Accept the mount options */
607
rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
610
async_answer_0(rid, rc);
616
/* Allocate libext2 filesystem structure */
617
fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
619
async_answer_0(rid, ENOMEM);
623
/* Allocate instance structure */
624
inst = (ext2fs_instance_t *) malloc(sizeof(ext2fs_instance_t));
627
async_answer_0(rid, ENOMEM);
631
/* Initialize the filesystem */
632
rc = ext2_filesystem_init(fs, devmap_handle);
636
async_answer_0(rid, rc);
640
/* Do some sanity checking */
641
rc = ext2_filesystem_check_sanity(fs);
643
ext2_filesystem_fini(fs);
646
async_answer_0(rid, rc);
651
rc = ext2_filesystem_check_flags(fs, &read_only);
653
ext2_filesystem_fini(fs);
656
async_answer_0(rid, rc);
660
/* Initialize instance */
661
link_initialize(&inst->link);
662
inst->devmap_handle = devmap_handle;
663
inst->filesystem = fs;
664
inst->open_nodes_count = 0;
667
fs_node_t *root_node;
668
rc = ext2fs_node_get_core(&root_node, inst, EXT2_INODE_ROOT_INDEX);
670
ext2_filesystem_fini(fs);
673
async_answer_0(rid, rc);
676
ext2fs_node_t *enode = EXT2FS_NODE(root_node);
678
/* Add instance to the list */
679
fibril_mutex_lock(&instance_list_mutex);
680
list_append(&inst->link, &instance_list);
681
fibril_mutex_unlock(&instance_list_mutex);
683
async_answer_3(rid, EOK,
684
EXT2_INODE_ROOT_INDEX,
686
ext2_inode_get_usage_count(enode->inode_ref->inode));
688
ext2fs_node_put(root_node);
691
void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request)
694
libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
697
void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request)
700
devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
701
ext2fs_instance_t *inst;
704
rc = ext2fs_instance_get(devmap_handle, &inst);
707
async_answer_0(rid, rc);
711
fibril_mutex_lock(&open_nodes_lock);
713
EXT2FS_DBG("open_nodes_count = %d", inst->open_nodes_count)
714
if (inst->open_nodes_count != 0) {
715
fibril_mutex_unlock(&open_nodes_lock);
716
async_answer_0(rid, EBUSY);
720
/* Remove the instance from the list */
721
fibril_mutex_lock(&instance_list_mutex);
722
list_remove(&inst->link);
723
fibril_mutex_unlock(&instance_list_mutex);
725
fibril_mutex_unlock(&open_nodes_lock);
727
ext2_filesystem_fini(inst->filesystem);
729
async_answer_0(rid, EOK);
732
void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request)
735
libfs_unmount(&ext2fs_libfs_ops, rid, request);
738
void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request)
741
libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
744
void ext2fs_read(ipc_callid_t rid, ipc_call_t *request)
747
devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
748
fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
750
(aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
752
ext2fs_instance_t *inst;
753
ext2_inode_ref_t *inode_ref;
757
* Receive the read request.
761
if (!async_data_read_receive(&callid, &size)) {
762
async_answer_0(callid, EINVAL);
763
async_answer_0(rid, EINVAL);
767
rc = ext2fs_instance_get(devmap_handle, &inst);
769
async_answer_0(callid, rc);
770
async_answer_0(rid, rc);
774
rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
776
async_answer_0(callid, rc);
777
async_answer_0(rid, rc);
781
if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
782
EXT2_INODE_MODE_FILE)) {
783
ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);
785
else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
786
EXT2_INODE_MODE_DIRECTORY)) {
787
ext2fs_read_directory(rid, callid, pos, size, inst, inode_ref);
790
/* Other inode types not supported */
791
async_answer_0(callid, ENOTSUP);
792
async_answer_0(rid, ENOTSUP);
795
ext2_filesystem_put_inode_ref(inode_ref);
800
* Determine whether given directory entry name is . or ..
802
bool ext2fs_is_dots(const uint8_t *name, size_t name_size) {
803
if (name_size == 1 && name[0] == '.') {
807
if (name_size == 2 && name[0] == '.' && name[1] == '.') {
814
void ext2fs_read_directory(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
815
size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
817
ext2_directory_iterator_t it;
824
rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref);
826
async_answer_0(callid, rc);
827
async_answer_0(rid, rc);
831
/* Find the index we want to read
832
* Note that we need to iterate and count as
833
* the underlying structure is a linked list
834
* Moreover, we want to skip . and .. entries
835
* as these are not used in HelenOS
838
while (it.current != NULL) {
839
if (it.current->inode == 0) {
843
name_size = ext2_directory_entry_ll_get_name_length(
844
inst->filesystem->superblock, it.current);
847
if (ext2fs_is_dots(&it.current->name, name_size)) {
851
/* Is this the dir entry we want to read? */
853
/* The on-disk entry does not contain \0 at the end
854
* end of entry name, so we copy it to new buffer
855
* and add the \0 at the end
857
buf = malloc(name_size+1);
859
ext2_directory_iterator_fini(&it);
860
async_answer_0(callid, ENOMEM);
861
async_answer_0(rid, ENOMEM);
864
memcpy(buf, &it.current->name, name_size);
865
*(buf+name_size) = 0;
867
(void) async_data_read_finalize(callid, buf, name_size+1);
874
rc = ext2_directory_iterator_next(&it);
876
ext2_directory_iterator_fini(&it);
877
async_answer_0(callid, rc);
878
async_answer_0(rid, rc);
883
rc = ext2_directory_iterator_fini(&it);
885
async_answer_0(rid, rc);
890
async_answer_1(rid, EOK, 1);
893
async_answer_0(callid, ENOENT);
894
async_answer_0(rid, ENOENT);
898
void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
899
size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
906
size_t offset_in_block;
911
file_size = ext2_inode_get_size(inst->filesystem->superblock,
914
if (pos >= file_size) {
915
/* Read 0 bytes successfully */
916
async_data_read_finalize(callid, NULL, 0);
917
async_answer_1(rid, EOK, 0);
921
/* For now, we only read data from one block at a time */
922
block_size = ext2_superblock_get_block_size(inst->filesystem->superblock);
923
file_block = pos / block_size;
924
offset_in_block = pos % block_size;
925
bytes = min(block_size - offset_in_block, size);
927
/* Handle end of file */
928
if (pos + bytes > file_size) {
929
bytes = file_size - pos;
932
/* Get the real block number */
933
rc = ext2_filesystem_get_inode_data_block_index(inst->filesystem,
934
inode_ref->inode, file_block, &fs_block);
936
async_answer_0(callid, rc);
937
async_answer_0(rid, rc);
941
/* Check for sparse file
942
* If ext2_filesystem_get_inode_data_block_index returned
943
* fs_block == 0, it means that the given block is not allocated for the
944
* file and we need to return a buffer of zeros
947
buffer = malloc(bytes);
948
if (buffer == NULL) {
949
async_answer_0(callid, ENOMEM);
950
async_answer_0(rid, ENOMEM);
954
memset(buffer, 0, bytes);
956
async_data_read_finalize(callid, buffer, bytes);
957
async_answer_1(rid, EOK, bytes);
964
/* Usual case - we need to read a block from device */
965
rc = block_get(&block, inst->devmap_handle, fs_block, BLOCK_FLAGS_NONE);
967
async_answer_0(callid, rc);
968
async_answer_0(rid, rc);
972
assert(offset_in_block + bytes <= block_size);
973
async_data_read_finalize(callid, block->data + offset_in_block, bytes);
975
rc = block_put(block);
977
async_answer_0(rid, rc);
981
async_answer_1(rid, EOK, bytes);
984
void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
987
// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
988
// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
990
// (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
993
async_answer_0(rid, ENOTSUP);
996
void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request)
999
// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
1000
// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
1002
// (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
1005
async_answer_0(rid, ENOTSUP);
1008
void ext2fs_close(ipc_callid_t rid, ipc_call_t *request)
1011
async_answer_0(rid, EOK);
1014
void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request)
1017
// devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
1018
// fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
1021
async_answer_0(rid, ENOTSUP);
1024
void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request)
1027
libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
1030
void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request)
1033
libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
1036
void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request)
1039
// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
1040
// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
1043
async_answer_0(rid, ENOTSUP);