diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2012-12-14 10:45:29 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2012-12-14 10:45:29 +0000 |
commit | 05297cca5fe43585ba7f8b6299d318b8b31b634a (patch) | |
tree | 36ab6968209c5f6c4a5fb2344dbf313f68612720 /winsup | |
parent | 60f901f4a9e7ab9e6030cc38f297b140233640ea (diff) | |
download | newlib-05297cca5fe43585ba7f8b6299d318b8b31b634a.zip newlib-05297cca5fe43585ba7f8b6299d318b8b31b634a.tar.gz newlib-05297cca5fe43585ba7f8b6299d318b8b31b634a.tar.bz2 |
* 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.
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/ChangeLog | 18 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.cc | 17 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_disk_file.cc | 7 | ||||
-rw-r--r-- | winsup/cygwin/include/sys/mount.h | 4 | ||||
-rw-r--r-- | winsup/cygwin/mount.cc | 4 | ||||
-rw-r--r-- | winsup/cygwin/path.h | 10 |
6 files changed, 48 insertions, 12 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f9bca39..9311dd8 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -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. diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index b84263d..169ff95 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -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 diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 92bb589..ca4f902 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -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 ()); } diff --git a/winsup/cygwin/include/sys/mount.h b/winsup/cygwin/include/sys/mount.h index 0680e45..94620f9 100644 --- a/winsup/cygwin/include/sys/mount.h +++ b/winsup/cygwin/include/sys/mount.h @@ -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" */ diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index 70603d7..160fc4d 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -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"); diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index cb7480a..a9e8b7c 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -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 ();} |