1 /* 2 * Copyright 2010, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include <new> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include <errno.h> 15 #include <dirent.h> 16 17 #include <fs_info.h> 18 #include <fs_interface.h> 19 20 #include <debug.h> 21 #include <KernelExport.h> 22 23 #include <io_requests.h> 24 25 static const char *kLogFilePrefix = "/var/log/log_overlay"; 26 27 28 #define DO_LOG(format, args...) \ 29 { \ 30 char _printBuffer[256]; \ 31 int _printSize = snprintf(_printBuffer, sizeof(_printBuffer), \ 32 "%llu %ld %p: " format, system_time(), find_thread(NULL), \ 33 ((fs_vnode *)vnode->private_node)->private_node, args); \ 34 if ((unsigned int)_printSize > sizeof(_printBuffer)) { \ 35 _printBuffer[sizeof(_printBuffer) - 1] = '\n'; \ 36 _printSize = sizeof(_printBuffer); \ 37 } \ 38 write((int)volume->private_volume, _printBuffer, _printSize); \ 39 } 40 41 #define OVERLAY_CALL(op, params...) \ 42 status_t result = B_UNSUPPORTED; \ 43 fs_vnode *superVnode = (fs_vnode *)vnode->private_node; \ 44 if (superVnode->ops->op != NULL) \ 45 result = superVnode->ops->op(volume->super_volume, superVnode, params); \ 46 47 48 static status_t 49 overlay_put_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter) 50 { 51 DO_LOG("put_vnode reenter: %s\n", reenter ? "yes" : "no"); 52 53 status_t result = B_UNSUPPORTED; 54 fs_vnode *superVnode = (fs_vnode *)vnode->private_node; 55 if (superVnode->ops->put_vnode != NULL) { 56 result = superVnode->ops->put_vnode(volume->super_volume, superVnode, 57 reenter); 58 } 59 60 DO_LOG("put_vnode result: 0x%08lx\n", result); 61 delete (fs_vnode *)vnode->private_node; 62 return result; 63 } 64 65 66 static status_t 67 overlay_remove_vnode(fs_volume *volume, fs_vnode *vnode, bool reenter) 68 { 69 DO_LOG("remove_vnode reenter: %s\n", reenter ? "yes" : "no"); 70 71 status_t result = B_UNSUPPORTED; 72 fs_vnode *superVnode = (fs_vnode *)vnode->private_node; 73 if (superVnode->ops->remove_vnode != NULL) { 74 result = superVnode->ops->remove_vnode(volume->super_volume, superVnode, 75 reenter); 76 } 77 78 DO_LOG("remove_vnode result: 0x%08lx\n", result); 79 delete (fs_vnode *)vnode->private_node; 80 return result; 81 } 82 83 84 static status_t 85 overlay_get_super_vnode(fs_volume *volume, fs_vnode *vnode, 86 fs_volume *superVolume, fs_vnode *_superVnode) 87 { 88 if (volume == superVolume) { 89 *_superVnode = *vnode; 90 return B_OK; 91 } 92 93 fs_vnode *superVnode = (fs_vnode *)vnode->private_node; 94 if (superVnode->ops->get_super_vnode != NULL) { 95 return superVnode->ops->get_super_vnode(volume->super_volume, 96 superVnode, superVolume, _superVnode); 97 } 98 99 *_superVnode = *superVnode; 100 return B_OK; 101 } 102 103 104 static status_t 105 overlay_lookup(fs_volume *volume, fs_vnode *vnode, const char *name, ino_t *id) 106 { 107 DO_LOG("lookup name: \"%s\"\n", name); 108 OVERLAY_CALL(lookup, name, id) 109 DO_LOG("lookup result: 0x%08lx; id: %llu\n", result, *id); 110 return result; 111 } 112 113 114 static status_t 115 overlay_get_vnode_name(fs_volume *volume, fs_vnode *vnode, char *buffer, 116 size_t bufferSize) 117 { 118 DO_LOG("get_vnode_name buffer: %p; buffer_size: %lu\n", buffer, bufferSize); 119 OVERLAY_CALL(get_vnode_name, buffer, bufferSize) 120 DO_LOG("get_vnode_name result: 0x%08lx; buffer: \"%s\"\n", result, 121 result == B_OK ? buffer : "unsafe"); 122 return result; 123 } 124 125 126 static bool 127 overlay_can_page(fs_volume *volume, fs_vnode *vnode, void *cookie) 128 { 129 DO_LOG("can_page cookie: %p\n", cookie); 130 bool result = false; 131 fs_vnode *superVnode = (fs_vnode *)vnode->private_node; 132 if (superVnode->ops->can_page != NULL) { 133 result = superVnode->ops->can_page(volume->super_volume, superVnode, 134 cookie); 135 } 136 137 DO_LOG("can_page result: %s\n", result ? "yes" : "no"); 138 return result; 139 } 140 141 142 static status_t 143 overlay_read_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, 144 const iovec *vecs, size_t count, size_t *numBytes) 145 { 146 DO_LOG("read_pages cookie: %p; pos: %lld; vecs: %p; count: %lu;" 147 " num_bytes: %lu\n", cookie, pos, vecs, count, *numBytes); 148 OVERLAY_CALL(read_pages, cookie, pos, vecs, count, numBytes) 149 DO_LOG("read_pages result: 0x%08lx; num_bytes: %lu\n", result, *numBytes); 150 return result; 151 } 152 153 154 static status_t 155 overlay_write_pages(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, 156 const iovec *vecs, size_t count, size_t *numBytes) 157 { 158 DO_LOG("write_pages cookie: %p; pos: %lld; vecs: %p; count: %lu;" 159 " num_bytes: %lu\n", cookie, pos, vecs, count, *numBytes); 160 OVERLAY_CALL(write_pages, cookie, pos, vecs, count, numBytes) 161 DO_LOG("write_pages result: 0x%08lx; num_bytes: %lu\n", result, *numBytes); 162 return result; 163 } 164 165 166 static status_t 167 overlay_io(fs_volume *volume, fs_vnode *vnode, void *cookie, 168 io_request *request) 169 { 170 DO_LOG("io cookie: %p; request: %p (write: %s; offset: %lld; length: %llu)" 171 "\n", cookie, request, io_request_is_write(request) ? "yes" : "no", 172 io_request_offset(request), io_request_length(request)); 173 OVERLAY_CALL(io, cookie, request) 174 DO_LOG("io result: 0x%08lx\n", result); 175 return result; 176 } 177 178 179 static status_t 180 overlay_cancel_io(fs_volume *volume, fs_vnode *vnode, void *cookie, 181 io_request *request) 182 { 183 DO_LOG("cancel_io cookie: %p; request: %p\n", cookie, request); 184 OVERLAY_CALL(cancel_io, cookie, request) 185 DO_LOG("cancel_io result: 0x%08lx\n", result); 186 return result; 187 } 188 189 190 static status_t 191 overlay_get_file_map(fs_volume *volume, fs_vnode *vnode, off_t offset, 192 size_t size, struct file_io_vec *vecs, size_t *count) 193 { 194 DO_LOG("get_file_map offset: %lld; size: %lu; vecs: %p; count: %lu\n", 195 offset, size, vecs, *count); 196 OVERLAY_CALL(get_file_map, offset, size, vecs, count) 197 DO_LOG("get_file_map result: 0x%08lx; count: %lu\n", result, *count); 198 return result; 199 } 200 201 202 static status_t 203 overlay_ioctl(fs_volume *volume, fs_vnode *vnode, void *cookie, uint32 op, 204 void *buffer, size_t length) 205 { 206 DO_LOG("ioctl cookie: %p; op: %lu; buffer: %p; size: %lu\n", cookie, op, 207 buffer, length); 208 OVERLAY_CALL(ioctl, cookie, op, buffer, length) 209 DO_LOG("ioctl result: 0x%08lx\n", result); 210 return result; 211 } 212 213 214 static status_t 215 overlay_set_flags(fs_volume *volume, fs_vnode *vnode, void *cookie, 216 int flags) 217 { 218 DO_LOG("set_flags cookie: %p; flags: %d\n", cookie, flags); 219 OVERLAY_CALL(set_flags, cookie, flags) 220 DO_LOG("set_flags result: 0x%08lx\n", result); 221 return result; 222 } 223 224 225 static status_t 226 overlay_select(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event, 227 selectsync *sync) 228 { 229 DO_LOG("select cookie: %p; event: %u; selectsync: %p\n", cookie, event, 230 sync); 231 OVERLAY_CALL(select, cookie, event, sync) 232 DO_LOG("select result: 0x%08lx\n", result); 233 return result; 234 } 235 236 237 static status_t 238 overlay_deselect(fs_volume *volume, fs_vnode *vnode, void *cookie, uint8 event, 239 selectsync *sync) 240 { 241 DO_LOG("deselect cookie: %p; event: %u; selectsync: %p\n", cookie, event, 242 sync); 243 OVERLAY_CALL(deselect, cookie, event, sync) 244 DO_LOG("deselect result: 0x%08lx\n", result); 245 return result; 246 } 247 248 249 static status_t 250 overlay_fsync(fs_volume *volume, fs_vnode *vnode) 251 { 252 DO_LOG("%s\n", "fsync"); 253 254 status_t result = B_UNSUPPORTED; 255 fs_vnode *superVnode = (fs_vnode *)vnode->private_node; 256 if (superVnode->ops->fsync != NULL) 257 result = superVnode->ops->fsync(volume->super_volume, superVnode); 258 259 DO_LOG("fsync result: 0x%08lx\n", result); 260 return result; 261 } 262 263 264 static status_t 265 overlay_read_symlink(fs_volume *volume, fs_vnode *vnode, char *buffer, 266 size_t *bufferSize) 267 { 268 DO_LOG("read_symlink buffer: %p; buffer_size: %lu\n", buffer, *bufferSize); 269 OVERLAY_CALL(read_symlink, buffer, bufferSize) 270 DO_LOG("read_symlink result: 0x%08lx; buffer_size: %lu; \"%.*s\"\n", result, 271 *bufferSize, result == B_OK ? (int)*bufferSize : 6, 272 result == B_OK ? buffer : "unsafe"); 273 return result; 274 } 275 276 277 static status_t 278 overlay_create_symlink(fs_volume *volume, fs_vnode *vnode, const char *name, 279 const char *path, int mode) 280 { 281 DO_LOG("create_symlink name: \"%s\"; path: \"%s\"; mode: %u\n", name, path, 282 mode); 283 OVERLAY_CALL(create_symlink, name, path, mode) 284 DO_LOG("create_symlink result: 0x%08lx\n", result); 285 return result; 286 } 287 288 289 static status_t 290 overlay_link(fs_volume *volume, fs_vnode *vnode, const char *name, 291 fs_vnode *target) 292 { 293 DO_LOG("link name: \"%s\"; target: %p\n", name, 294 ((fs_vnode *)target->private_node)->private_node); 295 OVERLAY_CALL(link, name, (fs_vnode *)target->private_node) 296 DO_LOG("link result: 0x%08lx\n", result); 297 return result; 298 } 299 300 301 static status_t 302 overlay_unlink(fs_volume *volume, fs_vnode *vnode, const char *name) 303 { 304 DO_LOG("unlink name: \"%s\"\n", name); 305 OVERLAY_CALL(unlink, name) 306 DO_LOG("unlink result: 0x%08lx\n", result); 307 return result; 308 } 309 310 311 static status_t 312 overlay_rename(fs_volume *volume, fs_vnode *vnode, 313 const char *fromName, fs_vnode *toDir, const char *toName) 314 { 315 DO_LOG("rename from_name: \"%s\"; to_dir: %p; to_name: \"%s\"\n", 316 fromName, ((fs_vnode *)toDir->private_node)->private_node, toName); 317 OVERLAY_CALL(rename, fromName, (fs_vnode *)toDir->private_node, toName) 318 DO_LOG("rename result: 0x%08lx\n", result); 319 return result; 320 } 321 322 323 static status_t 324 overlay_access(fs_volume *volume, fs_vnode *vnode, int mode) 325 { 326 DO_LOG("access mode: %u\n", mode); 327 OVERLAY_CALL(access, mode) 328 DO_LOG("access result: 0x%08lx\n", result); 329 return result; 330 } 331 332 333 static status_t 334 overlay_read_stat(fs_volume *volume, fs_vnode *vnode, struct stat *stat) 335 { 336 DO_LOG("read_stat stat: %p\n", stat); 337 OVERLAY_CALL(read_stat, stat) 338 if (result == B_OK) { 339 DO_LOG("read_stat result: 0x%08lx; stat(dev: %lu; ino: %llu; mode: %u;" 340 " uid: %u; gid %u; size: %llu)\n", result, stat->st_dev, 341 stat->st_ino, stat->st_mode, stat->st_uid, stat->st_gid, 342 stat->st_size); 343 } else 344 DO_LOG("read_stat result: 0x%08lx\n", result); 345 return result; 346 } 347 348 349 static status_t 350 overlay_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat, 351 uint32 statMask) 352 { 353 DO_LOG("write_stat stat: %p; mask: %lu\n", stat, statMask); 354 OVERLAY_CALL(write_stat, stat, statMask) 355 DO_LOG("write_stat result: 0x%08lx\n", result); 356 return result; 357 } 358 359 360 static status_t 361 overlay_create(fs_volume *volume, fs_vnode *vnode, const char *name, 362 int openMode, int perms, void **cookie, ino_t *newVnodeID) 363 { 364 DO_LOG("create name: \"%s\"; open_mode: %u; perms: %u\n", name, openMode, 365 perms); 366 OVERLAY_CALL(create, name, openMode, perms, cookie, newVnodeID) 367 DO_LOG("create result: 0x%08lx; cookie: %p; new_vnode_id: %llu\n", result, 368 *cookie, *newVnodeID); 369 return result; 370 } 371 372 373 static status_t 374 overlay_open(fs_volume *volume, fs_vnode *vnode, int openMode, void **cookie) 375 { 376 DO_LOG("open open_mode: %u\n", openMode); 377 OVERLAY_CALL(open, openMode, cookie) 378 DO_LOG("open result: 0x%08lx; cookie: %p\n", result, *cookie); 379 return result; 380 } 381 382 383 static status_t 384 overlay_close(fs_volume *volume, fs_vnode *vnode, void *cookie) 385 { 386 DO_LOG("close cookie %p\n", cookie); 387 OVERLAY_CALL(close, cookie) 388 DO_LOG("close result: 0x%08lx\n", result); 389 return result; 390 } 391 392 393 static status_t 394 overlay_free_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie) 395 { 396 DO_LOG("free_cookie cookie %p\n", cookie); 397 OVERLAY_CALL(free_cookie, cookie) 398 DO_LOG("free_cookie result: 0x%08lx\n", result); 399 return result; 400 } 401 402 403 static status_t 404 overlay_read(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, 405 void *buffer, size_t *length) 406 { 407 DO_LOG("read cookie: %p; pos: %lld; buffer: %p; length: %lu\n", cookie, pos, 408 buffer, *length); 409 OVERLAY_CALL(read, cookie, pos, buffer, length) 410 DO_LOG("read result: 0x%08lx; length: %lu\n", result, *length); 411 return result; 412 } 413 414 415 static status_t 416 overlay_write(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, 417 const void *buffer, size_t *length) 418 { 419 DO_LOG("write cookie: %p; pos: %lld; buffer: %p; length: %lu\n", cookie, 420 pos, buffer, *length); 421 OVERLAY_CALL(write, cookie, pos, buffer, length) 422 DO_LOG("write result: 0x%08lx; length: %lu\n", result, *length); 423 return result; 424 } 425 426 427 static status_t 428 overlay_create_dir(fs_volume *volume, fs_vnode *vnode, const char *name, 429 int perms) 430 { 431 DO_LOG("create_dir name: \"%s\"; perms: %u\n", name, perms); 432 OVERLAY_CALL(create_dir, name, perms) 433 DO_LOG("create_dir result: 0x%08lx\n", result); 434 return result; 435 } 436 437 438 static status_t 439 overlay_remove_dir(fs_volume *volume, fs_vnode *vnode, const char *name) 440 { 441 DO_LOG("remove_dir name: \"%s\"\n", name); 442 OVERLAY_CALL(remove_dir, name) 443 DO_LOG("remove_dir result: 0x%08lx\n", result); 444 return result; 445 } 446 447 448 static status_t 449 overlay_open_dir(fs_volume *volume, fs_vnode *vnode, void **cookie) 450 { 451 DO_LOG("%s\n", "open_dir"); 452 OVERLAY_CALL(open_dir, cookie) 453 DO_LOG("open_dir result: 0x%08lx; cookie: %p\n", result, *cookie); 454 return result; 455 } 456 457 458 static status_t 459 overlay_close_dir(fs_volume *volume, fs_vnode *vnode, void *cookie) 460 { 461 DO_LOG("close_dir cookie: %p\n", cookie); 462 OVERLAY_CALL(close_dir, cookie) 463 DO_LOG("close_dir result: 0x%08lx\n", result); 464 return result; 465 } 466 467 468 static status_t 469 overlay_free_dir_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie) 470 { 471 DO_LOG("free_dir_cookie cookie: %p\n", cookie); 472 OVERLAY_CALL(free_dir_cookie, cookie) 473 DO_LOG("free_dir_cookie result: 0x%08lx\n", result); 474 return result; 475 } 476 477 478 static status_t 479 overlay_read_dir(fs_volume *volume, fs_vnode *vnode, void *cookie, 480 struct dirent *buffer, size_t bufferSize, uint32 *num) 481 { 482 DO_LOG("read_dir cookie: %p; buffer: %p; buffer_size: %lu\n", cookie, 483 buffer, bufferSize); 484 OVERLAY_CALL(read_dir, cookie, buffer, bufferSize, num); 485 DO_LOG("read_dir result: 0x%08lx; num: %lu\n", result, *num); 486 return result; 487 } 488 489 490 static status_t 491 overlay_rewind_dir(fs_volume *volume, fs_vnode *vnode, void *cookie) 492 { 493 DO_LOG("rewind_dir cookie: %p\n", cookie); 494 OVERLAY_CALL(rewind_dir, cookie) 495 DO_LOG("rewind_dir result: 0x%08lx\n", result); 496 return result; 497 } 498 499 500 static status_t 501 overlay_open_attr_dir(fs_volume *volume, fs_vnode *vnode, void **cookie) 502 { 503 DO_LOG("%s\n", "open_attr_dir"); 504 OVERLAY_CALL(open_attr_dir, cookie) 505 DO_LOG("open_attr_dir result: 0x%08lx; cookie: %p\n", result, *cookie); 506 return result; 507 } 508 509 510 static status_t 511 overlay_close_attr_dir(fs_volume *volume, fs_vnode *vnode, void *cookie) 512 { 513 DO_LOG("close_attr_dir cookie: %p\n", cookie); 514 OVERLAY_CALL(close_attr_dir, cookie) 515 DO_LOG("close_attr_dir result: 0x%08lx\n", result); 516 return result; 517 } 518 519 520 static status_t 521 overlay_free_attr_dir_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie) 522 { 523 DO_LOG("free_attr_dir_cookie cookie: %p\n", cookie); 524 OVERLAY_CALL(free_attr_dir_cookie, cookie) 525 DO_LOG("free_attr_dir_cookie result: 0x%08lx\n", result); 526 return result; 527 } 528 529 530 static status_t 531 overlay_read_attr_dir(fs_volume *volume, fs_vnode *vnode, void *cookie, 532 struct dirent *buffer, size_t bufferSize, uint32 *num) 533 { 534 DO_LOG("read_attr_dir cookie: %p; buffer: %p; buffer_size: %lu\n", cookie, 535 buffer, bufferSize); 536 OVERLAY_CALL(read_attr_dir, cookie, buffer, bufferSize, num); 537 DO_LOG("read_attr_dir result: 0x%08lx; num: %lu\n", result, *num); 538 return result; 539 } 540 541 542 static status_t 543 overlay_rewind_attr_dir(fs_volume *volume, fs_vnode *vnode, void *cookie) 544 { 545 DO_LOG("rewind_attr_dir cookie: %p\n", cookie); 546 OVERLAY_CALL(rewind_attr_dir, cookie) 547 DO_LOG("rewind_attr_dir result: 0x%08lx\n", result); 548 return result; 549 } 550 551 552 static status_t 553 overlay_create_attr(fs_volume *volume, fs_vnode *vnode, const char *name, 554 uint32 type, int openMode, void **cookie) 555 { 556 DO_LOG("create_attr name: \"%s\"; type: 0x%08lx; open_mode: %u\n", name, 557 type, openMode); 558 OVERLAY_CALL(create_attr, name, type, openMode, cookie) 559 DO_LOG("create_attr result: 0x%08lx; cookie: %p\n", result, *cookie); 560 return result; 561 } 562 563 564 static status_t 565 overlay_open_attr(fs_volume *volume, fs_vnode *vnode, const char *name, 566 int openMode, void **cookie) 567 { 568 DO_LOG("open_attr name: \"%s\"; open_mode: %u\n", name, openMode); 569 OVERLAY_CALL(open_attr, name, openMode, cookie) 570 DO_LOG("open_attr result: 0x%08lx; cookie: %p\n", result, *cookie); 571 return result; 572 } 573 574 575 static status_t 576 overlay_close_attr(fs_volume *volume, fs_vnode *vnode, void *cookie) 577 { 578 DO_LOG("close_attr cookie: %p\n", cookie); 579 OVERLAY_CALL(close_attr, cookie) 580 DO_LOG("close_attr result: 0x%08lx\n", result); 581 return result; 582 } 583 584 585 static status_t 586 overlay_free_attr_cookie(fs_volume *volume, fs_vnode *vnode, void *cookie) 587 { 588 DO_LOG("free_attr_cookie cookie: %p\n", cookie); 589 OVERLAY_CALL(free_attr_cookie, cookie) 590 DO_LOG("free_attr_cookie result: 0x%08lx\n", result); 591 return result; 592 } 593 594 595 static status_t 596 overlay_read_attr(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, 597 void *buffer, size_t *length) 598 { 599 DO_LOG("read_attr cookie: %p; pos: %lld; buffer: %p; length: %lu\n", cookie, 600 pos, buffer, *length); 601 OVERLAY_CALL(read_attr, cookie, pos, buffer, length) 602 DO_LOG("read_attr result: 0x%08lx; length: %lu\n", result, *length); 603 return result; 604 } 605 606 607 static status_t 608 overlay_write_attr(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos, 609 const void *buffer, size_t *length) 610 { 611 DO_LOG("write_attr cookie: %p; pos: %lld; buffer: %p; length: %lu\n", 612 cookie, pos, buffer, *length); 613 OVERLAY_CALL(write_attr, cookie, pos, buffer, length) 614 DO_LOG("write_attr result: 0x%08lx; length: %lu\n", result, *length); 615 return result; 616 } 617 618 619 static status_t 620 overlay_read_attr_stat(fs_volume *volume, fs_vnode *vnode, void *cookie, 621 struct stat *stat) 622 { 623 DO_LOG("read_attr_stat cookie: %p; stat: %p\n", cookie, stat); 624 OVERLAY_CALL(read_attr_stat, cookie, stat) 625 if (result == B_OK) { 626 DO_LOG("read_attr_stat result: 0x%08lx; stat(dev: %lu; ino: %llu;" 627 " mode: %u; uid: %u; gid %u; size: %llu; type: 0x%08lx)\n", result, 628 stat->st_dev, stat->st_ino, stat->st_mode, stat->st_uid, 629 stat->st_gid, stat->st_size, stat->st_type); 630 } else 631 DO_LOG("read_attr_stat result: 0x%08lx\n", result); 632 return result; 633 } 634 635 636 static status_t 637 overlay_write_attr_stat(fs_volume *volume, fs_vnode *vnode, void *cookie, 638 const struct stat *stat, int statMask) 639 { 640 DO_LOG("write_attr_stat cookie: %p; stat: %p; mask: %u\n", cookie, stat, 641 statMask); 642 OVERLAY_CALL(write_attr_stat, cookie, stat, statMask) 643 DO_LOG("write_attr_stat result: 0x%08lx\n", result); 644 return result; 645 } 646 647 648 static status_t 649 overlay_rename_attr(fs_volume *volume, fs_vnode *vnode, 650 const char *fromName, fs_vnode *toVnode, const char *toName) 651 { 652 DO_LOG("rename_attr from_name: \"%s\"; to_vnode: %p; to_name: \"%s\"\n", 653 fromName, ((fs_vnode *)toVnode->private_node)->private_node, toName); 654 OVERLAY_CALL(rename_attr, fromName, (fs_vnode *)toVnode->private_node, 655 toName) 656 DO_LOG("rename_attr result: 0x%08lx\n", result); 657 return result; 658 } 659 660 661 static status_t 662 overlay_remove_attr(fs_volume *volume, fs_vnode *vnode, const char *name) 663 { 664 DO_LOG("remove_attr name: \"%s\"\n", name); 665 OVERLAY_CALL(remove_attr, name) 666 DO_LOG("remove_attr result: 0x%08lx\n", result); 667 return result; 668 } 669 670 671 static status_t 672 overlay_create_special_node(fs_volume *volume, fs_vnode *vnode, 673 const char *name, fs_vnode *subVnode, mode_t mode, uint32 flags, 674 fs_vnode *_superVnode, ino_t *nodeID) 675 { 676 DO_LOG("create_special_node name: \"%s\"; sub_vnode: %p; mode: %u;" 677 " flags: %lu\n", name, subVnode->private_node, mode, flags); 678 OVERLAY_CALL(create_special_node, name, (fs_vnode *)subVnode->private_node, 679 mode, flags, _superVnode, nodeID) 680 DO_LOG("create_special_node result: 0x%08lx; super_vnode: %p;" 681 " node_id: %llu\n", result, _superVnode->private_node, *nodeID); 682 return result; 683 } 684 685 686 static fs_vnode_ops sOverlayVnodeOps = { 687 &overlay_lookup, 688 &overlay_get_vnode_name, 689 690 &overlay_put_vnode, 691 &overlay_remove_vnode, 692 693 &overlay_can_page, 694 &overlay_read_pages, 695 &overlay_write_pages, 696 697 &overlay_io, 698 &overlay_cancel_io, 699 700 &overlay_get_file_map, 701 702 /* common */ 703 &overlay_ioctl, 704 &overlay_set_flags, 705 &overlay_select, 706 &overlay_deselect, 707 &overlay_fsync, 708 709 &overlay_read_symlink, 710 &overlay_create_symlink, 711 &overlay_link, 712 &overlay_unlink, 713 &overlay_rename, 714 715 &overlay_access, 716 &overlay_read_stat, 717 &overlay_write_stat, 718 NULL, // fs_preallocate 719 720 /* file */ 721 &overlay_create, 722 &overlay_open, 723 &overlay_close, 724 &overlay_free_cookie, 725 &overlay_read, 726 &overlay_write, 727 728 /* directory */ 729 &overlay_create_dir, 730 &overlay_remove_dir, 731 &overlay_open_dir, 732 &overlay_close_dir, 733 &overlay_free_dir_cookie, 734 &overlay_read_dir, 735 &overlay_rewind_dir, 736 737 /* attribute directory operations */ 738 &overlay_open_attr_dir, 739 &overlay_close_attr_dir, 740 &overlay_free_attr_dir_cookie, 741 &overlay_read_attr_dir, 742 &overlay_rewind_attr_dir, 743 744 /* attribute operations */ 745 &overlay_create_attr, 746 &overlay_open_attr, 747 &overlay_close_attr, 748 &overlay_free_attr_cookie, 749 &overlay_read_attr, 750 &overlay_write_attr, 751 752 &overlay_read_attr_stat, 753 &overlay_write_attr_stat, 754 &overlay_rename_attr, 755 &overlay_remove_attr, 756 757 /* support for node and FS layers */ 758 &overlay_create_special_node, 759 &overlay_get_super_vnode 760 }; 761 762 763 // #pragma mark - volume ops 764 765 766 #define DO_VOLUME_LOG(format, args...) \ 767 { \ 768 char _printBuffer[256]; \ 769 int _printSize = snprintf(_printBuffer, sizeof(_printBuffer), \ 770 "%llu %ld %p: " format, system_time(), find_thread(NULL), \ 771 volume->super_volume, args); \ 772 if ((unsigned int)_printSize > sizeof(_printBuffer)) { \ 773 _printBuffer[sizeof(_printBuffer) - 1] = '\n'; \ 774 _printSize = sizeof(_printBuffer); \ 775 } \ 776 write((int)volume->private_volume, _printBuffer, _printSize); \ 777 } 778 779 #define OVERLAY_VOLUME_CALL(op, params...) \ 780 status_t result = B_UNSUPPORTED; \ 781 if (volume->super_volume->ops->op != NULL) \ 782 result = volume->super_volume->ops->op(volume->super_volume, params); \ 783 784 785 static status_t 786 overlay_unmount(fs_volume *volume) 787 { 788 if (volume->super_volume != NULL 789 && volume->super_volume->ops != NULL 790 && volume->super_volume->ops->unmount != NULL) 791 volume->super_volume->ops->unmount(volume->super_volume); 792 793 close((int)volume->private_volume); 794 return B_OK; 795 } 796 797 798 static status_t 799 overlay_read_fs_info(fs_volume *volume, struct fs_info *info) 800 { 801 DO_VOLUME_LOG("%s\n", "read_fs_info"); 802 OVERLAY_VOLUME_CALL(read_fs_info, info) 803 DO_VOLUME_LOG("read_fs_info result: 0x%08lx; info(dev: %lu; root: %llu;" 804 " flags: %lu; block_size: %lld; io_size: %lld; total_blocks: %lld;" 805 " free_blocks: %lld; total_nodes: %lld; free_nodes: %lld;" 806 " device_name: \"%s\"; volume_name: \"%s\"; fsh_name: \"%s\")\n", 807 result, info->dev, info->root, info->flags, info->block_size, 808 info->io_size, info->total_blocks, info->free_blocks, 809 info->total_nodes, info->free_nodes, info->device_name, 810 info->volume_name, info->fsh_name); 811 return result; 812 } 813 814 815 static status_t 816 overlay_write_fs_info(fs_volume *volume, const struct fs_info *info, 817 uint32 mask) 818 { 819 DO_VOLUME_LOG("write_fs_info info: %p; mask: %lu\n", info, mask); 820 OVERLAY_VOLUME_CALL(write_fs_info, info, mask) 821 DO_VOLUME_LOG("write_fs_info result: 0x%08lx\n", result); 822 return result; 823 } 824 825 826 static status_t 827 overlay_sync(fs_volume *volume) 828 { 829 DO_VOLUME_LOG("%s\n", "sync"); 830 status_t result = B_UNSUPPORTED; 831 if (volume->super_volume->ops->sync != NULL) 832 result = volume->super_volume->ops->sync(volume->super_volume); 833 DO_VOLUME_LOG("sync result: 0x%08lx\n", result); 834 return result; 835 } 836 837 838 static status_t 839 overlay_get_vnode(fs_volume *volume, ino_t id, fs_vnode *vnode, int *type, 840 uint32 *flags, bool reenter) 841 { 842 DO_VOLUME_LOG("get_vnode id: %llu; vnode: %p; type*: %p; flags*: %p;" 843 " reenter: %d\n", id, vnode, type, flags, reenter); 844 845 if (volume->super_volume->ops->get_vnode == NULL) { 846 DO_VOLUME_LOG("get_vnode %s\n", "not supported"); 847 return B_UNSUPPORTED; 848 } 849 850 fs_vnode *superVnode = new(std::nothrow) fs_vnode; 851 if (superVnode == NULL) { 852 DO_VOLUME_LOG("get_vnode %s\n", "no memory"); 853 return B_NO_MEMORY; 854 } 855 856 status_t result = volume->super_volume->ops->get_vnode(volume->super_volume, 857 id, superVnode, type, flags, reenter); 858 if (result != B_OK) { 859 DO_VOLUME_LOG("get_vnode result: 0x%08lx\n", result); 860 delete superVnode; 861 return result; 862 } 863 864 vnode->private_node = superVnode; 865 vnode->ops = &sOverlayVnodeOps; 866 867 DO_VOLUME_LOG("get_vnode result: 0x%08lx; super_vnode: %p\n", result, 868 superVnode->private_node); 869 return B_OK; 870 } 871 872 873 static status_t 874 overlay_open_index_dir(fs_volume *volume, void **cookie) 875 { 876 DO_VOLUME_LOG("%s\n", "open_index_dir"); 877 OVERLAY_VOLUME_CALL(open_index_dir, cookie) 878 DO_VOLUME_LOG("open_index_dir result: 0x%08lx; cookie: %p\n", result, 879 *cookie); 880 return result; 881 } 882 883 884 static status_t 885 overlay_close_index_dir(fs_volume *volume, void *cookie) 886 { 887 DO_VOLUME_LOG("close_index_dir cookie: %p\n", cookie); 888 OVERLAY_VOLUME_CALL(close_index_dir, cookie) 889 DO_VOLUME_LOG("close_index_dir result: 0x%08lx\n", result); 890 return result; 891 } 892 893 894 static status_t 895 overlay_free_index_dir_cookie(fs_volume *volume, void *cookie) 896 { 897 DO_VOLUME_LOG("free_index_dir_cookie cookie: %p\n", cookie); 898 OVERLAY_VOLUME_CALL(free_index_dir_cookie, cookie) 899 DO_VOLUME_LOG("free_index_dir_cookie result: 0x%08lx\n", result); 900 return result; 901 } 902 903 904 static status_t 905 overlay_read_index_dir(fs_volume *volume, void *cookie, struct dirent *buffer, 906 size_t bufferSize, uint32 *num) 907 { 908 DO_VOLUME_LOG("read_index_dir cookie: %p; buffer: %p; buffer_size: %lu\n", 909 cookie, buffer, bufferSize); 910 OVERLAY_VOLUME_CALL(read_index_dir, cookie, buffer, bufferSize, num) 911 DO_VOLUME_LOG("read_index_dir result: 0x%08lx; num: %lu\n", result, *num); 912 return result; 913 } 914 915 916 static status_t 917 overlay_rewind_index_dir(fs_volume *volume, void *cookie) 918 { 919 DO_VOLUME_LOG("rewind_index_dir cookie: %p\n", cookie); 920 OVERLAY_VOLUME_CALL(rewind_index_dir, cookie) 921 DO_VOLUME_LOG("rewind_index_dir result: 0x%08lx\n", result); 922 return result; 923 } 924 925 926 static status_t 927 overlay_create_index(fs_volume *volume, const char *name, uint32 type, 928 uint32 flags) 929 { 930 DO_VOLUME_LOG("create_index name: \"%s\"; type: %lu; flags: %lu\n", name, 931 type, flags); 932 OVERLAY_VOLUME_CALL(create_index, name, type, flags) 933 DO_VOLUME_LOG("create_index result: 0x%08lx\n", result); 934 return result; 935 } 936 937 938 static status_t 939 overlay_remove_index(fs_volume *volume, const char *name) 940 { 941 DO_VOLUME_LOG("remove_index name: \"%s\"\n", name); 942 OVERLAY_VOLUME_CALL(remove_index, name) 943 DO_VOLUME_LOG("remove_index result: 0x%08lx\n", result); 944 return result; 945 } 946 947 948 static status_t 949 overlay_read_index_stat(fs_volume *volume, const char *name, struct stat *stat) 950 { 951 DO_VOLUME_LOG("read_index_stat name: \"%s\"; stat: %p\n", name, stat); 952 OVERLAY_VOLUME_CALL(read_index_stat, name, stat) 953 if (result == B_OK) { 954 DO_VOLUME_LOG("read_index_stat result: 0x%08lx; stat(dev: %lu;" 955 " ino: %llu; mode: %u; uid: %u; gid %u; size: %llu;" 956 " type: 0x%08lx)\n", result, stat->st_dev, stat->st_ino, 957 stat->st_mode, stat->st_uid, stat->st_gid, stat->st_size, 958 stat->st_type); 959 } else 960 DO_VOLUME_LOG("read_index_stat result: 0x%08lx\n", result); 961 return result; 962 } 963 964 965 static status_t 966 overlay_open_query(fs_volume *volume, const char *query, uint32 flags, 967 port_id port, uint32 token, void **cookie) 968 { 969 DO_VOLUME_LOG("open_query query: \"%s\"; flags: %lu; port: %ld;" 970 " token: %lu\n", query, flags, port, token); 971 OVERLAY_VOLUME_CALL(open_query, query, flags, port, token, cookie) 972 DO_VOLUME_LOG("open_query result: 0x%08lx; cookie: %p\n", result, *cookie); 973 return result; 974 } 975 976 977 static status_t 978 overlay_close_query(fs_volume *volume, void *cookie) 979 { 980 DO_VOLUME_LOG("close_query cookie: %p\n", cookie); 981 OVERLAY_VOLUME_CALL(close_query, cookie) 982 DO_VOLUME_LOG("close_query result: 0x%08lx\n", result); 983 return result; 984 } 985 986 987 static status_t 988 overlay_free_query_cookie(fs_volume *volume, void *cookie) 989 { 990 DO_VOLUME_LOG("free_query_cookie cookie: %p\n", cookie); 991 OVERLAY_VOLUME_CALL(free_query_cookie, cookie) 992 DO_VOLUME_LOG("free_query_cookie result: 0x%08lx\n", result); 993 return result; 994 } 995 996 997 static status_t 998 overlay_read_query(fs_volume *volume, void *cookie, struct dirent *buffer, 999 size_t bufferSize, uint32 *num) 1000 { 1001 DO_VOLUME_LOG("read_query cookie: %p; buffer: %p; buffer_size: %lu\n", 1002 cookie, buffer, bufferSize); 1003 OVERLAY_VOLUME_CALL(read_query, cookie, buffer, bufferSize, num) 1004 DO_VOLUME_LOG("read_query result: 0x%08lx; num: %lu\n", result, *num); 1005 return result; 1006 } 1007 1008 1009 static status_t 1010 overlay_rewind_query(fs_volume *volume, void *cookie) 1011 { 1012 DO_VOLUME_LOG("rewind_query cookie: %p\n", cookie); 1013 OVERLAY_VOLUME_CALL(rewind_query, cookie) 1014 DO_VOLUME_LOG("rewind_query result: 0x%08lx\n", result); 1015 return result; 1016 } 1017 1018 1019 static status_t 1020 overlay_all_layers_mounted(fs_volume *volume) 1021 { 1022 return B_OK; 1023 } 1024 1025 1026 static status_t 1027 overlay_create_sub_vnode(fs_volume *volume, ino_t id, fs_vnode *vnode) 1028 { 1029 fs_vnode *superVnode = new(std::nothrow) fs_vnode; 1030 if (superVnode == NULL) 1031 return B_NO_MEMORY; 1032 1033 *superVnode = *vnode; 1034 vnode->private_node = superVnode; 1035 vnode->ops = &sOverlayVnodeOps; 1036 return B_OK; 1037 } 1038 1039 1040 static status_t 1041 overlay_delete_sub_vnode(fs_volume *volume, fs_vnode *vnode) 1042 { 1043 delete (fs_vnode *)vnode->private_node; 1044 return B_OK; 1045 } 1046 1047 1048 static fs_volume_ops sOverlayVolumeOps = { 1049 &overlay_unmount, 1050 1051 &overlay_read_fs_info, 1052 &overlay_write_fs_info, 1053 &overlay_sync, 1054 1055 &overlay_get_vnode, 1056 &overlay_open_index_dir, 1057 &overlay_close_index_dir, 1058 &overlay_free_index_dir_cookie, 1059 &overlay_read_index_dir, 1060 &overlay_rewind_index_dir, 1061 1062 &overlay_create_index, 1063 &overlay_remove_index, 1064 &overlay_read_index_stat, 1065 1066 &overlay_open_query, 1067 &overlay_close_query, 1068 &overlay_free_query_cookie, 1069 &overlay_read_query, 1070 &overlay_rewind_query, 1071 1072 &overlay_all_layers_mounted, 1073 &overlay_create_sub_vnode, 1074 &overlay_delete_sub_vnode 1075 }; 1076 1077 1078 // #pragma mark - filesystem module 1079 1080 1081 static status_t 1082 overlay_mount(fs_volume *volume, const char *device, uint32 flags, 1083 const char *args, ino_t *rootID) 1084 { 1085 char filename[256]; 1086 snprintf(filename, sizeof(filename), "%s%s", kLogFilePrefix, device); 1087 filename[sizeof(filename) - 1] = 0; 1088 1089 int filenameLength = strlen(filename); 1090 for (int i = strlen(kLogFilePrefix); i < filenameLength; i++) { 1091 if (filename[i] == '/') 1092 filename[i] = '_'; 1093 } 1094 1095 int fd = creat(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 1096 if (fd < 0) 1097 return errno; 1098 1099 volume->private_volume = (void *)fd; 1100 volume->ops = &sOverlayVolumeOps; 1101 return B_OK; 1102 } 1103 1104 1105 static status_t 1106 overlay_std_ops(int32 op, ...) 1107 { 1108 switch (op) { 1109 case B_MODULE_INIT: 1110 case B_MODULE_UNINIT: 1111 return B_OK; 1112 default: 1113 return B_ERROR; 1114 } 1115 } 1116 1117 1118 static file_system_module_info sOverlayFileSystem = { 1119 { 1120 "file_systems/log_overlay"B_CURRENT_FS_API_VERSION, 1121 0, 1122 overlay_std_ops, 1123 }, 1124 1125 "log_overlay", // short_name 1126 "Logging Overlay File System", // pretty_name 1127 0, // DDM flags 1128 1129 // scanning 1130 NULL, // identify_partition 1131 NULL, // scan_partition 1132 NULL, // free_identify_partition_cookie 1133 NULL, // free_partition_content_cookie 1134 1135 // general operations 1136 &overlay_mount, 1137 1138 // capability querying 1139 NULL, // get_supported_operations 1140 1141 NULL, // validate_resize 1142 NULL, // validate_move 1143 NULL, // validate_set_content_name 1144 NULL, // validate_set_content_parameters 1145 NULL, // validate_initialize 1146 1147 // shadow partition modification 1148 NULL, // shadow_changed 1149 1150 // writing 1151 NULL, // defragment 1152 NULL, // repair 1153 NULL, // resize 1154 NULL, // move 1155 NULL, // set_content_name 1156 NULL, // set_content_parameters 1157 NULL // initialize 1158 }; 1159 1160 module_info *modules[] = { 1161 (module_info *)&sOverlayFileSystem, 1162 NULL, 1163 }; 1164