Subversion Repositories HelenOS

Rev

Rev 2544 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2007 Jakub Jermar
  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    vfs.c
  35.  * @brief   VFS_LOOKUP method and Path Lookup Buffer code.
  36.  */
  37.  
  38. #include <ipc/ipc.h>
  39. #include <async.h>
  40. #include <errno.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <bool.h>
  44. #include <futex.h>
  45. #include <libadt/list.h>
  46. #include "vfs.h"
  47.  
  48. #define min(a, b)   ((a) < (b) ? (a) : (b))
  49.  
  50. atomic_t plb_futex = FUTEX_INITIALIZER;
  51. link_t plb_head;    /**< PLB entry ring buffer. */
  52. uint8_t *plb = NULL;
  53.  
  54. int vfs_lookup_internal(char *path, size_t len, vfs_node_t *result)
  55. {
  56.     if (!len)
  57.         return EINVAL;
  58.  
  59.     if (!rootfs)
  60.         return ENOENT;
  61.    
  62.     futex_down(&plb_futex);
  63.  
  64.     plb_entry_t entry;
  65.     link_initialize(&entry.plb_link);
  66.     entry.len = len;
  67.  
  68.     off_t first;    /* the first free index */
  69.     off_t last; /* the last free index */
  70.  
  71.     if (list_empty(&plb_head)) {
  72.         first = 0;
  73.         last = PLB_SIZE - 1;
  74.     } else {
  75.         plb_entry_t *oldest = list_get_instance(plb_head.next,
  76.             plb_entry_t, plb_link);
  77.         plb_entry_t *newest = list_get_instance(plb_head.prev,
  78.             plb_entry_t, plb_link);
  79.  
  80.         first = (newest->index + newest->len) % PLB_SIZE;
  81.         last = (oldest->index - 1) % PLB_SIZE;
  82.     }
  83.  
  84.     if (first <= last) {
  85.         if ((last - first) + 1 < len) {
  86.             /*
  87.              * The buffer cannot absorb the path.
  88.              */
  89.             futex_up(&plb_futex);
  90.             return ELIMIT;
  91.         }
  92.     } else {
  93.         if (PLB_SIZE - ((first - last) + 1) < len) {
  94.             /*
  95.              * The buffer cannot absorb the path.
  96.              */
  97.             futex_up(&plb_futex);
  98.             return ELIMIT;
  99.         }
  100.     }
  101.  
  102.     /*
  103.      * We know the first free index in PLB and we also know that there is
  104.      * enough space in the buffer to hold our path.
  105.      */
  106.  
  107.     entry.index = first;
  108.     entry.len = len;
  109.  
  110.     /*
  111.      * Claim PLB space by inserting the entry into the PLB entry ring
  112.      * buffer.
  113.      */
  114.     list_append(&entry.plb_link, &plb_head);
  115.    
  116.     futex_up(&plb_futex);
  117.  
  118.     /*
  119.      * Copy the path into PLB.
  120.      */
  121.     size_t cnt1 = min(len, (PLB_SIZE - first) + 1);
  122.     size_t cnt2 = len - cnt1;
  123.    
  124.     memcpy(&plb[first], path, cnt1);
  125.     memcpy(plb, &path[cnt1], cnt2);
  126.  
  127.     ipc_call_t answer;
  128.     int phone = vfs_grab_phone(rootfs->fs_handle);
  129.     aid_t req = async_send_3(phone, VFS_LOOKUP, (ipcarg_t) first,
  130.         (ipcarg_t) last, (ipcarg_t) rootfs->dev_handle, &answer);
  131.     vfs_release_phone(phone);
  132.  
  133.     ipcarg_t rc;
  134.     async_wait_for(req, &rc);
  135.  
  136.     futex_down(&plb_futex);
  137.     list_remove(&entry.plb_link);
  138.     futex_up(&plb_futex);
  139.  
  140.     if (rc == EOK) {
  141.         result->fs_handle = (int) IPC_GET_ARG1(answer);
  142.         result->dev_handle = (int) IPC_GET_ARG2(answer);
  143.         result->index = (int) IPC_GET_ARG3(answer);
  144.     }
  145.  
  146.     return rc;
  147. }
  148.  
  149. /**
  150.  * @}
  151.  */
  152.