Changeset bf9dc4e2 in mainline for uspace/srv/vfs


Ignore:
Timestamp:
2013-07-28T19:32:36Z (12 years ago)
Author:
Jiri Zarevucky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
778d26d
Parents:
d60ce4a
Message:

Relativize and simplify lookup().

Location:
uspace/srv/vfs
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs.h

    rd60ce4a rbf9dc4e2  
    180180extern vfs_info_t *fs_handle_to_info(fs_handle_t);
    181181
    182 extern int vfs_lookup_internal(char *, int, vfs_lookup_res_t *,
    183     vfs_pair_t *, ...);
     182extern int vfs_lookup_internal(vfs_triplet_t *, char *, int, vfs_lookup_res_t *);
     183extern int vfs_link_internal(vfs_triplet_t *, char *, vfs_triplet_t *);
    184184
    185185extern bool vfs_nodes_init(void);
  • uspace/srv/vfs/vfs_lookup.c

    rd60ce4a rbf9dc4e2  
    4646#include <adt/list.h>
    4747#include <vfs/canonify.h>
     48#include <dirent.h>
     49#include <assert.h>
     50
     51#define DPRINTF(...)
    4852
    4953#define min(a, b)  ((a) < (b) ? (a) : (b))
     
    5357uint8_t *plb = NULL;
    5458
    55 /** Perform a path lookup.
    56  *
    57  * @param path    Path to be resolved; it must be a NULL-terminated
    58  *                string.
    59  * @param lflag   Flags to be used during lookup.
    60  * @param result  Empty structure where the lookup result will be stored.
    61  *                Can be NULL.
    62  * @param altroot If non-empty, will be used instead of rootfs as the root
    63  *                of the whole VFS tree.
    64  *
    65  * @return EOK on success or an error code from errno.h.
    66  *
    67  */
    68 int vfs_lookup_internal(char *path, int lflag, vfs_lookup_res_t *result,
    69     vfs_pair_t *altroot, ...)
    70 {
    71         vfs_pair_t *root;
    72 
    73         if (altroot)
    74                 root = altroot;
    75         else
    76                 root = &rootfs;
    77 
    78         if (!root->fs_handle)
    79                 return ENOENT;
    80        
    81         size_t len;
    82         path = canonify(path, &len);
    83         if (!path)
    84                 return EINVAL;
    85        
    86         fs_index_t index = 0;
    87         if (lflag & L_LINK) {
    88                 va_list ap;
    89 
    90                 va_start(ap, altroot);
    91                 index = va_arg(ap, fs_index_t);
    92                 va_end(ap);
    93         }
    94        
     59static int plb_insert_entry(plb_entry_t *entry, char *path, size_t *start, size_t len)
     60{
    9561        fibril_mutex_lock(&plb_mutex);
    9662
    97         plb_entry_t entry;
    98         link_initialize(&entry.plb_link);
    99         entry.len = len;
     63        link_initialize(&entry->plb_link);
     64        entry->len = len;
    10065
    10166        size_t first;   /* the first free index */
     
    138103         */
    139104
    140         entry.index = first;
    141         entry.len = len;
     105        entry->index = first;
     106        entry->len = len;
    142107
    143108        /*
     
    145110         * buffer.
    146111         */
    147         list_append(&entry.plb_link, &plb_entries);
     112        list_append(&entry->plb_link, &plb_entries);
    148113       
    149114        fibril_mutex_unlock(&plb_mutex);
     
    158123        memcpy(plb, &path[cnt1], cnt2);
    159124
    160         ipc_call_t answer;
    161         async_exch_t *exch = vfs_exchange_grab(root->fs_handle);
    162         aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first,
    163             (sysarg_t) (first + len - 1) % PLB_SIZE,
    164             (sysarg_t) root->service_id, (sysarg_t) lflag, (sysarg_t) index,
    165             &answer);
    166        
    167         sysarg_t rc;
    168         async_wait_for(req, &rc);
    169         vfs_exchange_release(exch);
    170        
     125        *start = first;
     126        return EOK;
     127}
     128
     129static void plb_clear_entry(plb_entry_t *entry, size_t first, size_t len)
     130{
    171131        fibril_mutex_lock(&plb_mutex);
    172         list_remove(&entry.plb_link);
     132        list_remove(&entry->plb_link);
    173133        /*
    174134         * Erasing the path from PLB will come handy for debugging purposes.
    175135         */
     136        size_t cnt1 = min(len, (PLB_SIZE - first) + 1);
     137        size_t cnt2 = len - cnt1;
    176138        memset(&plb[first], 0, cnt1);
    177139        memset(plb, 0, cnt2);
    178140        fibril_mutex_unlock(&plb_mutex);
    179        
    180         if ((int) rc < EOK)
    181                 return (int) rc;
    182 
    183         if (!result)
    184                 return EOK;
     141}
     142
     143static char *_strrchr(char *path, int c)
     144{
     145        char *res = NULL;
     146        while (*path != 0) {
     147                if (*path == c) {
     148                        res = path;
     149                }
     150                path++;
     151        }
     152        return res;
     153}
     154
     155int vfs_link_internal(vfs_triplet_t *base, char *path, vfs_triplet_t *child)
     156{
     157        assert(base != NULL);
     158        assert(child != NULL);
     159        assert(base->fs_handle);
     160        assert(child->fs_handle);
     161        assert(path != NULL);
     162       
     163        vfs_lookup_res_t res;
     164        char component[NAME_MAX + 1];
     165        int rc;
     166       
     167        size_t len;
     168        char *npath = canonify(path, &len);
     169        if (!npath) {
     170                rc = EINVAL;
     171                goto out;
     172        }
     173        path = npath;
     174       
     175        char *slash = _strrchr(path, '/');
     176        if (slash && slash != path) {
     177                if (slash[1] == 0) {
     178                        rc = EINVAL;
     179                        goto out;
     180                }
     181               
     182                memcpy(component, slash + 1, str_size(slash));
     183                *slash = 0;
     184               
     185                rc = vfs_lookup_internal(base, path, L_DIRECTORY, &res);
     186                if (rc != EOK) {
     187                        goto out;
     188                }
     189                base = &res.triplet;
     190               
     191                *slash = '/';
     192        } else {
     193                memcpy(component, path + 1, str_size(path));
     194        }
     195       
     196        if (base->fs_handle != child->fs_handle || base->service_id != child->service_id) {
     197                rc = EXDEV;
     198                goto out;
     199        }
     200       
     201        async_exch_t *exch = vfs_exchange_grab(base->fs_handle);
     202        aid_t req = async_send_3(exch, VFS_OUT_LINK, base->service_id, base->index, child->index, NULL);
     203       
     204        rc = async_data_write_start(exch, component, str_size(component) + 1);
     205        sysarg_t orig_rc;
     206        async_wait_for(req, &orig_rc);
     207        vfs_exchange_release(exch);
     208        if (orig_rc != EOK) {
     209                rc = orig_rc;
     210        }
     211       
     212out:
     213        DPRINTF("vfs_link_internal() with path '%s' returns %d\n", path, rc);
     214        return rc;
     215}
     216
     217/** Perform a path lookup.
     218 *
     219 * @param base    The file from which to perform the lookup.
     220 * @param path    Path to be resolved; it must be a NULL-terminated
     221 *                string.
     222 * @param lflag   Flags to be used during lookup.
     223 * @param result  Empty structure where the lookup result will be stored.
     224 *                Can be NULL.
     225 *
     226 * @return EOK on success or an error code from errno.h.
     227 *
     228 */
     229int vfs_lookup_internal(vfs_triplet_t *base, char *path, int lflag, vfs_lookup_res_t *result)
     230{
     231        assert(base != NULL);
     232        assert(path != NULL);
     233       
     234        sysarg_t rc;
     235       
     236        if (!base->fs_handle) {
     237                rc = ENOENT;
     238                goto out;
     239        }
     240       
     241        size_t len;
     242        char *npath = canonify(path, &len);
     243        if (!npath) {
     244                rc = EINVAL;
     245                goto out;
     246        }
     247        path = npath;
     248       
     249        assert(path[0] == '/');
     250       
     251        size_t first;
     252       
     253        plb_entry_t entry;
     254        rc = plb_insert_entry(&entry, path, &first, len);
     255        if (rc != EOK) {
     256                goto out;
     257        }
     258       
     259        ipc_call_t answer;
     260        async_exch_t *exch = vfs_exchange_grab(base->fs_handle);
     261        aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) first, (sysarg_t) len,
     262            (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer);
     263        async_wait_for(req, &rc);
     264        vfs_exchange_release(exch);
     265       
     266        plb_clear_entry(&entry, first, len);
     267       
     268        if ((int) rc < 0) {
     269                goto out;
     270        }
     271       
     272        if (!result) {
     273                rc = EOK;
     274                goto out;
     275        }
    185276       
    186277        result->triplet.fs_handle = (fs_handle_t) rc;
     
    197288        else
    198289                result->type = VFS_NODE_UNKNOWN;
    199        
    200         return EOK;
     290
     291        rc = EOK;
     292
     293out:
     294        DPRINTF("vfs_lookup_internal() with path '%s' returns %d\n", path, rc);
     295        return rc;
    201296}
    202297
  • uspace/srv/vfs/vfs_ops.c

    rd60ce4a rbf9dc4e2  
    6868FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
    6969
    70 vfs_pair_t rootfs = {
    71         .fs_handle = 0,
    72         .service_id = 0
    73 };
     70vfs_node_t *root = NULL;
    7471
    7572static int vfs_mount_internal(ipc_callid_t rid, service_id_t service_id,
     
    9087        /* Resolve the path to the mountpoint. */
    9188        fibril_rwlock_write_lock(&namespace_rwlock);
    92         if (rootfs.fs_handle) {
    93                 /* We already have the root FS. */
    94                 if (str_cmp(mp, "/") == 0) {
    95                         /* Trying to mount root FS over root FS */
    96                         fibril_rwlock_write_unlock(&namespace_rwlock);
    97                         async_answer_0(rid, EBUSY);
    98                         return EBUSY;
    99                 }
    100                
    101                 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
    102                 if (rc != EOK) {
    103                         /* The lookup failed for some reason. */
    104                         fibril_rwlock_write_unlock(&namespace_rwlock);
    105                         async_answer_0(rid, rc);
    106                         return rc;
    107                 }
    108                
    109                 mp_node = vfs_node_get(&mp_res);
    110                 if (!mp_node) {
    111                         fibril_rwlock_write_unlock(&namespace_rwlock);
    112                         async_answer_0(rid, ENOMEM);
    113                         return ENOMEM;
    114                 }
    115                
    116                 /*
    117                  * Now we hold a reference to mp_node.
    118                  * It will be dropped upon the corresponding VFS_IN_UNMOUNT.
    119                  * This prevents the mount point from being deleted.
    120                  */
    121         } else {
     89        if (root == NULL) {
    12290                /* We still don't have the root file system mounted. */
    123                 if (str_cmp(mp, "/") == 0) {
    124                         /*
    125                          * For this simple, but important case,
    126                          * we are almost done.
    127                          */
    128                        
    129                         /* Tell the mountee that it is being mounted. */
    130                         exch = vfs_exchange_grab(fs_handle);
    131                         msg = async_send_1(exch, VFS_OUT_MOUNTED,
    132                             (sysarg_t) service_id, &answer);
    133                         /* Send the mount options */
    134                         rc = async_data_write_start(exch, (void *)opts,
    135                             str_size(opts));
    136                         vfs_exchange_release(exch);
    137                        
    138                         if (rc != EOK) {
    139                                 async_forget(msg);
    140                                 fibril_rwlock_write_unlock(&namespace_rwlock);
    141                                 async_answer_0(rid, rc);
    142                                 return rc;
    143                         }
    144                         async_wait_for(msg, &rc);
    145                        
    146                         if (rc != EOK) {
    147                                 fibril_rwlock_write_unlock(&namespace_rwlock);
    148                                 async_answer_0(rid, rc);
    149                                 return rc;
    150                         }
    151 
    152                         rindex = (fs_index_t) IPC_GET_ARG1(answer);
    153                         rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
    154                             IPC_GET_ARG3(answer));
    155                         rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
    156                        
    157                         mr_res.triplet.fs_handle = fs_handle;
    158                         mr_res.triplet.service_id = service_id;
    159                         mr_res.triplet.index = rindex;
    160                         mr_res.size = rsize;
    161                         mr_res.lnkcnt = rlnkcnt;
    162                         mr_res.type = VFS_NODE_DIRECTORY;
    163                        
    164                         rootfs.fs_handle = fs_handle;
    165                         rootfs.service_id = service_id;
    166                        
    167                         /* Add reference to the mounted root. */
    168                         mr_node = vfs_node_get(&mr_res);
    169                         assert(mr_node);
    170                        
    171                         fibril_rwlock_write_unlock(&namespace_rwlock);
    172                         async_answer_0(rid, rc);
    173                         return rc;
    174                 } else {
     91                if (str_cmp(mp, "/") != 0) {
    17592                        /*
    17693                         * We can't resolve this without the root filesystem
     
    18198                        return ENOENT;
    18299                }
    183         }
     100               
     101                /*
     102                 * For this simple, but important case,
     103                 * we are almost done.
     104                 */
     105                       
     106                /* Tell the mountee that it is being mounted. */
     107                exch = vfs_exchange_grab(fs_handle);
     108                msg = async_send_1(exch, VFS_OUT_MOUNTED,
     109                    (sysarg_t) service_id, &answer);
     110                /* Send the mount options */
     111                rc = async_data_write_start(exch, (void *)opts,
     112                    str_size(opts));
     113                vfs_exchange_release(exch);
     114                       
     115                if (rc != EOK) {
     116                        async_forget(msg);
     117                        fibril_rwlock_write_unlock(&namespace_rwlock);
     118                        async_answer_0(rid, rc);
     119                        return rc;
     120                }
     121                async_wait_for(msg, &rc);
     122                       
     123                if (rc != EOK) {
     124                        fibril_rwlock_write_unlock(&namespace_rwlock);
     125                        async_answer_0(rid, rc);
     126                        return rc;
     127                }
     128
     129                rindex = (fs_index_t) IPC_GET_ARG1(answer);
     130                rsize = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(answer),
     131                    IPC_GET_ARG3(answer));
     132                rlnkcnt = (unsigned) IPC_GET_ARG4(answer);
     133               
     134                mr_res.triplet.fs_handle = fs_handle;
     135                mr_res.triplet.service_id = service_id;
     136                mr_res.triplet.index = rindex;
     137                mr_res.size = rsize;
     138                mr_res.lnkcnt = rlnkcnt;
     139                mr_res.type = VFS_NODE_DIRECTORY;
     140                       
     141                /* Add reference to the mounted root. */
     142                root = vfs_node_get(&mr_res);
     143                assert(root);
     144                       
     145                fibril_rwlock_write_unlock(&namespace_rwlock);
     146                async_answer_0(rid, rc);
     147                return rc;
     148        }
     149       
     150        /* We already have the root FS. */
     151        if (str_cmp(mp, "/") == 0) {
     152                /* Trying to mount root FS over root FS */
     153                fibril_rwlock_write_unlock(&namespace_rwlock);
     154                async_answer_0(rid, EBUSY);
     155                return EBUSY;
     156        }
     157       
     158        rc = vfs_lookup_internal((vfs_triplet_t *) root, mp, L_DIRECTORY, &mp_res);
     159        if (rc != EOK) {
     160                /* The lookup failed. */
     161                fibril_rwlock_write_unlock(&namespace_rwlock);
     162                async_answer_0(rid, rc);
     163                return rc;
     164        }
     165       
     166        mp_node = vfs_node_get(&mp_res);
     167        if (!mp_node) {
     168                fibril_rwlock_write_unlock(&namespace_rwlock);
     169                async_answer_0(rid, ENOMEM);
     170                return ENOMEM;
     171        }
     172       
     173        /*
     174         * Now we hold a reference to mp_node.
     175         * It will be dropped upon the corresponding VFS_IN_UNMOUNT.
     176         * This prevents the mount point from being deleted.
     177         */
    184178       
    185179        /*
     
    435429         * Lookup the mounted root and instantiate it.
    436430         */
    437         rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL);
     431        rc = vfs_lookup_internal((vfs_triplet_t *) root, mp, 0, &mr_res);
    438432        if (rc != EOK) {
    439433                fibril_rwlock_write_unlock(&namespace_rwlock);
     
    488482                }
    489483               
    490                 rootfs.fs_handle = 0;
    491                 rootfs.service_id = 0;
     484                root = NULL;
    492485        } else {
    493486               
     
    499492                 */
    500493               
    501                 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
     494                rc = vfs_lookup_internal((vfs_triplet_t *) root, mp, L_MP, &mp_res);
    502495                if (rc != EOK) {
    503496                        fibril_rwlock_write_unlock(&namespace_rwlock);
     
    624617        /* Lookup the file structure corresponding to the file descriptor. */
    625618        vfs_file_t *parent = NULL;
    626         vfs_pair_t *parent_node = NULL;
     619        vfs_node_t *parent_node = root;
    627620        // TODO: Client-side root.
    628621        if (parentfd != -1) {
     
    633626                        return;
    634627                }
    635                 parent_node = (vfs_pair_t *)parent->node;
     628                parent_node = parent->node;
    636629        }
    637630       
     
    639632       
    640633        vfs_lookup_res_t lr;
    641         rc = vfs_lookup_internal(path, walk_lookup_flags(flags), &lr, parent_node);
     634        rc = vfs_lookup_internal((vfs_triplet_t *) parent_node, path, walk_lookup_flags(flags), &lr);
    642635        free(path);
    643636
     
    10691062        vfs_file_t *parent = NULL;
    10701063        vfs_file_t *expect = NULL;
    1071         vfs_pair_t *parent_node = NULL;
     1064        vfs_node_t *parent_node = root;
    10721065       
    10731066        int parentfd = IPC_GET_ARG1(*request);
     
    10911084                        goto exit;
    10921085                }
    1093                 parent_node = (vfs_pair_t *)parent->node;
     1086                parent_node = parent->node;
    10941087        }
    10951088       
     
    11021095               
    11031096                vfs_lookup_res_t lr;
    1104                 rc = vfs_lookup_internal(path, lflag, &lr, parent_node);
     1097                rc = vfs_lookup_internal((vfs_triplet_t *) parent_node, path, lflag, &lr);
    11051098                if (rc != EOK) {
    11061099                        goto exit;
     
    11171110       
    11181111        vfs_lookup_res_t lr;
    1119         rc = vfs_lookup_internal(path, lflag | L_UNLINK, &lr, parent_node);
     1112        rc = vfs_lookup_internal((vfs_triplet_t *) parent_node, path, lflag | L_UNLINK, &lr);
    11201113        if (rc != EOK) {
    11211114                goto exit;
     
    12011194       
    12021195        /* Lookup the node belonging to the old file name. */
    1203         rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
     1196        rc = vfs_lookup_internal((vfs_triplet_t *) root, oldc, L_NONE, &old_lr);
    12041197        if (rc != EOK) {
    12051198                fibril_rwlock_write_unlock(&namespace_rwlock);
     
    12371230       
    12381231        /* Lookup parent of the new file name. */
    1239         rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
     1232        rc = vfs_lookup_internal((vfs_triplet_t *) root, parentc, L_NONE, &new_par_lr);
    12401233        free(parentc);  /* not needed anymore */
    12411234        if (rc != EOK) {
     
    12611254        /* Destroy the old link for the new name. */
    12621255        vfs_node_t *new_node = NULL;
    1263         rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
     1256        rc = vfs_lookup_internal((vfs_triplet_t *) root, newc, L_UNLINK, &new_lr);
    12641257       
    12651258        switch (rc) {
     
    12911284       
    12921285        /* Create the new link for the new name. */
    1293         rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
     1286        rc = vfs_link_internal((vfs_triplet_t *) root, newc, (vfs_triplet_t *) old_node);
    12941287        if (rc != EOK) {
    12951288                fibril_rwlock_write_unlock(&namespace_rwlock);
     
    13081301       
    13091302        /* Destroy the link for the old name. */
    1310         rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
     1303        rc = vfs_lookup_internal((vfs_triplet_t *) root, oldc, L_UNLINK, NULL);
    13111304        if (rc != EOK) {
    13121305                fibril_rwlock_write_unlock(&namespace_rwlock);
Note: See TracChangeset for help on using the changeset viewer.