%
It is well known that the filesystem is the most basic resource in a
\ system, so basic and ubiquitous that it needs a more handy name ---
I'll stick to the standard practice of calling it simply ``fs''.
I'll assume the reader already knows the basic \ fs ideas ---
access permissions, inodes, the superblock, <#2504#> mount<#2504#>ing and
<#2505#> umount<#2505#>ing. Those concepts are well explained
by smarter authors than me within the standard \ literature, so I
won't duplicate their efforts and I'll stick to \ specific issues.
%
While the first Unices used to support a single fs type,
whose structure was widespread in the whole kernel, today's practice
is to use a standardized interface between the kernel and the fs, in order
to ease data interchange across architectures. \ itself provides
a standardized layer to pass information between the kernel and each fs
module. This interface layer is called VFS, for ``virtual filesystem''.
Filesystem code is therefore split into two layers: the upper layer is
concerned with the management of kernel tables and data structures,
while the lower layer is made up of the set of fs-dependent functions,
and is invoked through the VFS data structures.
All the fs-independent material resides in the <#2506#> fs/*.c<#2506#> files.
They address the following issues:
- Managing the buffer cache (<#2508#> buffer.c<#2508#>);
- Responding to the <#2509#> fcntl()<#2509#> and <#2510#> ioctl()<#2510#> system calls
(<#2511#> fcntl.c<#2511#> and <#2512#> ioctl.c<#2512#>);
- Mapping pipes and FIFOs on inodes and buffers
(<#2513#> fifo.c<#2513#>, <#2514#> pipe.c<#2514#>);
- Managing file- and inode-tables (<#2515#> file_table.c<#2515#>, <#2516#> inode.c<#2516#>);
- Locking and unlocking files and records (<#2517#> locks.c<#2517#>);
- Mapping names to inodes (<#2518#> namei.c<#2518#>, <#2519#> open.c<#2519#>);
- Implementing the tricky <#2520#> select()<#2520#> function (<#2521#> select.c<#2521#>);
- Providing information (<#2522#> stat.c<#2522#>);
- <#2523#> mount<#2523#>ing and <#2524#> umount<#2524#>ing filesystems (<#2525#> super.c<#2525#>);
- <#2526#> exec()<#2526#>ing executables and dumping cores (<#2527#> exec.c<#2527#>);
- Loading the various binary formats (<#2528#> bin_fmt*.c<#2528#>,
as outlined above).
The VFS interface, then, consists of a set of relatively high-level
operations which are invoked from the fs-independent code and are
actually performed by each filesystem type. The most relevant structures are
<#2530#> inode_operations<#2530#> and <#2531#> file_operations<#2531#>, though they're not alone: other
structures exist as well.
All of them are defined within <#2532#> include/linux/fs.h<#2532#>.
The kernel entry point to the actual file system is
the structure <#2533#> file_system_type<#2533#>. An array of <#2534#> file_system_type<#2534#>s is
embodied within <#2535#> fs/filesystems.c<#2535#> and it is referenced whenever a
<#2536#> mount<#2536#> is issued. The function <#2537#> read_super<#2537#> for the relevant fs type
is then in charge of filling a <#2538#> struct super_block<#2538#> item, which in turn
embeds a <#2539#> struct super_operations<#2539#> and a <#2731#> struct <#2540#> type<#2540#>_sb_info<#2731#>.
The former provides pointers to generic fs operations for the
current fs-type, the latter embeds specific information for the fs-type.
#tex2html_wrap2958#