[newlib-cygwin/main] Cygwin: pwrite(2): sparsify file

Corinna Vinschen corinna@sourceware.org
Tue Nov 28 10:03:20 GMT 2023


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=f64f3eced8e0f51753bc199f3ba96fab06a54848

commit f64f3eced8e0f51753bc199f3ba96fab06a54848
Author:     Corinna Vinschen <corinna@vinschen.de>
AuthorDate: Mon Nov 27 22:48:50 2023 +0100
Commit:     Corinna Vinschen <corinna@vinschen.de>
CommitDate: Tue Nov 28 10:55:38 2023 +0100

    Cygwin: pwrite(2): sparsify file
    
    write(2) sparsifies a file after an lseek far enough beyond EOF.
    
    Let pwrite(2) sparsify as well if offset is far enough beyond EOF.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/fhandler/disk_file.cc | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc
index b49b25c71ad0..c70afed49f1e 100644
--- a/winsup/cygwin/fhandler/disk_file.cc
+++ b/winsup/cygwin/fhandler/disk_file.cc
@@ -1724,6 +1724,7 @@ fhandler_disk_file::pwrite (void *buf, size_t count, off_t offset, void *aio)
     {
       NTSTATUS status;
       IO_STATUS_BLOCK io;
+      FILE_STANDARD_INFORMATION fsi;
       LARGE_INTEGER off = { QuadPart:offset };
       HANDLE evt = aio ? (HANDLE) aiocb->aio_wincb.event : NULL;
       PIO_STATUS_BLOCK pio = aio ? (PIO_STATUS_BLOCK) &aiocb->aio_wincb : &io;
@@ -1732,6 +1733,25 @@ fhandler_disk_file::pwrite (void *buf, size_t count, off_t offset, void *aio)
       if (prw_handle && (prw_handle_isasync != !!aio))
         NtClose (prw_handle), prw_handle = NULL;
 
+      /* If the file system supports sparse files and the application is
+         writing beyond EOF spanning more than one sparsifiable chunk,
+	 convert the file to a sparse file. */
+      if (pc.support_sparse ()
+	  && !has_attribute (FILE_ATTRIBUTE_SPARSE_FILE)
+	  && NT_SUCCESS (NtQueryInformationFile (get_handle (),
+						 &io, &fsi, sizeof fsi,
+						 FileStandardInformation))
+	  && offset >= fsi.EndOfFile.QuadPart + (128 * 1024))
+	{
+	  NTSTATUS status;
+	  status = NtFsControlFile (get_handle (), NULL, NULL, NULL,
+				    &io, FSCTL_SET_SPARSE, NULL, 0, NULL, 0);
+	  if (NT_SUCCESS (status))
+	    pc.file_attributes (pc.file_attributes ()
+				| FILE_ATTRIBUTE_SPARSE_FILE);
+	  debug_printf ("%y = NtFsControlFile(%S, FSCTL_SET_SPARSE)",
+			status, pc.get_nt_native_path ());
+	}
       if (!prw_handle && prw_open (true, aio))
 	goto non_atomic;
       status = NtWriteFile (prw_handle, evt, NULL, NULL, pio, buf, count,


More information about the Cygwin-cvs mailing list