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 {...@@ -146,7 +146,7 @@ pub const Node = extern struct {
146146
147 pub fn hasMoved(ni: Node.Index, mf: *const MappedFile) bool {147 pub fn hasMoved(ni: Node.Index, mf: *const MappedFile) bool {
148 var parent_ni = ni;148 var parent_ni = ni;
149 while (parent_ni != .none) {149 while (parent_ni != Node.Index.root) {
150 const parent = parent_ni.get(mf);150 const parent = parent_ni.get(mf);
151 if (parent.flags.moved) return true;151 if (parent.flags.moved) return true;
152 parent_ni = parent.parent;152 parent_ni = parent.parent;
...@@ -164,7 +164,7 @@ pub const Node = extern struct {...@@ -164,7 +164,7 @@ pub const Node = extern struct {
164 }164 }
165 fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {165 fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {
166 var parent_ni = ni;166 var parent_ni = ni;
167 while (parent_ni != .none) {167 while (parent_ni != Node.Index.root) {
168 const parent_node = parent_ni.get(mf);168 const parent_node = parent_ni.get(mf);
169 if (parent_node.flags.moved) return;169 if (parent_node.flags.moved) return;
170 parent_ni = parent_node.parent;170 parent_ni = parent_node.parent;
...@@ -550,9 +550,9 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested...@@ -550,9 +550,9 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
550 const new_size = node.flags.alignment.forward(@intCast(requested_size));550 const new_size = node.flags.alignment.forward(@intCast(requested_size));
551 // Resize the entire file551 // Resize the entire file
552 if (ni == Node.Index.root) {552 if (ni == Node.Index.root) {
553 try mf.ensureCapacityForSetLocation(gpa);
553 try mf.file.setEndPos(new_size);554 try mf.file.setEndPos(new_size);
554 try mf.ensureTotalCapacity(@intCast(new_size));555 try mf.ensureTotalCapacity(@intCast(new_size));
555 try mf.ensureCapacityForSetLocation(gpa);
556 ni.setLocationAssumeCapacity(mf, old_offset, new_size);556 ni.setLocationAssumeCapacity(mf, old_offset, new_size);
557 return;557 return;
558 }558 }
...@@ -585,56 +585,56 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested...@@ -585,56 +585,56 @@ fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested
585 continue;585 continue;
586 }586 }
587 const range_file_offset = ni.fileLocation(mf, false).offset + old_size;587 const range_file_offset = ni.fileLocation(mf, false).offset + old_size;
588 retry: while (true) {588 while (true) switch (linux.E.init(linux.fallocate(
589 switch (linux.E.init(linux.fallocate(589 mf.file.handle,
590 mf.file.handle,590 linux.FALLOC.FL_INSERT_RANGE,
591 linux.FALLOC.FL_INSERT_RANGE,591 @intCast(range_file_offset),
592 @intCast(range_file_offset),592 @intCast(range_size),
593 @intCast(range_size),593 ))) {
594 ))) {594 .SUCCESS => {
595 .SUCCESS => {595 var enclosing_ni = ni;
596 var enclosing_ni = ni;596 while (true) {
597 while (enclosing_ni != .none) {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) {
598 try mf.ensureCapacityForSetLocation(gpa);610 try mf.ensureCapacityForSetLocation(gpa);
599 const enclosing = enclosing_ni.get(mf);611 const after = after_ni.get(mf);
600 const enclosing_offset, const enclosing_size =612 const after_offset, const after_size = after.location().resolve(mf);
601 enclosing.location().resolve(mf);613 after_ni.setLocationAssumeCapacity(
602 enclosing_ni.setLocationAssumeCapacity(
603 mf,614 mf,
604 enclosing_offset,615 range_size + after_offset,
605 enclosing_size + range_size,616 after_size,
606 );617 );
607 var after_ni = enclosing.next;618 after_ni = after.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;
620 }619 }
621 return;620 enclosing_ni = enclosing.parent;
622 },621 }
623 .INTR => continue :retry,622 return;
624 .BADF, .FBIG, .INVAL => unreachable,623 },
625 .IO => return error.InputOutput,624 .INTR => continue,
626 .NODEV => return error.NotFile,625 .BADF, .FBIG, .INVAL => unreachable,
627 .NOSPC => return error.NoSpaceLeft,626 .IO => return error.InputOutput,
628 .NOSYS, .OPNOTSUPP => {627 .NODEV => return error.NotFile,
629 mf.flags.fallocate_insert_range_unsupported = true;628 .NOSPC => return error.NoSpaceLeft,
630 break :insert_range;629 .NOSYS, .OPNOTSUPP => {
631 },630 mf.flags.fallocate_insert_range_unsupported = true;
632 .PERM => return error.PermissionDenied,631 break :insert_range;
633 .SPIPE => return error.Unseekable,632 },
634 .TXTBSY => return error.FileBusy,633 .PERM => return error.PermissionDenied,
635 else => |e| return std.posix.unexpectedErrno(e),634 .SPIPE => return error.Unseekable,
636 }635 .TXTBSY => return error.FileBusy,
637 }636 else => |e| return std.posix.unexpectedErrno(e),
637 };
638 }638 }
639 switch (node.next) {639 switch (node.next) {
640 .none => {640 .none => {
...@@ -728,7 +728,6 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size:...@@ -728,7 +728,6 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size:
728 // delete the copy of this node at the old location728 // delete the copy of this node at the old location
729 if (is_linux and !mf.flags.fallocate_punch_hole_unsupported and729 if (is_linux and !mf.flags.fallocate_punch_hole_unsupported and
730 size >= mf.flags.block_size.toByteUnits() * 2 - 1) while (true)730 size >= mf.flags.block_size.toByteUnits() * 2 - 1) while (true)
731 {
732 switch (linux.E.init(linux.fallocate(731 switch (linux.E.init(linux.fallocate(
733 mf.file.handle,732 mf.file.handle,
734 linux.FALLOC.FL_PUNCH_HOLE | linux.FALLOC.FL_KEEP_SIZE,733 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:...@@ -749,8 +748,7 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size:
749 .SPIPE => return error.Unseekable,748 .SPIPE => return error.Unseekable,
750 .TXTBSY => return error.FileBusy,749 .TXTBSY => return error.FileBusy,
751 else => |e| return std.posix.unexpectedErrno(e),750 else => |e| return std.posix.unexpectedErrno(e),
752 }751 };
753 };
754 @memset(mf.contents[@intCast(old_file_offset)..][0..@intCast(size)], 0);752 @memset(mf.contents[@intCast(old_file_offset)..][0..@intCast(size)], 0);
755}753}
756754