Skip to content

Commit 081388c

Browse files
benhillisBen Hillis
andauthored
virtiofs: add support for statx syscall (#14087)
* virtiofs: add support for statx syscall * add statx drvfs test * skip statx drvfs test on wsl1 * skip stax tests on smb and fat --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
1 parent d8cd707 commit 081388c

File tree

3 files changed

+191
-14
lines changed

3 files changed

+191
-14
lines changed

packages.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<package id="Microsoft.WSL.bsdtar" version="0.0.2-2" />
1919
<package id="Microsoft.WSL.Dependencies.amd64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
2020
<package id="Microsoft.WSL.Dependencies.arm64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
21-
<package id="Microsoft.WSL.DeviceHost" version="1.1.8-0" />
21+
<package id="Microsoft.WSL.DeviceHost" version="1.1.10-0" />
2222
<package id="Microsoft.WSL.Kernel" version="6.6.114.1-1" targetFramework="native" />
2323
<package id="Microsoft.WSL.LinuxSdk" version="1.20.0" targetFramework="native" />
2424
<package id="Microsoft.WSL.TestDistro" version="2.5.7-47" />

test/linux/unit_tests/drvfs.c

Lines changed: 179 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ LXT_VARIATION_HANDLER DrvFsTestFatWslPath;
156156

157157
LXT_VARIATION_HANDLER DrvFsTestFstat;
158158

159+
LXT_VARIATION_HANDLER DrvFsTestStatx;
160+
159161
LXT_VARIATION_HANDLER DrvFsTestGetDents64Alignment;
160162

161163
LXT_VARIATION_HANDLER DrvFsTestGetDentsAlignment;
@@ -246,6 +248,7 @@ static const LXT_VARIATION g_LxtVariations[] = {
246248
{"DrvFs - hard links", DrvFsTestHardLinks},
247249
{"DrvFs - block count", DrvFsTestBlockCount},
248250
{"DrvFs - fstat", DrvFsTestFstat},
251+
{"DrvFs - statx", DrvFsTestStatx},
249252
{"DrvFs - reopen unlinked file", DrvFsTestReopenUnlinked},
250253
{"DrvFs - delete loop", DrvFsTestDeleteLoop},
251254
{"DrvFs - seek", DrvFsTestSeek},
@@ -336,6 +339,7 @@ static const LXT_VARIATION g_LxtMetadataVariations[] = {
336339
{"DrvFs - hard links", DrvFsTestHardLinks},
337340
{"DrvFs - block count", DrvFsTestBlockCount},
338341
{"DrvFs - fstat", DrvFsTestFstat},
342+
{"DrvFs - statx", DrvFsTestStatx},
339343
{"DrvFs - reopen unlinked file", DrvFsTestReopenUnlinked},
340344
{"DrvFs - delete loop", DrvFsTestDeleteLoop},
341345
{"DrvFs - seek", DrvFsTestSeek},
@@ -368,6 +372,7 @@ static const LXT_VARIATION g_LxtReFsVariations[] = {
368372
{"DrvFs - hard links", DrvFsTestHardLinks},
369373
{"DrvFs - block count", DrvFsTestBlockCount},
370374
{"DrvFs - fstat", DrvFsTestFstat},
375+
{"DrvFs - statx", DrvFsTestStatx},
371376
{"DrvFs - reopen unlinked file", DrvFsTestReopenUnlinked},
372377
{"DrvFs - delete loop", DrvFsTestDeleteLoop},
373378
{"DrvFs - seek", DrvFsTestSeek},
@@ -1389,13 +1394,6 @@ Return Value:
13891394

13901395
int Result;
13911396

1392-
if (g_LxtFsInfo.FsType == LxtFsTypeVirtioFs)
1393-
{
1394-
LxtLogInfo("TODO: debug this test on virtiofs.");
1395-
Result = 0;
1396-
goto ErrorExit;
1397-
}
1398-
13991397
LxtCheckErrno(LxtFsDeleteCurrentWorkingDirectoryCommon(DRVFS_PREFIX, FS_DELETE_DRVFS));
14001398

14011399
ErrorExit:
@@ -2027,6 +2025,180 @@ Return Value:
20272025
return Result;
20282026
}
20292027

2028+
int DrvFsTestStatx(PLXT_ARGS Args)
2029+
2030+
/*++
2031+
2032+
Description:
2033+
2034+
This routine tests the statx system call on drvfs files.
2035+
2036+
Arguments:
2037+
2038+
Args - Supplies the command line arguments.
2039+
2040+
Return Value:
2041+
2042+
Returns 0 on success, -1 on failure.
2043+
2044+
--*/
2045+
2046+
{
2047+
2048+
int Fd;
2049+
int Result;
2050+
struct stat Stat1;
2051+
struct statx Statx1;
2052+
struct statx Statx2;
2053+
2054+
Fd = -1;
2055+
2056+
if (g_LxtFsInfo.FsType == LxtFsTypeDrvFs)
2057+
{
2058+
LxtLogInfo("statx is not supported on drvfs in WSL1.");
2059+
Result = 0;
2060+
goto ErrorExit;
2061+
}
2062+
2063+
//
2064+
// Create a test file and symlink.
2065+
//
2066+
2067+
LxtCheckErrnoZeroSuccess(mkdir(DRVFS_BASIC_PREFIX, 0777));
2068+
LxtCheckErrno(Fd = creat(DRVFS_BASIC_PREFIX "/testfile", 0666));
2069+
LxtCheckErrnoZeroSuccess(symlink(DRVFS_BASIC_PREFIX "/testfile", DRVFS_BASIC_PREFIX "/testlink"));
2070+
2071+
//
2072+
// Stat and statx should have consistent results.
2073+
//
2074+
2075+
LxtCheckErrnoZeroSuccess(stat(DRVFS_BASIC_PREFIX "/testfile", &Stat1));
2076+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_BASIC_STATS, &Statx1));
2077+
LxtCheckEqual(Stat1.st_ino, Statx1.stx_ino, "%llu");
2078+
LxtCheckEqual(Stat1.st_size, Statx1.stx_size, "%llu");
2079+
LxtCheckEqual(Stat1.st_mode, Statx1.stx_mode, "0%o");
2080+
2081+
//
2082+
// Statx with AT_EMPTY_PATH on an fd.
2083+
//
2084+
2085+
LxtCheckErrnoZeroSuccess(statx(Fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, &Statx2));
2086+
LxtCheckEqual(Statx1.stx_ino, Statx2.stx_ino, "%llu");
2087+
2088+
//
2089+
// Test AT_SYMLINK_NOFOLLOW flag.
2090+
//
2091+
2092+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testlink", AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS, &Statx2));
2093+
LxtCheckTrue(S_ISLNK(Statx2.stx_mode));
2094+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testlink", 0, STATX_BASIC_STATS, &Statx2));
2095+
LxtCheckTrue(S_ISREG(Statx2.stx_mode));
2096+
2097+
//
2098+
// Test STATX_BTIME (birth/creation time).
2099+
//
2100+
2101+
memset(&Statx2, 0, sizeof(Statx2));
2102+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_BASIC_STATS | STATX_BTIME, &Statx2));
2103+
if (Statx2.stx_mask & STATX_BTIME)
2104+
{
2105+
LxtLogInfo("Birth time supported: tv_sec=%lld", (long long)Statx2.stx_btime.tv_sec);
2106+
}
2107+
2108+
//
2109+
// Test sync flags.
2110+
//
2111+
2112+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", AT_STATX_FORCE_SYNC, STATX_BASIC_STATS, &Statx2));
2113+
LxtCheckEqual(Statx1.stx_ino, Statx2.stx_ino, "%llu");
2114+
2115+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", AT_STATX_DONT_SYNC, STATX_BASIC_STATS, &Statx2));
2116+
LxtCheckEqual(Statx1.stx_ino, Statx2.stx_ino, "%llu");
2117+
2118+
//
2119+
// Test individual field masks.
2120+
//
2121+
2122+
memset(&Statx2, 0, sizeof(Statx2));
2123+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_TYPE, &Statx2));
2124+
LxtCheckTrue((Statx2.stx_mask & STATX_TYPE) != 0);
2125+
LxtCheckTrue(S_ISREG(Statx2.stx_mode));
2126+
2127+
memset(&Statx2, 0, sizeof(Statx2));
2128+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_MODE, &Statx2));
2129+
LxtCheckTrue((Statx2.stx_mask & STATX_MODE) != 0);
2130+
LxtCheckEqual((Statx1.stx_mode & 0777), (Statx2.stx_mode & 0777), "0%o");
2131+
2132+
memset(&Statx2, 0, sizeof(Statx2));
2133+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_NLINK, &Statx2));
2134+
LxtCheckTrue((Statx2.stx_mask & STATX_NLINK) != 0);
2135+
LxtCheckEqual(Statx1.stx_nlink, Statx2.stx_nlink, "%u");
2136+
2137+
memset(&Statx2, 0, sizeof(Statx2));
2138+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_UID, &Statx2));
2139+
LxtCheckTrue((Statx2.stx_mask & STATX_UID) != 0);
2140+
LxtCheckEqual(Statx1.stx_uid, Statx2.stx_uid, "%u");
2141+
2142+
memset(&Statx2, 0, sizeof(Statx2));
2143+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_GID, &Statx2));
2144+
LxtCheckTrue((Statx2.stx_mask & STATX_GID) != 0);
2145+
LxtCheckEqual(Statx1.stx_gid, Statx2.stx_gid, "%u");
2146+
2147+
memset(&Statx2, 0, sizeof(Statx2));
2148+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_ATIME, &Statx2));
2149+
LxtCheckTrue((Statx2.stx_mask & STATX_ATIME) != 0);
2150+
LxtCheckEqual(Statx1.stx_atime.tv_sec, Statx2.stx_atime.tv_sec, "%lld");
2151+
2152+
memset(&Statx2, 0, sizeof(Statx2));
2153+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_MTIME, &Statx2));
2154+
LxtCheckTrue((Statx2.stx_mask & STATX_MTIME) != 0);
2155+
LxtCheckEqual(Statx1.stx_mtime.tv_sec, Statx2.stx_mtime.tv_sec, "%lld");
2156+
2157+
memset(&Statx2, 0, sizeof(Statx2));
2158+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_CTIME, &Statx2));
2159+
LxtCheckTrue((Statx2.stx_mask & STATX_CTIME) != 0);
2160+
LxtCheckEqual(Statx1.stx_ctime.tv_sec, Statx2.stx_ctime.tv_sec, "%lld");
2161+
2162+
memset(&Statx2, 0, sizeof(Statx2));
2163+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_INO, &Statx2));
2164+
LxtCheckTrue((Statx2.stx_mask & STATX_INO) != 0);
2165+
LxtCheckEqual(Statx1.stx_ino, Statx2.stx_ino, "%llu");
2166+
2167+
memset(&Statx2, 0, sizeof(Statx2));
2168+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_SIZE, &Statx2));
2169+
LxtCheckTrue((Statx2.stx_mask & STATX_SIZE) != 0);
2170+
LxtCheckEqual(Statx1.stx_size, Statx2.stx_size, "%llu");
2171+
2172+
memset(&Statx2, 0, sizeof(Statx2));
2173+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/testfile", 0, STATX_BLOCKS, &Statx2));
2174+
LxtCheckTrue((Statx2.stx_mask & STATX_BLOCKS) != 0);
2175+
LxtCheckEqual(Statx1.stx_blocks, Statx2.stx_blocks, "%llu");
2176+
2177+
//
2178+
// Test on a directory.
2179+
//
2180+
2181+
LxtCheckErrnoZeroSuccess(statx(AT_FDCWD, DRVFS_BASIC_PREFIX, 0, STATX_BASIC_STATS, &Statx2));
2182+
LxtCheckTrue(S_ISDIR(Statx2.stx_mode));
2183+
2184+
//
2185+
// Test error case.
2186+
//
2187+
2188+
LxtCheckErrnoFailure(statx(AT_FDCWD, DRVFS_BASIC_PREFIX "/nonexistent", 0, STATX_BASIC_STATS, &Statx2), ENOENT);
2189+
2190+
ErrorExit:
2191+
if (Fd >= 0)
2192+
{
2193+
close(Fd);
2194+
}
2195+
2196+
unlink(DRVFS_BASIC_PREFIX "/testlink");
2197+
unlink(DRVFS_BASIC_PREFIX "/testfile");
2198+
rmdir(DRVFS_BASIC_PREFIX);
2199+
return Result;
2200+
}
2201+
20302202
int DrvFsTestGetDents64Alignment(PLXT_ARGS Args)
20312203

20322204
/*++

test/linux/unit_tests/lxtfs.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -444,13 +444,18 @@ Return Value:
444444
//
445445
// Try to chdir to the parent.
446446
//
447+
// N.B. This currently doesn't work on virtiofs.
448+
//
447449

448-
LxtCheckErrnoZeroSuccess(chdir(".."));
449-
LxtCheckErrno(LxtGetcwd(Path, sizeof(Path)));
450-
LxtCheckStringEqual(Path, BaseDir);
451-
memset(Path, 0, sizeof(Path));
452-
LxtCheckErrno(readlink(FS_PROC_SELF_CWD, Path, sizeof(Path)));
453-
LxtCheckStringEqual(Path, BaseDir);
450+
if (g_LxtFsInfo.FsType != LxtFsTypeVirtioFs)
451+
{
452+
LxtCheckErrnoZeroSuccess(chdir(".."));
453+
LxtCheckErrno(LxtGetcwd(Path, sizeof(Path)));
454+
LxtCheckStringEqual(Path, BaseDir);
455+
memset(Path, 0, sizeof(Path));
456+
LxtCheckErrno(readlink(FS_PROC_SELF_CWD, Path, sizeof(Path)));
457+
LxtCheckStringEqual(Path, BaseDir);
458+
}
454459

455460
//
456461
// Try to chdir back to the deleted directory.

0 commit comments

Comments
 (0)