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

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

Link mfs_plb_get_char to the libfs structure

  • Property mode set to 100644
File size: 9.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 LIST_INITIALIZE(inst_list);
47static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
48
49libfs_ops_t mfs_libfs_ops = {
50 .size_get = mfs_size_get,
51 .root_get = mfs_root_get,
52 .device_get = mfs_device_get,
53 .is_directory = mfs_is_directory,
54 .is_file = mfs_is_file,
55 .node_get = mfs_node_get,
56 .plb_get_char = mfs_plb_get_char
57};
58
59void mfs_mounted(ipc_callid_t rid, ipc_call_t *request)
60{
61 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
62 enum cache_mode cmode;
63 struct mfs_superblock *sb;
64 struct mfs3_superblock *sb3;
65 struct mfs_sb_info *sbi;
66 struct mfs_instance *instance;
67 bool native, longnames;
68 mfs_version_t version;
69 uint16_t magic;
70
71 /* Accept the mount options */
72 char *opts;
73 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
74
75 if (rc != EOK) {
76 mfsdebug("Can't accept async data write\n");
77 async_answer_0(rid, rc);
78 return;
79 }
80
81 /* Check for option enabling write through. */
82 if (str_cmp(opts, "wtcache") == 0)
83 cmode = CACHE_MODE_WT;
84 else
85 cmode = CACHE_MODE_WB;
86
87 free(opts);
88
89 /* initialize libblock */
90 rc = block_init(devmap_handle, 1024);
91 if (rc != EOK) {
92 mfsdebug("libblock initialization failed\n");
93 async_answer_0(rid, rc);
94 return;
95 }
96
97 /*Allocate space for generic MFS superblock*/
98 sbi = (struct mfs_sb_info *) malloc(sizeof(struct mfs_sb_info));
99
100 if (!sbi) {
101 async_answer_0(rid, ENOMEM);
102 return;
103 }
104
105 /*Allocate space for filesystem instance*/
106 instance = (struct mfs_instance *) malloc(sizeof(struct mfs_instance));
107
108 if (!instance) {
109 async_answer_0(rid, ENOMEM);
110 return;
111 }
112
113 sb = (struct mfs_superblock *) malloc(MFS_SUPERBLOCK_SIZE);
114
115 if (!sb) {
116 async_answer_0(rid, ENOMEM);
117 return;
118 }
119
120 /* Read the superblock */
121 rc = block_read_direct(devmap_handle, MFS_SUPERBLOCK << 1, 1, sb);
122 if (rc != EOK) {
123 block_fini(devmap_handle);
124 async_answer_0(rid, rc);
125 return;
126 }
127
128 sb3 = (struct mfs3_superblock *) sb;
129
130 if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
131 magic = sb->s_magic;
132 goto recognized;
133 }
134
135 if (!check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
136 mfsdebug("magic number not recognized\n");
137 block_fini(devmap_handle);
138 async_answer_0(rid, ENOTSUP);
139 return;
140 }
141
142 magic = sb3->s_magic;
143
144recognized:
145
146 mfsdebug("magic number recognized = %04x\n", magic);
147
148 /*Fill superblock info structure*/
149
150 sbi->fs_version = version;
151 sbi->long_names = longnames;
152 sbi->native = native;
153 sbi->magic = magic;
154
155 if (version == MFS_VERSION_V3) {
156 sbi->ninodes = conv32(native, sb3->s_ninodes);
157 sbi->ibmap_blocks = conv16(native, sb3->s_ibmap_blocks);
158 sbi->zbmap_blocks = conv16(native, sb3->s_zbmap_blocks);
159 sbi->firstdatazone = conv16(native, sb3->s_first_data_zone);
160 sbi->log2_zone_size = conv16(native, sb3->s_log2_zone_size);
161 sbi->max_file_size = conv32(native, sb3->s_max_file_size);
162 sbi->nzones = conv32(native, sb3->s_nzones);
163 sbi->block_size = conv16(native, sb3->s_block_size);
164 } else {
165 sbi->ninodes = conv16(native, sb->s_ninodes);
166 sbi->ibmap_blocks = conv16(native, sb->s_ibmap_blocks);
167 sbi->zbmap_blocks = conv16(native, sb->s_zbmap_blocks);
168 sbi->firstdatazone = conv16(native, sb->s_first_data_zone);
169 sbi->log2_zone_size = conv16(native, sb->s_log2_zone_size);
170 sbi->max_file_size = conv32(native, sb->s_max_file_size);
171 sbi->nzones = conv16(native, sb->s_nzones);
172 sbi->block_size = MFS_BLOCKSIZE;
173 if (version == MFS_VERSION_V2)
174 sbi->nzones = conv32(native, sb->s_nzones2);
175 }
176
177 free(sb);
178
179 rc = block_cache_init(devmap_handle, sbi->block_size, 0, CACHE_MODE_WT);
180
181 if (rc != EOK) {
182 block_fini(devmap_handle);
183 async_answer_0(rid, EINVAL);
184 mfsdebug("block cache initialization failed\n");
185 return;
186 }
187
188 /*Initialize the instance structure and add it to the list*/
189 link_initialize(&instance->link);
190 instance->handle = devmap_handle;
191 instance->sbi = sbi;
192
193 fibril_mutex_lock(&inst_list_mutex);
194 list_append(&instance->link, &inst_list);
195 fibril_mutex_unlock(&inst_list_mutex);
196
197 mfsdebug("mount successful\n");
198
199 async_answer_0(rid, EOK);
200}
201
202void mfs_mount(ipc_callid_t rid, ipc_call_t *request)
203{
204 libfs_mount(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
205}
206
207devmap_handle_t mfs_device_get(fs_node_t *fsnode)
208{
209 struct mfs_node *node = fsnode->data;
210 return node->instance->handle;
211}
212
213aoff64_t mfs_size_get(fs_node_t *node)
214{
215 mfsdebug("request for inode size\n");
216 assert(node);
217
218 const struct mfs_node *mnode = node->data;
219 assert(mnode);
220 assert(mnode->ino_i);
221
222 return mnode->ino_i->i_size;
223}
224
225void mfs_stat(ipc_callid_t rid, ipc_call_t *request)
226{
227 mfsdebug("mfs_stat called\n");
228 libfs_stat(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
229}
230
231int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
232 fs_index_t index)
233{
234 int rc;
235 struct mfs_instance *instance;
236
237 rc = mfs_instance_get(devmap_handle, &instance);
238
239 if (rc != EOK)
240 return rc;
241
242 return mfs_node_core_get(rfn, instance, index);
243}
244
245static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
246 fs_index_t index)
247{
248 fs_node_t *node = NULL;
249 struct mfs_node *mnode = NULL;
250 int rc;
251
252 const struct mfs_sb_info *sbi = inst->sbi;
253
254 node = (fs_node_t *) malloc(sizeof(fs_node_t));
255 if (!node) {
256 rc = ENOMEM;
257 goto out_err;
258 }
259
260 fs_node_initialize(node);
261
262 mnode = (struct mfs_node *) malloc(sizeof(struct mfs_node));
263 if (!mnode) {
264 rc = ENOMEM;
265 goto out_err;
266 }
267
268 struct mfs_ino_info *ino_i;
269
270 if (sbi->fs_version == MFS_VERSION_V1) {
271 /*Read MFS V1 inode*/
272 ino_i = mfs_read_inode_raw(inst, index);
273 } else {
274 /*Read MFS V2/V3 inode*/
275 ino_i = mfs2_read_inode_raw(inst, index);
276 }
277
278 if (!ino_i)
279 return -1;
280
281 mnode->ino_i = ino_i;
282
283 mnode->instance = inst;
284 node->data = mnode;
285 *rfn = node;
286
287 return EOK;
288
289out_err:
290 if (node)
291 free(node);
292 if (mnode)
293 free(mnode);
294 return rc;
295}
296
297bool mfs_is_directory(fs_node_t *fsnode)
298{
299 const struct mfs_node *node = fsnode->data;
300 return S_ISDIR(node->ino_i->i_mode);
301}
302
303bool mfs_is_file(fs_node_t *fsnode)
304{
305 struct mfs_node *node = fsnode->data;
306 return S_ISREG(node->ino_i->i_mode);
307}
308
309int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle)
310{
311 return mfs_node_get(rfn, handle, MFS_ROOT_INO);
312}
313
314char mfs_plb_get_char(unsigned pos)
315{
316 return mfs_reg.plb_ro[pos % PLB_SIZE];
317}
318
319/*
320 * Find a filesystem instance given the devmap handle
321 */
322int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
323{
324 link_t *link;
325 struct mfs_instance *instance_ptr;
326
327 fibril_mutex_lock(&inst_list_mutex);
328
329 for (link = inst_list.next; link != &inst_list; link = link->next) {
330 instance_ptr = list_get_instance(link, struct mfs_instance, link);
331
332 if (instance_ptr->handle == handle) {
333 *instance = instance_ptr;
334 fibril_mutex_unlock(&inst_list_mutex);
335 return EOK;
336 }
337 }
338
339 mfsdebug("Instance not found\n");
340
341 fibril_mutex_unlock(&inst_list_mutex);
342 return EINVAL;
343}
344
345static bool check_magic_number(uint16_t magic, bool *native,
346 mfs_version_t *version, bool *longfilenames)
347{
348 *longfilenames = false;
349
350 if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
351 *native = magic == MFS_MAGIC_V1;
352 *version = MFS_VERSION_V1;
353 return true;
354 } else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
355 *native = magic == MFS_MAGIC_V1L;
356 *version = MFS_VERSION_V1;
357 *longfilenames = true;
358 return true;
359 } else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
360 *native = magic == MFS_MAGIC_V2;
361 *version = MFS_VERSION_V2;
362 return true;
363 } else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
364 *native = magic == MFS_MAGIC_V2L;
365 *version = MFS_VERSION_V2;
366 *longfilenames = true;
367 return true;
368 } else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
369 *native = magic == MFS_MAGIC_V3;
370 *version = MFS_VERSION_V3;
371 return true;
372 }
373
374 return false;
375}
376
377/**
378 * @}
379 */
380
Note: See TracBrowser for help on using the repository browser.