xref: /haiku/docs/develop/file_systems/xfs.rst (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1The XFS File System
2===================
3
4This document describes how to test the XFS file system, XFS file system API for haiku
5and Its current status on haiku.
6
7
8Testing XFS File System
9-----------------------
10
11There are three ways we can test XFS :
12
13-  Using xfs_shell.
14-  Using userlandfs.
15-  Building a version of haiku with XFS support and then mounting a file system.
16
17But before that we will need to create XFS images for all testing purposes.
18
19Creating File System Images
20^^^^^^^^^^^^^^^^^^^^^^^^^^^
21
22Currently only linux has full XFS support so we will use linux for generating file system images.
23
24First we need to create an empty sparse image using command::
25
26   $ dd if=/dev/zero of=fs.img count=0 bs=1 seek=5G
27
28The output will be::
29
30   0+0 records in
31   0+0 records out
32   0 bytes (0 B) copied, 0.000133533 s, 0.0 kB/s
33
34Do note that we can create images of whatever size or name we want, for example the above command
35creates fs.img of size 5 GB, if we alter seek = 10G it will create fs.img with size 10 GB.
36
37The XFS file system on linux supports two versions, V4 and V5.
38
39To put XFS V5 file system on our sparse image run command::
40
41   $ /sbin/mkfs.xfs fs.img
42
43The output will be::
44
45   meta-data   =fs.img                 isize=512    agcount=4, agsize=65536 blks
46               =                       sectsz=512   attr=2, projid32bit=1
47               =                       crc=1        finobt=1, sparse=1, rmapbt=0
48               =                       reflink=1
49   data        =                       bsize=4096   blocks=262144, imaxpct=25
50               =                       sunit=0      swidth=0 blks
51   naming      =version 2              bsize=4096   ascii-ci=0, ftype=1
52   log         =internal log           bsize=4096   blocks=2560, version=2
53               =                       sectsz=512   sunit=0 blks, lazy-count=1
54   realtime    =none                   extsz=4096   blocks=0, rtextents=0
55
56To put XFS V4 file system on our sparse image run command::
57
58   $ /sbin/mkfs.xfs -m crc=0 file.img
59
60The output will be::
61
62    meta-data=fs.img                 isize=256    agcount=4, agsize=327680 blks
63             =                       sectsz=512   attr=2, projid32bit=0
64    data     =                       bsize=4096   blocks=1310720, imaxpct=25
65             =                       sunit=0      swidth=0 blks
66    naming   =version 2              bsize=4096   ascii-ci=0
67    log      =internal log           bsize=4096   blocks=2560, version=2
68             =                       sectsz=512   sunit=0 blks, lazy-count=1
69    realtime =none                   extsz=4096   blocks=0, rtextents=0
70
71**The linux kernel will support older XFS v4 filesystems by default until 2025 and
72Support for the V4 format will be removed entirely in September 2030**
73
74Now we can mount our file system image and create entries for testing XFS haiku driver.
75
76Test using xfs_shell
77^^^^^^^^^^^^^^^^^^^^^^^
78
79The idea of fs_shell is to run the file system code outside of haiku. We can run it
80as an application, it provides a simple command line interface to perform various
81operations on the file system (list directories, read and display files, etc).
82
83First we have to compile it::
84
85   jam "<build>xfs_shell"
86
87Then run it::
88
89   jam run ":<build>xfs_shell" fs.img
90
91Where fs.img is the file system image we created from linux kernel.
92
93Test directly inside Haiku
94^^^^^^^^^^^^^^^^^^^^^^^^^^
95
96First build a version of haiku with XFS support, to do this we need to add "xfs" to the `image
97definition <https://git.haiku-os.org/haiku/tree/build/jam/images/definitions/minimum#n239>`__.
98
99Then compile haiku as usual and run the resulting system in a virtual machine or on real hardware.
100
101We can then try to mount an XFS file system using command on Haiku::
102
103   mount -t xfs <path to image> <path to mount folder>
104
105for example::
106
107   mount -t xfs /boot/home/Desktop/fs.img /boot/home/Desktop/Testing
108
109Here fs.img is file system image and Testing is mount point.
110
111Test using userlandfs
112^^^^^^^^^^^^^^^^^^^^^
113
114To be updated
115
116
117Haiku XFS API
118-------------
119
120All the necessary hooks for file system like xfs_mount(), open_dir(), read_dir() etc.. are
121implemented in the **kernel_interface.cpp** file. It acts as an interface between the Haiku kernel
122and the XFS file system. Documentation for all necessary file system hooks can be found
123`in the API reference <https://www.haiku-os.org/docs/api/fs_modules.html>`_
124
125Whenever we run a file system under fs_shell we can't use system headers, fs_shell compatible
126headers are there which needs to be used whenever we try to mount XFS file system using xfs_shell.
127To resolve this problem we use **system_dependencies.h** header file which takes care to use
128correct headers whenever we mount XFS file system either using xfs_shell or directly inside Haiku.
129
130XFS stores data on disk in Big Endian byte order, to convert data into host order
131all classes and data headers has **SwapEndian()** function, Its better to have all data
132conversions at one place to avoid future problems related to data byte order.
133
134XFS SuperBlock starts at ondisk offset 0, the definition of SuperBlock is in **xfs.h** file.
135
136A Volume is an instance of file system and defined in **Volume.h** file.
137XFS Volume contains SuperBlock, file system device and essential functions
138like Identify(), mount() etc...
139
140*  *Identify()* function reads SuperBlock from disk and verifies it.
141*  *Mount()* function mounts file system device and publishes root inode of file system
142   (Typically root inode number for XFS is 128).
143
144XFS uses TRACE Macro to debug file system, definitions for TRACE, ERROR and ASSERT
145are defined at **Debug.h** in the form of Macro.
146
147To enable TRACE calls just add ``#define TRACE_XFS`` in Debug.h file and
148vice versa to disable it.
149
150
151XFS V5 introduced metadata checksums to ensure the integrity of metadata in file system,
152It uses CRC32C checksum algorithm. For XFS all checksums related functions are defined in
153**Checksum.h** header file.
154It contains following functions :
155
156*  *xfs_verify_cksum()* to verify checksum for buffer.
157*  *xfs_update_cksum()* to update checksum for buffer.
158
159**XFS stores checksum in little endian byte order unlike other ondisk data which is stored
160in big endian byte order**
161
162XFS V5 introduced many other fields for metadata verification like *BlockNo* *UUID* *Owner*
163etc.. All this fields are common in every data header and so are their checks. So to not
164repeat same checks again and again for all headers we created a *VerifyHeader* template
165function which is defined in **VerifyHeader.h** file. This function is commonly used in
166all forms of headers for verification purposes.
167
168Inodes
169^^^^^^
170
171XFS inodes comes in three versions:
172
173*  Inode V1 & V2. (Version 4 XFS)
174*  Inode V3. (Version 5 XFS)
175
176Version 1 inode support is already deprecated on linux kernel, Haiku XFS supports it only
177in read format. When we will have write support for XFS we will only support V2 and V3 inodes.
178
179V1 & V2 inodes are 256 bytes while V3 inodes are 512 bytes in size allowing more data to be
180stored directly inside inode.
181
182**CoreInodeSize()** is a helper funtion which returns size of inode based on version of XFS and
183is used throughout our XFS code.
184
185**DIR_DFORK_PTR** is a Macro which expands to void pointer to the data offset in inode, which
186could be either shortform entries, extents or B+Tree root node depending on the data format
187of inode (di_format).
188
189Similarly **DIR_AFORK_PTR** Macro expands to void pointer to the attribute offset in inode,
190which could be either shortform attributes, attributes extents or B+Tree node depending on
191the attribute format of Inode (di_aformat).
192
193Since size of inodes could differ based on different versions of XFS we pass CoreInodeSize()
194function as a parameter to DIR_DFORK_PTR and DIR_AFORK_PTR macros to return correct pointer offset.
195
196**di_forkoff** specifies the offset into the inode's literal area where the extended attribute
197fork starts. This value is initially zero until an extended attribute is created.
198It is fixed for V1 & V2 inode's while for V3 Inodes it is dynamic in size,
199allowing complete use of inode's literal area.
200
201Directories
202^^^^^^^^^^^
203
204Depending on the number of entries inside directory, XFS divides directories into five formats :
205
206*  Shortform directory.
207*  Block directory.
208*  Leaf directory.
209*  Node directory.
210*  B+Tree directorcy.
211
212Class DirectoryIterator in **Directory.h** file provides an interface between kernel request
213to open, read directory and all forms of directories. It first identifies correct format of
214entries inside inode and then returns request as per format found.
215
216**Shortform directory**
217
218*  When the number of entries inside directory are small enough such that we can store all
219   metadata inside inode itself, this form of directory is known as shortform directory.
220*  We can check if a directory is shortform if the format of inode is *XFS_DINODE_FMT_LOCAL*.
221*  The header for ShortForm entries is located at data fork pointer inside inode, which we cast
222   directly to *ShortFormHeader*.
223*  Since number of entries are short we can simply iterate over all entries for *Lookup()* and
224   *GetNext()* functions.
225
226**Block directory**
227
228*  When number of entries expand such that we can no longer store all directory metadata
229   inside inode we use extents.
230*  We can check if a directory is extent based if the format of inode is *XFS_DINODE_FMT_EXTENTS*.
231*  In Block directory we have a single directory block for Data header, leaf header
232   and free data header. This simple fact helps us to determine if given extent format
233   in inode is block directory.
234*  Since XFS V4 & V5 data headers differs we use a virtual class *ExtentDataHeader* which
235   acts as an interface between V4 & V5 data header, this class only stores pure virtual
236   functions and no data.
237*  *CreateDataHeader* returns a class instance based on the version of XFS mounted.
238*  Since now we have a virtual class with V_PTRS we need to be very careful with data stored
239   ondisk and data inside class, for example we now can't use sizeof() operator on class to
240   return its size which is consistent with its size inside disk. To handle this issue helper
241   function like *SizeOfDataHeader* are created which needs to be used instead of sizeof() operator.
242*  In *GetNext()* function we simply iterate over all entries inside buffer, though a found
243   entry could be unused entry so we need to have checks if a entry found is proper entry.
244*  In *Lookup()* function first we generate a hash value of entry for lookup, then we find
245   lowerbound of this hash value inside leaf entries to get address of entry inside data.
246   At last if entry matches we return B_OK else we return B_ENTRY_NOT_FOUND.
247
248**Leaf directory**
249
250*  When number of entries expand such that we can no longer store all directory metadata inside
251   directory block we use leaf format.
252*  In leaf directory we have a multiple directory block for Data header and free data header,
253   while single directory block for leaf header.
254*  To check if given extent based inode is leaf type, we simply check for offset inside last
255   extent map, if its equal to *LEAF_STARTOFFSET* then the given inode is leaf type else it is
256   node type.
257*  Since XFS V4 & V5 leaf headers differs we use a virtual class *ExtentLeafHeader* which acts
258   as an interface between V4 & V5 leaf header, this class only stores pure virtual functions
259   and no data.
260*  *CreateLeafHeader* returns a class instance based on the version of XFS mounted.
261*  Instead of sizeof() operator on ExtentLeafHeader we should always use *SizeOfLeafHeader()* function
262   to return correct size of class inside disk.
263*  *Lookup()* and *GetNext()* functions are similar to block directories except now we don't use single
264   directory block buffer.
265
266TODO : Document Node and B+Tree based directories.
267
268Files
269^^^^^
270
271XFS stores files in two formats :
272
273*  Extent based file.
274*  B+Tree based file.
275
276All implementation of read support for files is inside *Inode()* class in **Inode.h** file.
277
278When the format inside inode of file is *XFS_DINODE_FMT_EXTENTS* it is an extent based file,
279to read all data of file we simply iterate over all extents which is very similar to how we
280do it in Extent based directories.
281
282When the file becomes too large such that we cannot store more extent maps inside inode the
283format of file is changed to B+Tree. When the format inside inode of file is
284*XFS_DINODE_FMT_BTREE* it is an B+Tree based file, to read all data of file
285first we read blocks of B+Tree to extract extent maps and then read extents
286to get file's data.
287
288
289Current Status of XFS
290---------------------
291
292Currently we only have read support for XFS, below briefly summarises read support for all formats.
293
294
295Directories
296^^^^^^^^^^^
297
298**Short-Directory**
299   Stable read support for both V4 and V5 inside Haiku.
300
301**Block-Directory**
302   Stable read support for both V4 and V5 inside Haiku.
303
304**Leaf-Directory**
305   Stable read support for both V4 and V5 inside Haiku.
306
307**Node-Directory**
308   Stable read support for both V4 and V5 inside Haiku.
309
310**B+Tree-Directory**
311   Unstable read support for both V4 and V5, due to so many read from disk entire
312   process inside Haiku is too slow.
313
314Files
315^^^^^
316
317**Extent based Files**
318   |  *xfs_shell* - stable read support for both V4 and V5.
319   |  *Haiku* - Unstable, Cat command doesn't print entire file and never terminates process.
320
321**B+Tree based Files**
322   |  *xfs_shell* - stable read support for both V4 and V5.
323   |  *Haiku* - Unstable, Cat command doesn't print entire file and never terminates process.
324
325Attributes
326^^^^^^^^^^
327
328Currently we have no extended attributes support for xfs.
329
330Symlinks
331^^^^^^^^
332
333Currently we have no symlinks support for xfs.
334
335XFS V5 exclusive features
336^^^^^^^^^^^^^^^^^^^^^^^^^
337
338**MetaData Checksumming**
339   Metadata checksums for superblock, Inodes, and data headers are implemented.
340
341**Big Timestamps**
342   Currently we have no support.
343
344**Reverse mapping btree**
345   Currently we have no support, this data structure is still under construction
346   and testing inside linux kernel.
347
348**Refrence count btree**
349   Currently we have no support, this data structure is still under construction
350   and testing inside linux kernel.
351
352Write Support
353^^^^^^^^^^^^^
354
355Currently we have no write support for xfs.
356
357
358References
359----------
360
361The best and only reference for xfs is latest version of "xfs_filesystem_structure"
362written by Linux-XFS developers.
363
364The pdf version of above Doc can be found
365`here <http://ftp.ntu.edu.tw/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf>`_
366