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

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

Fix some debug messages

  • Property mode set to 100644
File size: 14.7 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 "mfs.h"
39#include "mfs_utils.h"
40
41static bool check_magic_number(uint16_t magic, bool *native,
42 mfs_version_t *version, bool *longfilenames);
43static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
44 fs_index_t index);
45
46static int mfs_node_put(fs_node_t *fsnode);
47static int mfs_node_open(fs_node_t *fsnode);
48static fs_index_t mfs_index_get(fs_node_t *fsnode);
49static unsigned mfs_lnkcnt_get(fs_node_t *fsnode);
50static char mfs_plb_get_char(unsigned pos);
51static bool mfs_is_directory(fs_node_t *fsnode);
52static bool mfs_is_file(fs_node_t *fsnode);
53static int mfs_has_children(bool *has_children, fs_node_t *fsnode);
54static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle);
55static devmap_handle_t mfs_device_get(fs_node_t *fsnode);
56static aoff64_t mfs_size_get(fs_node_t *node);
57static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component);
58static int mfs_create_node(fs_node_t **rfn, devmap_handle_t handle, int flags);
59static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name);
60
61static
62int 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->nzones = conv16(native, sb->s_nzones);
208 sbi->block_size = MFS_BLOCKSIZE;
209 sbi->ino_per_block = V1_INODES_PER_BLOCK;
210 if (version == MFS_VERSION_V2)
211 sbi->nzones = conv32(native, sb->s_nzones2);
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 if (r != EOK)
266 return r;
267
268 if (flags & L_DIRECTORY) {
269 /*Not yet supported*/
270 return ENOTSUP;
271 }
272
273 /*Alloc a new inode*/
274 r = mfs_alloc_bit(inst, &inum, BMAP_INODE);
275 if (r != EOK)
276 return r;
277
278 struct mfs_ino_info *ino_i;
279
280 ino_i = malloc(sizeof(*ino_i));
281 if (!ino_i) {
282 r = ENOMEM;
283 goto out_err;
284 }
285
286 mnode = malloc(sizeof(*mnode));
287 if (!mnode) {
288 r = ENOMEM;
289 goto out_err_1;
290 }
291
292 fsnode = malloc(sizeof(fs_node_t));
293 if (!fsnode) {
294 r = ENOMEM;
295 goto out_err_2;
296 }
297
298 ino_i->i_mode = S_IFREG;
299 ino_i->i_nlinks = 1;
300 ino_i->i_uid = 0;
301 ino_i->i_gid = 0;
302 ino_i->i_size = 0;
303 ino_i->i_atime = 0;
304 ino_i->i_mtime = 0;
305 ino_i->i_ctime = 0;
306
307 memset(ino_i->i_dzone, 0, sizeof(uint32_t) * V2_NR_DIRECT_ZONES);
308 memset(ino_i->i_izone, 0, sizeof(uint32_t) * V2_NR_INDIRECT_ZONES);
309
310 ino_i->index = inum;
311 ino_i->dirty = true;
312 mnode->ino_i = ino_i;
313 mnode->instance = inst;
314
315 put_inode(mnode);
316
317 fs_node_initialize(fsnode);
318 fsnode->data = mnode;
319 *rfn = fsnode;
320
321 return EOK;
322
323out_err_2:
324 free(mnode);
325out_err_1:
326 free(ino_i);
327out_err:
328 return r;
329}
330
331static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
332{
333 struct mfs_node *mnode = pfn->data;
334 struct mfs_ino_info *ino_i = mnode->ino_i;
335 struct mfs_dentry_info *d_info;
336
337 mfsdebug("mfs_match()\n");
338
339 if (!S_ISDIR(ino_i->i_mode))
340 return ENOTDIR;
341
342 struct mfs_sb_info *sbi = mnode->instance->sbi;
343 const size_t comp_size = str_size(component);
344
345 int i = 2;
346 while (1) {
347 d_info = read_directory_entry(mnode, i++);
348 if (!d_info) {
349 /*Reached the end of the directory entry list*/
350 break;
351 }
352
353 if (!d_info->d_inum) {
354 /*This entry is not used*/
355 free(d_info);
356 continue;
357 }
358
359 if (!bcmp(component, d_info->d_name, min(sbi->max_name_len,
360 comp_size))) {
361 /*Hit!*/
362 mfs_node_core_get(rfn, mnode->instance,
363 d_info->d_inum);
364 free(d_info);
365 goto found;
366 }
367 free(d_info);
368 }
369 *rfn = NULL;
370 return ENOENT;
371found:
372 return EOK;
373}
374
375static aoff64_t mfs_size_get(fs_node_t *node)
376{
377 assert(node);
378
379 const struct mfs_node *mnode = node->data;
380 assert(mnode);
381 assert(mnode->ino_i);
382
383 mfsdebug("inode links = %d\n", (int) mnode->ino_i->i_nlinks);
384 mfsdebug("inode size is %d\n", (int) mnode->ino_i->i_size);
385
386 return mnode->ino_i->i_size;
387}
388
389void mfs_stat(ipc_callid_t rid, ipc_call_t *request)
390{
391 mfsdebug("mfs_stat()\n");
392 libfs_stat(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
393}
394
395static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
396 fs_index_t index)
397{
398 int rc;
399 struct mfs_instance *instance;
400
401 mfsdebug("mfs_node_get()\n");
402
403 rc = mfs_instance_get(devmap_handle, &instance);
404
405 if (rc != EOK)
406 return rc;
407
408 return mfs_node_core_get(rfn, instance, index);
409}
410
411static int mfs_node_put(fs_node_t *fsnode)
412{
413 struct mfs_node *mnode = fsnode->data;
414
415 mfsdebug("mfs_node_put()\n");
416
417 put_inode(mnode);
418 free(mnode->ino_i);
419 free(mnode);
420
421 return EOK;
422}
423
424static int mfs_node_open(fs_node_t *fsnode)
425{
426 /*
427 * Opening a file is stateless, nothing
428 * to be done here.
429 */
430 return EOK;
431}
432
433static fs_index_t mfs_index_get(fs_node_t *fsnode)
434{
435 struct mfs_node *mnode = fsnode->data;
436
437 mfsdebug("mfs_index_get()\n");
438
439 assert(mnode->ino_i);
440 return mnode->ino_i->index;
441}
442
443static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
444{
445 unsigned rc;
446 struct mfs_node *mnode = fsnode->data;
447
448 assert(mnode);
449 assert(mnode->ino_i);
450
451 rc = mnode->ino_i->i_nlinks;
452 mfsdebug("mfs_lnkcnt_get(): %u\n", rc);
453 return rc;
454}
455
456static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
457 fs_index_t index)
458{
459 fs_node_t *node = NULL;
460 struct mfs_node *mnode = NULL;
461 int rc;
462
463 node = malloc(sizeof(fs_node_t));
464 if (!node) {
465 rc = ENOMEM;
466 goto out_err;
467 }
468
469 fs_node_initialize(node);
470
471 mnode = malloc(sizeof(*mnode));
472 if (!mnode) {
473 rc = ENOMEM;
474 goto out_err;
475 }
476
477 struct mfs_ino_info *ino_i;
478
479 rc = get_inode(inst, &ino_i, index);
480 if (rc != EOK)
481 goto out_err;
482
483 ino_i->index = index;
484 mnode->ino_i = ino_i;
485
486 mnode->instance = inst;
487 node->data = mnode;
488 *rfn = node;
489
490 mfsdebug("node_get_core(%d) OK\n", (int) index);
491
492 return EOK;
493
494out_err:
495 if (node)
496 free(node);
497 if (mnode)
498 free(mnode);
499 return rc;
500}
501
502static bool mfs_is_directory(fs_node_t *fsnode)
503{
504 const struct mfs_node *node = fsnode->data;
505 return S_ISDIR(node->ino_i->i_mode);
506}
507
508static bool mfs_is_file(fs_node_t *fsnode)
509{
510 struct mfs_node *node = fsnode->data;
511 return S_ISREG(node->ino_i->i_mode);
512}
513
514static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle)
515{
516 int rc = mfs_node_get(rfn, handle, MFS_ROOT_INO);
517
518 mfsdebug("mfs_root_get %s\n", rc == EOK ? "OK" : "FAIL");
519 return rc;
520}
521
522void mfs_lookup(ipc_callid_t rid, ipc_call_t *request)
523{
524 libfs_lookup(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
525}
526
527static char mfs_plb_get_char(unsigned pos)
528{
529 return mfs_reg.plb_ro[pos % PLB_SIZE];
530}
531
532static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
533{
534 mfsdebug("mfs_link()\n");
535 return ENOTSUP;
536}
537
538static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
539{
540 struct mfs_node *mnode = fsnode->data;
541
542 *has_children = false;
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 d_info = read_directory_entry(mnode, i++);
553
554 if (!d_info) {
555 /*Reached the end of the dentries list*/
556 break;
557 }
558
559 if (d_info->d_inum) {
560 /*A valid entry has been found*/
561 *has_children = true;
562 free(d_info);
563 break;
564 }
565
566 free(d_info);
567 }
568
569out:
570
571 if (*has_children)
572 mfsdebug("Has children\n");
573 else
574 mfsdebug("Has not children\n");
575
576 return EOK;
577}
578
579/*
580 * Find a filesystem instance given the devmap handle
581 */
582int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
583{
584 link_t *link;
585 struct mfs_instance *instance_ptr;
586
587 fibril_mutex_lock(&inst_list_mutex);
588
589 for (link = inst_list.next; link != &inst_list; link = link->next) {
590 instance_ptr = list_get_instance(link, struct mfs_instance,
591 link);
592
593 if (instance_ptr->handle == handle) {
594 *instance = instance_ptr;
595 fibril_mutex_unlock(&inst_list_mutex);
596 return EOK;
597 }
598 }
599
600 mfsdebug("Instance not found\n");
601
602 fibril_mutex_unlock(&inst_list_mutex);
603 return EINVAL;
604}
605
606static bool check_magic_number(uint16_t magic, bool *native,
607 mfs_version_t *version, bool *longfilenames)
608{
609 bool rc = false;
610 *longfilenames = false;
611
612 if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
613 *native = magic == MFS_MAGIC_V1;
614 *version = MFS_VERSION_V1;
615 rc = true;
616 } else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
617 *native = magic == MFS_MAGIC_V1L;
618 *version = MFS_VERSION_V1;
619 *longfilenames = true;
620 rc = true;
621 } else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
622 *native = magic == MFS_MAGIC_V2;
623 *version = MFS_VERSION_V2;
624 rc = true;
625 } else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
626 *native = magic == MFS_MAGIC_V2L;
627 *version = MFS_VERSION_V2;
628 *longfilenames = true;
629 rc = true;
630 } else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
631 *native = magic == MFS_MAGIC_V3;
632 *version = MFS_VERSION_V3;
633 rc = true;
634 }
635
636 return rc;
637}
638
639/**
640 * @}
641 */
642
Note: See TracBrowser for help on using the repository browser.