Changeset 5126f80 in mainline for uspace/srv/vfs/vfs_ops.c


Ignore:
Timestamp:
2017-03-08T11:42:17Z (8 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0d35511
Parents:
a737667e
git-author:
Jiri Zarevucky <zarevucky.jiri@…> (2017-03-08 11:42:17)
git-committer:
Jakub Jermar <jakub@…> (2017-03-08 11:42:17)
Message:

Merge from lp:~zarevucky-jiri/helenos/vfs-2.5/ revision 1946

Original commit messages:

1946: Jiri Zarevucky 2013-08-06 Relativize mount, add root handle to libc and remove root from VFS server. This wraps up the "relativization" phase.

Breakage:

  • Dynamic builds broken
  • Mount table lookups by name
File:
1 edited

Legend:

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

    ra737667e r5126f80  
    6868FIBRIL_RWLOCK_INITIALIZE(namespace_rwlock);
    6969
    70 vfs_node_t *root = NULL;
    71 
    7270static int vfs_connect_internal(service_id_t service_id, unsigned flags, unsigned instance,
    73         char *options, char *fsname, vfs_node_t **root)
     71    char *options, char *fsname, vfs_node_t **root)
    7472{
    7573        fs_handle_t fs_handle = 0;
     
    7977                fs_handle = fs_name_to_handle(instance, fsname, false);
    8078               
    81                 if (fs_handle != 0 || !(flags & IPC_FLAG_BLOCKING)) {
     79                if (fs_handle != 0 || !(flags & VFS_MOUNT_BLOCKING)) {
    8280                        break;
    8381                }
     
    123121}
    124122
    125 static int vfs_mount_internal(service_id_t service_id, unsigned flags, unsigned instance,
    126         char *opts, char *fs_name, char *mp)
    127 {
    128         /* Resolve the path to the mountpoint. */
    129        
    130         if (root == NULL) {
    131                 /* We still don't have the root file system mounted. */
    132                 if (str_cmp(mp, "/") != 0) {
    133                         /*
    134                          * We can't resolve this without the root filesystem
    135                          * being mounted first.
    136                          */
    137                         return ENOENT;
    138                 }
    139                
    140                 return vfs_connect_internal(service_id, flags, instance, opts, fs_name, &root);
    141         }
    142        
    143         /* We already have the root FS. */
    144         if (str_cmp(mp, "/") == 0) {
    145                 /* Trying to mount root FS over root FS */
    146                 return EBUSY;
    147         }
    148        
    149         vfs_lookup_res_t mp_res;
    150         int rc = vfs_lookup_internal(root, mp, L_DIRECTORY, &mp_res);
    151         if (rc != EOK) {
    152                 /* The lookup failed. */
    153                 return rc;
    154         }
    155        
    156         vfs_node_t *mp_node;
    157         mp_node = vfs_node_get(&mp_res);
    158         if (!mp_node) {
    159                 return ENOMEM;
    160         }
    161        
    162         if (mp_node->mount != NULL) {
    163                 return EBUSY;
    164         }
    165        
    166         if (mp_node->type != VFS_NODE_DIRECTORY) {
    167                 printf("%s node not a directory, type=%d\n", mp, mp_node->type);
    168                 return ENOTDIR;
    169         }
    170        
    171         if (vfs_node_has_children(mp_node)) {
    172                 return ENOTEMPTY;
    173         }
    174        
    175         vfs_node_t *mountee;
    176        
    177         rc = vfs_connect_internal(service_id, flags, instance, opts, fs_name, &mountee);
    178         if (rc != EOK) {
    179                 vfs_node_put(mp_node);
    180                 return ENOMEM;
    181         }
    182        
    183         mp_node->mount = mountee;
    184         /* The two references to nodes are held by the mount so that they cannot be freed.
    185          * They are removed in detach_internal().
    186          */
    187         return EOK;
    188 }
    189 
    190123void vfs_mount_srv(ipc_callid_t rid, ipc_call_t *request)
    191124{
     125        int mpfd = IPC_GET_ARG1(*request);
     126       
    192127        /*
    193128         * We expect the library to do the device-name to device-handle
     
    195130         * in the request.
    196131         */
    197         service_id_t service_id = (service_id_t) IPC_GET_ARG1(*request);
     132        service_id_t service_id = (service_id_t) IPC_GET_ARG2(*request);
    198133       
    199134        /*
    200135         * Mount flags are passed as ARG2.
    201136         */
    202         unsigned int flags = (unsigned int) IPC_GET_ARG2(*request);
     137        unsigned int flags = (unsigned int) IPC_GET_ARG3(*request);
    203138       
    204139        /*
    205140         * Instance number is passed as ARG3.
    206141         */
    207         unsigned int instance = IPC_GET_ARG3(*request);
    208 
    209         /* We want the client to send us the mount point. */
    210         char *mp;
    211         int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
     142        unsigned int instance = IPC_GET_ARG4(*request);
     143       
     144        char *opts = NULL;
     145        char *fs_name = NULL;
     146        vfs_file_t *mp = NULL;
     147        vfs_file_t *file = NULL;
     148        int fd = -1;
     149        mtab_ent_t *mtab_ent = NULL;
     150
     151        /* Now we expect to receive the mount options. */
     152        int rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
    212153            0, NULL);
    213154        if (rc != EOK) {
    214                 async_answer_0(rid, rc);
    215                 return;
    216         }
    217        
    218         /* Now we expect to receive the mount options. */
    219         char *opts;
    220         rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
    221             0, NULL);
    222         if (rc != EOK) {
    223                 async_answer_0(rid, rc);
    224                 free(mp);
    225                 return;
     155                async_data_write_void(rc);
     156                goto out;
    226157        }
    227158       
     
    230161         * system.
    231162         */
    232         char *fs_name;
    233163        rc = async_data_write_accept((void **) &fs_name, true, 0,
    234164            FS_NAME_MAXLEN, 0, NULL);
    235165        if (rc != EOK) {
    236                 async_answer_0(rid, rc);
    237                 free(mp);
    238                 free(opts);
    239                 return;
     166                goto out;
     167        }
     168       
     169        if (!(flags & VFS_MOUNT_CONNECT_ONLY)) {
     170                mp = vfs_file_get(mpfd);
     171                if (mp == NULL) {
     172                        rc = EBADF;
     173                        goto out;
     174                }
     175               
     176                if (mp->node->mount != NULL) {
     177                        rc = EBUSY;
     178                        goto out;
     179                }
     180               
     181                if (mp->node->type != VFS_NODE_DIRECTORY) {
     182                        rc = ENOTDIR;
     183                        goto out;
     184                }
     185               
     186                if (vfs_node_has_children(mp->node)) {
     187                        rc = ENOTEMPTY;
     188                        goto out;
     189                }
     190        }
     191       
     192        if (!(flags & VFS_MOUNT_NO_REF)) {
     193                fd = vfs_fd_alloc(&file, false);
     194                if (fd < 0) {
     195                        rc = fd;
     196                        goto out;
     197                }
    240198        }
    241199       
    242200        /* Add the filesystem info to the list of mounted filesystems */
    243         mtab_ent_t *mtab_ent = malloc(sizeof(mtab_ent_t));
     201        mtab_ent = malloc(sizeof(mtab_ent_t));
    244202        if (!mtab_ent) {
    245                 async_answer_0(rid, ENOMEM);
    246                 free(mp);
    247                 free(fs_name);
    248                 free(opts);
    249                 return;
    250         }
    251        
    252         /* Mount the filesystem. */
     203                rc = ENOMEM;
     204                goto out;
     205        }
     206       
     207        vfs_node_t *root = NULL;
     208       
    253209        fibril_rwlock_write_lock(&namespace_rwlock);
    254         rc = vfs_mount_internal(service_id, flags, instance, opts, fs_name, mp);
     210
     211        rc = vfs_connect_internal(service_id, flags, instance, opts, fs_name, &root);
     212        if (rc == EOK && !(flags & VFS_MOUNT_CONNECT_ONLY)) {
     213                vfs_node_addref(mp->node);
     214                vfs_node_addref(root);
     215                mp->node->mount = root;
     216        }
     217       
    255218        fibril_rwlock_write_unlock(&namespace_rwlock);
    256 
     219       
     220        if (rc != EOK) {
     221                goto out;
     222        }
     223       
     224       
     225        if (flags & VFS_MOUNT_NO_REF) {
     226                vfs_node_delref(root);
     227        } else {
     228                assert(file != NULL);
     229               
     230                file->node = root;
     231                file->permissions = MODE_READ | MODE_WRITE | MODE_APPEND;
     232                file->open_read = false;
     233                file->open_write = false;
     234        }
     235       
    257236        /* Add the filesystem info to the list of mounted filesystems */
    258237        if (rc == EOK) {
    259                 str_cpy(mtab_ent->mp, MAX_PATH_LEN, mp);
     238                str_cpy(mtab_ent->mp, MAX_PATH_LEN, "fixme");
    260239                str_cpy(mtab_ent->fs_name, FS_NAME_MAXLEN, fs_name);
    261240                str_cpy(mtab_ent->opts, MAX_MNTOPTS_LEN, opts);
     
    269248                mtab_size++;
    270249                fibril_mutex_unlock(&mtab_list_lock);
    271         }
    272        
    273         async_answer_0(rid, rc);
    274 
    275         free(mp);
    276         free(fs_name);
    277         free(opts);
     250        }       
     251       
     252        rc = EOK;
     253
     254out:
     255        async_answer_1(rid, rc, rc == EOK ? fd : 0);
     256
     257        if (opts) {
     258                free(opts);
     259        }
     260        if (fs_name) {
     261                free(fs_name);
     262        }
     263        if (mp) {
     264                vfs_file_put(mp);
     265        }
     266        if (file) {
     267                vfs_file_put(file);
     268        }
     269        if (rc != EOK && fd >= 0) {
     270                vfs_fd_free(fd);
     271        }
    278272}
    279273
    280274void vfs_unmount_srv(ipc_callid_t rid, ipc_call_t *request)
    281275{
    282         /*
    283          * Receive the mount point path.
    284          */
    285         char *mp;
    286         int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
    287             0, NULL);
    288         if (rc != EOK)
    289                 async_answer_0(rid, rc);
    290        
    291         /*
    292          * Taking the namespace lock will do two things for us. First, it will
    293          * prevent races with other lookup operations. Second, it will stop new
    294          * references to already existing VFS nodes and creation of new VFS
    295          * nodes. This is because new references are added as a result of some
    296          * lookup operation or at least of some operation which is protected by
    297          * the namespace lock.
    298          */
     276        int mpfd = IPC_GET_ARG1(*request);
     277       
     278        vfs_file_t *mp = vfs_file_get(mpfd);
     279        if (mp == NULL) {
     280                async_answer_0(rid, EBADF);
     281                return;
     282        }
     283       
     284        if (mp->node->mount == NULL) {
     285                async_answer_0(rid, ENOENT);
     286                vfs_file_put(mp);
     287                return;
     288        }
     289       
    299290        fibril_rwlock_write_lock(&namespace_rwlock);
    300                
    301         if (str_cmp(mp, "/") == 0) {
    302                 free(mp);
    303                
    304                 /*
    305                  * Unmounting the root file system.
    306                  *
    307                  * In this case, there is no mount point node and we send
    308                  * VFS_OUT_UNMOUNTED directly to the mounted file system.
    309                  */
    310                
    311                 if (!root) {
    312                         fibril_rwlock_write_unlock(&namespace_rwlock);
    313                         async_answer_0(rid, ENOENT);
    314                         return;
    315                 }
    316                
    317                 /*
    318                  * Count the total number of references for the mounted file system. We
    319                  * are expecting at least one, which we got when the file system was mounted.
    320                  * If we find more, it means that
    321                  * the file system cannot be gracefully unmounted at the moment because
    322                  * someone is working with it.
    323                  */
    324                 if (vfs_nodes_refcount_sum_get(root->fs_handle, root->service_id) != 1) {
    325                         fibril_rwlock_write_unlock(&namespace_rwlock);
    326                         async_answer_0(rid, EBUSY);
    327                         return;
    328                 }
    329                
    330                 async_exch_t *exch = vfs_exchange_grab(root->fs_handle);
    331                 rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, root->service_id);
    332                 vfs_exchange_release(exch);
    333                
    334                 fibril_rwlock_write_unlock(&namespace_rwlock);
    335                 if (rc == EOK) {
    336                         vfs_node_forget(root);
    337                         root = NULL;
    338                 }
    339                 async_answer_0(rid, rc);
    340                 return;
    341         }
    342        
    343         /*
    344          * Lookup the mounted root and instantiate it.
    345          */
    346         vfs_lookup_res_t mp_res;
    347         rc = vfs_lookup_internal(root, mp, L_MP, &mp_res);
    348         if (rc != EOK) {
    349                 fibril_rwlock_write_unlock(&namespace_rwlock);
    350                 free(mp);
    351                 async_answer_0(rid, rc);
    352                 return;
    353         }
    354         vfs_node_t *mp_node = vfs_node_get(&mp_res);
    355         if (!mp_node) {
    356                 fibril_rwlock_write_unlock(&namespace_rwlock);
    357                 free(mp);
    358                 async_answer_0(rid, ENOMEM);
    359                 return;
    360         }
    361        
    362         if (mp_node->mount == NULL) {
    363                 fibril_rwlock_write_unlock(&namespace_rwlock);
    364                 vfs_node_put(mp_node);
    365                 free(mp);
    366                 async_answer_0(rid, ENOENT);
    367                 return;
    368         }
    369291       
    370292        /*
    371293         * Count the total number of references for the mounted file system. We
    372          * are expecting at least one, which we got when the file system was mounted.
     294         * are expecting at least one, which is held by the mount point.
    373295         * If we find more, it means that
    374296         * the file system cannot be gracefully unmounted at the moment because
    375297         * someone is working with it.
    376298         */
    377         if (vfs_nodes_refcount_sum_get(mp_node->mount->fs_handle, mp_node->mount->service_id) != 1) {
     299        if (vfs_nodes_refcount_sum_get(mp->node->mount->fs_handle, mp->node->mount->service_id) != 1) {
     300                async_answer_0(rid, EBUSY);
     301                vfs_file_put(mp);
    378302                fibril_rwlock_write_unlock(&namespace_rwlock);
    379                 vfs_node_put(mp_node);
    380                 free(mp);
    381                 async_answer_0(rid, EBUSY);
    382                 return;
    383         }
    384        
    385         /* Unmount the filesystem. */
    386         async_exch_t *exch = vfs_exchange_grab(mp_node->mount->fs_handle);
    387         rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, mp_node->mount->service_id);
     303                return;
     304        }
     305       
     306        async_exch_t *exch = vfs_exchange_grab(mp->node->mount->fs_handle);
     307        int rc = async_req_1_0(exch, VFS_OUT_UNMOUNTED, mp->node->mount->service_id);
    388308        vfs_exchange_release(exch);
    389309       
    390         vfs_node_forget(mp_node->mount);
    391         mp_node->mount = NULL;
    392        
    393         vfs_node_put(mp_node);
     310        if (rc != EOK) {
     311                async_answer_0(rid, rc);
     312                vfs_file_put(mp);
     313                fibril_rwlock_write_unlock(&namespace_rwlock);
     314                return;
     315        }
     316       
     317        vfs_node_forget(mp->node->mount);
     318        vfs_node_put(mp->node);
     319        mp->node->mount = NULL;
     320       
    394321        fibril_rwlock_write_unlock(&namespace_rwlock);
    395322       
     
    398325
    399326        list_foreach(mtab_list, link, mtab_ent_t, mtab_ent) {
    400                 if (str_cmp(mtab_ent->mp, mp) == 0) {
     327                // FIXME: mp name
     328                if (str_cmp(mtab_ent->mp, "fixme") == 0) {
    401329                        list_remove(&mtab_ent->link);
    402330                        mtab_size--;
     
    408336        assert(found);
    409337        fibril_mutex_unlock(&mtab_list_lock);
    410 
    411         free(mp);       
    412        
     338       
     339        vfs_file_put(mp);
    413340        async_answer_0(rid, EOK);
    414         return;
    415341}
    416342
     
    448374        if (flags&WALK_DIRECTORY) {
    449375                lflags |= L_DIRECTORY;
     376        }
     377        if (flags&WALK_MOUNT_POINT) {
     378                lflags |= L_MP;
    450379        }
    451380        return lflags;
     
    470399       
    471400        /* Lookup the file structure corresponding to the file descriptor. */
    472         vfs_file_t *parent = NULL;
    473         vfs_node_t *parent_node = root;
    474         // TODO: Client-side root.
    475         if (parentfd != -1) {
    476                 parent = vfs_file_get(parentfd);
    477                 if (!parent) {
    478                         free(path);
    479                         async_answer_0(rid, EBADF);
    480                         return;
    481                 }
    482                 parent_node = parent->node;
     401        vfs_file_t *parent = vfs_file_get(parentfd);
     402        if (!parent) {
     403                free(path);
     404                async_answer_0(rid, EBADF);
     405                return;
    483406        }
    484407       
     
    486409       
    487410        vfs_lookup_res_t lr;
    488         rc = vfs_lookup_internal(parent_node, path, walk_lookup_flags(flags), &lr);
     411        rc = vfs_lookup_internal(parent->node, path, walk_lookup_flags(flags), &lr);
    489412        free(path);
    490413
     
    963886        vfs_file_t *parent = NULL;
    964887        vfs_file_t *expect = NULL;
    965         vfs_node_t *parent_node = root;
    966888       
    967889        int parentfd = IPC_GET_ARG1(*request);
     
    974896                return;
    975897        }
     898        if (parentfd == expectfd) {
     899                async_answer_0(rid, EINVAL);
     900                return;
     901        }
    976902       
    977903        fibril_rwlock_write_lock(&namespace_rwlock);
     
    980906
    981907        /* Files are retrieved in order of file descriptors, to prevent deadlock. */
    982         if (parentfd >= 0 && parentfd < expectfd) {
     908        if (parentfd < expectfd) {
    983909                parent = vfs_file_get(parentfd);
    984910                if (!parent) {
    985                         rc = ENOENT;
     911                        rc = EBADF;
    986912                        goto exit;
    987913                }
     
    996922        }
    997923       
    998         if (parentfd >= 0 && parentfd >= expectfd) {
     924        if (parentfd > expectfd) {
    999925                parent = vfs_file_get(parentfd);
    1000926                if (!parent) {
    1001                         rc = ENOENT;
     927                        rc = EBADF;
    1002928                        goto exit;
    1003929                }
    1004930        }
    1005931       
    1006         if (parent) {
    1007                 parent_node = parent->node;
    1008         }
     932        assert(parent != NULL);
    1009933       
    1010934        if (expectfd >= 0) {
    1011935                vfs_lookup_res_t lr;
    1012                 rc = vfs_lookup_internal(parent_node, path, lflag, &lr);
     936                rc = vfs_lookup_internal(parent->node, path, lflag, &lr);
    1013937                if (rc != EOK) {
    1014938                        goto exit;
     
    1026950       
    1027951        vfs_lookup_res_t lr;
    1028         rc = vfs_lookup_internal(parent_node, path, lflag | L_UNLINK, &lr);
     952        rc = vfs_lookup_internal(parent->node, path, lflag | L_UNLINK, &lr);
    1029953        if (rc != EOK) {
    1030954                goto exit;
     
    11881112       
    11891113        /* Lookup the file structure corresponding to the file descriptor. */
    1190         vfs_node_t *base_node = root;
    1191         // TODO: Client-side root.
    1192         if (basefd != -1) {
    1193                 base = vfs_file_get(basefd);
    1194                 if (!base) {
    1195                         rc = EBADF;
    1196                         goto out;
    1197                 }
    1198                 base_node = base->node;
    1199         }
    1200        
    1201         rc = vfs_rename_internal(base_node, oldc, newc);
     1114        base = vfs_file_get(basefd);
     1115        if (!base) {
     1116                rc = EBADF;
     1117                goto out;
     1118        }
     1119       
     1120        rc = vfs_rename_internal(base->node, oldc, newc);
    12021121
    12031122out:
     
    13581277        /* Lookup the file structure corresponding to fd. */
    13591278        vfs_file_t *oldfile = vfs_file_get(oldfd);
    1360         if (!oldfile) {
     1279        if (oldfile == NULL) {
    13611280                async_answer_0(rid, EBADF);
    13621281                return;
     
    13651284        vfs_file_t *newfile;
    13661285        int newfd = vfs_fd_alloc(&newfile, desc);
     1286        async_answer_0(rid, newfd);
     1287       
    13671288        if (newfd < 0) {
    1368                 async_answer_0(rid, newfd);
    13691289                vfs_file_put(oldfile);
    13701290                return;
     
    13791299        vfs_file_put(oldfile);
    13801300        vfs_file_put(newfile);
    1381        
    1382         async_answer_0(rid, newfd);
    13831301}
    13841302
Note: See TracChangeset for help on using the changeset viewer.