Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1893)

Unified Diff: base/test_file_util_win.cc

Issue 12833: Making sure that the buffer we use with ReadFile/WriteFile is page... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/test_file_util_win.cc
===================================================================
--- base/test_file_util_win.cc (revision 6152)
+++ base/test_file_util_win.cc (working copy)
@@ -13,31 +13,88 @@
namespace file_util {
+// We could use GetSystemInfo to get the page size, but this serves
+// our purpose fine since 4K is the page size on x86 as well as x64.
+static const ptrdiff_t kPageSize = 4096;
+
bool EvictFileFromSystemCache(const wchar_t* file) {
// Request exclusive access to the file and overwrite it with no buffering.
- ScopedHandle hfile(
+ ScopedHandle file_handle(
CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_NO_BUFFERING,
- NULL));
- if (!hfile)
+ OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL));
+ if (!file_handle)
return false;
+ // Get some attributes to restore later.
+ BY_HANDLE_FILE_INFORMATION bhi = {0};
+ CHECK(::GetFileInformationByHandle(file_handle, &bhi));
+
// Execute in chunks. It could be optimized. We want to do few of these since
- // these opterations will be slow without the cache.
- char buffer[4096];
+ // these operations will be slow without the cache.
+
+ // Non-buffered reads and writes need to be sector aligned and since sector
+ // sizes typically range from 512-4096 bytes, we just use the page size.
+ // The buffer size is twice the size of a page (minus one) since we need to
+ // get an aligned pointer into the buffer that we can use.
+ char buffer[2 * kPageSize - 1];
+ // Get an aligned pointer into buffer.
+ char* read_write = reinterpret_cast<char*>(
+ reinterpret_cast<ptrdiff_t>(buffer + kPageSize - 1) & ~(kPageSize - 1));
+ DCHECK((reinterpret_cast<int>(read_write) % kPageSize) == 0);
+
+ // If the file size isn't a multiple of kPageSize, we'll need special
+ // processing.
+ bool file_is_page_aligned = true;
int total_bytes = 0;
- DWORD bytes_read;
+ DWORD bytes_read, bytes_written;
for (;;) {
bytes_read = 0;
- ReadFile(hfile, buffer, sizeof(buffer), &bytes_read, NULL);
+ ReadFile(file_handle, read_write, kPageSize, &bytes_read, NULL);
if (bytes_read == 0)
break;
- SetFilePointer(hfile, total_bytes, 0, FILE_BEGIN);
- if (!WriteFile(hfile, buffer, bytes_read, &bytes_read, NULL))
+ if (bytes_read < kPageSize) {
+ // Zero out the remaining part of the buffer.
+ // WriteFile will fail if we provide a buffer size that isn't a
+ // sector multiple, so we'll have to write the entire buffer with
+ // padded zeros and then use SetEndOfFile to truncate the file.
+ ZeroMemory(read_write + bytes_read, kPageSize - bytes_read);
+ file_is_page_aligned = false;
+ }
+
+ // Move back to the position we just read from.
+ // Note that SetFilePointer will also fail if total_bytes isn't sector
+ // aligned, but that shouldn't happen here.
+ DCHECK((total_bytes % kPageSize) == 0);
+ SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN);
+ if (!WriteFile(file_handle, read_write, kPageSize, &bytes_written, NULL) ||
+ bytes_written != kPageSize) {
+ DCHECK(false);
return false;
+ }
+
total_bytes += bytes_read;
+
+ // If this is false, then we just processed the last portion of the file.
+ if (!file_is_page_aligned)
+ break;
}
+
+ if (!file_is_page_aligned) {
+ // The size of the file isn't a multiple of the page size, so we'll have
+ // to open the file again, this time without the FILE_FLAG_NO_BUFFERING
+ // flag and use SetEndOfFile to mark EOF.
+ file_handle.Set(CreateFile(file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+ 0, NULL));
+ CHECK(SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN) !=
+ INVALID_SET_FILE_POINTER);
+ CHECK(::SetEndOfFile(file_handle));
+ }
+
+ // Restore the file attributes.
+ CHECK(::SetFileTime(file_handle, &bhi.ftCreationTime, &bhi.ftLastAccessTime,
+ &bhi.ftLastWriteTime));
+
return true;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698