Section 6.3. Structures Associated with VFS


6.3. Structures Associated with VFS

Other than the four main VFS structures, a few other structures interact with VFS: fs_struct, files_struct, namespace, and fd_set. The structures fs_struct, files_stuct, and namespace are all process-related objects that contain file-related data. Figure 6.10 relates how a process descriptor associates with file-related structures. We now look at these additional structures.

Figure 6.10. Process-Related Objects


6.3.1. fs_struct Structure

In Linux, multiple processes could refer to a single file. As a result, the Linux VFS must store information about how processes and files interact. For example, a process started by one user might differ from a process started by another user with respect to permissions related to file operations. The fs_struct structure holds all the information associating a particular process to a file. We need to examine the fs_struct structure prior to examining the files_struct structure because it uses the fs_struct datatype.

fs_struct can be referred to by multiple process descriptors, so it is not uncommon that an fs_struct representing a file is referenced by many task_struct descriptors:

 ----------------------------------------------------------------------- include/linux/fs_struct.h  7  struct fs_struct {  8   atomic_t count;  9   rwlock_t lock; 10   int umask; 11   struct dentry * root, * pwd, * altroot; 12   struct vfsmount * rootmnt, * pwdmnt, * altrootmnt; 13  }; ----------------------------------------------------------------------- 

6.3.1.1. count

The count field holds the number of process descriptors that reference the particular fs_struct.

6.3.1.2. umask

The umask field holds the mask representing the permissions to be set on files opened.

6.3.1.3. root, pwd, and altroot

The root and pwd fields are pointers to the dentry object associated with the process' root directory and current working directory, respectively. altroot is a pointer to the dentry structure of an alternative root directory. This field is used for emulation environments.

6.3.1.4. rootmnt, pwdmnt, and altrootmnt

The fields rootmnt, pwdmnt, and altrootmnt are pointers to the mounted filesystem object of the process' root, current working, and alternative root directories, respectively.

6.3.2. files_struct Structure

files_struct contains information related to open files and their descriptors. In the introduction, we mentioned that file descriptors are unique int datatypes associated with an open file. In kernel terms, the file descriptor is the index into the fd array of the files object of the current task's task_struct or current->files->fd. Figure 6.7 shows the fd array of a task_struct and how it points to the file's file structure.

Linux can associate sets of file descriptors according to shared qualities, such as read-only or read-write. The fd_struct structure represents the file descriptor sets. The files_struct uses these sets to group its file descriptors:

 ----------------------------------------------------------------------- include/linux/file.h 22  struct files_struct { 23    atomic_t count; 24   spinlock_t file_lock 25    int max_fds; 26    int max_fdset; 27    int next_fd; 28    struct file ** fd;   29    fd_set *close_on_exec; 30    fd_set *open_fds; 31    fd_set close_on_exec_init; 32    fd_set open_fds_init; 33    struct file * fd_array[NR_OPEN_DEFAULT]; 34  }; ----------------------------------------------------------------------- 

Line 23

The count field exists because the files_struct can be referred to by multiple process descriptors, much like the fs_struct. This field is incremented in the kernel routine fget() and decremented in the kernel routine fput(). These functions are called during the file-closing process.

Line 25

The max_fds field keeps track of the maximum number of files that the process can have open. The default of max_fds is 32 as associated with NR_OPEN_DEFAULT size of the fd_array. When a file wants to open more than 32 files, this value is grown.

Line 26

The max_fdset field keeps track of the maximum number of file descriptors. Similar to max_fds, this field can be expanded if the total number of files the process has open exceeds its value.

Line 27

The next_fd field holds the value of the next file descriptor to be assigned. We see how it is manipulated through the opening and closing of files, but one thing should be understood: File descriptors are assigned in an incremental manner unless a previously assigned file descriptor's associated file is closed. In this case, the next_fd field is set to that value. Thus, file descriptors are assigned in a lowest available value manner.

Line 28

The fd array points to the open file object array. It defaults to fd_array, which holds 32 file descriptors. When a request for more than 32 file descriptors comes in, it points to a newly generated array.

Lines 3032

close_on_exec, open_fds, close_on_exec_init, and open_fds_init are all fields of type fd_set. We mentioned that the fd_set structure holds sets of file descriptors. Before explaining each field individually, we look at the fd_set structure.

The fd_set datatype can be traced back to a struct that holds an array of unsigned longs, each of which holds a file descriptor:

 ----------------------------------------------------------------------- include/linux/types.h 22  typedef __kernel_fd_set   fd_set; ----------------------------------------------------------------------- 

The fd_set datatype is a type definition of __kernel_fd_set. This datatype structure holds an array of unsigned longs:

 ----------------------------------------------------------------------- include/linux/posix_types.h 36  typedef struct { 37   unsigned long fds_bits [__FDSET_LONGS]; 38  } __kernel_fd_set; ----------------------------------------------------------------------- 

__FDSET_LONGS has a value of 32 on a 32-bit system and 16 on a 64-bit system, which ensures that fd_sets always has a bitmap of size 1,024. This is where __FDSET_LONGS is defined:

 ----------------------------------------------------------------------- include/linux/posix_types.h  6  #undef __NFDBITS  7  #define __NFDBITS  (8 * sizeof(unsigned long))  8  9  #undef __FD_SETSIZE 10  #define __FD_SETSIZE  1024 11   12  #undef __FDSET_LONGS 13  #define __FDSET_LONGS  (__FD_SETSIZE/__NFDBITS) ----------------------------------------------------------------------- 

Four macros are available for the manipulation of these file descriptor sets (see Table 6.8).

Table 6.8. File Descriptor Set Macros

Macro

Description

FD_SET

Sets the file descriptor in the set.

FD_CLR

Clears the file descriptor from the set.

FD_ZERO

Clears the file descriptor set.

FD_ISSET

Returns if the file descriptor is set.


Now, we look at the various fields.

6.3.2.1. close_on_exec

The close_on_exec field is a pointer to the set of file descriptors that are marked to be closed on exec(). It initially (and usually) points to the close_on_exec_init field. This changes if the number of file descriptors marked to be open on exec() grows beyond the size of the close_on_exec_init bit field.

6.3.2.2. open_fds

The open_fds field is a pointer to the set of file descriptors that are marked as open. Like close_on_exec, it initially points to the open_fds_init field and changes if the number of file descriptors marked as open grows beyond the size of open_fds_init bit field.

6.3.2.3. close_on_exec

The close_on_exec_init field holds the bit field that keeps track of the file descriptors of files that are to be closed on exec().

6.3.2.4. open_fds_init

The open_fds_init field holds the bit field that keeps track of the file descriptors of files that are open.

6.3.2.5. fd_array

The fd_array array pointer points to the first 32 open file descriptors.

The fs_struct structures are initialized by the INIT_FILES macro:

 ----------------------------------------------------------------------- include/linux/init_task.h  6  #define INIT_FILES \  7  {           8   .count    = ATOMIC_INIT(1),     9   .file_lock   = SPIN_LOCK_UNLOCKED,    10   .max_fds   = NR_OPEN_DEFAULT,    11   .max_fdset   = __FD_SETSIZE,    12   .next_fd   = 0,       13   .fd    = &init_files.fd_array[0],   14   .close_on_exec  = &init_files.close_on_exec_init,  15   .open_fds   = &init_files.open_fds_init,   16   .close_on_exec_init = { { 0, } },    17   .open_fds_init  = { { 0, } },     18   .fd_array   = { NULL, }     19  } ----------------------------------------------------------------------- 

Figure 6.11 illustrates what the fs_struct looks like after it is initialized.

 ----------------------------------------------------------------------- include/linux/file.h 6  #define NR_OPEN_DEFAULT BITS_PER_LONG ----------------------------------------------------------------------- 

Figure 6.11. init fs_struct


The NR_OPEN_DEFAULT global definition is set to BITS_PER_LONG, which is 32 on 32-bit systems and 64 on 64-bit systems.




The Linux Kernel Primer. A Top-Down Approach for x86 and PowerPC Architectures
The Linux Kernel Primer. A Top-Down Approach for x86 and PowerPC Architectures
ISBN: 131181637
EAN: N/A
Year: 2005
Pages: 134

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net