cleanup: switch drvfs.cpp to use common MountUtil helper (#13890)
* cleanup: switch drvfs.cpp to use common MountUtil helper * adjust mount.drvfs error logging * adjust mount.drvfs error logging --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Ben Hillis committed
Dec 19, 2025 at 13:34 UTC
f4b67e3cb40852f25d527d7b7dd214514fbbaa6f
3 files changed
+34
-53
.gitignore
+1
-1
@@ -44,7 +44,7 @@ bin/
44
*.nupkg
45
build/
46
generated/
47
-Microsoft.WSL.PluginApi.nuspec
47
+*.nuspec
48
test/linux/unit_tests/wsl_unit_tests
49
*.dir/
50
UserConfig.cmake
src/linux/init/drvfs.cpp
+11
-48
@@ -220,11 +220,7 @@ int MountWithRetry(const char* Source, const char* Target, const char* FsType, c
220
221
Routine Description:
222
223
- This routine will perform a mount using the /bin/mount binary, and will
224
- retry it if it fails.
225
-
226
- N.B. This routine is used for virtio-9p and virtiofs which can transiently
227
- fail to mount if the PCI device isn't ready yet.
223
+ This routine performs a mount with retry logic for DrvFs filesystems.
224
225
Arguments:
226
@@ -246,52 +242,19 @@ Return Value:
242
243
try
244
{
249
- int Result;
250
- try
245
+ //
246
+ // Verify the target directory exists before mounting.
247
+ //
248
+
249
+ int Result = access(Target, F_OK);
250
+ if (Result < 0)
251
{
252
- bool PrintWarning = true;
253
- wsl::shared::retry::RetryWithTimeout<void>(
254
- [&]() { THROW_LAST_ERROR_IF(mountutil::MountFilesystem(Source, Target, FsType, Options) < 0); },
255
- std::chrono::milliseconds{100},
256
- std::chrono::seconds{2},
257
- [&]() {
258
- // For virtio-9p, there are two errors that could indicate the PCI device is not ready:
259
- // EBUSY - Returned if all devices with the tag are already in use.
260
- // ENOENT - Returned if there are no devices with the tag, which can happen after the VM first boots.
261
- // In this case, check if the target exists; if it doesn't, ENOENT is for that and there's no reason to retry.
262
- //
263
- // For virtiofs, EINVAL will be returned if the tag is not ready.
264
- auto savedErrno = wil::ResultFromCaughtException();
265
- if (strcmp(FsType, PLAN9_FS_TYPE) == 0)
266
- {
267
- if (errno != EBUSY && (errno != ENOENT || access(Target, F_OK) != 0))
268
- {
269
- errno = savedErrno;
270
- return false;
271
- }
272
- }
273
- else if ((strcmp(FsType, VIRTIO_FS_TYPE) == 0) && (errno != EINVAL))
274
- {
275
- return false;
276
- }
277
-
278
- if (PrintWarning)
279
- {
280
- LOG_WARNING("mount: waiting for virtio device {}", Source);
281
- PrintWarning = false;
282
- }
283
-
284
- return true;
285
- });
286
-
287
- Result = 0;
252
+ LOG_STDERR(errno);
253
}
289
- catch (...)
254
+ else
255
{
291
- errno = wil::ResultFromCaughtException();
292
- auto parsed = mountutil::MountParseFlags(Options);
293
- LOG_ERROR("mount({}, {}, {}, {:#x}, {}) failed: {}", Source, Target, FsType, parsed.MountFlags, parsed.StringOptions.c_str(), strerror(errno));
294
- Result = -1;
256
+ auto Parsed = mountutil::MountParseFlags(Options);
257
+ Result = UtilMount(Source, Target, FsType, Parsed.MountFlags, Parsed.StringOptions.c_str(), std::chrono::seconds{2});
258
}
259
260
if (ExitCode)
src/linux/init/util.cpp
+22
-4
@@ -1706,8 +1706,10 @@ Return Value:
1706
//
1707
// Mount the device to the mount point.
1708
//
1709
- // N.B. The mount operation is only retried if the mount source does not yet exist,
1710
- // which can happen when hot-added devices are not yet available in the guest.
1709
+ // N.B. The mount operation is retried if:
1710
+ // - The mount source does not yet exist (hot-added devices)
1711
+ // - For Plan9 (9p): device is busy or not found
1712
+ // - For VirtioFS: invalid tag (device not ready)
1713
//
1714
1715
try
@@ -1720,7 +1722,23 @@ Return Value:
1722
TimeoutSeconds.value(),
1723
[&]() {
1724
errno = wil::ResultFromCaughtException();
1723
- return errno == ENOENT || errno == ENXIO || errno == EIO;
1725
+
1726
+ // Generic device not ready errors
1727
+ if (errno == ENXIO || errno == EIO || errno == ENOENT)
1728
+ {
1729
+ return true;
1730
+ }
1731
+
1732
+ // Filesystem-specific device readiness errors
1733
+ if (Type != nullptr)
1734
+ {
1735
+ if ((strcmp(Type, PLAN9_FS_TYPE) == 0 && errno == EBUSY) || (strcmp(Type, VIRTIO_FS_TYPE) == 0 && errno == EINVAL))
1736
+ {
1737
+ return true;
1738
+ }
1739
+ }
1740
+
1741
+ return false;
1742
});
1743
}
1744
else
@@ -1731,7 +1749,7 @@ Return Value:
1749
catch (...)
1750
{
1751
errno = wil::ResultFromCaughtException();
1734
- LOG_ERROR("mount({}, {}, {}, 0x{}x, {}) failed {}", Source, Target, Type, MountFlags, Options, errno);
1752
+ LOG_ERROR("mount({}, {}, {}, {:#x}, {}) failed {}", Source, Target, Type, MountFlags, Options, errno);
1753
return -errno;
1754
}
1755