gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/statfs.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <fcntl.h> 16 #include <linux/magic.h> 17 #include <sys/mount.h> 18 #include <sys/statfs.h> 19 #include <unistd.h> 20 21 #include <cstdint> 22 #include <string> 23 #include <vector> 24 25 #include "gtest/gtest.h" 26 #include "test/util/file_descriptor.h" 27 #include "test/util/fs_util.h" 28 #include "test/util/linux_capability_util.h" 29 #include "test/util/mount_util.h" 30 #include "test/util/temp_path.h" 31 #include "test/util/test_util.h" 32 33 namespace gvisor { 34 namespace testing { 35 36 namespace { 37 38 TEST(StatfsTest, CannotStatBadPath) { 39 auto temp_file = NewTempAbsPath(); 40 41 struct statfs st; 42 EXPECT_THAT(statfs(temp_file.c_str(), &st), SyscallFailsWithErrno(ENOENT)); 43 } 44 45 TEST(StatfsTest, TempPath) { 46 auto temp_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 47 48 struct statfs st; 49 EXPECT_THAT(statfs(temp_file.path().c_str(), &st), SyscallSucceeds()); 50 EXPECT_GT(st.f_namelen, 0); 51 } 52 53 TEST(StatfsTest, InternalDevShm) { 54 struct statfs st; 55 EXPECT_THAT(statfs("/dev/shm", &st), SyscallSucceeds()); 56 57 EXPECT_GT(st.f_namelen, 0); 58 // This assumes that /dev/shm is tmpfs. 59 // Note: We could be an overlay on some configurations. 60 EXPECT_TRUE(st.f_type == TMPFS_MAGIC || st.f_type == OVERLAYFS_SUPER_MAGIC); 61 } 62 63 TEST(StatFsTest, MountFlags) { 64 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN))); 65 66 const std::vector<int64_t> flags = {MS_NOEXEC, MS_NOATIME, MS_NODEV, 67 MS_NOSUID, MS_RDONLY}; 68 69 for (const auto& flag : flags) { 70 auto const dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 71 auto const mount = ASSERT_NO_ERRNO_AND_VALUE( 72 Mount("", dir.path(), "tmpfs", flag, "mode=0777", 0)); 73 struct statfs st; 74 EXPECT_THAT(statfs(dir.path().c_str(), &st), SyscallSucceeds()); 75 EXPECT_TRUE((st.f_flags & flag) == flag); 76 } 77 } 78 79 TEST(FstatfsTest, CannotStatBadFd) { 80 struct statfs st; 81 EXPECT_THAT(fstatfs(-1, &st), SyscallFailsWithErrno(EBADF)); 82 } 83 84 TEST(FstatfsTest, TempPath) { 85 auto temp_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 86 const FileDescriptor fd = 87 ASSERT_NO_ERRNO_AND_VALUE(Open(temp_file.path(), O_RDONLY)); 88 89 struct statfs st; 90 EXPECT_THAT(fstatfs(fd.get(), &st), SyscallSucceeds()); 91 EXPECT_GT(st.f_namelen, 0); 92 } 93 94 TEST(FstatfsTest, CanStatFileWithOpath) { 95 auto temp_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 96 const FileDescriptor fd = 97 ASSERT_NO_ERRNO_AND_VALUE(Open(temp_file.path(), O_PATH)); 98 99 struct statfs st; 100 EXPECT_THAT(fstatfs(fd.get(), &st), SyscallSucceeds()); 101 } 102 103 TEST(FstatfsTest, InternalDevShm) { 104 auto temp_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 105 const FileDescriptor fd = 106 ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/shm", O_RDONLY)); 107 108 struct statfs st; 109 EXPECT_THAT(fstatfs(fd.get(), &st), SyscallSucceeds()); 110 EXPECT_GT(st.f_namelen, 0); 111 // This assumes that /dev/shm is tmpfs. 112 // Note: We could be an overlay on some configurations. 113 EXPECT_TRUE(st.f_type == TMPFS_MAGIC || st.f_type == OVERLAYFS_SUPER_MAGIC); 114 } 115 116 // Tests that the number of blocks free in the filesystem, as reported by 117 // statfs(2) updates appropriately when pages are allocated. 118 TEST(FstatfsTest, BlocksFree) { 119 // This test relies on the test being the only user of the filesystem, which 120 // is not feasible outside of a sandbox. 121 SKIP_IF(!IsRunningOnGvisor()); 122 123 const std::string file_path = NewTempAbsPath(); 124 const std::string dir = std::string(Dirname(file_path)); 125 struct statfs st_before; 126 EXPECT_THAT(statfs(dir.c_str(), &st_before), SyscallSucceeds()); 127 // Only test for tmpfs. Passthru gofer does not expose host filesystem 128 // statfs(2) results. It always returns 0 for blocks free. 129 SKIP_IF(st_before.f_type != TMPFS_MAGIC); 130 131 ASSERT_NO_ERRNO(CreateWithContents(file_path, "abcd")); 132 struct statfs st_after; 133 EXPECT_THAT(statfs(dir.c_str(), &st_after), SyscallSucceeds()); 134 EXPECT_GT(st_before.f_bfree, st_after.f_bfree); 135 EXPECT_GT(st_before.f_bavail, st_after.f_bavail); 136 } 137 138 } // namespace 139 } // namespace testing 140 } // namespace gvisor