← Documents Documentation/filesystems/fiemap.rst GitHub 원문 ↗

Linux 6.18.37 · Filesystems

Fiemap Ioctl

FIEMAP request·extent flag, raw I/O 제약과 filesystem callback 구현을 옮긴 전문 번역입니다.

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

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

1. 요약·해설

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

요약·해설

fiemap.rst:1-217

FIEMAP은 file의 logical-to-physical mapping을 block별이 아닌 extent list로 돌려주는 userspace ioctl입니다.

unsupported flag 보고, 짧은 output array의 재호출, specific/general extent flag 관계와 raw block-device 접근 금지 규칙이 API 안전성의 핵심입니다.

FIEMAP 호출 흐름
`struct fiemap`과 extent array 준비`ioctl_fiemap()`이 `->fiemap` callback 호출`fiemap_prep()`로 flag·range 검증extent마다 `fiemap_fill_next_extent()``fm_mapped_extents`와 `LAST`로 완료 판단

userspace request부터 filesystem callback까지의 경로입니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ============
4 Fiemap Ioctl
5 ============
6
7 The fiemap ioctl is an efficient method for userspace to get file
8 extent mappings. Instead of block-by-block mapping (such as bmap), fiemap
9 returns a list of extents.
10
11
12 Request Basics
13 --------------
14
15 A fiemap request is encoded within struct fiemap:
16
17 .. kernel-doc:: include/uapi/linux/fiemap.h
18 :identifiers: fiemap
19
20 fm_start, and fm_length specify the logical range within the file
21 which the process would like mappings for. Extents returned mirror
22 those on disk - that is, the logical offset of the 1st returned extent
23 may start before fm_start, and the range covered by the last returned
24 extent may end after fm_length. All offsets and lengths are in bytes.
25
26 Certain flags to modify the way in which mappings are looked up can be
27 set in fm_flags. If the kernel doesn't understand some particular
28 flags, it will return EBADR and the contents of fm_flags will contain
29 the set of flags which caused the error. If the kernel is compatible
30 with all flags passed, the contents of fm_flags will be unmodified.
31 It is up to userspace to determine whether rejection of a particular
32 flag is fatal to its operation. This scheme is intended to allow the
33 fiemap interface to grow in the future but without losing
34 compatibility with old software.
35
36 fm_extent_count specifies the number of elements in the fm_extents[] array
37 that can be used to return extents. If fm_extent_count is zero, then the
38 fm_extents[] array is ignored (no extents will be returned), and the
39 fm_mapped_extents count will hold the number of extents needed in
40 fm_extents[] to hold the file's current mapping. Note that there is
41 nothing to prevent the file from changing between calls to FIEMAP.
42
43 The following flags can be set in fm_flags:
44
45 FIEMAP_FLAG_SYNC
46 If this flag is set, the kernel will sync the file before mapping extents.
47
48 FIEMAP_FLAG_XATTR
49 If this flag is set, the extents returned will describe the inodes
50 extended attribute lookup tree, instead of its data tree.
51
52 FIEMAP_FLAG_CACHE
53 This flag requests caching of the extents.
54
55 Extent Mapping
56 --------------
57
58 Extent information is returned within the embedded fm_extents array
59 which userspace must allocate along with the fiemap structure. The
60 number of elements in the fiemap_extents[] array should be passed via
61 fm_extent_count. The number of extents mapped by kernel will be
62 returned via fm_mapped_extents. If the number of fiemap_extents
63 allocated is less than would be required to map the requested range,
64 the maximum number of extents that can be mapped in the fm_extent[]
65 array will be returned and fm_mapped_extents will be equal to
66 fm_extent_count. In that case, the last extent in the array will not
67 complete the requested range and will not have the FIEMAP_EXTENT_LAST
68 flag set (see the next section on extent flags).
69
70 Each extent is described by a single fiemap_extent structure as
71 returned in fm_extents:
72
73 .. kernel-doc:: include/uapi/linux/fiemap.h
74 :identifiers: fiemap_extent
75
76 All offsets and lengths are in bytes and mirror those on disk. It is valid
77 for an extents logical offset to start before the request or its logical
78 length to extend past the request. Unless FIEMAP_EXTENT_NOT_ALIGNED is
79 returned, fe_logical, fe_physical, and fe_length will be aligned to the
80 block size of the file system. With the exception of extents flagged as
81 FIEMAP_EXTENT_MERGED, adjacent extents will not be merged.
82
83 The fe_flags field contains flags which describe the extent returned.
84 A special flag, FIEMAP_EXTENT_LAST is always set on the last extent in
85 the file so that the process making fiemap calls can determine when no
86 more extents are available, without having to call the ioctl again.
87
88 Some flags are intentionally vague and will always be set in the
89 presence of other more specific flags. This way a program looking for
90 a general property does not have to know all existing and future flags
91 which imply that property.
92
93 For example, if FIEMAP_EXTENT_DATA_INLINE or FIEMAP_EXTENT_DATA_TAIL
94 are set, FIEMAP_EXTENT_NOT_ALIGNED will also be set. A program looking
95 for inline or tail-packed data can key on the specific flag. Software
96 which simply cares not to try operating on non-aligned extents
97 however, can just key on FIEMAP_EXTENT_NOT_ALIGNED, and not have to
98 worry about all present and future flags which might imply unaligned
99 data. Note that the opposite is not true - it would be valid for
100 FIEMAP_EXTENT_NOT_ALIGNED to appear alone.
101
102 FIEMAP_EXTENT_LAST
103 This is generally the last extent in the file. A mapping attempt past
104 this extent may return nothing. Some implementations set this flag to
105 indicate this extent is the last one in the range queried by the user
106 (via fiemap->fm_length).
107
108 FIEMAP_EXTENT_UNKNOWN
109 The location of this extent is currently unknown. This may indicate
110 the data is stored on an inaccessible volume or that no storage has
111 been allocated for the file yet.
112
113 FIEMAP_EXTENT_DELALLOC
114 This will also set FIEMAP_EXTENT_UNKNOWN.
115
116 Delayed allocation - while there is data for this extent, its
117 physical location has not been allocated yet.
118
119 FIEMAP_EXTENT_ENCODED
120 This extent does not consist of plain filesystem blocks but is
121 encoded (e.g. encrypted or compressed). Reading the data in this
122 extent via I/O to the block device will have undefined results.
123
124 Note that it is *always* undefined to try to update the data
125 in-place by writing to the indicated location without the
126 assistance of the filesystem, or to access the data using the
127 information returned by the FIEMAP interface while the filesystem
128 is mounted. In other words, user applications may only read the
129 extent data via I/O to the block device while the filesystem is
130 unmounted, and then only if the FIEMAP_EXTENT_ENCODED flag is
131 clear; user applications must not try reading or writing to the
132 filesystem via the block device under any other circumstances.
133
134 FIEMAP_EXTENT_DATA_ENCRYPTED
135 This will also set FIEMAP_EXTENT_ENCODED
136 The data in this extent has been encrypted by the file system.
137
138 FIEMAP_EXTENT_NOT_ALIGNED
139 Extent offsets and length are not guaranteed to be block aligned.
140
141 FIEMAP_EXTENT_DATA_INLINE
142 This will also set FIEMAP_EXTENT_NOT_ALIGNED
143 Data is located within a meta data block.
144
145 FIEMAP_EXTENT_DATA_TAIL
146 This will also set FIEMAP_EXTENT_NOT_ALIGNED
147 Data is packed into a block with data from other files.
148
149 FIEMAP_EXTENT_UNWRITTEN
150 Unwritten extent - the extent is allocated but its data has not been
151 initialized. This indicates the extent's data will be all zero if read
152 through the filesystem but the contents are undefined if read directly from
153 the device.
154
155 FIEMAP_EXTENT_MERGED
156 This will be set when a file does not support extents, i.e., it uses a block
157 based addressing scheme. Since returning an extent for each block back to
158 userspace would be highly inefficient, the kernel will try to merge most
159 adjacent blocks into 'extents'.
160
161 FIEMAP_EXTENT_SHARED
162 This flag is set to request that space be shared with other files.
163
164 VFS -> File System Implementation
165 ---------------------------------
166
167 File systems wishing to support fiemap must implement a ->fiemap callback on
168 their inode_operations structure. The fs ->fiemap call is responsible for
169 defining its set of supported fiemap flags, and calling a helper function on
170 each discovered extent::
171
172 struct inode_operations {
173 ...
174
175 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
176 u64 len);
177
178 ->fiemap is passed struct fiemap_extent_info which describes the
179 fiemap request:
180
181 .. kernel-doc:: include/linux/fiemap.h
182 :identifiers: fiemap_extent_info
183
184 It is intended that the file system should not need to access any of this
185 structure directly. Filesystem handlers should be tolerant to signals and return
186 EINTR once fatal signal received.
187
188
189 Flag checking should be done at the beginning of the ->fiemap callback via the
190 fiemap_prep() helper::
191
192 int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
193 u64 start, u64 *len, u32 supported_flags);
194
195 The struct fieinfo should be passed in as received from ioctl_fiemap(). The
196 set of fiemap flags which the fs understands should be passed via fs_flags. If
197 fiemap_prep finds invalid user flags, it will place the bad values in
198 fieinfo->fi_flags and return -EBADR. If the file system gets -EBADR, from
199 fiemap_prep(), it should immediately exit, returning that error back to
200 ioctl_fiemap(). Additionally the range is validate against the supported
201 maximum file size.
202
203
204 For each extent in the request range, the file system should call
205 the helper function, fiemap_fill_next_extent()::
206
207 int fiemap_fill_next_extent(struct fiemap_extent_info *info, u64 logical,
208 u64 phys, u64 len, u32 flags, u32 dev);
209
210 fiemap_fill_next_extent() will use the passed values to populate the
211 next free extent in the fm_extents array. 'General' extent flags will
212 automatically be set from specific flags on behalf of the calling file
213 system so that the userspace API is not broken.
214
215 fiemap_fill_next_extent() returns 0 on success, and 1 when the
216 user-supplied fm_extents array is full. If an error is encountered
217 while copying the extent to user memory, -EFAULT will be returned.
218

3. 한국어 전문 번역

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

FIEMAP request와 request flag

1-54

FIEMAP ioctl은 userspace가 file의 extent mapping을 효율적으로 얻는 interface입니다. `bmap`처럼 block마다 mapping하지 않고 extent list를 반환합니다.

request는 `struct fiemap`에 담깁니다. `fm_start`와 `fm_length`는 mapping을 요청할 logical byte range입니다. 반환 extent는 실제 on-disk extent를 반영하므로 첫 extent가 `fm_start`보다 앞에서 시작하거나 마지막 extent가 요청 끝을 지나 끝날 수 있습니다. 모든 offset과 length 단위는 byte입니다.

lookup 방식을 바꾸는 flag는 `fm_flags`에 넣습니다. kernel이 모르는 flag가 있으면 `EBADR`를 반환하고 문제 flag 집합을 `fm_flags`에 남깁니다. 모두 이해하면 `fm_flags`는 바뀌지 않습니다. 해당 거부가 치명적인지는 userspace가 결정하므로 오래된 software와 호환성을 유지하며 interface를 확장할 수 있습니다.

`fm_extent_count`는 userspace가 준비한 `fm_extents[]` 원소 수입니다. 0이면 배열을 무시하고 extent를 반환하지 않으며, `fm_mapped_extents`에 현재 mapping을 담는 데 필요한 extent 수를 돌려줍니다. 두 FIEMAP call 사이에 file이 바뀔 수 있다는 점은 보장하지 않습니다.

FIEMAP request flag
Flag동작
`FIEMAP_FLAG_SYNC`extent mapping 전에 kernel이 file을 sync합니다.
`FIEMAP_FLAG_XATTR`data tree 대신 inode의 extended-attribute lookup tree extent를 반환합니다.
`FIEMAP_FLAG_CACHE`extent를 cache하도록 요청합니다.

`fm_flags`에 설정할 수 있는 flag입니다.

.. SPDX-License-Identifier: GPL-2.0

============
Fiemap Ioctl
============

The fiemap ioctl is an efficient method for userspace to get file
extent mappings. Instead of block-by-block mapping (such as bmap), fiemap
returns a list of extents.


Request Basics
--------------

A fiemap request is encoded within struct fiemap:

.. kernel-doc:: include/uapi/linux/fiemap.h
   :identifiers: fiemap

fm_start, and fm_length specify the logical range within the file
which the process would like mappings for. Extents returned mirror
those on disk - that is, the logical offset of the 1st returned extent
may start before fm_start, and the range covered by the last returned
extent may end after fm_length. All offsets and lengths are in bytes.

Certain flags to modify the way in which mappings are looked up can be
set in fm_flags. If the kernel doesn't understand some particular
flags, it will return EBADR and the contents of fm_flags will contain
the set of flags which caused the error. If the kernel is compatible
with all flags passed, the contents of fm_flags will be unmodified.
It is up to userspace to determine whether rejection of a particular
flag is fatal to its operation. This scheme is intended to allow the
fiemap interface to grow in the future but without losing
compatibility with old software.

fm_extent_count specifies the number of elements in the fm_extents[] array
that can be used to return extents.  If fm_extent_count is zero, then the
fm_extents[] array is ignored (no extents will be returned), and the
fm_mapped_extents count will hold the number of extents needed in
fm_extents[] to hold the file's current mapping.  Note that there is
nothing to prevent the file from changing between calls to FIEMAP.

The following flags can be set in fm_flags:

FIEMAP_FLAG_SYNC
  If this flag is set, the kernel will sync the file before mapping extents.

FIEMAP_FLAG_XATTR
  If this flag is set, the extents returned will describe the inodes
  extended attribute lookup tree, instead of its data tree.

FIEMAP_FLAG_CACHE
  This flag requests caching of the extents.

Extent 배열·flag와 직접 I/O 제약

55-163

userspace는 `struct fiemap`과 함께 embedded `fm_extents[]`를 할당하고 원소 수를 `fm_extent_count`로 넘깁니다. kernel이 mapping한 수는 `fm_mapped_extents`로 돌아옵니다.

배열이 요청 범위 전체를 담기에 작으면 가능한 최대 extent만 채우며 `fm_mapped_extents == fm_extent_count`가 됩니다. 이때 마지막 배열 원소는 요청 범위를 끝내지 못하므로 `FIEMAP_EXTENT_LAST`가 없습니다.

각 extent는 `struct fiemap_extent`입니다. `FIEMAP_EXTENT_NOT_ALIGNED`가 없으면 `fe_logical`, `fe_physical`, `fe_length`는 filesystem block size에 정렬됩니다. `FIEMAP_EXTENT_MERGED`를 제외하면 인접 extent를 합치지 않습니다.

일반 property flag는 더 구체적인 flag와 함께 자동 설정될 수 있습니다. 예를 들어 `DATA_INLINE` 또는 `DATA_TAIL`이면 `NOT_ALIGNED`도 설정됩니다. 반대는 성립하지 않아 `NOT_ALIGNED`만 단독으로 나타날 수 있습니다.

FIEMAP extent flag
Flag의미
`FIEMAP_EXTENT_LAST`대체로 file의 마지막 extent입니다. 일부 구현은 query range의 마지막 extent라는 의미로도 사용합니다.
`FIEMAP_EXTENT_UNKNOWN`현재 physical location을 알 수 없습니다. volume에 접근할 수 없거나 아직 storage가 할당되지 않았을 수 있습니다.
`FIEMAP_EXTENT_DELALLOC`data는 있지만 delayed allocation 때문에 physical location은 아직 없습니다. `UNKNOWN`도 함께 설정됩니다.
`FIEMAP_EXTENT_ENCODED`plain filesystem block이 아니라 encrypted/compressed 형태입니다. block device로 직접 읽은 결과는 정의되지 않습니다.
`FIEMAP_EXTENT_DATA_ENCRYPTED`filesystem이 data를 암호화했습니다. `ENCODED`도 함께 설정됩니다.
`FIEMAP_EXTENT_NOT_ALIGNED`extent offset과 length가 block-aligned임을 보장하지 않습니다.
`FIEMAP_EXTENT_DATA_INLINE`data가 metadata block 안에 있습니다. `NOT_ALIGNED`도 함께 설정됩니다.
`FIEMAP_EXTENT_DATA_TAIL`다른 file의 data와 한 block에 tail-packed되어 있습니다. `NOT_ALIGNED`도 함께 설정됩니다.
`FIEMAP_EXTENT_UNWRITTEN`extent는 할당됐지만 초기화되지 않았습니다. filesystem을 통해 읽으면 0이고 device 직접 읽기 내용은 정의되지 않습니다.
`FIEMAP_EXTENT_MERGED`block-based addressing filesystem에서 block마다 반환하는 비용을 피하려고 인접 block을 extent처럼 합쳤습니다.
`FIEMAP_EXTENT_SHARED`다른 file과 공간을 공유함을 나타냅니다.

`fe_flags`가 설명하는 extent property와 포함 관계입니다.

FIEMAP이 알려 준 block location에 filesystem 도움 없이 in-place write하는 것은 언제나 정의되지 않은 동작입니다. mounted filesystem의 block device를 FIEMAP 정보로 직접 읽는 것도 금지됩니다. userspace가 extent data를 block device에서 직접 읽을 수 있는 유일한 경우는 filesystem이 unmount되어 있고 `FIEMAP_EXTENT_ENCODED`가 해제된 때이며, 직접 쓰기는 허용되지 않습니다.

Block device 직접 접근 허용 조건
filesystem이 unmounted인지 확인`FIEMAP_EXTENT_ENCODED`가 clear인지 확인조건을 모두 만족할 때 read-only raw I/O만 허용mounted 상태 raw I/O 또는 어떤 상태의 in-place write도 금지

FIEMAP 결과를 raw I/O에 사용할 수 있는 매우 제한적인 조건입니다.

Extent Mapping
--------------

Extent information is returned within the embedded fm_extents array
which userspace must allocate along with the fiemap structure. The
number of elements in the fiemap_extents[] array should be passed via
fm_extent_count. The number of extents mapped by kernel will be
returned via fm_mapped_extents. If the number of fiemap_extents
allocated is less than would be required to map the requested range,
the maximum number of extents that can be mapped in the fm_extent[]
array will be returned and fm_mapped_extents will be equal to
fm_extent_count. In that case, the last extent in the array will not
complete the requested range and will not have the FIEMAP_EXTENT_LAST
flag set (see the next section on extent flags).

Each extent is described by a single fiemap_extent structure as
returned in fm_extents:

.. kernel-doc:: include/uapi/linux/fiemap.h
    :identifiers: fiemap_extent

All offsets and lengths are in bytes and mirror those on disk.  It is valid
for an extents logical offset to start before the request or its logical
length to extend past the request.  Unless FIEMAP_EXTENT_NOT_ALIGNED is
returned, fe_logical, fe_physical, and fe_length will be aligned to the
block size of the file system.  With the exception of extents flagged as
FIEMAP_EXTENT_MERGED, adjacent extents will not be merged.

The fe_flags field contains flags which describe the extent returned.
A special flag, FIEMAP_EXTENT_LAST is always set on the last extent in
the file so that the process making fiemap calls can determine when no
more extents are available, without having to call the ioctl again.

Some flags are intentionally vague and will always be set in the
presence of other more specific flags. This way a program looking for
a general property does not have to know all existing and future flags
which imply that property.

For example, if FIEMAP_EXTENT_DATA_INLINE or FIEMAP_EXTENT_DATA_TAIL
are set, FIEMAP_EXTENT_NOT_ALIGNED will also be set. A program looking
for inline or tail-packed data can key on the specific flag. Software
which simply cares not to try operating on non-aligned extents
however, can just key on FIEMAP_EXTENT_NOT_ALIGNED, and not have to
worry about all present and future flags which might imply unaligned
data. Note that the opposite is not true - it would be valid for
FIEMAP_EXTENT_NOT_ALIGNED to appear alone.

FIEMAP_EXTENT_LAST
  This is generally the last extent in the file. A mapping attempt past
  this extent may return nothing. Some implementations set this flag to
  indicate this extent is the last one in the range queried by the user
  (via fiemap->fm_length).

FIEMAP_EXTENT_UNKNOWN
  The location of this extent is currently unknown. This may indicate
  the data is stored on an inaccessible volume or that no storage has
  been allocated for the file yet.

FIEMAP_EXTENT_DELALLOC
  This will also set FIEMAP_EXTENT_UNKNOWN.

  Delayed allocation - while there is data for this extent, its
  physical location has not been allocated yet.

FIEMAP_EXTENT_ENCODED
  This extent does not consist of plain filesystem blocks but is
  encoded (e.g. encrypted or compressed).  Reading the data in this
  extent via I/O to the block device will have undefined results.

Note that it is *always* undefined to try to update the data
in-place by writing to the indicated location without the
assistance of the filesystem, or to access the data using the
information returned by the FIEMAP interface while the filesystem
is mounted.  In other words, user applications may only read the
extent data via I/O to the block device while the filesystem is
unmounted, and then only if the FIEMAP_EXTENT_ENCODED flag is
clear; user applications must not try reading or writing to the
filesystem via the block device under any other circumstances.

FIEMAP_EXTENT_DATA_ENCRYPTED
  This will also set FIEMAP_EXTENT_ENCODED
  The data in this extent has been encrypted by the file system.

FIEMAP_EXTENT_NOT_ALIGNED
  Extent offsets and length are not guaranteed to be block aligned.

FIEMAP_EXTENT_DATA_INLINE
  This will also set FIEMAP_EXTENT_NOT_ALIGNED
  Data is located within a meta data block.

FIEMAP_EXTENT_DATA_TAIL
  This will also set FIEMAP_EXTENT_NOT_ALIGNED
  Data is packed into a block with data from other files.

FIEMAP_EXTENT_UNWRITTEN
  Unwritten extent - the extent is allocated but its data has not been
  initialized.  This indicates the extent's data will be all zero if read
  through the filesystem but the contents are undefined if read directly from
  the device.

FIEMAP_EXTENT_MERGED
  This will be set when a file does not support extents, i.e., it uses a block
  based addressing scheme.  Since returning an extent for each block back to
  userspace would be highly inefficient, the kernel will try to merge most
  adjacent blocks into 'extents'.

FIEMAP_EXTENT_SHARED
  This flag is set to request that space be shared with other files.

VFS에서 filesystem `->fiemap` 구현

164-217

FIEMAP을 지원하는 filesystem은 `inode_operations`에 `->fiemap(struct inode *, struct fiemap_extent_info *, u64 start, u64 len)` callback을 구현해야 합니다. filesystem은 지원 flag를 정의하고 발견한 extent마다 helper를 호출합니다.

struct inode_operations {
        ...
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
};

callback은 request를 설명하는 `struct fiemap_extent_info`를 받지만 filesystem이 이 structure 내부에 직접 접근할 필요는 없습니다. handler는 signal을 허용하고 fatal signal을 받으면 `EINTR`를 반환해야 합니다.

callback 시작에서 `fiemap_prep(inode, fieinfo, start, &len, supported_flags)`로 flag와 range를 검사합니다. `ioctl_fiemap()`에서 받은 `fieinfo`를 그대로 넘기고 filesystem이 이해하는 flag를 `supported_flags`로 전달합니다.

invalid user flag가 있으면 `fiemap_prep()`가 잘못된 bit를 `fieinfo->fi_flags`에 넣고 `-EBADR`를 반환합니다. filesystem은 즉시 종료해 그 error를 `ioctl_fiemap()`으로 돌려줘야 합니다. request range도 지원 최대 file size와 대조해 검증됩니다.

요청 범위의 각 extent마다 `fiemap_fill_next_extent(info, logical, phys, len, flags, dev)`를 호출합니다. helper는 다음 free `fm_extents` slot을 채우며 specific flag에서 general flag를 자동 추가해 userspace API를 유지합니다.

FIEMAP helper 반환값
Helper반환값의미
`fiemap_prep()``0`flag와 range가 유효
`fiemap_prep()``-EBADR`unsupported flag를 `fi_flags`에 기록하고 즉시 반환
`fiemap_fill_next_extent()``0`extent 복사 성공
`fiemap_fill_next_extent()``1`userspace `fm_extents[]`가 가득 참
`fiemap_fill_next_extent()``-EFAULT`userspace memory로 extent 복사 실패

filesystem callback이 처리해야 하는 결과입니다.

VFS -> File System Implementation
---------------------------------

File systems wishing to support fiemap must implement a ->fiemap callback on
their inode_operations structure. The fs ->fiemap call is responsible for
defining its set of supported fiemap flags, and calling a helper function on
each discovered extent::

  struct inode_operations {
       ...

       int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                     u64 len);

->fiemap is passed struct fiemap_extent_info which describes the
fiemap request:

.. kernel-doc:: include/linux/fiemap.h
    :identifiers: fiemap_extent_info

It is intended that the file system should not need to access any of this
structure directly. Filesystem handlers should be tolerant to signals and return
EINTR once fatal signal received.


Flag checking should be done at the beginning of the ->fiemap callback via the
fiemap_prep() helper::

  int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
                  u64 start, u64 *len, u32 supported_flags);

The struct fieinfo should be passed in as received from ioctl_fiemap(). The
set of fiemap flags which the fs understands should be passed via fs_flags. If
fiemap_prep finds invalid user flags, it will place the bad values in
fieinfo->fi_flags and return -EBADR. If the file system gets -EBADR, from
fiemap_prep(), it should immediately exit, returning that error back to
ioctl_fiemap().  Additionally the range is validate against the supported
maximum file size.


For each extent in the request range, the file system should call
the helper function, fiemap_fill_next_extent()::

  int fiemap_fill_next_extent(struct fiemap_extent_info *info, u64 logical,
                              u64 phys, u64 len, u32 flags, u32 dev);

fiemap_fill_next_extent() will use the passed values to populate the
next free extent in the fm_extents array. 'General' extent flags will
automatically be set from specific flags on behalf of the calling file
system so that the userspace API is not broken.

fiemap_fill_next_extent() returns 0 on success, and 1 when the
user-supplied fm_extents array is full. If an error is encountered
while copying the extent to user memory, -EFAULT will be returned.