source: mainline/uspace/srv/fs/tmpfs/tmpfs_ops.c@ d4a172b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d4a172b was cf95bc0, checked in by Jakub Jermar <jakub@…>, 16 years ago

Streamline TMPFS and fix its design so that it properly supports hardlinks.
libfs operation unlink() is now passed also the name of the component being
unlinked.

  • Property mode set to 100644
File size: 15.2 KB
RevLine 
[d5cdffe]1/*
[41a0d27]2 * Copyright (c) 2008 Jakub Jermar
[d5cdffe]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/**
34 * @file tmpfs_ops.c
35 * @brief Implementation of VFS operations for the TMPFS file system
36 * server.
37 */
38
39#include "tmpfs.h"
40#include "../../vfs/vfs.h"
41#include <ipc/ipc.h>
42#include <async.h>
43#include <errno.h>
[4b11571]44#include <atomic.h>
45#include <stdlib.h>
46#include <string.h>
47#include <stdio.h>
[5973fd0]48#include <assert.h>
[a4eb8a60]49#include <sys/types.h>
50#include <libadt/hash_table.h>
51#include <as.h>
[2c448fb]52#include <libfs.h>
[a4eb8a60]53
54#define min(a, b) ((a) < (b) ? (a) : (b))
55#define max(a, b) ((a) > (b) ? (a) : (b))
[d5cdffe]56
[cf95bc0]57#define NODES_BUCKETS 256
[3298ddc]58
[8d049ee0]59/** All root nodes have index 0. */
60#define TMPFS_SOME_ROOT 0
61/** Global counter for assigning node indices. Shared by all instances. */
62fs_index_t tmpfs_next_index = 1;
[adb5fe3]63
[2c448fb]64/*
65 * Implementation of the libfs interface.
66 */
[b5553a2]67
[fdb7795]68/* Forward declarations of static functions. */
[b6035ba]69static fs_node_t *tmpfs_match(fs_node_t *, const char *);
70static fs_node_t *tmpfs_node_get(dev_handle_t, fs_index_t);
71static void tmpfs_node_put(fs_node_t *);
72static fs_node_t *tmpfs_create_node(dev_handle_t, int);
73static int tmpfs_link_node(fs_node_t *, fs_node_t *, const char *);
[cf95bc0]74static int tmpfs_unlink_node(fs_node_t *, fs_node_t *, const char *);
[b6035ba]75static int tmpfs_destroy_node(fs_node_t *);
[2c448fb]76
77/* Implementation of helper functions. */
[b6035ba]78static fs_index_t tmpfs_index_get(fs_node_t *fn)
[2c448fb]79{
[b6035ba]80 return TMPFS_NODE(fn)->index;
[2c448fb]81}
82
[b6035ba]83static size_t tmpfs_size_get(fs_node_t *fn)
[2c448fb]84{
[b6035ba]85 return TMPFS_NODE(fn)->size;
[2c448fb]86}
87
[b6035ba]88static unsigned tmpfs_lnkcnt_get(fs_node_t *fn)
[2c448fb]89{
[b6035ba]90 return TMPFS_NODE(fn)->lnkcnt;
[2c448fb]91}
92
[b6035ba]93static bool tmpfs_has_children(fs_node_t *fn)
[2c448fb]94{
[cf95bc0]95 return !list_empty(&TMPFS_NODE(fn)->cs_head);
[2c448fb]96}
97
[b6035ba]98static fs_node_t *tmpfs_root_get(dev_handle_t dev_handle)
[2c448fb]99{
[8d049ee0]100 return tmpfs_node_get(dev_handle, TMPFS_SOME_ROOT);
[2c448fb]101}
102
103static char tmpfs_plb_get_char(unsigned pos)
104{
105 return tmpfs_reg.plb_ro[pos % PLB_SIZE];
106}
107
[b6035ba]108static bool tmpfs_is_directory(fs_node_t *fn)
[2c448fb]109{
[b6035ba]110 return TMPFS_NODE(fn)->type == TMPFS_DIRECTORY;
[2c448fb]111}
112
[b6035ba]113static bool tmpfs_is_file(fs_node_t *fn)
[2c448fb]114{
[b6035ba]115 return TMPFS_NODE(fn)->type == TMPFS_FILE;
[2c448fb]116}
117
118/** libfs operations */
119libfs_ops_t tmpfs_libfs_ops = {
120 .match = tmpfs_match,
[a8e9ab8d]121 .node_get = tmpfs_node_get,
[06901c6b]122 .node_put = tmpfs_node_put,
[2c448fb]123 .create = tmpfs_create_node,
124 .destroy = tmpfs_destroy_node,
125 .link = tmpfs_link_node,
126 .unlink = tmpfs_unlink_node,
127 .index_get = tmpfs_index_get,
128 .size_get = tmpfs_size_get,
129 .lnkcnt_get = tmpfs_lnkcnt_get,
[736c164]130 .has_children = tmpfs_has_children,
[2c448fb]131 .root_get = tmpfs_root_get,
132 .plb_get_char = tmpfs_plb_get_char,
133 .is_directory = tmpfs_is_directory,
134 .is_file = tmpfs_is_file
135};
[fdb7795]136
[cf95bc0]137/** Hash table of all TMPFS nodes. */
138hash_table_t nodes;
[a4eb8a60]139
[cf95bc0]140#define NODES_KEY_INDEX 0
141#define NODES_KEY_DEV 1
[8d049ee0]142
[cf95bc0]143/* Implementation of hash table interface for the nodes hash table. */
144static hash_index_t nodes_hash(unsigned long key[])
[a4eb8a60]145{
[cf95bc0]146 return key[NODES_KEY_INDEX] % NODES_BUCKETS;
[a4eb8a60]147}
148
[cf95bc0]149static int nodes_compare(unsigned long key[], hash_count_t keys, link_t *item)
[a4eb8a60]150{
[cf95bc0]151 tmpfs_node_t *nodep = hash_table_get_instance(item, tmpfs_node_t,
152 nh_link);
153 return (nodep->index == key[NODES_KEY_INDEX] &&
154 nodep->dev_handle == key[NODES_KEY_DEV]);
[a4eb8a60]155}
156
[cf95bc0]157static void nodes_remove_callback(link_t *item)
[a4eb8a60]158{
159}
160
[cf95bc0]161/** TMPFS nodes hash table operations. */
162hash_table_operations_t nodes_ops = {
163 .hash = nodes_hash,
164 .compare = nodes_compare,
165 .remove_callback = nodes_remove_callback
[a4eb8a60]166};
167
[cf95bc0]168static void tmpfs_node_initialize(tmpfs_node_t *nodep)
[3298ddc]169{
[cf95bc0]170 nodep->bp = NULL;
171 nodep->index = 0;
172 nodep->dev_handle = 0;
173 nodep->type = TMPFS_NONE;
174 nodep->lnkcnt = 0;
175 nodep->size = 0;
176 nodep->data = NULL;
177 link_initialize(&nodep->nh_link);
178 list_initialize(&nodep->cs_head);
[3298ddc]179}
180
[cf95bc0]181static void tmpfs_dentry_initialize(tmpfs_dentry_t *dentryp)
[3298ddc]182{
[cf95bc0]183 link_initialize(&dentryp->link);
184 dentryp->name = NULL;
185 dentryp->node = NULL;
[4b11571]186}
187
[8d049ee0]188bool tmpfs_init(void)
[4b11571]189{
[cf95bc0]190 if (!hash_table_create(&nodes, NODES_BUCKETS, 2, &nodes_ops))
[a4eb8a60]191 return false;
[8d049ee0]192
193 return true;
194}
195
196static bool tmpfs_instance_init(dev_handle_t dev_handle)
197{
[b6035ba]198 fs_node_t *rfn;
[8d049ee0]199
[b6035ba]200 rfn = tmpfs_create_node(dev_handle, L_DIRECTORY);
201 if (!rfn)
[3298ddc]202 return false;
[b6035ba]203 TMPFS_NODE(rfn)->lnkcnt = 0; /* FS root is not linked */
[3298ddc]204 return true;
[4b11571]205}
206
[b6035ba]207fs_node_t *tmpfs_match(fs_node_t *pfn, const char *component)
[736c164]208{
[cf95bc0]209 tmpfs_node_t *parentp = TMPFS_NODE(pfn);
210 link_t *lnk;
[736c164]211
[cf95bc0]212 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
213 lnk = lnk->next) {
214 tmpfs_dentry_t *dentryp = list_get_instance(lnk, tmpfs_dentry_t,
215 link);
216 if (!str_cmp(dentryp->name, component))
217 return FS_NODE(dentryp->node);
218 }
[736c164]219
[cf95bc0]220 return NULL;
[736c164]221}
222
[b6035ba]223fs_node_t *tmpfs_node_get(dev_handle_t dev_handle, fs_index_t index)
[a8e9ab8d]224{
[8d049ee0]225 unsigned long key[] = {
[cf95bc0]226 [NODES_KEY_INDEX] = index,
227 [NODES_KEY_DEV] = dev_handle
[8d049ee0]228 };
[cf95bc0]229 link_t *lnk = hash_table_find(&nodes, key);
[a8e9ab8d]230 if (!lnk)
231 return NULL;
[cf95bc0]232 return FS_NODE(hash_table_get_instance(lnk, tmpfs_node_t, nh_link));
[a8e9ab8d]233}
234
[b6035ba]235void tmpfs_node_put(fs_node_t *fn)
[06901c6b]236{
237 /* nothing to do */
238}
239
[b6035ba]240fs_node_t *tmpfs_create_node(dev_handle_t dev_handle, int lflag)
[b8b23c8]241{
[72bde81]242 assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
243
[cf95bc0]244 tmpfs_node_t *nodep = malloc(sizeof(tmpfs_node_t));
245 if (!nodep)
[b6035ba]246 return NULL;
[cf95bc0]247 tmpfs_node_initialize(nodep);
248 nodep->bp = malloc(sizeof(fs_node_t));
249 if (!nodep->bp) {
250 free(nodep);
[3298ddc]251 return NULL;
252 }
[cf95bc0]253 nodep->bp->data = nodep; /* link the FS and TMPFS nodes */
[8d049ee0]254 if (!tmpfs_root_get(dev_handle))
[cf95bc0]255 nodep->index = TMPFS_SOME_ROOT;
[8d049ee0]256 else
[cf95bc0]257 nodep->index = tmpfs_next_index++;
258 nodep->dev_handle = dev_handle;
[72bde81]259 if (lflag & L_DIRECTORY)
[cf95bc0]260 nodep->type = TMPFS_DIRECTORY;
[72bde81]261 else
[cf95bc0]262 nodep->type = TMPFS_FILE;
[72bde81]263
[cf95bc0]264 /* Insert the new node into the nodes hash table. */
[8d049ee0]265 unsigned long key[] = {
[cf95bc0]266 [NODES_KEY_INDEX] = nodep->index,
267 [NODES_KEY_DEV] = nodep->dev_handle
[8d049ee0]268 };
[cf95bc0]269 hash_table_insert(&nodes, key, &nodep->nh_link);
270 return FS_NODE(nodep);
[fdb7795]271}
272
[b6035ba]273int tmpfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
[fdb7795]274{
[cf95bc0]275 tmpfs_node_t *parentp = TMPFS_NODE(pfn);
276 tmpfs_node_t *childp = TMPFS_NODE(cfn);
277 tmpfs_dentry_t *dentryp;
278 link_t *lnk;
[fdb7795]279
280 assert(parentp->type == TMPFS_DIRECTORY);
281
[cf95bc0]282 /* Check for duplicit entries. */
283 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
284 lnk = lnk->next) {
285 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
286 if (!str_cmp(dentryp->name, nm))
287 return EEXIST;
288 }
289
290 /* Allocate and initialize the dentry. */
291 dentryp = malloc(sizeof(tmpfs_dentry_t));
292 if (!dentryp)
[0013b9ce]293 return ENOMEM;
[cf95bc0]294 tmpfs_dentry_initialize(dentryp);
295
296 /* Populate and link the new dentry. */
[92fd52d7]297 size_t size = str_size(nm);
[cf95bc0]298 dentryp->name = malloc(size + 1);
299 if (!dentryp->name) {
300 free(dentryp);
[0013b9ce]301 return ENOMEM;
[3298ddc]302 }
[cf95bc0]303 str_cpy(dentryp->name, size + 1, nm);
304 dentryp->node = childp;
[adc8a63]305 childp->lnkcnt++;
[cf95bc0]306 list_append(&dentryp->link, &parentp->cs_head);
[72bde81]307
[0013b9ce]308 return EOK;
[b8b23c8]309}
[4b11571]310
[cf95bc0]311int tmpfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
[b8b23c8]312{
[cf95bc0]313 tmpfs_node_t *parentp = TMPFS_NODE(pfn);
314 tmpfs_node_t *childp = NULL;
315 tmpfs_dentry_t *dentryp;
316 link_t *lnk;
[16105cba]317
[7b6d98b]318 if (!parentp)
[16105cba]319 return EBUSY;
[cf95bc0]320
321 for (lnk = parentp->cs_head.next; lnk != &parentp->cs_head;
322 lnk = lnk->next) {
323 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
324 if (!str_cmp(dentryp->name, nm)) {
325 childp = dentryp->node;
326 assert(FS_NODE(childp) == cfn);
327 break;
328 }
[16105cba]329 }
330
[cf95bc0]331 if (!childp)
332 return ENOENT;
333
334 if ((childp->lnkcnt == 1) && !list_empty(&childp->cs_head))
335 return ENOTEMPTY;
[fdb7795]336
[cf95bc0]337 list_remove(&dentryp->link);
338 free(dentryp);
[7b6d98b]339 childp->lnkcnt--;
[adc8a63]340
[16105cba]341 return EOK;
[d5cdffe]342}
343
[b6035ba]344int tmpfs_destroy_node(fs_node_t *fn)
[fdb7795]345{
[cf95bc0]346 tmpfs_node_t *nodep = TMPFS_NODE(fn);
[fdb7795]347
[cf95bc0]348 assert(!nodep->lnkcnt);
349 assert(list_empty(&nodep->cs_head));
[fdb7795]350
[8d049ee0]351 unsigned long key[] = {
[cf95bc0]352 [NODES_KEY_INDEX] = nodep->index,
353 [NODES_KEY_DEV] = nodep->dev_handle
[8d049ee0]354 };
[cf95bc0]355 hash_table_remove(&nodes, key, 2);
[fdb7795]356
[cf95bc0]357 if (nodep->type == TMPFS_FILE)
358 free(nodep->data);
359 free(nodep->bp);
360 free(nodep);
[45f244b]361 return EOK;
[fdb7795]362}
363
[f49b0ea]364void tmpfs_mounted(ipc_callid_t rid, ipc_call_t *request)
[64b67c3]365{
[f49b0ea]366 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
[64b67c3]367
[594303b]368 /* accept the mount options */
369 ipc_callid_t callid;
370 size_t size;
371 if (!ipc_data_write_receive(&callid, &size)) {
372 ipc_answer_0(callid, EINVAL);
373 ipc_answer_0(rid, EINVAL);
374 return;
375 }
376 char *opts = malloc(size + 1);
377 if (!opts) {
378 ipc_answer_0(callid, ENOMEM);
379 ipc_answer_0(rid, ENOMEM);
380 return;
381 }
382 ipcarg_t retval = ipc_data_write_finalize(callid, opts, size);
383 if (retval != EOK) {
384 ipc_answer_0(rid, retval);
385 free(opts);
386 return;
387 }
388 opts[size] = '\0';
389
[8d049ee0]390 /* Initialize TMPFS instance. */
391 if (!tmpfs_instance_init(dev_handle)) {
[4b11571]392 ipc_answer_0(rid, ENOMEM);
393 return;
394 }
[f49b0ea]395
[cf95bc0]396 tmpfs_node_t *rootp = TMPFS_NODE(tmpfs_root_get(dev_handle));
[594303b]397 if (str_cmp(opts, "restore") == 0) {
[f49b0ea]398 if (tmpfs_restore(dev_handle))
[cf95bc0]399 ipc_answer_3(rid, EOK, rootp->index, rootp->size,
400 rootp->lnkcnt);
[f49b0ea]401 else
402 ipc_answer_0(rid, ELIMIT);
403 } else {
[cf95bc0]404 ipc_answer_3(rid, EOK, rootp->index, rootp->size,
405 rootp->lnkcnt);
[f49b0ea]406 }
407}
408
409void tmpfs_mount(ipc_callid_t rid, ipc_call_t *request)
410{
411 dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
412 fs_index_t mp_index = (fs_index_t) IPC_GET_ARG2(*request);
413 fs_handle_t mr_fs_handle = (fs_handle_t) IPC_GET_ARG3(*request);
414 dev_handle_t mr_dev_handle = (dev_handle_t) IPC_GET_ARG4(*request);
415
416 ipc_answer_0(rid, ENOTSUP);
417}
418
419void tmpfs_lookup(ipc_callid_t rid, ipc_call_t *request)
420{
[2c448fb]421 libfs_lookup(&tmpfs_libfs_ops, tmpfs_reg.fs_handle, rid, request);
[d5cdffe]422}
423
[a4eb8a60]424void tmpfs_read(ipc_callid_t rid, ipc_call_t *request)
425{
[f2ec8c8]426 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
427 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
428 off_t pos = (off_t)IPC_GET_ARG3(*request);
[a4eb8a60]429
430 /*
[cf95bc0]431 * Lookup the respective TMPFS node.
[a4eb8a60]432 */
433 link_t *hlp;
[8d049ee0]434 unsigned long key[] = {
[cf95bc0]435 [NODES_KEY_INDEX] = index,
436 [NODES_KEY_DEV] = dev_handle,
[8d049ee0]437 };
[cf95bc0]438 hlp = hash_table_find(&nodes, key);
[a4eb8a60]439 if (!hlp) {
440 ipc_answer_0(rid, ENOENT);
441 return;
442 }
[cf95bc0]443 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
444 nh_link);
[a4eb8a60]445
446 /*
[a92da0a]447 * Receive the read request.
[a4eb8a60]448 */
449 ipc_callid_t callid;
[92fd52d7]450 size_t size;
451 if (!ipc_data_read_receive(&callid, &size)) {
[a4eb8a60]452 ipc_answer_0(callid, EINVAL);
453 ipc_answer_0(rid, EINVAL);
454 return;
455 }
456
[5973fd0]457 size_t bytes;
[cf95bc0]458 if (nodep->type == TMPFS_FILE) {
459 bytes = max(0, min(nodep->size - pos, size));
460 (void) ipc_data_read_finalize(callid, nodep->data + pos,
[5973fd0]461 bytes);
462 } else {
[cf95bc0]463 tmpfs_dentry_t *dentryp;
464 link_t *lnk;
[5973fd0]465 int i;
466
[cf95bc0]467 assert(nodep->type == TMPFS_DIRECTORY);
[5973fd0]468
469 /*
470 * Yes, we really use O(n) algorithm here.
471 * If it bothers someone, it could be fixed by introducing a
472 * hash table.
473 */
[cf95bc0]474 for (i = 0, lnk = nodep->cs_head.next;
475 i < pos && lnk != &nodep->cs_head;
476 i++, lnk = lnk->next)
[5973fd0]477 ;
478
[cf95bc0]479 if (lnk == &nodep->cs_head) {
[5973fd0]480 ipc_answer_0(callid, ENOENT);
481 ipc_answer_1(rid, ENOENT, 0);
482 return;
483 }
484
[cf95bc0]485 dentryp = list_get_instance(lnk, tmpfs_dentry_t, link);
[3298ddc]486
[cf95bc0]487 (void) ipc_data_read_finalize(callid, dentryp->name,
488 str_size(dentryp->name) + 1);
[5973fd0]489 bytes = 1;
490 }
[7dab6b8]491
492 /*
493 * Answer the VFS_READ call.
494 */
495 ipc_answer_1(rid, EOK, bytes);
[a4eb8a60]496}
497
[ee1b8ca]498void tmpfs_write(ipc_callid_t rid, ipc_call_t *request)
499{
[f2ec8c8]500 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
501 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
502 off_t pos = (off_t)IPC_GET_ARG3(*request);
[ee1b8ca]503
504 /*
[cf95bc0]505 * Lookup the respective TMPFS node.
[ee1b8ca]506 */
507 link_t *hlp;
[8d049ee0]508 unsigned long key[] = {
[cf95bc0]509 [NODES_KEY_INDEX] = index,
510 [NODES_KEY_DEV] = dev_handle
[8d049ee0]511 };
[cf95bc0]512 hlp = hash_table_find(&nodes, key);
[ee1b8ca]513 if (!hlp) {
514 ipc_answer_0(rid, ENOENT);
515 return;
516 }
[cf95bc0]517 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
518 nh_link);
[ee1b8ca]519
520 /*
521 * Receive the write request.
522 */
523 ipc_callid_t callid;
[92fd52d7]524 size_t size;
525 if (!ipc_data_write_receive(&callid, &size)) {
[ee1b8ca]526 ipc_answer_0(callid, EINVAL);
527 ipc_answer_0(rid, EINVAL);
528 return;
529 }
530
[c1bf5cb]531 /*
532 * Check whether the file needs to grow.
533 */
[cf95bc0]534 if (pos + size <= nodep->size) {
[c1bf5cb]535 /* The file size is not changing. */
[cf95bc0]536 (void) ipc_data_write_finalize(callid, nodep->data + pos, size);
537 ipc_answer_2(rid, EOK, size, nodep->size);
[c1bf5cb]538 return;
539 }
[cf95bc0]540 size_t delta = (pos + size) - nodep->size;
[ee1b8ca]541 /*
542 * At this point, we are deliberately extremely straightforward and
[c1bf5cb]543 * simply realloc the contents of the file on every write that grows the
544 * file. In the end, the situation might not be as bad as it may look:
545 * our heap allocator can save us and just grow the block whenever
546 * possible.
[ee1b8ca]547 */
[cf95bc0]548 void *newdata = realloc(nodep->data, nodep->size + delta);
[ee1b8ca]549 if (!newdata) {
550 ipc_answer_0(callid, ENOMEM);
[cf95bc0]551 ipc_answer_2(rid, EOK, 0, nodep->size);
[ee1b8ca]552 return;
553 }
[0ee4322]554 /* Clear any newly allocated memory in order to emulate gaps. */
[cf95bc0]555 memset(newdata + nodep->size, 0, delta);
556 nodep->size += delta;
557 nodep->data = newdata;
558 (void) ipc_data_write_finalize(callid, nodep->data + pos, size);
559 ipc_answer_2(rid, EOK, size, nodep->size);
[ee1b8ca]560}
561
[0ee4322]562void tmpfs_truncate(ipc_callid_t rid, ipc_call_t *request)
563{
[f2ec8c8]564 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
565 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
566 size_t size = (off_t)IPC_GET_ARG3(*request);
[0ee4322]567
568 /*
[cf95bc0]569 * Lookup the respective TMPFS node.
[0ee4322]570 */
571 link_t *hlp;
[8d049ee0]572 unsigned long key[] = {
[cf95bc0]573 [NODES_KEY_INDEX] = index,
574 [NODES_KEY_DEV] = dev_handle
[8d049ee0]575 };
[cf95bc0]576 hlp = hash_table_find(&nodes, key);
[0ee4322]577 if (!hlp) {
578 ipc_answer_0(rid, ENOENT);
579 return;
580 }
[cf95bc0]581 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
582 nh_link);
[0ee4322]583
[cf95bc0]584 if (size == nodep->size) {
[0ee4322]585 ipc_answer_0(rid, EOK);
586 return;
587 }
588
[cf95bc0]589 void *newdata = realloc(nodep->data, size);
[0ee4322]590 if (!newdata) {
591 ipc_answer_0(rid, ENOMEM);
592 return;
593 }
[cf95bc0]594 if (size > nodep->size) {
595 size_t delta = size - nodep->size;
596 memset(newdata + nodep->size, 0, delta);
[0ee4322]597 }
[cf95bc0]598 nodep->size = size;
599 nodep->data = newdata;
[0ee4322]600 ipc_answer_0(rid, EOK);
601}
602
[fdb7795]603void tmpfs_destroy(ipc_callid_t rid, ipc_call_t *request)
[f17667a]604{
[f2ec8c8]605 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request);
606 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
[45f244b]607 int rc;
[f17667a]608
609 link_t *hlp;
[8d049ee0]610 unsigned long key[] = {
[cf95bc0]611 [NODES_KEY_INDEX] = index,
612 [NODES_KEY_DEV] = dev_handle
[8d049ee0]613 };
[cf95bc0]614 hlp = hash_table_find(&nodes, key);
[f17667a]615 if (!hlp) {
616 ipc_answer_0(rid, ENOENT);
617 return;
618 }
[cf95bc0]619 tmpfs_node_t *nodep = hash_table_get_instance(hlp, tmpfs_node_t,
620 nh_link);
621 rc = tmpfs_destroy_node(FS_NODE(nodep));
[45f244b]622 ipc_answer_0(rid, rc);
[f17667a]623}
624
[d5cdffe]625/**
626 * @}
627 */
Note: See TracBrowser for help on using the repository browser.