* fhandler.cc (fhandler_base::write): Don't attempt to sparsify
an already sparse file. Drop check for FILE_SUPPORTS_SPARSE_FILES flag. Explicitely set FILE_ATTRIBUTE_SPARSE_FILE attribute in cached attributes. (fhandler_base::lseek): Only set did_lseek if sparseness is supported. * fhandler_disk_file.cc (fhandler_disk_file::ftruncate): Don't attempt to sparsify an already sparse file. Explicitely set FILE_ATTRIBUTE_SPARSE_FILE attribute in cached attributes. * mount.cc (oopt): Add "sparse" flag. (fillout_mntent): Ditto. * path.h (enum path_types): Add PATH_SPARSE. (path_conv::support_sparse): New method. (path_conv::fs_flags): Constify. (path_conv::fs_name_len): Ditto. include/sys/mount.h: Replace unused MOUNT_MIXED flag with MOUNT_SPARSE.
This commit is contained in:
		| @@ -1,3 +1,21 @@ | ||||
| 2012-12-14  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* fhandler.cc (fhandler_base::write): Don't attempt to sparsify | ||||
| 	an already sparse file.  Drop check for FILE_SUPPORTS_SPARSE_FILES | ||||
| 	flag.  Explicitely set FILE_ATTRIBUTE_SPARSE_FILE attribute in | ||||
| 	cached attributes. | ||||
| 	(fhandler_base::lseek): Only set did_lseek if sparseness is supported. | ||||
| 	* fhandler_disk_file.cc (fhandler_disk_file::ftruncate): Don't attempt | ||||
| 	to sparsify an already sparse file.  Explicitely set | ||||
| 	FILE_ATTRIBUTE_SPARSE_FILE attribute in cached attributes. | ||||
| 	* mount.cc (oopt): Add "sparse" flag. | ||||
| 	(fillout_mntent): Ditto. | ||||
| 	* path.h (enum path_types): Add PATH_SPARSE. | ||||
| 	(path_conv::support_sparse): New method. | ||||
| 	(path_conv::fs_flags): Constify. | ||||
| 	(path_conv::fs_name_len): Ditto. | ||||
| 	include/sys/mount.h: Replace unused MOUNT_MIXED flag with MOUNT_SPARSE. | ||||
|  | ||||
| 2012-12-10  Christopher Faylor  <me.cygwin2012@cgf.cx> | ||||
|  | ||||
| 	* sigproc.h (sig_send): Accept tid as argument #3.  Default to NULL. | ||||
|   | ||||
| @@ -817,15 +817,17 @@ ssize_t __stdcall | ||||
| fhandler_base::write (const void *ptr, size_t len) | ||||
| { | ||||
|   int res; | ||||
|   IO_STATUS_BLOCK io; | ||||
|   FILE_POSITION_INFORMATION fpi; | ||||
|   FILE_STANDARD_INFORMATION fsi; | ||||
|  | ||||
|   if (did_lseek ()) | ||||
|     { | ||||
|       IO_STATUS_BLOCK io; | ||||
|       FILE_POSITION_INFORMATION fpi; | ||||
|       FILE_STANDARD_INFORMATION fsi; | ||||
|  | ||||
|       did_lseek (false); /* don't do it again */ | ||||
|  | ||||
|       if (!(get_flags () & O_APPEND) | ||||
| 	  && !has_attribute (FILE_ATTRIBUTE_SPARSE_FILE) | ||||
| 	  && NT_SUCCESS (NtQueryInformationFile (get_output_handle (), | ||||
| 						 &io, &fsi, sizeof fsi, | ||||
| 						 FileStandardInformation)) | ||||
| @@ -833,8 +835,7 @@ fhandler_base::write (const void *ptr, size_t len) | ||||
| 						 &io, &fpi, sizeof fpi, | ||||
| 						 FilePositionInformation)) | ||||
| 	  && fpi.CurrentByteOffset.QuadPart | ||||
| 	     >= fsi.EndOfFile.QuadPart + (128 * 1024) | ||||
| 	  && (pc.fs_flags () & FILE_SUPPORTS_SPARSE_FILES)) | ||||
| 	     >= fsi.EndOfFile.QuadPart + (128 * 1024)) | ||||
| 	{ | ||||
| 	  /* If the file system supports sparse files and the application | ||||
| 	     is writing after a long seek beyond EOF, convert the file to | ||||
| @@ -842,6 +843,9 @@ fhandler_base::write (const void *ptr, size_t len) | ||||
| 	  NTSTATUS status; | ||||
| 	  status = NtFsControlFile (get_output_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 ("%p = NtFsControlFile(%S, FSCTL_SET_SPARSE)", | ||||
| 			status, pc.get_nt_native_path ()); | ||||
| 	} | ||||
| @@ -1071,7 +1075,8 @@ fhandler_base::lseek (_off64_t offset, int whence) | ||||
|  | ||||
|   /* When next we write(), we will check to see if *this* seek went beyond | ||||
|      the end of the file and if so, potentially sparsify the file. */ | ||||
|   did_lseek (true); | ||||
|   if (pc.support_sparse ()) | ||||
|     did_lseek (true); | ||||
|  | ||||
|   /* If this was a SEEK_CUR with offset 0, we still might have | ||||
|      readahead that we have to take into account when calculating | ||||
|   | ||||
| @@ -1189,12 +1189,15 @@ fhandler_disk_file::ftruncate (_off64_t length, bool allow_truncate) | ||||
|       feofi.EndOfFile.QuadPart = length; | ||||
|       /* Create sparse files only when called through ftruncate, not when | ||||
| 	 called through posix_fallocate. */ | ||||
|       if (allow_truncate | ||||
| 	  && (pc.fs_flags () & FILE_SUPPORTS_SPARSE_FILES) | ||||
|       if (allow_truncate && pc.support_sparse () | ||||
| 	  && !has_attribute (FILE_ATTRIBUTE_SPARSE_FILE) | ||||
| 	  && length >= fsi.EndOfFile.QuadPart + (128 * 1024)) | ||||
| 	{ | ||||
| 	  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); | ||||
| 	  syscall_printf ("%p = NtFsControlFile(%S, FSCTL_SET_SPARSE)", | ||||
| 			  status, pc.get_nt_native_path ()); | ||||
| 	} | ||||
|   | ||||
| @@ -26,8 +26,8 @@ enum | ||||
| 					   device mount */ | ||||
|   MOUNT_CYGWIN_EXEC =	0x00040,	/* file or directory is or contains a | ||||
| 					   cygwin executable */ | ||||
|   MOUNT_MIXED	=	0x00080,	/* reads are text, writes are binary | ||||
| 					   not yet implemented */ | ||||
|   MOUNT_SPARSE	=	0x00080,	/* Support automatic sparsifying of | ||||
| 					   files. */ | ||||
|   MOUNT_NOTEXEC =	0x00100,	/* don't check files for executable magic */ | ||||
|   MOUNT_DEVFS =		0x00200,	/* /device "filesystem" */ | ||||
|   MOUNT_PROC =		0x00400,	/* /proc "filesystem" */ | ||||
|   | ||||
| @@ -1028,6 +1028,7 @@ struct opt | ||||
|   {"override", MOUNT_OVERRIDE, 0}, | ||||
|   {"posix=0", MOUNT_NOPOSIX, 0}, | ||||
|   {"posix=1", MOUNT_NOPOSIX, 1}, | ||||
|   {"sparse", MOUNT_SPARSE, 0}, | ||||
|   {"text", MOUNT_BINARY, 1}, | ||||
|   {"user", MOUNT_SYSTEM, 1} | ||||
| }; | ||||
| @@ -1667,6 +1668,9 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags) | ||||
|   if (flags & MOUNT_NOPOSIX) | ||||
|     strcat (_my_tls.locals.mnt_opts, (char *) ",posix=0"); | ||||
|  | ||||
|   if (flags & MOUNT_SPARSE) | ||||
|     strcat (_my_tls.locals.mnt_opts, (char *) ",sparse"); | ||||
|  | ||||
|   if (!(flags & MOUNT_SYSTEM))		/* user mount */ | ||||
|     strcat (_my_tls.locals.mnt_opts, (char *) ",user"); | ||||
|  | ||||
|   | ||||
| @@ -70,6 +70,7 @@ enum path_types | ||||
|   PATH_EXEC		= MOUNT_EXEC, | ||||
|   PATH_NOTEXEC		= MOUNT_NOTEXEC, | ||||
|   PATH_CYGWIN_EXEC	= MOUNT_CYGWIN_EXEC, | ||||
|   PATH_SPARSE		= MOUNT_SPARSE, | ||||
|   PATH_RO		= MOUNT_RO, | ||||
|   PATH_NOACL		= MOUNT_NOACL, | ||||
|   PATH_NOPOSIX		= MOUNT_NOPOSIX, | ||||
| @@ -153,6 +154,11 @@ class path_conv | ||||
|   bool has_acls () const {return !(path_flags & PATH_NOACL) && fs.has_acls (); } | ||||
|   bool hasgood_inode () const {return !(path_flags & PATH_IHASH); } | ||||
|   bool isgood_inode (__ino64_t ino) const; | ||||
|   bool support_sparse () const | ||||
|   { | ||||
|     return (path_flags & PATH_SPARSE) | ||||
| 	   && (fs_flags () & FILE_SUPPORTS_SPARSE_FILES); | ||||
|   } | ||||
|   int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;} | ||||
|   int has_dos_filenames_only () const {return path_flags & PATH_DOS;} | ||||
|   int has_buggy_open () const {return fs.has_buggy_open ();} | ||||
| @@ -342,8 +348,8 @@ class path_conv | ||||
|   short get_unitn () const {return dev.get_minor ();} | ||||
|   DWORD file_attributes () const {return fileattr;} | ||||
|   void file_attributes (DWORD new_attr) {fileattr = new_attr;} | ||||
|   DWORD fs_flags () {return fs.flags ();} | ||||
|   DWORD fs_name_len () {return fs.name_len ();} | ||||
|   DWORD fs_flags () const {return fs.flags ();} | ||||
|   DWORD fs_name_len () const {return fs.name_len ();} | ||||
|   bool fs_got_fs () const { return fs.got_fs (); } | ||||
|   bool fs_is_fat () const {return fs.is_fat ();} | ||||
|   bool fs_is_ntfs () const {return fs.is_ntfs ();} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user