| ... | @@ -856,19 +856,20 @@ fn resizeNode( | ... | @@ -856,19 +856,20 @@ fn resizeNode( |
| 856 | ni.setLocationAssumeCapacity(mf, old_offset, new_size); | 856 | ni.setLocationAssumeCapacity(mf, old_offset, new_size); |
| 857 | return; | 857 | return; |
| 858 | } | 858 | } |
| 859 | if (is_linux and !mf.flags.fallocate_insert_range_unsupported and | | |
| 860 | node.flags.alignment.order(mf.flags.block_size).compare(.gte)) | | |
| 861 | insert_range: { | 859 | insert_range: { |
| | 860 | if (!is_linux) break :insert_range; |
| | 861 | if (mf.flags.fallocate_insert_range_unsupported) break :insert_range; |
| | 862 | |
| | 863 | // We need the node to be aligned to `mf.flags.block_size` in the file in order to use this |
| | 864 | // fast path. It is not sufficient to check `node.flags.alignment`, because that doesn't |
| | 865 | // necessarily mean that all *parent* nodes are equally aligned; instead we must compute the |
| | 866 | // actual file offset. |
| 862 | const range_file_offset = ni.fileLocation(mf, false).offset + old_size; | 867 | const range_file_offset = ni.fileLocation(mf, false).offset + old_size; |
| 863 | const range_size = node.flags.alignment.forward( | 868 | const range_size = node.flags.alignment.forward( |
| 864 | @intCast(requested_size +| requested_size / growth_factor), | 869 | @intCast(requested_size +| requested_size / growth_factor), |
| 865 | ) - old_size; | 870 | ) - old_size; |
| 866 | | 871 | if (!mf.flags.block_size.check(@intCast(range_file_offset))) break :insert_range; |
| 867 | // If this node is being realigned, its current state might not | 872 | if (!mf.flags.block_size.check(@intCast(range_size))) break :insert_range; |
| 868 | // meet the requirements for fallocate | | |
| 869 | if (!mf.flags.block_size.check(@intCast(range_file_offset)) or | | |
| 870 | !mf.flags.block_size.check(@intCast(range_size))) | | |
| 871 | break :insert_range; | | |
| 872 | | 873 | |
| 873 | mf.memory_map.write(io) catch |err| switch (err) { | 874 | mf.memory_map.write(io) catch |err| switch (err) { |
| 874 | error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking | 875 | error.WouldBlock => return error.Unexpected, // file was not opened as non-blocking |
| ... | @@ -1208,9 +1209,11 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: | ... | @@ -1208,9 +1209,11 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: |
| 1208 | // make a copy of this node at the new location | 1209 | // make a copy of this node at the new location |
| 1209 | try mf.copyRange(old_file_offset, new_file_offset, size); | 1210 | try mf.copyRange(old_file_offset, new_file_offset, size); |
| 1210 | // delete the copy of this node at the old location | 1211 | // delete the copy of this node at the old location |
| 1211 | if (is_linux and !mf.flags.fallocate_punch_hole_unsupported and | 1212 | if (is_linux and |
| 1212 | size >= mf.flags.block_size.toByteUnits() * 2 - 1) while (true) | 1213 | !mf.flags.fallocate_punch_hole_unsupported and |
| 1213 | switch (linux.errno(linux.fallocate( | 1214 | size >= mf.flags.block_size.toByteUnits() * 2 - 1) |
| | 1215 | { |
| | 1216 | while (true) switch (linux.errno(linux.fallocate( |
| 1214 | mf.memory_map.file.handle, | 1217 | mf.memory_map.file.handle, |
| 1215 | linux.FALLOC.FL_PUNCH_HOLE | linux.FALLOC.FL_KEEP_SIZE, | 1218 | linux.FALLOC.FL_PUNCH_HOLE | linux.FALLOC.FL_KEEP_SIZE, |
| 1216 | @intCast(old_file_offset), | 1219 | @intCast(old_file_offset), |
| ... | @@ -1224,13 +1227,14 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: | ... | @@ -1224,13 +1227,14 @@ fn moveRange(mf: *MappedFile, old_file_offset: u64, new_file_offset: u64, size: |
| 1224 | .NOSPC => return error.NoSpaceLeft, | 1227 | .NOSPC => return error.NoSpaceLeft, |
| 1225 | .NOSYS, .OPNOTSUPP => { | 1228 | .NOSYS, .OPNOTSUPP => { |
| 1226 | mf.flags.fallocate_punch_hole_unsupported = true; | 1229 | mf.flags.fallocate_punch_hole_unsupported = true; |
| 1227 | break; | 1230 | break; // fall back to slow path |
| 1228 | }, | 1231 | }, |
| 1229 | .PERM => return error.PermissionDenied, | 1232 | .PERM => return error.PermissionDenied, |
| 1230 | .SPIPE => return error.Unseekable, | 1233 | .SPIPE => return error.Unseekable, |
| 1231 | .TXTBSY => return error.FileBusy, | 1234 | .TXTBSY => return error.FileBusy, |
| 1232 | else => |e| return std.posix.unexpectedErrno(e), | 1235 | else => |e| return std.posix.unexpectedErrno(e), |
| 1233 | }; | 1236 | }; |
| | 1237 | } |
| 1234 | @memset(mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(size)], 0); | 1238 | @memset(mf.memory_map.memory[@intCast(old_file_offset)..][0..@intCast(size)], 0); |
| 1235 | } | 1239 | } |
| 1236 | | 1240 | |