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

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

Use a generic minixfs inode in core to avoid code duplication

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