The directory item of the file “hello.txt” is loaded into directory file user2. We first intro- duce the schematic diagram of the directory file (Figure 5.10).
The new directory item that was inserted continuously
Case 1 Case 2 Case 3 Case 4 Case 5
The directory item which has never been used
The directory item which has been deleted after used The occupied directory item Directory file
The first data block (1 KB)
The second data block (1 KB)
The third data block (1 KB)
The fourth data block (1 KB)
Directory file Directory file Directory file Directory file
Figure 5.10 Schematic diagram of the directory file.
if (!(inode = get_empty_inode())) //get free i-node item in inode_table[32]
return NULL;
if (!(sb = get_super(dev))) //get device super block(loaded when installing file system) panic(“new_inode with unknown device”);
//below set i-node bitmap based on information about i-node bitmap from super block j = 8192;
for (i = 0 ; i<8 ; i++) if (bh = sb->s_imap[i])
if ((j = find_first_zero(bh->b_data))<8192) break;
if (!bh || j > = 8192 || j+i*8192 > sb->s_ninodes) { iput(inode);
return NULL;
}
if (set_bit(j,bh->b_data))
panic(“new_inode: bit already set”);
//above set i-node bitmap based on information about i-node bitmap from super block bh->b_dirt = 1; //1set revised flag of buffer block where i-node bitmap is as 1 //below set property of i-node
inode->i_count = 1;
inode->i_nlinks = 1;
inode->i_dev = dev;
inode->i_uid = current->euid;
inode->i_gid = current->egid;
inode->i_dirt = 1;
inode->i_num = j + i*8192;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
return inode;
}
Situation 1 is the initial state of a content file. Situation 2 concerns deleting one of the directory items (i.e., clear the i node number of directory items as 0). Situations 3, 4, and 5 involve loading directory items continuously.
The system calls the function add_entry() to create a new directory item.
The code is as follows:
The task of the function add_entry() is to load a new directory item if an free item can be found in the directory file. If not, the system will create a new data block in the periph- erals to load. The scenario of loading is shown previously.
The code is as follows:
//code path:fs/namei.c:
int open_namei(const char * pathname, int flag, int mode, struct m_inode **
res_inode) {
……
inode = new_inode(dir->i_dev); //create new i-node if (!inode) {
iput(dir);
return -ENOSPC;
}
inode->i_uid = current->euid; //set id of i-node user inode->i_mode = mode; //set i-node as access mode inode->i_dirt = 1; //set use-flag of i-node as 1 bh = add_entry(dir,basename,namelen,&de); //add directory item
if (!bh) {
inode->i_nlinks— ; iput(inode);
iput(dir);
return -ENOSPC;
}
de->inode = inode->i_num; //add i-node number in directory item bh->b_dirt = 1;
brelse(bh);
iput(dir);
*res_inode = inode;
return 0;
}
……
}
//code path:fs/namei.c:
static struct buffer_head * add_entry(struct m_inode * dir,
const char * name, int namelen, struct dir_entry ** res_dir) //add directory item in //directory file user2 {
int block,i;
struct buffer_head * bh;
struct dir_entry * de;
*res_dir = NULL;
#ifdef NO_TRUNCATE if (namelen > NAME_LEN)
return NULL;
#else
if (namelen > NAME_LEN) namelen = NAME_LEN;
The code of the function create_block() is as follows:
#endif
if (!namelen) return NULL;
if (!(block = dir->i_zone[0])) //confirm logic block number on //device of the first file block in directory file user2(not 0)
return NULL;
if (!(bh = bread(dir->i_dev,block))) //load content of directory file into a //data block
return NULL;
i = 0;
de = (struct dir_entry *) bh->b_data;
while (1) { //search idle directory item in directory file
// = = = = =load next data block to continue searching when whole data block has no free item //create new data block on device to load new content item when all have no free item = = = = = =
if ((char *)de >= BLOCK_SIZE+bh->b_data) { brelse(bh);
bh = NULL;
block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
if (!block)
return NULL;
if (!(bh = bread(dir->i_dev,block))) { i += DIR_ENTRIES_PER_BLOCK;
continue;
}
de = (struct dir_entry *) bh->b_data;
}
//= = = = = = = = = = = = = = = = = = = =find free item at end of data block, and load //directory item where it is idle = = = = = = = = = = = = = = = = = = = =
if (i*sizeof(struct dir_entry) >= dir->i_size) { de->inode=0;
dir->i_size = (i+1)*sizeof(struct dir_entry);
dir->i_dirt = 1;
dir->i_ctime = CURRENT_TIME;
}
//= = = = = = = = = = = = = = = = = = = =find free item in middle of data block, and load //directory item there = = = = = = = = = = = = = = = = = = = =
if (!de->inode) {
dir->i_mtime = CURRENT_TIME;
for (i=0; i < NAME_LEN ; i++)
de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
bh->b_dirt = 1;
*res_dir = de;
return bh;
} de++;
i++;
}
brelse(bh);
return NULL;
}
//code path:fs/inode.c:
int create_block(struct m_inode * inode, int block) {
return _bmap(inode,block,1);
//last parameter is creating flag,here it is set as 1,meaning //creating new data block probably, which is different in chapter 5.3.1 }
After entering the function _bmp(), the code below is very important:
//code path:fs/inode.c:
static int _bmap(struct m_inode * inode,int block,int create) {
struct buffer_head * bh;
int i;
if (block<0) //if data block number of file to be operated is less //than 0
panic(“_bmap: block<0”);
if (block > = 7+512+512*512) //if data block number of file to be operated is less //than allowable limits
panic(“_bmap: block>big”);
//= = = = = = = = = = = = = =not more than 7 logic blocks = = = = = = = = = = = = = = = = = = if (block<7) { //file block number of data block to be operated is
//less than 7
if (create && !inode->i_zone[block]) //if it is to create a new data block, //execute below code
if (inode->i_zone[block] = new_block(inode->i_dev)) { inode->i_ctime = CURRENT_TIME;
inode->i_dirt = 1;
}
return inode->i_zone[block]; //return value of logic block number //recorded in block item of i_zone }
//= = = = = = = = = = = = between 7 and (7+512) logic blocks = = = = = = = = = = = = = = = = block - = 7;
if (block<512) { //if file block number of data block to be //operated is less than 512, block number of one-level indirect search file is needed
if (create && !inode->i_zone[7]) //if it is to create a //new data block, execute below code
if (inode->i_zone[7] = new_block(inode->i_dev)) { inode->i_dirt = 1;
inode->i_ctime = CURRENT_TIME;
}
if (!inode->i_zone[7]) //return 0 directly if one-level block has //no index number
return 0;
if (!(bh = bread(inode->i_dev,inode->i_zone[7]))) //get one-level indirect block return 0;
i = ((unsigned short *) (bh->b_data))[block]; //get logic block number of block //item in direct block
if (create && !i) //execute below code if it is to //create a new data block if (i = new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block] = i;
bh->b_dirt = 1;
} brelse(bh);
return i;
}
//= = = = = = = = = = between 7+512 and 7+512+512*512 logic blocks = = = = = = = = = = = = = block - = 512;
if (create && !inode->i_zone[8]) //execute below code if it is to create a //new data block
if (inode->i_zone[8] = new_block(inode->i_dev)) { inode->i_dirt = 1;
inode->i_ctime = CURRENT_TIME;
}
if (!inode->i_zone[8]) //return 0 if one-level indirect block has no index return 0;
if (!(bh = bread(inode->i_dev,inode->i_zone[8]))) //get one-level indirect block return 0;
i = ((unsigned short *)bh->b_data)[block>>9]; //get logic block number of //block/512 item in indirect block
When the create flag is set, it’s not means creating a new data block without any condition. Furthermore, we should ensure that the next file block does not exist, that is,
!inode->izone[...] or !i is true; thus, apply a new data block. Similar to this example, when loading the content of a directory item with no idle item found in a data block, the next data block might have one idle item. If the data block is forced to be allocated, the existing block will be overwritten, leading to directory file management confusion.
The task of creating a new data block is finished in the function new_block(). We will introduce it in detail in Section 5.5.
The scenario of creating a new directory item is shown in Figure 5.11.
hello.txt
ROM BIOS and VGA
Kernel
0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF
Create a new directory item for hello.txt
Directory item
Figure 5.11 Find idle directory item and add directory data.
if (create && !i) //if it is to create a new data
//block, execute below code if (i = new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block>>9] = i;
bh->b_dirt = 1;
} brelse(bh);
if (!i) return 0;
if (!(bh = bread(inode->i_dev,i))) //get two-level indirect block return 0;
i = ((unsigned short *)bh->b_data)[block&511]; //get logic block number of block&512 item in indirect block
if (create && !i) //if it is to create a new data block, execute below code if (i = new_block(inode->i_dev)) {
((unsigned short *) (bh->b_data))[block&511] = i;
bh->b_dirt = 1;
} brelse(bh);
return i;
}