Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 8: The Virtual Filesystem


❑ f_opspecifies the functions invoked for file operations (see Section 8.3.4).
❑ f_versionis used by filesystems to check whether afileinstance is still compatible with the
contents of the associated inode. This is important to ensure the consistency of cached objects.
❑ mappingpoints to the address space mapping that belongs to the inode instance with which
the file is associated. Usually, it is a shorthand forinode->i_mapping,butfilesystemsor
other subsystems of the kernel may modify it for their purposes, which I will not discuss any
further.

Every superblock provides ans_listlist head element to holdfileobjects — linked by means of
file->f_list. The list includes all opened files of the filesystem represented by the superblock. It is
scanned when, for example, a filesysteminRead/WritemodeistoberemountedinReadOnlymode.
Of course, this cannot be done if files are still open in Write mode — and the kernel checks this list to
find out.^8

fileinstances can be reserved withget_empty_filp, which employs its own cache and pre-initializes
the instances with essential data.

Increasing the Initial Limits


Whenever the kernel opens a file or does some other action that could need more entries infile_struct
than initially provided, it callsexpand_files. The function checks if an enlargement is necessary
and callsexpand_fdtableif this is the case. The function is — slightly simplified — implemented as
follows.

fs/file.c
static int expand_fdtable(struct files_struct *files, int nr)
{
struct fdtable *new_fdt, *cur_fdt;

spin_unlock(&files->file_lock);
new_fdt = alloc_fdtable(nr);
spin_lock(&files->file_lock);

copy_fdtable(new_fdt, cur_fdt);
rcu_assign_pointer(files->fdt, new_fdt);
if (cur_fdt->max_fds > NR_OPEN_DEFAULT)
free_fdtable(cur_fdt);

return 1;
}

alloc_fdtableallocates a file descriptor table with the maximal number of possible entries and also
reserves memory for the enlarged bitmaps — it only makes sense to increase all components at the
same time. After this, the function copies the previous contents of the file descriptor table into the
new, enlarged instance. Switching the pointerfiles_fdtto the new instance is handled by the RCU
functionrcu_assign_pointeras described in Chapter 5. After this, the old file descriptor table can
be freed.

(^8) Actually, this is slightly more complicated in reality because the RCU mechanism is used to make the freeing offileinstances
more efficient. Since this only complicates things, but does not add new insights. I am not going to discuss it any further.

Free download pdf