← Documents Documentation/filesystems/nfs/localio.rst GitHub 원문 ↗

Linux 6.18.37 · Filesystems / NFS

NFS LOCALIO

NFS LOCALIO locality handshake, auxiliary RPC, lifetime interlock, direct I/O와 보안의 전문 번역입니다.

Source pathDocumentation/filesystems/nfs/localio.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약·해설

localio.rst:1-357

NFS LOCALIO는 기존 NFS connection의 auxiliary RPC로 client와 server가 같은 Linux host인지 single-use UUID를 통해 검증하고, local인 경우 open/read/write/commit에서 SUNRPC와 XDR을 우회합니다. IP address 비교와 달리 iptables·container namespace에서도 locality를 견고하게 판별합니다.

직접 I/O 경로는 `nfs_uuid_t`, per-CPU `nfsd_net_ref`, RCU와 명시적 get/put으로 container별 NFSD network namespace의 수명을 보호합니다. Security는 기존 `AUTH_UNIX`/`AUTH_SYS`, `auth_domain`, export ID translation을 재사용하며 end-to-end O_DIRECT는 별도 parameter로 opt-in합니다.

LOCALIO 전체 수명주기
UUID_IS_LOCAL로 같은 host 검증nfs_uuid_t를 nfsd_serv clients_list에 연결nfsd_net_try_get()으로 namespace 수명 고정nfsd_file을 열어 backing filesystem에 직접 I/Onfsd_file_put_local()로 reference 해제-ENXIO 또는 server restart 시 nfs_local_probe() 재시도

Discovery, resource interlock, direct I/O와 recovery를 연결합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 ===========
2 NFS LOCALIO
3 ===========
4
5 Overview
6 ========
7
8 The LOCALIO auxiliary RPC protocol allows the Linux NFS client and
9 server to reliably handshake to determine if they are on the same
10 host. Select "NFS client and server support for LOCALIO auxiliary
11 protocol" in menuconfig to enable CONFIG_NFS_LOCALIO in the kernel
12 config (both CONFIG_NFS_FS and CONFIG_NFSD must also be enabled).
13
14 Once an NFS client and server handshake as "local", the client will
15 bypass the network RPC protocol for read, write and commit operations.
16 Due to this XDR and RPC bypass, these operations will operate faster.
17
18 The LOCALIO auxiliary protocol's implementation, which uses the same
19 connection as NFS traffic, follows the pattern established by the NFS
20 ACL protocol extension.
21
22 The LOCALIO auxiliary protocol is needed to allow robust discovery of
23 clients local to their servers. In a private implementation that
24 preceded use of this LOCALIO protocol, a fragile sockaddr network
25 address based match against all local network interfaces was attempted.
26 But unlike the LOCALIO protocol, the sockaddr-based matching didn't
27 handle use of iptables or containers.
28
29 The robust handshake between local client and server is just the
30 beginning, the ultimate use case this locality makes possible is the
31 client is able to open files and issue reads, writes and commits
32 directly to the server without having to go over the network. The
33 requirement is to perform these loopback NFS operations as efficiently
34 as possible, this is particularly useful for container use cases
35 (e.g. kubernetes) where it is possible to run an IO job local to the
36 server.
37
38 The performance advantage realized from LOCALIO's ability to bypass
39 using XDR and RPC for reads, writes and commits can be extreme, e.g.:
40
41 fio for 20 secs with directio, qd of 8, 16 libaio threads:
42 - With LOCALIO:
43 4K read: IOPS=979k, BW=3825MiB/s (4011MB/s)(74.7GiB/20002msec)
44 4K write: IOPS=165k, BW=646MiB/s (678MB/s)(12.6GiB/20002msec)
45 128K read: IOPS=402k, BW=49.1GiB/s (52.7GB/s)(982GiB/20002msec)
46 128K write: IOPS=11.5k, BW=1433MiB/s (1503MB/s)(28.0GiB/20004msec)
47
48 - Without LOCALIO:
49 4K read: IOPS=79.2k, BW=309MiB/s (324MB/s)(6188MiB/20003msec)
50 4K write: IOPS=59.8k, BW=234MiB/s (245MB/s)(4671MiB/20002msec)
51 128K read: IOPS=33.9k, BW=4234MiB/s (4440MB/s)(82.7GiB/20004msec)
52 128K write: IOPS=11.5k, BW=1434MiB/s (1504MB/s)(28.0GiB/20011msec)
53
54 fio for 20 secs with directio, qd of 8, 1 libaio thread:
55 - With LOCALIO:
56 4K read: IOPS=230k, BW=898MiB/s (941MB/s)(17.5GiB/20001msec)
57 4K write: IOPS=22.6k, BW=88.3MiB/s (92.6MB/s)(1766MiB/20001msec)
58 128K read: IOPS=38.8k, BW=4855MiB/s (5091MB/s)(94.8GiB/20001msec)
59 128K write: IOPS=11.4k, BW=1428MiB/s (1497MB/s)(27.9GiB/20001msec)
60
61 - Without LOCALIO:
62 4K read: IOPS=77.1k, BW=301MiB/s (316MB/s)(6022MiB/20001msec)
63 4K write: IOPS=32.8k, BW=128MiB/s (135MB/s)(2566MiB/20001msec)
64 128K read: IOPS=24.4k, BW=3050MiB/s (3198MB/s)(59.6GiB/20001msec)
65 128K write: IOPS=11.4k, BW=1430MiB/s (1500MB/s)(27.9GiB/20001msec)
66
67 FAQ
68 ===
69
70 1. What are the use cases for LOCALIO?
71
72 a. Workloads where the NFS client and server are on the same host
73 realize improved IO performance. In particular, it is common when
74 running containerised workloads for jobs to find themselves
75 running on the same host as the knfsd server being used for
76 storage.
77
78 2. What are the requirements for LOCALIO?
79
80 a. Bypass use of the network RPC protocol as much as possible. This
81 includes bypassing XDR and RPC for open, read, write and commit
82 operations.
83 b. Allow client and server to autonomously discover if they are
84 running local to each other without making any assumptions about
85 the local network topology.
86 c. Support the use of containers by being compatible with relevant
87 namespaces (e.g. network, user, mount).
88 d. Support all versions of NFS. NFSv3 is of particular importance
89 because it has wide enterprise usage and pNFS flexfiles makes use
90 of it for the data path.
91
92 3. Why doesn’t LOCALIO just compare IP addresses or hostnames when
93 deciding if the NFS client and server are co-located on the same
94 host?
95
96 Since one of the main use cases is containerised workloads, we cannot
97 assume that IP addresses will be shared between the client and
98 server. This sets up a requirement for a handshake protocol that
99 needs to go over the same connection as the NFS traffic in order to
100 identify that the client and the server really are running on the
101 same host. The handshake uses a secret that is sent over the wire,
102 and can be verified by both parties by comparing with a value stored
103 in shared kernel memory if they are truly co-located.
104
105 4. Does LOCALIO improve pNFS flexfiles?
106
107 Yes, LOCALIO complements pNFS flexfiles by allowing it to take
108 advantage of NFS client and server locality. Policy that initiates
109 client IO as closely to the server where the data is stored naturally
110 benefits from the data path optimization LOCALIO provides.
111
112 5. Why not develop a new pNFS layout to enable LOCALIO?
113
114 A new pNFS layout could be developed, but doing so would put the
115 onus on the server to somehow discover that the client is co-located
116 when deciding to hand out the layout.
117 There is value in a simpler approach (as provided by LOCALIO) that
118 allows the NFS client to negotiate and leverage locality without
119 requiring more elaborate modeling and discovery of such locality in a
120 more centralized manner.
121
122 6. Why is having the client perform a server-side file OPEN, without
123 using RPC, beneficial? Is the benefit pNFS specific?
124
125 Avoiding the use of XDR and RPC for file opens is beneficial to
126 performance regardless of whether pNFS is used. Especially when
127 dealing with small files its best to avoid going over the wire
128 whenever possible, otherwise it could reduce or even negate the
129 benefits of avoiding the wire for doing the small file I/O itself.
130 Given LOCALIO's requirements the current approach of having the
131 client perform a server-side file open, without using RPC, is ideal.
132 If in the future requirements change then we can adapt accordingly.
133
134 7. Why is LOCALIO only supported with UNIX Authentication (AUTH_UNIX)?
135
136 Strong authentication is usually tied to the connection itself. It
137 works by establishing a context that is cached by the server, and
138 that acts as the key for discovering the authorisation token, which
139 can then be passed to rpc.mountd to complete the authentication
140 process. On the other hand, in the case of AUTH_UNIX, the credential
141 that was passed over the wire is used directly as the key in the
142 upcall to rpc.mountd. This simplifies the authentication process, and
143 so makes AUTH_UNIX easier to support.
144
145 8. How do export options that translate RPC user IDs behave for LOCALIO
146 operations (eg. root_squash, all_squash)?
147
148 Export options that translate user IDs are managed by nfsd_setuser()
149 which is called by nfsd_setuser_and_check_port() which is called by
150 __fh_verify(). So they get handled exactly the same way for LOCALIO
151 as they do for non-LOCALIO.
152
153 9. How does LOCALIO make certain that object lifetimes are managed
154 properly given NFSD and NFS operate in different contexts?
155
156 See the detailed "NFS Client and Server Interlock" section below.
157
158 RPC
159 ===
160
161 The LOCALIO auxiliary RPC protocol consists of a single "UUID_IS_LOCAL"
162 RPC method that allows the Linux NFS client to verify the local Linux
163 NFS server can see the nonce (single-use UUID) the client generated and
164 made available in nfs_common. This protocol isn't part of an IETF
165 standard, nor does it need to be considering it is Linux-to-Linux
166 auxiliary RPC protocol that amounts to an implementation detail.
167
168 The UUID_IS_LOCAL method encodes the client generated uuid_t in terms of
169 the fixed UUID_SIZE (16 bytes). The fixed size opaque encode and decode
170 XDR methods are used instead of the less efficient variable sized
171 methods.
172
173 The RPC program number for the NFS_LOCALIO_PROGRAM is 400122 (as assigned
174 by IANA, see https://www.iana.org/assignments/rpc-program-numbers/ ):
175 Linux Kernel Organization 400122 nfslocalio
176
177 The LOCALIO protocol spec in rpcgen syntax is::
178
179 /* raw RFC 9562 UUID */
180 #define UUID_SIZE 16
181 typedef u8 uuid_t<UUID_SIZE>;
182
183 program NFS_LOCALIO_PROGRAM {
184 version LOCALIO_V1 {
185 void
186 NULL(void) = 0;
187
188 void
189 UUID_IS_LOCAL(uuid_t) = 1;
190 } = 1;
191 } = 400122;
192
193 LOCALIO uses the same transport connection as NFS traffic. As such,
194 LOCALIO is not registered with rpcbind.
195
196 NFS Common and Client/Server Handshake
197 ======================================
198
199 fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS client
200 to generate a nonce (single-use UUID) and associated short-lived
201 nfs_uuid_t struct, register it with nfs_common for subsequent lookup and
202 verification by the NFS server and if matched the NFS server populates
203 members in the nfs_uuid_t struct. The NFS client then uses nfs_common to
204 transfer the nfs_uuid_t from its nfs_uuids to the nn->nfsd_serv
205 clients_list from the nfs_common's uuids_list. See:
206 fs/nfs/localio.c:nfs_local_probe()
207
208 nfs_common's nfs_uuids list is the basis for LOCALIO enablement, as such
209 it has members that point to nfsd memory for direct use by the client
210 (e.g. 'net' is the server's network namespace, through it the client can
211 access nn->nfsd_serv with proper rcu read access). It is this client
212 and server synchronization that enables advanced usage and lifetime of
213 objects to span from the host kernel's nfsd to per-container knfsd
214 instances that are connected to nfs client's running on the same local
215 host.
216
217 NFS Client and Server Interlock
218 ===============================
219
220 LOCALIO provides the nfs_uuid_t object and associated interfaces to
221 allow proper network namespace (net-ns) and NFSD object refcounting.
222
223 LOCALIO required the introduction and use of NFSD's percpu nfsd_net_ref
224 to interlock nfsd_shutdown_net() and nfsd_open_local_fh(), to ensure
225 each net-ns is not destroyed while in use by nfsd_open_local_fh(), and
226 warrants a more detailed explanation:
227
228 nfsd_open_local_fh() uses nfsd_net_try_get() before opening its
229 nfsd_file handle and then the caller (NFS client) must drop the
230 reference for the nfsd_file and associated net-ns using
231 nfsd_file_put_local() once it has completed its IO.
232
233 This interlock working relies heavily on nfsd_open_local_fh() being
234 afforded the ability to safely deal with the possibility that the
235 NFSD's net-ns (and nfsd_net by association) may have been destroyed
236 by nfsd_destroy_serv() via nfsd_shutdown_net().
237
238 This interlock of the NFS client and server has been verified to fix an
239 easy to hit crash that would occur if an NFSD instance running in a
240 container, with a LOCALIO client mounted, is shutdown. Upon restart of
241 the container and associated NFSD, the client would go on to crash due
242 to NULL pointer dereference that occurred due to the LOCALIO client's
243 attempting to nfsd_open_local_fh() without having a proper reference on
244 NFSD's net-ns.
245
246 NFS Client issues IO instead of Server
247 ======================================
248
249 Because LOCALIO is focused on protocol bypass to achieve improved IO
250 performance, alternatives to the traditional NFS wire protocol (SUNRPC
251 with XDR) must be provided to access the backing filesystem.
252
253 See fs/nfs/localio.c:nfs_local_open_fh() and
254 fs/nfsd/localio.c:nfsd_open_local_fh() for the interface that makes
255 focused use of select nfs server objects to allow a client local to a
256 server to open a file pointer without needing to go over the network.
257
258 The client's fs/nfs/localio.c:nfs_local_open_fh() will call into the
259 server's fs/nfsd/localio.c:nfsd_open_local_fh() and carefully access
260 both the associated nfsd network namespace and nn->nfsd_serv in terms of
261 RCU. If nfsd_open_local_fh() finds that the client no longer sees valid
262 nfsd objects (be it struct net or nn->nfsd_serv) it returns -ENXIO
263 to nfs_local_open_fh() and the client will try to reestablish the
264 LOCALIO resources needed by calling nfs_local_probe() again. This
265 recovery is needed if/when an nfsd instance running in a container were
266 to reboot while a LOCALIO client is connected to it.
267
268 Once the client has an open nfsd_file pointer it will issue reads,
269 writes and commits directly to the underlying local filesystem (normally
270 done by the nfs server). As such, for these operations, the NFS client
271 is issuing IO to the underlying local filesystem that it is sharing with
272 the NFS server. See: fs/nfs/localio.c:nfs_local_doio() and
273 fs/nfs/localio.c:nfs_local_commit().
274
275 With normal NFS that makes use of RPC to issue IO to the server, if an
276 application uses O_DIRECT the NFS client will bypass the pagecache but
277 the NFS server will not. The NFS server's use of buffered IO affords
278 applications to be less precise with their alignment when issuing IO to
279 the NFS client. But if all applications properly align their IO, LOCALIO
280 can be configured to use end-to-end O_DIRECT semantics from the NFS
281 client to the underlying local filesystem, that it is sharing with
282 the NFS server, by setting the 'localio_O_DIRECT_semantics' nfs module
283 parameter to Y, e.g.:
284
285 echo Y > /sys/module/nfs/parameters/localio_O_DIRECT_semantics
286
287 Once enabled, it will cause LOCALIO to use end-to-end O_DIRECT semantics
288 (but again, this may cause IO to fail if applications do not properly
289 align their IO).
290
291 Security
292 ========
293
294 LOCALIO is only supported when UNIX-style authentication (AUTH_UNIX, aka
295 AUTH_SYS) is used.
296
297 Care is taken to ensure the same NFS security mechanisms are used
298 (authentication, etc) regardless of whether LOCALIO or regular NFS
299 access is used. The auth_domain established as part of the traditional
300 NFS client access to the NFS server is also used for LOCALIO.
301
302 Relative to containers, LOCALIO gives the client access to the network
303 namespace the server has. This is required to allow the client to access
304 the server's per-namespace nfsd_net struct. With traditional NFS, the
305 client is afforded this same level of access (albeit in terms of the NFS
306 protocol via SUNRPC). No other namespaces (user, mount, etc) have been
307 altered or purposely extended from the server to the client.
308
309 Module Parameters
310 =================
311
312 /sys/module/nfs/parameters/localio_enabled (bool)
313 controls if LOCALIO is enabled, defaults to Y. If client and server are
314 local but 'localio_enabled' is set to N then LOCALIO will not be used.
315
316 /sys/module/nfs/parameters/localio_O_DIRECT_semantics (bool)
317 controls if O_DIRECT extends down to the underlying filesystem, defaults
318 to N. Application IO must be logical blocksize aligned, otherwise
319 O_DIRECT will fail.
320
321 /sys/module/nfsv3/parameters/nfs3_localio_probe_throttle (uint)
322 controls if NFSv3 read and write IOs will trigger (re)enabling of
323 LOCALIO every N (nfs3_localio_probe_throttle) IOs, defaults to 0
324 (disabled). Must be power-of-2, admin keeps all the pieces if they
325 misconfigure (too low a value or non-power-of-2).
326
327 Testing
328 =======
329
330 The LOCALIO auxiliary protocol and associated NFS LOCALIO read, write
331 and commit access have proven stable against various test scenarios:
332
333 - Client and server both on the same host.
334
335 - All permutations of client and server support enablement for both
336 local and remote client and server.
337
338 - Testing against NFS storage products that don't support the LOCALIO
339 protocol was also performed.
340
341 - Client on host, server within a container (for both v3 and v4.2).
342 The container testing was in terms of podman managed containers and
343 includes successful container stop/restart scenario.
344
345 - Formalizing these test scenarios in terms of existing test
346 infrastructure is on-going. Initial regular coverage is provided in
347 terms of ktest running xfstests against a LOCALIO-enabled NFS loopback
348 mount configuration, and includes lockdep and KASAN coverage, see:
349 https://evilpiepirate.org/~testdashboard/ci?user=snitzer&branch=snitm-nfs-next
350 https://github.com/koverstreet/ktest
351
352 - Various kdevops testing (in terms of "Chuck's BuildBot") has been
353 performed to regularly verify the LOCALIO changes haven't caused any
354 regressions to non-LOCALIO NFS use cases.
355
356 - All of Hammerspace's various sanity tests pass with LOCALIO enabled
357 (this includes numerous pNFS and flexfiles tests).
358

3. 한국어 전문 번역

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

LOCALIO handshake와 network RPC 우회

1-40

LOCALIO auxiliary RPC protocol은 Linux NFS client와 server가 같은 host에 있는지 신뢰성 있게 handshake하여 판별하게 합니다. Kernel config에서 `NFS client and server support for LOCALIO auxiliary protocol`을 선택해 `CONFIG_NFS_LOCALIO`를 켜며, `CONFIG_NFS_FS`와 `CONFIG_NFSD`도 함께 활성화해야 합니다.

Client와 server가 local이라고 확인되면 client는 read, write, commit operation에서 network RPC protocol을 우회합니다. XDR encode/decode와 RPC 전달을 생략하므로 같은 host의 backing filesystem에 더 빠르게 접근할 수 있습니다. LOCALIO는 NFS traffic과 동일한 connection을 사용하며 NFS ACL protocol extension이 세운 구현 pattern을 따릅니다.

이 auxiliary protocol은 local client를 견고하게 발견하기 위해 필요합니다. 이전 private 구현은 모든 local network interface의 `sockaddr`와 주소를 비교했지만 iptables와 container 환경을 처리하지 못했습니다. IP address나 interface topology가 달라도 protocol handshake는 실제 kernel locality를 확인할 수 있습니다.

Handshake는 시작일 뿐이며 최종 목적은 client가 network를 거치지 않고 server-side file을 열어 read, write, commit을 직접 수행하게 하는 것입니다. Loopback NFS operation을 최대한 효율화하며, 특히 Kubernetes 같은 container 환경에서 I/O job이 storage server와 같은 host에 배치될 때 유용합니다.

LOCALIO가 read, write, commit에서 XDR과 RPC를 제거하면 workload에 따라 성능 차이가 매우 커질 수 있습니다. 이어지는 fio 결과는 direct I/O, queue depth 8 조건에서 이를 예시하지만 특정 측정 환경의 결과이므로 일반적인 보장값으로 해석해서는 안 됩니다.

LOCALIO data path 선택
NFS client가 server와 기존 NFS connection 수립LOCALIO auxiliary RPC로 같은 host인지 검증Remote이면 일반 SUNRPC + XDR 경로 유지Local이면 open/read/write/commit의 network 경로 우회Backing filesystem에 직접 I/O 수행

동일 connection의 handshake 결과가 I/O 경로를 결정합니다.

===========
NFS LOCALIO
===========

Overview
========

The LOCALIO auxiliary RPC protocol allows the Linux NFS client and
server to reliably handshake to determine if they are on the same
host. Select "NFS client and server support for LOCALIO auxiliary
protocol" in menuconfig to enable CONFIG_NFS_LOCALIO in the kernel
config (both CONFIG_NFS_FS and CONFIG_NFSD must also be enabled).

Once an NFS client and server handshake as "local", the client will
bypass the network RPC protocol for read, write and commit operations.
Due to this XDR and RPC bypass, these operations will operate faster.

The LOCALIO auxiliary protocol's implementation, which uses the same
connection as NFS traffic, follows the pattern established by the NFS
ACL protocol extension.

The LOCALIO auxiliary protocol is needed to allow robust discovery of
clients local to their servers. In a private implementation that
preceded use of this LOCALIO protocol, a fragile sockaddr network
address based match against all local network interfaces was attempted.
But unlike the LOCALIO protocol, the sockaddr-based matching didn't
handle use of iptables or containers.

The robust handshake between local client and server is just the
beginning, the ultimate use case this locality makes possible is the
client is able to open files and issue reads, writes and commits
directly to the server without having to go over the network. The
requirement is to perform these loopback NFS operations as efficiently
as possible, this is particularly useful for container use cases
(e.g. kubernetes) where it is possible to run an IO job local to the
server.

The performance advantage realized from LOCALIO's ability to bypass
using XDR and RPC for reads, writes and commits can be extreme, e.g.:

fio direct I/O 측정 결과

41-66

첫 측정은 20초, direct I/O, queue depth 8, libaio thread 16개 조건입니다. LOCALIO 사용 시 4K read는 979k IOPS와 3825 MiB/s, 4K write는 165k IOPS와 646 MiB/s, 128K read는 402k IOPS와 49.1 GiB/s입니다. 128K write는 11.5k IOPS와 1433 MiB/s입니다.

같은 16-thread 조건에서 LOCALIO를 끄면 4K read는 79.2k IOPS, 4K write는 59.8k IOPS, 128K read는 33.9k IOPS로 낮아집니다. 128K write는 11.5k IOPS로 사실상 동일하여 workload와 operation에 따라 우회 효과가 달라짐을 보여 줍니다.

둘째 측정은 같은 시간·direct I/O·queue depth에서 libaio thread를 1개만 사용합니다. LOCALIO 사용 시 4K read 230k, 4K write 22.6k, 128K read 38.8k, 128K write 11.4k IOPS입니다. LOCALIO를 끄면 각각 77.1k, 32.8k, 24.4k, 11.4k IOPS입니다.

Single-thread 4K write는 이 표에서 LOCALIO 쪽이 더 낮고 128K write는 거의 차이가 없습니다. 따라서 LOCALIO의 이점은 단순한 일괄 배수가 아니라 XDR/RPC overhead 비중, concurrency, I/O size와 backing filesystem 동작에 좌우됩니다.

LOCALIO fio 결과
libaio threadsI/OLOCALIO일반 NFS
164K read979k IOPS79.2k IOPS
164K write165k IOPS59.8k IOPS
16128K read402k IOPS33.9k IOPS
16128K write11.5k IOPS11.5k IOPS
14K read230k IOPS77.1k IOPS
14K write22.6k IOPS32.8k IOPS
1128K read38.8k IOPS24.4k IOPS
1128K write11.4k IOPS11.4k IOPS

원문의 IOPS를 thread 수와 I/O 형태별로 비교합니다.

fio for 20 secs with directio, qd of 8, 16 libaio threads:
  - With LOCALIO:
    4K read:    IOPS=979k,  BW=3825MiB/s (4011MB/s)(74.7GiB/20002msec)
    4K write:   IOPS=165k,  BW=646MiB/s  (678MB/s)(12.6GiB/20002msec)
    128K read:  IOPS=402k,  BW=49.1GiB/s (52.7GB/s)(982GiB/20002msec)
    128K write: IOPS=11.5k, BW=1433MiB/s (1503MB/s)(28.0GiB/20004msec)

  - Without LOCALIO:
    4K read:    IOPS=79.2k, BW=309MiB/s  (324MB/s)(6188MiB/20003msec)
    4K write:   IOPS=59.8k, BW=234MiB/s  (245MB/s)(4671MiB/20002msec)
    128K read:  IOPS=33.9k, BW=4234MiB/s (4440MB/s)(82.7GiB/20004msec)
    128K write: IOPS=11.5k, BW=1434MiB/s (1504MB/s)(28.0GiB/20011msec)

fio for 20 secs with directio, qd of 8, 1 libaio thread:
  - With LOCALIO:
    4K read:    IOPS=230k,  BW=898MiB/s  (941MB/s)(17.5GiB/20001msec)
    4K write:   IOPS=22.6k, BW=88.3MiB/s (92.6MB/s)(1766MiB/20001msec)
    128K read:  IOPS=38.8k, BW=4855MiB/s (5091MB/s)(94.8GiB/20001msec)
    128K write: IOPS=11.4k, BW=1428MiB/s (1497MB/s)(27.9GiB/20001msec)

  - Without LOCALIO:
    4K read:    IOPS=77.1k, BW=301MiB/s  (316MB/s)(6022MiB/20001msec)
    4K write:   IOPS=32.8k, BW=128MiB/s  (135MB/s)(2566MiB/20001msec)
    128K read:  IOPS=24.4k, BW=3050MiB/s (3198MB/s)(59.6GiB/20001msec)
    128K write: IOPS=11.4k, BW=1430MiB/s (1500MB/s)(27.9GiB/20001msec)

사용 사례, 요구 사항과 locality 판별

67-120

LOCALIO의 주요 사용 사례는 NFS client와 server가 같은 host에서 실행되는 workload입니다. Containerized workload에서는 storage로 사용하는 knfsd server와 job이 같은 host에 놓이는 일이 흔하며, 이때 local I/O path가 성능을 개선합니다.

요구 사항은 네 가지입니다. 첫째 open, read, write, commit에서 가능한 한 XDR과 network RPC를 우회해야 합니다. 둘째 local network topology를 가정하지 않고 client와 server가 서로 local인지 자율적으로 발견해야 합니다. 셋째 network, user, mount namespace 같은 container 관련 namespace와 호환되어야 합니다. 넷째 NFSv3를 포함한 모든 NFS version을 지원해야 합니다. NFSv3는 enterprise에서 널리 사용되고 pNFS flexfiles data path에도 쓰이므로 특히 중요합니다.

IP address나 hostname만 비교하지 않는 이유는 container client와 server가 address를 공유한다고 가정할 수 없기 때문입니다. LOCALIO handshake는 NFS traffic과 같은 connection으로 secret을 전달합니다. 양쪽이 실제로 같은 host라면 shared kernel memory에 저장된 값과 비교해 그 secret을 모두 검증할 수 있습니다.

LOCALIO는 pNFS flexfiles가 client/server locality를 활용하게 하여 보완합니다. Data가 있는 server 가까이에서 client I/O를 시작하는 policy는 LOCALIO가 제공하는 data-path 최적화의 이점을 자연스럽게 얻습니다.

새 pNFS layout으로 같은 기능을 만들 수도 있지만 그러면 layout을 배포할 때 server가 client co-location을 발견해야 하는 부담이 생깁니다. LOCALIO는 client가 locality를 협상하고 활용하므로 중앙화된 정교한 locality model과 discovery가 필요하지 않은 더 단순한 접근입니다.

LOCALIO 설계 요구
요구구체적 의미
Protocol bypassOpen/read/write/commit의 XDR과 RPC 최소화
Topology 독립 discoveryIP·hostname 공유를 가정하지 않음
Namespace 호환Network, user, mount namespace 환경 지원
Version 범위NFSv3를 포함한 모든 NFS version
pNFS 연동Flexfiles data path가 locality를 활용

Protocol 우회와 container locality를 함께 만족해야 합니다.

FAQ
===

1. What are the use cases for LOCALIO?

   a. Workloads where the NFS client and server are on the same host
      realize improved IO performance. In particular, it is common when
      running containerised workloads for jobs to find themselves
      running on the same host as the knfsd server being used for
      storage.

2. What are the requirements for LOCALIO?

   a. Bypass use of the network RPC protocol as much as possible. This
      includes bypassing XDR and RPC for open, read, write and commit
      operations.
   b. Allow client and server to autonomously discover if they are
      running local to each other without making any assumptions about
      the local network topology.
   c. Support the use of containers by being compatible with relevant
      namespaces (e.g. network, user, mount).
   d. Support all versions of NFS. NFSv3 is of particular importance
      because it has wide enterprise usage and pNFS flexfiles makes use
      of it for the data path.

3. Why doesn’t LOCALIO just compare IP addresses or hostnames when
   deciding if the NFS client and server are co-located on the same
   host?

   Since one of the main use cases is containerised workloads, we cannot
   assume that IP addresses will be shared between the client and
   server. This sets up a requirement for a handshake protocol that
   needs to go over the same connection as the NFS traffic in order to
   identify that the client and the server really are running on the
   same host. The handshake uses a secret that is sent over the wire,
   and can be verified by both parties by comparing with a value stored
   in shared kernel memory if they are truly co-located.

4. Does LOCALIO improve pNFS flexfiles?

   Yes, LOCALIO complements pNFS flexfiles by allowing it to take
   advantage of NFS client and server locality.  Policy that initiates
   client IO as closely to the server where the data is stored naturally
   benefits from the data path optimization LOCALIO provides.

5. Why not develop a new pNFS layout to enable LOCALIO?

   A new pNFS layout could be developed, but doing so would put the
   onus on the server to somehow discover that the client is co-located
   when deciding to hand out the layout.
   There is value in a simpler approach (as provided by LOCALIO) that
   allows the NFS client to negotiate and leverage locality without
   requiring more elaborate modeling and discovery of such locality in a
   more centralized manner.

Local open, AUTH_UNIX, ID translation과 lifetime

121-157

Client가 RPC 없이 server-side file `OPEN`을 수행하면 pNFS 사용 여부와 무관하게 XDR과 RPC overhead를 줄입니다. 특히 small file에서는 실제 I/O가 network를 피하더라도 open이 wire를 왕복하면 이득이 줄거나 사라질 수 있으므로 local open이 중요합니다.

현재 요구 사항에서는 client가 RPC 없이 server-side file open을 수행하는 방식이 적절합니다. 향후 요구가 바뀌면 구현도 조정할 수 있습니다.

LOCALIO가 `AUTH_UNIX`만 지원하는 이유는 strong authentication이 보통 connection에 묶인 context를 server에 cache하고, 그 context를 authorization token discovery의 key로 사용한 뒤 `rpc.mountd`에 전달하는 구조이기 때문입니다. 반면 `AUTH_UNIX`는 wire로 받은 credential 자체를 `rpc.mountd` upcall의 key로 사용하므로 지원 과정이 단순합니다.

`root_squash`, `all_squash`처럼 RPC user ID를 변환하는 export option은 `__fh_verify()`가 호출하는 `nfsd_setuser_and_check_port()`와 그 안의 `nfsd_setuser()`가 처리합니다. 따라서 LOCALIO에서도 일반 NFS와 완전히 같은 방식으로 적용됩니다.

NFSD와 NFS가 서로 다른 context에서 동작할 때 object lifetime을 올바르게 관리하는 방식은 뒤의 `NFS Client and Server Interlock` 절에서 `nfs_uuid_t`, network namespace reference와 함께 설명합니다.

LOCALIO open과 credential 처리
Client가 local server-side file open 요청AUTH_UNIX credential을 기존 auth_domain과 연결__fh_verify()가 nfsd_setuser_and_check_port() 호출nfsd_setuser()가 root_squash/all_squash 적용검증된 nfsd_file을 client가 직접 I/O에 사용

Network RPC는 우회하지만 기존 NFSD authorization 경로를 재사용합니다.


6. Why is having the client perform a server-side file OPEN, without
   using RPC, beneficial?  Is the benefit pNFS specific?

   Avoiding the use of XDR and RPC for file opens is beneficial to
   performance regardless of whether pNFS is used. Especially when
   dealing with small files its best to avoid going over the wire
   whenever possible, otherwise it could reduce or even negate the
   benefits of avoiding the wire for doing the small file I/O itself.
   Given LOCALIO's requirements the current approach of having the
   client perform a server-side file open, without using RPC, is ideal.
   If in the future requirements change then we can adapt accordingly.

7. Why is LOCALIO only supported with UNIX Authentication (AUTH_UNIX)?

   Strong authentication is usually tied to the connection itself. It
   works by establishing a context that is cached by the server, and
   that acts as the key for discovering the authorisation token, which
   can then be passed to rpc.mountd to complete the authentication
   process. On the other hand, in the case of AUTH_UNIX, the credential
   that was passed over the wire is used directly as the key in the
   upcall to rpc.mountd. This simplifies the authentication process, and
   so makes AUTH_UNIX easier to support.

8. How do export options that translate RPC user IDs behave for LOCALIO
   operations (eg. root_squash, all_squash)?

   Export options that translate user IDs are managed by nfsd_setuser()
   which is called by nfsd_setuser_and_check_port() which is called by
   __fh_verify().  So they get handled exactly the same way for LOCALIO
   as they do for non-LOCALIO.

9. How does LOCALIO make certain that object lifetimes are managed
   properly given NFSD and NFS operate in different contexts?

   See the detailed "NFS Client and Server Interlock" section below.

UUID_IS_LOCAL auxiliary RPC 명세

158-195

LOCALIO auxiliary RPC protocol은 `UUID_IS_LOCAL` method 하나로 구성됩니다. Linux NFS client가 생성해 `nfs_common`에 공개한 single-use UUID nonce를 local Linux NFS server도 볼 수 있는지 검증합니다. Linux-to-Linux 구현 세부 사항인 auxiliary protocol이므로 IETF standard의 일부가 아니며 그럴 필요도 없습니다.

`UUID_IS_LOCAL`은 client가 만든 `uuid_t`를 고정 `UUID_SIZE`, 즉 16 byte로 encode합니다. 가변 크기 방식보다 효율적인 fixed-size opaque XDR encode/decode method를 사용합니다.

IANA가 할당한 `NFS_LOCALIO_PROGRAM` RPC program number는 400122이며 등록 이름은 `nfslocalio`입니다. Version `LOCALIO_V1`에는 procedure 0인 `NULL(void)`와 procedure 1인 `UUID_IS_LOCAL(uuid_t)`가 있습니다.

/* raw RFC 9562 UUID */
#define UUID_SIZE 16
typedef u8 uuid_t<UUID_SIZE>;

program NFS_LOCALIO_PROGRAM {
    version LOCALIO_V1 {
        void NULL(void) = 0;
        void UUID_IS_LOCAL(uuid_t) = 1;
    } = 1;
} = 400122;

LOCALIO는 NFS traffic과 같은 transport connection을 사용합니다. 별도 service endpoint를 찾을 필요가 없으므로 `rpcbind`에는 등록하지 않습니다.

LOCALIO RPC program
항목
Program`NFS_LOCALIO_PROGRAM` = 400122
Version`LOCALIO_V1` = 1
Procedure 0`NULL(void)`
Procedure 1`UUID_IS_LOCAL(uuid_t)`
UUID`UUID_SIZE` = 16 byte, RFC 9562 raw UUID
Transport기존 NFS connection, rpcbind 미등록

고정 UUID를 확인하는 최소 auxiliary protocol입니다.

RPC
===

The LOCALIO auxiliary RPC protocol consists of a single "UUID_IS_LOCAL"
RPC method that allows the Linux NFS client to verify the local Linux
NFS server can see the nonce (single-use UUID) the client generated and
made available in nfs_common. This protocol isn't part of an IETF
standard, nor does it need to be considering it is Linux-to-Linux
auxiliary RPC protocol that amounts to an implementation detail.

The UUID_IS_LOCAL method encodes the client generated uuid_t in terms of
the fixed UUID_SIZE (16 bytes). The fixed size opaque encode and decode
XDR methods are used instead of the less efficient variable sized
methods.

The RPC program number for the NFS_LOCALIO_PROGRAM is 400122 (as assigned
by IANA, see https://www.iana.org/assignments/rpc-program-numbers/ ):
Linux Kernel Organization       400122  nfslocalio

The LOCALIO protocol spec in rpcgen syntax is::

  /* raw RFC 9562 UUID */
  #define UUID_SIZE 16
  typedef u8 uuid_t<UUID_SIZE>;

  program NFS_LOCALIO_PROGRAM {
      version LOCALIO_V1 {
          void
              NULL(void) = 0;

          void
              UUID_IS_LOCAL(uuid_t) = 1;
      } = 1;
  } = 400122;

LOCALIO uses the same transport connection as NFS traffic. As such,
LOCALIO is not registered with rpcbind.

nfs_common handshake와 nfs_uuid_t 이전

196-216

`fs/nfs_common/nfslocalio.c`는 NFS client가 single-use UUID nonce와 수명이 짧은 `nfs_uuid_t`를 생성하는 interface를 제공합니다. Client는 이를 `nfs_common`에 등록해 NFS server가 나중에 lookup하고 검증할 수 있게 합니다.

Server가 nonce를 일치시키면 `nfs_uuid_t`의 member를 채웁니다. 그 뒤 client는 `nfs_common`을 사용해 이 object를 `nfs_common`의 `uuids_list`에 있는 자신의 `nfs_uuids`에서 `nn->nfsd_serv`의 `clients_list`로 옮깁니다. Client 측 진입점은 `fs/nfs/localio.c:nfs_local_probe()`입니다.

`nfs_common`의 `nfs_uuids` list는 LOCALIO enablement의 기반입니다. Entry는 client가 직접 사용할 nfsd memory를 가리키며, 예를 들어 server network namespace인 `net`을 통해 적절한 RCU read access 아래 `nn->nfsd_serv`에 접근할 수 있습니다.

이 client/server synchronization 덕분에 host kernel의 nfsd와 같은 local host에서 NFS client에 연결된 container별 knfsd instance 사이에서도 object의 advanced usage와 lifetime을 안전하게 이어 갈 수 있습니다.

LOCALIO locality handshake
Client가 nonce UUID와 short-lived nfs_uuid_t 생성nfs_common의 nfs_uuids/uuids_list에 등록UUID_IS_LOCAL로 server가 shared-kernel nonce 검증Server가 nfs_uuid_t에 net 등 nfsd member 설정Object를 nn->nfsd_serv의 clients_list로 이전

Nonce 생성부터 server client list 편입까지의 object 이동입니다.

NFS Common and Client/Server Handshake
======================================

fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS client
to generate a nonce (single-use UUID) and associated short-lived
nfs_uuid_t struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct. The NFS client then uses nfs_common to
transfer the nfs_uuid_t from its nfs_uuids to the nn->nfsd_serv
clients_list from the nfs_common's uuids_list.  See:
fs/nfs/localio.c:nfs_local_probe()

nfs_common's nfs_uuids list is the basis for LOCALIO enablement, as such
it has members that point to nfsd memory for direct use by the client
(e.g. 'net' is the server's network namespace, through it the client can
access nn->nfsd_serv with proper rcu read access). It is this client
and server synchronization that enables advanced usage and lifetime of
objects to span from the host kernel's nfsd to per-container knfsd
instances that are connected to nfs client's running on the same local
host.

NFS client/server network namespace interlock

217-245

LOCALIO는 `nfs_uuid_t` object와 관련 interface를 제공해 network namespace, 즉 net-ns와 NFSD object의 reference count를 올바르게 관리합니다.

이를 위해 NFSD의 per-CPU `nfsd_net_ref`가 도입되었습니다. `nfsd_shutdown_net()`과 `nfsd_open_local_fh()`를 interlock하여 `nfsd_open_local_fh()`가 사용하는 동안 각 net-ns가 파괴되지 않도록 합니다.

`nfsd_open_local_fh()`는 `nfsd_file` handle을 열기 전에 `nfsd_net_try_get()`으로 reference를 얻습니다. I/O가 끝나면 caller인 NFS client가 `nfsd_file_put_local()`을 호출해 `nfsd_file`과 연결된 net-ns reference를 내려야 합니다.

Interlock은 `nfsd_destroy_serv()`가 `nfsd_shutdown_net()`을 거쳐 NFSD net-ns와 연관된 `nfsd_net`을 이미 파괴했을 가능성을 `nfsd_open_local_fh()`가 안전하게 처리할 수 있어야 한다는 점에 크게 의존합니다.

이 구조는 container 안 NFSD instance를 LOCALIO client가 mount한 상태에서 종료하고 다시 시작할 때 발생하던 crash를 고쳤습니다. 이전에는 client가 NFSD net-ns reference 없이 `nfsd_open_local_fh()`를 시도해 NULL pointer dereference가 발생할 수 있었습니다.

nfsd_file과 net-ns reference 수명
nfsd_open_local_fh()가 nfsd_net_try_get() 호출유효한 net-ns reference 아래 nfsd_file openClient가 local read/write/commit 수행nfsd_file_put_local()로 file과 net-ns reference 해제nfsd_shutdown_net()이 reference 소진 뒤 namespace 파괴

Open 전 획득과 I/O 후 해제가 shutdown과 맞물립니다.

NFS Client and Server Interlock
===============================

LOCALIO provides the nfs_uuid_t object and associated interfaces to
allow proper network namespace (net-ns) and NFSD object refcounting.

LOCALIO required the introduction and use of NFSD's percpu nfsd_net_ref
to interlock nfsd_shutdown_net() and nfsd_open_local_fh(), to ensure
each net-ns is not destroyed while in use by nfsd_open_local_fh(), and
warrants a more detailed explanation:

    nfsd_open_local_fh() uses nfsd_net_try_get() before opening its
    nfsd_file handle and then the caller (NFS client) must drop the
    reference for the nfsd_file and associated net-ns using
    nfsd_file_put_local() once it has completed its IO.

    This interlock working relies heavily on nfsd_open_local_fh() being
    afforded the ability to safely deal with the possibility that the
    NFSD's net-ns (and nfsd_net by association) may have been destroyed
    by nfsd_destroy_serv() via nfsd_shutdown_net().

This interlock of the NFS client and server has been verified to fix an
easy to hit crash that would occur if an NFSD instance running in a
container, with a LOCALIO client mounted, is shutdown. Upon restart of
the container and associated NFSD, the client would go on to crash due
to NULL pointer dereference that occurred due to the LOCALIO client's
attempting to nfsd_open_local_fh() without having a proper reference on
NFSD's net-ns.

Client가 backing filesystem에 직접 I/O 수행

246-290

LOCALIO는 I/O 성능을 위해 protocol을 우회하므로 전통적인 NFS wire protocol인 XDR 기반 SUNRPC 대신 backing filesystem에 접근할 interface가 필요합니다.

Client의 `fs/nfs/localio.c:nfs_local_open_fh()`와 server의 `fs/nfsd/localio.c:nfsd_open_local_fh()`는 선택된 NFS server object를 사용해 network를 거치지 않고 local client가 file pointer를 열게 합니다. Client 함수가 server 함수를 직접 호출하고, server의 network namespace와 `nn->nfsd_serv`를 RCU 규칙에 맞춰 조심스럽게 접근합니다.

`nfsd_open_local_fh()`가 `struct net` 또는 `nn->nfsd_serv` 같은 유효한 nfsd object를 더 이상 보지 못하면 `-ENXIO`를 반환합니다. Client의 `nfs_local_open_fh()`는 이를 받아 `nfs_local_probe()`를 다시 호출해 LOCALIO resource를 재설정합니다. Container의 nfsd가 연결 중 reboot할 수 있으므로 이 recovery가 필요합니다.

Client가 열린 `nfsd_file` pointer를 얻으면 보통 NFS server가 수행할 read, write, commit을 공유 중인 local backing filesystem에 직접 발행합니다. 구현 진입점은 `fs/nfs/localio.c:nfs_local_doio()`와 `fs/nfs/localio.c:nfs_local_commit()`입니다.

일반 NFS에서 application이 `O_DIRECT`를 사용하면 client는 page cache를 우회하지만 server는 buffered I/O를 사용할 수 있습니다. 이 server buffering은 application의 alignment가 다소 부정확해도 동작하게 합니다.

모든 application이 I/O를 올바르게 align한다면 `localio_O_DIRECT_semantics` nfs module parameter를 `Y`로 설정해 client부터 backing filesystem까지 end-to-end `O_DIRECT`를 사용할 수 있습니다. 활성화 뒤 alignment가 맞지 않으면 I/O가 실패할 수 있습니다.

echo Y > /sys/module/nfs/parameters/localio_O_DIRECT_semantics
LOCALIO direct I/O 경로
경로ClientServer/backing filesystemAlignment
일반 NFS + O_DIRECTPage cache 우회Server buffered I/O 가능Server buffering이 일부 오차 흡수
LOCALIO 기본Local nfsd_file로 직접 I/O기본 설정에 따른 I/O기존 호환성 유지
LOCALIO end-to-end O_DIRECTDirect I/OBacking filesystem까지 directLogical block size 정렬 필수

일반 NFS와 LOCALIO의 cache·alignment 의미를 비교합니다.

NFS Client issues IO instead of Server
======================================

Because LOCALIO is focused on protocol bypass to achieve improved IO
performance, alternatives to the traditional NFS wire protocol (SUNRPC
with XDR) must be provided to access the backing filesystem.

See fs/nfs/localio.c:nfs_local_open_fh() and
fs/nfsd/localio.c:nfsd_open_local_fh() for the interface that makes
focused use of select nfs server objects to allow a client local to a
server to open a file pointer without needing to go over the network.

The client's fs/nfs/localio.c:nfs_local_open_fh() will call into the
server's fs/nfsd/localio.c:nfsd_open_local_fh() and carefully access
both the associated nfsd network namespace and nn->nfsd_serv in terms of
RCU. If nfsd_open_local_fh() finds that the client no longer sees valid
nfsd objects (be it struct net or nn->nfsd_serv) it returns -ENXIO
to nfs_local_open_fh() and the client will try to reestablish the
LOCALIO resources needed by calling nfs_local_probe() again. This
recovery is needed if/when an nfsd instance running in a container were
to reboot while a LOCALIO client is connected to it.

Once the client has an open nfsd_file pointer it will issue reads,
writes and commits directly to the underlying local filesystem (normally
done by the nfs server). As such, for these operations, the NFS client
is issuing IO to the underlying local filesystem that it is sharing with
the NFS server. See: fs/nfs/localio.c:nfs_local_doio() and
fs/nfs/localio.c:nfs_local_commit().

With normal NFS that makes use of RPC to issue IO to the server, if an
application uses O_DIRECT the NFS client will bypass the pagecache but
the NFS server will not. The NFS server's use of buffered IO affords
applications to be less precise with their alignment when issuing IO to
the NFS client. But if all applications properly align their IO, LOCALIO
can be configured to use end-to-end O_DIRECT semantics from the NFS
client to the underlying local filesystem, that it is sharing with
the NFS server, by setting the 'localio_O_DIRECT_semantics' nfs module
parameter to Y, e.g.:

    echo Y > /sys/module/nfs/parameters/localio_O_DIRECT_semantics

Once enabled, it will cause LOCALIO to use end-to-end O_DIRECT semantics
(but again, this may cause IO to fail if applications do not properly
align their IO).

보안 경계와 module parameter

291-326

LOCALIO는 UNIX-style authentication인 `AUTH_UNIX`, 즉 `AUTH_SYS`를 사용할 때만 지원됩니다. LOCALIO와 일반 NFS 접근에서 authentication을 포함한 동일한 NFS security mechanism을 사용하도록 하며, 전통적인 NFS client 접근에서 만든 `auth_domain`을 LOCALIO에도 재사용합니다.

Container 환경에서 LOCALIO client는 server의 network namespace에 접근할 수 있습니다. 이는 namespace별 `nfsd_net`에 접근하는 데 필요하며 일반 NFS client도 SUNRPC protocol을 통해 사실상 같은 수준의 접근을 받습니다. User, mount 등 다른 namespace를 server에서 client로 일부러 확장하거나 변경하지는 않습니다.

Boolean `/sys/module/nfs/parameters/localio_enabled`는 LOCALIO 사용 여부를 제어하며 기본값은 `Y`입니다. Client와 server가 local이어도 값을 `N`으로 설정하면 LOCALIO를 사용하지 않습니다.

Boolean `/sys/module/nfs/parameters/localio_O_DIRECT_semantics`는 `O_DIRECT`가 underlying filesystem까지 이어지는지 제어하며 기본값은 `N`입니다. 활성화하면 application I/O가 logical block size에 맞게 align되어야 하며 그렇지 않으면 실패합니다.

Unsigned integer `/sys/module/nfsv3/parameters/nfs3_localio_probe_throttle`은 NFSv3 read/write I/O가 매 N회마다 LOCALIO 재활성화를 시도할지 제어합니다. 기본값 0은 비활성화입니다. 값은 power of 2여야 하며 너무 작거나 power of 2가 아닌 값으로 잘못 구성한 결과는 administrator가 감수해야 합니다.

LOCALIO module parameter
ParameterType/default효과
`localio_enabled`bool / YLOCALIO 전체 사용 여부
`localio_O_DIRECT_semantics`bool / NBacking filesystem까지 O_DIRECT 확장
`nfs3_localio_probe_throttle`uint / 0NFSv3 I/O N회마다 probe, power-of-2 필요

기본값과 활성화 시 의미입니다.

Security
========

LOCALIO is only supported when UNIX-style authentication (AUTH_UNIX, aka
AUTH_SYS) is used.

Care is taken to ensure the same NFS security mechanisms are used
(authentication, etc) regardless of whether LOCALIO or regular NFS
access is used. The auth_domain established as part of the traditional
NFS client access to the NFS server is also used for LOCALIO.

Relative to containers, LOCALIO gives the client access to the network
namespace the server has. This is required to allow the client to access
the server's per-namespace nfsd_net struct. With traditional NFS, the
client is afforded this same level of access (albeit in terms of the NFS
protocol via SUNRPC). No other namespaces (user, mount, etc) have been
altered or purposely extended from the server to the client.

Module Parameters
=================

/sys/module/nfs/parameters/localio_enabled (bool)
controls if LOCALIO is enabled, defaults to Y. If client and server are
local but 'localio_enabled' is set to N then LOCALIO will not be used.

/sys/module/nfs/parameters/localio_O_DIRECT_semantics (bool)
controls if O_DIRECT extends down to the underlying filesystem, defaults
to N. Application IO must be logical blocksize aligned, otherwise
O_DIRECT will fail.

/sys/module/nfsv3/parameters/nfs3_localio_probe_throttle (uint)
controls if NFSv3 read and write IOs will trigger (re)enabling of
LOCALIO every N (nfs3_localio_probe_throttle) IOs, defaults to 0
(disabled). Must be power-of-2, admin keeps all the pieces if they
misconfigure (too low a value or non-power-of-2).

검증 시나리오와 회귀 검사

327-357

LOCALIO auxiliary protocol과 NFS LOCALIO read, write, commit 경로는 여러 test scenario에서 안정성을 검증했습니다. Client와 server가 같은 host인 기본 경우뿐 아니라 local·remote 배치와 양쪽 LOCALIO 지원 enablement의 모든 조합을 시험했습니다.

LOCALIO protocol을 지원하지 않는 NFS storage product와의 호환성도 검사했습니다. Host의 client와 container 내부 server 조합은 NFSv3와 NFSv4.2에서 모두 시험했고, Podman 관리 container의 정상 stop/restart도 성공했습니다.

이 scenario를 기존 test infrastructure에 정식 편입하는 작업은 진행 중입니다. 초기 정기 coverage는 LOCALIO-enabled NFS loopback mount에 `xfstests`를 실행하는 `ktest`로 제공되며 lockdep과 KASAN 검사도 포함합니다. 원문은 test dashboard와 ktest GitHub URL을 제시합니다.

Chuck's BuildBot 형태의 여러 `kdevops` test도 LOCALIO 변경이 일반 non-LOCALIO NFS 사용 사례에 regression을 만들지 않았는지 정기적으로 확인했습니다. Hammerspace의 pNFS와 flexfiles test를 포함한 여러 sanity test도 LOCALIO 활성 상태에서 통과했습니다.

LOCALIO 검증 범위
범주검증 내용
Locality같은 host client/server와 local·remote 조합
CapabilityClient/server 지원 enablement 모든 조합
호환성LOCALIO 미지원 NFS storage product
Container lifetimePodman server stop/restart, NFSv3·v4.2
Kernel 검사xfstests, lockdep, KASAN, ktest
회귀kdevops와 non-LOCALIO NFS 사용 사례

기능과 호환성, lifetime, regression을 함께 확인합니다.

Testing
=======

The LOCALIO auxiliary protocol and associated NFS LOCALIO read, write
and commit access have proven stable against various test scenarios:

- Client and server both on the same host.

- All permutations of client and server support enablement for both
  local and remote client and server.

- Testing against NFS storage products that don't support the LOCALIO
  protocol was also performed.

- Client on host, server within a container (for both v3 and v4.2).
  The container testing was in terms of podman managed containers and
  includes successful container stop/restart scenario.

- Formalizing these test scenarios in terms of existing test
  infrastructure is on-going. Initial regular coverage is provided in
  terms of ktest running xfstests against a LOCALIO-enabled NFS loopback
  mount configuration, and includes lockdep and KASAN coverage, see:
  https://evilpiepirate.org/~testdashboard/ci?user=snitzer&branch=snitm-nfs-next
  https://github.com/koverstreet/ktest

- Various kdevops testing (in terms of "Chuck's BuildBot") has been
  performed to regularly verify the LOCALIO changes haven't caused any
  regressions to non-LOCALIO NFS use cases.

- All of Hammerspace's various sanity tests pass with LOCALIO enabled
  (this includes numerous pNFS and flexfiles tests).