Hi, I have some questions about handling of sparse file in cygwin 1.5.5 onwards. cygwin makes a file as a sparse if there is a write request beyond 128 KB from file end. I am not sure whether it is a heuristic or some statistical fact governs the use of 128 KB. Please clarify. The code of fhandler_base::write in fhandler.cc suggest that the check for sparse file runs if there has been a seek before write request. The code performs fine when dealing with local file. For files on network (netapps or samba) write performance degrades because of this code. If a testcase performs seek followed by write then each time code checks whether the file is sparse or not. In that case GetFileSize gets called each time write is performed, which takes good amount of time on network. Is there any alternative to GetFileSize which does not take much time? I searched in MSDN and found none faster than GetFileSize. I found that if i comment GetFileSize then the same application takes half of the time what it was taking before on samba.
The code in question is written below: else if (get_did_lseek ()) { _off64_t actual_length, current_position; DWORD size_high = 0; LONG pos_high = 0; set_did_lseek (0); /* don't do it again */ actual_length = GetFileSize (get_output_handle (), &size_high); actual_length += ((_off64_t) size_high) << 32; current_position = SetFilePointer (get_output_handle (), 0, &pos_high, FILE_CURRENT); current_position += ((_off64_t) pos_high) << 32; if (current_position > actual_length) { if ((get_fs_flags (FILE_SUPPORTS_SPARSE_FILES)) && current_position >= actual_length + (128 * 1024)) { /* If the file systemn supports sparse files and the application is writing after a long seek beyond EOF, convert the file to a sparse file. */ DWORD dw; HANDLE h = get_output_handle (); BOOL r = DeviceIoControl (h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dw, NULL); syscall_printf ("%d = DeviceIoControl(%p, FSCTL_SET_SPARSE, " "NULL, 0, NULL, 0, &dw, NULL)", r, h); } else if (wincap.has_lseek_bug ()) { /* Oops, this is the bug case - Win95 uses whatever is on the disk instead of some known (safe) value, so we must seek back and fill in the gap with zeros. - DJ Note: this bug doesn't happen on NT4, even though the documentation for WriteFile() says that it *may* happen on any OS. */ char zeros[512]; int number_of_zeros_to_write = current_position - actual_length; memset (zeros, 0, 512); SetFilePointer (get_output_handle (), 0, NULL, FILE_END); while (number_of_zeros_to_write > 0) { DWORD zeros_this_time = (number_of_zeros_to_write > 512 ? 512 : number_of_zeros_to_write); DWORD written; if (!WriteFile (get_output_handle (), zeros, zeros_this_time, &written, NULL)) { __seterrno (); if (get_errno () == EPIPE) raise (SIGPIPE); /* This might fail, but it's the best we can hope for */ SetFilePointer (get_output_handle (), current_position, NULL, FILE_BEGIN); return -1; } if (written < zeros_this_time) /* just in case */ { set_errno (ENOSPC); /* This might fail, but it's the best we can hope for */ SetFilePointer (get_output_handle (), current_position, NULL, FILE_BEGIN); return -1; } number_of_zeros_to_write -= written; } } } } regards Vinay -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/