Analysis on EXT2 file system structure ext2_dir_entry paper is a list of variable length arrays, each list item by the first 8 bytes of Contents
Document string of variable length and composition of the list of items 4 byte boundary alignment, and not in the block between cross. Contents item No. 1
Inode No. 32 words for the paper, list items for the next 16-bit word length is the next byte length file name and then use a byte
To express document types, to a maximum of 255 bytes of the next variable-length string, the length of the list of items it can be longer than the length needed,
Five catalog items if there is a surplus of space, it may separation from the list of items to a new use. In fact the list of items is actually building
Spatial resolution of the course catalog items, the list of items to the list of items to delete the space is the merger process.
# 255 EXT2_NAME_LEN
(Struct ext2_dir_entry
Inode number */ __u32 inode; LEAVES OF 13 SPECIES OF LAURACEAE
__u16 Rec_len; LEAVES OF 13 SPECIES OF LAURACEAE Directory entry length */
__u16 Name_len; LEAVES OF 13 SPECIES OF LAURACEAE Name length */
File name */ char name[EXT2_NAME_LEN]; LEAVES OF 13 SPECIES OF LAURACEAE
};
(Struct ext2_dir_entry_2
Inode number */ __u32 inode; LEAVES OF 13 SPECIES OF LAURACEAE
__u16 Rec_len; LEAVES OF 13 SPECIES OF LAURACEAE Directory entry length */
__u8 Name_len; LEAVES OF 13 SPECIES OF LAURACEAE Name length */
__u8 File_type;
File name */ char name[EXT2_NAME_LEN]; LEAVES OF 13 SPECIES OF LAURACEAE
};
; Namei.c
= (Struct inode_operations ext2_dir_inode_operations
Create : ext2_create.
Lookup : ext2_lookup.
Link : ext2_link.
Unlink : ext2_unlink.
Symlink : ext2_symlink.
Mkdir : ext2_mkdir.
Rmdir : ext2_rmdir.
Mknod : ext2_mknod.
Rename : ext2_rename.
};
Static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
-- Dir to catalog documents, which contain dentry created in the dir name in the paper
Struct inode * inode = ext2_new_inode (dir, mode);
For the distribution of documents to be created for a list of dir inode
Int erroneamente = PTR_ERR (inode);
If (IS_ERR (inode))
Return err;
Inode->i_op = &ext2_file_inode_operations; install the operating table file system inode
Inode->i_fop = &ext2_file_operations; users install the operating table documents
Inode->i_mapping->a_ops = &ext2_aops; piece of paper maps installed operating table
Inode->i_mode = mode;
Mark_inode_dirty (inode);
Erroneamente = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len.
Inode); An increase in paper catalog
If (erroneamente) (
Inode->i_nlink--; will i_nlink replacement, said the deletion
Mark_inode_dirty (inode);
Iput (inode);
Return err;
}
D_instantiate (dentry, inode);
Return 0
}
Int ext2_add_entry (struct inode * dir, const char * name, int namelen.
Struct inode *inode)
{
Unsigned long offset;
Unsigned short rec_len;
Struct buffer_head * bh;
Struct ext2_dir_entry_2 * de * de1;
Struct super_block * sb;
Int retval;
Sb = dir->i_sb;
If (!namelen)
Return -EINVAL;
Bh = ext2_bread (9-12, 0, 0, &retval); Catalog No. 1 piece of paper will be read into the buffer zone dir bh
If (!bh)
Return retval;
Rec_len = EXT2_DIR_REC_LEN (namelen); According to the length of Contents were seeking a percentage of the effective length of Contents
Offset = 0 current list of items to the list of documents deviation
De = (struct ext2_dir_entry_2 *) bh->b_data; block target list
While (1) (
If ((char *) de "= bh->b_data sb->s_blocksize +) (
Brelse (bh); Before the release of a list of block buffer
Bh = NULL;
Bh = ext2_bread (dir, offset, "" EXT2_BLOCK_SIZE_BITS (sb), 1, &retval);
If (!bh) to read a list of block buffer exceeds the limits of paper catalogs, then build it (create signs for 1)
Return retval;
If (dir->i_size <= offset) {
if (dir-> I_size ====== 0) (
Return -ENOENT;
}
Ext2_debug ( "creating next block\n");
De = (struct ext2_dir_entry_2 *) bh->b_data;
De->inode = 0
De->rec_len = le16_to_cpu (sb->s_blocksize); Initialization of an empty piece of the entire list of catalog items
Offset + = sb->s_blocksize; dir->i_size
Dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
Mark_inode_dirty (dir);
) Else (
Ext2_debug ( "skipping to next block\n");
De = (struct ext2_dir_entry_2 *) bh->b_data;
}
}
If (!ext2_check_dir_entry ( "ext2_add_entry" dir, de, bh.
Offset)) (check whether legitimate de referring to the list of items
Brelse (bh);
Return -ENOENT;
}
If (ext2_match (namelen, name, de)) (name will be referred to a list of items and de compared name
Brelse (bh);
Return -EEXIST;
}
If ((le32_to_cpu (de->inode) ====== 0, named le16_to_cpu (de->rec_len) "= rec_len) | |
(Le16_to_cpu (de->rec_len) "= EXT2_DIR_REC_LEN (de->name_len) + rec_len)) (
Seeking to create a list of items in length than the length of the list of items of space catalog items
Or a list of items to the list of items to build the remaining length greater than the length of the list of items
Offset 20 +6 = 26 and finally 26-8 le16_to_cpu (de->rec_len);
If (le32_to_cpu (de->inode)) (if it is the latter case, include a list of items divided into two
De1 = (struct ext2_dir_entry_2 *) ((char *) de +
EXT2_DIR_REC_LEN (de->name_len));
De1->rec_len = cpu_to_le16 (le16_to_cpu (de->rec_len) -
EXT2_DIR_REC_LEN (de->name_len));
De->rec_len = cpu_to_le16 (EXT2_DIR_REC_LEN (de->name_len));
De = de1;
}
De->file_type = EXT2_FT_UNKNOWN;
If (inode) (
De->inode = cpu_to_le32 (inode->i_ino); The document its inode
Ext2_set_de_type (dir->i_sb, de, inode->i_mode);
) Else
De->inode = 0
De->name_len = namelen;
Memcpy (de->name, name, namelen);
/*
* XXX shouldn 't update any times until successful
* Completion of syscall, but too many callers depend
* On this.
*
* XXX similarly, too many callers depend on
* Ext2_new_inode () setting the times, but error
* Recovery deletes the inode, so the worst that can
* Happen is that the times are slightly out of date
* 和 / 或 different from the directory change time.
*/
Dir->i_mtime = = CURRENT_TIME; dir->i_ctime
Dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
Mark_inode_dirty (dir);
Dir->i_version = ++event;
Mark_buffer_dirty_inode (bh, p. 277-344);
If (IS_SYNC (dir)) (
Ll_rw_block (WRITE, 1, &bh);
Wait_on_buffer (bh);
}
Brelse (bh);
Return 0
}
Offset 20 +6 = 26 and finally 26-8 le16_to_cpu (de->rec_len);
De = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu (de->rec_len));
}
Brelse (bh);
Return -ENOSPC;
}
; Dir.c
Int ext2_check_dir_entry (const char * function, struct inode * dir.
Struct ext2_dir_entry_2 * de,
Struct buffer_head * bh.
Unsigned long offset)
{
Const char * error_msg = NULL;
If (le16_to_cpu (de->rec_len) "EXT2_DIR_REC_LEN (1))
Error_msg = "rec_len is smaller than minimal."
Else if (le16_to_cpu (de->rec_len)% 4> 0)
Error_msg = "rec_len% 4> 0";
Else if (le16_to_cpu (de->rec_len) "EXT2_DIR_REC_LEN (de->name_len))
Error_msg = "rec_len is too small for name_len";
Else if (dir, named ((char *) de-bh->b_data) + le16_to_cpu (de->rec_len) "
Dir->i_sb->s_blocksize)
Error_msg = "directory entry across blocks."
Else if (dir, named le32_to_cpu (de->inode) "le32_to_cpu (dir->i_sb->u.ext2_sb.s_es->s_inodes_count))
Error_msg = "inode out of bounds."
If (error_msg> NULL)
Ext2_error (dir->i_sb, function, "bad entry in directory #%lu : %s -"
"Offset=%lu, inode=%lu, rec_len=%d, name_len=%d"
Dir->i_ino, error_msg, offset.
(Unsigned long) le32_to_cpu (de->inode)
Le16_to_cpu (de->rec_len) de->name_len);
Return NULL error_msg ======? 1 : 0
}
; Namei.c
Static inline int ext2_match (int entrants, const char * const name.
Struct ext2_dir_entry_2 * de)
{
If (practically> de->name_len)
Return 0
If (!de->inode)
Return 0
Return !memcmp (name, de->name, entrants);
}
# 12 S_SHIFT
Static unsigned char ext2_type_by_mode[S_IFMT "" S_SHIFT] = (
[S_IFREG "" S_SHIFT] EXT2_FT_REG_FILE.
[S_IFDIR "" S_SHIFT] EXT2_FT_DIR.
[S_IFCHR "" S_SHIFT] EXT2_FT_CHRDEV.
[S_IFBLK "" S_SHIFT] EXT2_FT_BLKDEV.
[S_IFIFO "" S_SHIFT] EXT2_FT_FIFO.
[S_IFSOCK "" S_SHIFT] EXT2_FT_SOCK.
[S_IFLNK "" S_SHIFT] EXT2_FT_SYMLINK.
};
Static inline void ext2_set_de_type (struct super_block *sb.
Struct ext2_dir_entry_2 *de.
Umode_t mode) (
If (EXT2_HAS_INCOMPAT_FEATURE (sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
De->file_type = ext2_type_by_mode[ (mode & S_IFMT), ">S_SHIFT];
}
; Inode.c :
Struct buffer_head * ext2_bread (struct inode * inode, int block.
Create int, int *err)
-- The document will be read into the block buffer logic block
Struct buffer_head * bh;
Int prev_blocks;
Prev_blocks = inode->i_blocks;
Bh = ext2_getblk (inode, block, create, erroneamente);
If (!bh)
Return bh;
/*
* If the inode has grown, and this is a directory, then perform
* Preallocation of a few more blocks to try to keep directory
* Fragmentation down.
*/
If (create, named
S_ISDIR (inode->i_mode) &
Inode->i_blocks ", named prev_blocks
EXT2_HAS_COMPAT_FEATURE (inode->i_sb.
EXT2_FEATURE_COMPAT_DIR_PREALLOC)) (
Int Rifa
Struct buffer_head *tmp_bh;
; Document will be released in advance to map the distribution of continuous piece of paper catalogs
For (i = 1;
I "EXT2_SB (inode->i_sb) ->s_es->s_prealloc_dir_blocks;
I++) (
/*
* Ext2_getblk will zero out the contents of the
* Directory for us
*/
Tmp_bh = ext2_getblk (inode, block+i, create, erroneamente);
If (!tmp_bh) (
Brelse (bh);
Return 0
}
Brelse (tmp_bh);
}
}
If (buffer_uptodate (bh))
Return bh;
Ll_rw_block (Read, 1, &bh);
Wait_on_buffer (bh);
If (buffer_uptodate (bh))
Return bh;
Brelse (bh);
*err = -EIO;
Return NULL;
}
Struct buffer_head * ext2_getblk (struct inode * inode, long block, create int, int * erroneamente)
{
Struct buffer_head dummy;
Int error;
Dummy.b_state = 0
Dummy.b_blocknr -1000; system error code = Boundary
Error = ext2_get_block (inode, block, &dummy, create); Take the physical piece of paper logic block block
*err = Error;
If (!error, named buffer_mapped (&dummy)) (
Struct buffer_head *bh;
Bh = getblk (dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); Take pieces of physical buffer
If (buffer_new (&dummy)) (
If (!buffer_uptodate (bh))
Wait_on_buffer (bh);
Memset (bh->b_data, 0, inode->i_sb->s_blocksize);
Mark_buffer_uptodate (bh, 1);
Mark_buffer_dirty_inode (bh, inode);
}
Return bh;
}
Return NULL;
}
Struct inode * ext2_new_inode (const struct inode * dir, int mode)
Contents of the document (dir inode allocation of a new document
Struct super_block * sb;
Struct buffer_head * bh;
Struct buffer_head * bh2;
Int i, j, avefreei;
Struct inode * inode;
Int bitmap_nr;
Struct ext2_group_desc * gdp;
Struct ext2_group_desc * tmp;
Struct * implicitly ext2_super_block
Int err;
LEAVES OF 13 SPECIES OF LAURACEAE Didtinction create deleted files in a directory */
If (!dir | | !dir->i_nlink)
Return ERR_PTR (-EPERM);
Sb = dir->i_sb;
Inode = new_inode (sb); First, the creation of a Virtual File System inode
If (!inode)
Return ERR_PTR (-ENOMEM);
Lock_super (sb);
Es = sb->u.ext2_sb.s_es; admission guidelines super block
Repeat :
Gdp = NULL; i=0;
If (S_ISDIR (mode)) (for Contents
Avefreei = le32_to_cpu (es->s_free_inodes_count) /
Sb->u.ext2_sb.s_groups_count; group seeking the freedom inode number of each block
LEAVES OF 13 SPECIES OF LAURACEAE I am not yet convinced that this next bit is necessary.
I = block where the group dir->u.ext2_i.i_block_group; take Contents
For (j = 0, j "sb->u.ext2_sb.s_groups_count; j + +) (
Tmp = ext2_get_group_desc (sb, i, &bh2);
If (tmp, named
(Le16_to_cpu (tmp->bg_used_dirs_count) "" 8) "
Le16_to_cpu (tmp->bg_free_inodes_count)) (
Gdp = tmp;
Break;
}
Else
I =% sb->u.ext2_sb.s_groups_count; ++i
}
*/
If (!gdp) (
For (j = 0, j "sb->u.ext2_sb.s_groups_count; j + +) (
Tmp = ext2_get_group_desc (sb, j, &bh2);
If (tmp, named
Le16_to_cpu (tmp->bg_free_inodes_count) &
Le16_to_cpu (tmp->bg_free_inodes_count) "= avefreei) (
If (!gdp | |
(Le16_to_cpu (tmp->bg_free_blocks_count) "
Le16_to_cpu (gdp->bg_free_blocks_count))) (
I = j;
Gdp = tmp; find inode free inode number is greater than the average number of pieces of that group and the largest free block
}
}
}
}
}
Else
{
/*
* Try to place the inode in its parent directory
*/
I = block where the group dir->u.ext2_i.i_block_group; take Contents
Tmp = ext2_get_group_desc (sb, i, &bh2);
If (tmp, named le16_to_cpu (tmp->bg_free_inodes_count))
Gdp = tmp;
Else
If the inode list -- where block groups have already been used up, doubled to step 2 blocks can be used to find the other group
/*
* Use a quadratic hash to find a group with a
* Free inode
*/
For (j = 1; j "sb->u.ext2_sb.s_groups_count; j <= 1) {
i += j;
if (i > = Sb->u.ext2_sb.s_groups_count)
I -= sb->u.ext2_sb.s_groups_count;
Tmp = ext2_get_group_desc (sb, i, &bh2);
If (tmp, named
Le16_to_cpu (tmp->bg_free_inodes_count)) (
Gdp = tmp;
Break;
}
}
}
If (!gdp) (
/*
* That failed : try linear search for a free inode
*/
Dir->u.ext2_i.i_block_group i + = 1;
For (j = 2; j "sb->u.ext2_sb.s_groups_count; j + +) (
If (++i "= sb->u.ext2_sb.s_groups_count)
I = 0
Tmp = ext2_get_group_desc (sb, i, &bh2);
If (tmp, named
Le16_to_cpu (tmp->bg_free_inodes_count)) (
Gdp = tmp;
Break;
}
}
}
}
Erroneamente = -ENOSPC;
If (!gdp)
Goto fail;
Erroneamente = -EIO;
Bitmap_nr = load_inode_bitmap (sb, i); The loading can block inode allocation bitmap Caowei
If (bitmap_nr "0)
Goto fail;
Bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
If ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data.
EXT2_INODES_PER_GROUP (sb))) <
EXT2_INODES_PER_GROUP(sb)) { 找到一未分配位
if (ext2_set_bit (j, bh-> B_data)) (
Ext2_error (sb, "ext2_new_inode"
"Bit already set for inode %d" j);
Goto repeat;
}
Mark_buffer_dirty (bh); Inode to be marked dirty bitmap distribution
If (sb->s_flags & MS_SYNCHRONOUS) (
Ll_rw_block (WRITE, 1, &bh);
Wait_on_buffer (bh);
}
) Else (
If (le16_to_cpu (gdp->bg_free_inodes_count)> 0) (
Ext2_error (sb, "ext2_new_inode"
"Free inodes count corrupted in group %d"
I);
Is it really ENOSPC? */ LEAVES OF 13 SPECIES OF LAURACEAE
Erroneamente = -ENOSPC;
If (sb->s_flags & MS_RDONLY)
Goto fail;
Gdp->bg_free_inodes_count = 0
Mark_buffer_dirty (bh2);
}
Goto repeat;
}
I * j EXT2_INODES_PER_GROUP 20 +6 = 26 and finally 26-8 (sb) + 1; calculating its inode
If (j "EXT2_FIRST_INO (sb) | | j" le32_to_cpu (es->s_inodes_count)) (
Ext2_error (sb, "ext2_new_inode"
"Reserved inode or inode" inodes count - "
"Block_group = %d, inode=%d", i, j);
Erroneamente = -EIO;
Goto fail;
}
Gdp->bg_free_inodes_count =
Cpu_to_le16 (le16_to_cpu (gdp->bg_free_inodes_count) - 1);
If (S_ISDIR (mode))
Gdp->bg_used_dirs_count =
Cpu_to_le16 (le16_to_cpu (gdp->bg_used_dirs_count) + 1);
Mark_buffer_dirty (bh2);
Es->s_free_inodes_count =
Cpu_to_le32 (le32_to_cpu (es->s_free_inodes_count) - 1);
Mark_buffer_dirty (sb->u.ext2_sb.s_sbh);
Sb->s_dirt = 1;
Inode->i_mode = mode;
Inode->i_uid = current->fsuid;
If (test_opt (sb, GRPID))
Inode->i_gid = dir->i_gid;
Else if (dir->i_mode & S_ISGID) (
Inode->i_gid = dir->i_gid;
If (S_ISDIR (mode))
S_ISGID; mode)
) Else
Inode->i_gid = current->fsgid;
Inode->i_ino = j;
Inode->i_blksize = IO PAGE_SIZE; LEAVES OF 13 SPECIES OF LAURACEAE This is the optimal size (for stat), not the fs block size */
Inode->i_blocks = 0
Inode->i_mtime inode->i_atime = = = CURRENT_TIME; inode->i_ctime
Inode->u.ext2_i.i_new_inode = 1;
Inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
If (S_ISLNK (mode))
Inode->u.ext2_i.i_flags &= ~ (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL);
Inode->u.ext2_i.i_faddr = 0
Inode->u.ext2_i.i_frag_no = 0
Inode->u.ext2_i.i_frag_size = 0
Inode->u.ext2_i.i_file_acl = 0
Inode->u.ext2_i.i_dir_acl = 0
Inode->u.ext2_i.i_dtime = 0
Inode->u.ext2_i.i_block_group = Rifa
If (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
Inode->i_flags) S_SYNC;
Insert_inode_hash (inode);
Serial = event++; inode->i_generation
Mark_inode_dirty (inode);
Unlock_super (sb);
If (DQUOT_ALLOC_INODE (sb, inode)) (
Sb->dq_op->drop (inode);
Inode->i_nlink = 0
Iput (inode);
Return ERR_PTR (-EDQUOT);
}
Ext2_debug ( "allocating inode %lu\n" inode->i_ino);
Return inode;
Fail :
Unlock_super (sb);
Iput (inode);
Return ERR_PTR (erroneamente);
}
|