source: mainline/uspace/srv/fs/mfs/mfs_inode.c@ 4e00f87

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

cstyle

  • Property mode set to 100644
File size: 9.1 KB
RevLine 
[6adba0a8]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
[f213ae7]33#include <stdlib.h>
34#include "mfs.h"
35
[10eb754]36static int
37mfs_write_inode_raw(struct mfs_node *mnode);
38
[cdab59e]39static int
40mfs2_write_inode_raw(struct mfs_node *mnode);
41
[4bf0052a]42static int
43mfs_read_inode_raw(const struct mfs_instance *instance,
[6d4d883]44 struct mfs_ino_info **ino_ptr, uint16_t inum);
[c922bc7]45
[4bf0052a]46static int
47mfs2_read_inode_raw(const struct mfs_instance *instance,
[6d4d883]48 struct mfs_ino_info **ino_ptr, uint32_t inum);
[c922bc7]49
[77ec4d9]50/**Read a MINIX inode from disk
51 *
52 * @param inst Pointer to the filesystem instance.
53 * @param ino_i Pointer to the generic MINIX inode
54 * where the inode content will be stored.
55 * @param index index of the inode to read.
56 *
57 * @return EOK on success or a negative error code.
58 */
[c922bc7]59int
[3a5ee6c]60mfs_get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
[6d4d883]61 fs_index_t index)
[c922bc7]62{
63 struct mfs_sb_info *sbi = inst->sbi;
[4bf0052a]64 int r;
[c922bc7]65
66 if (sbi->fs_version == MFS_VERSION_V1) {
[6d4d883]67 /* Read a MFS V1 inode */
[4bf0052a]68 r = mfs_read_inode_raw(inst, ino_i, index);
[c922bc7]69 } else {
[6d4d883]70 /* Read a MFS V2/V3 inode */
[4bf0052a]71 r = mfs2_read_inode_raw(inst, ino_i, index);
[c922bc7]72 }
73
[4bf0052a]74 return r;
[c922bc7]75}
76
[4bf0052a]77static int
78mfs_read_inode_raw(const struct mfs_instance *instance,
[6d4d883]79 struct mfs_ino_info **ino_ptr, uint16_t inum)
80{
[4bf0052a]81 struct mfs_inode *ino;
[155f792]82 struct mfs_ino_info *ino_i = NULL;
[f213ae7]83 struct mfs_sb_info *sbi;
84 block_t *b;
[4bf0052a]85 int i, r;
[10eb754]86
87 sbi = instance->sbi;
[e33100c]88
[6d4d883]89 /* inode 0 does not exist */
[e33100c]90 inum -= 1;
91
[10eb754]92 const int ino_off = inum % sbi->ino_per_block;
[f213ae7]93
[b438804]94 ino_i = malloc(sizeof(*ino_i));
[f213ae7]95
[4bf0052a]96 if (!ino_i) {
97 r = ENOMEM;
[155f792]98 goto out_err;
[4bf0052a]99 }
[f213ae7]100
[10eb754]101 const int itable_off = sbi->itable_off;
[8b86ed26]102
[03bc76a]103 r = block_get(&b, instance->service_id,
[6d4d883]104 itable_off + inum / sbi->ino_per_block,
105 BLOCK_FLAGS_NONE);
106
[c699b0c]107 if (r != EOK)
108 goto out_err;
[f213ae7]109
[4bf0052a]110 ino = b->data + ino_off * sizeof(struct mfs_inode);
[f213ae7]111
[155f792]112 ino_i->i_mode = conv16(sbi->native, ino->i_mode);
113 ino_i->i_uid = conv16(sbi->native, ino->i_uid);
114 ino_i->i_size = conv32(sbi->native, ino->i_size);
115 ino_i->i_mtime = conv32(sbi->native, ino->i_mtime);
[7cb975e]116 ino_i->i_nlinks = ino->i_nlinks;
[f213ae7]117
118 for (i = 0; i < V1_NR_DIRECT_ZONES; ++i)
[155f792]119 ino_i->i_dzone[i] = conv16(sbi->native, ino->i_dzone[i]);
[f213ae7]120
121 for (i = 0; i < V1_NR_INDIRECT_ZONES; ++i)
[155f792]122 ino_i->i_izone[i] = conv16(sbi->native, ino->i_izone[i]);
[f213ae7]123
[4bf0052a]124 r = block_put(b);
[54caa41b]125 ino_i->dirty = false;
[4bf0052a]126 *ino_ptr = ino_i;
[54caa41b]127
[4bf0052a]128 return r;
[155f792]129
130out_err:
131 if (ino_i)
132 free(ino_i);
[4bf0052a]133 return EOK;
[f213ae7]134}
135
[4bf0052a]136static int
137mfs2_read_inode_raw(const struct mfs_instance *instance,
[6d4d883]138 struct mfs_ino_info **ino_ptr, uint32_t inum)
139{
[4bf0052a]140 struct mfs2_inode *ino;
[155f792]141 struct mfs_ino_info *ino_i = NULL;
[df22c36]142 struct mfs_sb_info *sbi;
143 block_t *b;
[4bf0052a]144 int i, r;
[df22c36]145
[b438804]146 ino_i = malloc(sizeof(*ino_i));
[df22c36]147
[4bf0052a]148 if (!ino_i) {
149 r = ENOMEM;
[155f792]150 goto out_err;
[4bf0052a]151 }
[df22c36]152
153 sbi = instance->sbi;
154
[6d4d883]155 /* inode 0 does not exist */
[e33100c]156 inum -= 1;
157
[10eb754]158 const int itable_off = sbi->itable_off;
159 const int ino_off = inum % sbi->ino_per_block;
[cfff7a8f]160
[03bc76a]161 r = block_get(&b, instance->service_id,
[6d4d883]162 itable_off + inum / sbi->ino_per_block,
163 BLOCK_FLAGS_NONE);
164
[c699b0c]165 if (r != EOK)
166 goto out_err;
[df22c36]167
[4bf0052a]168 ino = b->data + ino_off * sizeof(struct mfs2_inode);
[df22c36]169
[155f792]170 ino_i->i_mode = conv16(sbi->native, ino->i_mode);
171 ino_i->i_nlinks = conv16(sbi->native, ino->i_nlinks);
172 ino_i->i_uid = conv16(sbi->native, ino->i_uid);
173 ino_i->i_gid = conv16(sbi->native, ino->i_gid);
174 ino_i->i_size = conv32(sbi->native, ino->i_size);
175 ino_i->i_atime = conv32(sbi->native, ino->i_atime);
176 ino_i->i_mtime = conv32(sbi->native, ino->i_mtime);
177 ino_i->i_ctime = conv32(sbi->native, ino->i_ctime);
[df22c36]178
179 for (i = 0; i < V2_NR_DIRECT_ZONES; ++i)
[155f792]180 ino_i->i_dzone[i] = conv32(sbi->native, ino->i_dzone[i]);
[df22c36]181
182 for (i = 0; i < V2_NR_INDIRECT_ZONES; ++i)
[155f792]183 ino_i->i_izone[i] = conv32(sbi->native, ino->i_izone[i]);
[df22c36]184
[4bf0052a]185 r = block_put(b);
[54caa41b]186 ino_i->dirty = false;
[4bf0052a]187 *ino_ptr = ino_i;
[54caa41b]188
[4bf0052a]189 return r;
[155f792]190
191out_err:
192 if (ino_i)
193 free(ino_i);
[4bf0052a]194 return EOK;
[df22c36]195}
196
[77ec4d9]197/**Write a MINIX inode on disk (if marked as dirty)
198 *
199 * @param mnode Pointer to the generic MINIX inode in memory.
200 *
201 * @return EOK on success or a negative error code.
202 */
[10eb754]203int
[5f509cc]204mfs_put_inode(struct mfs_node *mnode)
[10eb754]205{
206 int rc = EOK;
207
208 if (!mnode->ino_i->dirty)
209 goto out;
210
211 struct mfs_instance *inst = mnode->instance;
212 struct mfs_sb_info *sbi = inst->sbi;
213
214 if (sbi->fs_version == MFS_VERSION_V1)
215 rc = mfs_write_inode_raw(mnode);
[cdab59e]216 else
217 rc = mfs2_write_inode_raw(mnode);
[10eb754]218
219out:
220 return rc;
221}
222
223static int
224mfs_write_inode_raw(struct mfs_node *mnode)
225{
226 int i, r;
227 block_t *b;
228 struct mfs_ino_info *ino_i = mnode->ino_i;
229 struct mfs_sb_info *sbi = mnode->instance->sbi;
230
[3ab580a]231 const uint32_t inum = ino_i->index - 1;
[10eb754]232 const int itable_off = sbi->itable_off;
[3ab580a]233 const int ino_off = inum % sbi->ino_per_block;
[10eb754]234 const bool native = sbi->native;
235
[03bc76a]236 r = block_get(&b, mnode->instance->service_id,
[c2e50d7]237 itable_off + inum / sbi->ino_per_block,
238 BLOCK_FLAGS_NONE);
[10eb754]239
[c699b0c]240 if (r != EOK)
241 goto out;
[10eb754]242
243 struct mfs_inode *ino = b->data;
244 ino += ino_off;
245
246 ino->i_mode = conv16(native, ino_i->i_mode);
247 ino->i_uid = conv16(native, ino_i->i_uid);
248 ino->i_gid = ino_i->i_gid;
249 ino->i_nlinks = ino_i->i_nlinks;
250 ino->i_size = conv32(native, ino_i->i_size);
251 ino->i_mtime = conv32(native, ino_i->i_mtime);
252
253 for (i = 0; i < V1_NR_DIRECT_ZONES; ++i)
254 ino->i_dzone[i] = conv16(native, ino_i->i_dzone[i]);
255 for (i = 0; i < V1_NR_INDIRECT_ZONES; ++i)
256 ino->i_izone[i] = conv16(native, ino_i->i_izone[i]);
257
258 b->dirty = true;
[9530d94]259 r = block_put(b);
[10eb754]260
261 ino_i->dirty = false;
262out:
263 return r;
264}
265
[cdab59e]266static int
267mfs2_write_inode_raw(struct mfs_node *mnode)
268{
269 struct mfs_ino_info *ino_i = mnode->ino_i;
270 struct mfs_sb_info *sbi = mnode->instance->sbi;
271 block_t *b;
272 int i, r;
273
[3ab580a]274 const uint32_t inum = ino_i->index - 1;
[cdab59e]275 const int itable_off = sbi->itable_off;
[3ab580a]276 const int ino_off = inum % sbi->ino_per_block;
[cdab59e]277 const bool native = sbi->native;
[44c6091f]278
[03bc76a]279 r = block_get(&b, mnode->instance->service_id,
[c2e50d7]280 itable_off + inum / sbi->ino_per_block,
281 BLOCK_FLAGS_NONE);
[cdab59e]282
[c699b0c]283 if (r != EOK)
284 goto out;
[cdab59e]285
286 struct mfs2_inode *ino2 = b->data;
287 ino2 += ino_off;
288
289 ino2->i_mode = conv16(native, ino_i->i_mode);
[c2fcfc0]290 ino2->i_nlinks = conv16(native, ino_i->i_nlinks);
[cdab59e]291 ino2->i_uid = conv16(native, ino_i->i_uid);
292 ino2->i_gid = conv16(native, ino_i->i_gid);
[44c6091f]293 ino2->i_size = conv32(native, ino_i->i_size);
[cdab59e]294 ino2->i_atime = conv32(native, ino_i->i_atime);
295 ino2->i_mtime = conv32(native, ino_i->i_mtime);
296 ino2->i_ctime = conv32(native, ino_i->i_ctime);
297
298 for (i = 0; i < V2_NR_DIRECT_ZONES; ++i)
299 ino2->i_dzone[i] = conv32(native, ino_i->i_dzone[i]);
300
301 for (i = 0; i < V2_NR_INDIRECT_ZONES; ++i)
302 ino2->i_izone[i] = conv32(native, ino_i->i_izone[i]);
303
304 b->dirty = true;
[9530d94]305 r = block_put(b);
[cdab59e]306 ino_i->dirty = false;
307
308out:
309 return r;
310}
311
[77ec4d9]312/**Reduce the inode size of a given number of bytes
313 *
314 * @param mnode Pointer to the generic MINIX inode in memory.
315 * @param size_shrink Number of bytes that will be subtracted to the inode.
316 *
317 * @return EOK on success or a negative error code.
318 */
[8a49fed]319int
[3a5ee6c]320mfs_inode_shrink(struct mfs_node *mnode, size_t size_shrink)
[8a49fed]321{
322 struct mfs_sb_info *sbi = mnode->instance->sbi;
323 struct mfs_ino_info *ino_i = mnode->ino_i;
324 const size_t bs = sbi->block_size;
325 int r;
326
[44799a0]327 if (size_shrink == 0) {
[6d4d883]328 /* Nothing to be done */
[44799a0]329 return EOK;
330 }
[8a49fed]331
332 const size_t old_size = ino_i->i_size;
333 const size_t new_size = ino_i->i_size - size_shrink;
334
335 assert(size_shrink <= old_size);
336
337 ino_i->dirty = true;
338
[6d4d883]339 /* Compute the number of zones to free */
[38b7233]340 unsigned zones_to_free;
[8a49fed]341
[38b7233]342 size_t diff = old_size - new_size;
343 zones_to_free = diff / bs;
[8a49fed]344
[38b7233]345 if (diff % bs != 0)
346 zones_to_free++;
[8a49fed]347
348 uint32_t pos = old_size - 1;
349 unsigned i;
350 for (i = 0; i < zones_to_free; ++i, pos -= bs) {
351 uint32_t old_zone;
352
[3a5ee6c]353 r = mfs_write_map(mnode, pos, 0, &old_zone);
[c699b0c]354 if (r != EOK)
355 goto exit_error;
[8a49fed]356
357 ino_i->i_size -= bs;
358
359 if (old_zone == 0)
[6d4d883]360 continue; /* Sparse block */
[8a49fed]361
[70ac0af]362 r = mfs_free_zone(mnode->instance, old_zone);
[c699b0c]363 if (r != EOK)
364 goto exit_error;
[8a49fed]365 }
366
367 ino_i->i_size = new_size;
[1878386]368
[3a5ee6c]369 return mfs_prune_ind_zones(mnode, new_size);
[8a49fed]370
371exit_error:
372 return r;
373}
374
[6adba0a8]375/**
376 * @}
[44c6091f]377 */
[6adba0a8]378
Note: See TracBrowser for help on using the repository browser.