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