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

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

Add the mfs_write() function implementation.

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