lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAGudoHEi7b0aO4GZLXgY=AOBYjfCs7NWkOi_46Rv1cj_mooX6A@mail.gmail.com>
Date: Mon, 10 Nov 2025 11:45:48 +0100
From: Mateusz Guzik <mjguzik@...il.com>
To: Al Viro <viro@...iv.linux.org.uk>
Cc: Christian Brauner <brauner@...nel.org>, Jan Kara <jack@...e.cz>, 
	linux-fsdevel <linux-fsdevel@...r.kernel.org>, linux-kernel <linux-kernel@...r.kernel.org>
Subject: on synthetic filesystems like tmpfs path lookups for non-existent
 files create transient entries

As in, a dentry is allocated solely to return -ENOENT, it gets freed
immediately after. That's a lot of overhead for nothing.

One could argue tmpfs could benefit from caching these anyway or that
there is no point trying to cache these for such a fs. I'm not going
to go there.

Given that there is no time pressure to fix this and seeing how not
creating them for no reason can be implemented in different
taste-dependent ways, I think it will be most time-efficient if you
fix it at your own leisure. ;) I'm not posting patches for this one.

As for a testcase, you can plop this into will-it-scale:
# cat tests/statneg.c
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>

char *testcase_description = "non-existent file stat";

void testcase(unsigned long long *iterations, unsigned long nr)
{
    struct stat sb;

    while (1) {
        int error = stat("/tmp/nonexistent", &sb);
        assert(error != 0);

        (*iterations)++;
    }
}

Then running ./statneg_processes showcases the problem, being super
slow single-threaded. Hitting these in parallel does not scale at all
either:

# ./statneg_processes -t 10
testcase:non-existent file stat
warmup
min:261181 max:285570 total:2780930
min:311086 max:352403 total:3348461
min:310552 max:349138 total:3277166
min:308172 max:321618 total:3134878
min:310914 max:332300 total:3185394
min:355424 max:385750 total:3702454
measurement
min:311937 max:348949 total:3289838
min:293611 max:323888 total:3070839
min:296091 max:313330 total:3036069
min:288423 max:303650 total:2981185
min:287714 max:317808 total:3023488

this is contending on a spinlock:

@[
    __pv_queued_spin_lock_slowpath+5
    _raw_spin_lock+41
    d_alloc_parallel+126
    __lookup_slow+94
    walk_component+219
    path_lookupat+85
    filename_lookup+224
    vfs_statx+108
    vfs_fstatat+107
    __do_sys_newfstatat+36
    do_syscall_64+85
    entry_SYSCALL_64_after_hwframe+118
]: 1115404
@[
    __pv_queued_spin_lock_slowpath+5
    _raw_spin_lock+41
    dput+321
    terminate_walk+89
    path_lookupat+120
    filename_lookup+224
    vfs_statx+108
    vfs_fstatat+107
    __do_sys_newfstatat+36
    do_syscall_64+85
    entry_SYSCALL_64_after_hwframe+118
]: 1118216

things scale fine on ext4:
min:5945177 max:6203067 total:60466641
min:6350640 max:6630364 total:64641156
min:6352730 max:6644954 total:64719190
min:6358623 max:6659048 total:64768382

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ