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