authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-09-22 12:59:00-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-24 16:09:46-07:00
log4a344de651de757f01d9139ce0fbda7935048cf5
treeb7694b3e8b708cd2bc345962024029b23d4e06c0
parent94d319a10f90f8dfaf717fb537eeaf5415c47f9b

MappedFile: fix the insert range path not updating the root node


1 files changed, 50 insertions(+), 52 deletions(-)

src/link/MappedFile.zig+50-52
......@@ -146,7 +146,7 @@ pub const Node = extern struct {
146146
147147 pub fn hasMoved(ni: Node.Index, mf: *const MappedFile) bool {
148148 var parent_ni = ni;
149 while (parent_ni != .none) {
149 while (parent_ni != Node.Index.root) {
150150 const parent = parent_ni.get(mf);
151151 if (parent.flags.moved) return true;
152152 parent_ni = parent.parent;
......@@ -164,7 +164,7 @@ pub const Node = extern struct {
164164 }
165165 fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {
166166 var parent_ni = ni;
167 while (parent_ni != .none) {
167 while (parent_ni != Node.Index.root) {
168168 const parent_node = parent_ni.get(mf);
169169 if (parent_node.flags.moved) return;
170170 parent_ni = parent_node.parent;
......@@ -550,9 +550,9 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
550550 const new_size = node.flags.alignment.forward(@intCast(requested_size));
551551 // Resize the entire file
552552 if (ni == Node.Index.root) {
553 try mf.ensureCapacityForSetLocation(gpa);
553554 try mf.file.setEndPos(new_size);
554555 try mf.ensureTotalCapacity(@intCast(new_size));
555 try mf.ensureCapacityForSetLocation(gpa);
556556 ni.setLocationAssumeCapacity(mf, old_offset, new_size);
557557 return;
558558 }
......@@ -585,56 +585,56 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
585585 continue;
586586 }
587587 const range_file_offset = ni.fileLocation(mf, false).offset + old_size;
588 retry: while (true) {
589 switch (linux.E.init(linux.fallocate(
590 mf.file.handle,
591 linux.FALLOC.FL_INSERT_RANGE,
592 @intCast(range_file_offset),
593 @intCast(range_size),
594 ))) {
595 .SUCCESS => {
596 var enclosing_ni = ni;
597 while (enclosing_ni != .none) {
588 while (true) switch (linux.E.init(linux.fallocate(
589 mf.file.handle,
590 linux.FALLOC.FL_INSERT_RANGE,
591 @intCast(range_file_offset),
592 @intCast(range_size),
593 ))) {
594 .SUCCESS => {
595 var enclosing_ni = ni;
596 while (true) {
597 try mf.ensureCapacityForSetLocation(gpa);
598 const enclosing = enclosing_ni.get(mf);
599 const enclosing_offset, const old_enclosing_size =
600 enclosing.location().resolve(mf);
601 const new_enclosing_size = old_enclosing_size + range_size;
602 enclosing_ni.setLocationAssumeCapacity(mf, enclosing_offset, new_enclosing_size);
603 if (enclosing_ni == Node.Index.root) {
604 assert(enclosing_offset == 0);
605 try mf.ensureTotalCapacity(@intCast(new_enclosing_size));
606 break;
607 }
608 var after_ni = enclosing.next;
609 while (after_ni != .none) {
598610 try mf.ensureCapacityForSetLocation(gpa);
599 const enclosing = enclosing_ni.get(mf);
600 const enclosing_offset, const enclosing_size =
601 enclosing.location().resolve(mf);
602 enclosing_ni.setLocationAssumeCapacity(
611 const after = after_ni.get(mf);
612 const after_offset, const after_size = after.location().resolve(mf);
613 after_ni.setLocationAssumeCapacity(
603614 mf,
604 enclosing_offset,
605 enclosing_size + range_size,
615 range_size + after_offset,
616 after_size,
606617 );
607 var after_ni = enclosing.next;
608 while (after_ni != .none) {
609 try mf.ensureCapacityForSetLocation(gpa);
610 const after = after_ni.get(mf);
611 const after_offset, const after_size = after.location().resolve(mf);
612 after_ni.setLocationAssumeCapacity(
613 mf,
614 range_size + after_offset,
615 after_size,
616 );
617 after_ni = after.next;
618 }
619 enclosing_ni = enclosing.parent;
618 after_ni = after.next;
620619 }
621 return;
622 },
623 .INTR => continue :retry,
624 .BADF, .FBIG, .INVAL => unreachable,
625 .IO => return error.InputOutput,
626 .NODEV => return error.NotFile,
627 .NOSPC => return error.NoSpaceLeft,
628 .NOSYS, .OPNOTSUPP => {
629 mf.flags.fallocate_insert_range_unsupported = true;
630 break :insert_range;
631 },
632 .PERM => return error.PermissionDenied,
633 .SPIPE => return error.Unseekable,
634 .TXTBSY => return error.FileBusy,
635 else => |e| return std.posix.unexpectedErrno(e),
636 }
637 }
620 enclosing_ni = enclosing.parent;
621 }
622 return;
623 },
624 .INTR => continue,
625 .BADF, .FBIG, .INVAL => unreachable,
626 .IO => return error.InputOutput,
627 .NODEV => return error.NotFile,
628 .NOSPC => return error.NoSpaceLeft,
629 .NOSYS, .OPNOTSUPP => {
630 mf.flags.fallocate_insert_range_unsupported = true;
631 break :insert_range;
632 },
633 .PERM => return error.PermissionDenied,
634 .SPIPE => return error.Unseekable,
635 .TXTBSY => return error.FileBusy,
636 else => |e| return std.posix.unexpectedErrno(e),
637 };
638638 }
639639 switch (node.next) {
640640 .none => {
......@@ -728,7 +728,6 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size:
728728 // delete the copy of this node at the old location
729729 if (is_linux and !mf.flags.fallocate_punch_hole_unsupported and
730730 size >= mf.flags.block_size.toByteUnits() * 2 - 1) while (true)
731 {
732731 switch (linux.E.init(linux.fallocate(
733732 mf.file.handle,
734733 linux.FALLOC.FL_PUNCH_HOLE | linux.FALLOC.FL_KEEP_SIZE,
......@@ -749,8 +748,7 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size:
749748 .SPIPE => return error.Unseekable,
750749 .TXTBSY => return error.FileBusy,
751750 else => |e| return std.posix.unexpectedErrno(e),
752 }
753 };
751 };
754752 @memset(mf.contents[@intCast(old_file_offset)..][0..@intCast(size)], 0);
755753}
756754