Commit 6b17b68
macOS: skip set_readwrite_recursive walk after clonefile (~1.85x materialization speedup) (#2349)
* fs_util: skip set_readwrite_recursive walk after clonefile
The macOS clonefile fast path was followed by a recursive chmod walk that
made every file in the cloned tree writable (0o644 / 0o755). On real
Bazel input shapes (~2000-file SwiftCompile) that walk accounted for
~46% of materialization time — ~33 µs per file, ~67 ms per action.
Replace the walk with a single chmod(2) on the destination root.
Existing entries inherit the source's read-only mode (0o555 dirs,
0o444 files). The worker can still create the action's declared output
files inside the root because the root itself is 0o755.
This matches the hermeticity contract enforced by Bazel's local
sandbox (linux-sandbox bind-mounts inputs read-only;
darwin-sandbox / sandbox-exec denies writes outside declared output
paths) and the REAPI Action.output_files / output_directories
semantics: actions write only to declared outputs, never mutate
inputs. An action that does try to mutate an input now hits EACCES,
which is the correct REAPI behavior — same failure mode as on
Bazel's own sandbox.
Bench (nativelink-util/benches/chmod_strategy.rs on the bench branch),
toplevel_only vs full walk:
shape walk toplevel_only speedup
small_flat (64 files) 4.66 ms 2.61 ms 1.79x
pcm_cluster (219 files) 15.17 ms 8.19 ms 1.85x
medium_flat (635 files) 46.36 ms 25.10 ms 1.85x
large_flat (1978 files) 147.39 ms 80.17 ms 1.84x
set_readwrite_recursive stays public — directory_cache.rs:451 still
uses it on the source side during eviction.
Tests:
- test_clonefile_root_writable_inputs_readonly: root 0o755, subdirs
0o555, files 0o444 (replaces the old test_clonefile_dest_is_writable
which assumed subdirs would be made writable).
- test_clonefile_root_accepts_new_files: worker can create outputs at
the root even though everything inside the clone is read-only.
- test_clonefile_input_mutation_fails: writes to existing input files
fail with PermissionDenied — encodes the hermeticity contract.
* fs_util: remove dead set_readwrite_recursive after post-#2347 cleanup
After #2347 (DirectoryCache cleanup uses set_dir_writable_recursive)
and this PR (post-clonefile path uses chmod_dir_writable), the
generic set_readwrite_recursive helper has zero remaining callers.
Both replacements are intentionally narrower - set_dir_writable_recursive
chmods only directories so file inodes aren't mutated, and
chmod_dir_writable chmods only the destination root so the clone
tree stays read-only inside. Delete the old helper and its private
companion set_readwrite_one_path.
Addresses palfrey's review feedback on #2347 ("set_readwrite_recursive
and set_readwrite_one_path can be dropped as part of this") - sequenced
on this PR instead because both PRs had to land before the helpers
became dead.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* worker: make the APFS clonefile directory-cache path work end-to-end
PR #2338's clonefile fast path is effectively dead in production — it
materialized 1 of 1771 actions in a real build. Three coupled bugs kept
the directory cache silently falling back to the slow download path, and
two of them only surface once the fast path actually fires, so they must
land together.
Bug 1: prepare_action_inputs received a work directory the caller had
already created, but hardlink_directory_tree and clonefile(2) both
require the destination to NOT exist. Every cache attempt failed its
precondition and fell back to download_to_directory. Fix: remove the
empty pre-created directory before invoking the cache, and recreate it
on cache failure so the download fallback (which needs an existing
destination) still works. Adds fs::remove_dir for the empty-dir removal.
Bug 2: set_readonly_recursive chmod'd files to 0o444, stripping the
execute bit from cached executables. Once a tree is cloned into a
workspace this makes an action's interpreter/wrapper script fail with
EACCES. Fix: mark files 0o555 instead of 0o444 — read + execute, still
no write bit, so the hermeticity contract is unchanged.
Bug 3: the clonefile path chmods only the destination root writable;
cloned subdirectories keep the source's 0o555 mode. Bazel actions
declare outputs at paths nested inside input subdirectories, and
creating those files needs write permission on the parent directory.
Fix: after a cache hit, set_dir_writable_recursive makes every directory
in the materialized tree writable. Files stay read-only — they may be
CAS-hardlinked and chmoding them would corrupt the shared inode.
Adds regression tests for nested output creation, which the existing
root-only clonefile tests did not cover.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Marcus Eagan <marcuseagan@gmail.com>1 parent 41c7789 commit 6b17b68
4 files changed
Lines changed: 234 additions & 78 deletions
File tree
- nativelink-util/src
- nativelink-worker/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
369 | 369 | | |
370 | 370 | | |
371 | 371 | | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
372 | 379 | | |
373 | 380 | | |
374 | 381 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
58 | 62 | | |
59 | 63 | | |
60 | 64 | | |
| |||
97 | 101 | | |
98 | 102 | | |
99 | 103 | | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
105 | 113 | | |
106 | | - | |
| 114 | + | |
107 | 115 | | |
108 | 116 | | |
109 | 117 | | |
| |||
178 | 186 | | |
179 | 187 | | |
180 | 188 | | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
181 | 204 | | |
182 | 205 | | |
183 | 206 | | |
| |||
271 | 294 | | |
272 | 295 | | |
273 | 296 | | |
274 | | - | |
275 | | - | |
276 | | - | |
277 | | - | |
278 | | - | |
279 | | - | |
280 | | - | |
281 | | - | |
282 | | - | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
287 | | - | |
288 | | - | |
289 | 297 | | |
290 | 298 | | |
291 | 299 | | |
| |||
319 | 327 | | |
320 | 328 | | |
321 | 329 | | |
322 | | - | |
323 | | - | |
324 | | - | |
325 | | - | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
326 | 338 | | |
327 | 339 | | |
328 | 340 | | |
| |||
343 | 355 | | |
344 | 356 | | |
345 | 357 | | |
346 | | - | |
347 | | - | |
348 | | - | |
349 | | - | |
350 | | - | |
351 | | - | |
352 | | - | |
353 | | - | |
354 | | - | |
355 | | - | |
356 | | - | |
357 | | - | |
358 | | - | |
359 | | - | |
360 | | - | |
361 | | - | |
362 | | - | |
363 | | - | |
364 | | - | |
365 | | - | |
366 | | - | |
367 | | - | |
368 | | - | |
369 | | - | |
370 | | - | |
371 | | - | |
372 | | - | |
373 | | - | |
374 | | - | |
375 | | - | |
376 | | - | |
377 | | - | |
378 | | - | |
379 | | - | |
380 | | - | |
381 | 358 | | |
382 | 359 | | |
383 | 360 | | |
| |||
590 | 567 | | |
591 | 568 | | |
592 | 569 | | |
593 | | - | |
| 570 | + | |
594 | 571 | | |
595 | 572 | | |
596 | 573 | | |
597 | | - | |
| 574 | + | |
598 | 575 | | |
599 | 576 | | |
600 | 577 | | |
601 | 578 | | |
602 | 579 | | |
603 | | - | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
604 | 590 | | |
605 | 591 | | |
606 | 592 | | |
607 | 593 | | |
608 | 594 | | |
609 | | - | |
610 | | - | |
| 595 | + | |
| 596 | + | |
611 | 597 | | |
612 | 598 | | |
613 | | - | |
| 599 | + | |
614 | 600 | | |
615 | 601 | | |
616 | 602 | | |
617 | 603 | | |
618 | 604 | | |
619 | | - | |
620 | | - | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
621 | 618 | | |
622 | 619 | | |
623 | 620 | | |
624 | 621 | | |
625 | 622 | | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
626 | 667 | | |
627 | 668 | | |
628 | 669 | | |
| |||
647 | 688 | | |
648 | 689 | | |
649 | 690 | | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
650 | 735 | | |
651 | 736 | | |
652 | 737 | | |
| |||
663 | 748 | | |
664 | 749 | | |
665 | 750 | | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
666 | 782 | | |
667 | 783 | | |
668 | 784 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
451 | 451 | | |
452 | 452 | | |
453 | 453 | | |
454 | | - | |
455 | | - | |
| 454 | + | |
| 455 | + | |
456 | 456 | | |
457 | 457 | | |
458 | 458 | | |
| |||
733 | 733 | | |
734 | 734 | | |
735 | 735 | | |
736 | | - | |
737 | | - | |
| 736 | + | |
| 737 | + | |
738 | 738 | | |
739 | 739 | | |
740 | 740 | | |
| |||
758 | 758 | | |
759 | 759 | | |
760 | 760 | | |
761 | | - | |
| 761 | + | |
762 | 762 | | |
763 | 763 | | |
764 | 764 | | |
| |||
0 commit comments