Linuxinodecache mechanism analysis

Source: Internet
Author: User
Article title: Linuxinodecache mechanism analysis. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
The Linux inode cache mechanism is implemented in the fs/inode. c file.
  
   1.1.Inode slab distributor cache
The implementation of the index node cache (icache) mechanism is based on the slab distributor cache of inode objects. Therefore, you must apply for or release an inode object from the physical memory, you must use the kmem_cache_alloc () and kmem_cache_free () functions.
The slab allocation cache of Inode objects is defined by inode_cache_t, a kmem_cache_t type pointer variable. The slab distributor cache is created through the kmem_cache_create () function in the inode_init () initialization function of inode cache.
Linux in inode. the c file defines two encapsulation functions to allocate an inode object from the inode_cacheslab distributor cache or release an unused inode object to the slab distributor, as shown below:
# Define alloc_inode ()\
(Struct inode *) kmem_cache_alloc (inode_cachu, SLAB_KERNEL ))
Static void destroy_inode (struct inode * inode)
{
If (! List_empty (& inode-> I _dirty_buffers ))
BUG ();
Kmem_cache_free (inode_caclap, (inode ));
}
  
   1.2 some underlying operations related to inode objects
In the source file inode. c, some basic underlying operations on inode objects are implemented as follows:
(1) clean_inode () -- initialize some inode object Member domains
This function is used to initialize some members of an inode object that has just been allocated from the inode_cachu slab distributor to a known value (usually 0), but there is an exception, the number of I _nlink links is initialized to 1. This is a static internal function, so it can only be called by other functions in inode. c, such as get_empty_inode () and get_new_inode ().
/*
* This just initializes the inode fields
* To known values before returning the inode ..
*
* I _sb, I _ino, I _count, I _state and the lists have
* Been initialized elsewhere ..
*/
Static void clean_inode (struct inode * inode)
{
Static struct address_space_operations empty_aops;
Static struct inode_operations empty_iops;
Static struct file_operations empty_fops;
Memset (& inode-> u, 0, sizeof (inode-> u ));
Inode-> I _sock = 0;
Inode-> I _op = & empty_iops;
Inode-> I _fop = & empty_fops;
Inode-> I _nlink = 1;/* NOTE! I _nlink is initialized to 1 */
Atomic_set (& inode-> I _writecount, 0 );
Inode-> I _size = 0;
Inode-> I _generation = 0;
Memset (& inode-> I _dquot, 0, sizeof (inode-> I _dquot ));
Inode-> I _pipe = NULL;
Inode-> I _bdev = NULL;
Inode-> I _data.a_ops = & empty_aops;
Inode-> I _data.host = inode;
Inode-> I _mapping = & inode-> I _data;
}
(2) get_empty_inode () -- allocate an empty inode object from the slab distributor
This function allocates an inode object from the slab distributor by calling the alloc_inode macro, then, all fields except I _count reference count and link count I _nlink are initialized to NULL (some fields are initialized by calling the clean_inode function ), and link the inode object to the inode_in_use linked list. Finally, the pointer of this inode object is returned, as shown below:
Struct inode * get_empty_inode (void)
{
Static unsigned long last_ino;
Struct inode * inode;
  
Inode = alloc_inode ();
If (inode)
{
Spin_lock (& inode_lock );
Inodes_stat.nr_inodes ++;
List_add (& inode-> I _list, & inode_in_use );
Inode-> I _sb = NULL;
Inode-> I _dev = 0;
Inode-> I _ino = ++ last_ino;
Inode-> I _flags = 0;
Atomic_set (& inode-> I _count, 1 );
Inode-> I _state = 0;
Spin_unlock (& inode_lock );
Clean_inode (inode );
}
Return inode;
}
Linux kernel modules generally do not call this function to allocate an inode object. Kernel modules (such as the network layer) that want to obtain an inode object without an index node number, and fs with no known information, this function is usually used to obtain a new inode object.
(3) clear_inode () -- clears the content of an inode object
Before calling the destroy_inode () function to release an inode object, you can call this function to clear the content of the inode object, for example: invalidates the buffer referenced by inode, removes the reference to other objects, and so on.
/**
* Clear_inode-clear an inode
* @ Inode: inode to clear
*
* This is called by the filesystem to tell us
* That the inode is no longer useful. We just
* Terminate it with extreme prejudice.
*/
Void clear_inode (struct inode * inode)
{
If (! List_empty (& inode-> I _dirty_buffers ))
Invalidate_inode_buffers (inode );
  
If (inode-> I _data.nrpages)
BUG ();
If (! (Inode-> I _state & I _FREEING ))
BUG ();
If (inode-> I _state & I _CLEAR)
BUG ();
Wait_on_inode (inode );
If (IS_QUOTAINIT (inode ))
DQUOT_DROP (inode );
If (inode-> I _sb & inode-> I _sb-> s_op-> clear_inode)
Inode-> I _sb-> s_op-> clear_inode (inode );
If (inode-> I _bdev ){
Bdput (inode-> I _bdev );
Inode-> I _bdev = NULL;
}
Inode-> I _state = I _CLEAR;
}
  
   1.3 icache data structure
Linux defines a variety of two-way linked lists based on the inode_cacheslab distributor cache to implement the inode Cache mechanism, so as to effectively manage memory inode objects. These linked lists include the inode linked list in use, unused inode linked list, inode hash linked list, and anonymous inode hash linked list. their definitions are as follows:
Static LIST_HEAD (inode_in_use );
Static LIST_HEAD (inode_unused );
Static struct list_head * inode_hashtable;
Static LIST_HEAD (anon_hash_chain);/* for inodes with NULL I _sb */
In addition, each super block object super_block has a modified and in use inode bidirectional linked list s_dirty.
Each inode object will exist in two separated two-way linked lists:
(1) inode_hashtable, an inode hash linked list, is used to accelerate inode search. Each inode object is linked to the hash linked list through the I _hash pointer.
(2) Another is the inode "type" linked list:
L If I _count> 0, I _nlink> 0, and the inode is not dirty, the inode is linked to the global inode_in_use bidirectional linked list through its I _list pointer.
L if both I _count and I _nlink are greater than 0, but the inode is dirty (I _DIRTY flag is set in the I _state domain ), the inode uses the I _list pointer to link the s_dirty linked list of the super_block object to which it belongs.
L If I _count = 0, the inode_unused linked list is linked through its I _list.
For anonymous inode objects that do not belong to any super block object (that is, I _sb = NULL), the I _hash pointer is used to link them to the system's global Anonymous inode hash linked list anon_hash_chain.
  
   1.3.1 protection of inode cache linked list locks
Linux defines the spin lock inode_lock in inode. c to implement mutually exclusive access to all inode cache linked lists. That is, any code segment that accesses any inode cache linked list must hold the spin lock by calling the spin_lock () function and release the spin lock through the spin_unlock () after the Access ends. Inode_lock is defined as follows:
Spinlock_t inode_lock = SPIN_LOCK_UNLOCKED;
NOTE! If you want to change the I _state domain of an inode object in use, you must first hold the spin lock.
  
   1.3.2 inode cache statistics
The global variable inodes_stat defines the inode cache statistics, including the total number of inode objects in the cache and the number of unused inode objects. its definition is as follows:
Struct {
Int nr_inodes;
Int nr_unused;
Int dummy [5];
} Inodes_stat;
  
   1.3.3 inode hash linked list
The main purpose of the inode hash linked list is to accelerate the search for a specific inode object in icache. The pointer inode_hashtable points to a set of hash linked list headers. all inode objects with the same hash function value (as h) form a two-way linked list through the I _hash pointer, after the hash table header inode_hashtable [h. The headers of all hash linked lists are put together to form an array. The first address of the array is pointed by the inode_hashtable pointer.
In Linux, inode hash linked list header arrays are stored in 2 consecutive physical page frames, where order ≥1, the value is related to the value of num_physpages in the system's total number of physical page frames. Therefore, the number of hash table headers is 2order * PAGE_SIZE/sizeof (struct list_head ). Because the size of the list_head structure is 8 bytes (2 32-bit pointers), the number of inode hash table headers can be expressed as 2 (order + 12-3 ).
1. hash linked list initialization
Inode cache initialization is completed by the inode_init () function. it mainly completes two tasks: (1) inode hash linked list initialization, including allocating physical memory to the inode hash linked list header array; (2) creating inode slab distributor cache. The source code of this function is as follows:
/*
* Initialize the hash tables.
*/
Void _ init inode_init (unsigned long mempages)
{
Struct list_head * head;
Unsigned long order;
Unsigned int nr_hash;
Int I;
  
/* Calculate the value of order, but I don't know why? :)*/
Mempages >>= (14-PAGE_SHIFT );
Mempages * = sizeof (struct list_head );
For (order = 0; (1UL
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.