]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/stat-util: avoid access syscall
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 24 Jul 2025 13:09:58 +0000 (15:09 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 27 Jul 2025 11:13:43 +0000 (13:13 +0200)
I was looking at strace for systemd-getty-generator and noticed the call to
faccessat2(3</sys>, "", W_OK, AT_EMPTY_PATH), even though we already did
fstatfs(3</sys>), which should give us all the necessary information. Let's
only do this additional check when it's likely to yield something useful, i.e.
for network fses and otherwise skip the syscall.

The call to statvfs is replaced by statfs because that gives us the .f_type
field and allows is_network_fs() to be called.

I'm a bit worried that the is_network_fs() is somewhat costly. This will be
improved in later commits.

src/basic/stat-util.c

index 72360daadfefb5ee4bdb0f02355973a7a4e52c95..5582c5903757ac54c626d271af34a46df34ce520 100644 (file)
@@ -220,20 +220,22 @@ int null_or_empty_path_with_root(const char *fn, const char *root) {
 }
 
 int fd_is_read_only_fs(int fd) {
-        struct statvfs st;
+        struct statfs st;
 
         assert(fd >= 0);
 
-        if (fstatvfs(fd, &st) < 0)
+        if (fstatfs(fd, &st) < 0)
                 return -errno;
 
-        if (st.f_flag & ST_RDONLY)
+        if (st.f_flags & ST_RDONLY)
                 return true;
 
-        /* On NFS, fstatvfs() might not reflect whether we can actually write to the remote share. Let's try
-         * again with access(W_OK) which is more reliable, at least sometimes. */
-        if (access_fd(fd, W_OK) == -EROFS)
-                return true;
+        if (is_network_fs(&st)) {
+                /* On NFS, fstatfs() might not reflect whether we can actually write to the remote share.
+                 * Let's try again with access(W_OK) which is more reliable, at least sometimes. */
+                if (access_fd(fd, W_OK) == -EROFS)
+                        return true;
+        }
 
         return false;
 }