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

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

Remove wrong assertions

  • Property mode set to 100644
File size: 13.3 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);
59
60static
61int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
62 fs_index_t index);
63
64
65static LIST_INITIALIZE(inst_list);
66static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
67
68libfs_ops_t mfs_libfs_ops = {
69 .size_get = mfs_size_get,
70 .root_get = mfs_root_get,
71 .device_get = mfs_device_get,
72 .is_directory = mfs_is_directory,
73 .is_file = mfs_is_file,
74 .node_get = mfs_node_get,
75 .node_put = mfs_node_put,
76 .node_open = mfs_node_open,
77 .index_get = mfs_index_get,
78 .match = mfs_match,
79 .create = mfs_create_node,
80 .plb_get_char = mfs_plb_get_char,
81 .has_children = mfs_has_children,
82 .lnkcnt_get = mfs_lnkcnt_get
83};
84
85void mfs_mounted(ipc_callid_t rid, ipc_call_t *request)
86{
87 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
88 enum cache_mode cmode;
89 struct mfs_superblock *sb;
90 struct mfs3_superblock *sb3;
91 struct mfs_sb_info *sbi;
92 struct mfs_instance *instance;
93 bool native, longnames;
94 mfs_version_t version;
95 uint16_t magic;
96
97 /* Accept the mount options */
98 char *opts;
99 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
100
101 if (rc != EOK) {
102 mfsdebug("Can't accept async data write\n");
103 async_answer_0(rid, rc);
104 return;
105 }
106
107 /* Check for option enabling write through. */
108 if (str_cmp(opts, "wtcache") == 0)
109 cmode = CACHE_MODE_WT;
110 else
111 cmode = CACHE_MODE_WB;
112
113 free(opts);
114
115 /* initialize libblock */
116 rc = block_init(devmap_handle, 1024);
117 if (rc != EOK) {
118 mfsdebug("libblock initialization failed\n");
119 async_answer_0(rid, rc);
120 return;
121 }
122
123 /*Allocate space for generic MFS superblock*/
124 sbi = malloc(sizeof(*sbi));
125
126 if (!sbi) {
127 async_answer_0(rid, ENOMEM);
128 return;
129 }
130
131 /*Allocate space for filesystem instance*/
132 instance = malloc(sizeof(*instance));
133
134 if (!instance) {
135 async_answer_0(rid, ENOMEM);
136 return;
137 }
138
139 sb = malloc(MFS_SUPERBLOCK_SIZE);
140
141 if (!sb) {
142 async_answer_0(rid, ENOMEM);
143 return;
144 }
145
146 /* Read the superblock */
147 rc = block_read_direct(devmap_handle, MFS_SUPERBLOCK << 1, 1, sb);
148 if (rc != EOK) {
149 block_fini(devmap_handle);
150 async_answer_0(rid, rc);
151 return;
152 }
153
154 sb3 = (struct mfs3_superblock *) sb;
155
156 if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
157 /*This is a V1 or V2 Minix filesystem*/
158 magic = sb->s_magic;
159 goto recognized;
160 }
161
162 if (!check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
163 mfsdebug("magic number not recognized\n");
164 block_fini(devmap_handle);
165 async_answer_0(rid, ENOTSUP);
166 return;
167 }
168
169 /*This is a V3 Minix filesystem*/
170
171 magic = sb3->s_magic;
172
173recognized:
174
175 mfsdebug("magic number recognized = %04x\n", magic);
176
177 /*Fill superblock info structure*/
178
179 sbi->fs_version = version;
180 sbi->long_names = longnames;
181 sbi->native = native;
182 sbi->magic = magic;
183 sbi->isearch = 0;
184 sbi->zsearch = 0;
185
186 if (version == MFS_VERSION_V3) {
187 sbi->ninodes = conv32(native, sb3->s_ninodes);
188 sbi->ibmap_blocks = conv16(native, sb3->s_ibmap_blocks);
189 sbi->zbmap_blocks = conv16(native, sb3->s_zbmap_blocks);
190 sbi->firstdatazone = conv16(native, sb3->s_first_data_zone);
191 sbi->log2_zone_size = conv16(native, sb3->s_log2_zone_size);
192 sbi->max_file_size = conv32(native, sb3->s_max_file_size);
193 sbi->nzones = conv32(native, sb3->s_nzones);
194 sbi->block_size = conv16(native, sb3->s_block_size);
195 sbi->ino_per_block = V3_INODES_PER_BLOCK(sbi->block_size);
196 sbi->dirsize = MFS3_DIRSIZE;
197 sbi->max_name_len = MFS3_MAX_NAME_LEN;
198 } else {
199 sbi->ninodes = conv16(native, sb->s_ninodes);
200 sbi->ibmap_blocks = conv16(native, sb->s_ibmap_blocks);
201 sbi->zbmap_blocks = conv16(native, sb->s_zbmap_blocks);
202 sbi->firstdatazone = conv16(native, sb->s_first_data_zone);
203 sbi->log2_zone_size = conv16(native, sb->s_log2_zone_size);
204 sbi->max_file_size = conv32(native, sb->s_max_file_size);
205 sbi->nzones = conv16(native, sb->s_nzones);
206 sbi->block_size = MFS_BLOCKSIZE;
207 sbi->ino_per_block = V1_INODES_PER_BLOCK;
208 if (version == MFS_VERSION_V2)
209 sbi->nzones = conv32(native, sb->s_nzones2);
210 sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
211 sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
212 MFS_MAX_NAME_LEN;
213 }
214 sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
215
216 free(sb);
217
218 rc = block_cache_init(devmap_handle, sbi->block_size, 0, cmode);
219
220 if (rc != EOK) {
221 block_fini(devmap_handle);
222 async_answer_0(rid, EINVAL);
223 mfsdebug("block cache initialization failed\n");
224 return;
225 }
226
227 /*Initialize the instance structure and add it to the list*/
228 link_initialize(&instance->link);
229 instance->handle = devmap_handle;
230 instance->sbi = sbi;
231
232 fibril_mutex_lock(&inst_list_mutex);
233 list_append(&instance->link, &inst_list);
234 fibril_mutex_unlock(&inst_list_mutex);
235
236 mfsdebug("mount successful\n");
237
238 async_answer_0(rid, EOK);
239}
240
241void mfs_mount(ipc_callid_t rid, ipc_call_t *request)
242{
243 libfs_mount(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
244}
245
246devmap_handle_t mfs_device_get(fs_node_t *fsnode)
247{
248 struct mfs_node *node = fsnode->data;
249 return node->instance->handle;
250}
251
252static int mfs_create_node(fs_node_t **rfn, devmap_handle_t handle, int flags)
253{
254 mfsdebug("create_node()\n");
255 return ENOTSUP;
256}
257
258static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
259{
260 struct mfs_node *mnode = pfn->data;
261 struct mfs_ino_info *ino_i = mnode->ino_i;
262 struct mfs_dentry_info *d_info;
263
264 if (!S_ISDIR(ino_i->i_mode))
265 return ENOTDIR;
266
267 mfsdebug("mfs_match()\n");
268
269 struct mfs_sb_info *sbi = mnode->instance->sbi;
270 const size_t comp_size = str_size(component);
271
272 int i = 2;
273 while (1) {
274 d_info = read_directory_entry(mnode, i++);
275 if (!d_info) {
276 /*Reached the end of the directory entry list*/
277 break;
278 }
279
280 if (!d_info->d_inum) {
281 /*This entry is not used*/
282 free(d_info);
283 continue;
284 }
285
286 if (!bcmp(component, d_info->d_name, min(sbi->max_name_len,
287 comp_size))) {
288 /*Hit!*/
289 mfs_node_core_get(rfn, mnode->instance,
290 d_info->d_inum);
291 free(d_info);
292 goto found;
293 }
294 free(d_info);
295 }
296 *rfn = NULL;
297 return ENOENT;
298found:
299 return EOK;
300}
301
302static aoff64_t mfs_size_get(fs_node_t *node)
303{
304 assert(node);
305
306 const struct mfs_node *mnode = node->data;
307 assert(mnode);
308 assert(mnode->ino_i);
309
310 mfsdebug("inode size is %d\n", (int) mnode->ino_i->i_size);
311
312 return mnode->ino_i->i_size;
313}
314
315void mfs_stat(ipc_callid_t rid, ipc_call_t *request)
316{
317 mfsdebug("mfs_stat()\n");
318 libfs_stat(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
319}
320
321static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
322 fs_index_t index)
323{
324 int rc;
325 struct mfs_instance *instance;
326
327 mfsdebug("mfs_node_get()\n");
328
329 rc = mfs_instance_get(devmap_handle, &instance);
330
331 if (rc != EOK)
332 return rc;
333
334 return mfs_node_core_get(rfn, instance, index);
335}
336
337static int mfs_node_put(fs_node_t *fsnode)
338{
339 struct mfs_node *mnode = fsnode->data;
340
341 mfsdebug("mfs_node_put()\n");
342
343 put_inode(mnode);
344 free(mnode->ino_i);
345 free(mnode);
346
347 return EOK;
348}
349
350static int mfs_node_open(fs_node_t *fsnode)
351{
352 /*
353 * Opening a file is stateless, nothing
354 * to be done here.
355 */
356 return EOK;
357}
358
359static fs_index_t mfs_index_get(fs_node_t *fsnode)
360{
361 struct mfs_node *mnode = fsnode->data;
362
363 mfsdebug("mfs_index_get()\n");
364
365 assert(mnode->ino_i);
366 return mnode->ino_i->index;
367}
368
369static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
370{
371 unsigned rc;
372 struct mfs_node *mnode = fsnode->data;
373
374 assert(mnode);
375 assert(mnode->ino_i);
376
377 rc = mnode->ino_i->i_nlinks;
378 mfsdebug("mfs_lnkcnt_get(): %u\n", rc);
379 return rc;
380}
381
382static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
383 fs_index_t index)
384{
385 fs_node_t *node = NULL;
386 struct mfs_node *mnode = NULL;
387 int rc;
388
389 node = malloc(sizeof(fs_node_t));
390 if (!node) {
391 rc = ENOMEM;
392 goto out_err;
393 }
394
395 fs_node_initialize(node);
396
397 mnode = malloc(sizeof(*mnode));
398 if (!mnode) {
399 rc = ENOMEM;
400 goto out_err;
401 }
402
403 struct mfs_ino_info *ino_i;
404
405 rc = get_inode(inst, &ino_i, index);
406 if (rc != EOK)
407 goto out_err;
408
409 ino_i->index = index;
410 mnode->ino_i = ino_i;
411
412 mnode->instance = inst;
413 node->data = mnode;
414 *rfn = node;
415
416 mfsdebug("node_get_core(%d) OK\n", (int) index);
417
418 return EOK;
419
420out_err:
421 if (node)
422 free(node);
423 if (mnode)
424 free(mnode);
425 return rc;
426}
427
428static bool mfs_is_directory(fs_node_t *fsnode)
429{
430 const struct mfs_node *node = fsnode->data;
431 return S_ISDIR(node->ino_i->i_mode);
432}
433
434static bool mfs_is_file(fs_node_t *fsnode)
435{
436 struct mfs_node *node = fsnode->data;
437 return S_ISREG(node->ino_i->i_mode);
438}
439
440static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle)
441{
442 int rc = mfs_node_get(rfn, handle, MFS_ROOT_INO);
443
444 mfsdebug("mfs_root_get %s\n", rc == EOK ? "OK" : "FAIL");
445 return rc;
446}
447
448void mfs_lookup(ipc_callid_t rid, ipc_call_t *request)
449{
450 libfs_lookup(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
451}
452
453static char mfs_plb_get_char(unsigned pos)
454{
455 return mfs_reg.plb_ro[pos % PLB_SIZE];
456}
457
458static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
459{
460 struct mfs_node *mnode = fsnode->data;
461
462 *has_children = false;
463
464 if (!S_ISDIR(mnode->ino_i->i_mode))
465 goto out;
466
467 struct mfs_dentry_info *d_info;
468
469 /* The first two dentries are always . and .. */
470 int i = 2;
471 while (1) {
472 d_info = read_directory_entry(mnode, i++);
473
474 if (!d_info) {
475 /*Reached the end of the dentries list*/
476 break;
477 }
478
479 if (d_info->d_inum) {
480 /*A valid entry has been found*/
481 *has_children = true;
482 free(d_info);
483 break;
484 }
485
486 free(d_info);
487 }
488
489out:
490
491 if (*has_children)
492 mfsdebug("Has children\n");
493 else
494 mfsdebug("Has not children\n");
495
496 return EOK;
497}
498
499/*
500 * Find a filesystem instance given the devmap handle
501 */
502int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
503{
504 link_t *link;
505 struct mfs_instance *instance_ptr;
506
507 fibril_mutex_lock(&inst_list_mutex);
508
509 for (link = inst_list.next; link != &inst_list; link = link->next) {
510 instance_ptr = list_get_instance(link, struct mfs_instance,
511 link);
512
513 if (instance_ptr->handle == handle) {
514 *instance = instance_ptr;
515 fibril_mutex_unlock(&inst_list_mutex);
516 return EOK;
517 }
518 }
519
520 mfsdebug("Instance not found\n");
521
522 fibril_mutex_unlock(&inst_list_mutex);
523 return EINVAL;
524}
525
526static bool check_magic_number(uint16_t magic, bool *native,
527 mfs_version_t *version, bool *longfilenames)
528{
529 bool rc = false;
530 *longfilenames = false;
531
532 if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
533 *native = magic == MFS_MAGIC_V1;
534 *version = MFS_VERSION_V1;
535 rc = true;
536 } else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
537 *native = magic == MFS_MAGIC_V1L;
538 *version = MFS_VERSION_V1;
539 *longfilenames = true;
540 rc = true;
541 } else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
542 *native = magic == MFS_MAGIC_V2;
543 *version = MFS_VERSION_V2;
544 rc = true;
545 } else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
546 *native = magic == MFS_MAGIC_V2L;
547 *version = MFS_VERSION_V2;
548 *longfilenames = true;
549 rc = true;
550 } else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
551 *native = magic == MFS_MAGIC_V3;
552 *version = MFS_VERSION_V3;
553 rc = true;
554 }
555
556 return rc;
557}
558
559/**
560 * @}
561 */
562
Note: See TracBrowser for help on using the repository browser.