]> wimlib.net Git - wimlib/blobdiff - src/wimboot.c
Add warning messages and retries around FSCTL_SET_EXTERNAL_BACKING
[wimlib] / src / wimboot.c
index 3562890d7636b08d4ea686df1fe5f9e26002deb7..b1db0f8c5feac1f842d77c99c1d36610e2ca2885 100644 (file)
@@ -121,7 +121,7 @@ query_partition_and_disk_info(const wchar_t *path,
                                 extents, extents_size))
                        break;
                if (GetLastError() != ERROR_MORE_DATA) {
-                       ERROR("\"%ls\": Can't get volume extent info (err="PRIu32")",
+                       ERROR("\"%ls\": Can't get volume extent info (err=%"PRIu32")",
                              vol_name, (u32)GetLastError());
                        ret = WIMLIB_ERR_READ;
                        goto out;
@@ -1059,8 +1059,6 @@ out:
  *
  * @h
  *     Open handle to the file, with GENERIC_WRITE access.
- * @printable_name
- *     Printable representation of the path to the file.
  * @lte
  *     Unnamed data stream of the file.
  * @data_source_id
@@ -1071,11 +1069,10 @@ out:
  *     %true if the WOF driver appears to be available and working; %false if
  *     not.
  *
- * Returns 0 on success, or a positive error code on failure.
+ * Returns %true on success, or %false on failure with GetLastError() set.
  */
-int
+bool
 wimboot_set_pointer(HANDLE h,
-                   const wchar_t *printable_name,
                    const struct wim_lookup_table_entry *lte,
                    u64 data_source_id,
                    const u8 lookup_table_hash[SHA1_HASH_SIZE],
@@ -1087,12 +1084,15 @@ wimboot_set_pointer(HANDLE h,
        if (wof_running) {
                /* The WOF driver is running.  We can create the reparse point
                 * using FSCTL_SET_EXTERNAL_BACKING.  */
-
+               unsigned int max_retries = 4;
                struct {
                        struct wof_external_info wof_info;
                        struct wim_provider_external_info wim_info;
                } in;
 
+       retry:
+               memset(&in, 0, sizeof(in));
+
                in.wof_info.version = WOF_CURRENT_VERSION;
                in.wof_info.provider = WOF_PROVIDER_WIM;
 
@@ -1106,7 +1106,22 @@ wimboot_set_pointer(HANDLE h,
                if (!DeviceIoControl(h, FSCTL_SET_EXTERNAL_BACKING,
                                     &in, sizeof(in), NULL, 0,
                                     &bytes_returned, NULL))
-                       goto fail;
+               {
+                       /* Try to track down sporadic errors  */
+                       if (wimlib_print_errors) {
+                               WARNING("FSCTL_SET_EXTERNAL_BACKING failed (err=%u); data was %zu bytes:",
+                                       (u32)GetLastError(), sizeof(in));
+                               print_byte_field((const u8 *)&in, sizeof(in), wimlib_error_file);
+                               putc('\n', wimlib_error_file);
+                       }
+                       if (--max_retries) {
+                               WARNING("Retrying after 100ms...");
+                               Sleep(100);
+                               goto retry;
+                       }
+                       WARNING("Too many retries; returning failure");
+                       return false;
+               }
        } else {
 
                /* The WOF driver is running.  We need to create the reparse
@@ -1144,7 +1159,7 @@ wimboot_set_pointer(HANDLE h,
 
                if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT,
                                     &in, sizeof(in), NULL, 0, &bytes_returned, NULL))
-                       goto fail;
+                       return false;
 
                /* We also need to create an unnamed data stream of the correct
                 * size.  Otherwise the file shows up as zero length.  It can be
@@ -1152,25 +1167,18 @@ wimboot_set_pointer(HANDLE h,
                 * are unimportant.  */
                if (!DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0,
                                     &bytes_returned, NULL))
-                       goto fail;
+                       return false;
 
                if (!SetFilePointerEx(h,
                                      (LARGE_INTEGER){ .QuadPart = lte->size},
                                      NULL, FILE_BEGIN))
-                       goto fail;
+                       return false;
 
                if (!SetEndOfFile(h))
-                       goto fail;
+                       return false;
        }
 
-       return 0;
-
-fail:
-       err = GetLastError();
-       set_errno_from_win32_error(err);
-       ERROR_WITH_ERRNO("\"%ls\": Couldn't set WIMBoot pointer data "
-                        "(err=%"PRIu32")", printable_name, (u32)err);
-       return WIMLIB_ERR_WIMBOOT;
+       return true;
 }
 
 #endif /* __WIN32__ */