Changeset 3b3e776 in mainline for uspace/srv/vfs/vfs_ops.c


Ignore:
Timestamp:
2010-02-05T10:57:50Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0358da0
Parents:
3f085132 (diff), b4cbef1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merged with head

File:
1 edited

Legend:

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

    r3f085132 r3b3e776  
    4444#include <string.h>
    4545#include <bool.h>
    46 #include <fibril_sync.h>
     46#include <fibril_synch.h>
    4747#include <adt/list.h>
    4848#include <unistd.h>
     
    9292                }
    9393               
    94                 rc = vfs_lookup_internal(mp, L_DIRECTORY, &mp_res, NULL);
     94                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
    9595                if (rc != EOK) {
    9696                        /* The lookup failed for some reason. */
     
    266266       
    267267        /* We want the client to send us the mount point. */
    268         ipc_callid_t callid;
    269         size_t size;
    270         if (!async_data_write_receive(&callid, &size)) {
    271                 ipc_answer_0(callid, EINVAL);
    272                 ipc_answer_0(rid, EINVAL);
    273                 return;
    274         }
    275        
    276         /* Check whether size is reasonable wrt. the mount point. */
    277         if ((size < 1) || (size > MAX_PATH_LEN)) {
    278                 ipc_answer_0(callid, EINVAL);
    279                 ipc_answer_0(rid, EINVAL);
    280                 return;
    281         }
    282        
    283         /* Allocate buffer for the mount point data being received. */
    284         char *mp = malloc(size + 1);
    285         if (!mp) {
    286                 ipc_answer_0(callid, ENOMEM);
    287                 ipc_answer_0(rid, ENOMEM);
    288                 return;
    289         }
    290        
    291         /* Deliver the mount point. */
    292         ipcarg_t retval = async_data_write_finalize(callid, mp, size);
    293         if (retval != EOK) {
    294                 ipc_answer_0(rid, retval);
     268        char *mp;
     269        int rc = async_string_receive(&mp, MAX_PATH_LEN, NULL);
     270        if (rc != EOK) {
     271                ipc_answer_0(rid, rc);
     272                return;
     273        }
     274       
     275        /* Now we expect to receive the mount options. */
     276        char *opts;
     277        rc = async_string_receive(&opts, MAX_MNTOPTS_LEN, NULL);
     278        if (rc != EOK) {
    295279                free(mp);
    296                 return;
    297         }
    298         mp[size] = '\0';
    299        
    300         /* Now we expect to receive the mount options. */
    301         if (!async_data_write_receive(&callid, &size)) {
    302                 ipc_answer_0(callid, EINVAL);
    303                 ipc_answer_0(rid, EINVAL);
    304                 free(mp);
    305                 return;
    306         }
    307 
    308         /* Check the offered options size. */
    309         if (size > MAX_MNTOPTS_LEN) {
    310                 ipc_answer_0(callid, EINVAL);
    311                 ipc_answer_0(rid, EINVAL);
    312                 free(mp);
    313                 return;
    314         }
    315 
    316         /* Allocate buffer for the mount options. */
    317         char *opts = (char *) malloc(size + 1);
    318         if (!opts) {
    319                 ipc_answer_0(callid, ENOMEM);
    320                 ipc_answer_0(rid, ENOMEM);
    321                 free(mp);
    322                 return;
    323         }
    324 
    325         /* Deliver the mount options. */
    326         retval = async_data_write_finalize(callid, opts, size);
    327         if (retval != EOK) {
    328                 ipc_answer_0(rid, retval);
     280                ipc_answer_0(rid, rc);
     281                return;
     282        }
     283       
     284        /*
     285         * Now, we expect the client to send us data with the name of the file
     286         * system.
     287         */
     288        char *fs_name;
     289        rc = async_string_receive(&fs_name, FS_NAME_MAXLEN, NULL);
     290        if (rc != EOK) {
    329291                free(mp);
    330292                free(opts);
    331                 return;
    332         }
    333         opts[size] = '\0';
    334        
    335         /*
    336          * Now, we expect the client to send us data with the name of the file
    337          * system.
    338          */
    339         if (!async_data_write_receive(&callid, &size)) {
    340                 ipc_answer_0(callid, EINVAL);
    341                 ipc_answer_0(rid, EINVAL);
    342                 free(mp);
    343                 free(opts);
    344                 return;
    345         }
    346        
    347         /*
    348          * Don't receive more than is necessary for storing a full file system
    349          * name.
    350          */
    351         if ((size < 1) || (size > FS_NAME_MAXLEN)) {
    352                 ipc_answer_0(callid, EINVAL);
    353                 ipc_answer_0(rid, EINVAL);
    354                 free(mp);
    355                 free(opts);
    356                 return;
    357         }
    358        
    359         /*
    360          * Allocate buffer for file system name.
    361          */
    362         char *fs_name = (char *) malloc(size + 1);
    363         if (fs_name == NULL) {
    364                 ipc_answer_0(callid, ENOMEM);
    365                 ipc_answer_0(rid, ENOMEM);
    366                 free(mp);
    367                 free(opts);
    368                 return;
    369         }
    370        
    371         /* Deliver the file system name. */
    372         retval = async_data_write_finalize(callid, fs_name, size);
    373         if (retval != EOK) {
    374                 ipc_answer_0(rid, retval);
    375                 free(mp);
    376                 free(opts);
    377                 free(fs_name);
    378                 return;
    379         }
    380         fs_name[size] = '\0';
    381 
     293                ipc_answer_0(rid, rc);
     294                return;
     295        }
     296       
    382297        /*
    383298         * Wait for IPC_M_PING so that we can return an error if we don't know
     
    385300         */
    386301        ipc_call_t data;
    387         callid = async_get_call(&data);
     302        ipc_callid_t callid = async_get_call(&data);
    388303        if (IPC_GET_METHOD(data) != IPC_M_PING) {
    389304                ipc_answer_0(callid, ENOTSUP);
     
    429344}
    430345
     346void vfs_unmount(ipc_callid_t rid, ipc_call_t *request)
     347{
     348        int rc;
     349        char *mp;
     350        vfs_lookup_res_t mp_res;
     351        vfs_lookup_res_t mr_res;
     352        vfs_node_t *mp_node;
     353        vfs_node_t *mr_node;
     354        int phone;
     355
     356        /*
     357         * Receive the mount point path.
     358         */
     359        rc = async_string_receive(&mp, MAX_PATH_LEN, NULL);
     360        if (rc != EOK)
     361                ipc_answer_0(rid, rc);
     362
     363        /*
     364         * Taking the namespace lock will do two things for us. First, it will
     365         * prevent races with other lookup operations. Second, it will stop new
     366         * references to already existing VFS nodes and creation of new VFS
     367         * nodes. This is because new references are added as a result of some
     368         * lookup operation or at least of some operation which is protected by
     369         * the namespace lock.
     370         */
     371        fibril_rwlock_write_lock(&namespace_rwlock);
     372       
     373        /*
     374         * Lookup the mounted root and instantiate it.
     375         */
     376        rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL);
     377        if (rc != EOK) {
     378                fibril_rwlock_write_unlock(&namespace_rwlock);
     379                free(mp);
     380                ipc_answer_0(rid, rc);
     381                return;
     382        }
     383        mr_node = vfs_node_get(&mr_res);
     384        if (!mr_node) {
     385                fibril_rwlock_write_unlock(&namespace_rwlock);
     386                free(mp);
     387                ipc_answer_0(rid, ENOMEM);
     388                return;
     389        }
     390
     391        /*
     392         * Count the total number of references for the mounted file system. We
     393         * are expecting at least two. One which we got above and one which we
     394         * got when the file system was mounted. If we find more, it means that
     395         * the file system cannot be gracefully unmounted at the moment because
     396         * someone is working with it.
     397         */
     398        if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
     399            mr_node->dev_handle) != 2) {
     400                fibril_rwlock_write_unlock(&namespace_rwlock);
     401                vfs_node_put(mr_node);
     402                free(mp);
     403                ipc_answer_0(rid, EBUSY);
     404                return;
     405        }
     406
     407        if (str_cmp(mp, "/") == 0) {
     408
     409                /*
     410                 * Unmounting the root file system.
     411                 *
     412                 * In this case, there is no mount point node and we send
     413                 * VFS_OUT_UNMOUNTED directly to the mounted file system.
     414                 */
     415
     416                free(mp);
     417                phone = vfs_grab_phone(mr_node->fs_handle);
     418                rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
     419                    mr_node->dev_handle);
     420                vfs_release_phone(phone);
     421                if (rc != EOK) {
     422                        fibril_rwlock_write_unlock(&namespace_rwlock);
     423                        vfs_node_put(mr_node);
     424                        ipc_answer_0(rid, rc);
     425                        return;
     426                }
     427                rootfs.fs_handle = 0;
     428                rootfs.dev_handle = 0;
     429        } else {
     430
     431                /*
     432                 * Unmounting a non-root file system.
     433                 *
     434                 * We have a regular mount point node representing the parent
     435                 * file system, so we delegate the operation to it.
     436                 */
     437
     438                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
     439                free(mp);
     440                if (rc != EOK) {
     441                        fibril_rwlock_write_unlock(&namespace_rwlock);
     442                        vfs_node_put(mr_node);
     443                        ipc_answer_0(rid, rc);
     444                        return;
     445                }
     446                vfs_node_t *mp_node = vfs_node_get(&mp_res);
     447                if (!mp_node) {
     448                        fibril_rwlock_write_unlock(&namespace_rwlock);
     449                        vfs_node_put(mr_node);
     450                        ipc_answer_0(rid, ENOMEM);
     451                        return;
     452                }
     453
     454                phone = vfs_grab_phone(mp_node->fs_handle);
     455                rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle,
     456                    mp_node->index);
     457                vfs_release_phone(phone);
     458                if (rc != EOK) {
     459                        fibril_rwlock_write_unlock(&namespace_rwlock);
     460                        vfs_node_put(mp_node);
     461                        vfs_node_put(mr_node);
     462                        ipc_answer_0(rid, rc);
     463                        return;
     464                }
     465
     466                /* Drop the reference we got above. */
     467                vfs_node_put(mp_node);
     468                /* Drop the reference from when the file system was mounted. */
     469                vfs_node_put(mp_node);
     470        }
     471
     472
     473        /*
     474         * All went well, the mounted file system was successfully unmounted.
     475         * The only thing left is to forget the unmounted root VFS node.
     476         */
     477        vfs_node_forget(mr_node);
     478
     479        fibril_rwlock_write_unlock(&namespace_rwlock);
     480        ipc_answer_0(rid, EOK);
     481}
     482
    431483void vfs_open(ipc_callid_t rid, ipc_call_t *request)
    432484{
     
    454506        /*
    455507         * Make sure that we are called with exactly one of L_FILE and
    456          * L_DIRECTORY. Make sure that the user does not pass L_OPEN.
     508         * L_DIRECTORY. Make sure that the user does not pass L_OPEN,
     509         * L_ROOT or L_MP.
    457510         */
    458511        if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
    459512            ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
    460             ((lflag & L_OPEN) != 0)) {
     513            (lflag & (L_OPEN | L_ROOT | L_MP))) {
    461514                ipc_answer_0(rid, EINVAL);
    462515                return;
     
    468521                lflag |= L_EXCLUSIVE;
    469522       
    470         ipc_callid_t callid;
    471         if (!async_data_write_receive(&callid, &len)) {
    472                 ipc_answer_0(callid, EINVAL);
    473                 ipc_answer_0(rid, EINVAL);
    474                 return;
    475         }
    476        
    477         char *path = malloc(len + 1);
    478         if (!path) {
    479                 ipc_answer_0(callid, ENOMEM);
    480                 ipc_answer_0(rid, ENOMEM);
    481                 return;
    482         }
    483        
    484         int rc;
    485         if ((rc = async_data_write_finalize(callid, path, len))) {
    486                 ipc_answer_0(rid, rc);
    487                 free(path);
    488                 return;
    489         }
    490         path[len] = '\0';
     523        char *path;
     524        int rc = async_string_receive(&path, 0, NULL);
     525        if (rc != EOK) {
     526                ipc_answer_0(rid, rc);
     527                return;
     528        }
    491529       
    492530        /*
     
    679717}
    680718
    681 static int vfs_close_internal(vfs_file_t *file)
     719int vfs_close_internal(vfs_file_t *file)
    682720{
    683721        /*
     
    756794       
    757795        /*
    758          * Now we need to receive a call with client's
    759          * IPC_M_DATA_READ/IPC_M_DATA_WRITE request.
    760          */
    761         ipc_callid_t callid;
    762         int res;
    763         if (read)
    764                 res = async_data_read_receive(&callid, NULL);
    765         else
    766                 res = async_data_write_receive(&callid, NULL);
    767         if (!res) {
    768                 ipc_answer_0(callid, EINVAL);
    769                 ipc_answer_0(rid, EINVAL);
    770                 return;
    771         }
    772        
    773         /*
    774796         * Lock the open file structure so that no other thread can manipulate
    775797         * the same open file at a time.
     
    795817        }
    796818       
    797         int fs_phone = vfs_grab_phone(file->node->fs_handle);   
    798        
    799         /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */
    800         aid_t msg;
    801         ipc_call_t answer;
    802         if (!read && file->append)
    803                 file->pos = file->node->size;
    804         msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE,
    805             file->node->dev_handle, file->node->index, file->pos, &answer);
    806        
    807         /*
    808          * Forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
     819        int fs_phone = vfs_grab_phone(file->node->fs_handle);
     820       
     821        /*
     822         * Make a VFS_READ/VFS_WRITE request at the destination FS server
     823         * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
    809824         * destination FS server. The call will be routed as if sent by
    810825         * ourselves. Note that call arguments are immutable in this case so we
    811826         * don't have to bother.
    812827         */
    813         ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    814 
    815         /* Wait for reply from the FS server. */
    816828        ipcarg_t rc;
    817         async_wait_for(msg, &rc);
     829        ipc_call_t answer;
     830        if (read) {
     831                if (file->append)
     832                        file->pos = file->node->size;
     833               
     834                rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
     835                    file->node->dev_handle, file->node->index, file->pos,
     836                    &answer);
     837        } else {
     838                rc = async_data_forward_3_1(fs_phone, VFS_OUT_WRITE,
     839                    file->node->dev_handle, file->node->index, file->pos,
     840                    &answer);
     841        }
    818842       
    819843        vfs_release_phone(fs_phone);
    820844       
    821845        size_t bytes = IPC_GET_ARG1(answer);
    822 
     846       
    823847        if (file->node->type == VFS_NODE_DIRECTORY)
    824848                fibril_rwlock_read_unlock(&namespace_rwlock);
     
    900924                }
    901925                newpos = size + off;
     926                file->pos = newpos;
    902927                fibril_mutex_unlock(&file->lock);
    903928                ipc_answer_1(rid, EOK, newpos);
     
    9811006void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
    9821007{
    983         size_t len;
     1008        char *path;
     1009        int rc = async_string_receive(&path, 0, NULL);
     1010        if (rc != EOK) {
     1011                ipc_answer_0(rid, rc);
     1012                return;
     1013        }
     1014       
    9841015        ipc_callid_t callid;
    985 
    986         if (!async_data_write_receive(&callid, &len)) {
    987                 ipc_answer_0(callid, EINVAL);
    988                 ipc_answer_0(rid, EINVAL);
    989                 return;
    990         }
    991         char *path = malloc(len + 1);
    992         if (!path) {
    993                 ipc_answer_0(callid, ENOMEM);
    994                 ipc_answer_0(rid, ENOMEM);
    995                 return;
    996         }
    997         int rc;
    998         if ((rc = async_data_write_finalize(callid, path, len))) {
    999                 ipc_answer_0(rid, rc);
    1000                 free(path);
    1001                 return;
    1002         }
    1003         path[len] = '\0';
    1004 
    10051016        if (!async_data_read_receive(&callid, NULL)) {
    10061017                free(path);
     
    10481059{
    10491060        int mode = IPC_GET_ARG1(*request);
    1050 
    1051         size_t len;
    1052         ipc_callid_t callid;
    1053 
    1054         if (!async_data_write_receive(&callid, &len)) {
    1055                 ipc_answer_0(callid, EINVAL);
    1056                 ipc_answer_0(rid, EINVAL);
    1057                 return;
    1058         }
    1059         char *path = malloc(len + 1);
    1060         if (!path) {
    1061                 ipc_answer_0(callid, ENOMEM);
    1062                 ipc_answer_0(rid, ENOMEM);
    1063                 return;
    1064         }
    1065         int rc;
    1066         if ((rc = async_data_write_finalize(callid, path, len))) {
    1067                 ipc_answer_0(rid, rc);
    1068                 free(path);
    1069                 return;
    1070         }
    1071         path[len] = '\0';
    1072 
     1061       
     1062        char *path;
     1063        int rc = async_string_receive(&path, 0, NULL);
     1064        if (rc != EOK) {
     1065                ipc_answer_0(rid, rc);
     1066                return;
     1067        }
     1068       
    10731069        /* Ignore mode for now. */
    10741070        (void) mode;
     
    10851081{
    10861082        int lflag = IPC_GET_ARG1(*request);
    1087 
    1088         size_t len;
    1089         ipc_callid_t callid;
    1090 
    1091         if (!async_data_write_receive(&callid, &len)) {
    1092                 ipc_answer_0(callid, EINVAL);
    1093                 ipc_answer_0(rid, EINVAL);
    1094                 return;
    1095         }
    1096         char *path = malloc(len + 1);
    1097         if (!path) {
    1098                 ipc_answer_0(callid, ENOMEM);
    1099                 ipc_answer_0(rid, ENOMEM);
    1100                 return;
    1101         }
    1102         int rc;
    1103         if ((rc = async_data_write_finalize(callid, path, len))) {
    1104                 ipc_answer_0(rid, rc);
    1105                 free(path);
    1106                 return;
    1107         }
    1108         path[len] = '\0';
     1083       
     1084        char *path;
     1085        int rc = async_string_receive(&path, 0, NULL);
     1086        if (rc != EOK) {
     1087                ipc_answer_0(rid, rc);
     1088                return;
     1089        }
    11091090       
    11101091        fibril_rwlock_write_lock(&namespace_rwlock);
     
    11351116void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
    11361117{
    1137         size_t olen, nlen;
    1138         ipc_callid_t callid;
    1139         int rc;
    1140 
    11411118        /* Retrieve the old path. */
    1142         if (!async_data_write_receive(&callid, &olen)) {
    1143                 ipc_answer_0(callid, EINVAL);
    1144                 ipc_answer_0(rid, EINVAL);
    1145                 return;
    1146         }
    1147         char *old = malloc(olen + 1);
    1148         if (!old) {
    1149                 ipc_answer_0(callid, ENOMEM);
    1150                 ipc_answer_0(rid, ENOMEM);
    1151                 return;
    1152         }
    1153         if ((rc = async_data_write_finalize(callid, old, olen))) {
    1154                 ipc_answer_0(rid, rc);
     1119        char *old;
     1120        int rc = async_string_receive(&old, 0, NULL);
     1121        if (rc != EOK) {
     1122                ipc_answer_0(rid, rc);
     1123                return;
     1124        }
     1125       
     1126        /* Retrieve the new path. */
     1127        char *new;
     1128        rc = async_string_receive(&new, 0, NULL);
     1129        if (rc != EOK) {
    11551130                free(old);
    1156                 return;
    1157         }
    1158         old[olen] = '\0';
    1159        
    1160         /* Retrieve the new path. */
    1161         if (!async_data_write_receive(&callid, &nlen)) {
    1162                 ipc_answer_0(callid, EINVAL);
    1163                 ipc_answer_0(rid, EINVAL);
    1164                 free(old);
    1165                 return;
    1166         }
    1167         char *new = malloc(nlen + 1);
    1168         if (!new) {
    1169                 ipc_answer_0(callid, ENOMEM);
    1170                 ipc_answer_0(rid, ENOMEM);
    1171                 free(old);
    1172                 return;
    1173         }
    1174         if ((rc = async_data_write_finalize(callid, new, nlen))) {
    1175                 ipc_answer_0(rid, rc);
    1176                 free(old);
    1177                 free(new);
    1178                 return;
    1179         }
    1180         new[nlen] = '\0';
    1181 
     1131                ipc_answer_0(rid, rc);
     1132                return;
     1133        }
     1134       
     1135        size_t olen;
     1136        size_t nlen;
    11821137        char *oldc = canonify(old, &olen);
    11831138        char *newc = canonify(new, &nlen);
    1184         if (!oldc || !newc) {
     1139       
     1140        if ((!oldc) || (!newc)) {
    11851141                ipc_answer_0(rid, EINVAL);
    11861142                free(old);
     
    11881144                return;
    11891145        }
     1146       
    11901147        oldc[olen] = '\0';
    11911148        newc[nlen] = '\0';
     1149       
    11921150        if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
    11931151            ((newc[str_length(oldc)] == '/') ||
     
    12101168        vfs_lookup_res_t new_par_lr;
    12111169        fibril_rwlock_write_lock(&namespace_rwlock);
     1170       
    12121171        /* Lookup the node belonging to the old file name. */
    12131172        rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
     
    12191178                return;
    12201179        }
     1180       
    12211181        vfs_node_t *old_node = vfs_node_get(&old_lr);
    12221182        if (!old_node) {
     
    12271187                return;
    12281188        }
     1189       
    12291190        /* Determine the path to the parent of the node with the new name. */
    12301191        char *parentc = str_dup(newc);
     
    12361197                return;
    12371198        }
     1199       
    12381200        char *lastsl = str_rchr(parentc + 1, '/');
    12391201        if (lastsl)
     
    12411203        else
    12421204                parentc[1] = '\0';
     1205       
    12431206        /* Lookup parent of the new file name. */
    12441207        rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
     
    12511214                return;
    12521215        }
     1216       
    12531217        /* Check whether linking to the same file system instance. */
    12541218        if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
     
    12601224                return;
    12611225        }
     1226       
    12621227        /* Destroy the old link for the new name. */
    12631228        vfs_node_t *new_node = NULL;
    12641229        rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
     1230       
    12651231        switch (rc) {
    12661232        case ENOENT:
     
    12871253                return;
    12881254        }
     1255       
    12891256        /* Create the new link for the new name. */
    12901257        rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
     
    12981265                return;
    12991266        }
     1267       
    13001268        fibril_mutex_lock(&nodes_mutex);
    13011269        old_node->lnkcnt++;
    13021270        fibril_mutex_unlock(&nodes_mutex);
     1271       
    13031272        /* Destroy the link for the old name. */
    13041273        rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
     
    13131282                return;
    13141283        }
     1284       
    13151285        fibril_mutex_lock(&nodes_mutex);
    13161286        old_node->lnkcnt--;
     
    13181288        fibril_rwlock_write_unlock(&namespace_rwlock);
    13191289        vfs_node_put(old_node);
     1290       
    13201291        if (new_node)
    13211292                vfs_node_put(new_node);
     1293       
    13221294        free(old);
    13231295        free(new);
Note: See TracChangeset for help on using the changeset viewer.