| ... | @@ -7685,6 +7685,8 @@ fn dirRenameWindowsInner( | ... | @@ -7685,6 +7685,8 @@ fn dirRenameWindowsInner( |
| 7685 | defer w.CloseHandle(src_fd); | 7685 | defer w.CloseHandle(src_fd); |
| 7686 | | 7686 | |
| 7687 | var rc: w.NTSTATUS = undefined; | 7687 | var rc: w.NTSTATUS = undefined; |
| | 7688 | var attempt: u5 = 0; |
| | 7689 | |
| 7688 | // FileRenameInformationEx has varying levels of support: | 7690 | // FileRenameInformationEx has varying levels of support: |
| 7689 | // - FILE_RENAME_INFORMATION_EX requires >= win10_rs1 | 7691 | // - FILE_RENAME_INFORMATION_EX requires >= win10_rs1 |
| 7690 | // (INVALID_INFO_CLASS is returned if not supported) | 7692 | // (INVALID_INFO_CLASS is returned if not supported) |
| ... | @@ -7708,24 +7710,43 @@ fn dirRenameWindowsInner( | ... | @@ -7708,24 +7710,43 @@ fn dirRenameWindowsInner( |
| 7708 | }); | 7710 | }); |
| 7709 | var io_status_block: w.IO_STATUS_BLOCK = undefined; | 7711 | var io_status_block: w.IO_STATUS_BLOCK = undefined; |
| 7710 | const rename_info_buf = rename_info.toBuffer(); | 7712 | const rename_info_buf = rename_info.toBuffer(); |
| 7711 | rc = w.ntdll.NtSetInformationFile( | 7713 | var syscall: Syscall = try .start(); |
| 7712 | src_fd, | 7714 | while (true) { |
| 7713 | &io_status_block, | 7715 | rc = w.ntdll.NtSetInformationFile( |
| 7714 | rename_info_buf.ptr, | 7716 | src_fd, |
| 7715 | @intCast(rename_info_buf.len), | 7717 | &io_status_block, |
| 7716 | .RenameEx, | 7718 | rename_info_buf.ptr, |
| 7717 | ); | 7719 | @intCast(rename_info_buf.len), |
| 7718 | switch (rc) { | 7720 | .RenameEx, |
| 7719 | .SUCCESS => return, | 7721 | ); |
| 7720 | // The filesystem does not support FileDispositionInformationEx | 7722 | switch (rc) { |
| 7721 | .INVALID_PARAMETER, | 7723 | // For all other statuses, fall down to the switch below to handle them. |
| 7722 | // The operating system does not support FileDispositionInformationEx | 7724 | else => { |
| 7723 | .INVALID_INFO_CLASS, | 7725 | syscall.finish(); |
| 7724 | // The operating system does not support one of the flags | 7726 | break :need_fallback false; |
| 7725 | .NOT_SUPPORTED, | 7727 | }, |
| 7726 | => break :need_fallback true, | 7728 | .CANCELLED => try syscall.checkCancel(), |
| 7727 | // For all other statuses, fall down to the switch below to handle them. | 7729 | // The filesystem does not support FileDispositionInformationEx |
| 7728 | else => break :need_fallback false, | 7730 | .INVALID_PARAMETER, |
| | 7731 | // The operating system does not support FileDispositionInformationEx |
| | 7732 | .INVALID_INFO_CLASS, |
| | 7733 | // The operating system does not support one of the flags |
| | 7734 | .NOT_SUPPORTED, |
| | 7735 | => { |
| | 7736 | syscall.finish(); |
| | 7737 | break :need_fallback true; |
| | 7738 | }, |
| | 7739 | .ACCESS_DENIED => { |
| | 7740 | syscall.finish(); |
| | 7741 | if (max_windows_kernel_bug_retries - attempt == 0) break :need_fallback false; |
| | 7742 | try parking_sleep.sleep(.{ .duration = .{ |
| | 7743 | .raw = .fromMilliseconds((@as(u32, 1) << attempt) >> 1), |
| | 7744 | .clock = .awake, |
| | 7745 | } }); |
| | 7746 | attempt += 1; |
| | 7747 | syscall = try .start(); |
| | 7748 | }, |
| | 7749 | } |
| 7729 | } | 7750 | } |
| 7730 | }; | 7751 | }; |
| 7731 | | 7752 | |
| ... | @@ -7737,13 +7758,33 @@ fn dirRenameWindowsInner( | ... | @@ -7737,13 +7758,33 @@ fn dirRenameWindowsInner( |
| 7737 | }); | 7758 | }); |
| 7738 | var io_status_block: w.IO_STATUS_BLOCK = undefined; | 7759 | var io_status_block: w.IO_STATUS_BLOCK = undefined; |
| 7739 | const rename_info_buf = rename_info.toBuffer(); | 7760 | const rename_info_buf = rename_info.toBuffer(); |
| 7740 | rc = w.ntdll.NtSetInformationFile( | 7761 | var syscall: Syscall = try .start(); |
| 7741 | src_fd, | 7762 | while (true) { |
| 7742 | &io_status_block, | 7763 | rc = w.ntdll.NtSetInformationFile( |
| 7743 | rename_info_buf.ptr, | 7764 | src_fd, |
| 7744 | @intCast(rename_info_buf.len), | 7765 | &io_status_block, |
| 7745 | .Rename, | 7766 | rename_info_buf.ptr, |
| 7746 | ); | 7767 | @intCast(rename_info_buf.len), |
| | 7768 | .Rename, |
| | 7769 | ); |
| | 7770 | switch (rc) { |
| | 7771 | else => { |
| | 7772 | syscall.finish(); |
| | 7773 | break; |
| | 7774 | }, |
| | 7775 | .CANCELLED => try syscall.checkCancel(), |
| | 7776 | .ACCESS_DENIED => { |
| | 7777 | syscall.finish(); |
| | 7778 | if (max_windows_kernel_bug_retries - attempt == 0) break; |
| | 7779 | try parking_sleep.sleep(.{ .duration = .{ |
| | 7780 | .raw = .fromMilliseconds((@as(u32, 1) << attempt) >> 1), |
| | 7781 | .clock = .awake, |
| | 7782 | } }); |
| | 7783 | attempt += 1; |
| | 7784 | syscall = try .start(); |
| | 7785 | }, |
| | 7786 | } |
| | 7787 | } |
| 7747 | } | 7788 | } |
| 7748 | | 7789 | |
| 7749 | switch (rc) { | 7790 | switch (rc) { |