diff --git a/kernel/actiondfs/actiondfs.c b/kernel/actiondfs/actiondfs.c index fa0fe6c..af26f29 100644 --- a/kernel/actiondfs/actiondfs.c +++ b/kernel/actiondfs/actiondfs.c @@ -3115,6 +3115,10 @@ static int actiondfs_open_stage_file(struct inode *inode, if ((dir_file->stage_file || dir_file->stage_eof) && dir_file->stage_generation == generation) return 0; + if (dir_file->stage_file && !dir_file->stage_eof) { + dir_file->stage_generation = generation; + return 0; + } if (dir_file->stage_file || dir_file->stage_eof) actiondfs_reset_stage_file(dir_file); dir_file->stage_generation = generation; diff --git a/tools/e2e_action_tool.zig b/tools/e2e_action_tool.zig index 0d67b86..93adbb1 100644 --- a/tools/e2e_action_tool.zig +++ b/tools/e2e_action_tool.zig @@ -1096,6 +1096,34 @@ fn exerciseDirectoryIteration(io: std.Io, dir: std.Io.Dir) !void { try dir.deleteFile(io, name); } + try dir.createDirPath(io, "delete-during-iteration"); + { + var deleting_dir = try dir.openDir(io, "delete-during-iteration", .{ .iterate = true }); + defer deleting_dir.close(io); + const deletion_count = 1536; + for (0..deletion_count) |index| { + var name_buffer: [96]u8 = undefined; + const name = try std.fmt.bufPrint( + &name_buffer, + "delete-{d:0>4}-long-directory-entry-for-multiple-getdents-buffers.txt", + .{index}, + ); + try writeDefaultFile(io, deleting_dir, name, ""); + } + + var deleting = deleting_dir.iterate(); + var deleted: usize = 0; + while (try deleting.next(io)) |entry| { + try deleting_dir.deleteFile(io, entry.name); + deleted += 1; + } + try requireFilesystem( + deleted == deletion_count, + "directory iteration skipped staged entries while deleting them", + ); + } + try dir.deleteDir(io, "delete-during-iteration"); + try writeDefaultFile(io, dir, "created-after-rewind.txt", "created after the initial directory listing\n"); try expectDirectoryEntry(io, dir, "created-after-rewind.txt", .file, true);