Changeset 5bcd5b7 in mainline for uspace/srv/vfs/vfs_lookup.c


Ignore:
Timestamp:
2013-07-29T14:36:57Z (11 years ago)
Author:
Jiri Zarevucky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4636a60
Parents:
677745a
Message:

Add support for server-side mounts.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/vfs/vfs_lookup.c

    r677745a r5bcd5b7  
    153153}
    154154
    155 int vfs_link_internal(vfs_triplet_t *base, char *path, vfs_triplet_t *child)
     155int vfs_link_internal(vfs_node_t *base, char *path, vfs_triplet_t *child)
    156156{
    157157        assert(base != NULL);
     
    173173        path = npath;
    174174       
     175        vfs_triplet_t *triplet;
     176       
    175177        char *slash = _strrchr(path, '/');
    176178        if (slash && slash != path) {
     
    187189                        goto out;
    188190                }
    189                 base = &res.triplet;
     191                triplet = &res.triplet;
    190192               
    191193                *slash = '/';
    192194        } else {
     195                if (base->mount != NULL) {
     196                        rc = EINVAL;
     197                        goto out;
     198                }
     199               
    193200                memcpy(component, path + 1, str_size(path));
    194         }
    195        
    196         if (base->fs_handle != child->fs_handle || base->service_id != child->service_id) {
     201                triplet = (vfs_triplet_t *) base;
     202        }
     203       
     204        if (triplet->fs_handle != child->fs_handle || triplet->service_id != child->service_id) {
    197205                rc = EXDEV;
    198206                goto out;
    199207        }
    200208       
    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);
     209        async_exch_t *exch = vfs_exchange_grab(triplet->fs_handle);
     210        aid_t req = async_send_3(exch, VFS_OUT_LINK, triplet->service_id, triplet->index, child->index, NULL);
    203211       
    204212        rc = async_data_write_start(exch, component, str_size(component) + 1);
     
    215223}
    216224
     225static int out_lookup(vfs_triplet_t *base, unsigned *pfirst, unsigned *plen,
     226        int lflag, vfs_lookup_res_t *result)
     227{
     228        assert(base);
     229        assert(result);
     230       
     231        sysarg_t rc;
     232        ipc_call_t answer;
     233        async_exch_t *exch = vfs_exchange_grab(base->fs_handle);
     234        aid_t req = async_send_5(exch, VFS_OUT_LOOKUP, (sysarg_t) *pfirst, (sysarg_t) *plen,
     235            (sysarg_t) base->service_id, (sysarg_t) base->index, (sysarg_t) lflag, &answer);
     236        async_wait_for(req, &rc);
     237        vfs_exchange_release(exch);
     238       
     239        if ((int) rc < 0) {
     240                return (int) rc;
     241        }
     242       
     243        unsigned last = *pfirst + *plen;
     244        *pfirst = IPC_GET_ARG3(answer);
     245        *plen = last - *pfirst;
     246       
     247        result->triplet.fs_handle = (fs_handle_t) rc;
     248        result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer);
     249        result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
     250        result->size = (int64_t)(int32_t) IPC_GET_ARG4(answer);
     251        result->type = IPC_GET_ARG5(answer);
     252        return EOK;
     253}
     254
    217255/** Perform a path lookup.
    218256 *
     
    227265 *
    228266 */
    229 int vfs_lookup_internal(vfs_triplet_t *base, char *path, int lflag, vfs_lookup_res_t *result)
     267int vfs_lookup_internal(vfs_node_t *base, char *path, int lflag, vfs_lookup_res_t *result)
    230268{
    231269        assert(base != NULL);
    232270        assert(path != NULL);
    233271       
    234         sysarg_t rc;
    235        
    236         if (!base->fs_handle) {
    237                 rc = ENOENT;
    238                 goto out;
    239         }
    240        
    241272        size_t len;
     273        int rc;
    242274        char *npath = canonify(path, &len);
    243275        if (!npath) {
     276                DPRINTF("vfs_lookup_internal() can't canonify path: %s\n", path);
    244277                rc = EINVAL;
    245                 goto out;
     278                return rc;
    246279        }
    247280        path = npath;
     
    254287        rc = plb_insert_entry(&entry, path, &first, len);
    255288        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        
     289                DPRINTF("vfs_lookup_internal() can't insert entry into PLB: %d\n", rc);
     290                return rc;
     291        }
     292       
     293        size_t next = first;
     294        size_t nlen = len;
     295       
     296        vfs_lookup_res_t res;
     297       
     298        /* Resolve path as long as there are mount points to cross. */
     299        while (nlen > 0) {
     300                while (base->mount != NULL) {
     301                        if (lflag & L_DISABLE_MOUNTS) {
     302                                rc = EXDEV;
     303                                goto out;
     304                        }
     305                       
     306                        base = base->mount;
     307                }
     308               
     309                rc = out_lookup((vfs_triplet_t *) base, &next, &nlen, lflag, &res);
     310                if (rc != EOK) {
     311                        goto out;
     312                }
     313               
     314                if (nlen > 0) {
     315                        base = vfs_node_peek(&res);
     316                        if (base == NULL || base->mount == NULL) {
     317                                rc = ENOENT;
     318                                goto out;
     319                        }
     320                        if (lflag & L_DISABLE_MOUNTS) {
     321                                rc = EXDEV;
     322                                goto out;
     323                        }
     324                }
     325        }
     326       
     327        assert(nlen == 0);
     328        rc = EOK;
     329       
     330        if (result != NULL) {
     331                /* The found file may be a mount point. Try to cross it. */
     332                if (!(lflag & L_MP)) {
     333                        base = vfs_node_peek(&res);
     334                        if (base != NULL && base->mount != NULL) {
     335                                while (base->mount != NULL) {
     336                                        base = base->mount;
     337                                }
     338                               
     339                                result->triplet = *(vfs_triplet_t *)base;
     340                                result->type = base->type;
     341                                result->size = base->size;                             
     342                                goto out;
     343                        }
     344                }
     345
     346                __builtin_memcpy(result, &res, sizeof(vfs_lookup_res_t));
     347        }
     348       
     349out:
    266350        plb_clear_entry(&entry, first, len);
    267        
    268         if ((int) rc < 0) {
    269                 goto out;
    270         }
    271        
    272         unsigned last = IPC_GET_ARG3(answer);
    273         if (last != first + len) {
    274                 /* The path wasn't processed entirely. */
    275                 rc = ENOENT;
    276                 goto out;
    277         }
    278        
    279         if (!result) {
    280                 rc = EOK;
    281                 goto out;
    282         }
    283        
    284         result->triplet.fs_handle = (fs_handle_t) rc;
    285         result->triplet.service_id = (service_id_t) IPC_GET_ARG1(answer);
    286         result->triplet.index = (fs_index_t) IPC_GET_ARG2(answer);
    287         result->size = (int64_t)(int32_t) IPC_GET_ARG4(answer);
    288         result->type = IPC_GET_ARG5(answer);
    289         rc = EOK;
    290 
    291 out:
    292351        DPRINTF("vfs_lookup_internal() with path '%s' returns %d\n", path, rc);
    293352        return rc;
Note: See TracChangeset for help on using the changeset viewer.