source: mainline/uspace/srv/fs/minixfs/mfs_ops.c@ 44c6091f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 44c6091f was 44c6091f, checked in by Maurizio Lombardi <m.lombardi85@…>, 15 years ago

cstyle

  • Property mode set to 100644
File size: 20.1 KB
Line 
1/*
2 * Copyright (c) 2011 Maurizio Lombardi
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#include <stdlib.h>
34#include <fibril_synch.h>
35#include <align.h>
36#include "mfs.h"
37#include "mfs_utils.h"
38
39static bool check_magic_number(uint16_t magic, bool *native,
40 mfs_version_t *version, bool *longfilenames);
41static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
42 fs_index_t index);
43
44static int mfs_node_put(fs_node_t *fsnode);
45static int mfs_node_open(fs_node_t *fsnode);
46static fs_index_t mfs_index_get(fs_node_t *fsnode);
47static unsigned mfs_lnkcnt_get(fs_node_t *fsnode);
48static char mfs_plb_get_char(unsigned pos);
49static bool mfs_is_directory(fs_node_t *fsnode);
50static bool mfs_is_file(fs_node_t *fsnode);
51static int mfs_has_children(bool *has_children, fs_node_t *fsnode);
52static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle);
53static devmap_handle_t mfs_device_get(fs_node_t *fsnode);
54static aoff64_t mfs_size_get(fs_node_t *node);
55static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component);
56static int mfs_create_node(fs_node_t **rfn, devmap_handle_t handle, int flags);
57static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name);
58
59static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
60 fs_index_t index);
61
62
63static LIST_INITIALIZE(inst_list);
64static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
65
66libfs_ops_t mfs_libfs_ops = {
67 .size_get = mfs_size_get,
68 .root_get = mfs_root_get,
69 .device_get = mfs_device_get,
70 .is_directory = mfs_is_directory,
71 .is_file = mfs_is_file,
72 .node_get = mfs_node_get,
73 .node_put = mfs_node_put,
74 .node_open = mfs_node_open,
75 .index_get = mfs_index_get,
76 .match = mfs_match,
77 .create = mfs_create_node,
78 .link = mfs_link,
79 .plb_get_char = mfs_plb_get_char,
80 .has_children = mfs_has_children,
81 .lnkcnt_get = mfs_lnkcnt_get
82};
83
84void mfs_mounted(ipc_callid_t rid, ipc_call_t *request)
85{
86 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
87 enum cache_mode cmode;
88 struct mfs_superblock *sb;
89 struct mfs3_superblock *sb3;
90 struct mfs_sb_info *sbi;
91 struct mfs_instance *instance;
92 bool native, longnames;
93 mfs_version_t version;
94 uint16_t magic;
95
96 /* Accept the mount options */
97 char *opts;
98 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
99
100 if (rc != EOK) {
101 mfsdebug("Can't accept async data write\n");
102 async_answer_0(rid, rc);
103 return;
104 }
105
106 /* Check for option enabling write through. */
107 if (str_cmp(opts, "wtcache") == 0)
108 cmode = CACHE_MODE_WT;
109 else
110 cmode = CACHE_MODE_WB;
111
112 free(opts);
113
114 /* initialize libblock */
115 rc = block_init(devmap_handle, 1024);
116 if (rc != EOK) {
117 mfsdebug("libblock initialization failed\n");
118 async_answer_0(rid, rc);
119 return;
120 }
121
122 /*Allocate space for generic MFS superblock*/
123 sbi = malloc(sizeof(*sbi));
124
125 if (!sbi) {
126 async_answer_0(rid, ENOMEM);
127 return;
128 }
129
130 /*Allocate space for filesystem instance*/
131 instance = malloc(sizeof(*instance));
132
133 if (!instance) {
134 async_answer_0(rid, ENOMEM);
135 return;
136 }
137
138 sb = malloc(MFS_SUPERBLOCK_SIZE);
139
140 if (!sb) {
141 async_answer_0(rid, ENOMEM);
142 return;
143 }
144
145 /* Read the superblock */
146 rc = block_read_direct(devmap_handle, MFS_SUPERBLOCK << 1, 1, sb);
147 if (rc != EOK) {
148 block_fini(devmap_handle);
149 async_answer_0(rid, rc);
150 return;
151 }
152
153 sb3 = (struct mfs3_superblock *) sb;
154
155 if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
156 /*This is a V1 or V2 Minix filesystem*/
157 magic = sb->s_magic;
158 goto recognized;
159 }
160
161 if (!check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
162 mfsdebug("magic number not recognized\n");
163 block_fini(devmap_handle);
164 async_answer_0(rid, ENOTSUP);
165 return;
166 }
167
168 /*This is a V3 Minix filesystem*/
169
170 magic = sb3->s_magic;
171
172recognized:
173
174 mfsdebug("magic number recognized = %04x\n", magic);
175
176 /*Fill superblock info structure*/
177
178 sbi->fs_version = version;
179 sbi->long_names = longnames;
180 sbi->native = native;
181 sbi->magic = magic;
182 sbi->isearch = 0;
183 sbi->zsearch = 0;
184
185 if (version == MFS_VERSION_V3) {
186 sbi->ninodes = conv32(native, sb3->s_ninodes);
187 sbi->ibmap_blocks = conv16(native, sb3->s_ibmap_blocks);
188 sbi->zbmap_blocks = conv16(native, sb3->s_zbmap_blocks);
189 sbi->firstdatazone = conv16(native, sb3->s_first_data_zone);
190 sbi->log2_zone_size = conv16(native, sb3->s_log2_zone_size);
191 sbi->max_file_size = conv32(native, sb3->s_max_file_size);
192 sbi->nzones = conv32(native, sb3->s_nzones);
193 sbi->block_size = conv16(native, sb3->s_block_size);
194 sbi->ino_per_block = V3_INODES_PER_BLOCK(sbi->block_size);
195 sbi->dirsize = MFS3_DIRSIZE;
196 sbi->max_name_len = MFS3_MAX_NAME_LEN;
197 } else {
198 sbi->ninodes = conv16(native, sb->s_ninodes);
199 sbi->ibmap_blocks = conv16(native, sb->s_ibmap_blocks);
200 sbi->zbmap_blocks = conv16(native, sb->s_zbmap_blocks);
201 sbi->firstdatazone = conv16(native, sb->s_first_data_zone);
202 sbi->log2_zone_size = conv16(native, sb->s_log2_zone_size);
203 sbi->max_file_size = conv32(native, sb->s_max_file_size);
204 sbi->block_size = MFS_BLOCKSIZE;
205 if (version == MFS_VERSION_V2) {
206 sbi->nzones = conv32(native, sb->s_nzones2);
207 sbi->ino_per_block = V2_INODES_PER_BLOCK;
208 } else {
209 sbi->nzones = conv16(native, sb->s_nzones);
210 sbi->ino_per_block = V1_INODES_PER_BLOCK;
211 }
212 sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
213 sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
214 MFS_MAX_NAME_LEN;
215 }
216 sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
217
218 free(sb);
219
220 rc = block_cache_init(devmap_handle, sbi->block_size, 0, cmode);
221
222 if (rc != EOK) {
223 block_fini(devmap_handle);
224 async_answer_0(rid, EINVAL);
225 mfsdebug("block cache initialization failed\n");
226 return;
227 }
228
229 /*Initialize the instance structure and add it to the list*/
230 link_initialize(&instance->link);
231 instance->handle = devmap_handle;
232 instance->sbi = sbi;
233
234 fibril_mutex_lock(&inst_list_mutex);
235 list_append(&instance->link, &inst_list);
236 fibril_mutex_unlock(&inst_list_mutex);
237
238 mfsdebug("mount successful\n");
239
240 async_answer_0(rid, EOK);
241}
242
243void mfs_mount(ipc_callid_t rid, ipc_call_t *request)
244{
245 libfs_mount(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
246}
247
248devmap_handle_t mfs_device_get(fs_node_t *fsnode)
249{
250 struct mfs_node *node = fsnode->data;
251 return node->instance->handle;
252}
253
254static int mfs_create_node(fs_node_t **rfn, devmap_handle_t handle, int flags)
255{
256 int r;
257 struct mfs_instance *inst;
258 struct mfs_node *mnode;
259 fs_node_t *fsnode;
260 uint32_t inum;
261
262 mfsdebug("create_node()\n");
263
264 r = mfs_instance_get(handle, &inst);
265 on_error(r, return r);
266
267 if (flags & L_DIRECTORY) {
268 /*Not yet supported*/
269 return ENOTSUP;
270 }
271
272 /*Alloc a new inode*/
273 r = mfs_alloc_bit(inst, &inum, BMAP_INODE);
274 on_error(r, return r);
275
276 struct mfs_ino_info *ino_i;
277
278 ino_i = malloc(sizeof(*ino_i));
279 if (!ino_i) {
280 r = ENOMEM;
281 goto out_err;
282 }
283
284 mnode = malloc(sizeof(*mnode));
285 if (!mnode) {
286 r = ENOMEM;
287 goto out_err_1;
288 }
289
290 fsnode = malloc(sizeof(fs_node_t));
291 if (!fsnode) {
292 r = ENOMEM;
293 goto out_err_2;
294 }
295
296 ino_i->i_mode = S_IFREG;
297 ino_i->i_nlinks = 1;
298 ino_i->i_uid = 0;
299 ino_i->i_gid = 0;
300 ino_i->i_size = 0;
301 ino_i->i_atime = 0;
302 ino_i->i_mtime = 0;
303 ino_i->i_ctime = 0;
304
305 memset(ino_i->i_dzone, 0, sizeof(uint32_t) * V2_NR_DIRECT_ZONES);
306 memset(ino_i->i_izone, 0, sizeof(uint32_t) * V2_NR_INDIRECT_ZONES);
307
308 mfsdebug("new node idx = %d\n", (int) inum);
309
310 ino_i->index = inum;
311 ino_i->dirty = true;
312 mnode->ino_i = ino_i;
313 mnode->instance = inst;
314
315 r = put_inode(mnode);
316 on_error(r, goto out_err_2);
317
318 fs_node_initialize(fsnode);
319 fsnode->data = mnode;
320 *rfn = fsnode;
321
322 return EOK;
323
324out_err_2:
325 free(mnode);
326out_err_1:
327 free(ino_i);
328out_err:
329 return r;
330}
331
332static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
333{
334 struct mfs_node *mnode = pfn->data;
335 struct mfs_ino_info *ino_i = mnode->ino_i;
336 struct mfs_dentry_info *d_info;
337 int r;
338
339 mfsdebug("mfs_match()\n");
340
341 if (!S_ISDIR(ino_i->i_mode))
342 return ENOTDIR;
343
344 struct mfs_sb_info *sbi = mnode->instance->sbi;
345 const size_t comp_size = str_size(component);
346
347 int i = 2;
348 while (1) {
349 r = read_directory_entry(mnode, &d_info, i++);
350 on_error(r, return r);
351
352 if (!d_info) {
353 /*Reached the end of the directory entry list*/
354 break;
355 }
356
357 if (!d_info->d_inum) {
358 /*This entry is not used*/
359 free(d_info);
360 continue;
361 }
362
363 if (!bcmp(component, d_info->d_name, min(sbi->max_name_len,
364 comp_size))) {
365 /*Hit!*/
366 mfs_node_core_get(rfn, mnode->instance,
367 d_info->d_inum);
368 free(d_info);
369 goto found;
370 }
371 free(d_info);
372 }
373 *rfn = NULL;
374found:
375 return EOK;
376}
377
378static aoff64_t mfs_size_get(fs_node_t *node)
379{
380 assert(node);
381
382 const struct mfs_node *mnode = node->data;
383 assert(mnode);
384 assert(mnode->ino_i);
385
386 return mnode->ino_i->i_size;
387}
388
389void mfs_stat(ipc_callid_t rid, ipc_call_t *request)
390{
391 libfs_stat(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
392}
393
394static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
395 fs_index_t index)
396{
397 int rc;
398 struct mfs_instance *instance;
399
400 rc = mfs_instance_get(devmap_handle, &instance);
401 on_error(rc, return rc);
402
403 return mfs_node_core_get(rfn, instance, index);
404}
405
406static int mfs_node_put(fs_node_t *fsnode)
407{
408 struct mfs_node *mnode = fsnode->data;
409
410 put_inode(mnode);
411 free(mnode->ino_i);
412 free(mnode);
413
414 return EOK;
415}
416
417static int mfs_node_open(fs_node_t *fsnode)
418{
419 /*
420 * Opening a file is stateless, nothing
421 * to be done here.
422 */
423 return EOK;
424}
425
426static fs_index_t mfs_index_get(fs_node_t *fsnode)
427{
428 struct mfs_node *mnode = fsnode->data;
429
430 assert(mnode->ino_i);
431 return mnode->ino_i->index;
432}
433
434static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
435{
436 unsigned rc;
437 struct mfs_node *mnode = fsnode->data;
438
439 assert(mnode);
440 assert(mnode->ino_i);
441
442 rc = mnode->ino_i->i_nlinks;
443 return rc;
444}
445
446static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
447 fs_index_t index)
448{
449 fs_node_t *node = NULL;
450 struct mfs_node *mnode = NULL;
451 int rc;
452
453 node = malloc(sizeof(fs_node_t));
454 if (!node) {
455 rc = ENOMEM;
456 goto out_err;
457 }
458
459 fs_node_initialize(node);
460
461 mnode = malloc(sizeof(*mnode));
462 if (!mnode) {
463 rc = ENOMEM;
464 goto out_err;
465 }
466
467 struct mfs_ino_info *ino_i;
468
469 rc = get_inode(inst, &ino_i, index);
470 on_error(rc, goto out_err);
471
472 ino_i->index = index;
473 mnode->ino_i = ino_i;
474
475 mnode->instance = inst;
476 node->data = mnode;
477 *rfn = node;
478
479 mfsdebug("node_get_core(%d) OK\n", (int) index);
480
481 return EOK;
482
483out_err:
484 if (node)
485 free(node);
486 if (mnode)
487 free(mnode);
488 return rc;
489}
490
491static bool mfs_is_directory(fs_node_t *fsnode)
492{
493 const struct mfs_node *node = fsnode->data;
494 return S_ISDIR(node->ino_i->i_mode);
495}
496
497static bool mfs_is_file(fs_node_t *fsnode)
498{
499 struct mfs_node *node = fsnode->data;
500 return S_ISREG(node->ino_i->i_mode);
501}
502
503static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle)
504{
505 int rc = mfs_node_get(rfn, handle, MFS_ROOT_INO);
506 return rc;
507}
508
509void mfs_lookup(ipc_callid_t rid, ipc_call_t *request)
510{
511 libfs_lookup(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
512}
513
514static char mfs_plb_get_char(unsigned pos)
515{
516 return mfs_reg.plb_ro[pos % PLB_SIZE];
517}
518
519static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
520{
521 struct mfs_node *parent = pfn->data;
522 struct mfs_node *child = cfn->data;
523 struct mfs_sb_info *sbi = parent->instance->sbi;
524
525 mfsdebug("mfs_link() %d\n", (int) child->ino_i->index);
526
527 if (str_size(name) > sbi->max_name_len)
528 return ENAMETOOLONG;
529
530 int r = insert_dentry(parent, name, child->ino_i->index);
531
532 return r;
533}
534
535static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
536{
537 struct mfs_node *mnode = fsnode->data;
538 int r;
539
540 *has_children = false;
541
542 mfsdebug("mfs_has_children()\n");
543
544 if (!S_ISDIR(mnode->ino_i->i_mode))
545 goto out;
546
547 struct mfs_dentry_info *d_info;
548
549 /* The first two dentries are always . and .. */
550 int i = 2;
551 while (1) {
552 r = read_directory_entry(mnode, &d_info, i++);
553 on_error(r, return r);
554
555 if (!d_info) {
556 /*Reached the end of the dentries list*/
557 break;
558 }
559
560 if (d_info->d_inum) {
561 /*A valid entry has been found*/
562 *has_children = true;
563 free(d_info);
564 break;
565 }
566
567 free(d_info);
568 }
569
570out:
571
572 if (*has_children) {
573 mfsdebug("Has children\n");
574 } else {
575 mfsdebug("Has not children\n");
576 }
577
578 return EOK;
579}
580
581void
582mfs_read(ipc_callid_t rid, ipc_call_t *request)
583{
584 int rc;
585 devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(*request);
586 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
587 aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request),
588 IPC_GET_ARG4(*request));
589 fs_node_t *fn;
590
591 mfsdebug("mfs_read()\n");
592
593 rc = mfs_node_get(&fn, handle, index);
594 if (rc != EOK) {
595 async_answer_0(rid, rc);
596 return;
597 }
598 if (!fn) {
599 async_answer_0(rid, ENOENT);
600 return;
601 }
602
603 struct mfs_node *mnode;
604 struct mfs_ino_info *ino_i;
605 size_t len, bytes = 0;
606 ipc_callid_t callid;
607
608 mnode = fn->data;
609 ino_i = mnode->ino_i;
610
611 if (!async_data_read_receive(&callid, &len)) {
612 rc = EINVAL;
613 goto out_error;
614 }
615
616 if (S_ISDIR(ino_i->i_mode)) {
617 aoff64_t spos = pos;
618 struct mfs_dentry_info *d_info;
619
620 while (1) {
621 rc = read_directory_entry(mnode, &d_info, pos);
622 on_error(rc, goto out_error);
623
624 if (!d_info) {
625 /*Reached the end of the dentries list*/
626 break;
627 }
628
629 if (d_info->d_inum) {
630 /*Dentry found!*/
631 mfsdebug("DENTRY FOUND %s!!\n", d_info->d_name);
632 goto found;
633 }
634
635 free(d_info);
636 pos++;
637 }
638
639 rc = mfs_node_put(fn);
640 async_answer_0(callid, rc != EOK ? rc : ENOENT);
641 async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
642 return;
643found:
644 async_data_read_finalize(callid, d_info->d_name,
645 str_size(d_info->d_name) + 1);
646 bytes = ((pos - spos) + 1);
647 } else {
648 struct mfs_sb_info *sbi = mnode->instance->sbi;
649
650 if (pos >= (size_t) ino_i->i_size) {
651 /*Trying to read beyond the end of file*/
652 bytes = 0;
653 (void) async_data_read_finalize(callid, NULL, 0);
654 goto out_success;
655 }
656
657 bytes = min(len, sbi->block_size - pos % sbi->block_size);
658 bytes = min(bytes, ino_i->i_size - pos);
659
660 uint32_t zone;
661 block_t *b;
662
663 rc = read_map(&zone, mnode, pos);
664 on_error(rc, goto out_error);
665
666 if (zone == 0) {
667 /*sparse file*/
668 uint8_t *buf = malloc(sbi->block_size);
669 if (!buf) {
670 rc = ENOMEM;
671 goto out_error;
672 }
673 memset(buf, 0, sizeof(sbi->block_size));
674 async_data_read_finalize(callid,
675 buf + pos % sbi->block_size, bytes);
676 free(buf);
677 goto out_success;
678 }
679
680 rc = block_get(&b, handle, zone, BLOCK_FLAGS_NONE);
681 on_error(rc, goto out_error);
682
683 async_data_read_finalize(callid, b->data +
684 pos % sbi->block_size, bytes);
685
686 rc = block_put(b);
687 if (rc != EOK) {
688 mfs_node_put(fn);
689 async_answer_0(rid, rc);
690 return;
691 }
692 }
693out_success:
694 rc = mfs_node_put(fn);
695 async_answer_1(rid, rc, (sysarg_t)bytes);
696 return;
697out_error:
698 ;
699 int tmp = mfs_node_put(fn);
700 async_answer_0(callid, tmp != EOK ? tmp : rc);
701 async_answer_0(rid, tmp != EOK ? tmp : rc);
702}
703
704void
705mfs_write(ipc_callid_t rid, ipc_call_t *request)
706{
707 mfsdebug("mfs_write()\n");
708
709 devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(*request);
710 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
711 aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request),
712 IPC_GET_ARG4(*request));
713
714 fs_node_t *fn;
715 int r;
716 int flags = BLOCK_FLAGS_NONE;
717
718 r = mfs_node_get(&fn, handle, index);
719 if (r != EOK) {
720 async_answer_0(rid, r);
721 return;
722 }
723
724 if (!fn) {
725 async_answer_0(rid, ENOENT);
726 return;
727 }
728
729 ipc_callid_t callid;
730 size_t len;
731
732 if (!async_data_write_receive(&callid, &len)) {
733 r = EINVAL;
734 goto out_err;
735 }
736
737 struct mfs_node *mnode = fn->data;
738 struct mfs_sb_info *sbi = mnode->instance->sbi;
739 struct mfs_ino_info *ino_i = mnode->ino_i;
740 const size_t bs = sbi->block_size;
741 size_t bytes = min(len, bs - pos % bs);
742 size_t boundary = ROUND_UP(ino_i->i_size, bs);
743 uint32_t block;
744
745 if (bytes == bs)
746 flags = BLOCK_FLAGS_NOREAD;
747
748 if (pos < boundary) {
749 r = read_map(&block, mnode, pos);
750 on_error(r, goto out_err);
751
752 if (block == 0) {
753 /*Writing in a sparse block*/
754 r = mfs_alloc_bit(mnode->instance, &block, BMAP_ZONE);
755 on_error(r, goto out_err);
756 flags = BLOCK_FLAGS_NOREAD;
757 }
758 } else {
759 uint32_t dummy;
760
761 r = mfs_alloc_bit(mnode->instance, &block, BMAP_ZONE);
762 on_error(r, goto out_err);
763
764 r = write_map(mnode, pos, block, &dummy);
765 on_error(r, goto out_err);
766 }
767
768 block_t *b;
769 r = block_get(&b, handle, block, flags);
770 on_error(r, goto out_err);
771
772 async_data_write_finalize(callid, b->data + pos % bs, bytes);
773 b->dirty = true;
774
775 r = block_put(b);
776 if (r != EOK) {
777 mfs_node_put(fn);
778 async_answer_0(rid, r);
779 return;
780 }
781
782 ino_i->i_size = pos + bytes;
783 ino_i->dirty = true;
784 r = mfs_node_put(fn);
785 async_answer_2(rid, r, bytes, pos + bytes);
786 return;
787
788out_err:
789 mfs_node_put(fn);
790 async_answer_0(callid, r);
791 async_answer_0(rid, r);
792}
793
794void
795mfs_truncate(ipc_callid_t rid, ipc_call_t *request)
796{
797 devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(*request);
798 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
799 aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request),
800 IPC_GET_ARG4(*request));
801 fs_node_t *fn;
802 int r;
803
804 mfsdebug("mfs_truncate()\n");
805
806 r = mfs_node_get(&fn, handle, index);
807 if (r != EOK) {
808 async_answer_0(rid, r);
809 return;
810 }
811
812 if (!fn) {
813 async_answer_0(rid, r);
814 return;
815 }
816
817 struct mfs_node *mnode = fn->data;
818 struct mfs_ino_info *ino_i = mnode->ino_i;
819
820 if (ino_i->i_size == size)
821 r = EOK;
822 else
823 r = inode_shrink(mnode, ino_i->i_size - size);
824
825 async_answer_0(rid, r);
826 mfs_node_put(fn);
827}
828
829int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
830{
831 link_t *link;
832 struct mfs_instance *instance_ptr;
833
834 fibril_mutex_lock(&inst_list_mutex);
835
836 for (link = inst_list.next; link != &inst_list; link = link->next) {
837 instance_ptr = list_get_instance(link, struct mfs_instance,
838 link);
839
840 if (instance_ptr->handle == handle) {
841 *instance = instance_ptr;
842 fibril_mutex_unlock(&inst_list_mutex);
843 return EOK;
844 }
845 }
846
847 mfsdebug("Instance not found\n");
848
849 fibril_mutex_unlock(&inst_list_mutex);
850 return EINVAL;
851}
852
853static bool check_magic_number(uint16_t magic, bool *native,
854 mfs_version_t *version, bool *longfilenames)
855{
856 bool rc = true;
857 *longfilenames = false;
858
859 if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
860 *native = magic == MFS_MAGIC_V1;
861 *version = MFS_VERSION_V1;
862 } else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
863 *native = magic == MFS_MAGIC_V1L;
864 *version = MFS_VERSION_V1;
865 *longfilenames = true;
866 } else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
867 *native = magic == MFS_MAGIC_V2;
868 *version = MFS_VERSION_V2;
869 } else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
870 *native = magic == MFS_MAGIC_V2L;
871 *version = MFS_VERSION_V2;
872 *longfilenames = true;
873 } else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
874 *native = magic == MFS_MAGIC_V3;
875 *version = MFS_VERSION_V3;
876 } else
877 rc = false;
878
879 return rc;
880}
881
882void
883mfs_close(ipc_callid_t rid, ipc_call_t *request)
884{
885 async_answer_0(rid, EOK);
886}
887
888void
889mfs_open_node(ipc_callid_t rid, ipc_call_t *request)
890{
891 libfs_open_node(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
892}
893
894/**
895 * @}
896 */
897
Note: See TracBrowser for help on using the repository browser.