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

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

cstyle

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