diff --git a/src/kernel/filesystem/initrd.zig b/src/kernel/filesystem/initrd.zig index 373afb5..d8aa56b 100644 --- a/src/kernel/filesystem/initrd.zig +++ b/src/kernel/filesystem/initrd.zig @@ -345,7 +345,7 @@ test "init with files cleans memory if OutOfMemory" { } // Ensure we have freed any memory allocated - try std.testing.allocator_instance.validate(); + std.testing.expectEqual(false, std.testing.allocator_instance.detectLeaks()); } } @@ -413,6 +413,14 @@ test "open fail with invalid flags" { } test "open fail with NoSuchFileOrDir" { + var ramdisk_bytes = try createInitrd(std.testing.allocator); + defer std.testing.allocator.free(ramdisk_bytes); + + var initrd_stream = std.io.fixedBufferStream(ramdisk_bytes); + var fs = try InitrdFS.init(&initrd_stream, std.testing.allocator); + defer fs.deinit(); + + vfs.setRoot(fs.root_node); expectError(error.NoSuchFileOrDir, vfs.openFile("/text10.txt", .NO_CREATION)); expectError(error.NoSuchFileOrDir, vfs.openDir("/temp/", .NO_CREATION)); } diff --git a/src/kernel/filesystem/vfs.zig b/src/kernel/filesystem/vfs.zig index 452b916..9ee6861 100644 --- a/src/kernel/filesystem/vfs.zig +++ b/src/kernel/filesystem/vfs.zig @@ -246,6 +246,7 @@ fn traversePath(path: []const u8, flags: OpenFlags) (Allocator.Error || Error)!* child: []const u8, const Self = @This(); + fn func(split: *std.mem.SplitIterator, node: *Node, rec_flags: OpenFlags) (Allocator.Error || Error)!Self { // Get segment string. This will not be unreachable as we've made sure the spliterator has more segments left const seg = split.next() orelse unreachable; @@ -560,8 +561,8 @@ test "mount" { // The root fs var testfs = try testInitFs(allocator); - defer testfs.deinit(); defer allocator.destroy(testfs); + defer testfs.deinit(); testfs.instance = 1; root = testfs.tree.val; @@ -594,8 +595,8 @@ test "mount" { test "traversePath" { var allocator = testing.allocator; var testfs = try testInitFs(allocator); - defer testfs.deinit(); defer allocator.destroy(testfs); + defer testfs.deinit(); root = testfs.tree.val; // Get the root @@ -649,8 +650,8 @@ test "isFile" { test "open" { var testfs = try testInitFs(testing.allocator); - defer testfs.deinit(); defer testing.allocator.destroy(testfs); + defer testfs.deinit(); root = testfs.tree.val; // Creating a file @@ -698,8 +699,8 @@ test "open" { test "read" { var testfs = try testInitFs(testing.allocator); - defer testfs.deinit(); defer testing.allocator.destroy(testfs); + defer testfs.deinit(); root = testfs.tree.val; var test_file = try openFile("/foo.txt", .CREATE_FILE); @@ -736,8 +737,8 @@ test "read" { test "write" { var testfs = try testInitFs(testing.allocator); - defer testfs.deinit(); defer testing.allocator.destroy(testfs); + defer testfs.deinit(); root = testfs.tree.val; var test_file = try openFile("/foo.txt", .CREATE_FILE); diff --git a/src/kernel/heap.zig b/src/kernel/heap.zig index 1559c98..2a1f5b1 100644 --- a/src/kernel/heap.zig +++ b/src/kernel/heap.zig @@ -182,8 +182,10 @@ const FreeListAllocator = struct { /// Arguments: /// IN allocator: *std.Allocator - The allocator to resize within. /// IN old_mem: []u8 - The buffer to resize. + /// IN old_align: u29 - The original alignment for old_mem. /// IN new_size: usize - What to resize to. /// IN size_alignment: u29 - The alignment that the size should have. + /// IN ret_addr: usize - The return address passed by the high-level Allocator API. This is ignored /// /// Return: usize /// The new size of the buffer, which will be new_size if the operation was successful. @@ -191,7 +193,7 @@ const FreeListAllocator = struct { /// Error: std.Allocator.Error /// std.Allocator.Error.OutOfMemory - If there wasn't enough free memory to expand into /// - fn resize(allocator: *Allocator, old_mem: []u8, new_size: usize, size_alignment: u29) Allocator.Error!usize { + fn resize(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, size_alignment: u29, ret_addr: usize) Allocator.Error!usize { var self = @fieldParentPtr(FreeListAllocator, "allocator", allocator); if (new_size == 0) { self.free(old_mem); @@ -304,6 +306,7 @@ const FreeListAllocator = struct { /// IN size: usize - The amount of memory requested /// IN alignment: u29 - The alignment that the address of the allocated memory should have /// IN size_alignment: u29 - The alignment that the length of the allocated memory should have + /// IN ret_addr: usize - The return address passed by the high-level Allocator API. This is ignored /// /// Return: []u8 /// The allocated memory @@ -311,7 +314,7 @@ const FreeListAllocator = struct { /// Error: std.Allocator.Error /// std.Allocator.Error.OutOfMemory - There wasn't enough memory left to fulfill the request /// - pub fn alloc(allocator: *Allocator, size: usize, alignment: u29, size_alignment: u29) Allocator.Error![]u8 { + pub fn alloc(allocator: *Allocator, size: usize, alignment: u29, size_alignment: u29, ret_addr: usize) Allocator.Error![]u8 { var self = @fieldParentPtr(FreeListAllocator, "allocator", allocator); if (self.first_free == null) return Allocator.Error.OutOfMemory; @@ -433,7 +436,7 @@ const FreeListAllocator = struct { std.debug.warn("", .{}); - const alloc0 = try alloc(allocator, 64, 0, 0); + const alloc0 = try alloc(allocator, 64, 0, 0, @returnAddress()); const alloc0_addr = @ptrToInt(alloc0.ptr); // Should be at the start of the heap testing.expectEqual(alloc0_addr, start); @@ -446,7 +449,7 @@ const FreeListAllocator = struct { std.debug.warn("", .{}); // 64 bytes aligned to 4 bytes - const alloc1 = try alloc(allocator, 64, 4, 0); + const alloc1 = try alloc(allocator, 64, 4, 0, @returnAddress()); const alloc1_addr = @ptrToInt(alloc1.ptr); const alloc1_end = alloc1_addr + alloc1.len; // Should be to the right of the first allocation, with some alignment padding in between @@ -459,7 +462,7 @@ const FreeListAllocator = struct { testing.expectEqual(header.next_free, null); testing.expectEqual(free_list.first_free, header); - const alloc2 = try alloc(allocator, 64, 256, 0); + const alloc2 = try alloc(allocator, 64, 256, 0, @returnAddress()); const alloc2_addr = @ptrToInt(alloc2.ptr); const alloc2_end = alloc2_addr + alloc2.len; testing.expect(alloc1_end < alloc2_addr); @@ -475,7 +478,7 @@ const FreeListAllocator = struct { } // Try allocating something smaller than @sizeOf(Header). This should scale up to @sizeOf(Header) - var alloc3 = try alloc(allocator, 1, 0, 0); + var alloc3 = try alloc(allocator, 1, 0, 0, @returnAddress()); const alloc3_addr = @ptrToInt(alloc3.ptr); const alloc3_end = alloc3_addr + @sizeOf(Header); const header2 = @intToPtr(*Header, alloc3_end); @@ -486,10 +489,10 @@ const FreeListAllocator = struct { // Attempting to allocate more than the size of the largest free node should fail const remaining_size = second_header.size + @sizeOf(Header); - testing.expectError(Allocator.Error.OutOfMemory, alloc(&free_list.allocator, remaining_size + 1, 0, 0)); + testing.expectError(Allocator.Error.OutOfMemory, alloc(&free_list.allocator, remaining_size + 1, 0, 0, @returnAddress())); // Alloc a non aligned to header - var alloc4 = try alloc(allocator, 13, 1, 0); + var alloc4 = try alloc(allocator, 13, 1, 0, @returnAddress()); const alloc4_addr = @ptrToInt(alloc4.ptr); const alloc4_end = alloc4_addr + std.mem.alignForward(13, @alignOf(Header)); const header3 = @intToPtr(*Header, alloc4_end); @@ -512,9 +515,9 @@ const FreeListAllocator = struct { var free_list = &(try FreeListAllocator.init(start, size)); var allocator = &free_list.allocator; - var alloc0 = try alloc(allocator, 128, 0, 0); - var alloc1 = try alloc(allocator, 256, 0, 0); - var alloc2 = try alloc(allocator, 64, 0, 0); + var alloc0 = try alloc(allocator, 128, 0, 0, @returnAddress()); + var alloc1 = try alloc(allocator, 256, 0, 0, @returnAddress()); + var alloc2 = try alloc(allocator, 64, 0, 0, @returnAddress()); // There should be a single free node after alloc2 const free_node3 = @intToPtr(*Header, @ptrToInt(alloc2.ptr) + alloc2.len); @@ -551,14 +554,14 @@ const FreeListAllocator = struct { var free_list = &(try FreeListAllocator.init(start, size)); var allocator = &free_list.allocator; - var alloc0 = try alloc(allocator, 128, 0, 0); - var alloc1 = try alloc(allocator, 256, 0, 0); + var alloc0 = try alloc(allocator, 128, 0, 0, @returnAddress()); + var alloc1 = try alloc(allocator, 256, 0, 0, @returnAddress()); // Expanding alloc0 should fail as alloc1 is right next to it - testing.expectError(Allocator.Error.OutOfMemory, resize(&free_list.allocator, alloc0, 136, 0)); + testing.expectError(Allocator.Error.OutOfMemory, resize(&free_list.allocator, alloc0, 0, 136, 0, @returnAddress())); // Expanding alloc1 should succeed - testing.expectEqual(try resize(allocator, alloc1, 512, 0), 512); + testing.expectEqual(try resize(allocator, alloc1, 0, 512, 0, @returnAddress()), 512); alloc1 = alloc1.ptr[0..512]; // And there should be a free node on the right of it var header = @intToPtr(*Header, @ptrToInt(alloc1.ptr) + 512); @@ -567,7 +570,7 @@ const FreeListAllocator = struct { testing.expectEqual(free_list.first_free, header); // Shrinking alloc1 should produce a big free node on the right - testing.expectEqual(try resize(allocator, alloc1, 128, 0), 128); + testing.expectEqual(try resize(allocator, alloc1, 0, 128, 0, @returnAddress()), 128); alloc1 = alloc1.ptr[0..128]; header = @intToPtr(*Header, @ptrToInt(alloc1.ptr) + 128); testing.expectEqual(header.size, size - 128 - 128 - @sizeOf(Header)); @@ -575,9 +578,9 @@ const FreeListAllocator = struct { testing.expectEqual(free_list.first_free, header); // Shrinking by less space than would allow for a new Header shouldn't work - testing.expectEqual(resize(allocator, alloc1, alloc1.len - @sizeOf(Header) / 2, 0), 128); + testing.expectEqual(resize(allocator, alloc1, 0, alloc1.len - @sizeOf(Header) / 2, 0, @returnAddress()), 128); // Shrinking to less space than would allow for a new Header shouldn't work - testing.expectEqual(resize(allocator, alloc1, @sizeOf(Header) / 2, 0), @sizeOf(Header)); + testing.expectEqual(resize(allocator, alloc1, 0, @sizeOf(Header) / 2, 0, @returnAddress()), @sizeOf(Header)); } };