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