Changeset 3b3e776 in mainline for uspace/lib/libfs/libfs.c
- Timestamp:
- 2010-02-05T10:57:50Z (15 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libfs/libfs.c
r3f085132 r3b3e776 1 1 /* 2 * Copyright (c) 2009 Jakub Jermar 2 * Copyright (c) 2009 Jakub Jermar 3 3 * All rights reserved. 4 4 * … … 27 27 */ 28 28 29 /** @addtogroup libfs 29 /** @addtogroup libfs 30 30 * @{ 31 */ 31 */ 32 32 /** 33 33 * @file 34 * Glue code which is common od to all FS implementations.34 * Glue code which is common to all FS implementations. 35 35 */ 36 36 37 #include "libfs.h" 37 #include "libfs.h" 38 38 #include "../../srv/vfs/vfs.h" 39 39 #include <errno.h> … … 67 67 * code. 68 68 * 69 * @param vfs_phone Open phone for communication with VFS. 70 * @param reg File system registration structure. It will be 71 * initialized by this function. 72 * @param info VFS info structure supplied by the file system 73 * implementation. 74 * @param conn Connection fibril for handling all calls originating in 75 * VFS. 76 * 77 * @return EOK on success or a non-zero error code on errror. 69 * @param vfs_phone Open phone for communication with VFS. 70 * @param reg File system registration structure. It will be 71 * initialized by this function. 72 * @param info VFS info structure supplied by the file system 73 * implementation. 74 * @param conn Connection fibril for handling all calls originating in 75 * VFS. 76 * 77 * @return EOK on success or a non-zero error code on errror. 78 * 78 79 */ 79 80 int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info, … … 87 88 ipc_call_t answer; 88 89 aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer); 89 90 90 91 /* 91 92 * Send our VFS info structure to VFS. … … 96 97 return rc; 97 98 } 98 99 99 100 /* 100 101 * Ask VFS for callback connection. 101 102 */ 102 103 ipc_connect_to_me(vfs_phone, 0, 0, 0, ®->vfs_phonehash); 103 104 104 105 /* 105 106 * Allocate piece of address space for PLB. … … 110 111 return ENOMEM; 111 112 } 112 113 113 114 /* 114 115 * Request sharing the Path Lookup Buffer with VFS. … … 136 137 */ 137 138 async_set_client_connection(conn); 138 139 139 140 return IPC_GET_RETVAL(answer); 140 141 } … … 154 155 int res; 155 156 ipcarg_t rc; 156 157 157 158 ipc_call_t call; 158 159 ipc_callid_t callid; 159 160 /* accept the phone */160 161 /* Accept the phone */ 161 162 callid = async_get_call(&call); 162 int mountee_phone = (int) IPC_GET_ARG1(call);163 int mountee_phone = (int) IPC_GET_ARG1(call); 163 164 if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) || 164 mountee_phone < 0) {165 (mountee_phone < 0)) { 165 166 ipc_answer_0(callid, EINVAL); 166 167 ipc_answer_0(rid, EINVAL); 167 168 return; 168 169 } 169 ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */ 170 171 res = async_data_write_receive(&callid, NULL); 172 if (!res) { 173 ipc_hangup(mountee_phone); 174 ipc_answer_0(callid, EINVAL); 175 ipc_answer_0(rid, EINVAL); 176 return; 177 } 178 170 171 /* Acknowledge the mountee_phone */ 172 ipc_answer_0(callid, EOK); 173 179 174 fs_node_t *fn; 180 175 res = ops->node_get(&fn, mp_dev_handle, mp_fs_index); 181 if ( res != EOK || !fn) {176 if ((res != EOK) || (!fn)) { 182 177 ipc_hangup(mountee_phone); 183 ipc_answer_0(callid,combine_rc(res, ENOENT));178 async_data_void(combine_rc(res, ENOENT)); 184 179 ipc_answer_0(rid, combine_rc(res, ENOENT)); 185 180 return; 186 181 } 187 182 188 183 if (fn->mp_data.mp_active) { 189 184 ipc_hangup(mountee_phone); 190 185 (void) ops->node_put(fn); 191 ipc_answer_0(callid,EBUSY);186 async_data_void(EBUSY); 192 187 ipc_answer_0(rid, EBUSY); 193 188 return; 194 189 } 195 190 196 191 rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); 197 192 if (rc != EOK) { 198 193 ipc_hangup(mountee_phone); 199 194 (void) ops->node_put(fn); 200 ipc_answer_0(callid,rc);195 async_data_void(rc); 201 196 ipc_answer_0(rid, rc); 202 197 return; … … 204 199 205 200 ipc_call_t answer; 206 aid_t msg = async_send_1(mountee_phone, VFS_OUT_MOUNTED, mr_dev_handle,201 rc = async_data_forward_1_1(mountee_phone, VFS_OUT_MOUNTED, mr_dev_handle, 207 202 &answer); 208 ipc_forward_fast(callid, mountee_phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);209 async_wait_for(msg, &rc);210 203 211 204 if (rc == EOK) { … … 215 208 fn->mp_data.phone = mountee_phone; 216 209 } 210 217 211 /* 218 212 * Do not release the FS node so that it stays in memory. … … 220 214 ipc_answer_3(rid, rc, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), 221 215 IPC_GET_ARG3(answer)); 216 } 217 218 void libfs_unmount(libfs_ops_t *ops, ipc_callid_t rid, ipc_call_t *request) 219 { 220 dev_handle_t mp_dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 221 fs_index_t mp_fs_index = (fs_index_t) IPC_GET_ARG2(*request); 222 fs_node_t *fn; 223 int res; 224 225 res = ops->node_get(&fn, mp_dev_handle, mp_fs_index); 226 if ((res != EOK) || (!fn)) { 227 ipc_answer_0(rid, combine_rc(res, ENOENT)); 228 return; 229 } 230 231 /* 232 * We are clearly expecting to find the mount point active. 233 */ 234 if (!fn->mp_data.mp_active) { 235 (void) ops->node_put(fn); 236 ipc_answer_0(rid, EINVAL); 237 return; 238 } 239 240 /* 241 * Tell the mounted file system to unmount. 242 */ 243 res = async_req_1_0(fn->mp_data.phone, VFS_OUT_UNMOUNTED, 244 fn->mp_data.dev_handle); 245 246 /* 247 * If everything went well, perform the clean-up on our side. 248 */ 249 if (res == EOK) { 250 ipc_hangup(fn->mp_data.phone); 251 fn->mp_data.mp_active = false; 252 fn->mp_data.fs_handle = 0; 253 fn->mp_data.dev_handle = 0; 254 fn->mp_data.phone = 0; 255 /* Drop the reference created in libfs_mount(). */ 256 (void) ops->node_put(fn); 257 } 258 259 (void) ops->node_put(fn); 260 ipc_answer_0(rid, res); 222 261 } 223 262 … … 238 277 ipc_call_t *request) 239 278 { 240 unsigned first = IPC_GET_ARG1(*request);241 unsigned last = IPC_GET_ARG2(*request);242 unsigned next = first;279 unsigned int first = IPC_GET_ARG1(*request); 280 unsigned int last = IPC_GET_ARG2(*request); 281 unsigned int next = first; 243 282 dev_handle_t dev_handle = IPC_GET_ARG3(*request); 244 283 int lflag = IPC_GET_ARG4(*request); 245 fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */284 fs_index_t index = IPC_GET_ARG5(*request); 246 285 char component[NAME_MAX + 1]; 247 286 int len; 248 287 int rc; 249 288 250 289 if (last < next) 251 290 last += PLB_SIZE; 252 291 253 292 fs_node_t *par = NULL; 254 293 fs_node_t *cur = NULL; 255 294 fs_node_t *tmp = NULL; 256 295 257 296 rc = ops->root_get(&cur, dev_handle); 258 297 on_error(rc, goto out_with_answer); 259 298 260 299 if (cur->mp_data.mp_active) { 261 300 ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP, … … 265 304 return; 266 305 } 267 306 307 /* Eat slash */ 268 308 if (ops->plb_get_char(next) == '/') 269 next++; /* eat slash */309 next++; 270 310 271 311 while (next <= last) { 272 312 bool has_children; 273 313 274 314 rc = ops->has_children(&has_children, cur); 275 315 on_error(rc, goto out_with_answer); 276 316 if (!has_children) 277 317 break; 278 279 /* collect the component */318 319 /* Collect the component */ 280 320 len = 0; 281 while ((next <= last) && 321 while ((next <= last) && (ops->plb_get_char(next) != '/')) { 282 322 if (len + 1 == NAME_MAX) { 283 /* component length overflow */323 /* Component length overflow */ 284 324 ipc_answer_0(rid, ENAMETOOLONG); 285 325 goto out; 286 326 } 287 327 component[len++] = ops->plb_get_char(next); 288 next++; /* process next character */ 328 /* Process next character */ 329 next++; 289 330 } 290 331 291 332 assert(len); 292 333 component[len] = '\0'; 293 next++; /* eat slash */ 294 295 /* match the component */ 334 /* Eat slash */ 335 next++; 336 337 /* Match the component */ 296 338 rc = ops->match(&tmp, cur, component); 297 339 on_error(rc, goto out_with_answer); 298 299 if (tmp && tmp->mp_data.mp_active) { 340 341 /* 342 * If the matching component is a mount point, there are two 343 * legitimate semantics of the lookup operation. The first is 344 * the commonly used one in which the lookup crosses each mount 345 * point into the mounted file system. The second semantics is 346 * used mostly during unmount() and differs from the first one 347 * only in that the last mount point in the looked up path, 348 * which is also its last component, is not crossed. 349 */ 350 351 if ((tmp) && (tmp->mp_data.mp_active) && 352 (!(lflag & L_MP) || (next <= last))) { 300 353 if (next > last) 301 354 next = last = first; 302 355 else 303 356 next--; 304 357 305 358 ipc_forward_slow(rid, tmp->mp_data.phone, 306 359 VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle, … … 312 365 return; 313 366 } 314 315 /* handle miss: match amongst siblings */367 368 /* Handle miss: match amongst siblings */ 316 369 if (!tmp) { 317 370 if (next <= last) { 318 /* there are unprocessed components */371 /* There are unprocessed components */ 319 372 ipc_answer_0(rid, ENOENT); 320 373 goto out; 321 374 } 322 /* miss in the last component */ 323 if (lflag & (L_CREATE | L_LINK)) { 324 /* request to create a new link */ 375 376 /* Miss in the last component */ 377 if (lflag & (L_CREATE | L_LINK)) { 378 /* Request to create a new link */ 325 379 if (!ops->is_directory(cur)) { 326 380 ipc_answer_0(rid, ENOTDIR); 327 381 goto out; 328 382 } 383 329 384 fs_node_t *fn; 330 385 if (lflag & L_CREATE) … … 335 390 index); 336 391 on_error(rc, goto out_with_answer); 392 337 393 if (fn) { 338 394 rc = ops->link(cur, fn, component); … … 349 405 (void) ops->node_put(fn); 350 406 } 351 } else {407 } else 352 408 ipc_answer_0(rid, ENOSPC); 353 }409 354 410 goto out; 355 } 411 } 412 356 413 ipc_answer_0(rid, ENOENT); 357 414 goto out; 358 415 } 359 416 360 417 if (par) { 361 418 rc = ops->node_put(par); 362 419 on_error(rc, goto out_with_answer); 363 420 } 364 365 /* descend one level */421 422 /* Descend one level */ 366 423 par = cur; 367 424 cur = tmp; 368 425 tmp = NULL; 369 426 } 370 371 /* handle miss: excessive components */427 428 /* Handle miss: excessive components */ 372 429 if (next <= last) { 373 430 bool has_children; 374 375 431 rc = ops->has_children(&has_children, cur); 376 432 on_error(rc, goto out_with_answer); 433 377 434 if (has_children) 378 435 goto skip_miss; 379 436 380 437 if (lflag & (L_CREATE | L_LINK)) { 381 438 if (!ops->is_directory(cur)) { … … 383 440 goto out; 384 441 } 385 386 /* collect next component */442 443 /* Collect next component */ 387 444 len = 0; 388 445 while (next <= last) { 389 446 if (ops->plb_get_char(next) == '/') { 390 /* more than one component */447 /* More than one component */ 391 448 ipc_answer_0(rid, ENOENT); 392 449 goto out; 393 450 } 451 394 452 if (len + 1 == NAME_MAX) { 395 /* component length overflow */453 /* Component length overflow */ 396 454 ipc_answer_0(rid, ENAMETOOLONG); 397 455 goto out; 398 456 } 457 399 458 component[len++] = ops->plb_get_char(next); 400 next++; /* process next character */ 459 /* Process next character */ 460 next++; 401 461 } 462 402 463 assert(len); 403 464 component[len] = '\0'; 404 465 405 466 fs_node_t *fn; 406 467 if (lflag & L_CREATE) … … 409 470 rc = ops->node_get(&fn, dev_handle, index); 410 471 on_error(rc, goto out_with_answer); 472 411 473 if (fn) { 412 474 rc = ops->link(cur, fn, component); … … 423 485 (void) ops->node_put(fn); 424 486 } 425 } else {487 } else 426 488 ipc_answer_0(rid, ENOSPC); 427 }489 428 490 goto out; 429 491 } 492 430 493 ipc_answer_0(rid, ENOENT); 431 494 goto out; 432 495 } 496 433 497 skip_miss: 434 435 /* handle hit */498 499 /* Handle hit */ 436 500 if (lflag & L_UNLINK) { 437 unsigned old_lnkcnt = ops->lnkcnt_get(cur);501 unsigned int old_lnkcnt = ops->lnkcnt_get(cur); 438 502 rc = ops->unlink(par, cur, component); 439 ipc_answer_5(rid, (ipcarg_t) rc, fs_handle, dev_handle,503 ipc_answer_5(rid, (ipcarg_t) rc, fs_handle, dev_handle, 440 504 ops->index_get(cur), ops->size_get(cur), old_lnkcnt); 441 505 goto out; 442 506 } 507 443 508 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 444 509 (lflag & L_LINK)) { … … 446 511 goto out; 447 512 } 513 448 514 if ((lflag & L_FILE) && (ops->is_directory(cur))) { 449 515 ipc_answer_0(rid, EISDIR); 450 516 goto out; 451 517 } 518 452 519 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { 453 520 ipc_answer_0(rid, ENOTDIR); … … 455 522 } 456 523 524 if ((lflag & L_ROOT) && par) { 525 ipc_answer_0(rid, EINVAL); 526 goto out; 527 } 528 457 529 out_with_answer: 530 458 531 if (rc == EOK) { 459 ipc_answer_5(rid, EOK, fs_handle, dev_handle, 532 if (lflag & L_OPEN) 533 rc = ops->node_open(cur); 534 535 ipc_answer_5(rid, rc, fs_handle, dev_handle, 460 536 ops->index_get(cur), ops->size_get(cur), 461 537 ops->lnkcnt_get(cur)); 462 } else {538 } else 463 539 ipc_answer_0(rid, rc); 464 } 465 540 466 541 out: 542 467 543 if (par) 468 544 (void) ops->node_put(par); 545 469 546 if (cur) 470 547 (void) ops->node_put(cur); 548 471 549 if (tmp) 472 550 (void) ops->node_put(tmp); … … 478 556 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 479 557 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 558 480 559 fs_node_t *fn; 481 int rc; 482 483 rc = ops->node_get(&fn, dev_handle, index); 560 int rc = ops->node_get(&fn, dev_handle, index); 484 561 on_error(rc, answer_and_return(rid, rc)); 485 562 486 563 ipc_callid_t callid; 487 564 size_t size; 488 if (!async_data_read_receive(&callid, &size) || 489 size != sizeof(struct stat)) { 565 if ((!async_data_read_receive(&callid, &size)) || 566 (size != sizeof(struct stat))) { 567 ops->node_put(fn); 490 568 ipc_answer_0(callid, EINVAL); 491 569 ipc_answer_0(rid, EINVAL); 492 570 return; 493 571 } 494 572 495 573 struct stat stat; 496 574 memset(&stat, 0, sizeof(struct stat)); … … 499 577 stat.dev_handle = dev_handle; 500 578 stat.index = index; 501 stat.lnkcnt = ops->lnkcnt_get(fn); 579 stat.lnkcnt = ops->lnkcnt_get(fn); 502 580 stat.is_file = ops->is_file(fn); 581 stat.is_directory = ops->is_directory(fn); 503 582 stat.size = ops->size_get(fn); 504 583 stat.device = ops->device_get(fn); 584 585 ops->node_put(fn); 586 505 587 async_data_read_finalize(callid, &stat, sizeof(struct stat)); 506 588 ipc_answer_0(rid, EOK); … … 509 591 /** Open VFS triplet. 510 592 * 511 * @param ops 512 * 513 * @param rid 514 * @param request 593 * @param ops libfs operations structure with function pointers to 594 * file system implementation 595 * @param rid Request ID of the VFS_OUT_OPEN_NODE request. 596 * @param request VFS_OUT_OPEN_NODE request data itself. 515 597 * 516 598 */ … … 531 613 } 532 614 533 ipc_answer_3(rid, EOK, ops->size_get(fn), ops->lnkcnt_get(fn), 615 rc = ops->node_open(fn); 616 ipc_answer_3(rid, rc, ops->size_get(fn), ops->lnkcnt_get(fn), 534 617 (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0)); 535 618
Note:
See TracChangeset
for help on using the changeset viewer.