Changes in uspace/lib/libfs/libfs.c [0143f72:1313ee9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libfs/libfs.c
r0143f72 r1313ee9 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.35 */ 36 37 #include "libfs.h" 34 * Glue code which is common to all FS implementations. 35 */ 36 37 #include "libfs.h" 38 38 #include "../../srv/vfs/vfs.h" 39 39 #include <errno.h> … … 46 46 #include <sys/stat.h> 47 47 48 #define on_error(rc, action) \ 49 do { \ 50 if ((rc) != EOK) \ 51 action; \ 52 } while (0) 53 54 #define combine_rc(rc1, rc2) \ 55 ((rc1) == EOK ? (rc2) : (rc1)) 56 57 #define answer_and_return(rid, rc) \ 58 do { \ 59 ipc_answer_0((rid), (rc)); \ 60 return; \ 61 } while (0) 62 48 63 /** Register file system server. 49 64 * … … 52 67 * code. 53 68 * 54 * @param vfs_phone Open phone for communication with VFS. 55 * @param reg File system registration structure. It will be 56 * initialized by this function. 57 * @param info VFS info structure supplied by the file system 58 * implementation. 59 * @param conn Connection fibril for handling all calls originating in 60 * VFS. 61 * 62 * @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 * 63 79 */ 64 80 int fs_register(int vfs_phone, fs_reg_t *reg, vfs_info_t *info, … … 72 88 ipc_call_t answer; 73 89 aid_t req = async_send_0(vfs_phone, VFS_IN_REGISTER, &answer); 74 90 75 91 /* 76 92 * Send our VFS info structure to VFS. 77 93 */ 78 int rc = ipc_data_write_start(vfs_phone, info, sizeof(*info));94 int rc = async_data_write_start(vfs_phone, info, sizeof(*info)); 79 95 if (rc != EOK) { 80 96 async_wait_for(req, NULL); 81 97 return rc; 82 98 } 83 99 84 100 /* 85 101 * Ask VFS for callback connection. 86 102 */ 87 103 ipc_connect_to_me(vfs_phone, 0, 0, 0, ®->vfs_phonehash); 88 104 89 105 /* 90 106 * Allocate piece of address space for PLB. … … 95 111 return ENOMEM; 96 112 } 97 113 98 114 /* 99 115 * Request sharing the Path Lookup Buffer with VFS. 100 116 */ 101 rc = ipc_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE);117 rc = async_share_in_start_0_0(vfs_phone, reg->plb_ro, PLB_SIZE); 102 118 if (rc) { 103 119 async_wait_for(req, NULL); … … 121 137 */ 122 138 async_set_client_connection(conn); 123 139 124 140 return IPC_GET_RETVAL(answer); 125 141 } … … 139 155 int res; 140 156 ipcarg_t rc; 141 157 142 158 ipc_call_t call; 143 159 ipc_callid_t callid; 144 145 /* accept the phone */160 161 /* Accept the phone */ 146 162 callid = async_get_call(&call); 147 163 int mountee_phone = (int)IPC_GET_ARG1(call); 148 164 if ((IPC_GET_METHOD(call) != IPC_M_CONNECTION_CLONE) || 149 mountee_phone < 0) {165 (mountee_phone < 0)) { 150 166 ipc_answer_0(callid, EINVAL); 151 167 ipc_answer_0(rid, EINVAL); 152 168 return; 153 169 } 154 ipc_answer_0(callid, EOK); /* acknowledge the mountee_phone */ 155 156 res = ipc_data_write_receive(&callid, NULL); 170 171 /* Acknowledge the mountee_phone */ 172 ipc_answer_0(callid, EOK); 173 174 res = async_data_write_receive(&callid, NULL); 157 175 if (!res) { 158 176 ipc_hangup(mountee_phone); … … 161 179 return; 162 180 } 163 164 fs_node_t *fn = ops->node_get(mp_dev_handle, mp_fs_index); 165 if (!fn) { 181 182 fs_node_t *fn; 183 res = ops->node_get(&fn, mp_dev_handle, mp_fs_index); 184 if ((res != EOK) || (!fn)) { 166 185 ipc_hangup(mountee_phone); 167 ipc_answer_0(callid, ENOENT);168 ipc_answer_0(rid, ENOENT);169 return; 170 } 171 186 ipc_answer_0(callid, combine_rc(res, ENOENT)); 187 ipc_answer_0(rid, combine_rc(res, ENOENT)); 188 return; 189 } 190 172 191 if (fn->mp_data.mp_active) { 173 192 ipc_hangup(mountee_phone); 174 ops->node_put(fn);193 (void) ops->node_put(fn); 175 194 ipc_answer_0(callid, EBUSY); 176 195 ipc_answer_0(rid, EBUSY); 177 196 return; 178 197 } 179 198 180 199 rc = async_req_0_0(mountee_phone, IPC_M_CONNECT_ME); 181 if (rc != 0) {200 if (rc != EOK) { 182 201 ipc_hangup(mountee_phone); 183 ops->node_put(fn);202 (void) ops->node_put(fn); 184 203 ipc_answer_0(callid, rc); 185 204 ipc_answer_0(rid, rc); … … 199 218 fn->mp_data.phone = mountee_phone; 200 219 } 220 201 221 /* 202 222 * Do not release the FS node so that it stays in memory. … … 222 242 ipc_call_t *request) 223 243 { 224 unsigned first = IPC_GET_ARG1(*request);225 unsigned last = IPC_GET_ARG2(*request);226 unsigned next = first;244 unsigned int first = IPC_GET_ARG1(*request); 245 unsigned int last = IPC_GET_ARG2(*request); 246 unsigned int next = first; 227 247 dev_handle_t dev_handle = IPC_GET_ARG3(*request); 228 248 int lflag = IPC_GET_ARG4(*request); 229 fs_index_t index = IPC_GET_ARG5(*request); /* when L_LINK specified */249 fs_index_t index = IPC_GET_ARG5(*request); 230 250 char component[NAME_MAX + 1]; 231 251 int len; 232 252 int rc; 253 233 254 if (last < next) 234 255 last += PLB_SIZE; 235 256 236 257 fs_node_t *par = NULL; 237 fs_node_t *cur = ops->root_get(dev_handle);258 fs_node_t *cur = NULL; 238 259 fs_node_t *tmp = NULL; 239 260 261 rc = ops->root_get(&cur, dev_handle); 262 on_error(rc, goto out_with_answer); 263 240 264 if (cur->mp_data.mp_active) { 241 265 ipc_forward_slow(rid, cur->mp_data.phone, VFS_OUT_LOOKUP, 242 266 next, last, cur->mp_data.dev_handle, lflag, index, 243 267 IPC_FF_ROUTE_FROM_ME); 244 ops->node_put(cur); 245 return; 246 } 247 268 (void) ops->node_put(cur); 269 return; 270 } 271 272 /* Eat slash */ 248 273 if (ops->plb_get_char(next) == '/') 249 next++; /* eat slash */ 250 251 while (next <= last && ops->has_children(cur)) { 252 /* collect the component */ 274 next++; 275 276 while (next <= last) { 277 bool has_children; 278 279 rc = ops->has_children(&has_children, cur); 280 on_error(rc, goto out_with_answer); 281 if (!has_children) 282 break; 283 284 /* Collect the component */ 253 285 len = 0; 254 while ((next <= last) && 286 while ((next <= last) && (ops->plb_get_char(next) != '/')) { 255 287 if (len + 1 == NAME_MAX) { 256 /* component length overflow */288 /* Component length overflow */ 257 289 ipc_answer_0(rid, ENAMETOOLONG); 258 290 goto out; 259 291 } 260 292 component[len++] = ops->plb_get_char(next); 261 next++; /* process next character */ 293 /* Process next character */ 294 next++; 262 295 } 263 296 264 297 assert(len); 265 298 component[len] = '\0'; 266 next++; /* eat slash */ 267 268 /* match the component */ 269 tmp = ops->match(cur, component); 270 if (tmp && tmp->mp_data.mp_active) { 299 /* Eat slash */ 300 next++; 301 302 /* Match the component */ 303 rc = ops->match(&tmp, cur, component); 304 on_error(rc, goto out_with_answer); 305 306 if ((tmp) && (tmp->mp_data.mp_active)) { 271 307 if (next > last) 272 308 next = last = first; 273 309 else 274 310 next--; 275 311 276 312 ipc_forward_slow(rid, tmp->mp_data.phone, 277 313 VFS_OUT_LOOKUP, next, last, tmp->mp_data.dev_handle, 278 314 lflag, index, IPC_FF_ROUTE_FROM_ME); 279 ops->node_put(cur);280 ops->node_put(tmp);315 (void) ops->node_put(cur); 316 (void) ops->node_put(tmp); 281 317 if (par) 282 ops->node_put(par);318 (void) ops->node_put(par); 283 319 return; 284 320 } 285 286 /* handle miss: match amongst siblings */321 322 /* Handle miss: match amongst siblings */ 287 323 if (!tmp) { 288 324 if (next <= last) { 289 /* there are unprocessed components */325 /* There are unprocessed components */ 290 326 ipc_answer_0(rid, ENOENT); 291 327 goto out; 292 328 } 293 /* miss in the last component */ 294 if (lflag & (L_CREATE | L_LINK)) { 295 /* request to create a new link */ 329 330 /* Miss in the last component */ 331 if (lflag & (L_CREATE | L_LINK)) { 332 /* Request to create a new link */ 296 333 if (!ops->is_directory(cur)) { 297 334 ipc_answer_0(rid, ENOTDIR); 298 335 goto out; 299 336 } 337 300 338 fs_node_t *fn; 301 339 if (lflag & L_CREATE) 302 fn = ops->create(dev_handle, lflag); 340 rc = ops->create(&fn, dev_handle, 341 lflag); 303 342 else 304 fn = ops->node_get(dev_handle,343 rc = ops->node_get(&fn, dev_handle, 305 344 index); 345 on_error(rc, goto out_with_answer); 346 306 347 if (fn) { 307 int rc;308 309 348 rc = ops->link(cur, fn, component); 310 349 if (rc != EOK) { 311 if (lflag & L_CREATE) { 312 (void)ops->destroy(fn); 313 } 350 if (lflag & L_CREATE) 351 (void) ops->destroy(fn); 314 352 ipc_answer_0(rid, rc); 315 353 } else { … … 319 357 ops->size_get(fn), 320 358 ops->lnkcnt_get(fn)); 321 ops->node_put(fn);359 (void) ops->node_put(fn); 322 360 } 323 } else {361 } else 324 362 ipc_answer_0(rid, ENOSPC); 325 }363 326 364 goto out; 327 } 365 } 366 328 367 ipc_answer_0(rid, ENOENT); 329 368 goto out; 330 369 } 331 332 if (par) 333 ops->node_put(par); 334 335 /* descend one level */ 370 371 if (par) { 372 rc = ops->node_put(par); 373 on_error(rc, goto out_with_answer); 374 } 375 376 /* Descend one level */ 336 377 par = cur; 337 378 cur = tmp; 338 379 tmp = NULL; 339 380 } 340 341 /* handle miss: excessive components */ 342 if (next <= last && !ops->has_children(cur)) { 381 382 /* Handle miss: excessive components */ 383 if (next <= last) { 384 bool has_children; 385 rc = ops->has_children(&has_children, cur); 386 on_error(rc, goto out_with_answer); 387 388 if (has_children) 389 goto skip_miss; 390 343 391 if (lflag & (L_CREATE | L_LINK)) { 344 392 if (!ops->is_directory(cur)) { … … 346 394 goto out; 347 395 } 348 349 /* collect next component */396 397 /* Collect next component */ 350 398 len = 0; 351 399 while (next <= last) { 352 400 if (ops->plb_get_char(next) == '/') { 353 /* more than one component */401 /* More than one component */ 354 402 ipc_answer_0(rid, ENOENT); 355 403 goto out; 356 404 } 405 357 406 if (len + 1 == NAME_MAX) { 358 /* component length overflow */407 /* Component length overflow */ 359 408 ipc_answer_0(rid, ENAMETOOLONG); 360 409 goto out; 361 410 } 411 362 412 component[len++] = ops->plb_get_char(next); 363 next++; /* process next character */ 413 /* Process next character */ 414 next++; 364 415 } 416 365 417 assert(len); 366 418 component[len] = '\0'; 367 419 368 420 fs_node_t *fn; 369 421 if (lflag & L_CREATE) 370 fn = ops->create(dev_handle, lflag);422 rc = ops->create(&fn, dev_handle, lflag); 371 423 else 372 fn = ops->node_get(dev_handle, index); 424 rc = ops->node_get(&fn, dev_handle, index); 425 on_error(rc, goto out_with_answer); 426 373 427 if (fn) { 374 int rc;375 376 428 rc = ops->link(cur, fn, component); 377 429 if (rc != EOK) { 378 430 if (lflag & L_CREATE) 379 (void) ops->destroy(fn);431 (void) ops->destroy(fn); 380 432 ipc_answer_0(rid, rc); 381 433 } else { … … 385 437 ops->size_get(fn), 386 438 ops->lnkcnt_get(fn)); 387 ops->node_put(fn);439 (void) ops->node_put(fn); 388 440 } 389 } else {441 } else 390 442 ipc_answer_0(rid, ENOSPC); 391 }443 392 444 goto out; 393 445 } 446 394 447 ipc_answer_0(rid, ENOENT); 395 448 goto out; 396 449 } 397 398 /* handle hit */ 450 451 skip_miss: 452 453 /* Handle hit */ 399 454 if (lflag & L_UNLINK) { 400 unsigned old_lnkcnt = ops->lnkcnt_get(cur);401 int res= ops->unlink(par, cur, component);402 ipc_answer_5(rid, (ipcarg_t) res, fs_handle, dev_handle,455 unsigned int old_lnkcnt = ops->lnkcnt_get(cur); 456 rc = ops->unlink(par, cur, component); 457 ipc_answer_5(rid, (ipcarg_t) rc, fs_handle, dev_handle, 403 458 ops->index_get(cur), ops->size_get(cur), old_lnkcnt); 404 459 goto out; 405 460 } 461 406 462 if (((lflag & (L_CREATE | L_EXCLUSIVE)) == (L_CREATE | L_EXCLUSIVE)) || 407 463 (lflag & L_LINK)) { … … 409 465 goto out; 410 466 } 467 411 468 if ((lflag & L_FILE) && (ops->is_directory(cur))) { 412 469 ipc_answer_0(rid, EISDIR); 413 470 goto out; 414 471 } 472 415 473 if ((lflag & L_DIRECTORY) && (ops->is_file(cur))) { 416 474 ipc_answer_0(rid, ENOTDIR); 417 475 goto out; 418 476 } 419 420 ipc_answer_5(rid, EOK, fs_handle, dev_handle, ops->index_get(cur), 421 ops->size_get(cur), ops->lnkcnt_get(cur)); 422 477 478 out_with_answer: 479 480 if (rc == EOK) { 481 if (lflag & L_OPEN) 482 rc = ops->node_open(cur); 483 484 ipc_answer_5(rid, rc, fs_handle, dev_handle, 485 ops->index_get(cur), ops->size_get(cur), 486 ops->lnkcnt_get(cur)); 487 } else 488 ipc_answer_0(rid, rc); 489 423 490 out: 491 424 492 if (par) 425 ops->node_put(par); 493 (void) ops->node_put(par); 494 426 495 if (cur) 427 ops->node_put(cur); 496 (void) ops->node_put(cur); 497 428 498 if (tmp) 429 ops->node_put(tmp);499 (void) ops->node_put(tmp); 430 500 } 431 501 … … 435 505 dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request); 436 506 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 437 fs_node_t *fn = ops->node_get(dev_handle, index); 438 507 508 fs_node_t *fn; 509 int rc = ops->node_get(&fn, dev_handle, index); 510 on_error(rc, answer_and_return(rid, rc)); 511 439 512 ipc_callid_t callid; 440 513 size_t size; 441 if (!ipc_data_read_receive(&callid, &size) || 442 size != sizeof(struct stat)) { 514 if ((!async_data_read_receive(&callid, &size)) || 515 (size != sizeof(struct stat))) { 516 ops->node_put(fn); 443 517 ipc_answer_0(callid, EINVAL); 444 518 ipc_answer_0(rid, EINVAL); 445 519 return; 446 520 } 447 521 448 522 struct stat stat; 449 523 memset(&stat, 0, sizeof(struct stat)); … … 452 526 stat.dev_handle = dev_handle; 453 527 stat.index = index; 454 stat.lnkcnt = ops->lnkcnt_get(fn); 528 stat.lnkcnt = ops->lnkcnt_get(fn); 455 529 stat.is_file = ops->is_file(fn); 530 stat.is_directory = ops->is_directory(fn); 456 531 stat.size = ops->size_get(fn); 457 458 ipc_data_read_finalize(callid, &stat, sizeof(struct stat)); 532 stat.device = ops->device_get(fn); 533 534 ops->node_put(fn); 535 536 async_data_read_finalize(callid, &stat, sizeof(struct stat)); 459 537 ipc_answer_0(rid, EOK); 460 538 } … … 462 540 /** Open VFS triplet. 463 541 * 464 * @param ops 465 * 466 * @param rid 467 * @param request 542 * @param ops libfs operations structure with function pointers to 543 * file system implementation 544 * @param rid Request ID of the VFS_OUT_OPEN_NODE request. 545 * @param request VFS_OUT_OPEN_NODE request data itself. 468 546 * 469 547 */ … … 473 551 dev_handle_t dev_handle = IPC_GET_ARG1(*request); 474 552 fs_index_t index = IPC_GET_ARG2(*request); 475 476 fs_node_t *node = ops->node_get(dev_handle, index); 477 478 if (node == NULL) { 553 fs_node_t *fn; 554 int rc; 555 556 rc = ops->node_get(&fn, dev_handle, index); 557 on_error(rc, answer_and_return(rid, rc)); 558 559 if (fn == NULL) { 479 560 ipc_answer_0(rid, ENOENT); 480 561 return; 481 562 } 482 563 483 ipc_answer_5(rid, EOK, fs_handle, dev_handle, index, 484 ops->size_get(node), ops->lnkcnt_get(node)); 485 486 ops->node_put(node); 564 rc = ops->node_open(fn); 565 ipc_answer_3(rid, rc, ops->size_get(fn), ops->lnkcnt_get(fn), 566 (ops->is_file(fn) ? L_FILE : 0) | (ops->is_directory(fn) ? L_DIRECTORY : 0)); 567 568 (void) ops->node_put(fn); 487 569 } 488 570
Note:
See TracChangeset
for help on using the changeset viewer.