Changes in uspace/srv/vfs/vfs_ops.c [dd2cfa7:ffa2c8ef] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/vfs/vfs_ops.c
rdd2cfa7 rffa2c8ef 37 37 38 38 #include "vfs.h" 39 #include <ipc/ipc.h> 39 #include <macros.h> 40 #include <stdint.h> 40 41 #include <async.h> 41 42 #include <errno.h> 42 43 #include <stdio.h> 43 44 #include <stdlib.h> 44 #include <str ing.h>45 #include <str.h> 45 46 #include <bool.h> 46 #include <fibril_sync .h>47 #include <fibril_synch.h> 47 48 #include <adt/list.h> 48 49 #include <unistd.h> … … 53 54 54 55 /* Forward declarations of static functions. */ 55 static int vfs_truncate_internal(fs_handle_t, dev_handle_t, fs_index_t, size_t); 56 static int vfs_truncate_internal(fs_handle_t, devmap_handle_t, fs_index_t, 57 aoff64_t); 56 58 57 59 /** … … 63 65 vfs_pair_t rootfs = { 64 66 .fs_handle = 0, 65 .dev _handle = 067 .devmap_handle = 0 66 68 }; 67 69 68 static void vfs_mount_internal(ipc_callid_t rid, dev _handle_t dev_handle,70 static void vfs_mount_internal(ipc_callid_t rid, devmap_handle_t devmap_handle, 69 71 fs_handle_t fs_handle, char *mp, char *opts) 70 72 { … … 76 78 size_t rsize; 77 79 unsigned rlnkcnt; 78 ipcarg_t rc;80 sysarg_t rc; 79 81 int phone; 80 82 aid_t msg; … … 88 90 /* Trying to mount root FS over root FS */ 89 91 fibril_rwlock_write_unlock(&namespace_rwlock); 90 ipc_answer_0(rid, EBUSY);91 return; 92 } 93 94 rc = vfs_lookup_internal(mp, L_ DIRECTORY, &mp_res, NULL);92 async_answer_0(rid, EBUSY); 93 return; 94 } 95 96 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 95 97 if (rc != EOK) { 96 98 /* The lookup failed for some reason. */ 97 99 fibril_rwlock_write_unlock(&namespace_rwlock); 98 ipc_answer_0(rid, rc);100 async_answer_0(rid, rc); 99 101 return; 100 102 } … … 103 105 if (!mp_node) { 104 106 fibril_rwlock_write_unlock(&namespace_rwlock); 105 ipc_answer_0(rid, ENOMEM);107 async_answer_0(rid, ENOMEM); 106 108 return; 107 109 } … … 123 125 phone = vfs_grab_phone(fs_handle); 124 126 msg = async_send_1(phone, VFS_OUT_MOUNTED, 125 ( ipcarg_t) dev_handle, &answer);127 (sysarg_t) devmap_handle, &answer); 126 128 /* send the mount options */ 127 rc = ipc_data_write_start(phone, (void *)opts,129 rc = async_data_write_start(phone, (void *)opts, 128 130 str_size(opts)); 129 131 if (rc != EOK) { 130 132 async_wait_for(msg, NULL); 131 vfs_release_phone( phone);133 vfs_release_phone(fs_handle, phone); 132 134 fibril_rwlock_write_unlock(&namespace_rwlock); 133 ipc_answer_0(rid, rc);135 async_answer_0(rid, rc); 134 136 return; 135 137 } 136 138 async_wait_for(msg, &rc); 137 vfs_release_phone( phone);139 vfs_release_phone(fs_handle, phone); 138 140 139 141 if (rc != EOK) { 140 142 fibril_rwlock_write_unlock(&namespace_rwlock); 141 ipc_answer_0(rid, rc);143 async_answer_0(rid, rc); 142 144 return; 143 145 } … … 148 150 149 151 mr_res.triplet.fs_handle = fs_handle; 150 mr_res.triplet.dev _handle = dev_handle;152 mr_res.triplet.devmap_handle = devmap_handle; 151 153 mr_res.triplet.index = rindex; 152 154 mr_res.size = rsize; … … 155 157 156 158 rootfs.fs_handle = fs_handle; 157 rootfs.dev _handle = dev_handle;159 rootfs.devmap_handle = devmap_handle; 158 160 159 161 /* Add reference to the mounted root. */ … … 162 164 163 165 fibril_rwlock_write_unlock(&namespace_rwlock); 164 ipc_answer_0(rid, rc);166 async_answer_0(rid, rc); 165 167 return; 166 168 } else { … … 170 172 */ 171 173 fibril_rwlock_write_unlock(&namespace_rwlock); 172 ipc_answer_0(rid, ENOENT);174 async_answer_0(rid, ENOENT); 173 175 return; 174 176 } … … 185 187 phone = vfs_grab_phone(mp_res.triplet.fs_handle); 186 188 msg = async_send_4(phone, VFS_OUT_MOUNT, 187 ( ipcarg_t) mp_res.triplet.dev_handle,188 ( ipcarg_t) mp_res.triplet.index,189 ( ipcarg_t) fs_handle,190 ( ipcarg_t) dev_handle, &answer);189 (sysarg_t) mp_res.triplet.devmap_handle, 190 (sysarg_t) mp_res.triplet.index, 191 (sysarg_t) fs_handle, 192 (sysarg_t) devmap_handle, &answer); 191 193 192 194 /* send connection */ … … 194 196 if (rc != EOK) { 195 197 async_wait_for(msg, NULL); 196 vfs_release_phone( mountee_phone);197 vfs_release_phone( phone);198 vfs_release_phone(fs_handle, mountee_phone); 199 vfs_release_phone(mp_res.triplet.fs_handle, phone); 198 200 /* Mount failed, drop reference to mp_node. */ 199 201 if (mp_node) 200 202 vfs_node_put(mp_node); 201 ipc_answer_0(rid, rc);203 async_answer_0(rid, rc); 202 204 fibril_rwlock_write_unlock(&namespace_rwlock); 203 205 return; 204 206 } 205 207 206 vfs_release_phone( mountee_phone);208 vfs_release_phone(fs_handle, mountee_phone); 207 209 208 210 /* send the mount options */ 209 rc = ipc_data_write_start(phone, (void *)opts, str_size(opts));211 rc = async_data_write_start(phone, (void *)opts, str_size(opts)); 210 212 if (rc != EOK) { 211 213 async_wait_for(msg, NULL); 212 vfs_release_phone( phone);214 vfs_release_phone(mp_res.triplet.fs_handle, phone); 213 215 /* Mount failed, drop reference to mp_node. */ 214 216 if (mp_node) 215 217 vfs_node_put(mp_node); 216 218 fibril_rwlock_write_unlock(&namespace_rwlock); 217 ipc_answer_0(rid, rc);219 async_answer_0(rid, rc); 218 220 return; 219 221 } 220 222 async_wait_for(msg, &rc); 221 vfs_release_phone( phone);223 vfs_release_phone(mp_res.triplet.fs_handle, phone); 222 224 223 225 if (rc == EOK) { … … 227 229 228 230 mr_res.triplet.fs_handle = fs_handle; 229 mr_res.triplet.dev _handle = dev_handle;231 mr_res.triplet.devmap_handle = devmap_handle; 230 232 mr_res.triplet.index = rindex; 231 233 mr_res.size = rsize; … … 242 244 } 243 245 244 ipc_answer_0(rid, rc);246 async_answer_0(rid, rc); 245 247 fibril_rwlock_write_unlock(&namespace_rwlock); 246 248 } … … 248 250 void vfs_mount(ipc_callid_t rid, ipc_call_t *request) 249 251 { 252 devmap_handle_t devmap_handle; 253 250 254 /* 251 255 * We expect the library to do the device-name to device-handle … … 253 257 * in the request. 254 258 */ 255 dev _handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);259 devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 256 260 257 261 /* … … 266 270 267 271 /* We want the client to send us the mount point. */ 268 ipc_callid_t callid; 269 size_t size; 270 if (!ipc_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 = ipc_data_write_finalize(callid, mp, size); 293 if (retval != EOK) { 294 ipc_answer_0(rid, retval); 272 char *mp; 273 int rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 274 0, NULL); 275 if (rc != EOK) { 276 async_answer_0(rid, rc); 277 return; 278 } 279 280 /* Now we expect to receive the mount options. */ 281 char *opts; 282 rc = async_data_write_accept((void **) &opts, true, 0, MAX_MNTOPTS_LEN, 283 0, NULL); 284 if (rc != EOK) { 295 285 free(mp); 296 return; 297 } 298 mp[size] = '\0'; 299 300 /* Now we expect to receive the mount options. */ 301 if (!ipc_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 = ipc_data_write_finalize(callid, opts, size); 327 if (retval != EOK) { 328 ipc_answer_0(rid, retval); 286 async_answer_0(rid, rc); 287 return; 288 } 289 290 /* 291 * Now, we expect the client to send us data with the name of the file 292 * system. 293 */ 294 char *fs_name; 295 rc = async_data_write_accept((void **) &fs_name, true, 0, 296 FS_NAME_MAXLEN, 0, NULL); 297 if (rc != EOK) { 329 298 free(mp); 330 299 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 (!ipc_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 = ipc_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 300 async_answer_0(rid, rc); 301 return; 302 } 303 382 304 /* 383 305 * Wait for IPC_M_PING so that we can return an error if we don't know … … 385 307 */ 386 308 ipc_call_t data; 387 callid = async_get_call(&data);388 if (IPC_GET_ METHOD(data) != IPC_M_PING) {389 ipc_answer_0(callid, ENOTSUP);390 ipc_answer_0(rid, ENOTSUP);309 ipc_callid_t callid = async_get_call(&data); 310 if (IPC_GET_IMETHOD(data) != IPC_M_PING) { 311 async_answer_0(callid, ENOTSUP); 312 async_answer_0(rid, ENOTSUP); 391 313 free(mp); 392 314 free(opts); … … 410 332 411 333 fibril_mutex_unlock(&fs_head_lock); 412 ipc_answer_0(callid, ENOENT);413 ipc_answer_0(rid, ENOENT);334 async_answer_0(callid, ENOENT); 335 async_answer_0(rid, ENOENT); 414 336 free(mp); 415 337 free(fs_name); … … 420 342 421 343 /* Acknowledge that we know fs_name. */ 422 ipc_answer_0(callid, EOK);344 async_answer_0(callid, EOK); 423 345 424 346 /* Do the mount */ 425 vfs_mount_internal(rid, dev _handle, fs_handle, mp, opts);347 vfs_mount_internal(rid, devmap_handle, fs_handle, mp, opts); 426 348 free(mp); 427 349 free(fs_name); … … 429 351 } 430 352 353 void vfs_unmount(ipc_callid_t rid, ipc_call_t *request) 354 { 355 int rc; 356 char *mp; 357 vfs_lookup_res_t mp_res; 358 vfs_lookup_res_t mr_res; 359 vfs_node_t *mr_node; 360 int phone; 361 362 /* 363 * Receive the mount point path. 364 */ 365 rc = async_data_write_accept((void **) &mp, true, 0, MAX_PATH_LEN, 366 0, NULL); 367 if (rc != EOK) 368 async_answer_0(rid, rc); 369 370 /* 371 * Taking the namespace lock will do two things for us. First, it will 372 * prevent races with other lookup operations. Second, it will stop new 373 * references to already existing VFS nodes and creation of new VFS 374 * nodes. This is because new references are added as a result of some 375 * lookup operation or at least of some operation which is protected by 376 * the namespace lock. 377 */ 378 fibril_rwlock_write_lock(&namespace_rwlock); 379 380 /* 381 * Lookup the mounted root and instantiate it. 382 */ 383 rc = vfs_lookup_internal(mp, L_ROOT, &mr_res, NULL); 384 if (rc != EOK) { 385 fibril_rwlock_write_unlock(&namespace_rwlock); 386 free(mp); 387 async_answer_0(rid, rc); 388 return; 389 } 390 mr_node = vfs_node_get(&mr_res); 391 if (!mr_node) { 392 fibril_rwlock_write_unlock(&namespace_rwlock); 393 free(mp); 394 async_answer_0(rid, ENOMEM); 395 return; 396 } 397 398 /* 399 * Count the total number of references for the mounted file system. We 400 * are expecting at least two. One which we got above and one which we 401 * got when the file system was mounted. If we find more, it means that 402 * the file system cannot be gracefully unmounted at the moment because 403 * someone is working with it. 404 */ 405 if (vfs_nodes_refcount_sum_get(mr_node->fs_handle, 406 mr_node->devmap_handle) != 2) { 407 fibril_rwlock_write_unlock(&namespace_rwlock); 408 vfs_node_put(mr_node); 409 free(mp); 410 async_answer_0(rid, EBUSY); 411 return; 412 } 413 414 if (str_cmp(mp, "/") == 0) { 415 416 /* 417 * Unmounting the root file system. 418 * 419 * In this case, there is no mount point node and we send 420 * VFS_OUT_UNMOUNTED directly to the mounted file system. 421 */ 422 423 free(mp); 424 phone = vfs_grab_phone(mr_node->fs_handle); 425 rc = async_req_1_0(phone, VFS_OUT_UNMOUNTED, 426 mr_node->devmap_handle); 427 vfs_release_phone(mr_node->fs_handle, phone); 428 if (rc != EOK) { 429 fibril_rwlock_write_unlock(&namespace_rwlock); 430 vfs_node_put(mr_node); 431 async_answer_0(rid, rc); 432 return; 433 } 434 rootfs.fs_handle = 0; 435 rootfs.devmap_handle = 0; 436 } else { 437 438 /* 439 * Unmounting a non-root file system. 440 * 441 * We have a regular mount point node representing the parent 442 * file system, so we delegate the operation to it. 443 */ 444 445 rc = vfs_lookup_internal(mp, L_MP, &mp_res, NULL); 446 free(mp); 447 if (rc != EOK) { 448 fibril_rwlock_write_unlock(&namespace_rwlock); 449 vfs_node_put(mr_node); 450 async_answer_0(rid, rc); 451 return; 452 } 453 vfs_node_t *mp_node = vfs_node_get(&mp_res); 454 if (!mp_node) { 455 fibril_rwlock_write_unlock(&namespace_rwlock); 456 vfs_node_put(mr_node); 457 async_answer_0(rid, ENOMEM); 458 return; 459 } 460 461 phone = vfs_grab_phone(mp_node->fs_handle); 462 rc = async_req_2_0(phone, VFS_OUT_UNMOUNT, 463 mp_node->devmap_handle, mp_node->index); 464 vfs_release_phone(mp_node->fs_handle, phone); 465 if (rc != EOK) { 466 fibril_rwlock_write_unlock(&namespace_rwlock); 467 vfs_node_put(mp_node); 468 vfs_node_put(mr_node); 469 async_answer_0(rid, rc); 470 return; 471 } 472 473 /* Drop the reference we got above. */ 474 vfs_node_put(mp_node); 475 /* Drop the reference from when the file system was mounted. */ 476 vfs_node_put(mp_node); 477 } 478 479 480 /* 481 * All went well, the mounted file system was successfully unmounted. 482 * The only thing left is to forget the unmounted root VFS node. 483 */ 484 vfs_node_forget(mr_node); 485 486 fibril_rwlock_write_unlock(&namespace_rwlock); 487 async_answer_0(rid, EOK); 488 } 489 431 490 void vfs_open(ipc_callid_t rid, ipc_call_t *request) 432 491 { 433 if (!vfs_files_init()) {434 ipc_answer_0(rid, ENOMEM);435 return;436 }437 438 492 /* 439 493 * The POSIX interface is open(path, oflag, mode). … … 447 501 int oflag = IPC_GET_ARG2(*request); 448 502 int mode = IPC_GET_ARG3(*request); 449 size_t len;450 503 451 504 /* Ignore mode for now. */ … … 454 507 /* 455 508 * 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. 509 * L_DIRECTORY. Make sure that the user does not pass L_OPEN, 510 * L_ROOT or L_MP. 457 511 */ 458 512 if (((lflag & (L_FILE | L_DIRECTORY)) == 0) || 459 513 ((lflag & (L_FILE | L_DIRECTORY)) == (L_FILE | L_DIRECTORY)) || 460 ( (lflag & L_OPEN) != 0)) {461 ipc_answer_0(rid, EINVAL);514 (lflag & (L_OPEN | L_ROOT | L_MP))) { 515 async_answer_0(rid, EINVAL); 462 516 return; 463 517 } … … 468 522 lflag |= L_EXCLUSIVE; 469 523 470 ipc_callid_t callid; 471 if (!ipc_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 = ipc_data_write_finalize(callid, path, len))) { 486 ipc_answer_0(rid, rc); 487 free(path); 488 return; 489 } 490 path[len] = '\0'; 524 char *path; 525 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 526 if (rc != EOK) { 527 async_answer_0(rid, rc); 528 return; 529 } 491 530 492 531 /* … … 508 547 else 509 548 fibril_rwlock_read_unlock(&namespace_rwlock); 510 ipc_answer_0(rid, rc);549 async_answer_0(rid, rc); 511 550 free(path); 512 551 return; … … 527 566 if (node->size) { 528 567 rc = vfs_truncate_internal(node->fs_handle, 529 node->dev _handle, node->index, 0);568 node->devmap_handle, node->index, 0); 530 569 if (rc) { 531 570 fibril_rwlock_write_unlock(&node->contents_rwlock); 532 571 vfs_node_put(node); 533 ipc_answer_0(rid, rc);572 async_answer_0(rid, rc); 534 573 return; 535 574 } … … 543 582 * structure. 544 583 */ 545 int fd = vfs_fd_alloc( );584 int fd = vfs_fd_alloc((oflag & O_DESC) != 0); 546 585 if (fd < 0) { 547 586 vfs_node_put(node); 548 ipc_answer_0(rid, fd);587 async_answer_0(rid, fd); 549 588 return; 550 589 } 551 590 vfs_file_t *file = vfs_file_get(fd); 591 assert(file); 552 592 file->node = node; 553 593 if (oflag & O_APPEND) … … 563 603 vfs_node_addref(node); 564 604 vfs_node_put(node); 605 vfs_file_put(file); 565 606 566 607 /* Success! Return the new file descriptor to the client. */ 567 ipc_answer_1(rid, EOK, fd);608 async_answer_1(rid, EOK, fd); 568 609 } 569 610 … … 572 613 // FIXME: check for sanity of the supplied fs, dev and index 573 614 574 if (!vfs_files_init()) {575 ipc_answer_0(rid, ENOMEM);576 return;577 }578 579 615 /* 580 616 * The interface is open_node(fs, dev, index, oflag). … … 583 619 584 620 lr.triplet.fs_handle = IPC_GET_ARG1(*request); 585 lr.triplet.dev _handle = IPC_GET_ARG2(*request);621 lr.triplet.devmap_handle = IPC_GET_ARG2(*request); 586 622 lr.triplet.index = IPC_GET_ARG3(*request); 587 623 int oflag = IPC_GET_ARG4(*request); … … 592 628 if (rc != EOK) { 593 629 fibril_rwlock_read_unlock(&namespace_rwlock); 594 ipc_answer_0(rid, rc);630 async_answer_0(rid, rc); 595 631 return; 596 632 } … … 604 640 if (node->size) { 605 641 rc = vfs_truncate_internal(node->fs_handle, 606 node->dev _handle, node->index, 0);642 node->devmap_handle, node->index, 0); 607 643 if (rc) { 608 644 fibril_rwlock_write_unlock(&node->contents_rwlock); 609 645 vfs_node_put(node); 610 ipc_answer_0(rid, rc);646 async_answer_0(rid, rc); 611 647 return; 612 648 } … … 620 656 * structure. 621 657 */ 622 int fd = vfs_fd_alloc( );658 int fd = vfs_fd_alloc((oflag & O_DESC) != 0); 623 659 if (fd < 0) { 624 660 vfs_node_put(node); 625 ipc_answer_0(rid, fd);661 async_answer_0(rid, fd); 626 662 return; 627 663 } … … 640 676 vfs_node_addref(node); 641 677 vfs_node_put(node); 678 vfs_file_put(file); 642 679 643 680 /* Success! Return the new file descriptor to the client. */ 644 ipc_answer_1(rid, EOK, fd);681 async_answer_1(rid, EOK, fd); 645 682 } 646 683 … … 652 689 vfs_file_t *file = vfs_file_get(fd); 653 690 if (!file) { 654 ipc_answer_0(rid, ENOENT);691 async_answer_0(rid, ENOENT); 655 692 return; 656 693 } … … 666 703 aid_t msg; 667 704 ipc_call_t answer; 668 msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->dev _handle,705 msg = async_send_2(fs_phone, VFS_OUT_SYNC, file->node->devmap_handle, 669 706 file->node->index, &answer); 670 707 671 708 /* Wait for reply from the FS server. */ 672 ipcarg_t rc;709 sysarg_t rc; 673 710 async_wait_for(msg, &rc); 674 711 675 vfs_release_phone(f s_phone);712 vfs_release_phone(file->node->fs_handle, fs_phone); 676 713 fibril_mutex_unlock(&file->lock); 677 678 ipc_answer_0(rid, rc); 714 715 vfs_file_put(file); 716 async_answer_0(rid, rc); 717 } 718 719 int vfs_close_internal(vfs_file_t *file) 720 { 721 /* 722 * Lock the open file structure so that no other thread can manipulate 723 * the same open file at a time. 724 */ 725 fibril_mutex_lock(&file->lock); 726 727 if (file->refcnt <= 1) { 728 /* Only close the file on the destination FS server 729 if there are no more file descriptors (except the 730 present one) pointing to this file. */ 731 732 int fs_phone = vfs_grab_phone(file->node->fs_handle); 733 734 /* Make a VFS_OUT_CLOSE request at the destination FS server. */ 735 aid_t msg; 736 ipc_call_t answer; 737 msg = async_send_2(fs_phone, VFS_OUT_CLOSE, 738 file->node->devmap_handle, file->node->index, &answer); 739 740 /* Wait for reply from the FS server. */ 741 sysarg_t rc; 742 async_wait_for(msg, &rc); 743 744 vfs_release_phone(file->node->fs_handle, fs_phone); 745 fibril_mutex_unlock(&file->lock); 746 747 return IPC_GET_ARG1(answer); 748 } 749 750 fibril_mutex_unlock(&file->lock); 751 return EOK; 679 752 } 680 753 … … 686 759 vfs_file_t *file = vfs_file_get(fd); 687 760 if (!file) { 688 ipc_answer_0(rid, ENOENT); 689 return; 690 } 691 692 /* 693 * Lock the open file structure so that no other thread can manipulate 694 * the same open file at a time. 695 */ 696 fibril_mutex_lock(&file->lock); 697 int fs_phone = vfs_grab_phone(file->node->fs_handle); 698 699 /* Make a VFS_OUT_CLOSE request at the destination FS server. */ 700 aid_t msg; 701 ipc_call_t answer; 702 msg = async_send_2(fs_phone, VFS_OUT_CLOSE, file->node->dev_handle, 703 file->node->index, &answer); 704 705 /* Wait for reply from the FS server. */ 706 ipcarg_t rc; 707 async_wait_for(msg, &rc); 708 709 vfs_release_phone(fs_phone); 710 fibril_mutex_unlock(&file->lock); 711 712 int retval = IPC_GET_ARG1(answer); 713 if (retval != EOK) 714 ipc_answer_0(rid, retval); 715 716 retval = vfs_fd_free(fd); 717 ipc_answer_0(rid, retval); 761 async_answer_0(rid, ENOENT); 762 return; 763 } 764 765 int ret = vfs_close_internal(file); 766 if (ret != EOK) 767 async_answer_0(rid, ret); 768 769 vfs_file_put(file); 770 ret = vfs_fd_free(fd); 771 async_answer_0(rid, ret); 718 772 } 719 773 720 774 static void vfs_rdwr(ipc_callid_t rid, ipc_call_t *request, bool read) 721 775 { 776 vfs_info_t *vi; 722 777 723 778 /* … … 736 791 vfs_file_t *file = vfs_file_get(fd); 737 792 if (!file) { 738 ipc_answer_0(rid, ENOENT); 739 return; 740 } 741 742 /* 743 * Now we need to receive a call with client's 744 * IPC_M_DATA_READ/IPC_M_DATA_WRITE request. 745 */ 746 ipc_callid_t callid; 747 int res; 748 if (read) 749 res = ipc_data_read_receive(&callid, NULL); 750 else 751 res = ipc_data_write_receive(&callid, NULL); 752 if (!res) { 753 ipc_answer_0(callid, EINVAL); 754 ipc_answer_0(rid, EINVAL); 793 async_answer_0(rid, ENOENT); 755 794 return; 756 795 } … … 762 801 fibril_mutex_lock(&file->lock); 763 802 803 vi = fs_handle_to_info(file->node->fs_handle); 804 assert(vi); 805 764 806 /* 765 807 * Lock the file's node so that no other client can read/write to it at 766 * the same time. 767 */ 768 if (read) 808 * the same time unless the FS supports concurrent reads/writes and its 809 * write implementation does not modify the file size. 810 */ 811 if (read || (vi->concurrent_read_write && vi->write_retains_size)) 769 812 fibril_rwlock_read_lock(&file->node->contents_rwlock); 770 813 else … … 780 823 } 781 824 782 int fs_phone = vfs_grab_phone(file->node->fs_handle); 783 784 /* Make a VFS_READ/VFS_WRITE request at the destination FS server. */ 785 aid_t msg; 786 ipc_call_t answer; 787 if (!read && file->append) 788 file->pos = file->node->size; 789 msg = async_send_3(fs_phone, read ? VFS_OUT_READ : VFS_OUT_WRITE, 790 file->node->dev_handle, file->node->index, file->pos, &answer); 791 792 /* 793 * Forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the 825 int fs_phone = vfs_grab_phone(file->node->fs_handle); 826 827 /* 828 * Make a VFS_READ/VFS_WRITE request at the destination FS server 829 * and forward the IPC_M_DATA_READ/IPC_M_DATA_WRITE request to the 794 830 * destination FS server. The call will be routed as if sent by 795 831 * ourselves. Note that call arguments are immutable in this case so we 796 832 * don't have to bother. 797 833 */ 798 ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 799 800 /* Wait for reply from the FS server. */ 801 ipcarg_t rc; 802 async_wait_for(msg, &rc); 803 804 vfs_release_phone(fs_phone); 834 sysarg_t rc; 835 ipc_call_t answer; 836 if (read) { 837 rc = async_data_read_forward_3_1(fs_phone, VFS_OUT_READ, 838 file->node->devmap_handle, file->node->index, file->pos, 839 &answer); 840 } else { 841 if (file->append) 842 file->pos = file->node->size; 843 844 rc = async_data_write_forward_3_1(fs_phone, VFS_OUT_WRITE, 845 file->node->devmap_handle, file->node->index, file->pos, 846 &answer); 847 } 848 849 vfs_release_phone(file->node->fs_handle, fs_phone); 805 850 806 851 size_t bytes = IPC_GET_ARG1(answer); 807 852 808 853 if (file->node->type == VFS_NODE_DIRECTORY) 809 854 fibril_rwlock_read_unlock(&namespace_rwlock); 810 855 811 856 /* Unlock the VFS node. */ 812 if (read )857 if (read || (vi->concurrent_read_write && vi->write_retains_size)) 813 858 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 814 859 else { … … 823 868 file->pos += bytes; 824 869 fibril_mutex_unlock(&file->lock); 825 870 vfs_file_put(file); 871 826 872 /* 827 873 * FS server's reply is the final result of the whole operation we 828 874 * return to the client. 829 875 */ 830 ipc_answer_1(rid, rc, bytes);876 async_answer_1(rid, rc, bytes); 831 877 } 832 878 … … 844 890 { 845 891 int fd = (int) IPC_GET_ARG1(*request); 846 off _t off = (off_t) IPC_GET_ARG2(*request);847 int whence = (int) IPC_GET_ARG3(*request);848 849 892 off64_t off = (off64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), 893 IPC_GET_ARG3(*request)); 894 int whence = (int) IPC_GET_ARG4(*request); 895 850 896 /* Lookup the file structure corresponding to the file descriptor. */ 851 897 vfs_file_t *file = vfs_file_get(fd); 852 898 if (!file) { 853 ipc_answer_0(rid, ENOENT); 854 return; 855 } 856 857 off_t newpos; 899 async_answer_0(rid, ENOENT); 900 return; 901 } 902 858 903 fibril_mutex_lock(&file->lock); 859 if (whence == SEEK_SET) { 860 file->pos = off; 904 905 off64_t newoff; 906 switch (whence) { 907 case SEEK_SET: 908 if (off >= 0) { 909 file->pos = (aoff64_t) off; 910 fibril_mutex_unlock(&file->lock); 911 vfs_file_put(file); 912 async_answer_1(rid, EOK, off); 913 return; 914 } 915 break; 916 case SEEK_CUR: 917 if ((off >= 0) && (file->pos + off < file->pos)) { 918 fibril_mutex_unlock(&file->lock); 919 vfs_file_put(file); 920 async_answer_0(rid, EOVERFLOW); 921 return; 922 } 923 924 if ((off < 0) && (file->pos < (aoff64_t) -off)) { 925 fibril_mutex_unlock(&file->lock); 926 vfs_file_put(file); 927 async_answer_0(rid, EOVERFLOW); 928 return; 929 } 930 931 file->pos += off; 932 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos; 933 861 934 fibril_mutex_unlock(&file->lock); 862 ipc_answer_1(rid, EOK, off); 863 return; 864 } 865 if (whence == SEEK_CUR) { 866 if (file->pos + off < file->pos) { 935 vfs_file_put(file); 936 async_answer_2(rid, EOK, LOWER32(newoff), 937 UPPER32(newoff)); 938 return; 939 case SEEK_END: 940 fibril_rwlock_read_lock(&file->node->contents_rwlock); 941 aoff64_t size = file->node->size; 942 943 if ((off >= 0) && (size + off < size)) { 944 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 867 945 fibril_mutex_unlock(&file->lock); 868 ipc_answer_0(rid, EOVERFLOW); 869 return; 870 } 871 file->pos += off; 872 newpos = file->pos; 946 vfs_file_put(file); 947 async_answer_0(rid, EOVERFLOW); 948 return; 949 } 950 951 if ((off < 0) && (size < (aoff64_t) -off)) { 952 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 953 fibril_mutex_unlock(&file->lock); 954 vfs_file_put(file); 955 async_answer_0(rid, EOVERFLOW); 956 return; 957 } 958 959 file->pos = size + off; 960 newoff = (file->pos > OFF64_MAX) ? OFF64_MAX : file->pos; 961 962 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 873 963 fibril_mutex_unlock(&file->lock); 874 ipc_answer_1(rid, EOK, newpos); 875 return; 876 } 877 if (whence == SEEK_END) { 878 fibril_rwlock_read_lock(&file->node->contents_rwlock); 879 size_t size = file->node->size; 880 fibril_rwlock_read_unlock(&file->node->contents_rwlock); 881 if (size + off < size) { 882 fibril_mutex_unlock(&file->lock); 883 ipc_answer_0(rid, EOVERFLOW); 884 return; 885 } 886 newpos = size + off; 887 fibril_mutex_unlock(&file->lock); 888 ipc_answer_1(rid, EOK, newpos); 889 return; 890 } 964 vfs_file_put(file); 965 async_answer_2(rid, EOK, LOWER32(newoff), UPPER32(newoff)); 966 return; 967 } 968 891 969 fibril_mutex_unlock(&file->lock); 892 ipc_answer_0(rid, EINVAL);893 } 894 895 int 896 vfs_truncate_internal(fs_handle_t fs_handle, dev_handle_t dev_handle,897 fs_index_t index, size_t size)898 { 899 ipcarg_t rc;970 vfs_file_put(file); 971 async_answer_0(rid, EINVAL); 972 } 973 974 int vfs_truncate_internal(fs_handle_t fs_handle, devmap_handle_t devmap_handle, 975 fs_index_t index, aoff64_t size) 976 { 977 sysarg_t rc; 900 978 int fs_phone; 901 979 902 980 fs_phone = vfs_grab_phone(fs_handle); 903 rc = async_req_ 3_0(fs_phone, VFS_OUT_TRUNCATE, (ipcarg_t)dev_handle,904 ( ipcarg_t)index, (ipcarg_t)size);905 vfs_release_phone(fs_ phone);981 rc = async_req_4_0(fs_phone, VFS_OUT_TRUNCATE, (sysarg_t) devmap_handle, 982 (sysarg_t) index, LOWER32(size), UPPER32(size)); 983 vfs_release_phone(fs_handle, fs_phone); 906 984 return (int)rc; 907 985 } … … 910 988 { 911 989 int fd = IPC_GET_ARG1(*request); 912 size_t size = IPC_GET_ARG2(*request); 990 aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG2(*request), 991 IPC_GET_ARG3(*request)); 913 992 int rc; 914 993 915 994 vfs_file_t *file = vfs_file_get(fd); 916 995 if (!file) { 917 ipc_answer_0(rid, ENOENT);996 async_answer_0(rid, ENOENT); 918 997 return; 919 998 } … … 922 1001 fibril_rwlock_write_lock(&file->node->contents_rwlock); 923 1002 rc = vfs_truncate_internal(file->node->fs_handle, 924 file->node->dev _handle, file->node->index, size);1003 file->node->devmap_handle, file->node->index, size); 925 1004 if (rc == EOK) 926 1005 file->node->size = size; … … 928 1007 929 1008 fibril_mutex_unlock(&file->lock); 930 ipc_answer_0(rid, (ipcarg_t)rc); 1009 vfs_file_put(file); 1010 async_answer_0(rid, (sysarg_t)rc); 931 1011 } 932 1012 … … 934 1014 { 935 1015 int fd = IPC_GET_ARG1(*request); 936 size_t size = IPC_GET_ARG2(*request); 937 ipcarg_t rc; 1016 sysarg_t rc; 938 1017 939 1018 vfs_file_t *file = vfs_file_get(fd); 940 1019 if (!file) { 941 ipc_answer_0(rid, ENOENT);1020 async_answer_0(rid, ENOENT); 942 1021 return; 943 1022 } 944 1023 945 1024 ipc_callid_t callid; 946 if (!ipc_data_read_receive(&callid, NULL)) { 947 ipc_answer_0(callid, EINVAL); 948 ipc_answer_0(rid, EINVAL); 1025 if (!async_data_read_receive(&callid, NULL)) { 1026 vfs_file_put(file); 1027 async_answer_0(callid, EINVAL); 1028 async_answer_0(rid, EINVAL); 949 1029 return; 950 1030 } … … 955 1035 956 1036 aid_t msg; 957 msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->dev _handle,1037 msg = async_send_3(fs_phone, VFS_OUT_STAT, file->node->devmap_handle, 958 1038 file->node->index, true, NULL); 959 ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);1039 async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 960 1040 async_wait_for(msg, &rc); 961 vfs_release_phone(f s_phone);1041 vfs_release_phone(file->node->fs_handle, fs_phone); 962 1042 963 1043 fibril_mutex_unlock(&file->lock); 964 ipc_answer_0(rid, rc); 1044 vfs_file_put(file); 1045 async_answer_0(rid, rc); 965 1046 } 966 1047 967 1048 void vfs_stat(ipc_callid_t rid, ipc_call_t *request) 968 1049 { 969 size_t len; 1050 char *path; 1051 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1052 if (rc != EOK) { 1053 async_answer_0(rid, rc); 1054 return; 1055 } 1056 970 1057 ipc_callid_t callid; 971 972 if (!ipc_data_write_receive(&callid, &len)) { 973 ipc_answer_0(callid, EINVAL); 974 ipc_answer_0(rid, EINVAL); 975 return; 976 } 977 char *path = malloc(len + 1); 978 if (!path) { 979 ipc_answer_0(callid, ENOMEM); 980 ipc_answer_0(rid, ENOMEM); 981 return; 982 } 983 int rc; 984 if ((rc = ipc_data_write_finalize(callid, path, len))) { 985 ipc_answer_0(rid, rc); 1058 if (!async_data_read_receive(&callid, NULL)) { 986 1059 free(path); 987 return; 988 } 989 path[len] = '\0'; 990 991 if (!ipc_data_read_receive(&callid, NULL)) { 992 free(path); 993 ipc_answer_0(callid, EINVAL); 994 ipc_answer_0(rid, EINVAL); 1060 async_answer_0(callid, EINVAL); 1061 async_answer_0(rid, EINVAL); 995 1062 return; 996 1063 } … … 1002 1069 if (rc != EOK) { 1003 1070 fibril_rwlock_read_unlock(&namespace_rwlock); 1004 ipc_answer_0(callid, rc);1005 ipc_answer_0(rid, rc);1071 async_answer_0(callid, rc); 1072 async_answer_0(rid, rc); 1006 1073 return; 1007 1074 } … … 1009 1076 if (!node) { 1010 1077 fibril_rwlock_read_unlock(&namespace_rwlock); 1011 ipc_answer_0(callid, ENOMEM);1012 ipc_answer_0(rid, ENOMEM);1078 async_answer_0(callid, ENOMEM); 1079 async_answer_0(rid, ENOMEM); 1013 1080 return; 1014 1081 } … … 1018 1085 int fs_phone = vfs_grab_phone(node->fs_handle); 1019 1086 aid_t msg; 1020 msg = async_send_3(fs_phone, VFS_OUT_STAT, node->dev _handle,1087 msg = async_send_3(fs_phone, VFS_OUT_STAT, node->devmap_handle, 1021 1088 node->index, false, NULL); 1022 ipc_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);1023 1024 ipcarg_t rv;1089 async_forward_fast(callid, fs_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME); 1090 1091 sysarg_t rv; 1025 1092 async_wait_for(msg, &rv); 1026 vfs_release_phone( fs_phone);1027 1028 ipc_answer_0(rid, rv);1093 vfs_release_phone(node->fs_handle, fs_phone); 1094 1095 async_answer_0(rid, rv); 1029 1096 1030 1097 vfs_node_put(node); … … 1034 1101 { 1035 1102 int mode = IPC_GET_ARG1(*request); 1036 1037 size_t len; 1038 ipc_callid_t callid; 1039 1040 if (!ipc_data_write_receive(&callid, &len)) { 1041 ipc_answer_0(callid, EINVAL); 1042 ipc_answer_0(rid, EINVAL); 1043 return; 1044 } 1045 char *path = malloc(len + 1); 1046 if (!path) { 1047 ipc_answer_0(callid, ENOMEM); 1048 ipc_answer_0(rid, ENOMEM); 1049 return; 1050 } 1051 int rc; 1052 if ((rc = ipc_data_write_finalize(callid, path, len))) { 1053 ipc_answer_0(rid, rc); 1054 free(path); 1055 return; 1056 } 1057 path[len] = '\0'; 1058 1103 1104 char *path; 1105 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1106 if (rc != EOK) { 1107 async_answer_0(rid, rc); 1108 return; 1109 } 1110 1059 1111 /* Ignore mode for now. */ 1060 1112 (void) mode; … … 1065 1117 fibril_rwlock_write_unlock(&namespace_rwlock); 1066 1118 free(path); 1067 ipc_answer_0(rid, rc);1119 async_answer_0(rid, rc); 1068 1120 } 1069 1121 … … 1071 1123 { 1072 1124 int lflag = IPC_GET_ARG1(*request); 1073 1074 size_t len; 1075 ipc_callid_t callid; 1076 1077 if (!ipc_data_write_receive(&callid, &len)) { 1078 ipc_answer_0(callid, EINVAL); 1079 ipc_answer_0(rid, EINVAL); 1080 return; 1081 } 1082 char *path = malloc(len + 1); 1083 if (!path) { 1084 ipc_answer_0(callid, ENOMEM); 1085 ipc_answer_0(rid, ENOMEM); 1086 return; 1087 } 1088 int rc; 1089 if ((rc = ipc_data_write_finalize(callid, path, len))) { 1090 ipc_answer_0(rid, rc); 1091 free(path); 1092 return; 1093 } 1094 path[len] = '\0'; 1125 1126 char *path; 1127 int rc = async_data_write_accept((void **) &path, true, 0, 0, 0, NULL); 1128 if (rc != EOK) { 1129 async_answer_0(rid, rc); 1130 return; 1131 } 1095 1132 1096 1133 fibril_rwlock_write_lock(&namespace_rwlock); … … 1101 1138 if (rc != EOK) { 1102 1139 fibril_rwlock_write_unlock(&namespace_rwlock); 1103 ipc_answer_0(rid, rc);1140 async_answer_0(rid, rc); 1104 1141 return; 1105 1142 } … … 1116 1153 fibril_rwlock_write_unlock(&namespace_rwlock); 1117 1154 vfs_node_put(node); 1118 ipc_answer_0(rid, EOK);1155 async_answer_0(rid, EOK); 1119 1156 } 1120 1157 1121 1158 void vfs_rename(ipc_callid_t rid, ipc_call_t *request) 1122 1159 { 1123 size_t olen, nlen;1124 ipc_callid_t callid;1125 int rc;1126 1127 1160 /* Retrieve the old path. */ 1128 if (!ipc_data_write_receive(&callid, &olen)) { 1129 ipc_answer_0(callid, EINVAL); 1130 ipc_answer_0(rid, EINVAL); 1131 return; 1132 } 1133 char *old = malloc(olen + 1); 1134 if (!old) { 1135 ipc_answer_0(callid, ENOMEM); 1136 ipc_answer_0(rid, ENOMEM); 1137 return; 1138 } 1139 if ((rc = ipc_data_write_finalize(callid, old, olen))) { 1140 ipc_answer_0(rid, rc); 1161 char *old; 1162 int rc = async_data_write_accept((void **) &old, true, 0, 0, 0, NULL); 1163 if (rc != EOK) { 1164 async_answer_0(rid, rc); 1165 return; 1166 } 1167 1168 /* Retrieve the new path. */ 1169 char *new; 1170 rc = async_data_write_accept((void **) &new, true, 0, 0, 0, NULL); 1171 if (rc != EOK) { 1141 1172 free(old); 1142 return; 1143 } 1144 old[olen] = '\0'; 1145 1146 /* Retrieve the new path. */ 1147 if (!ipc_data_write_receive(&callid, &nlen)) { 1148 ipc_answer_0(callid, EINVAL); 1149 ipc_answer_0(rid, EINVAL); 1150 free(old); 1151 return; 1152 } 1153 char *new = malloc(nlen + 1); 1154 if (!new) { 1155 ipc_answer_0(callid, ENOMEM); 1156 ipc_answer_0(rid, ENOMEM); 1157 free(old); 1158 return; 1159 } 1160 if ((rc = ipc_data_write_finalize(callid, new, nlen))) { 1161 ipc_answer_0(rid, rc); 1173 async_answer_0(rid, rc); 1174 return; 1175 } 1176 1177 size_t olen; 1178 size_t nlen; 1179 char *oldc = canonify(old, &olen); 1180 char *newc = canonify(new, &nlen); 1181 1182 if ((!oldc) || (!newc)) { 1183 async_answer_0(rid, EINVAL); 1162 1184 free(old); 1163 1185 free(new); 1164 1186 return; 1165 1187 } 1166 new[nlen] = '\0'; 1167 1168 char *oldc = canonify(old, &olen); 1169 char *newc = canonify(new, &nlen); 1170 if (!oldc || !newc) { 1171 ipc_answer_0(rid, EINVAL); 1172 free(old); 1173 free(new); 1174 return; 1175 } 1188 1176 1189 oldc[olen] = '\0'; 1177 1190 newc[nlen] = '\0'; 1191 1178 1192 if ((!str_lcmp(newc, oldc, str_length(oldc))) && 1179 1193 ((newc[str_length(oldc)] == '/') || … … 1186 1200 * - oldc and newc are equal. 1187 1201 */ 1188 ipc_answer_0(rid, EINVAL);1202 async_answer_0(rid, EINVAL); 1189 1203 free(old); 1190 1204 free(new); … … 1196 1210 vfs_lookup_res_t new_par_lr; 1197 1211 fibril_rwlock_write_lock(&namespace_rwlock); 1212 1198 1213 /* Lookup the node belonging to the old file name. */ 1199 1214 rc = vfs_lookup_internal(oldc, L_NONE, &old_lr, NULL); 1200 1215 if (rc != EOK) { 1201 1216 fibril_rwlock_write_unlock(&namespace_rwlock); 1202 ipc_answer_0(rid, rc);1217 async_answer_0(rid, rc); 1203 1218 free(old); 1204 1219 free(new); 1205 1220 return; 1206 1221 } 1222 1207 1223 vfs_node_t *old_node = vfs_node_get(&old_lr); 1208 1224 if (!old_node) { 1209 1225 fibril_rwlock_write_unlock(&namespace_rwlock); 1210 ipc_answer_0(rid, ENOMEM);1226 async_answer_0(rid, ENOMEM); 1211 1227 free(old); 1212 1228 free(new); 1213 1229 return; 1214 1230 } 1231 1215 1232 /* Determine the path to the parent of the node with the new name. */ 1216 1233 char *parentc = str_dup(newc); 1217 1234 if (!parentc) { 1218 1235 fibril_rwlock_write_unlock(&namespace_rwlock); 1219 ipc_answer_0(rid, rc);1236 async_answer_0(rid, rc); 1220 1237 free(old); 1221 1238 free(new); 1222 1239 return; 1223 1240 } 1241 1224 1242 char *lastsl = str_rchr(parentc + 1, '/'); 1225 1243 if (lastsl) … … 1227 1245 else 1228 1246 parentc[1] = '\0'; 1247 1229 1248 /* Lookup parent of the new file name. */ 1230 1249 rc = vfs_lookup_internal(parentc, L_NONE, &new_par_lr, NULL); … … 1232 1251 if (rc != EOK) { 1233 1252 fibril_rwlock_write_unlock(&namespace_rwlock); 1234 ipc_answer_0(rid, rc);1253 async_answer_0(rid, rc); 1235 1254 free(old); 1236 1255 free(new); 1237 1256 return; 1238 1257 } 1258 1239 1259 /* Check whether linking to the same file system instance. */ 1240 1260 if ((old_node->fs_handle != new_par_lr.triplet.fs_handle) || 1241 (old_node->dev _handle != new_par_lr.triplet.dev_handle)) {1261 (old_node->devmap_handle != new_par_lr.triplet.devmap_handle)) { 1242 1262 fibril_rwlock_write_unlock(&namespace_rwlock); 1243 ipc_answer_0(rid, EXDEV); /* different file systems */1263 async_answer_0(rid, EXDEV); /* different file systems */ 1244 1264 free(old); 1245 1265 free(new); 1246 1266 return; 1247 1267 } 1268 1248 1269 /* Destroy the old link for the new name. */ 1249 1270 vfs_node_t *new_node = NULL; 1250 1271 rc = vfs_lookup_internal(newc, L_UNLINK, &new_lr, NULL); 1272 1251 1273 switch (rc) { 1252 1274 case ENOENT: … … 1257 1279 if (!new_node) { 1258 1280 fibril_rwlock_write_unlock(&namespace_rwlock); 1259 ipc_answer_0(rid, ENOMEM);1281 async_answer_0(rid, ENOMEM); 1260 1282 free(old); 1261 1283 free(new); … … 1268 1290 default: 1269 1291 fibril_rwlock_write_unlock(&namespace_rwlock); 1270 ipc_answer_0(rid, ENOTEMPTY);1292 async_answer_0(rid, ENOTEMPTY); 1271 1293 free(old); 1272 1294 free(new); 1273 1295 return; 1274 1296 } 1297 1275 1298 /* Create the new link for the new name. */ 1276 1299 rc = vfs_lookup_internal(newc, L_LINK, NULL, NULL, old_node->index); … … 1279 1302 if (new_node) 1280 1303 vfs_node_put(new_node); 1281 ipc_answer_0(rid, rc);1304 async_answer_0(rid, rc); 1282 1305 free(old); 1283 1306 free(new); 1284 1307 return; 1285 1308 } 1309 1286 1310 fibril_mutex_lock(&nodes_mutex); 1287 1311 old_node->lnkcnt++; 1288 1312 fibril_mutex_unlock(&nodes_mutex); 1313 1289 1314 /* Destroy the link for the old name. */ 1290 1315 rc = vfs_lookup_internal(oldc, L_UNLINK, NULL, NULL); … … 1294 1319 if (new_node) 1295 1320 vfs_node_put(new_node); 1296 ipc_answer_0(rid, rc);1321 async_answer_0(rid, rc); 1297 1322 free(old); 1298 1323 free(new); 1299 1324 return; 1300 1325 } 1326 1301 1327 fibril_mutex_lock(&nodes_mutex); 1302 1328 old_node->lnkcnt--; … … 1304 1330 fibril_rwlock_write_unlock(&namespace_rwlock); 1305 1331 vfs_node_put(old_node); 1332 1306 1333 if (new_node) 1307 1334 vfs_node_put(new_node); 1335 1308 1336 free(old); 1309 1337 free(new); 1310 ipc_answer_0(rid, EOK); 1338 async_answer_0(rid, EOK); 1339 } 1340 1341 void vfs_dup(ipc_callid_t rid, ipc_call_t *request) 1342 { 1343 int oldfd = IPC_GET_ARG1(*request); 1344 int newfd = IPC_GET_ARG2(*request); 1345 1346 /* If the file descriptors are the same, do nothing. */ 1347 if (oldfd == newfd) { 1348 async_answer_1(rid, EOK, newfd); 1349 return; 1350 } 1351 1352 /* Lookup the file structure corresponding to oldfd. */ 1353 vfs_file_t *oldfile = vfs_file_get(oldfd); 1354 if (!oldfile) { 1355 async_answer_0(rid, EBADF); 1356 return; 1357 } 1358 1359 /* 1360 * Lock the open file structure so that no other thread can manipulate 1361 * the same open file at a time. 1362 */ 1363 fibril_mutex_lock(&oldfile->lock); 1364 1365 /* Lookup an open file structure possibly corresponding to newfd. */ 1366 vfs_file_t *newfile = vfs_file_get(newfd); 1367 if (newfile) { 1368 /* Close the originally opened file. */ 1369 int ret = vfs_close_internal(newfile); 1370 if (ret != EOK) { 1371 fibril_mutex_unlock(&oldfile->lock); 1372 vfs_file_put(oldfile); 1373 vfs_file_put(newfile); 1374 async_answer_0(rid, ret); 1375 return; 1376 } 1377 1378 ret = vfs_fd_free(newfd); 1379 if (ret != EOK) { 1380 fibril_mutex_unlock(&oldfile->lock); 1381 vfs_file_put(oldfile); 1382 vfs_file_put(newfile); 1383 async_answer_0(rid, ret); 1384 return; 1385 } 1386 vfs_file_put(newfile); 1387 } 1388 1389 /* Assign the old file to newfd. */ 1390 int ret = vfs_fd_assign(oldfile, newfd); 1391 fibril_mutex_unlock(&oldfile->lock); 1392 vfs_file_put(oldfile); 1393 1394 if (ret != EOK) 1395 async_answer_0(rid, ret); 1396 else 1397 async_answer_1(rid, EOK, newfd); 1311 1398 } 1312 1399
Note:
See TracChangeset
for help on using the changeset viewer.