1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

[iso] improve write performance during ISO extraction

* Now preallocate the file size for each extracted file, to help the target
  filesystem avoid fragmentation issues and thus increase writing speed.
* Closes #1170
This commit is contained in:
Mattiwatti 2018-06-24 00:59:36 +02:00 committed by Pete Batard
parent dbc92e3adc
commit d4a4506b16
2 changed files with 55 additions and 40 deletions

View file

@ -361,6 +361,15 @@ static void __inline set_directory_timestamp(char* path, LPFILETIME creation, LP
safe_closehandle(dir_handle); safe_closehandle(dir_handle);
} }
// Preallocates the target size of a newly created file in order to prevent fragmentation from repeated writes
static void __inline preallocate_filesize(HANDLE hFile, int64_t file_length)
{
SetFileInformationByHandle(hFile, FileEndOfFileInfo, &file_length, sizeof(file_length));
// FileAllocationInfo does not require the size to be a multiple of the cluster size; the FS driver takes care of this.
SetFileInformationByHandle(hFile, FileAllocationInfo, &file_length, sizeof(file_length));
}
// Returns 0 on success, nonzero on error // Returns 0 on success, nonzero on error
static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path) static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path)
{ {
@ -440,23 +449,26 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
uprintf(stupid_antivirus); uprintf(stupid_antivirus);
else else
goto out; goto out;
} else while (file_length > 0) { } else {
if (FormatStatus) goto out; preallocate_filesize(file_handle, file_length);
memset(buf, 0, UDF_BLOCKSIZE); while (file_length > 0) {
read = udf_read_block(p_udf_dirent, buf, 1); if (FormatStatus) goto out;
if (read < 0) { memset(buf, 0, UDF_BLOCKSIZE);
uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]); read = udf_read_block(p_udf_dirent, buf, 1);
goto out; if (read < 0) {
uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]);
goto out;
}
buf_size = (DWORD)MIN(file_length, read);
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
if (!r) {
uprintf(" Error writing file: %s", WindowsErrorString());
goto out;
}
file_length -= read;
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks);
} }
buf_size = (DWORD)MIN(file_length, read);
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
if (!r) {
uprintf(" Error writing file: %s", WindowsErrorString());
goto out;
}
file_length -= read;
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks);
} }
if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)), if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)),
to_filetime(udf_get_access_time(p_udf_dirent)), to_filetime(udf_get_modification_time(p_udf_dirent))))) to_filetime(udf_get_access_time(p_udf_dirent)), to_filetime(udf_get_modification_time(p_udf_dirent)))))
@ -586,26 +598,29 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
uprintf(stupid_antivirus); uprintf(stupid_antivirus);
else else
goto out; goto out;
} else for (j=0; j<p_statbuf->extents; j++) { } else {
extent_length = p_statbuf->extsize[j]; preallocate_filesize(file_handle, file_length);
for (i=0; extent_length>0; i++) { for (j=0; j<p_statbuf->extents; j++) {
if (FormatStatus) goto out; extent_length = p_statbuf->extsize[j];
memset(buf, 0, ISO_BLOCKSIZE); for (i=0; extent_length>0; i++) {
lsn = p_statbuf->lsn[j] + (lsn_t)i; if (FormatStatus) goto out;
if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { memset(buf, 0, ISO_BLOCKSIZE);
uprintf(" Error reading ISO9660 file %s at LSN %lu", lsn = p_statbuf->lsn[j] + (lsn_t)i;
psz_iso_name, (long unsigned int)lsn); if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) {
goto out; uprintf(" Error reading ISO9660 file %s at LSN %lu",
psz_iso_name, (long unsigned int)lsn);
goto out;
}
buf_size = (DWORD)MIN(extent_length, ISO_BLOCKSIZE);
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
if (!r) {
uprintf(" Error writing file: %s", WindowsErrorString());
goto out;
}
extent_length -= ISO_BLOCKSIZE;
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks);
} }
buf_size = (DWORD)MIN(extent_length, ISO_BLOCKSIZE);
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
if (!r) {
uprintf(" Error writing file: %s", WindowsErrorString());
goto out;
}
extent_length -= ISO_BLOCKSIZE;
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks);
} }
} }
if (preserve_timestamps) { if (preserve_timestamps) {

View file

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326 IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.1.1322" CAPTION "Rufus 3.1.1323"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0 FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -389,8 +389,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,1,1322,0 FILEVERSION 3,1,1323,0
PRODUCTVERSION 3,1,1322,0 PRODUCTVERSION 3,1,1323,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -407,13 +407,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.1.1322" VALUE "FileVersion", "3.1.1323"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe" VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.1.1322" VALUE "ProductVersion", "3.1.1323"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"