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