vfs_lookup.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include "vfs.h"
00039 #include <macros.h>
00040 #include <async.h>
00041 #include <errno.h>
00042 #include <str.h>
00043 #include <stdarg.h>
00044 #include <bool.h>
00045 #include <fibril_synch.h>
00046 #include <adt/list.h>
00047 #include <vfs/canonify.h>
00048 
00049 #define min(a, b)  ((a) < (b) ? (a) : (b))
00050 
00051 FIBRIL_MUTEX_INITIALIZE(plb_mutex);
00052 LIST_INITIALIZE(plb_head);      
00053 uint8_t *plb = NULL;
00054 
00068 int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
00069     vfs_pair_t *altroot, ...)
00070 {
00071         vfs_pair_t *root;
00072 
00073         if (altroot)
00074                 root = altroot;
00075         else
00076                 root = &rootfs;
00077 
00078         if (!root->fs_handle)
00079                 return ENOENT;
00080         
00081         size_t len;
00082         path = canonify(path, &len);
00083         if (!path)
00084                 return EINVAL;
00085         
00086         fs_index_t index = 0;
00087         if (lflag & L_LINK) {
00088                 va_list ap;
00089 
00090                 va_start(ap, altroot);
00091                 index = va_arg(ap, fs_index_t);
00092                 va_end(ap);
00093         }
00094         
00095         fibril_mutex_lock(&plb_mutex);
00096 
00097         plb_entry_t entry;
00098         link_initialize(&entry.plb_link);
00099         entry.len = len;
00100 
00101         size_t first;   /* the first free index */
00102         size_t last;    /* the last free index */
00103 
00104         if (list_empty(&plb_head)) {
00105                 first = 0;
00106                 last = PLB_SIZE - 1;
00107         } else {
00108                 plb_entry_t *oldest = list_get_instance(plb_head.next,
00109                     plb_entry_t, plb_link);
00110                 plb_entry_t *newest = list_get_instance(plb_head.prev,
00111                     plb_entry_t, plb_link);
00112 
00113                 first = (newest->index + newest->len) % PLB_SIZE;
00114                 last = (oldest->index - 1) % PLB_SIZE;
00115         }
00116 
00117         if (first <= last) {
00118                 if ((last - first) + 1 < len) {
00119                         /*
00120                          * The buffer cannot absorb the path.
00121                          */
00122                         fibril_mutex_unlock(&plb_mutex);
00123                         return ELIMIT;
00124                 }
00125         } else {
00126                 if (PLB_SIZE - ((first - last) + 1) < len) {
00127                         /*
00128                          * The buffer cannot absorb the path.
00129                          */
00130                         fibril_mutex_unlock(&plb_mutex);
00131                         return ELIMIT;
00132                 }
00133         }
00134 
00135         /*
00136          * We know the first free index in PLB and we also know that there is
00137          * enough space in the buffer to hold our path.
00138          */
00139 
00140         entry.index = first;
00141         entry.len = len;
00142 
00143         /*
00144          * Claim PLB space by inserting the entry into the PLB entry ring
00145          * buffer.
00146          */
00147         list_append(&entry.plb_link, &plb_head);
00148         
00149         fibril_mutex_unlock(&plb_mutex);
00150 
00151         /*
00152          * Copy the path into PLB.
00153          */
00154         size_t cnt1 = min(len, (PLB_SIZE - first) + 1);
00155         size_t cnt2 = len - cnt1;
00156         
00157         memcpy(&plb[first], path, cnt1);
00158         memcpy(plb, &path[cnt1], cnt2);
00159 
00160         ipc_call_t answer;
00161         int phone = vfs_grab_phone(root->fs_handle);
00162         aid_t req = async_send_5(phone, VFS_OUT_LOOKUP, (sysarg_t) first,
00163             (sysarg_t) (first + len - 1) % PLB_SIZE,
00164             (sysarg_t) root->devmap_handle, (sysarg_t) lflag, (sysarg_t) index,
00165             &answer);
00166         
00167         sysarg_t rc;
00168         async_wait_for(req, &rc);
00169         vfs_release_phone(root->fs_handle, phone);
00170         
00171         fibril_mutex_lock(&plb_mutex);
00172         list_remove(&entry.plb_link);
00173         /*
00174          * Erasing the path from PLB will come handy for debugging purposes.
00175          */
00176         memset(&plb[first], 0, cnt1);
00177         memset(plb, 0, cnt2);
00178         fibril_mutex_unlock(&plb_mutex);
00179         
00180         if ((int) rc < EOK)
00181                 return (int) rc;
00182 
00183         if (!result)
00184                 return EOK;
00185         
00186         result->triplet.fs_handle = (fs_handle_t) rc;
00187         result->triplet.devmap_handle = (devmap_handle_t) IPC_GET_ARG1(answer);
00188         result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
00189         result->size =
00190             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(answer), IPC_GET_ARG4(answer));
00191         result->lnkcnt = (unsigned int) IPC_GET_ARG5(answer);
00192         
00193         if (lflag & L_FILE)
00194                 result->type = VFS_NODE_FILE;
00195         else if (lflag & L_DIRECTORY)
00196                 result->type = VFS_NODE_DIRECTORY;
00197         else
00198                 result->type = VFS_NODE_UNKNOWN;
00199         
00200         return EOK;
00201 }
00202 
00208 int vfs_open_node_internal(vfs_lookup_res_t *result)
00209 {
00210         int phone = vfs_grab_phone(result->triplet.fs_handle);
00211         
00212         ipc_call_t answer;
00213         aid_t req = async_send_2(phone, VFS_OUT_OPEN_NODE,
00214             (sysarg_t) result->triplet.devmap_handle,
00215             (sysarg_t) result->triplet.index, &answer);
00216         
00217         sysarg_t rc;
00218         async_wait_for(req, &rc);
00219         vfs_release_phone(result->triplet.fs_handle, phone);
00220         
00221         if (rc == EOK) {
00222                 result->size =
00223                     MERGE_LOUP32(IPC_GET_ARG1(answer), IPC_GET_ARG2(answer));
00224                 result->lnkcnt = (unsigned int) IPC_GET_ARG3(answer);
00225                 if (IPC_GET_ARG4(answer) & L_FILE)
00226                         result->type = VFS_NODE_FILE;
00227                 else if (IPC_GET_ARG4(answer) & L_DIRECTORY)
00228                         result->type = VFS_NODE_DIRECTORY;
00229                 else
00230                         result->type = VFS_NODE_UNKNOWN;
00231         }
00232         
00233         return rc;
00234 }
00235 

Generated on Thu Jun 2 07:45:50 2011 for HelenOS/USB by  doxygen 1.4.7