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
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
[92dd5c8]33#include <stdio.h>
[9e3dc95]34#include <stdlib.h>
[0d6ab10]35#include <assert.h>
[953a823]36#include <fibril_synch.h>
[9e3dc95]37#include <errno.h>
[7413683]38#include "mfs.h"
[9e3dc95]39#include "mfs_utils.h"
40
[8ceba1e]41static bool check_magic_number(uint16_t magic, bool *native,
42 mfs_version_t *version, bool *longfilenames);
[44c0f5b]43static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
44 fs_index_t index);
[096c8835]45
[41202a9]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);
[ac28650]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
[41202a9]62
[953a823]63static LIST_INITIALIZE(inst_list);
64static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
65
[e54ba607]66libfs_ops_t mfs_libfs_ops = {
[0d6ab10]67 .size_get = mfs_size_get,
[fe4ac35]68 .root_get = mfs_root_get,
[5a58ae2]69 .device_get = mfs_device_get,
[7d04324]70 .is_directory = mfs_is_directory,
[44c0f5b]71 .is_file = mfs_is_file,
[cfbcd86]72 .node_get = mfs_node_get,
[41202a9]73 .node_put = mfs_node_put,
74 .node_open = mfs_node_open,
75 .index_get = mfs_index_get,
[54caa41b]76 .plb_get_char = mfs_plb_get_char,
[41202a9]77 .has_children = mfs_has_children,
78 .lnkcnt_get = mfs_lnkcnt_get
[e54ba607]79};
[3b08178]80
[096c8835]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;
[953a823]85 struct mfs_superblock *sb;
86 struct mfs3_superblock *sb3;
87 struct mfs_sb_info *sbi;
88 struct mfs_instance *instance;
[8ceba1e]89 bool native, longnames;
[9e3dc95]90 mfs_version_t version;
[245eb02d]91 uint16_t magic;
[096c8835]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) {
[92dd5c8]98 mfsdebug("Can't accept async data write\n");
[096c8835]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 */
[92dd5c8]112 rc = block_init(devmap_handle, 1024);
[096c8835]113 if (rc != EOK) {
[92dd5c8]114 mfsdebug("libblock initialization failed\n");
[096c8835]115 async_answer_0(rid, rc);
116 return;
117 }
118
[953a823]119 /*Allocate space for generic MFS superblock*/
[b438804]120 sbi = malloc(sizeof(*sbi));
[953a823]121
122 if (!sbi) {
123 async_answer_0(rid, ENOMEM);
124 return;
125 }
126
127 /*Allocate space for filesystem instance*/
[b438804]128 instance = malloc(sizeof(*instance));
[953a823]129
130 if (!instance) {
131 async_answer_0(rid, ENOMEM);
132 return;
133 }
134
[b438804]135 sb = malloc(MFS_SUPERBLOCK_SIZE);
[953a823]136
137 if (!sb) {
138 async_answer_0(rid, ENOMEM);
139 return;
140 }
[92dd5c8]141
142 /* Read the superblock */
[953a823]143 rc = block_read_direct(devmap_handle, MFS_SUPERBLOCK << 1, 1, sb);
[096c8835]144 if (rc != EOK) {
145 block_fini(devmap_handle);
146 async_answer_0(rid, rc);
147 return;
148 }
149
[953a823]150 sb3 = (struct mfs3_superblock *) sb;
151
152 if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
[7a96476]153 /*This is a V1 or V2 Minix filesystem*/
[953a823]154 magic = sb->s_magic;
[245eb02d]155 goto recognized;
156 }
157
[953a823]158 if (!check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
[92dd5c8]159 mfsdebug("magic number not recognized\n");
[9e3dc95]160 block_fini(devmap_handle);
161 async_answer_0(rid, ENOTSUP);
162 return;
163 }
[92dd5c8]164
[7a96476]165 /*This is a V3 Minix filesystem*/
166
[953a823]167 magic = sb3->s_magic;
[245eb02d]168
169recognized:
170
171 mfsdebug("magic number recognized = %04x\n", magic);
[953a823]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;
[ef76d72]179 sbi->isearch = 0;
180 sbi->zsearch = 0;
[953a823]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);
[a04b62d]191 sbi->dirsize = MFS3_DIRSIZE;
[953a823]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);
[3b08178]200 sbi->block_size = MFS_BLOCKSIZE;
[953a823]201 if (version == MFS_VERSION_V2)
202 sbi->nzones = conv32(native, sb->s_nzones2);
[a04b62d]203 sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
[953a823]204 }
205
206 free(sb);
207
[3b08178]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
[953a823]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);
[9e3dc95]229}
230
[3b08178]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
[e54ba607]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
[ac28650]242static aoff64_t mfs_size_get(fs_node_t *node)
[0d6ab10]243{
244 assert(node);
245
246 const struct mfs_node *mnode = node->data;
247 assert(mnode);
[155f792]248 assert(mnode->ino_i);
[0d6ab10]249
[41202a9]250 mfsdebug("inode size is %d\n", (int) mnode->ino_i->i_size);
251
[155f792]252 return mnode->ino_i->i_size;
[0d6ab10]253}
254
255void mfs_stat(ipc_callid_t rid, ipc_call_t *request)
256{
[7a96476]257 mfsdebug("mfs_stat()\n");
[0d6ab10]258 libfs_stat(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
259}
260
[ac28650]261static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
[44c0f5b]262 fs_index_t index)
263{
264 int rc;
265 struct mfs_instance *instance;
266
[7a96476]267 mfsdebug("mfs_node_get()\n");
[41202a9]268
[44c0f5b]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
[41202a9]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
[44c0f5b]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
[b438804]336 node = malloc(sizeof(fs_node_t));
[44c0f5b]337 if (!node) {
338 rc = ENOMEM;
339 goto out_err;
340 }
341
342 fs_node_initialize(node);
343
[b438804]344 mnode = malloc(sizeof(*mnode));
[44c0f5b]345 if (!mnode) {
346 rc = ENOMEM;
347 goto out_err;
348 }
349
[155f792]350 struct mfs_ino_info *ino_i;
351
[44c0f5b]352 if (sbi->fs_version == MFS_VERSION_V1) {
353 /*Read MFS V1 inode*/
[155f792]354 ino_i = mfs_read_inode_raw(inst, index);
[44c0f5b]355 } else {
356 /*Read MFS V2/V3 inode*/
[155f792]357 ino_i = mfs2_read_inode_raw(inst, index);
[44c0f5b]358 }
359
[155f792]360 if (!ino_i)
[7a96476]361 goto out_err;
[155f792]362
[41202a9]363 ino_i->index = index;
[155f792]364 mnode->ino_i = ino_i;
365
[44c0f5b]366 mnode->instance = inst;
367 node->data = mnode;
368 *rfn = node;
369
[41202a9]370 mfsdebug("node_get_core(%d) OK\n", (int) index);
371
[44c0f5b]372 return EOK;
373
374out_err:
375 if (node)
376 free(node);
377 if (mnode)
378 free(mnode);
379 return rc;
380}
381
[ac28650]382static bool mfs_is_directory(fs_node_t *fsnode)
[5a58ae2]383{
[44c0f5b]384 const struct mfs_node *node = fsnode->data;
[155f792]385 return S_ISDIR(node->ino_i->i_mode);
[5a58ae2]386}
387
[ac28650]388static bool mfs_is_file(fs_node_t *fsnode)
[7d04324]389{
390 struct mfs_node *node = fsnode->data;
[155f792]391 return S_ISREG(node->ino_i->i_mode);
[7d04324]392}
393
[ac28650]394static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle)
[fe4ac35]395{
[41202a9]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;
[fe4ac35]400}
401
[54caa41b]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
[ac28650]407static char mfs_plb_get_char(unsigned pos)
[cfbcd86]408{
409 return mfs_reg.plb_ro[pos % PLB_SIZE];
410}
411
[ac28650]412static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
[54caa41b]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;
[ac28650]418 uint32_t n_dentries = 0;
[54caa41b]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;
[ac28650]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;
[54caa41b]433
[ac28650]434 int i = 2;
435 while (1) {
436 d_info = read_directory_entry(mnode, i++);
[54caa41b]437
[7a96476]438 if (!d_info) {
439 /*Reached the end of the dentries list*/
[152610a8]440 break;
[7a96476]441 }
[54caa41b]442
443 if (d_info->d_inum) {
[7a96476]444 /*A valid entry has been found*/
[54caa41b]445 *has_children = true;
446 free(d_info);
447 break;
448 }
449
450 free(d_info);
451 }
452
[41202a9]453out:
454
[ac28650]455 if (n_dentries > 2 && !*has_children)
[7a96476]456 printf(NAME ": Filesystem corruption detected\n");
[ac28650]457
[54caa41b]458 if (*has_children)
459 mfsdebug("Has children\n");
460 else
461 mfsdebug("Has not children\n");
462
463 return EOK;
464}
465
[3b08178]466/*
467 * Find a filesystem instance given the devmap handle
468 */
[44c0f5b]469int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
[3b08178]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
[8ceba1e]492static bool check_magic_number(uint16_t magic, bool *native,
493 mfs_version_t *version, bool *longfilenames)
[9e3dc95]494{
[7a96476]495 bool rc = false;
[8ceba1e]496 *longfilenames = false;
497
[57640e7]498 if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
499 *native = magic == MFS_MAGIC_V1;
[9e3dc95]500 *version = MFS_VERSION_V1;
[7a96476]501 rc = true;
[8ceba1e]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;
[7a96476]506 rc = true;
[57640e7]507 } else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
508 *native = magic == MFS_MAGIC_V2;
[9e3dc95]509 *version = MFS_VERSION_V2;
[7a96476]510 rc = true;
[8ceba1e]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;
[7a96476]515 rc = true;
[57640e7]516 } else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
517 *native = magic == MFS_MAGIC_V3;
[9e3dc95]518 *version = MFS_VERSION_V3;
[7a96476]519 rc = true;
[9e3dc95]520 }
521
[7a96476]522 return rc;
[096c8835]523}
524
525/**
526 * @}
527 */
528
Note: See TracBrowser for help on using the repository browser.