cygwin: unlink: workaround NFS non-ability to move file in certain cases
Under some not quite clear conditions, NFS fails to use its unlink workaround to rename a file to ".nfsXYZ". The problem has been reproduced with the GAWK testext.awk testcase. To workaround this in Cygwin, we now call try_to_bin on NFS, too. For some reason NFS doesn't fail to rename the .cygXYZ file to .nfsXYZ after this Cygwin rename. Fix comment in unlink_nt accordingly. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
5b7921523d
commit
88cfcda06b
@ -501,8 +501,11 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access, ULONG flags)
|
|||||||
Otherwise the below code closes the handle to allow replacing the file. */
|
Otherwise the below code closes the handle to allow replacing the file. */
|
||||||
status = NtSetInformationFile (fh, &io, &disp, sizeof disp,
|
status = NtSetInformationFile (fh, &io, &disp, sizeof disp,
|
||||||
FileDispositionInformation);
|
FileDispositionInformation);
|
||||||
if (status == STATUS_DIRECTORY_NOT_EMPTY)
|
switch (status)
|
||||||
{
|
{
|
||||||
|
case STATUS_SUCCESS:
|
||||||
|
break;
|
||||||
|
case STATUS_DIRECTORY_NOT_EMPTY:
|
||||||
/* Uh oh! This was supposed to be avoided by the check_dir_not_empty
|
/* Uh oh! This was supposed to be avoided by the check_dir_not_empty
|
||||||
test in unlink_nt, but given that the test isn't atomic, this *can*
|
test in unlink_nt, but given that the test isn't atomic, this *can*
|
||||||
happen. Try to move the dir back ASAP. */
|
happen. Try to move the dir back ASAP. */
|
||||||
@ -522,6 +525,34 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access, ULONG flags)
|
|||||||
}
|
}
|
||||||
debug_printf ("Renaming dir %S back to %S failed, status = %y",
|
debug_printf ("Renaming dir %S back to %S failed, status = %y",
|
||||||
&recycler, pc.get_nt_native_path (), status);
|
&recycler, pc.get_nt_native_path (), status);
|
||||||
|
break;
|
||||||
|
case STATUS_FILE_RENAMED:
|
||||||
|
/* On NFS, the subsequent request to set the delete disposition fails
|
||||||
|
with STATUS_FILE_RENAMED. We have to reopen the file, close the
|
||||||
|
original handle, and set the delete disposition on the reopened
|
||||||
|
handle to make sure setting delete disposition works. */
|
||||||
|
InitializeObjectAttributes (&attr, &ro_u_empty, 0, fh, NULL);
|
||||||
|
status = NtOpenFile (&tmp_fh, access, &attr, &io,
|
||||||
|
FILE_SHARE_VALID_FLAGS, flags);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
debug_printf ("NtOpenFile (%S) for reopening in renamed case failed, "
|
||||||
|
"status = %y", pc.get_nt_native_path (), status);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NtClose (fh);
|
||||||
|
fh = tmp_fh;
|
||||||
|
status = NtSetInformationFile (fh, &io, &disp, sizeof disp,
|
||||||
|
FileDispositionInformation);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
debug_printf ("Setting delete disposition %S (%S) in renamed "
|
||||||
|
"case failed, status = %y",
|
||||||
|
&recycler, pc.get_nt_native_path (), status);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug_printf ("Setting delete disposition on %S (%S) failed, status = %y",
|
||||||
|
&recycler, pc.get_nt_native_path (), status);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* In case of success, restore R/O attribute to accommodate hardlinks.
|
/* In case of success, restore R/O attribute to accommodate hardlinks.
|
||||||
That leaves potentially hardlinks around with the R/O bit suddenly
|
That leaves potentially hardlinks around with the R/O bit suddenly
|
||||||
@ -759,15 +790,19 @@ retry_open:
|
|||||||
{
|
{
|
||||||
debug_printf ("Sharing violation when opening %S",
|
debug_printf ("Sharing violation when opening %S",
|
||||||
pc.get_nt_native_path ());
|
pc.get_nt_native_path ());
|
||||||
/* We never call try_to_bin on NFS and NetApp for the follwing reasons:
|
/* We never call try_to_bin on NetApp. Netapp filesystems don't
|
||||||
|
understand the "move and delete" method at all and have all kinds
|
||||||
|
of weird effects. Just setting the delete dispositon usually
|
||||||
|
works fine, though.
|
||||||
|
|
||||||
NFS implements its own mechanism to remove in-use files, which looks
|
NFS implements its own mechanism to remove in-use files, which looks
|
||||||
quite similar to what we do in try_to_bin for remote files.
|
quite similar to what we do in try_to_bin for remote files. However,
|
||||||
|
apparently it doesn't work as desired in all cases. This has been
|
||||||
Netapp filesystems don't understand the "move and delete" method
|
observed when running the gawk 4.1.62++ testcase "testext.awk" under
|
||||||
at all and have all kinds of weird effects. Just setting the delete
|
Windows 10. So for NFS we still call try_to_bin to rename the file,
|
||||||
dispositon usually works fine, though. */
|
at least to make room for subsequent creation of a file with the
|
||||||
if (!pc.fs_is_nfs () && !pc.fs_is_netapp ())
|
same filename. */
|
||||||
|
if (!pc.fs_is_netapp ())
|
||||||
bin_stat = move_to_bin;
|
bin_stat = move_to_bin;
|
||||||
/* If the file is not a directory, of if we didn't set the move_to_bin
|
/* If the file is not a directory, of if we didn't set the move_to_bin
|
||||||
flag, just proceed with the FILE_SHARE_VALID_FLAGS set. */
|
flag, just proceed with the FILE_SHARE_VALID_FLAGS set. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user