Rev 4419 | Rev 4439 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4419 | Rev 4420 | ||
---|---|---|---|
Line 58... | Line 58... | ||
58 | /** Pending mount structure. */ |
58 | /** Pending mount structure. */ |
59 | typedef struct { |
59 | typedef struct { |
60 | link_t link; |
60 | link_t link; |
61 | char *fs_name; /**< File system name */ |
61 | char *fs_name; /**< File system name */ |
62 | char *mp; /**< Mount point */ |
62 | char *mp; /**< Mount point */ |
- | 63 | char *opts; /**< Mount options. */ |
|
63 | ipc_callid_t callid; /**< Call ID waiting for the mount */ |
64 | ipc_callid_t callid; /**< Call ID waiting for the mount */ |
64 | ipc_callid_t rid; /**< Request ID */ |
65 | ipc_callid_t rid; /**< Request ID */ |
65 | dev_handle_t dev_handle; /**< Device handle */ |
66 | dev_handle_t dev_handle; /**< Device handle */ |
66 | } pending_req_t; |
67 | } pending_req_t; |
67 | 68 | ||
Line 78... | Line 79... | ||
78 | .fs_handle = 0, |
79 | .fs_handle = 0, |
79 | .dev_handle = 0 |
80 | .dev_handle = 0 |
80 | }; |
81 | }; |
81 | 82 | ||
82 | static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
83 | static void vfs_mount_internal(ipc_callid_t rid, dev_handle_t dev_handle, |
83 | fs_handle_t fs_handle, char *mp) |
84 | fs_handle_t fs_handle, char *mp, char *opts) |
84 | { |
85 | { |
85 | /* Resolve the path to the mountpoint. */ |
- | |
86 | vfs_lookup_res_t mp_res; |
86 | vfs_lookup_res_t mp_res; |
- | 87 | vfs_lookup_res_t mr_res; |
|
87 | vfs_node_t *mp_node = NULL; |
88 | vfs_node_t *mp_node = NULL; |
- | 89 | vfs_node_t *mr_node; |
|
- | 90 | fs_index_t rindex; |
|
- | 91 | size_t rsize; |
|
- | 92 | unsigned rlnkcnt; |
|
88 | int rc; |
93 | ipcarg_t rc; |
89 | int phone; |
94 | int phone; |
- | 95 | aid_t msg; |
|
- | 96 | ipc_call_t answer; |
|
- | 97 | ||
- | 98 | ||
- | 99 | /* Resolve the path to the mountpoint. */ |
|
90 | futex_down(&rootfs_futex); |
100 | futex_down(&rootfs_futex); |
91 | if (rootfs.fs_handle) { |
101 | if (rootfs.fs_handle) { |
92 | /* We already have the root FS. */ |
102 | /* We already have the root FS. */ |
93 | rwlock_write_lock(&namespace_rwlock); |
103 | rwlock_write_lock(&namespace_rwlock); |
94 | if (str_cmp(mp, "/") == 0) { |
104 | if (str_cmp(mp, "/") == 0) { |
Line 123... | Line 133... | ||
123 | */ |
133 | */ |
124 | rwlock_write_unlock(&namespace_rwlock); |
134 | rwlock_write_unlock(&namespace_rwlock); |
125 | } else { |
135 | } else { |
126 | /* We still don't have the root file system mounted. */ |
136 | /* We still don't have the root file system mounted. */ |
127 | if (str_cmp(mp, "/") == 0) { |
137 | if (str_cmp(mp, "/") == 0) { |
128 | vfs_lookup_res_t mr_res; |
- | |
129 | vfs_node_t *mr_node; |
- | |
130 | ipcarg_t rindex; |
- | |
131 | ipcarg_t rsize; |
- | |
132 | ipcarg_t rlnkcnt; |
- | |
133 | - | ||
134 | /* |
138 | /* |
135 | * For this simple, but important case, |
139 | * For this simple, but important case, |
136 | * we are almost done. |
140 | * we are almost done. |
137 | */ |
141 | */ |
138 | 142 | ||
139 | /* Tell the mountee that it is being mounted. */ |
143 | /* Tell the mountee that it is being mounted. */ |
140 | phone = vfs_grab_phone(fs_handle); |
144 | phone = vfs_grab_phone(fs_handle); |
141 | rc = async_req_1_3(phone, VFS_MOUNTED, |
145 | msg = async_send_1(phone, VFS_MOUNTED, |
142 | (ipcarg_t) dev_handle, &rindex, &rsize, &rlnkcnt); |
146 | (ipcarg_t) dev_handle, &answer); |
- | 147 | /* send the mount options */ |
|
- | 148 | rc = ipc_data_write_start(phone, (void *)opts, |
|
- | 149 | str_size(opts)); |
|
- | 150 | if (rc != EOK) { |
|
- | 151 | async_wait_for(msg, NULL); |
|
- | 152 | vfs_release_phone(phone); |
|
- | 153 | futex_up(&rootfs_futex); |
|
- | 154 | ipc_answer_0(rid, rc); |
|
- | 155 | return; |
|
- | 156 | } |
|
- | 157 | async_wait_for(msg, &rc); |
|
143 | vfs_release_phone(phone); |
158 | vfs_release_phone(phone); |
144 | 159 | ||
145 | if (rc != EOK) { |
160 | if (rc != EOK) { |
146 | futex_up(&rootfs_futex); |
161 | futex_up(&rootfs_futex); |
147 | ipc_answer_0(rid, rc); |
162 | ipc_answer_0(rid, rc); |
148 | return; |
163 | return; |
149 | } |
164 | } |
- | 165 | ||
- | 166 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
|
- | 167 | rsize = (size_t) IPC_GET_ARG2(answer); |
|
- | 168 | rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
|
150 | 169 | ||
151 | mr_res.triplet.fs_handle = fs_handle; |
170 | mr_res.triplet.fs_handle = fs_handle; |
152 | mr_res.triplet.dev_handle = dev_handle; |
171 | mr_res.triplet.dev_handle = dev_handle; |
153 | mr_res.triplet.index = (fs_index_t) rindex; |
172 | mr_res.triplet.index = rindex; |
154 | mr_res.size = (size_t) rsize; |
173 | mr_res.size = rsize; |
155 | mr_res.lnkcnt = (unsigned) rlnkcnt; |
174 | mr_res.lnkcnt = rlnkcnt; |
156 | mr_res.type = VFS_NODE_DIRECTORY; |
175 | mr_res.type = VFS_NODE_DIRECTORY; |
157 | 176 | ||
158 | rootfs.fs_handle = fs_handle; |
177 | rootfs.fs_handle = fs_handle; |
159 | rootfs.dev_handle = dev_handle; |
178 | rootfs.dev_handle = dev_handle; |
160 | futex_up(&rootfs_futex); |
179 | futex_up(&rootfs_futex); |
Line 180... | Line 199... | ||
180 | /* |
199 | /* |
181 | * At this point, we have all necessary pieces: file system and device |
200 | * At this point, we have all necessary pieces: file system and device |
182 | * handles, and we know the mount point VFS node. |
201 | * handles, and we know the mount point VFS node. |
183 | */ |
202 | */ |
184 | 203 | ||
- | 204 | int mountee_phone = vfs_grab_phone(fs_handle); |
|
- | 205 | assert(mountee_phone >= 0); |
|
- | 206 | vfs_release_phone(mountee_phone); |
|
- | 207 | ||
185 | phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
208 | phone = vfs_grab_phone(mp_res.triplet.fs_handle); |
186 | rc = async_req_4_0(phone, VFS_MOUNT, |
209 | msg = async_send_4(phone, VFS_MOUNT, |
187 | (ipcarg_t) mp_res.triplet.dev_handle, |
210 | (ipcarg_t) mp_res.triplet.dev_handle, |
188 | (ipcarg_t) mp_res.triplet.index, |
211 | (ipcarg_t) mp_res.triplet.index, |
189 | (ipcarg_t) fs_handle, |
212 | (ipcarg_t) fs_handle, |
190 | (ipcarg_t) dev_handle); |
213 | (ipcarg_t) dev_handle, &answer); |
- | 214 | ||
- | 215 | /* send connection */ |
|
- | 216 | rc = async_req_1_0(phone, IPC_M_CONNECTION_CLONE, mountee_phone); |
|
- | 217 | if (rc != EOK) { |
|
- | 218 | async_wait_for(msg, NULL); |
|
- | 219 | vfs_release_phone(phone); |
|
- | 220 | /* Mount failed, drop reference to mp_node. */ |
|
- | 221 | if (mp_node) |
|
- | 222 | vfs_node_put(mp_node); |
|
- | 223 | ipc_answer_0(rid, rc); |
|
- | 224 | return; |
|
- | 225 | } |
|
- | 226 | ||
- | 227 | /* send the mount options */ |
|
- | 228 | rc = ipc_data_write_start(phone, (void *)opts, str_size(opts)); |
|
- | 229 | if (rc != EOK) { |
|
- | 230 | async_wait_for(msg, NULL); |
|
- | 231 | vfs_release_phone(phone); |
|
- | 232 | /* Mount failed, drop reference to mp_node. */ |
|
- | 233 | if (mp_node) |
|
- | 234 | vfs_node_put(mp_node); |
|
- | 235 | ipc_answer_0(rid, rc); |
|
- | 236 | return; |
|
- | 237 | } |
|
- | 238 | async_wait_for(msg, &rc); |
|
191 | vfs_release_phone(phone); |
239 | vfs_release_phone(phone); |
192 | 240 | ||
193 | if (rc != EOK) { |
241 | if (rc != EOK) { |
194 | /* Mount failed, drop reference to mp_node. */ |
242 | /* Mount failed, drop reference to mp_node. */ |
195 | if (mp_node) |
243 | if (mp_node) |
196 | vfs_node_put(mp_node); |
244 | vfs_node_put(mp_node); |
197 | } |
245 | } |
198 | 246 | ||
- | 247 | rindex = (fs_index_t) IPC_GET_ARG1(answer); |
|
- | 248 | rsize = (size_t) IPC_GET_ARG2(answer); |
|
- | 249 | rlnkcnt = (unsigned) IPC_GET_ARG3(answer); |
|
- | 250 | ||
- | 251 | mr_res.triplet.fs_handle = fs_handle; |
|
- | 252 | mr_res.triplet.dev_handle = dev_handle; |
|
- | 253 | mr_res.triplet.index = rindex; |
|
- | 254 | mr_res.size = rsize; |
|
- | 255 | mr_res.lnkcnt = rlnkcnt; |
|
- | 256 | mr_res.type = VFS_NODE_DIRECTORY; |
|
- | 257 | ||
- | 258 | /* Add reference to the mounted root. */ |
|
- | 259 | mr_node = vfs_node_get(&mr_res); |
|
- | 260 | assert(mr_node); |
|
- | 261 | ||
199 | ipc_answer_0(rid, rc); |
262 | ipc_answer_0(rid, rc); |
200 | } |
263 | } |
201 | 264 | ||
202 | /** Process pending mount requests */ |
265 | /** Process pending mount requests */ |
203 | void vfs_process_pending_mount() |
266 | void vfs_process_pending_mount() |
Line 214... | Line 277... | ||
214 | 277 | ||
215 | /* Acknowledge that we know fs_name. */ |
278 | /* Acknowledge that we know fs_name. */ |
216 | ipc_answer_0(pr->callid, EOK); |
279 | ipc_answer_0(pr->callid, EOK); |
217 | 280 | ||
218 | /* Do the mount */ |
281 | /* Do the mount */ |
219 | vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp); |
282 | vfs_mount_internal(pr->rid, pr->dev_handle, fs_handle, pr->mp, |
- | 283 | pr->opts); |
|
220 | 284 | ||
221 | free(pr->fs_name); |
285 | free(pr->fs_name); |
222 | free(pr->mp); |
286 | free(pr->mp); |
- | 287 | free(pr->opts); |
|
223 | list_remove(cur); |
288 | list_remove(cur); |
224 | free(pr); |
289 | free(pr); |
225 | goto loop; |
290 | goto loop; |
226 | } |
291 | } |
227 | } |
292 | } |
Line 270... | Line 335... | ||
270 | } |
335 | } |
271 | 336 | ||
272 | /* Deliver the mount point. */ |
337 | /* Deliver the mount point. */ |
273 | ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
338 | ipcarg_t retval = ipc_data_write_finalize(callid, mp, size); |
274 | if (retval != EOK) { |
339 | if (retval != EOK) { |
275 | ipc_answer_0(rid, EREFUSED); |
340 | ipc_answer_0(rid, retval); |
276 | free(mp); |
341 | free(mp); |
277 | return; |
342 | return; |
278 | } |
343 | } |
279 | mp[size] = '\0'; |
344 | mp[size] = '\0'; |
280 | 345 | ||
- | 346 | /* Now we expect to receive the mount options. */ |
|
- | 347 | if (!ipc_data_write_receive(&callid, &size)) { |
|
- | 348 | ipc_answer_0(callid, EINVAL); |
|
- | 349 | ipc_answer_0(rid, EINVAL); |
|
- | 350 | free(mp); |
|
- | 351 | return; |
|
- | 352 | } |
|
- | 353 | ||
- | 354 | /* Check the offered options size. */ |
|
- | 355 | if (size < 0 || size > MAX_MNTOPTS_LEN) { |
|
- | 356 | ipc_answer_0(callid, EINVAL); |
|
- | 357 | ipc_answer_0(rid, EINVAL); |
|
- | 358 | free(mp); |
|
- | 359 | return; |
|
- | 360 | } |
|
- | 361 | ||
- | 362 | /* Allocate buffer for the mount options. */ |
|
- | 363 | char *opts = (char *) malloc(size + 1); |
|
- | 364 | if (!opts) { |
|
- | 365 | ipc_answer_0(callid, ENOMEM); |
|
- | 366 | ipc_answer_0(rid, ENOMEM); |
|
- | 367 | free(mp); |
|
- | 368 | return; |
|
- | 369 | } |
|
- | 370 | ||
- | 371 | /* Deliver the mount options. */ |
|
- | 372 | retval = ipc_data_write_finalize(callid, opts, size); |
|
- | 373 | if (retval != EOK) { |
|
- | 374 | ipc_answer_0(rid, retval); |
|
- | 375 | free(mp); |
|
- | 376 | free(opts); |
|
- | 377 | return; |
|
- | 378 | } |
|
- | 379 | opts[size] = '\0'; |
|
- | 380 | ||
281 | /* |
381 | /* |
282 | * Now, we expect the client to send us data with the name of the file |
382 | * Now, we expect the client to send us data with the name of the file |
283 | * system. |
383 | * system. |
284 | */ |
384 | */ |
285 | if (!ipc_data_write_receive(&callid, &size)) { |
385 | if (!ipc_data_write_receive(&callid, &size)) { |
286 | ipc_answer_0(callid, EINVAL); |
386 | ipc_answer_0(callid, EINVAL); |
287 | ipc_answer_0(rid, EINVAL); |
387 | ipc_answer_0(rid, EINVAL); |
288 | free(mp); |
388 | free(mp); |
- | 389 | free(opts); |
|
289 | return; |
390 | return; |
290 | } |
391 | } |
291 | 392 | ||
292 | /* |
393 | /* |
293 | * Don't receive more than is necessary for storing a full file system |
394 | * Don't receive more than is necessary for storing a full file system |
Line 295... | Line 396... | ||
295 | */ |
396 | */ |
296 | if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
397 | if ((size < 1) || (size > FS_NAME_MAXLEN)) { |
297 | ipc_answer_0(callid, EINVAL); |
398 | ipc_answer_0(callid, EINVAL); |
298 | ipc_answer_0(rid, EINVAL); |
399 | ipc_answer_0(rid, EINVAL); |
299 | free(mp); |
400 | free(mp); |
- | 401 | free(opts); |
|
300 | return; |
402 | return; |
301 | } |
403 | } |
302 | 404 | ||
303 | /* |
405 | /* |
304 | * Allocate buffer for file system name. |
406 | * Allocate buffer for file system name. |
305 | */ |
407 | */ |
306 | char *fs_name = (char *) malloc(size + 1); |
408 | char *fs_name = (char *) malloc(size + 1); |
307 | if (fs_name == NULL) { |
409 | if (fs_name == NULL) { |
308 | ipc_answer_0(callid, ENOMEM); |
410 | ipc_answer_0(callid, ENOMEM); |
309 | ipc_answer_0(rid, EREFUSED); |
411 | ipc_answer_0(rid, ENOMEM); |
310 | free(mp); |
412 | free(mp); |
- | 413 | free(opts); |
|
311 | return; |
414 | return; |
312 | } |
415 | } |
313 | 416 | ||
314 | /* Deliver the file system name. */ |
417 | /* Deliver the file system name. */ |
315 | retval = ipc_data_write_finalize(callid, fs_name, size); |
418 | retval = ipc_data_write_finalize(callid, fs_name, size); |
316 | if (retval != EOK) { |
419 | if (retval != EOK) { |
317 | ipc_answer_0(rid, EREFUSED); |
420 | ipc_answer_0(rid, retval); |
318 | free(mp); |
421 | free(mp); |
- | 422 | free(opts); |
|
319 | free(fs_name); |
423 | free(fs_name); |
320 | return; |
424 | return; |
321 | } |
425 | } |
322 | fs_name[size] = '\0'; |
426 | fs_name[size] = '\0'; |
- | 427 | ||
- | 428 | /* |
|
- | 429 | * Wait for IPC_M_PING so that we can return an error if we don't know |
|
- | 430 | * fs_name. |
|
- | 431 | */ |
|
- | 432 | ipc_call_t data; |
|
- | 433 | callid = async_get_call(&data); |
|
- | 434 | if (IPC_GET_METHOD(data) != IPC_M_PING) { |
|
- | 435 | ipc_answer_0(callid, ENOTSUP); |
|
- | 436 | ipc_answer_0(rid, ENOTSUP); |
|
- | 437 | free(mp); |
|
- | 438 | free(opts); |
|
- | 439 | free(fs_name); |
|
- | 440 | return; |
|
323 | 441 | } |
|
- | 442 | ||
324 | /* |
443 | /* |
325 | * Check if we know a file system with the same name as is in fs_name. |
444 | * Check if we know a file system with the same name as is in fs_name. |
326 | * This will also give us its file system handle. |
445 | * This will also give us its file system handle. |
327 | */ |
446 | */ |
328 | fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
447 | fs_handle_t fs_handle = fs_name_to_handle(fs_name, true); |
329 | if (!fs_handle) { |
448 | if (!fs_handle) { |
330 | if (flags & IPC_FLAG_BLOCKING) { |
449 | if (flags & IPC_FLAG_BLOCKING) { |
- | 450 | pending_req_t *pr; |
|
- | 451 | ||
331 | /* Blocking mount, add to pending list */ |
452 | /* Blocking mount, add to pending list */ |
332 | pending_req_t *pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
453 | pr = (pending_req_t *) malloc(sizeof(pending_req_t)); |
333 | if (!pr) { |
454 | if (!pr) { |
334 | ipc_answer_0(callid, ENOMEM); |
455 | ipc_answer_0(callid, ENOMEM); |
335 | ipc_answer_0(rid, ENOMEM); |
456 | ipc_answer_0(rid, ENOMEM); |
336 | free(mp); |
457 | free(mp); |
337 | free(fs_name); |
458 | free(fs_name); |
- | 459 | free(opts); |
|
338 | return; |
460 | return; |
339 | } |
461 | } |
340 | 462 | ||
341 | pr->fs_name = fs_name; |
463 | pr->fs_name = fs_name; |
342 | pr->mp = mp; |
464 | pr->mp = mp; |
- | 465 | pr->opts = opts; |
|
343 | pr->callid = callid; |
466 | pr->callid = callid; |
344 | pr->rid = rid; |
467 | pr->rid = rid; |
345 | pr->dev_handle = dev_handle; |
468 | pr->dev_handle = dev_handle; |
346 | link_initialize(&pr->link); |
469 | link_initialize(&pr->link); |
347 | list_append(&pr->link, &pending_req); |
470 | list_append(&pr->link, &pending_req); |
Line 350... | Line 473... | ||
350 | 473 | ||
351 | ipc_answer_0(callid, ENOENT); |
474 | ipc_answer_0(callid, ENOENT); |
352 | ipc_answer_0(rid, ENOENT); |
475 | ipc_answer_0(rid, ENOENT); |
353 | free(mp); |
476 | free(mp); |
354 | free(fs_name); |
477 | free(fs_name); |
- | 478 | free(opts); |
|
355 | return; |
479 | return; |
356 | } |
480 | } |
357 | 481 | ||
358 | /* Acknowledge that we know fs_name. */ |
482 | /* Acknowledge that we know fs_name. */ |
359 | ipc_answer_0(callid, EOK); |
483 | ipc_answer_0(callid, EOK); |
360 | 484 | ||
361 | /* Do the mount */ |
485 | /* Do the mount */ |
362 | vfs_mount_internal(rid, dev_handle, fs_handle, mp); |
486 | vfs_mount_internal(rid, dev_handle, fs_handle, mp, opts); |
363 | free(mp); |
487 | free(mp); |
364 | free(fs_name); |
488 | free(fs_name); |
- | 489 | free(opts); |
|
365 | } |
490 | } |
366 | 491 | ||
367 | void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
492 | void vfs_open(ipc_callid_t rid, ipc_call_t *request) |
368 | { |
493 | { |
369 | if (!vfs_files_init()) { |
494 | if (!vfs_files_init()) { |
Line 857... | Line 982... | ||
857 | free(new); |
982 | free(new); |
858 | return; |
983 | return; |
859 | } |
984 | } |
860 | oldc[olen] = '\0'; |
985 | oldc[olen] = '\0'; |
861 | newc[nlen] = '\0'; |
986 | newc[nlen] = '\0'; |
862 | if (!str_lcmp(newc, oldc, str_length(oldc))) { |
987 | if ((!str_lcmp(newc, oldc, str_length(oldc))) && |
- | 988 | ((newc[str_length(oldc)] == '/') || |
|
- | 989 | (str_length(oldc) == 1) || |
|
- | 990 | (str_length(oldc) == str_length(newc)))) { |
|
- | 991 | /* |
|
863 | /* oldc is a prefix of newc */ |
992 | * oldc is a prefix of newc and either |
- | 993 | * - newc continues with a / where oldc ends, or |
|
- | 994 | * - oldc was / itself, or |
|
- | 995 | * - oldc and newc are equal. |
|
- | 996 | */ |
|
864 | ipc_answer_0(rid, EINVAL); |
997 | ipc_answer_0(rid, EINVAL); |
865 | free(old); |
998 | free(old); |
866 | free(new); |
999 | free(new); |
867 | return; |
1000 | return; |
868 | } |
1001 | } |
Line 886... | Line 1019... | ||
886 | ipc_answer_0(rid, ENOMEM); |
1019 | ipc_answer_0(rid, ENOMEM); |
887 | free(old); |
1020 | free(old); |
888 | free(new); |
1021 | free(new); |
889 | return; |
1022 | return; |
890 | } |
1023 | } |
- | 1024 | /* Determine the path to the parent of the node with the new name. */ |
|
- | 1025 | char *parentc = str_dup(newc); |
|
- | 1026 | if (!parentc) { |
|
- | 1027 | rwlock_write_unlock(&namespace_rwlock); |
|
- | 1028 | ipc_answer_0(rid, rc); |
|
- | 1029 | free(old); |
|
- | 1030 | free(new); |
|
- | 1031 | return; |
|
- | 1032 | } |
|
- | 1033 | char *lastsl = str_rchr(parentc + 1, L'/'); |
|
- | 1034 | if (lastsl) |
|
- | 1035 | *lastsl = '\0'; |
|
- | 1036 | else |
|
- | 1037 | parentc[1] = '\0'; |
|
891 | /* Lookup parent of the new file name. */ |
1038 | /* Lookup parent of the new file name. */ |
892 | rc = vfs_lookup_internal(newc, L_PARENT, &new_par_lr, NULL); |
1039 | rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); |
- | 1040 | free(parentc); /* not needed anymore */ |
|
893 | if (rc != EOK) { |
1041 | if (rc != EOK) { |
894 | rwlock_write_unlock(&namespace_rwlock); |
1042 | rwlock_write_unlock(&namespace_rwlock); |
895 | ipc_answer_0(rid, rc); |
1043 | ipc_answer_0(rid, rc); |
896 | free(old); |
1044 | free(old); |
897 | free(new); |
1045 | free(new); |