← Documents Documentation/filesystems/autofs-mount-control.rst GitHub 원문 ↗

Linux 6.18.37 · Filesystems

Miscellaneous Device control operations for autofs

autofs active restart, 공통 ioctl 구조와 11개 mount-control command의 전문 번역입니다.

Source pathDocumentation/filesystems/autofs-mount-control.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

autofs-mount-control.rst:1-410

autofs miscellaneous device interface는 covered mount를 유지한 active restart에서 mount handle, daemon pipe, requester identity와 expire 상태를 복원하기 위한 `/dev/autofs` ioctl 집합입니다.

autofs active restart control
기존 mount를 catatonic으로 전환`OPENMOUNT`로 covered trigger handle 획득`REQUESTER`로 UID/GID 복원`SETPIPEFD`로 새 daemon 연결`READY/FAIL`, `EXPIRE`, `ISMOUNTPOINT` control 재개

기존 mount를 내리지 않고 새 daemon이 control을 이어받는 핵심 순서입니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ====================================================================
4 Miscellaneous Device control operations for the autofs kernel module
5 ====================================================================
6
7 The problem
8 ===========
9
10 There is a problem with active restarts in autofs (that is to say
11 restarting autofs when there are busy mounts).
12
13 During normal operation autofs uses a file descriptor opened on the
14 directory that is being managed in order to be able to issue control
15 operations. Using a file descriptor gives ioctl operations access to
16 autofs specific information stored in the super block. The operations
17 are things such as setting an autofs mount catatonic, setting the
18 expire timeout and requesting expire checks. As is explained below,
19 certain types of autofs triggered mounts can end up covering an autofs
20 mount itself which prevents us being able to use open(2) to obtain a
21 file descriptor for these operations if we don't already have one open.
22
23 Currently autofs uses "umount -l" (lazy umount) to clear active mounts
24 at restart. While using lazy umount works for most cases, anything that
25 needs to walk back up the mount tree to construct a path, such as
26 getcwd(2) and the proc file system /proc/<pid>/cwd, no longer works
27 because the point from which the path is constructed has been detached
28 from the mount tree.
29
30 The actual problem with autofs is that it can't reconnect to existing
31 mounts. Immediately one thinks of just adding the ability to remount
32 autofs file systems would solve it, but alas, that can't work. This is
33 because autofs direct mounts and the implementation of "on demand mount
34 and expire" of nested mount trees have the file system mounted directly
35 on top of the mount trigger directory dentry.
36
37 For example, there are two types of automount maps, direct (in the kernel
38 module source you will see a third type called an offset, which is just
39 a direct mount in disguise) and indirect.
40
41 Here is a master map with direct and indirect map entries::
42
43 /- /etc/auto.direct
44 /test /etc/auto.indirect
45
46 and the corresponding map files::
47
48 /etc/auto.direct:
49
50 /automount/dparse/g6 budgie:/autofs/export1
51 /automount/dparse/g1 shark:/autofs/export1
52 and so on.
53
54 /etc/auto.indirect::
55
56 g1 shark:/autofs/export1
57 g6 budgie:/autofs/export1
58 and so on.
59
60 For the above indirect map an autofs file system is mounted on /test and
61 mounts are triggered for each sub-directory key by the inode lookup
62 operation. So we see a mount of shark:/autofs/export1 on /test/g1, for
63 example.
64
65 The way that direct mounts are handled is by making an autofs mount on
66 each full path, such as /automount/dparse/g1, and using it as a mount
67 trigger. So when we walk on the path we mount shark:/autofs/export1 "on
68 top of this mount point". Since these are always directories we can
69 use the follow_link inode operation to trigger the mount.
70
71 But, each entry in direct and indirect maps can have offsets (making
72 them multi-mount map entries).
73
74 For example, an indirect mount map entry could also be::
75
76 g1 \
77 / shark:/autofs/export5/testing/test \
78 /s1 shark:/autofs/export/testing/test/s1 \
79 /s2 shark:/autofs/export5/testing/test/s2 \
80 /s1/ss1 shark:/autofs/export1 \
81 /s2/ss2 shark:/autofs/export2
82
83 and a similarly a direct mount map entry could also be::
84
85 /automount/dparse/g1 \
86 / shark:/autofs/export5/testing/test \
87 /s1 shark:/autofs/export/testing/test/s1 \
88 /s2 shark:/autofs/export5/testing/test/s2 \
89 /s1/ss1 shark:/autofs/export2 \
90 /s2/ss2 shark:/autofs/export2
91
92 One of the issues with version 4 of autofs was that, when mounting an
93 entry with a large number of offsets, possibly with nesting, we needed
94 to mount and umount all of the offsets as a single unit. Not really a
95 problem, except for people with a large number of offsets in map entries.
96 This mechanism is used for the well known "hosts" map and we have seen
97 cases (in 2.4) where the available number of mounts are exhausted or
98 where the number of privileged ports available is exhausted.
99
100 In version 5 we mount only as we go down the tree of offsets and
101 similarly for expiring them which resolves the above problem. There is
102 somewhat more detail to the implementation but it isn't needed for the
103 sake of the problem explanation. The one important detail is that these
104 offsets are implemented using the same mechanism as the direct mounts
105 above and so the mount points can be covered by a mount.
106
107 The current autofs implementation uses an ioctl file descriptor opened
108 on the mount point for control operations. The references held by the
109 descriptor are accounted for in checks made to determine if a mount is
110 in use and is also used to access autofs file system information held
111 in the mount super block. So the use of a file handle needs to be
112 retained.
113
114
115 The Solution
116 ============
117
118 To be able to restart autofs leaving existing direct, indirect and
119 offset mounts in place we need to be able to obtain a file handle
120 for these potentially covered autofs mount points. Rather than just
121 implement an isolated operation it was decided to re-implement the
122 existing ioctl interface and add new operations to provide this
123 functionality.
124
125 In addition, to be able to reconstruct a mount tree that has busy mounts,
126 the uid and gid of the last user that triggered the mount needs to be
127 available because these can be used as macro substitution variables in
128 autofs maps. They are recorded at mount request time and an operation
129 has been added to retrieve them.
130
131 Since we're re-implementing the control interface, a couple of other
132 problems with the existing interface have been addressed. First, when
133 a mount or expire operation completes a status is returned to the
134 kernel by either a "send ready" or a "send fail" operation. The
135 "send fail" operation of the ioctl interface could only ever send
136 ENOENT so the re-implementation allows user space to send an actual
137 status. Another expensive operation in user space, for those using
138 very large maps, is discovering if a mount is present. Usually this
139 involves scanning /proc/mounts and since it needs to be done quite
140 often it can introduce significant overhead when there are many entries
141 in the mount table. An operation to lookup the mount status of a mount
142 point dentry (covered or not) has also been added.
143
144 Current kernel development policy recommends avoiding the use of the
145 ioctl mechanism in favor of systems such as Netlink. An implementation
146 using this system was attempted to evaluate its suitability and it was
147 found to be inadequate, in this case. The Generic Netlink system was
148 used for this as raw Netlink would lead to a significant increase in
149 complexity. There's no question that the Generic Netlink system is an
150 elegant solution for common case ioctl functions but it's not a complete
151 replacement probably because its primary purpose in life is to be a
152 message bus implementation rather than specifically an ioctl replacement.
153 While it would be possible to work around this there is one concern
154 that lead to the decision to not use it. This is that the autofs
155 expire in the daemon has become far to complex because umount
156 candidates are enumerated, almost for no other reason than to "count"
157 the number of times to call the expire ioctl. This involves scanning
158 the mount table which has proved to be a big overhead for users with
159 large maps. The best way to improve this is try and get back to the
160 way the expire was done long ago. That is, when an expire request is
161 issued for a mount (file handle) we should continually call back to
162 the daemon until we can't umount any more mounts, then return the
163 appropriate status to the daemon. At the moment we just expire one
164 mount at a time. A Generic Netlink implementation would exclude this
165 possibility for future development due to the requirements of the
166 message bus architecture.
167
168
169 autofs Miscellaneous Device mount control interface
170 ====================================================
171
172 The control interface is opening a device node, typically /dev/autofs.
173
174 All the ioctls use a common structure to pass the needed parameter
175 information and return operation results::
176
177 struct autofs_dev_ioctl {
178 __u32 ver_major;
179 __u32 ver_minor;
180 __u32 size; /* total size of data passed in
181 * including this struct */
182 __s32 ioctlfd; /* automount command fd */
183
184 /* Command parameters */
185 union {
186 struct args_protover protover;
187 struct args_protosubver protosubver;
188 struct args_openmount openmount;
189 struct args_ready ready;
190 struct args_fail fail;
191 struct args_setpipefd setpipefd;
192 struct args_timeout timeout;
193 struct args_requester requester;
194 struct args_expire expire;
195 struct args_askumount askumount;
196 struct args_ismountpoint ismountpoint;
197 };
198
199 char path[];
200 };
201
202 The ioctlfd field is a mount point file descriptor of an autofs mount
203 point. It is returned by the open call and is used by all calls except
204 the check for whether a given path is a mount point, where it may
205 optionally be used to check a specific mount corresponding to a given
206 mount point file descriptor, and when requesting the uid and gid of the
207 last successful mount on a directory within the autofs file system.
208
209 The union is used to communicate parameters and results of calls made
210 as described below.
211
212 The path field is used to pass a path where it is needed and the size field
213 is used account for the increased structure length when translating the
214 structure sent from user space.
215
216 This structure can be initialized before setting specific fields by using
217 the void function call init_autofs_dev_ioctl(``struct autofs_dev_ioctl *``).
218
219 All of the ioctls perform a copy of this structure from user space to
220 kernel space and return -EINVAL if the size parameter is smaller than
221 the structure size itself, -ENOMEM if the kernel memory allocation fails
222 or -EFAULT if the copy itself fails. Other checks include a version check
223 of the compiled in user space version against the module version and a
224 mismatch results in a -EINVAL return. If the size field is greater than
225 the structure size then a path is assumed to be present and is checked to
226 ensure it begins with a "/" and is NULL terminated, otherwise -EINVAL is
227 returned. Following these checks, for all ioctl commands except
228 AUTOFS_DEV_IOCTL_VERSION_CMD, AUTOFS_DEV_IOCTL_OPENMOUNT_CMD and
229 AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD the ioctlfd is validated and if it is
230 not a valid descriptor or doesn't correspond to an autofs mount point
231 an error of -EBADF, -ENOTTY or -EINVAL (not an autofs descriptor) is
232 returned.
233
234
235 The ioctls
236 ==========
237
238 An example of an implementation which uses this interface can be seen
239 in autofs version 5.0.4 and later in file lib/dev-ioctl-lib.c of the
240 distribution tar available for download from kernel.org in directory
241 /pub/linux/daemons/autofs/v5.
242
243 The device node ioctl operations implemented by this interface are:
244
245
246 AUTOFS_DEV_IOCTL_VERSION
247 ------------------------
248
249 Get the major and minor version of the autofs device ioctl kernel module
250 implementation. It requires an initialized struct autofs_dev_ioctl as an
251 input parameter and sets the version information in the passed in structure.
252 It returns 0 on success or the error -EINVAL if a version mismatch is
253 detected.
254
255
256 AUTOFS_DEV_IOCTL_PROTOVER_CMD and AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD
257 ------------------------------------------------------------------
258
259 Get the major and minor version of the autofs protocol version understood
260 by loaded module. This call requires an initialized struct autofs_dev_ioctl
261 with the ioctlfd field set to a valid autofs mount point descriptor
262 and sets the requested version number in version field of struct args_protover
263 or sub_version field of struct args_protosubver. These commands return
264 0 on success or one of the negative error codes if validation fails.
265
266
267 AUTOFS_DEV_IOCTL_OPENMOUNT and AUTOFS_DEV_IOCTL_CLOSEMOUNT
268 ----------------------------------------------------------
269
270 Obtain and release a file descriptor for an autofs managed mount point
271 path. The open call requires an initialized struct autofs_dev_ioctl with
272 the path field set and the size field adjusted appropriately as well
273 as the devid field of struct args_openmount set to the device number of
274 the autofs mount. The device number can be obtained from the mount options
275 shown in /proc/mounts. The close call requires an initialized struct
276 autofs_dev_ioct with the ioctlfd field set to the descriptor obtained
277 from the open call. The release of the file descriptor can also be done
278 with close(2) so any open descriptors will also be closed at process exit.
279 The close call is included in the implemented operations largely for
280 completeness and to provide for a consistent user space implementation.
281
282
283 AUTOFS_DEV_IOCTL_READY_CMD and AUTOFS_DEV_IOCTL_FAIL_CMD
284 --------------------------------------------------------
285
286 Return mount and expire result status from user space to the kernel.
287 Both of these calls require an initialized struct autofs_dev_ioctl
288 with the ioctlfd field set to the descriptor obtained from the open
289 call and the token field of struct args_ready or struct args_fail set
290 to the wait queue token number, received by user space in the foregoing
291 mount or expire request. The status field of struct args_fail is set to
292 the errno of the operation. It is set to 0 on success.
293
294
295 AUTOFS_DEV_IOCTL_SETPIPEFD_CMD
296 ------------------------------
297
298 Set the pipe file descriptor used for kernel communication to the daemon.
299 Normally this is set at mount time using an option but when reconnecting
300 to a existing mount we need to use this to tell the autofs mount about
301 the new kernel pipe descriptor. In order to protect mounts against
302 incorrectly setting the pipe descriptor we also require that the autofs
303 mount be catatonic (see next call).
304
305 The call requires an initialized struct autofs_dev_ioctl with the
306 ioctlfd field set to the descriptor obtained from the open call and
307 the pipefd field of struct args_setpipefd set to descriptor of the pipe.
308 On success the call also sets the process group id used to identify the
309 controlling process (eg. the owning automount(8) daemon) to the process
310 group of the caller.
311
312
313 AUTOFS_DEV_IOCTL_CATATONIC_CMD
314 ------------------------------
315
316 Make the autofs mount point catatonic. The autofs mount will no longer
317 issue mount requests, the kernel communication pipe descriptor is released
318 and any remaining waits in the queue released.
319
320 The call requires an initialized struct autofs_dev_ioctl with the
321 ioctlfd field set to the descriptor obtained from the open call.
322
323
324 AUTOFS_DEV_IOCTL_TIMEOUT_CMD
325 ----------------------------
326
327 Set the expire timeout for mounts within an autofs mount point.
328
329 The call requires an initialized struct autofs_dev_ioctl with the
330 ioctlfd field set to the descriptor obtained from the open call.
331
332
333 AUTOFS_DEV_IOCTL_REQUESTER_CMD
334 ------------------------------
335
336 Return the uid and gid of the last process to successfully trigger a the
337 mount on the given path dentry.
338
339 The call requires an initialized struct autofs_dev_ioctl with the path
340 field set to the mount point in question and the size field adjusted
341 appropriately. Upon return the uid field of struct args_requester contains
342 the uid and gid field the gid.
343
344 When reconstructing an autofs mount tree with active mounts we need to
345 re-connect to mounts that may have used the original process uid and
346 gid (or string variations of them) for mount lookups within the map entry.
347 This call provides the ability to obtain this uid and gid so they may be
348 used by user space for the mount map lookups.
349
350
351 AUTOFS_DEV_IOCTL_EXPIRE_CMD
352 ---------------------------
353
354 Issue an expire request to the kernel for an autofs mount. Typically
355 this ioctl is called until no further expire candidates are found.
356
357 The call requires an initialized struct autofs_dev_ioctl with the
358 ioctlfd field set to the descriptor obtained from the open call. In
359 addition an immediate expire that's independent of the mount timeout,
360 and a forced expire that's independent of whether the mount is busy,
361 can be requested by setting the how field of struct args_expire to
362 AUTOFS_EXP_IMMEDIATE or AUTOFS_EXP_FORCED, respectively . If no
363 expire candidates can be found the ioctl returns -1 with errno set to
364 EAGAIN.
365
366 This call causes the kernel module to check the mount corresponding
367 to the given ioctlfd for mounts that can be expired, issues an expire
368 request back to the daemon and waits for completion.
369
370 AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD
371 ------------------------------
372
373 Checks if an autofs mount point is in use.
374
375 The call requires an initialized struct autofs_dev_ioctl with the
376 ioctlfd field set to the descriptor obtained from the open call and
377 it returns the result in the may_umount field of struct args_askumount,
378 1 for busy and 0 otherwise.
379
380
381 AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD
382 ---------------------------------
383
384 Check if the given path is a mountpoint.
385
386 The call requires an initialized struct autofs_dev_ioctl. There are two
387 possible variations. Both use the path field set to the path of the mount
388 point to check and the size field adjusted appropriately. One uses the
389 ioctlfd field to identify a specific mount point to check while the other
390 variation uses the path and optionally in.type field of struct args_ismountpoint
391 set to an autofs mount type. The call returns 1 if this is a mount point
392 and sets out.devid field to the device number of the mount and out.magic
393 field to the relevant super block magic number (described below) or 0 if
394 it isn't a mountpoint. In both cases the device number (as returned
395 by new_encode_dev()) is returned in out.devid field.
396
397 If supplied with a file descriptor we're looking for a specific mount,
398 not necessarily at the top of the mounted stack. In this case the path
399 the descriptor corresponds to is considered a mountpoint if it is itself
400 a mountpoint or contains a mount, such as a multi-mount without a root
401 mount. In this case we return 1 if the descriptor corresponds to a mount
402 point and also returns the super magic of the covering mount if there
403 is one or 0 if it isn't a mountpoint.
404
405 If a path is supplied (and the ioctlfd field is set to -1) then the path
406 is looked up and is checked to see if it is the root of a mount. If a
407 type is also given we are looking for a particular autofs mount and if
408 a match isn't found a fail is returned. If the located path is the
409 root of a mount 1 is returned along with the super magic of the mount
410 or 0 otherwise.
411

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

active restart와 covered mount 문제

1-114

autofs의 active restart, 즉 busy mount가 남은 상태에서 daemon을 재시작할 때 문제가 생깁니다. 정상 동작 중에는 관리 directory에 연 file descriptor로 ioctl을 실행하고 superblock의 autofs 전용 정보에 접근합니다. 이 ioctl은 mount를 catatonic 상태로 만들거나 expire timeout을 설정하고 expire check를 요청합니다.

direct mount와 nested mount tree의 on-demand mount는 trigger directory dentry 바로 위에 filesystem을 올릴 수 있습니다. 이렇게 autofs mount 자체가 다른 mount에 덮이면 미리 descriptor를 열어 두지 않은 경우 `open(2)`으로 control FD를 다시 얻을 수 없습니다.

기존 재시작 방식은 `umount -l` lazy unmount로 active mount를 정리합니다. 대부분 동작하지만 mount tree에서 분리된 지점부터 path를 거슬러 올라갈 수 없으므로 `getcwd(2)`와 `/proc/<pid>/cwd` 같은 path 구성 기능이 깨집니다. 단순 remount도 trigger dentry가 이미 covered될 수 있어 해결책이 아닙니다.

automount map에는 direct와 indirect가 있습니다. kernel source의 offset은 실질적으로 direct mount의 변형입니다. master map의 `/- /etc/auto.direct`는 full path마다 trigger를 만들고, `/test /etc/auto.indirect`는 `/test`에 autofs를 mount한 뒤 subdirectory key lookup으로 `/test/g1` 같은 target을 mount합니다.

direct map은 `/automount/dparse/g1` 같은 full path마다 autofs trigger mount를 만들고 path를 따라갈 때 remote filesystem을 그 mount point 위에 올립니다. directory이므로 `follow_link` inode operation이 mount를 trigger합니다.

direct와 indirect entry 모두 nested offset을 가진 multi-mount가 될 수 있습니다. autofs v4는 많은 offset을 한 unit으로 모두 mount·unmount하여 mount 수나 privileged port를 고갈시킬 수 있었습니다. v5는 offset tree를 내려갈 때 필요한 것만 mount하고 expire 때도 같은 방식으로 처리합니다. 다만 offset도 direct mount와 같은 covered trigger가 됩니다.

control FD의 reference는 mount 사용 여부 검사에 포함되고 mount superblock 정보 접근에도 필요하므로 file handle 방식은 유지해야 합니다.

autofs map과 trigger 구조
형식autofs triggertarget mount
indirect`/test` 하나key lookup 때 `/test/g1` 같은 child
direct`/automount/dparse/g1` full pathtrigger mount point 바로 위
offsetmulti-mount entry의 nested direct triggertree를 내려갈 때 필요한 offset 위
v4 offset전체 offset을 한 unit으로 처리mount/port 고갈 가능
v5 offset필요한 경로만 mount·expiretrigger가 여전히 covered될 수 있음

direct·indirect·offset이 mount를 어디에 올리는지 비교합니다.

.. SPDX-License-Identifier: GPL-2.0

====================================================================
Miscellaneous Device control operations for the autofs kernel module
====================================================================

The problem
===========

There is a problem with active restarts in autofs (that is to say
restarting autofs when there are busy mounts).

During normal operation autofs uses a file descriptor opened on the
directory that is being managed in order to be able to issue control
operations. Using a file descriptor gives ioctl operations access to
autofs specific information stored in the super block. The operations
are things such as setting an autofs mount catatonic, setting the
expire timeout and requesting expire checks. As is explained below,
certain types of autofs triggered mounts can end up covering an autofs
mount itself which prevents us being able to use open(2) to obtain a
file descriptor for these operations if we don't already have one open.

Currently autofs uses "umount -l" (lazy umount) to clear active mounts
at restart. While using lazy umount works for most cases, anything that
needs to walk back up the mount tree to construct a path, such as
getcwd(2) and the proc file system /proc/<pid>/cwd, no longer works
because the point from which the path is constructed has been detached
from the mount tree.

The actual problem with autofs is that it can't reconnect to existing
mounts. Immediately one thinks of just adding the ability to remount
autofs file systems would solve it, but alas, that can't work. This is
because autofs direct mounts and the implementation of "on demand mount
and expire" of nested mount trees have the file system mounted directly
on top of the mount trigger directory dentry.

For example, there are two types of automount maps, direct (in the kernel
module source you will see a third type called an offset, which is just
a direct mount in disguise) and indirect.

Here is a master map with direct and indirect map entries::

    /-      /etc/auto.direct
    /test   /etc/auto.indirect

and the corresponding map files::

    /etc/auto.direct:

    /automount/dparse/g6  budgie:/autofs/export1
    /automount/dparse/g1  shark:/autofs/export1
    and so on.

/etc/auto.indirect::

    g1    shark:/autofs/export1
    g6    budgie:/autofs/export1
    and so on.

For the above indirect map an autofs file system is mounted on /test and
mounts are triggered for each sub-directory key by the inode lookup
operation. So we see a mount of shark:/autofs/export1 on /test/g1, for
example.

The way that direct mounts are handled is by making an autofs mount on
each full path, such as /automount/dparse/g1, and using it as a mount
trigger. So when we walk on the path we mount shark:/autofs/export1 "on
top of this mount point". Since these are always directories we can
use the follow_link inode operation to trigger the mount.

But, each entry in direct and indirect maps can have offsets (making
them multi-mount map entries).

For example, an indirect mount map entry could also be::

    g1  \
    /        shark:/autofs/export5/testing/test \
    /s1      shark:/autofs/export/testing/test/s1 \
    /s2      shark:/autofs/export5/testing/test/s2 \
    /s1/ss1  shark:/autofs/export1 \
    /s2/ss2  shark:/autofs/export2

and a similarly a direct mount map entry could also be::

    /automount/dparse/g1 \
        /       shark:/autofs/export5/testing/test \
        /s1     shark:/autofs/export/testing/test/s1 \
        /s2     shark:/autofs/export5/testing/test/s2 \
        /s1/ss1 shark:/autofs/export2 \
        /s2/ss2 shark:/autofs/export2

One of the issues with version 4 of autofs was that, when mounting an
entry with a large number of offsets, possibly with nesting, we needed
to mount and umount all of the offsets as a single unit. Not really a
problem, except for people with a large number of offsets in map entries.
This mechanism is used for the well known "hosts" map and we have seen
cases (in 2.4) where the available number of mounts are exhausted or
where the number of privileged ports available is exhausted.

In version 5 we mount only as we go down the tree of offsets and
similarly for expiring them which resolves the above problem. There is
somewhat more detail to the implementation but it isn't needed for the
sake of the problem explanation. The one important detail is that these
offsets are implemented using the same mechanism as the direct mounts
above and so the mount points can be covered by a mount.

The current autofs implementation uses an ioctl file descriptor opened
on the mount point for control operations. The references held by the
descriptor are accounted for in checks made to determine if a mount is
in use and is also used to access autofs file system information held
in the mount super block. So the use of a file handle needs to be
retained.

covered mount 재연결용 새 control interface

115-168

기존 direct, indirect, offset mount를 유지한 채 autofs를 재시작하려면 covered될 수 있는 autofs mount point의 file handle을 다시 얻어야 합니다. 이를 위해 기존 ioctl interface를 재구현하고 관련 operation을 추가했습니다.

busy mount tree를 재구성할 때는 mount를 마지막으로 trigger한 사용자의 UID/GID도 필요합니다. autofs map에서 macro substitution variable로 쓰일 수 있기 때문입니다. kernel은 mount request 때 이를 기록하고 새 requester operation으로 반환합니다.

기존 `send fail` ioctl은 항상 `ENOENT`만 보낼 수 있었지만 새 interface는 userspace가 실제 status를 반환할 수 있습니다. 또한 큰 map에서 `/proc/mounts`를 반복 scan하지 않고 covered 여부와 무관하게 mount point dentry의 mount 상태를 lookup하는 operation도 추가했습니다.

kernel 정책은 ioctl 대신 Netlink를 권하지만 Generic Netlink 구현을 평가한 결과 이 용도에는 맞지 않았습니다. Generic Netlink는 일반 ioctl형 message에는 우아하지만 본질적으로 message bus이므로 완전한 ioctl 대체가 아닙니다.

특히 daemon이 mount table을 scan해 expire candidate 수를 세고 ioctl을 그 횟수만큼 호출하는 비용을 줄이려면, 한 expire request 뒤 더는 unmount할 수 없을 때까지 kernel이 daemon에 반복 callback하는 방식이 적합합니다. message bus architecture는 이 향후 개선을 막을 수 있어 채택하지 않았습니다.

active restart 재연결
기존 direct·indirect·offset mount 유지`/dev/autofs` control device opencovered mount point용 file handle 획득마지막 requester UID/GID 복원새 daemon pipe FD 연결실제 ready/fail status와 expire operation 재개

covered autofs mount를 유지하면서 새 daemon이 control을 되찾는 과정입니다.

The Solution
============

To be able to restart autofs leaving existing direct, indirect and
offset mounts in place we need to be able to obtain a file handle
for these potentially covered autofs mount points. Rather than just
implement an isolated operation it was decided to re-implement the
existing ioctl interface and add new operations to provide this
functionality.

In addition, to be able to reconstruct a mount tree that has busy mounts,
the uid and gid of the last user that triggered the mount needs to be
available because these can be used as macro substitution variables in
autofs maps. They are recorded at mount request time and an operation
has been added to retrieve them.

Since we're re-implementing the control interface, a couple of other
problems with the existing interface have been addressed. First, when
a mount or expire operation completes a status is returned to the
kernel by either a "send ready" or a "send fail" operation. The
"send fail" operation of the ioctl interface could only ever send
ENOENT so the re-implementation allows user space to send an actual
status. Another expensive operation in user space, for those using
very large maps, is discovering if a mount is present. Usually this
involves scanning /proc/mounts and since it needs to be done quite
often it can introduce significant overhead when there are many entries
in the mount table. An operation to lookup the mount status of a mount
point dentry (covered or not) has also been added.

Current kernel development policy recommends avoiding the use of the
ioctl mechanism in favor of systems such as Netlink. An implementation
using this system was attempted to evaluate its suitability and it was
found to be inadequate, in this case. The Generic Netlink system was
used for this as raw Netlink would lead to a significant increase in
complexity. There's no question that the Generic Netlink system is an
elegant solution for common case ioctl functions but it's not a complete
replacement probably because its primary purpose in life is to be a
message bus implementation rather than specifically an ioctl replacement.
While it would be possible to work around this there is one concern
that lead to the decision to not use it. This is that the autofs
expire in the daemon has become far to complex because umount
candidates are enumerated, almost for no other reason than to "count"
the number of times to call the expire ioctl. This involves scanning
the mount table which has proved to be a big overhead for users with
large maps. The best way to improve this is try and get back to the
way the expire was done long ago. That is, when an expire request is
issued for a mount (file handle) we should continually call back to
the daemon until we can't umount any more mounts, then return the
appropriate status to the daemon. At the moment we just expire one
mount at a time. A Generic Netlink implementation would exclude this
possibility for future development due to the requirements of the
message bus architecture.

`autofs_dev_ioctl` 구조와 공통 검증

169-234

control interface는 보통 `/dev/autofs` device node를 열어 사용합니다. 모든 ioctl은 공통 `struct autofs_dev_ioctl`로 parameter를 전달하고 결과를 받습니다.

header의 `ver_major`, `ver_minor`는 version, `size`는 구조체 자신과 추가 path를 포함한 전체 byte 수, `ioctlfd`는 automount command FD입니다. union은 protocol version, open mount, ready/fail, pipe FD, timeout, requester, expire, ask-unmount, is-mountpoint argument를 담습니다. 마지막 flexible array `char path[]`는 필요한 path를 전달합니다.

`ioctlfd`는 open call이 반환한 autofs mount point FD이며 대부분의 command가 사용합니다. 예외는 path 자체가 mountpoint인지 검사하는 경우, 특정 descriptor를 선택적으로 검사하는 경우, autofs 내부 directory의 마지막 successful requester UID/GID를 요청하는 경우입니다.

구조체는 `init_autofs_dev_ioctl(struct autofs_dev_ioctl *)`로 초기화한 뒤 command별 field를 설정합니다.

모든 ioctl은 userspace 구조체를 kernel로 copy합니다. `size`가 구조체보다 작으면 `-EINVAL`, allocation 실패는 `-ENOMEM`, copy 실패는 `-EFAULT`입니다. userspace와 module version이 다르면 `-EINVAL`입니다.

`size`가 기본 구조체보다 크면 path가 있다고 가정하며 `/`로 시작하고 NULL-terminated인지 확인합니다. 아니면 `-EINVAL`입니다. `VERSION`, `OPENMOUNT`, `CLOSEMOUNT`를 제외한 command는 `ioctlfd`를 검증하여 invalid FD는 `-EBADF`, ioctl을 지원하지 않으면 `-ENOTTY`, autofs descriptor가 아니면 `-EINVAL`을 반환합니다.

`struct autofs_dev_ioctl`
field/member역할
`ver_major`, `ver_minor`interface version
`size`구조체와 `path[]`를 포함한 전체 크기
`ioctlfd`autofs mount point command FD
`protover`, `protosubver`protocol version 결과
`openmount`mount open parameter
`ready`, `fail`wait token과 completion status
`setpipefd`daemon communication pipe
`timeout`expire timeout
`requester`last requester UID/GID
`expire`, `askumount`expire와 busy 검사
`ismountpoint`mount type·device·super magic
`path[]`가변 길이 absolute path

공통 field와 union member의 역할입니다.

autofs Miscellaneous Device mount control interface
====================================================

The control interface is opening a device node, typically /dev/autofs.

All the ioctls use a common structure to pass the needed parameter
information and return operation results::

    struct autofs_dev_ioctl {
            __u32 ver_major;
            __u32 ver_minor;
            __u32 size;             /* total size of data passed in
                                    * including this struct */
            __s32 ioctlfd;          /* automount command fd */

            /* Command parameters */
            union {
                    struct args_protover                protover;
                    struct args_protosubver                protosubver;
                    struct args_openmount                openmount;
                    struct args_ready                ready;
                    struct args_fail                fail;
                    struct args_setpipefd                setpipefd;
                    struct args_timeout                timeout;
                    struct args_requester                requester;
                    struct args_expire                expire;
                    struct args_askumount                askumount;
                    struct args_ismountpoint        ismountpoint;
            };

            char path[];
    };

The ioctlfd field is a mount point file descriptor of an autofs mount
point. It is returned by the open call and is used by all calls except
the check for whether a given path is a mount point, where it may
optionally be used to check a specific mount corresponding to a given
mount point file descriptor, and when requesting the uid and gid of the
last successful mount on a directory within the autofs file system.

The union is used to communicate parameters and results of calls made
as described below.

The path field is used to pass a path where it is needed and the size field
is used account for the increased structure length when translating the
structure sent from user space.

This structure can be initialized before setting specific fields by using
the void function call init_autofs_dev_ioctl(``struct autofs_dev_ioctl *``).

All of the ioctls perform a copy of this structure from user space to
kernel space and return -EINVAL if the size parameter is smaller than
the structure size itself, -ENOMEM if the kernel memory allocation fails
or -EFAULT if the copy itself fails. Other checks include a version check
of the compiled in user space version against the module version and a
mismatch results in a -EINVAL return. If the size field is greater than
the structure size then a path is assumed to be present and is checked to
ensure it begins with a "/" and is NULL terminated, otherwise -EINVAL is
returned. Following these checks, for all ioctl commands except
AUTOFS_DEV_IOCTL_VERSION_CMD, AUTOFS_DEV_IOCTL_OPENMOUNT_CMD and
AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD the ioctlfd is validated and if it is
not a valid descriptor or doesn't correspond to an autofs mount point
an error of -EBADF, -ENOTTY or -EINVAL (not an autofs descriptor) is
returned.

device ioctl operation 목록

235-245

이 interface의 사용 예는 autofs 5.0.4 이상 배포본의 `lib/dev-ioctl-lib.c`에서 볼 수 있습니다. tarball은 kernel.org의 `/pub/linux/daemons/autofs/v5`에 있습니다.

autofs device ioctl
operation기능
`VERSION`device ioctl interface version
`PROTOVER`, `PROTOSUBVER`autofs protocol version
`OPENMOUNT`, `CLOSEMOUNT`covered mount handle 획득·해제
`READY`, `FAIL`mount/expire completion status
`SETPIPEFD`, `CATATONIC`daemon pipe 재연결과 비활성화
`TIMEOUT`, `EXPIRE`expire 정책과 request
`REQUESTER`last trigger UID/GID
`ASKUMOUNT`, `ISMOUNTPOINT`busy와 mountpoint 상태

뒤 절에서 설명하는 operation을 기능별로 묶었습니다.

The ioctls
==========

An example of an implementation which uses this interface can be seen
in autofs version 5.0.4 and later in file lib/dev-ioctl-lib.c of the
distribution tar available for download from kernel.org in directory
/pub/linux/daemons/autofs/v5.

The device node ioctl operations implemented by this interface are:

`AUTOFS_DEV_IOCTL_VERSION`

246-255

`AUTOFS_DEV_IOCTL_VERSION`은 autofs device ioctl kernel module 구현의 major/minor version을 얻습니다. 초기화한 `struct autofs_dev_ioctl`을 입력으로 받아 같은 구조체의 version field를 채웁니다.

성공하면 0을 반환하고 version mismatch가 발견되면 `-EINVAL`을 반환합니다.

VERSION ioctl
`init_autofs_dev_ioctl()``AUTOFS_DEV_IOCTL_VERSION` 호출kernel major/minor version 기록성공 0 또는 mismatch `-EINVAL`

초기화된 구조체가 version 결과를 받습니다.

AUTOFS_DEV_IOCTL_VERSION
------------------------

Get the major and minor version of the autofs device ioctl kernel module
implementation. It requires an initialized struct autofs_dev_ioctl as an
input parameter and sets the version information in the passed in structure.
It returns 0 on success or the error -EINVAL if a version mismatch is
detected.

`PROTOVER`와 `PROTOSUBVER`

256-266

`AUTOFS_DEV_IOCTL_PROTOVER_CMD`와 `AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD`는 loaded module이 이해하는 autofs protocol의 major/minor version을 얻습니다.

초기화한 `struct autofs_dev_ioctl`의 `ioctlfd`를 valid autofs mount descriptor로 설정합니다. 결과는 각각 `struct args_protover.version`과 `struct args_protosubver.sub_version`에 기록됩니다. 성공은 0, validation 실패는 해당 negative error code입니다.

protocol version ioctl
command결과 field
`AUTOFS_DEV_IOCTL_PROTOVER_CMD``args_protover.version`
`AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD``args_protosubver.sub_version`

두 command의 결과 field입니다.

AUTOFS_DEV_IOCTL_PROTOVER_CMD and AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD
------------------------------------------------------------------

Get the major and minor version of the autofs protocol version understood
by loaded module. This call requires an initialized struct autofs_dev_ioctl
with the ioctlfd field set to a valid autofs mount point descriptor
and sets the requested version number in version field of struct args_protover
or sub_version field of struct args_protosubver. These commands return
0 on success or one of the negative error codes if validation fails.

`OPENMOUNT`와 `CLOSEMOUNT`

267-282

`AUTOFS_DEV_IOCTL_OPENMOUNT`는 autofs가 관리하는 mount point path의 FD를 얻고 `CLOSEMOUNT`는 해제합니다.

open은 초기화한 구조체에 `path`를 넣고 `size`를 조정하며 `args_openmount.devid`를 autofs mount device number로 설정해야 합니다. device number는 `/proc/mounts`에 표시된 mount option에서 얻습니다.

close는 open에서 받은 descriptor를 `ioctlfd`에 넣습니다. 일반 `close(2)`로도 해제할 수 있어 process exit 때 열린 descriptor는 모두 닫힙니다. `CLOSEMOUNT`는 interface의 완전성과 userspace 구현 일관성을 위해 포함됐습니다. 원문의 `struct autofs_dev_ioct` 표기는 문맥상 `struct autofs_dev_ioctl`입니다.

covered mount handle
`/proc/mounts`에서 autofs `devid` 확인`path`, `size`, `args_openmount.devid` 설정`OPENMOUNT`로 `ioctlfd` 획득control operation 수행`CLOSEMOUNT` 또는 `close(2)`로 해제

device number로 특정 autofs mount FD를 여닫습니다.

AUTOFS_DEV_IOCTL_OPENMOUNT and AUTOFS_DEV_IOCTL_CLOSEMOUNT
----------------------------------------------------------

Obtain and release a file descriptor for an autofs managed mount point
path. The open call requires an initialized struct autofs_dev_ioctl with
the path field set and the size field adjusted appropriately as well
as the devid field of struct args_openmount set to the device number of
the autofs mount. The device number can be obtained from the mount options
shown in /proc/mounts. The close call requires an initialized struct
autofs_dev_ioct with the ioctlfd field set to the descriptor obtained
from the open call. The release of the file descriptor can also be done
with close(2) so any open descriptors will also be closed at process exit.
The close call is included in the implemented operations largely for
completeness and to provide for a consistent user space implementation.

`READY`와 `FAIL` completion

283-294

`AUTOFS_DEV_IOCTL_READY_CMD`와 `AUTOFS_DEV_IOCTL_FAIL_CMD`는 userspace에서 kernel로 mount 또는 expire 결과 status를 반환합니다.

open에서 얻은 descriptor를 `ioctlfd`에 넣고, 앞선 mount/expire request에서 받은 wait queue token number를 `args_ready.token` 또는 `args_fail.token`에 설정합니다. `args_fail.status`는 operation의 errno이며 성공일 때 0입니다.

mount/expire completion
commandtokenstatus
`READY_CMD``args_ready.token`성공 완료
`FAIL_CMD``args_fail.token``args_fail.status`의 실제 errno

wait token과 status 전달 field입니다.

AUTOFS_DEV_IOCTL_READY_CMD and AUTOFS_DEV_IOCTL_FAIL_CMD
--------------------------------------------------------

Return mount and expire result status from user space to the kernel.
Both of these calls require an initialized struct autofs_dev_ioctl
with the ioctlfd field set to the descriptor obtained from the open
call and the token field of struct args_ready or struct args_fail set
to the wait queue token number, received by user space in the foregoing
mount or expire request. The status field of struct args_fail is set to
the errno of the operation. It is set to 0 on success.

`SETPIPEFD` daemon 재연결

295-312

`AUTOFS_DEV_IOCTL_SETPIPEFD_CMD`는 kernel과 daemon 통신에 쓰는 pipe FD를 설정합니다. 보통 mount option으로 설정하지만 기존 mount에 재연결할 때 새 kernel pipe descriptor를 알려야 합니다.

잘못된 pipe descriptor 설정으로부터 mount를 보호하기 위해 대상 autofs mount가 먼저 catatonic 상태여야 합니다.

초기화한 구조체의 `ioctlfd`에 open descriptor를, `args_setpipefd.pipefd`에 pipe descriptor를 넣습니다. 성공하면 controlling process, 예를 들어 owner `automount(8)` daemon 식별용 process group ID도 caller의 process group으로 설정합니다.

daemon pipe 교체
기존 mount를 catatonic 상태로 전환새 daemon communication pipe 생성`ioctlfd`와 `args_setpipefd.pipefd` 설정`SETPIPEFD_CMD` 호출caller process group을 controller PGID로 기록

catatonic mount에 새 daemon channel을 연결합니다.

AUTOFS_DEV_IOCTL_SETPIPEFD_CMD
------------------------------

Set the pipe file descriptor used for kernel communication to the daemon.
Normally this is set at mount time using an option but when reconnecting
to a existing mount we need to use this to tell the autofs mount about
the new kernel pipe descriptor. In order to protect mounts against
incorrectly setting the pipe descriptor we also require that the autofs
mount be catatonic (see next call).

The call requires an initialized struct autofs_dev_ioctl with the
ioctlfd field set to the descriptor obtained from the open call and
the pipefd field of struct args_setpipefd set to descriptor of the pipe.
On success the call also sets the process group id used to identify the
controlling process (eg. the owning automount(8) daemon) to the process
group of the caller.

`CATATONIC` 상태

313-323

`AUTOFS_DEV_IOCTL_CATATONIC_CMD`는 autofs mount point를 catatonic 상태로 만듭니다. 그 뒤 mount request를 더 이상 발행하지 않고 kernel communication pipe descriptor를 해제하며 queue에 남은 모든 wait를 풀어 줍니다.

호출할 때 초기화한 `struct autofs_dev_ioctl`의 `ioctlfd`를 open에서 얻은 descriptor로 설정합니다.

catatonic 전환
valid autofs `ioctlfd` 설정`CATATONIC_CMD` 호출새 mount request 중단kernel communication pipe 해제남은 wait queue release

daemon 연결을 안전하게 끊는 효과입니다.

AUTOFS_DEV_IOCTL_CATATONIC_CMD
------------------------------

Make the autofs mount point catatonic. The autofs mount will no longer
issue mount requests, the kernel communication pipe descriptor is released
and any remaining waits in the queue released.

The call requires an initialized struct autofs_dev_ioctl with the
ioctlfd field set to the descriptor obtained from the open call.

`TIMEOUT` expire timeout

324-332

`AUTOFS_DEV_IOCTL_TIMEOUT_CMD`는 지정 autofs mount point 안의 mount에 적용할 expire timeout을 설정합니다.

초기화한 `struct autofs_dev_ioctl`의 `ioctlfd`를 open에서 얻은 descriptor로 설정해 호출합니다.

TIMEOUT ioctl 입력
입력의미
초기화 구조체`init_autofs_dev_ioctl()` 결과
`ioctlfd`대상 autofs mount point descriptor
timeout argument하위 mount expire 시간

timeout 설정에 필요한 공통 handle입니다.

AUTOFS_DEV_IOCTL_TIMEOUT_CMD
----------------------------

Set the expire timeout for mounts within an autofs mount point.

The call requires an initialized struct autofs_dev_ioctl with the
ioctlfd field set to the descriptor obtained from the open call.

`REQUESTER` UID/GID 복원

333-350

`AUTOFS_DEV_IOCTL_REQUESTER_CMD`는 주어진 path dentry에서 mount를 마지막으로 성공적으로 trigger한 process의 UID/GID를 반환합니다.

구조체의 `path`를 대상 mount point로 설정하고 `size`를 그 길이에 맞게 조정합니다. 반환 시 `struct args_requester.uid`와 `.gid`에 값이 들어갑니다.

active mount가 있는 autofs tree를 재구성할 때 기존 process UID/GID 또는 문자열 변형이 map entry lookup의 macro로 사용됐을 수 있습니다. 이 command가 그 값을 userspace에 제공하여 같은 map lookup을 재현하게 합니다.

requester identity 복원
대상 mount point `path` 지정`REQUESTER_CMD` 호출`args_requester.uid/gid` 반환UID/GID string macro 재구성기존 조건과 같은 autofs map lookup 수행

mount trigger identity를 map macro에 다시 사용합니다.

AUTOFS_DEV_IOCTL_REQUESTER_CMD
------------------------------

Return the uid and gid of the last process to successfully trigger a the
mount on the given path dentry.

The call requires an initialized struct autofs_dev_ioctl with the path
field set to the mount point in question and the size field adjusted
appropriately. Upon return the uid field of struct args_requester contains
the uid and gid field the gid.

When reconstructing an autofs mount tree with active mounts we need to
re-connect to mounts that may have used the original process uid and
gid (or string variations of them) for mount lookups within the map entry.
This call provides the ability to obtain this uid and gid so they may be
used by user space for the mount map lookups.

`EXPIRE` request

351-369

`AUTOFS_DEV_IOCTL_EXPIRE_CMD`는 kernel에 autofs mount expire request를 보냅니다. 보통 더 이상 expire candidate가 없을 때까지 반복 호출합니다.

초기화 구조체의 `ioctlfd`를 open descriptor로 설정합니다. `args_expire.how`에 `AUTOFS_EXP_IMMEDIATE`를 넣으면 mount timeout과 무관한 즉시 expire, `AUTOFS_EXP_FORCED`를 넣으면 busy 여부와 무관한 강제 expire를 요청합니다.

candidate가 없으면 ioctl은 -1을 반환하고 errno를 `EAGAIN`으로 설정합니다. kernel module은 `ioctlfd`에 대응하는 mount에서 expire 가능한 항목을 찾고 daemon에 expire request를 보낸 뒤 완료를 기다립니다.

autofs expire loop
대상 mount `ioctlfd` 설정normal/immediate/forced `how` 선택kernel이 expire candidate 탐색daemon에 expire request와 wait token 전달daemon completion을 기다림candidate가 없으면 `EAGAIN`

candidate를 하나씩 daemon과 협력해 처리합니다.

AUTOFS_DEV_IOCTL_EXPIRE_CMD
---------------------------

Issue an expire request to the kernel for an autofs mount. Typically
this ioctl is called until no further expire candidates are found.

The call requires an initialized struct autofs_dev_ioctl with the
ioctlfd field set to the descriptor obtained from the open call. In
addition an immediate expire that's independent of the mount timeout,
and a forced expire that's independent of whether the mount is busy,
can be requested by setting the how field of struct args_expire to
AUTOFS_EXP_IMMEDIATE or AUTOFS_EXP_FORCED, respectively . If no
expire candidates can be found the ioctl returns -1 with errno set to
EAGAIN.

This call causes the kernel module to check the mount corresponding
to the given ioctlfd for mounts that can be expired, issues an expire
request back to the daemon and waits for completion.

`ASKUMOUNT` busy 검사

370-380

`AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD`는 autofs mount point가 사용 중인지 검사합니다.

초기화 구조체의 `ioctlfd`를 open descriptor로 설정합니다. 결과는 `struct args_askumount.may_umount`에 기록되며 원문 기준 1은 busy, 0은 그 외 상태입니다.

ASKUMOUNT 결과
의미
`1`mount point가 busy
`0`busy가 아님

원문이 정의한 `may_umount` 값을 그대로 보존했습니다.

AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD
------------------------------

Checks if an autofs mount point is in use.

The call requires an initialized struct autofs_dev_ioctl with the
ioctlfd field set to the descriptor obtained from the open call and
it returns the result in the may_umount field of struct args_askumount,
1 for busy and 0 otherwise.

`ISMOUNTPOINT`의 FD·path 검사

381-410

`AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD`는 path가 mountpoint인지 확인합니다. 두 변형 모두 `path`와 조정된 `size`를 사용합니다.

첫 변형은 `ioctlfd`로 특정 mount를 지정합니다. 두 번째는 path를 사용하고 필요하면 `args_ismountpoint.in.type`에 autofs mount type을 설정합니다. mountpoint이면 1을 반환하고 `out.devid`에 device number, `out.magic`에 관련 superblock magic을 기록합니다. 아니면 0입니다. device number는 두 경우 모두 `new_encode_dev()` 형식으로 반환됩니다.

FD를 제공하면 mounted stack 맨 위가 아니어도 해당 descriptor의 특정 mount를 찾습니다. descriptor path 자체가 mountpoint이거나 root mount 없는 multi-mount처럼 내부에 mount를 포함해도 mountpoint로 간주합니다. covering mount가 있으면 그 super magic도 반환합니다.

path 방식에서는 `ioctlfd=-1`로 두고 lookup한 path가 mount root인지 확인합니다. type도 주어지면 특정 autofs mount와 일치해야 하며 일치하지 않으면 실패합니다. mount root이면 1과 super magic을, 아니면 0을 반환합니다.

ISMOUNTPOINT 두 검사 방식
방식입력판정·출력
specific FD`ioctlfd` + `path`해당 mount 또는 contained mount, covering super magic
path lookup`ioctlfd=-1` + `path`lookup path가 mount root인지 검사
typed pathpath + `in.type`특정 autofs mount type 일치 요구
mountpoint공통`1`, `out.devid`, `out.magic`
not mountpoint공통`0`, encoded `out.devid`

FD 기반 stack 검사와 path root 검사를 비교합니다.

AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD
---------------------------------

Check if the given path is a mountpoint.

The call requires an initialized struct autofs_dev_ioctl. There are two
possible variations. Both use the path field set to the path of the mount
point to check and the size field adjusted appropriately. One uses the
ioctlfd field to identify a specific mount point to check while the other
variation uses the path and optionally in.type field of struct args_ismountpoint
set to an autofs mount type. The call returns 1 if this is a mount point
and sets out.devid field to the device number of the mount and out.magic
field to the relevant super block magic number (described below) or 0 if
it isn't a mountpoint. In both cases the device number (as returned
by new_encode_dev()) is returned in out.devid field.

If supplied with a file descriptor we're looking for a specific mount,
not necessarily at the top of the mounted stack. In this case the path
the descriptor corresponds to is considered a mountpoint if it is itself
a mountpoint or contains a mount, such as a multi-mount without a root
mount. In this case we return 1 if the descriptor corresponds to a mount
point and also returns the super magic of the covering mount if there
is one or 0 if it isn't a mountpoint.

If a path is supplied (and the ioctlfd field is set to -1) then the path
is looked up and is checked to see if it is the root of a mount. If a
type is also given we are looking for a particular autofs mount and if
a match isn't found a fail is returned. If the located path is the
root of a mount 1 is returned along with the super magic of the mount
or 0 otherwise.