Changeset e27cf669 in mainline for uspace/srv/vfs/vfs_ops.c


Ignore:
Timestamp:
2010-02-09T20:19:23Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fb150d78
Parents:
975e7e9 (diff), eb73a50 (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:

Merge mainline changes.

File:
1 edited

Legend:

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

    r975e7e9 re27cf669  
    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_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
     270            0, NULL);
     271        if (rc != EOK) {
     272                ipc_answer_0(rid, rc);
     273                return;
     274        }
     275       
     276        /* Now we expect to receive the mount options. */
     277        char *opts;
     278        rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN,
     279            0, NULL);
     280        if (rc != EOK) {
    295281                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);
     282                ipc_answer_0(rid, rc);
     283                return;
     284        }
     285       
     286        /*
     287         * Now, we expect the client to send us data with the name of the file
     288         * system.
     289         */
     290        char *fs_name;
     291        rc = async_data_write_accept((void **) &fs_name, true, 0, FS_NAME_MAXLEN,
     292            0, NULL);
     293        if (rc != EOK) {
    329294                free(mp);
    330295                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 
     296                ipc_answer_0(rid, rc);
     297                return;
     298        }
     299       
    382300        /*
    383301         * Wait for IPC_M_PING so that we can return an error if we don't know
     
    385303         */
    386304        ipc_call_t data;
    387         callid = async_get_call(&data);
     305        ipc_callid_t callid = async_get_call(&data);
    388306        if (IPC_GET_METHOD(data) != IPC_M_PING) {
    389307                ipc_answer_0(callid, ENOTSUP);
     
    429347}
    430348
     349void vfs_unmount(ipc_callid_t rid, ipc_call_t *request)
     350{
     351        int rc;
     352        char *mp;
     353        vfs_lookup_res_t mp_res;
     354        vfs_lookup_res_t mr_res;
     355        vfs_node_t *mp_node;
     356        vfs_node_t *mr_node;
     357        int phone;
     358
     359        /*
     360         * Receive the mount point path.
     361         */
     362        rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN,
     363            0, NULL);
     364        if (rc != EOK)
     365                ipc_answer_0(rid, rc);
     366
     367        /*
     368         * Taking the namespace lock will do two things for us. First, it will
     369         * prevent races with other lookup operations. Second, it will stop new
     370         * references to already existing VFS nodes and creation of new VFS
     371         * nodes. This is because new references are added as a result of some
     372         * lookup operation or at least of some operation which is protected by
     373         * the namespace lock.
     374         */
     375        fibril_rwlock_write_lock(&namespace_rwlock);
     376       
     377        /*
     378         * Lookup the mounted root and instantiate it.
     379         */
     380        rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL);
     381        if (rc != EOK) {
     382                fibril_rwlock_write_unlock(&namespace_rwlock);
     383                free(mp);
     384                ipc_answer_0(rid, rc);
     385                return;
     386        }
     387        mr_node = vfs_node_get(&mr_res);
     388        if (!mr_node) {
     389                fibril_rwlock_write_unlock(&namespace_rwlock);
     390                free(mp);
     391                ipc_answer_0(rid, ENOMEM);
     392                return;
     393        }
     394
     395        /*
     396         * Count the total number of references for the mounted file system. We
     397         * are expecting at least two. One which we got above and one which we
     398         * got when the file system was mounted. If we find more, it means that
     399         * the file system cannot be gracefully unmounted at the moment because
     400         * someone is working with it.
     401         */
     402        if (vfs_nodes_refcount_sum_get(mr_node->fs_handle,
     403            mr_node->dev_handle) != 2) {
     404                fibril_rwlock_write_unlock(&namespace_rwlock);
     405                vfs_node_put(mr_node);
     406                free(mp);
     407                ipc_answer_0(rid, EBUSY);
     408                return;
     409        }
     410
     411        if (str_cmp(mp, "/") == 0) {
     412
     413                /*
     414                 * Unmounting the root file system.
     415                 *
     416                 * In this case, there is no mount point node and we send
     417                 * VFS_OUT_UNMOUNTED directly to the mounted file system.
     418                 */
     419
     420                free(mp);
     421                phone = vfs_grab_phone(mr_node->fs_handle);
     422                rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED,
     423                    mr_node->dev_handle);
     424                vfs_release_phone(phone);
     425                if (rc != EOK) {
     426                        fibril_rwlock_write_unlock(&namespace_rwlock);
     427                        vfs_node_put(mr_node);
     428                        ipc_answer_0(rid, rc);
     429                        return;
     430                }
     431                rootfs.fs_handle = 0;
     432                rootfs.dev_handle = 0;
     433        } else {
     434
     435                /*
     436                 * Unmounting a non-root file system.
     437                 *
     438                 * We have a regular mount point node representing the parent
     439                 * file system, so we delegate the operation to it.
     440                 */
     441
     442                rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL);
     443                free(mp);
     444                if (rc != EOK) {
     445                        fibril_rwlock_write_unlock(&namespace_rwlock);
     446                        vfs_node_put(mr_node);
     447                        ipc_answer_0(rid, rc);
     448                        return;
     449                }
     450                vfs_node_t *mp_node = vfs_node_get(&mp_res);
     451                if (!mp_node) {
     452                        fibril_rwlock_write_unlock(&namespace_rwlock);
     453                        vfs_node_put(mr_node);
     454                        ipc_answer_0(rid, ENOMEM);
     455                        return;
     456                }
     457
     458                phone = vfs_grab_phone(mp_node->fs_handle);
     459                rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, mp_node->dev_handle,
     460                    mp_node->index);
     461                vfs_release_phone(phone);
     462                if (rc != EOK) {
     463                        fibril_rwlock_write_unlock(&namespace_rwlock);
     464                        vfs_node_put(mp_node);
     465                        vfs_node_put(mr_node);
     466                        ipc_answer_0(rid, rc);
     467                        return;
     468                }
     469
     470                /* Drop the reference we got above. */
     471                vfs_node_put(mp_node);
     472                /* Drop the reference from when the file system was mounted. */
     473                vfs_node_put(mp_node);
     474        }
     475
     476
     477        /*
     478         * All went well, the mounted file system was successfully unmounted.
     479         * The only thing left is to forget the unmounted root VFS node.
     480         */
     481        vfs_node_forget(mr_node);
     482
     483        fibril_rwlock_write_unlock(&namespace_rwlock);
     484        ipc_answer_0(rid, EOK);
     485}
     486
    431487void vfs_open(ipc_callid_t rid, ipc_call_t *request)
    432488{
     
    454510        /*
    455511         * 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.
     512         * L_DIRECTORY. Make sure that the user does not pass L_OPEN,
     513         * L_ROOT or L_MP.
    457514         */
    458515        if (((lflag & (L_FILE | L_DIRECTORY)) == 0) ||
    459516            ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) ||
    460             ((lflag & L_OPEN) != 0)) {
     517            (lflag & (L_OPEN | L_ROOT | L_MP))) {
    461518                ipc_answer_0(rid, EINVAL);
    462519                return;
     
    468525                lflag |= L_EXCLUSIVE;
    469526       
    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';
     527        char *path;
     528        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     529        if (rc != EOK) {
     530                ipc_answer_0(rid, rc);
     531                return;
     532        }
    491533       
    492534        /*
     
    679721}
    680722
    681 static int vfs_close_internal(vfs_file_t *file)
     723int vfs_close_internal(vfs_file_t *file)
    682724{
    683725        /*
     
    756798       
    757799        /*
    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         /*
    774800         * Lock the open file structure so that no other thread can manipulate
    775801         * the same open file at a time.
     
    795821        }
    796822       
    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
     823        int fs_phone = vfs_grab_phone(file->node->fs_handle);
     824       
     825        /*
     826         * Make a VFS_READ/VFS_WRITE request at the destination FS server
     827         * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the
    809828         * destination FS server. The call will be routed as if sent by
    810829         * ourselves. Note that call arguments are immutable in this case so we
    811830         * don't have to bother.
    812831         */
    813         ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    814 
    815         /* Wait for reply from the FS server. */
    816832        ipcarg_t rc;
    817         async_wait_for(msg, &rc);
     833        ipc_call_t answer;
     834        if (read) {
     835                if (file->append)
     836                        file->pos = file->node->size;
     837               
     838                rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ,
     839                    file->node->dev_handle, file->node->index, file->pos,
     840                    &answer);
     841        } else {
     842                rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE,
     843                    file->node->dev_handle, file->node->index, file->pos,
     844                    &answer);
     845        }
    818846       
    819847        vfs_release_phone(fs_phone);
    820848       
    821849        size_t bytes = IPC_GET_ARG1(answer);
    822 
     850       
    823851        if (file->node->type == VFS_NODE_DIRECTORY)
    824852                fibril_rwlock_read_unlock(&namespace_rwlock);
     
    9821010void vfs_stat(ipc_callid_t rid, ipc_call_t *request)
    9831011{
    984         size_t len;
     1012        char *path;
     1013        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     1014        if (rc != EOK) {
     1015                ipc_answer_0(rid, rc);
     1016                return;
     1017        }
     1018       
    9851019        ipc_callid_t callid;
    986 
    987         if (!async_data_write_receive(&callid, &len)) {
    988                 ipc_answer_0(callid, EINVAL);
    989                 ipc_answer_0(rid, EINVAL);
    990                 return;
    991         }
    992         char *path = malloc(len + 1);
    993         if (!path) {
    994                 ipc_answer_0(callid, ENOMEM);
    995                 ipc_answer_0(rid, ENOMEM);
    996                 return;
    997         }
    998         int rc;
    999         if ((rc = async_data_write_finalize(callid, path, len))) {
    1000                 ipc_answer_0(rid, rc);
    1001                 free(path);
    1002                 return;
    1003         }
    1004         path[len] = '\0';
    1005 
    10061020        if (!async_data_read_receive(&callid, NULL)) {
    10071021                free(path);
     
    10491063{
    10501064        int mode = IPC_GET_ARG1(*request);
    1051 
    1052         size_t len;
    1053         ipc_callid_t callid;
    1054 
    1055         if (!async_data_write_receive(&callid, &len)) {
    1056                 ipc_answer_0(callid, EINVAL);
    1057                 ipc_answer_0(rid, EINVAL);
    1058                 return;
    1059         }
    1060         char *path = malloc(len + 1);
    1061         if (!path) {
    1062                 ipc_answer_0(callid, ENOMEM);
    1063                 ipc_answer_0(rid, ENOMEM);
    1064                 return;
    1065         }
    1066         int rc;
    1067         if ((rc = async_data_write_finalize(callid, path, len))) {
    1068                 ipc_answer_0(rid, rc);
    1069                 free(path);
    1070                 return;
    1071         }
    1072         path[len] = '\0';
    1073 
     1065       
     1066        char *path;
     1067        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     1068        if (rc != EOK) {
     1069                ipc_answer_0(rid, rc);
     1070                return;
     1071        }
     1072       
    10741073        /* Ignore mode for now. */
    10751074        (void) mode;
     
    10861085{
    10871086        int lflag = IPC_GET_ARG1(*request);
    1088 
    1089         size_t len;
    1090         ipc_callid_t callid;
    1091 
    1092         if (!async_data_write_receive(&callid, &len)) {
    1093                 ipc_answer_0(callid, EINVAL);
    1094                 ipc_answer_0(rid, EINVAL);
    1095                 return;
    1096         }
    1097         char *path = malloc(len + 1);
    1098         if (!path) {
    1099                 ipc_answer_0(callid, ENOMEM);
    1100                 ipc_answer_0(rid, ENOMEM);
    1101                 return;
    1102         }
    1103         int rc;
    1104         if ((rc = async_data_write_finalize(callid, path, len))) {
    1105                 ipc_answer_0(rid, rc);
    1106                 free(path);
    1107                 return;
    1108         }
    1109         path[len] = '\0';
     1087       
     1088        char *path;
     1089        int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL);
     1090        if (rc != EOK) {
     1091                ipc_answer_0(rid, rc);
     1092                return;
     1093        }
    11101094       
    11111095        fibril_rwlock_write_lock(&namespace_rwlock);
     
    11361120void vfs_rename(ipc_callid_t rid, ipc_call_t *request)
    11371121{
    1138         size_t olen, nlen;
    1139         ipc_callid_t callid;
    1140         int rc;
    1141 
    11421122        /* Retrieve the old path. */
    1143         if (!async_data_write_receive(&callid, &olen)) {
    1144                 ipc_answer_0(callid, EINVAL);
    1145                 ipc_answer_0(rid, EINVAL);
    1146                 return;
    1147         }
    1148         char *old = malloc(olen + 1);
    1149         if (!old) {
    1150                 ipc_answer_0(callid, ENOMEM);
    1151                 ipc_answer_0(rid, ENOMEM);
    1152                 return;
    1153         }
    1154         if ((rc = async_data_write_finalize(callid, old, olen))) {
    1155                 ipc_answer_0(rid, rc);
     1123        char *old;
     1124        int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL);
     1125        if (rc != EOK) {
     1126                ipc_answer_0(rid, rc);
     1127                return;
     1128        }
     1129       
     1130        /* Retrieve the new path. */
     1131        char *new;
     1132        rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL);
     1133        if (rc != EOK) {
    11561134                free(old);
    1157                 return;
    1158         }
    1159         old[olen] = '\0';
    1160        
    1161         /* Retrieve the new path. */
    1162         if (!async_data_write_receive(&callid, &nlen)) {
    1163                 ipc_answer_0(callid, EINVAL);
    1164                 ipc_answer_0(rid, EINVAL);
    1165                 free(old);
    1166                 return;
    1167         }
    1168         char *new = malloc(nlen + 1);
    1169         if (!new) {
    1170                 ipc_answer_0(callid, ENOMEM);
    1171                 ipc_answer_0(rid, ENOMEM);
    1172                 free(old);
    1173                 return;
    1174         }
    1175         if ((rc = async_data_write_finalize(callid, new, nlen))) {
    1176                 ipc_answer_0(rid, rc);
    1177                 free(old);
    1178                 free(new);
    1179                 return;
    1180         }
    1181         new[nlen] = '\0';
    1182 
     1135                ipc_answer_0(rid, rc);
     1136                return;
     1137        }
     1138       
     1139        size_t olen;
     1140        size_t nlen;
    11831141        char *oldc = canonify(old, &olen);
    11841142        char *newc = canonify(new, &nlen);
    1185         if (!oldc || !newc) {
     1143       
     1144        if ((!oldc) || (!newc)) {
    11861145                ipc_answer_0(rid, EINVAL);
    11871146                free(old);
     
    11891148                return;
    11901149        }
     1150       
    11911151        oldc[olen] = '\0';
    11921152        newc[nlen] = '\0';
     1153       
    11931154        if ((!str_lcmp(newc, oldc, str_length(oldc))) &&
    11941155            ((newc[str_length(oldc)] == '/') ||
     
    12111172        vfs_lookup_res_t new_par_lr;
    12121173        fibril_rwlock_write_lock(&namespace_rwlock);
     1174       
    12131175        /* Lookup the node belonging to the old file name. */
    12141176        rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL);
     
    12201182                return;
    12211183        }
     1184       
    12221185        vfs_node_t *old_node = vfs_node_get(&old_lr);
    12231186        if (!old_node) {
     
    12281191                return;
    12291192        }
     1193       
    12301194        /* Determine the path to the parent of the node with the new name. */
    12311195        char *parentc = str_dup(newc);
     
    12371201                return;
    12381202        }
     1203       
    12391204        char *lastsl = str_rchr(parentc + 1, '/');
    12401205        if (lastsl)
     
    12421207        else
    12431208                parentc[1] = '\0';
     1209       
    12441210        /* Lookup parent of the new file name. */
    12451211        rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL);
     
    12521218                return;
    12531219        }
     1220       
    12541221        /* Check whether linking to the same file system instance. */
    12551222        if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) ||
     
    12611228                return;
    12621229        }
     1230       
    12631231        /* Destroy the old link for the new name. */
    12641232        vfs_node_t *new_node = NULL;
    12651233        rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL);
     1234       
    12661235        switch (rc) {
    12671236        case ENOENT:
     
    12881257                return;
    12891258        }
     1259       
    12901260        /* Create the new link for the new name. */
    12911261        rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index);
     
    12991269                return;
    13001270        }
     1271       
    13011272        fibril_mutex_lock(&nodes_mutex);
    13021273        old_node->lnkcnt++;
    13031274        fibril_mutex_unlock(&nodes_mutex);
     1275       
    13041276        /* Destroy the link for the old name. */
    13051277        rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL);
     
    13141286                return;
    13151287        }
     1288       
    13161289        fibril_mutex_lock(&nodes_mutex);
    13171290        old_node->lnkcnt--;
     
    13191292        fibril_rwlock_write_unlock(&namespace_rwlock);
    13201293        vfs_node_put(old_node);
     1294       
    13211295        if (new_node)
    13221296                vfs_node_put(new_node);
     1297       
    13231298        free(old);
    13241299        free(new);
Note: See TracChangeset for help on using the changeset viewer.