2021SC@SDUSC

今天来分析ext4_extents.h 、 xattr.h 、 truncate.h 三个头文件,为以后分析inode.c核心文件打下基础。

以下是ext4_extents.h头文件的代码分析

// SPDX-License-Identifier: GPL-2.0
/** Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com* Written by Alex Tomas <alex@clusterfs.com>*/#ifndef _EXT4_EXTENTS
#define _EXT4_EXTENTS#include "ext4.h"/*随着aggressive ve_test的定义,索引/叶块的容量变得非常小,因此索引分裂、深度增长和其他硬变化发生得更频繁。这仅用于调试目的。*/
#define AGGRESSIVE_TEST_/*定义EXTENTS_STATS后,在截断路径中收集块和区段的数量。它们将在umount时间显示。*/
#define EXTENTS_STATS__/*如果定义了CHECK_BINSEARCH,那么二进制搜索的结果也将通过线性搜索进行检查。*/
#define CHECK_BINSEARCH__/*如果定义了EXT_STATS,则统计数据将被收集。这些数字将在umount时显示。*/
#define EXT_STATS_/** ext4_inode有i_block数组(总共60字节)。*前12字节存储ext4_extent_header;其余存储ext4_extent数组。对于非inode扩展块,ext4_extent_tail紧跟在数组之后。*//**这是磁盘上的extent tail结构。*所有其他区段结构都是12字节长。结果表明,对于大于512的2的所有幂,block_size % 12 >= 4,这覆盖了所有有效的ext4块大小。因此,这个尾部结构可以被塞到块的末端,而不需要重新平衡树。*/
struct ext4_extent_tail {__le32 et_checksum;    /* crc32c(uuid+inum+extent_block) */
};/*这是磁盘上的extent结构。它在树的底部使用。*/
struct ext4_extent {__le32  ee_block;   /* 首先逻辑块范围覆盖*/__le16    ee_len;     /* 范围所覆盖的块数*/__le16 ee_start_hi;    /* 高16位的物理块*/__le32 ee_start_lo;    /* 低32位物理块*/
};/*这是磁盘索引结构。除底部外,所有级别都使用。*/
struct ext4_extent_idx {__le32  ei_block;   /* 索引涵盖了来自“block”的逻辑块*/__le32   ei_leaf_lo; /*指针指向下一层的物理块。叶索引或下一个索引可能在那里*/__le16    ei_leaf_hi; /*高16位的物理块 */__u16  ei_unused;
};/*每个块(叶子和索引),即使是inode存储的也有头。*/
struct ext4_extent_header {__le16   eh_magic;   /* 可能会支持不同的格式*/__le16   eh_entries; /* 有效条目数量*/__le16   eh_max;     /* 入库容量*/__le16 eh_depth;   /*树有真正的底层块吗? */__le32   eh_generation;  /* 树的各代*/
};#define EXT4_EXT_MAGIC        cpu_to_le16(0xf30a)
#define EXT4_MAX_EXTENT_DEPTH 5#define EXT4_EXTENT_TAIL_OFFSET(hdr) \(sizeof(struct ext4_extent_header) + \(sizeof(struct ext4_extent) * le16_to_cpu((hdr)->eh_max)))static inline struct ext4_extent_tail *
find_ext4_extent_tail(struct ext4_extent_header *eh)
{return (struct ext4_extent_tail *)(((void *)eh) +EXT4_EXTENT_TAIL_OFFSET(eh));
}/*ext4_ext_path数组中包含路径。*创建/查找例程使用它来遍历/分割/等。* Truncate使用它来模拟递归遍历。*/
struct ext4_ext_path {ext4_fsblk_t          p_block;__u16               p_depth;__u16               p_maxdepth;struct ext4_extent       *p_ext;struct ext4_extent_idx       *p_idx;struct ext4_extent_header    *p_hdr;struct buffer_head       *p_bh;
};/**用于在空间移除期间遍历区段树时,记录在区段开始或结束时发现的簇的一部分。*如果一个部分集群中没有与未被删除的区段共享的块(处于空闲状态),可能会被移除。否则,它不能被删除(nofree状态)。*/
struct partial_cluster {ext4_fsblk_t pclu;  /* physical cluster number */ext4_lblk_t lblk;   /* logical block number within logical cluster */enum {initial, tofree, nofree} state;
};/**结构的外部API*//** EXT_INIT_MAX_LEN是在初始化的extent中可以拥有的最大块数。这是2^15而不是(2^16 - 1),因为我们在区段数据结构中使用ee_len字段的MSB来表示这个特定的区段是初始化的还是未写入的(即预分配的)。* EXT_UNWRITTEN_MAX_LEN是一个未写入区可以拥有的最大块数。如果ee_len <= 0x8000,则它是一个初始化的范围。否则,它是一个不成文的。换句话说,如果设置了ee_len的MSB,则它是一个未写入区,只有一个特殊场景:ee_len = 0x8000。在本例中,我们不能有长度为0的未写入范围,因此我们将其作为长度为0x8000的初始化范围的特殊情况。*通过这种方式,我们可以更好地对初始化的区段和组进行对齐。因此,在一个*初始化的*区段中我们可以拥有的最大块数是2^15(32768),而在一个*未写入的*区段中我们可以拥有的最大块数是2^15-1(32767)。*/
#define EXT_INIT_MAX_LEN    (1UL << 15)
#define EXT_UNWRITTEN_MAX_LEN   (EXT_INIT_MAX_LEN - 1)#define EXT_FIRST_EXTENT(__hdr__) \((struct ext4_extent *) (((char *) (__hdr__)) +       \sizeof(struct ext4_extent_header)))
#define EXT_FIRST_INDEX(__hdr__) \((struct ext4_extent_idx *) (((char *) (__hdr__)) +  \sizeof(struct ext4_extent_header)))
#define EXT_HAS_FREE_INDEX(__path__) \(le16_to_cpu((__path__)->p_hdr->eh_entries) \< le16_to_cpu((__path__)->p_hdr->eh_max))
#define EXT_LAST_EXTENT(__hdr__) \(EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
#define EXT_LAST_INDEX(__hdr__) \(EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
#define EXT_MAX_EXTENT(__hdr__) \((le16_to_cpu((__hdr__)->eh_max)) ? \((EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) \: 0)
#define EXT_MAX_INDEX(__hdr__) \((le16_to_cpu((__hdr__)->eh_max)) ? \((EXT_FIRST_INDEX((__hdr__)) + le16_to_cpu((__hdr__)->eh_max) - 1)) : 0)static inline struct ext4_extent_header *ext_inode_hdr(struct inode *inode)
{return (struct ext4_extent_header *) EXT4_I(inode)->i_data;
}static inline struct ext4_extent_header *ext_block_hdr(struct buffer_head *bh)
{return (struct ext4_extent_header *) bh->b_data;
}static inline unsigned short ext_depth(struct inode *inode)
{return le16_to_cpu(ext_inode_hdr(inode)->eh_depth);
}static inline void ext4_ext_mark_unwritten(struct ext4_extent *ext)
{/* We can not have an unwritten extent of zero length! */BUG_ON((le16_to_cpu(ext->ee_len) & ~EXT_INIT_MAX_LEN) == 0);ext->ee_len |= cpu_to_le16(EXT_INIT_MAX_LEN);
}static inline int ext4_ext_is_unwritten(struct ext4_extent *ext)
{/* Extent with ee_len of 0x8000 is treated as an initialized extent */return (le16_to_cpu(ext->ee_len) > EXT_INIT_MAX_LEN);
}static inline int ext4_ext_get_actual_len(struct ext4_extent *ext)
{return (le16_to_cpu(ext->ee_len) <= EXT_INIT_MAX_LEN ?le16_to_cpu(ext->ee_len) :(le16_to_cpu(ext->ee_len) - EXT_INIT_MAX_LEN));
}static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
{ext->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ext));
}/** ext4_ext_pblock:*将物理块号的高低部分合并成ext4_fsblk_t*/
static inline ext4_fsblk_t ext4_ext_pblock(struct ext4_extent *ex)
{ext4_fsblk_t block;block = le32_to_cpu(ex->ee_start_lo);block |= ((ext4_fsblk_t) le16_to_cpu(ex->ee_start_hi) << 31) << 1;return block;
}/** ext4_idx_pblock:将叶子物理块号的高低部分合并到ext4_fsblk_t中*/
static inline ext4_fsblk_t ext4_idx_pblock(struct ext4_extent_idx *ix)
{ext4_fsblk_t block;block = le32_to_cpu(ix->ei_leaf_lo);block |= ((ext4_fsblk_t) le16_to_cpu(ix->ei_leaf_hi) << 31) << 1;return block;
}/** ext4_ext_store_pblock:*将一个大的物理块数存储到一个区段结构中,并将其分解为多个部分*/
static inline void ext4_ext_store_pblock(struct ext4_extent *ex,ext4_fsblk_t pb)
{ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) &0xffff);
}/* ext4_idx_store_pblock:*将一个大的物理块数存储到一个索引结构中,并将其分解为多个部分*/
static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,ext4_fsblk_t pb)
{ix->ei_leaf_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));ix->ei_leaf_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) &0xffff);
}#endif /* _EXT4_EXTENTS */

以下是xattr.h头文件的代码分析

// SPDX-License-Identifier: GPL-2.0
/*File: fs/ext4/xattr.hOn-disk format of extended attributes for the ext4 filesystem.(C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/#include <linux/xattr.h>/* 属性块中的魔法值 */
#define EXT4_XATTR_MAGIC        0xEA020000/* 对一个属性块的最大引用数 */
#define EXT4_XATTR_REFCOUNT_MAX     1024/* 名称索引*/
#define EXT4_XATTR_INDEX_USER           1
#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS   2
#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT  3
#define EXT4_XATTR_INDEX_TRUSTED        4
#define EXT4_XATTR_INDEX_LUSTRE         5
#define EXT4_XATTR_INDEX_SECURITY           6
#define EXT4_XATTR_INDEX_SYSTEM         7
#define EXT4_XATTR_INDEX_RICHACL        8
#define EXT4_XATTR_INDEX_ENCRYPTION     9
#define EXT4_XATTR_INDEX_HURD           10 /* 预留给HURD */struct ext4_xattr_header {__le32    h_magic;    /* 用于标识的魔数 */__le32 h_refcount; /* 引用计数 */__le32    h_blocks;   /* 已使用的磁盘块数 */__le32    h_hash;     /* 所有属性的哈希值 */__le32    h_checksum; /* crc32c(uuid+id+xattrblock) *//* 如果refcount=1, Id = inum,否则为blknum */__u32 h_reserved[3];
};struct ext4_xattr_ibody_header {__le32    h_magic;    /* 用于标识的魔数 */
};struct ext4_xattr_entry {__u8 e_name_len; /* 名字的长度 */__u8 e_name_index;   /* 属性名称索引 */__le16  e_value_offs;   /* 磁盘块中的偏移值 */__le32    e_value_inum;   /* 存储值的索引节点 */__le32    e_value_size;   /* 属性值大小 */__le32   e_hash;     /* name和value的散列值 */char    e_name[];   /* 属性名称 */
};#define EXT4_XATTR_PAD_BITS       2
#define EXT4_XATTR_PAD      (1<<EXT4_XATTR_PAD_BITS)
#define EXT4_XATTR_ROUND        (EXT4_XATTR_PAD-1)
#define EXT4_XATTR_LEN(name_len) \(((name_len) + EXT4_XATTR_ROUND + \sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND)
#define EXT4_XATTR_NEXT(entry) \((struct ext4_xattr_entry *)( \(char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len)))
#define EXT4_XATTR_SIZE(size) \(((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND)#define IHDR(inode, raw_inode) \((struct ext4_xattr_ibody_header *) \((void *)raw_inode + \EXT4_GOOD_OLD_INODE_SIZE + \EXT4_I(inode)->i_extra_isize))
#define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))/*
XATTR_SIZE_MAX目前是64k,但是为了检查文件系统一致性错误,我们使用了一个更大的值。
这允许XATTR_SIZE_MAX在未来增长,但是在某些一致性检查中使用它而不是INT_MAX,我们不需要担心算术溢出。
(实际上XATTR_SIZE_MAX是在include/uapi/linux/limits.h中定义的,所以改变它不会是简单的....)*/
#define EXT4_XATTR_SIZE_MAX (1 << 24)/*
当您开始将EA值存储在外部索引节点时,
它的最小大小为块大小-头大小- 1个条目大小- 4个空字节
*/
#define EXT4_XATTR_MIN_LARGE_EA_SIZE(b)                 \((b) - EXT4_XATTR_LEN(3) - sizeof(struct ext4_xattr_header) - 4)#define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data))
#define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr))
#define BFIRST(bh) ENTRY(BHDR(bh)+1)
#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)#define EXT4_ZERO_XATTR_VALUE ((void *)-1)struct ext4_xattr_info {const char *name;const void *value;size_t value_len;int name_index;int in_inode;
};struct ext4_xattr_search {struct ext4_xattr_entry *first;void *base;void *end;struct ext4_xattr_entry *here;int not_found;
};struct ext4_xattr_ibody_find {struct ext4_xattr_search s;struct ext4_iloc iloc;
};struct ext4_xattr_inode_array {unsigned int count;        /* 数组中使用的条目的# */struct inode *inodes[];
};extern const struct xattr_handler ext4_xattr_user_handler;
extern const struct xattr_handler ext4_xattr_trusted_handler;
extern const struct xattr_handler ext4_xattr_security_handler;
extern const struct xattr_handler ext4_xattr_hurd_handler;#define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c"/*
EXT4_STATE_NO_EXPAND是重载的,用于两个目的。
第一个是发出信号,表示内联xattrs和数据占用了太多的空间,所以我们最好不要一直尝试扩展它。
其次,xattr_sem用于写入,因此不应该尝试递归到inode展开中。
对于第二种情况,我们需要确保适当地使用保存和恢复NO_EXPAND状态标志。*/
static inline void ext4_write_lock_xattr(struct inode *inode, int *save)
{down_write(&EXT4_I(inode)->xattr_sem);*save = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
}static inline int ext4_write_trylock_xattr(struct inode *inode, int *save)
{if (down_write_trylock(&EXT4_I(inode)->xattr_sem) == 0)return 0;*save = ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND);ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);return 1;
}static inline void ext4_write_unlock_xattr(struct inode *inode, int *save)
{if (*save == 0)ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);up_write(&EXT4_I(inode)->xattr_sem);
}extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);
extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
extern int ext4_xattr_set_credits(struct inode *inode, size_t value_len,bool is_create, int *credits);
extern int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode,struct buffer_head *block_bh, size_t value_len,bool is_create);extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,struct ext4_xattr_inode_array **array,int extra_credits);
extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array);extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,struct ext4_inode *raw_inode, handle_t *handle);extern const struct xattr_handler *ext4_xattr_handlers[];extern int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,struct ext4_xattr_ibody_find *is);
extern int ext4_xattr_ibody_get(struct inode *inode, int name_index,const char *name,void *buffer, size_t buffer_size);
extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,struct ext4_xattr_info *i,struct ext4_xattr_ibody_find *is);extern struct mb_cache *ext4_xattr_create_cache(void);
extern void ext4_xattr_destroy_cache(struct mb_cache *);#ifdef CONFIG_EXT4_FS_SECURITY
extern int ext4_init_security(handle_t *handle, struct inode *inode,struct inode *dir, const struct qstr *qstr);
#else
static inline int ext4_init_security(handle_t *handle, struct inode *inode,struct inode *dir, const struct qstr *qstr)
{return 0;
}
#endif#ifdef CONFIG_LOCKDEP
extern void ext4_xattr_inode_set_class(struct inode *ea_inode);
#else
static inline void ext4_xattr_inode_set_class(struct inode *ea_inode) { }
#endifextern int ext4_get_inode_usage(struct inode *inode, qsize_t *usage);

以下是truncate.h头文件的代码分析:

// SPDX-License-Identifier: GPL-2.0
/** linux/fs/ext4/truncate.h** Common inline functions needed for truncate support*//*
截断未被写入使用的块。
我们还必须截断页面缓存,以便正确地取消相应的缓冲区映射。*/
static inline void ext4_truncate_failed_write(struct inode *inode)
{/*我们不需要调用ext4_break_layouts(),因为我们正在截断的块对用户空间是不可见的。*/down_write(&EXT4_I(inode)->i_mmap_sem);truncate_inode_pages(inode->i_mapping, inode->i_size);ext4_truncate(inode);up_write(&EXT4_I(inode)->i_mmap_sem);
}/*
计算出我们需要多少块来处理截断事务的下一个块。*/
static inline unsigned long ext4_blocks_for_truncate(struct inode *inode)
{ext4_lblk_t needed;needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);/* 给我们足够的空间来处理i_blocks损坏的inode:我们在过去看到过磁盘损坏导致inode中出现随机数据,这些数据看起来很像ext4试图删除的常规文件。如果发生这种情况,事情会变得有点疯狂,但至少我们应该尽量不要让整个内核感到恐慌。*/if (needed < 2)needed = 2;/* 我们需要对事务进行约束,以避免日记账溢出。*/if (needed > EXT4_MAX_TRANS_DATA)needed = EXT4_MAX_TRANS_DATA;return EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + needed;

Linux内核文件系统7相关推荐

  1. DM365 linux内核文件系统的烧写步骤及其uboot参数配置

    DM365 linux内核&文件系统的烧写步骤及其uboot参数配置     目录 源文档下载:http://download.csdn.net/detail/zhangjikuan/6443 ...

  2. Linux内核文件系统10

    2021SC@SDUSC inode.c(1) 今天来分析inode.c文件.有了前面对ext4_jbd2.h.acl.h等头文件的分析做基础,今天的分析将相对简单. 在看代码之前,首先要说一下ino ...

  3. 【技术分享篇】Linux内核——手把手带你实现一个Linux内核文件系统丨Linux内核源码分析

    手把手带你实现一个Linux内核文件系统 1. 内核文件系统架构分析 2. 行行珠玑,代码实现 [技术分享篇]Linux内核--手把手带你实现一个Linux内核文件系统丨Linux内核源码分析 更多L ...

  4. Linux内核文件系统

    Linux 内核文件系统 概述 文件系统这一词在不同上下文时有不同的含义: 指一种具体的文件格式.例如Linux的文件系统是Ext2,MSDOS的文件系统是FAT16,而Windows NT的文件系统 ...

  5. 索引节点inode: Linux内核文件系统之(inode)

    inode译成中文就是索引节点,它用来存放档案及目录的基本信息,包含时间.档名.使用者及群组等. static int eachreg_open(struct inode *inode, struct ...

  6. linux内核文件系统的架构,《深入理解Linux内核》-文件系统学习心得

    内核中要注意的是各种结构体,结构体之间的联系和各个函数以及函数之间的调用关系,参数的传递和函数的功能. 内核中数据结构的字段无外乎包括三种字段:属性字段,调用方法,指向其它结构的指针.具体如下图所示: ...

  7. Linux内核文件系统5

    2021SC@SDUSC 今天来分析ext4.h文件 #ifndef _EXT4_H #define _EXT4_H#include <linux/types.h> #include &l ...

  8. Linux 内核文件系统模块结构体关系图

    导言 很久没有更新csdn博客了,工作两年,学习了不少新东西,很多都没有来的及整理,用过不久很快就忘记了,写到博客中做个记录. 关系图 下图为去年学习文件系统时所画,有参考网上其他博主的资料,也有自己 ...

  9. Linux内核文件系统12

    2021SC@SDUSC inode.c(3) /** 强制为给定的 inode 分配所有延迟分配块.*/ int ext4_alloc_da_blocks(struct inode *inode) ...

  10. Linux内核文件系统8

    2021SC@SDUSC 今天来分析ext4_jbd2.h 和 ext4_jbd2.c文件. 以下是ext4_jbd2.h头文件的代码分析 // SPDX-License-Identifier: GP ...

最新文章

  1. HALCON单目标定
  2. 算法提高课-搜索-最短路模型-AcWing 1076. 迷宫问题:bfs最短路、路径
  3. spring security CSRF 问题 Invalid CSRF Token 'null' was found on ......
  4. Python中使用wordcloud生成漂亮的中文词云
  5. 计算机视觉与深度学习 | 视觉里程计库Libviso2详解
  6. tf 矩阵行和列交换_TF-搞不懂的TF矩阵加法
  7. Linux下 安装Redis并配置服务
  8. 随笔-机器如何学习我们的知识?
  9. java与平台无关的原因
  10. mysql 主从一致性_mysql 主从一致性保证
  11. stc89c51单片机音乐盒系统设计_基于单片机的火控系统语音报读设计
  12. ai怎么渐变颜色_你根本想不到AI的混合工具有多神奇!
  13. 【Python游戏】Python实现一个简易版本的阴阳师游戏 | 附带源码
  14. plsql oracle 使用教程
  15. 医院病历html模板,三甲医院电子病历模板参考
  16. 学习总结-在Icepak模型中修改和增加零件
  17. [算法]代码运行时间增长数量级对比 线性级别N vs 线性对数级别 NlgN
  18. 检索有项目的教师信息mysql_学生成绩管理系统(六):项目总结
  19. Linux 下 美化字体
  20. GBin1专题之Web热点秀#12

热门文章

  1. linux常用cat,Linux常用操作命令之cat
  2. 计算机应届博士生的一点求职经验——概述篇
  3. 如何使用 JavaScript 和 Canvas 创建星形图案
  4. 使用python来搭建一个简易的文件下载环境以及用droopy来实现一个文件上传环境
  5. Python实现程序运行时间度量分析
  6. 数据库使用SHADOW系统实现高可用性
  7. 【文学】平凡的世界第三部
  8. 个人必备google搜索技巧
  9. 【用友CTO】解读企业数字化中台
  10. win11家庭版 安卓虚拟机