Re: Serious error in autofs docs, which has design implications

Ian Kent <[email protected]> Tue, 26 Aug 2025 10:22:01 +0800
Newsgroups gmane.linux.file-systems,gmane.linux.kernel.autofs
Message-ID <[email protected]>
On 25/8/25 22:38, Askar Safin wrote:
>   ---- On Fri, 22 Aug 2025 16:31:46 +0400  Ian Kent <[email protected]> wrote ---
>   > On 21/8/25 15:53, Askar Safin wrote:
>   > > autofs.rst says:
>   > >> mounting onto a directory is considered to be "beyond a `stat`"
>   > > in https://elixir.bootlin.com/linux/v6.17-rc2/source/Documentation/filesystems/autofs.rst#L109
>   > >
>   > > This is not true. Mounting does not trigger automounts.
>   >
>   > I don't understand that statement either, it's been many years
>
> Let me explain.

I do understand what your saying but without more information about

the meaning and intent of the text your concerned about I don't think

anything can be done about this right now.


I guess that I should also apologise to you as I'm pretty sure I

reviewed this at the time it was posted and didn't question this

at the time. But I most likely didn't see this as a problem because,

to my thinking, what follows explains what it's needed for rather

than the earlier statement justifying it.


To be clear, in my previous reply I said two things, first I also

find the statement you are concerned about unclear, perhaps even

misleading (but I would need to understand the statement original

intent to interpret that, which I don't) and second, the ->d_namage()

callback is most definitely needed for the function of the user space

daemon, automount(8) (via the autofs file system).


Ian

>
> Some syscalls follow (and trigger) automounts in last
> component of path, and some - not.
>
> stat(2) is one of syscalls, which don't follow
> automounts in last component of supplied path.
>
> Many other syscalls do follow automounts.
>
> autofs.rst calls syscalls, which follow automounts,
> as "beyond a stat".
>
> Notably mount(2) doesn't follow automounts in second argument
> (i. e. mountpoint). I know this, because I closely did read the code.
> Also I did experiment (see source in the end of this letter).
> Experiment was on 6.17-rc1.
>
> But "autofs.rst" says:
>> mounting onto a directory is considered to be "beyond a `stat`"
> I. e. "autofs.rst" says that mount(2) does follow automounts.
>
> This is wrong, as I explained above. (Again: I did experiment,
> so I'm totally sure that this "autofs.rst" sentence is wrong.)
>
> Moreover, then "autofs.rst" proceeds to explain why
> DCACHE_MANAGE_TRANSIT was introduced, based on this wrong fact.
>
> So it is possible that DCACHE_MANAGE_TRANSIT is in fact, not needed.
>
> I'm not asking for removal of DCACHE_MANAGE_TRANSIT.
>
> I merely point error in autofs.rst file and ask for fix.
>
> And if in process of fixing autofs.rst you will notice that
> DCACHE_MANAGE_TRANSIT is indeed not needed, then,
> of course, it should be removed.
>
> --
> Askar Safin
> https://types.pl/@safinaskar
>
> ====
>
> // This code is public domain
> // You should be root in initial user namespace
>
> #define _GNU_SOURCE
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdbool.h>
> #include <string.h>
> #include <unistd.h>
> #include <fcntl.h>
> #include <sched.h>
> #include <errno.h>
> #include <sys/stat.h>
> #include <sys/mount.h>
> #include <sys/syscall.h>
> #include <sys/vfs.h>
> #include <sys/sysmacros.h>
> #include <sys/statvfs.h>
> #include <sys/wait.h>
> #include <linux/openat2.h>
> #include <linux/nsfs.h>
>
> #define MY_ASSERT(cond) do { \
>      if (!(cond)) { \
>          fprintf (stderr, "%d: %s: assertion failed\n", __LINE__, #cond); \
>          exit (1); \
>      } \
> } while (0)
>
> #define MY_ASSERT_ERRNO(cond) do { \
>      if (!(cond)) { \
>          fprintf (stderr, "%d: %s: %m\n", __LINE__, #cond); \
>          exit (1); \
>      } \
> } while (0)
>
> static void
> mount_debugfs (void)
> {
>      if (mount (NULL, "/tmp/debugfs", "debugfs", 0, NULL) != 0)
>          {
>              perror ("mount debugfs");
>              exit (1);
>          }
> }
>
> int
> main (void)
> {
>      MY_ASSERT_ERRNO (chdir ("/") == 0);
>      MY_ASSERT_ERRNO (unshare (CLONE_NEWNS) == 0);
>      MY_ASSERT_ERRNO (mount (NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL) == 0);
>      MY_ASSERT_ERRNO (mount (NULL, "/tmp", "tmpfs", 0, NULL) == 0);
>      MY_ASSERT_ERRNO (mkdir ("/tmp/debugfs", 0777) == 0);
>      mount_debugfs ();
>      MY_ASSERT_ERRNO (mount (NULL, "/tmp/debugfs/tracing", "tmpfs", 0, NULL) == 0);
>      execlp ("/bin/busybox", "sh", NULL);
>      MY_ASSERT (false);
> }
>