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

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

unmount fix: remove the instance pointer from the list of instances, free the superblock reserved memory.

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