2021SC@SDUSC

今天来分析ext4.h文件

#ifndef _EXT4_H
#define _EXT4_H#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/magic.h>
#include <linux/jbd2.h>
#include <linux/quota.h>
#include <linux/rwsem.h>
#include <linux/rbtree.h>
#include <linux/seqlock.h>
#include <linux/mutex.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/sched/signal.h>
#include <linux/blockgroup_lock.h>
#include <linux/percpu_counter.h>
#include <linux/ratelimit.h>
#include <crypto/hash.h>
#include <linux/falloc.h>
#include <linux/percpu-rwsem.h>
#include <linux/fiemap.h>
#ifdef __KERNEL__
#include <linux/compat.h>
#endif#include <linux/fscrypt.h>
#include <linux/fsverity.h>#include <linux/compiler.h>/* 第四代扩展文件系统常量/结构*/
/*使用aggressive . check分配器对结构运行一致性检查。但这些检查会让系统运行慢很多*/
#define AGGRESSIVE_CHECK__/*使用DOUBLE_CHECK定义的mballoc创建持久的内核位图,维护和使用它们检查双分配*/
#define DOUBLE_CHECK__/*定义EXT4FS_DEBUG来生成调试消息*/
#undef EXT4FS_DEBUG/*调试代码 */
#ifdef EXT4FS_DEBUG
#define ext4_debug(f, a...)/*为假时输出调试结果信息 */do {                             printk(KERN_DEBUG "EXT4-fs DEBUG (%s, %d): %s:",  __FILE__, __LINE__, __func__);          printk(KERN_DEBUG f, ## a);             } while (0)
#else
#define ext4_debug(fmt, ...)    no_printk(fmt, ##__VA_ARGS__)
#endif/*打开EXT_DEBUG将在ext4_ext_show_path/leaf/move中启用ext4_ext_show_path*/
#define EXT_DEBUG__/*用于受控区调试的动态printk。*/
#ifdef CONFIG_EXT4_DEBUG
#define ext_debug(ino, fmt, ...)                    \pr_debug("[%s/%d] EXT4-fs (%s): ino %lu: (%s, %d): %s:" fmt, \current->comm, task_pid_nr(current),            \ino->i_sb->s_id, ino->i_ino, __FILE__, __LINE__,  \__func__, ##__VA_ARGS__)
#else
#define ext_debug(ino, fmt, ...)    no_printk(fmt, ##__VA_ARGS__)
#endif#define ASSERT(assert)                        \
do {
/*判断参数是否一致*/                            \if (unlikely(!(assert))) {                 \printk(KERN_EMERG                  \"Assertion failure in %s() at %s:%d: '%s'\n",  \__func__, __FILE__, __LINE__, #assert);        \BUG();                         \}                              \
} while (0)/*块组的块偏移的数据类型*/
typedef int ext4_grpblk_t;/*文件系统范围的块编号的数据类型 */
typedef unsigned long long ext4_fsblk_t;/*文件逻辑块号的数据类型*/
typedef __u32 ext4_lblk_t;/*块组号的数据类型*/
typedef unsigned int ext4_group_t;/*枚举转换方向*/
enum SHIFT_DIRECTION {SHIFT_LEFT = 0,SHIFT_RIGHT,
};/*在mballoc的allocation_context Flags字段中使用的标志。
也用于显示 通过traceport接口输出标志字段时的调试目标 *//*prefer goal again. length*/
#define EXT4_MB_HINT_MERGE      0x0001
/*预留块*/
#define EXT4_MB_HINT_RESERVED       0x0002
/*正在分配的元数据*/
#define EXT4_MB_HINT_METADATA       0x0004
/*文件中的第一个块*/
#define EXT4_MB_HINT_FIRST      0x0008
/*搜索最好的块*/
#define EXT4_MB_HINT_BEST       0x0010
/*正在分配的数据 */
#define EXT4_MB_HINT_DATA       0x0020
/*不要预分配(对于尾部)*/
#define EXT4_MB_HINT_NOPREALLOC     0x0040
/*为区域组分配*/
#define EXT4_MB_HINT_GROUP_ALLOC    0x0080
/*分配目标块或不分配目标块*/
#define EXT4_MB_HINT_GOAL_ONLY      0x0100
/*目标是有意义的*/
#define EXT4_MB_HINT_TRY_GOAL       0x0200
/*已被延迟分配提前预留的块 */
#define EXT4_MB_DELALLOC_RESERVED   0x0400
/*流分配*/
#define EXT4_MB_STREAM_ALLOC        0x0800
/*如果需要,使用保留的根块*/
#define EXT4_MB_USE_ROOT_BLOCKS     0x1000
/*使用保留池中的块*/
#define EXT4_MB_USE_RESERVED        0x2000
/*在重试块分配时是否严格检查空闲块 */
#define EXT4_MB_STRICT_CHECK        0x4000
/*对于cr = 0的大片段列表查找至少成功一次*/
#define EXT4_MB_CR0_OPTIMIZED       0x8000
/*对于cr = 1,平均片段大小的rb树查找至少成功一次*/
#define EXT4_MB_CR1_OPTIMIZED       0x00010000
/*对一个组执行线性遍历*/
#define EXT4_MB_SEARCH_NEXT_LINEAR  0x00020000
struct ext4_allocation_request {/*我们要分配的块的目标索引节点*/struct inode *inode;/*我们要分配多少块*/unsigned int len;/*目标节点中的逻辑块 */ext4_lblk_t logical;/*最接近左边的逻辑分配块*/ext4_lblk_t lleft;/*最接近右边的逻辑分配块*/ext4_lblk_t lright;/*物理目标块(提示)*/ext4_fsblk_t goal;/*用于左边最近的逻辑分配块的物理块*/ext4_fsblk_t pleft;/*用于右边最近的逻辑分配块的物理块*/ext4_fsblk_t pright;/*以上描述EXT4_MB_HINT_ *标志*/unsigned int flags;
};/ *
逻辑到物理块的映射,由ext4_map_blocks()使用。
该结构用于将请求传递给ext4_map_blocks(),以及存储ext4_map_blocks()返回的信息。它在堆栈上所占的空间小于结构体buffer_head。*/
#define EXT4_MAP_NEW        BIT(BH_New)
#define EXT4_MAP_MAPPED     BIT(BH_Mapped)
#define EXT4_MAP_UNWRITTEN  BIT(BH_Unwritten)
#define EXT4_MAP_BOUNDARY   BIT(BH_Boundary)
#define EXT4_MAP_FLAGS      (EXT4_MAP_NEW | EXT4_MAP_MAPPED |\EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY)struct ext4_map_blocks {ext4_fsblk_t m_pblk;ext4_lblk_t m_lblk;unsigned int m_len;unsigned int m_flags;
};/*系统区域rbtree范围内块的有效性检查。 */
struct ext4_system_blocks {struct rb_root root;struct rcu_head rcu;
};/*ext4文件系统的IO结尾的标志*/
#define EXT4_IO_END_UNWRITTEN   0x0001struct ext4_io_end_vec {struct list_head list;        /*io_end_vec列表*/loff_t offset;          /*文件中的偏移量*/ssize_t size;            /*范围大小*/
};/*用于转换工作队列上的未写区。'handle'用于缓冲回写。*/
typedef struct ext4_io_end {struct list_head    list;           /*每个文件完成的IO列表*/handle_t     *handle;        /*为区段转换保留句柄*/struct inode   *inode;     /*正在写入的文件*/struct bio       *bio;           /*覆盖范围内的完整的bios链表*/unsigned int  flag;      /* unwritten or not */atomic_t      count;      /*引用计数器*/struct list_head   list_vec;       /* ext4_io_end_vec 列表*/
} ext4_io_end_t;struct ext4_io_submit {struct writeback_control *io_wbc;struct bio      *io_bio;ext4_io_end_t       *io_end;sector_t        io_next_block;
};/*特殊的inode编号*/
#define EXT4_BAD_INO             1  /*坏块索引节点*/
#define EXT4_ROOT_INO            2  /*根索引节点 */
#define EXT4_USR_QUOTA_INO   3  /*用户配额索引节点 */
#define EXT4_GRP_QUOTA_INO   4  /* 组配额索引节点*/
#define EXT4_BOOT_LOADER_INO     5  /*引导加载程序索引节点*/
#define EXT4_UNDEL_DIR_INO       6  /*恢复删除的目录索引节点*/
#define EXT4_RESIZE_INO      7  /*保留组描述符索引节点*/
#define EXT4_JOURNAL_INO         8  /*日志索引节点*//*第一个用于旧ext4文件系统的非保留inode*/
#define EXT4_GOOD_OLD_FIRST_INO 11/*文件的最大链接数*/
#define EXT4_LINK_MAX       65000/*用于管理多个块大小的宏指令*/
#define EXT4_MIN_BLOCK_SIZE     1024
#define EXT4_MAX_BLOCK_SIZE     65536
#define EXT4_MIN_BLOCK_LOG_SIZE     10
#define EXT4_MAX_BLOCK_LOG_SIZE     16
#define EXT4_MAX_CLUSTER_LOG_SIZE   30
#ifdef __KERNEL__
# define EXT4_BLOCK_SIZE(s)     ((s)->s_blocksize)
#else
# define EXT4_BLOCK_SIZE(s)     (EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
#endif
#define EXT4_ADDR_PER_BLOCK(s)      (EXT4_BLOCK_SIZE(s) / sizeof(__u32))
#define EXT4_CLUSTER_SIZE(s)        (EXT4_BLOCK_SIZE(s) << \EXT4_SB(s)->s_cluster_bits)
#ifdef __KERNEL__
# define EXT4_BLOCK_SIZE_BITS(s)    ((s)->s_blocksize_bits)
# define EXT4_CLUSTER_BITS(s)       (EXT4_SB(s)->s_cluster_bits)
#else
# define EXT4_BLOCK_SIZE_BITS(s)    ((s)->s_log_block_size + 10)
#endif
#ifdef __KERNEL__
#define EXT4_ADDR_PER_BLOCK_BITS(s) (EXT4_SB(s)->s_addr_per_block_bits)
#define EXT4_INODE_SIZE(s)      (EXT4_SB(s)->s_inode_size)
#define EXT4_FIRST_INO(s)       (EXT4_SB(s)->s_first_ino)
#else
#define EXT4_INODE_SIZE(s)  (((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \EXT4_GOOD_OLD_INODE_SIZE : \(s)->s_inode_size)
#define EXT4_FIRST_INO(s)   (((s)->s_rev_level == EXT4_GOOD_OLD_REV) ? \EXT4_GOOD_OLD_FIRST_INO : \(s)->s_first_ino)
#endif
#define EXT4_BLOCK_ALIGN(size, blkbits)     ALIGN((size), (1 << (blkbits)))
#define EXT4_MAX_BLOCKS(size, offset, blkbits) \((EXT4_BLOCK_ALIGN(size + offset, blkbits) >> blkbits) - (offset >> \blkbits))/*block to cluster将块号转换为集群号*/
#define EXT4_B2C(sbi, blk)  ((blk) >> (sbi)->s_cluster_bits)
/* C2B的逆转将集群号转换为块号 */
#define EXT4_C2B(sbi, cluster)  ((cluster) << (sbi)->s_cluster_bits)
/*将blks的#转换为集群的# */
#define EXT4_NUM_B2C(sbi, blks) (((blks) + (sbi)->s_cluster_ratio - 1) >> \(sbi)->s_cluster_bits)
/*屏蔽低位以获得集群的起始块 */
#define EXT4_PBLK_CMASK(s, pblk) ((pblk) &              \~((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
#define EXT4_LBLK_CMASK(s, lblk) ((lblk) &              \~((ext4_lblk_t) (s)->s_cluster_ratio - 1))
/*填充低位以获得集群的最后一个块*/
#define EXT4_LBLK_CFILL(sbi, lblk) ((lblk) |                \((ext4_lblk_t) (sbi)->s_cluster_ratio - 1))
/*获取集群的偏移量*/
#define EXT4_PBLK_COFF(s, pblk) ((pblk) &               \((ext4_fsblk_t) (s)->s_cluster_ratio - 1))
#define EXT4_LBLK_COFF(s, lblk) ((lblk) &               \((ext4_lblk_t) (s)->s_cluster_ratio - 1))/*块组描述符的结构*/
struct ext4_group_desc
{__le32 bg_block_bitmap_lo; /*存放块位图的块*/__le32   bg_inode_bitmap_lo; /*存放inode位图的块 */__le32  bg_inode_table_lo;      /*存放inode表的块*/__le16    bg_free_blocks_count_lo;/*空闲块的数量*/__le16    bg_free_inodes_count_lo;/* 空闲节点的数量*/__le16  bg_used_dirs_count_lo;  /*目录的数量*/__le16 bg_flags;               /*EXT4_BG_flags (INODE_UNINIT等)*/__le32  bg_exclude_bitmap_lo;   /*排除快照的位图*/__le16  bg_block_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+bbitmap) LE crc32位循环冗余校验块位图*/__le16  bg_inode_bitmap_csum_lo;/* crc32c(s_uuid+grp_num+ibitmap) LE 循环冗余校验节点位图校验和;LE指"little-endian 小位先写" LE 的书写方式是先写最不足道位 LSD*/__le16  bg_itable_unused_lo;        /*未使用的节点数*/__le16  bg_checksum;         /* crc16(sb_uuid+group+desc) 16位位循环冗余校验块组校验和*/__le32  bg_block_bitmap_hi; /*块位图块MSB */__le32  bg_inode_bitmap_hi; /*索引节点位图块MSB*/__le32    bg_inode_table_hi;      /*索引节点表块MSB */__le16    bg_free_blocks_count_hi;/*空闲块计数MSB */__le16 bg_free_inodes_count_hi;/*空闲节点计数MSB*/__le16 bg_used_dirs_count_hi;  /*目录数最高有效位*/__le16  bg_itable_unused_hi;    /*未使用的节点计数MSB*/__le32  bg_exclude_bitmap_hi;   /* Exclude bitmap block MSB */__le16  bg_block_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+bbitmap) BE与上面的校验类似,但BE指 big-endian,BE 的书写方式是先写最大道位 MSD*/__le16  bg_inode_bitmap_csum_hi;/* crc32c(s_uuid+grp_num+ibitmap) BE */__u32   bg_reserved;
};#define EXT4_BG_INODE_BITMAP_CSUM_HI_END  \(offsetof(struct ext4_group_desc, bg_inode_bitmap_csum_hi) + \sizeof(__le16))
#define EXT4_BG_BLOCK_BITMAP_CSUM_HI_END    \(offsetof(struct ext4_group_desc, bg_block_bitmap_csum_hi) + \sizeof(__le16))/*可伸缩块组信息的结构*/struct flex_groups {atomic64_t free_clusters;atomic_t  free_inodes;atomic_t    used_dirs;
};#define EXT4_BG_INODE_UNINIT  0x0001 /*未使用Inode表/位图 */
#define EXT4_BG_BLOCK_UNINIT    0x0002 /*未使用的块位图 */
#define EXT4_BG_INODE_ZEROED    0x0004 /*磁盘上的可初始化为0的inode表*//*用于管理组描述符的宏指令*/
#define EXT4_MIN_DESC_SIZE      32
#define EXT4_MIN_DESC_SIZE_64BIT    64
#define EXT4_MAX_DESC_SIZE      EXT4_MIN_BLOCK_SIZE
#define EXT4_DESC_SIZE(s)       (EXT4_SB(s)->s_desc_size)
#ifdef __KERNEL__
# define EXT4_BLOCKS_PER_GROUP(s)   (EXT4_SB(s)->s_blocks_per_group)
# define EXT4_CLUSTERS_PER_GROUP(s) (EXT4_SB(s)->s_clusters_per_group)
# define EXT4_DESC_PER_BLOCK(s)     (EXT4_SB(s)->s_desc_per_block)
# define EXT4_INODES_PER_GROUP(s)   (EXT4_SB(s)->s_inodes_per_group)
# define EXT4_DESC_PER_BLOCK_BITS(s)    (EXT4_SB(s)->s_desc_per_block_bits)
#else
# define EXT4_BLOCKS_PER_GROUP(s)   ((s)->s_blocks_per_group)
# define EXT4_DESC_PER_BLOCK(s)     (EXT4_BLOCK_SIZE(s) / EXT4_DESC_SIZE(s))
# define EXT4_INODES_PER_GROUP(s)   ((s)->s_inodes_per_group)
#endif/*相对于数据块的常量*/
#define EXT4_NDIR_BLOCKS        12
#define EXT4_IND_BLOCK          EXT4_NDIR_BLOCKS
#define EXT4_DIND_BLOCK         (EXT4_IND_BLOCK + 1)
#define EXT4_TIND_BLOCK         (EXT4_DIND_BLOCK + 1)
#define EXT4_N_BLOCKS           (EXT4_TIND_BLOCK + 1)/*inode标志*/
#define EXT4_SECRM_FL           0x00000001 /*安全的删除*/
#define EXT4_UNRM_FL            0x00000002 /*恢复删除*/
#define EXT4_COMPR_FL           0x00000004 /*压缩文件 */
#define EXT4_SYNC_FL            0x00000008 /*同步更新*/
#define EXT4_IMMUTABLE_FL       0x00000010 /*不可改变的文件 */
#define EXT4_APPEND_FL          0x00000020 /*对文件的写入只能追加*/
#define EXT4_NODUMP_FL          0x00000040 /*不要转储文件*/
#define EXT4_NOATIME_FL         0x00000080 /* 不更新atime*/
/* 为压缩使用保留…*/
#define EXT4_DIRTY_FL           0x00000100
#define EXT4_COMPRBLK_FL        0x00000200 /*一个或多个压缩集群 */
#define EXT4_NOCOMPR_FL         0x00000400 /* 不压缩*//*nb:以前是EXT2_ECOMPR_FL*/
#define EXT4_ENCRYPT_FL         0x00000800 /*加密文件*/
/*结束压缩标志——可能没有全部使用 */
#define EXT4_INDEX_FL           0x00001000 /*hash-indexed目录*/
#define EXT4_IMAGIC_FL          0x00002000 /* AFS目录 */
#define EXT4_JOURNAL_DATA_FL        0x00004000 /* 应该记录文件数据*/
#define EXT4_NOTAIL_FL          0x00008000 /*文件尾部不应该合并*/
#define EXT4_DIRSYNC_FL         0x00010000 /*Dirsync行为(仅限目录)*/
#define EXT4_TOPDIR_FL          0x00020000 /*目录层次结构的顶部*/
#define EXT4_HUGE_FILE_FL               0x00040000 /*设置为每个大文件*/
#define EXT4_EXTENTS_FL         0x00080000 /*Inode区段使用*/
#define EXT4_VERITY_FL          0x00100000 /*真实性保护inode*/
#define EXT4_EA_INODE_FL            0x00200000 /*用于大型EA的Inode*/
/* 0x00400000 以前是EXT4_EOFBLOCKS_FL */#define EXT4_DAX_FL            0x02000000 /*Inode是DAX指数*/#define EXT4_INLINE_DATA_FL       0x10000000 /*Inode具有内联数据。*/
#define EXT4_PROJINHERIT_FL     0x20000000 /*用父项目id创建*/
#define EXT4_CASEFOLD_FL        0x40000000 /*Casefolded目录*/
#define EXT4_RESERVED_FL        0x80000000 /*为ext4 lib保留*//*用户可以修改的标志*/
#define EXT4_FL_USER_MODIFIABLE     (EXT4_SECRM_FL | \EXT4_UNRM_FL | \EXT4_COMPR_FL | \EXT4_SYNC_FL | \EXT4_IMMUTABLE_FL | \EXT4_APPEND_FL | \EXT4_NODUMP_FL | \EXT4_NOATIME_FL | \EXT4_JOURNAL_DATA_FL | \EXT4_NOTAIL_FL | \EXT4_DIRSYNC_FL | \EXT4_TOPDIR_FL | \EXT4_EXTENTS_FL | \0x00400000 /* EXT4_EOFBLOCKS_FL */ | \EXT4_DAX_FL | \EXT4_PROJINHERIT_FL | \EXT4_CASEFOLD_FL)/*用户可见的标志*/
#define EXT4_FL_USER_VISIBLE        (EXT4_FL_USER_MODIFIABLE | \EXT4_DIRTY_FL | \EXT4_COMPRBLK_FL | \EXT4_NOCOMPR_FL | \EXT4_ENCRYPT_FL | \EXT4_INDEX_FL | \EXT4_VERITY_FL | \EXT4_INLINE_DATA_FL)/*新索引节点应该从其父节点继承的标志。*/
#define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\EXT4_SYNC_FL | EXT4_NODUMP_FL | EXT4_NOATIME_FL |\EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL |\EXT4_PROJINHERIT_FL | EXT4_CASEFOLD_FL |\EXT4_DAX_FL)/*适用于常规文件的标志(除了特定于dir的文件外)。*/
#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL | EXT4_CASEFOLD_FL |\EXT4_PROJINHERIT_FL))/*适用于非目录/常规文件的标志。*/
#define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL)/*应该交换的唯一标志 */
#define EXT4_FL_SHOULD_SWAP (EXT4_HUGE_FILE_FL | EXT4_EXTENTS_FL)/*与DAX互斥的标志*/
#define EXT4_DAX_MUT_EXCL (EXT4_VERITY_FL | EXT4_ENCRYPT_FL |\EXT4_JOURNAL_DATA_FL | EXT4_INLINE_DATA_FL)/*屏蔽不适合给定类型的inode的标志。*/
static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
{if (S_ISDIR(mode))return flags;else if (S_ISREG(mode))return flags & EXT4_REG_FLMASK;elsereturn flags & EXT4_OTHER_FLMASK;
}/*用于原子set/get的Inode标志*/
enum {EXT4_INODE_SECRM  = 0,   /* Secure deletion */EXT4_INODE_UNRM        = 1,   /* Undelete */EXT4_INODE_COMPR  = 2,   /* Compress file */EXT4_INODE_SYNC      = 3,   /* Synchronous updates */EXT4_INODE_IMMUTABLE   = 4,   /* Immutable file */EXT4_INODE_APPEND   = 5,   /* writes to file may only append */EXT4_INODE_NODUMP   = 6,   /* do not dump file */EXT4_INODE_NOATIME    = 7,   /* do not update atime */
/* 为压缩使用保留…*/EXT4_INODE_DIRTY   = 8,EXT4_INODE_COMPRBLK    = 9,   /* One or more compressed clusters */EXT4_INODE_NOCOMPR = 10,  /* Don't compress */EXT4_INODE_ENCRYPT = 11,  /* Encrypted file */
/*结束压缩标志——可能没有全部使用*/EXT4_INODE_INDEX    = 12,  /* hash-indexed directory */EXT4_INODE_IMAGIC   = 13,  /* AFS directory */EXT4_INODE_JOURNAL_DATA  = 14,  /* file data should be journaled */EXT4_INODE_NOTAIL    = 15,  /* file tail should not be merged */EXT4_INODE_DIRSYNC  = 16,  /* dirsync behaviour (directories only) */EXT4_INODE_TOPDIR = 17,  /* Top of directory hierarchies*/EXT4_INODE_HUGE_FILE   = 18,  /* Set to each huge file */EXT4_INODE_EXTENTS   = 19,  /* Inode uses extents */EXT4_INODE_VERITY   = 20,  /* Verity protected inode */EXT4_INODE_EA_INODE = 21,  /* Inode used for large EA */
/* 22 过去是 EXT4_INODE_EOFBLOCKS */EXT4_INODE_DAX     = 25,  /* Inode is DAX */EXT4_INODE_INLINE_DATA    = 28,  /* Data in inode. */EXT4_INODE_PROJINHERIT  = 29,  /* Create with parents projid */EXT4_INODE_CASEFOLD = 30,  /* Casefolded directory */EXT4_INODE_RESERVED   = 31,  /* reserved for ext4 lib */
};/*由于很容易混淆位数和十六进制值,我们使用构建时检查来确保EXT4_XXX_FL与EXT4_INODE_XXX一致。如果一切正常,宏将被删除,因此,它不会在已编译的内核映像中消耗任何额外空间,否则,构建将失败。很重要的一点是,这些值是相同的,因为我们使用EXT4_INODE_XXX测试标志值,但EXT4_XXX_FL必须符合FS_XXX_FL的值定义在include / linux / fs.h和磁盘上的值ext2、ext3和ext4文件系统,当然e2fsprogs中定义的值。*/
#define TEST_FLAG_VALUE(FLAG) (EXT4_##FLAG##_FL == (1 << EXT4_INODE_##FLAG))
#define CHECK_FLAG_VALUE(FLAG) BUILD_BUG_ON(!TEST_FLAG_VALUE(FLAG))static inline void ext4_check_flag_values(void)
{CHECK_FLAG_VALUE(SECRM);CHECK_FLAG_VALUE(UNRM);CHECK_FLAG_VALUE(COMPR);CHECK_FLAG_VALUE(SYNC);CHECK_FLAG_VALUE(IMMUTABLE);CHECK_FLAG_VALUE(APPEND);CHECK_FLAG_VALUE(NODUMP);CHECK_FLAG_VALUE(NOATIME);CHECK_FLAG_VALUE(DIRTY);CHECK_FLAG_VALUE(COMPRBLK);CHECK_FLAG_VALUE(NOCOMPR);CHECK_FLAG_VALUE(ENCRYPT);CHECK_FLAG_VALUE(INDEX);CHECK_FLAG_VALUE(IMAGIC);CHECK_FLAG_VALUE(JOURNAL_DATA);CHECK_FLAG_VALUE(NOTAIL);CHECK_FLAG_VALUE(DIRSYNC);CHECK_FLAG_VALUE(TOPDIR);CHECK_FLAG_VALUE(HUGE_FILE);CHECK_FLAG_VALUE(EXTENTS);CHECK_FLAG_VALUE(VERITY);CHECK_FLAG_VALUE(EA_INODE);CHECK_FLAG_VALUE(INLINE_DATA);CHECK_FLAG_VALUE(PROJINHERIT);CHECK_FLAG_VALUE(CASEFOLD);CHECK_FLAG_VALUE(RESERVED);
}/*用于在完成在线调整大小时传递组描述符数据 */
struct ext4_new_group_input {__u32 group;           /*该数据的组号 */__u64 block_bitmap;  /*块位图的绝对块数*/__u64 inode_bitmap; /*inode位图的绝对块数*/__u64 inode_table;      /*inode表开始的绝对块数*/__u32 blocks_count;        /*这组数据块的总数*/__u16 reserved_blocks;  /*这组中保留块的数量 */__u16 unused;
};#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
struct compat_ext4_new_group_input {u32 group;compat_u64 block_bitmap;compat_u64 inode_bitmap;compat_u64 inode_table;u32 blocks_count;u16 reserved_blocks;u16 unused;
};
#endif/*内核空间中的ext4_new_group_input结构体,带有free_blocks_count*/
struct ext4_new_group_data {__u32 group;__u64 block_bitmap;__u64 inode_bitmap;__u64 inode_table;__u32 blocks_count;__u16 reserved_blocks;__u16 mdata_blocks;__u32 free_clusters_count;
};/*ext4_new_group_data中用于索引组表的索引*/
enum {BLOCK_BITMAP = 0,    /* block bitmap */INODE_BITMAP,     /* inode bitmap */INODE_TABLE,      /* inode tables */GROUP_TABLE_COUNT,
};/*ext4_map_blocks()使用的标志*//*分配任何需要的块且/或将未写入的区段转换为初始化的ext4*/
#define EXT4_GET_BLOCKS_CREATE          0x0001/*请求创建一个不成文的范围*/
#define EXT4_GET_BLOCKS_UNWRIT_EXT      0x0002
#define EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT   (EXT4_GET_BLOCKS_UNWRIT_EXT|\EXT4_GET_BLOCKS_CREATE)/*调用者从延迟分配写出路径最终执行延迟块的实际分配*/
#define EXT4_GET_BLOCKS_DELALLOC_RESERVE    0x0004/*调用者来自直接IO路径,请求创建未分配的未写区,如果块已经预分配,则分割未写区*/
#define EXT4_GET_BLOCKS_PRE_IO          0x0008
#define EXT4_GET_BLOCKS_CONVERT         0x0010
#define EXT4_GET_BLOCKS_IO_CREATE_EXT       (EXT4_GET_BLOCKS_PRE_IO|\EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT)/*在IO完成后将区段转换为初始化*/
#define EXT4_GET_BLOCKS_IO_CONVERT_EXT      (EXT4_GET_BLOCKS_CONVERT|\EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT)/* 最终的元数据分配(由于区段树的增长)应该不会失败,因此尝试为此使用保留块。*/
#define EXT4_GET_BLOCKS_METADATA_NOFAIL     0x0020/*不要将分配大小标准化(用于fallocate) */
#define EXT4_GET_BLOCKS_NO_NORMALIZE        0x0040/*将写入区转换为未写入区 */
#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN   0x0100/*向新创建的写入区写入0*/
#define EXT4_GET_BLOCKS_ZERO            0x0200
#define EXT4_GET_BLOCKS_CREATE_ZERO     (EXT4_GET_BLOCKS_CREATE |\EXT4_GET_BLOCKS_ZERO)/*调用者将在删除事务句柄之前提交数据。这允许jbd2避免在提交之前提交数据。*/
#define EXT4_GET_BLOCKS_IO_SUBMIT       0x0400/*这些标志的位位置不能与任何EXT4_GET_BLOCKS_*重叠。它们由ext4_find_extent()、read_extent_tree_block()、ext4_split_extent_at()、ext4_ext_insert_extent()和ext4_ext_create_new_leaf()使用。EXT4_EX_NOCACHE用于指示在进行截断或打孔操作时从区段树中读取区段时不应该缓存区段。*/
#define EXT4_EX_NOCACHE             0x40000000
#define EXT4_EX_FORCE_CACHE         0x20000000
#define EXT4_EX_NOFAIL              0x10000000/*由ext4_free_blocks使用的标志*/
#define EXT4_FREE_BLOCKS_METADATA       0x0001
#define EXT4_FREE_BLOCKS_FORGET         0x0002
#define EXT4_FREE_BLOCKS_VALIDATED      0x0004
#define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE     0x0008
#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER   0x0010
#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER    0x0020
#define EXT4_FREE_BLOCKS_RERESERVE_CLUSTER      0x0040/*ioctl命令专用于设备输入输出操作的系统调用*/
#define EXT4_IOC_GETVERSION     _IOR('f', 3, long)
#define EXT4_IOC_SETVERSION     _IOW('f', 4, long)
#define EXT4_IOC_GETVERSION_OLD     FS_IOC_GETVERSION
#define EXT4_IOC_SETVERSION_OLD     FS_IOC_SETVERSION
#define EXT4_IOC_GETRSVSZ       _IOR('f', 5, long)
#define EXT4_IOC_SETRSVSZ       _IOW('f', 6, long)
#define EXT4_IOC_GROUP_EXTEND       _IOW('f', 7, unsigned long)
#define EXT4_IOC_GROUP_ADD      _IOW('f', 8, struct ext4_new_group_input)
#define EXT4_IOC_MIGRATE        _IO('f', 9)/*注意ioctl 10为FIEMAP ioctl的早期版本保留*//*注意ioctl 11是保留给文件系统独立的FIEMAP ioctl*/
#define EXT4_IOC_ALLOC_DA_BLKS      _IO('f', 12)
#define EXT4_IOC_MOVE_EXT       _IOWR('f', 15, struct move_extent)
#define EXT4_IOC_RESIZE_FS      _IOW('f', 16, __u64)
#define EXT4_IOC_SWAP_BOOT      _IO('f', 17)
#define EXT4_IOC_PRECACHE_EXTENTS   _IO('f', 18)
/*Ioctl代码第19- 39为fscrypt保留*/
#define EXT4_IOC_CLEAR_ES_CACHE     _IO('f', 40)
#define EXT4_IOC_GETSTATE       _IOW('f', 41, __u32)
#define EXT4_IOC_GET_ES_CACHE       _IOWR('f', 42, struct fiemap)
#define EXT4_IOC_CHECKPOINT     _IOW('f', 43, __u32)#define EXT4_IOC_SHUTDOWN _IOR ('X', 125, __u32)/*下行操作的标志*/
#define EXT4_GOING_FLAGS_DEFAULT        0x0 /*下行*/
#define EXT4_GOING_FLAGS_LOGFLUSH       0x1 /*刷新日志,但不刷新数据*/
#define EXT4_GOING_FLAGS_NOLOGFLUSH     0x2 /*不要刷新日志或数据*//*EXT4_IOC_GETSTATE返回的标志我们只向用户空间公开i_state_flags中状态标志的一个子集
*/
#define EXT4_STATE_FLAG_EXT_PRECACHED   0x00000001
#define EXT4_STATE_FLAG_NEW     0x00000002
#define EXT4_STATE_FLAG_NEWENTRY    0x00000004
#define EXT4_STATE_FLAG_DA_ALLOC_CLOSE  0x00000008/*ioctl EXT4_IOC_CHECKPOINT的标志*/
#define EXT4_IOC_CHECKPOINT_FLAG_DISCARD    0x1
#define EXT4_IOC_CHECKPOINT_FLAG_ZEROOUT    0x2
#define EXT4_IOC_CHECKPOINT_FLAG_DRY_RUN    0x4
#define EXT4_IOC_CHECKPOINT_FLAG_VALID      (EXT4_IOC_CHECKPOINT_FLAG_DISCARD | \EXT4_IOC_CHECKPOINT_FLAG_ZEROOUT | \EXT4_IOC_CHECKPOINT_FLAG_DRY_RUN)#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
/* 32位仿真的ioctl命令*/
#define EXT4_IOC32_GETVERSION       _IOR('f', 3, int)
#define EXT4_IOC32_SETVERSION       _IOW('f', 4, int)
#define EXT4_IOC32_GETRSVSZ     _IOR('f', 5, int)
#define EXT4_IOC32_SETRSVSZ     _IOW('f', 6, int)
#define EXT4_IOC32_GROUP_EXTEND     _IOW('f', 7, unsigned int)
#define EXT4_IOC32_GROUP_ADD        _IOW('f', 8, struct compat_ext4_new_group_input)
#define EXT4_IOC32_GETVERSION_OLD   FS_IOC32_GETVERSION
#define EXT4_IOC32_SETVERSION_OLD   FS_IOC32_SETVERSION
#endif/*EXT4_IOC_GET_ES_CACHE作为一个额外的可能标志返回。表示区段状态缓存中的条目是为了一个孔。*/
#define EXT4_FIEMAP_EXTENT_HOLE     0x08000000/*最大的物理块,我们可以解决w/o区段*/
#define EXT4_MAX_BLOCK_FILE_PHYS    0xFFFFFFFF/*我们能支持的最大逻辑块*/
#define EXT4_MAX_LOGICAL_BLOCK      0xFFFFFFFE/*磁盘上inode的结构*/
struct ext4_inode {__le16   i_mode;     /* File mode */__le16   i_uid;      /* Low 16 bits of Owner Uid */__le32    i_size_lo;  /* Size in bytes */__le32   i_atime;    /* Access time */__le32 i_ctime;    /* Inode Change time */__le32   i_mtime;    /* Modification time */__le32   i_dtime;    /* Deletion Time */__le16   i_gid;      /* Low 16 bits of Group Id */__le16 i_links_count;  /* Links count */__le32 i_blocks_lo;    /* Blocks count */__le32    i_flags;    /* File flags */union {struct {__le32  l_i_version;} linux1;struct {__u32  h_i_translator;} hurd1;struct {__u32  m_i_reserved1;} masix1;} osd1;             /* OS dependent 1 */__le32  i_block[EXT4_N_BLOCKS];/* Pointers to blocks */__le32   i_generation;   /* File version (for NFS) */__le32  i_file_acl_lo;  /* File ACL */__le32    i_size_high;__le32  i_obso_faddr;   /* Obsoleted fragment address */union {struct {__le16   l_i_blocks_high; /* were l_i_reserved1 */__le16 l_i_file_acl_high;__le16    l_i_uid_high;   /* these 2 fields */__le16  l_i_gid_high;   /* were reserved2[0] */__le16   l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */__le16    l_i_reserved;} linux2;struct {__le16    h_i_reserved1;  /*在ext4中删除了废弃的片段号/大小*/__u16 h_i_mode_high;__u16 h_i_uid_high;__u16  h_i_gid_high;__u32  h_i_author;} hurd2;struct {__le16   h_i_reserved1;  /*在ext4中删除了废弃的片段号/大小*/__le16    m_i_file_acl_high;__u32 m_i_reserved2[2];} masix2;} osd2;               /* OS dependent 2 */__le16  i_extra_isize;__le16    i_checksum_hi;  /* crc32c(uuid+inum+inode) BE */__le32  i_ctime_extra;  /* extra Change time      (nsec << 2 | epoch) */__le32  i_mtime_extra;  /* extra Modification time(nsec << 2 | epoch) */__le32  i_atime_extra;  /* extra Access time      (nsec << 2 | epoch) */__le32  i_crtime;       /* File Creation time */__le32  i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */__le32  i_version_hi; /* high 32 bits for 64-bit version */__le32 i_projid;   /* Project ID */
};struct move_extent {__u32 reserved;       /* should be zero */__u32 donor_fd;     /* donor file descriptor */__u64 orig_start;    /* logical start offset in block for orig */__u64 donor_start;  /* logical start offset in block for donor */__u64 len;     /* block length to be moved */__u64 moved_len;  /* moved block length */
};#define EXT4_EPOCH_BITS 2
#define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
#define EXT4_NSEC_MASK  (~0UL << EXT4_EPOCH_BITS)/*如果文件系统使用大索引节点(-I 256或更大)格式化,并且当前没有任何EAs占用所有可用空间,则扩展字段将适合于索引节点。对于新inode,我们总是为内核的已知扩展字段保留足够的空间,但对于用旧内核创建的inode,情况可能并非如此。没有扩展的inode字段对正确的文件系统操作至关重要。这个宏检查某个字段是否适合inode。注意inode-size = GOOD_OLD_INODE_SIZE + i_extra_size*/
#define EXT4_FITS_IN_INODE(ext4_inode, einode, field)   \((offsetof(typeof(*ext4_inode), field) +  \sizeof((ext4_inode)->field))            \<= (EXT4_GOOD_OLD_INODE_SIZE +            \(einode)->i_extra_isize))           \/** 我们使用一种编码来保留额外纪元“00”的时间:** extra  msb of                         adjust for signed* epoch  32-bit                         32-bit tv_sec to* bits   time    decoded 64-bit tv_sec  64-bit tv_sec      valid time range* 0 0    1    -0x80000000..-0x00000001  0x000000000 1901-12-13..1969-12-31* 0 0    0    0x000000000..0x07fffffff  0x000000000 1970-01-01..2038-01-19* 0 1    1    0x080000000..0x0ffffffff  0x100000000 2038-01-19..2106-02-07* 0 1    0    0x100000000..0x17fffffff  0x100000000 2106-02-07..2174-02-25* 1 0    1    0x180000000..0x1ffffffff  0x200000000 2174-02-25..2242-03-16* 1 0    0    0x200000000..0x27fffffff  0x200000000 2242-03-16..2310-04-04* 1 1    1    0x280000000..0x2ffffffff  0x300000000 2310-04-04..2378-04-22* 1 1    0    0x300000000..0x37fffffff  0x300000000 2378-04-22..2446-05-10**注意,在64位系统上的以前版本的内核会不正确地使用1901到1970之间的额外纪元位1,1。E2fsck将纠正这个错误,假设它是在2242之前在受影响的文件系统上运行的。*/static inline __le32 ext4_encode_extra_time(struct timespec64 *time)
{u32 extra =((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK;return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
}static inline void ext4_decode_extra_time(struct timespec64 *time,__le32 extra)
{if (unlikely(extra & cpu_to_le32(EXT4_EPOCH_MASK)))time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
}#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)              \
do {                                        \if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra))     {\(raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec);   \(raw_inode)->xtime ## _extra =                 \ext4_encode_extra_time(&(inode)->xtime);    \}                              \else   \(raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (inode)->xtime.tv_sec, S32_MIN, S32_MAX));    \
} while (0)#define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode)                 \
do {                                           \if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime))              \(raw_inode)->xtime = cpu_to_le32((einode)->xtime.tv_sec);      \if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))         \(raw_inode)->xtime ## _extra =                     \ext4_encode_extra_time(&(einode)->xtime);      \
} while (0)#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode)                \
do {                                        \(inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime);    \if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) {   \ext4_decode_extra_time(&(inode)->xtime,             \raw_inode->xtime ## _extra);        \}                              \else                                   \(inode)->xtime.tv_nsec = 0;                    \
} while (0)#define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode)                 \
do {                                           \if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime))              \(einode)->xtime.tv_sec =                       \(signed)le32_to_cpu((raw_inode)->xtime);        \else                                       \(einode)->xtime.tv_sec = 0;                    \if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime ## _extra))        \ext4_decode_extra_time(&(einode)->xtime,            \raw_inode->xtime ## _extra);        \else                                       \(einode)->xtime.tv_nsec = 0;                       \
} while (0)#define i_disk_version osd1.linux1.l_i_version#if defined(__KERNEL__) || defined(__linux__)
#define i_reserved1 osd1.linux1.l_i_reserved1
#define i_file_acl_high osd2.linux2.l_i_file_acl_high
#define i_blocks_high   osd2.linux2.l_i_blocks_high
#define i_uid_low   i_uid
#define i_gid_low   i_gid
#define i_uid_high  osd2.linux2.l_i_uid_high
#define i_gid_high  osd2.linux2.l_i_gid_high
#define i_checksum_lo   osd2.linux2.l_i_checksum_lo#elif defined(__GNU__)#define i_translator   osd1.hurd1.h_i_translator
#define i_uid_high  osd2.hurd2.h_i_uid_high
#define i_gid_high  osd2.hurd2.h_i_gid_high
#define i_author    osd2.hurd2.h_i_author#elif defined(__masix__)#define i_reserved1    osd1.masix1.m_i_reserved1
#define i_file_acl_high osd2.masix2.m_i_file_acl_high
#define i_reserved2 osd2.masix2.m_i_reserved2#endif /* defined(__KERNEL__) || defined(__linux__) */#include "extents_status.h"
#include "fast_commit.h"/** 在ext4_inode_info结构中锁定i_data_sem的子类。*
*当我们需要在ext4_map_blocks()期间为配额inode分配块,而为一个普通(非配额)inode保持*i_data_sem时,需要使用这些参数来避免lockdep误报。由于我们没有对配额inode进行配额    *跟踪,这就避免了死锁(以及无限递归,因为它不会一直向下…)
* I_DATA_SEM_NORMAL -用于大多数inode
*I_DATA_SEM_OTHER  -由move_inode.c用于第二个普通inode,其中第二个inode的inode数大*于第一个
*I_DATA_SEM_QUOTA  - 仅用于配额索引节点*/
enum {I_DATA_SEM_NORMAL = 0,I_DATA_SEM_OTHER,I_DATA_SEM_QUOTA,
};/*内存中的ext4文件系统inode数据*/
struct ext4_inode_info {__le32  i_data[15]; /* unconverted */__u32  i_dtime;ext4_fsblk_t    i_file_acl;/* i_block_group是包含该文件inode的块组的编号。常量贯穿整个inode的生命周期,它用于做出块分配决策—我们试图将文件的数据块放在它的inode块附近,并将新inode放在它们的父目录的inode附近。*/ext4_group_t  i_block_group;ext4_lblk_t   i_dir_start_lookup;
#if (BITS_PER_LONG < 64)unsigned long    i_state_flags;      /*动态的状态标志*/
#endifunsigned long i_flags;/*扩展属性可以独立于主文件数据读取。即使在读取时使用i_mutex也会导致EAs的读取者和普通文件数据的写入者之间的争用,所以我们在读取或更改EAs时在xattr_sem上进行同步。*/struct rw_semaphore xattr_sem;struct list_head i_orphan;   /*未链接但打开的索引节点*//*快速提交相关信息*/struct list_head i_fc_list;  /*由sbi->s_fc_lock保护的需要快速提交的节点。*//*需要在快速提交操作中提交的lblk范围的起始点*/ext4_lblk_t i_fc_lblk_start;/*需要在快速提交操作中提交的lblk范围的末尾*/ext4_lblk_t i_fc_lblk_len;/*此inode上正在进行的更新数量*/atomic_t  i_fc_updates;/*这个inode的快速提交等待队列*/wait_queue_head_t i_fc_wait;/*保护i_fc_lblk_start和i_fc_lblk_len上的并发访问*/struct mutex i_fc_lock;/*i_disksize跟踪inode在磁盘上的大小,而不是在内存中。在截断期间,在调用     ext4_truncate()之前,VFS将i_size设置为新的大小,但是文件系统在实际进行截断之前不会 将i_disksize设置为0。原因是i_disksize总是表示该文件使用的块。如果在截断期间崩溃,  它允许在orphans上恢复重新启动截断。在写出节点时,我们实际上是将i_disksize写入磁 盘上的节点,而不是i_size。i_disksize和i_size唯一不同的时候是在进行截断时。唯一改变 i_disksize的是    ext4_get_block(增长)和ext4_truncate(收缩)。
*/loff_t    i_disksize;/*i_data_sem用于对ext4_getblock()序列化ext4_truncate()。在2.4 ext2设计中,inode数据 树的大块在截断过程中被截断。在ext4中不能这样做,因为每当我们在截断期间执行中间    提交时,inode和所有元数据块*必须*处于一致状态,这允许在恢复期间重新启动orphans    截断。因此,我们必须通过其他方法修复get_block-vs-truncate竞争,因此我们有i_data_sem。    */struct rw_semaphore i_data_sem;
/* i_mmap_sem用于序列化带有截断/穿孔操作的页面错误。我们必须确保新页面不会    在   正在打孔的inode部分出现故障。因为我们需要对整个穿孔操作进行保护,我们不能轻易    地使  用i_data_sem,而且i_data_sem的级别低于事务启动,所以我们不得不偶尔放弃使用   它。  */struct rw_semaphore i_mmap_sem;struct inode vfs_inode;struct jbd2_inode *jinode;spinlock_t i_raw_lock;    /*保护对原始inode的更新*//*文件创建时间。它的功能与泛型inode中的struct timespec64 i_{a,c,m}time相同。*/struct timespec64 i_crtime;/* mballoc */atomic_t i_prealloc_active;struct list_head i_prealloc_list;spinlock_t i_prealloc_lock;/* extents status tree */struct ext4_es_tree i_es_tree;rwlock_t i_es_lock;struct list_head i_es_list;unsigned int i_es_all_nr;   /* protected by i_es_lock */unsigned int i_es_shk_nr;   /* protected by i_es_lock */ext4_lblk_t i_es_shrink_lblk;   /*设置开始搜索要收缩的区段的位置。受i_es_lock保护*//* ialloc */ext4_group_t    i_last_alloc_group;/*delalloc的分配预留信息*//*在bigalloc中,它指的是集群而不是块*/unsigned int i_reserved_data_blocks;/*为bigalloc文件系统挂起的集群保留*/struct ext4_pending_tree i_pending_tree;/*磁盘上的额外的长度*/__u16 i_extra_isize;/*指示内联数据空间。*/u16 i_inline_off;u16 i_inline_size;#ifdef CONFIG_QUOTA/*配额空间预留,由配额代码内部管理 */qsize_t i_reserved_quota;
#endif/*锁定下面的保护列表*/spinlock_t i_completed_io_lock;/*完成的IOs需要未写入的区处理和事务保留*/struct list_head i_rsv_conversion_list;struct work_struct i_rsv_conversion_work;atomic_t i_unwritten; /* Nr. of inflight conversions pending */spinlock_t i_block_reservation_lock;/*包含分别完成fsync和fdatasync所需的inode元数据的事务。*/tid_t i_sync_tid;tid_t i_datasync_tid;#ifdef CONFIG_QUOTAstruct dquot *i_dquot[MAXQUOTAS];
#endif/*用于种子索引节点校验和的uuid+inum+igen校验和*/__u32 i_csum_seed;kprojid_t i_projid;
};
/*文件系统状态标志*/
#define EXT4_VALID_FS           0x0001  /* Unmounted cleanly */
#define EXT4_ERROR_FS           0x0002  /* Errors detected */
#define EXT4_ORPHAN_FS          0x0004  /* Orphans being recovered */
#define EXT4_FC_REPLAY          0x0020  /* Fast commit replay ongoing *//*Misc. filesystem文件系统杂项标志*/
#define EXT2_FLAGS_SIGNED_HASH      0x0001  /* Signed dirhash in use */
#define EXT2_FLAGS_UNSIGNED_HASH    0x0002  /* Unsigned dirhash in use */
#define EXT2_FLAGS_TEST_FILESYS     0x0004  /* to test development code *//*通过挂载选项或默认设置挂载标志*/
#define EXT4_MOUNT_NO_MBCACHE       0x00001 /* Do not use mbcache */
#define EXT4_MOUNT_GRPID        0x00004 /* Create files with directory's group */
#define EXT4_MOUNT_DEBUG        0x00008 /* Some debugging messages */
#define EXT4_MOUNT_ERRORS_CONT      0x00010 /* Continue on errors */
#define EXT4_MOUNT_ERRORS_RO        0x00020 /* Remount fs ro on errors */
#define EXT4_MOUNT_ERRORS_PANIC     0x00040 /* Panic on errors */
#define EXT4_MOUNT_ERRORS_MASK      0x00070
#define EXT4_MOUNT_MINIX_DF     0x00080 /* Mimics the Minix statfs */
#define EXT4_MOUNT_NOLOAD       0x00100 /* Don't use existing journal*/
#ifdef CONFIG_FS_DAX
#define EXT4_MOUNT_DAX_ALWAYS       0x00200 /* Direct Access */
#else
#define EXT4_MOUNT_DAX_ALWAYS       0
#endif
#define EXT4_MOUNT_DATA_FLAGS       0x00C00 /* Mode for data writes: */
#define EXT4_MOUNT_JOURNAL_DATA     0x00400 /* Write data to journal */
#define EXT4_MOUNT_ORDERED_DATA     0x00800 /* Flush data before commit */
#define EXT4_MOUNT_WRITEBACK_DATA   0x00C00 /* No data ordering */
#define EXT4_MOUNT_UPDATE_JOURNAL   0x01000 /* Update the journal format */
#define EXT4_MOUNT_NO_UID32     0x02000  /* Disable 32-bit UIDs */
#define EXT4_MOUNT_XATTR_USER       0x04000 /* Extended user attributes */
#define EXT4_MOUNT_POSIX_ACL        0x08000 /* POSIX Access Control Lists */
#define EXT4_MOUNT_NO_AUTO_DA_ALLOC 0x10000 /* No auto delalloc mapping */
#define EXT4_MOUNT_BARRIER      0x20000 /* Use block barriers */
#define EXT4_MOUNT_QUOTA        0x40000 /* Some quota option set */
#define EXT4_MOUNT_USRQUOTA     0x80000 /* "old" user quota, enable enforcement for hidden quota files */
#define EXT4_MOUNT_GRPQUOTA     0x100000 /* "old" group quota, enable enforcement for hidden quota files */
#define EXT4_MOUNT_PRJQUOTA     0x200000 /* Enable project quotaenforcement */
#define EXT4_MOUNT_DIOREAD_NOLOCK   0x400000 /* Enable support for dio read nolocking */
#define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */
#define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */
#define EXT4_MOUNT_WARN_ON_ERROR    0x2000000 /* Trigger WARN_ON on error */
#define EXT4_MOUNT_NO_PREFETCH_BLOCK_BITMAPS 0x4000000
#define EXT4_MOUNT_DELALLOC     0x8000000 /* Delalloc support */
#define EXT4_MOUNT_DATA_ERR_ABORT   0x10000000 /* Abort on file data write */
#define EXT4_MOUNT_BLOCK_VALIDITY   0x20000000 /* Block validity checking */
#define EXT4_MOUNT_DISCARD      0x40000000 /* Issue DISCARD requests */
#define EXT4_MOUNT_INIT_INODE_TABLE 0x80000000 /* Initialize uninitialized itables *//*根据文件系统特性或属性自动(无法通过挂载选项设置)设置挂载标志,或在特殊情况下(如区分显式挂载选项定义和默认值)设置挂载标志。*/
#define EXT4_MOUNT2_EXPLICIT_DELALLOC   0x00000001 /* User explicitlyspecified delalloc */
#define EXT4_MOUNT2_STD_GROUP_SIZE  0x00000002 /* We have standard groupsize of blocksize * 8blocks */
#define EXT4_MOUNT2_HURD_COMPAT     0x00000004 /* Support HURD-castratedfile systems */
#define EXT4_MOUNT2_EXPLICIT_JOURNAL_CHECKSUM   0x00000008 /* User explicitly specified journal checksum */#define EXT4_MOUNT2_JOURNAL_FAST_COMMIT  0x00000010 /* Journal fast commit */
#define EXT4_MOUNT2_DAX_NEVER       0x00000020 /* Do not allow Direct Access */
#define EXT4_MOUNT2_DAX_INODE       0x00000040 /* For printing options only */
#define EXT4_MOUNT2_MB_OPTIMIZE_SCAN    0x00000080 /* Optimize group scanning in mballoc */#define clear_opt(sb, opt)       EXT4_SB(sb)->s_mount_opt &= \~EXT4_MOUNT_##opt
#define set_opt(sb, opt)        EXT4_SB(sb)->s_mount_opt |= \EXT4_MOUNT_##opt
#define test_opt(sb, opt)       (EXT4_SB(sb)->s_mount_opt & \EXT4_MOUNT_##opt)#define clear_opt2(sb, opt)        EXT4_SB(sb)->s_mount_opt2 &= \~EXT4_MOUNT2_##opt
#define set_opt2(sb, opt)       EXT4_SB(sb)->s_mount_opt2 |= \EXT4_MOUNT2_##opt
#define test_opt2(sb, opt)      (EXT4_SB(sb)->s_mount_opt2 & \EXT4_MOUNT2_##opt)#define ext4_test_and_set_bit        __test_and_set_bit_le
#define ext4_set_bit            __set_bit_le
#define ext4_set_bit_atomic     ext2_set_bit_atomic
#define ext4_test_and_clear_bit     __test_and_clear_bit_le
#define ext4_clear_bit          __clear_bit_le
#define ext4_clear_bit_atomic       ext2_clear_bit_atomic
#define ext4_test_bit           test_bit_le
#define ext4_find_next_zero_bit     find_next_zero_bit_le
#define ext4_find_next_bit      find_next_bit_leextern void ext4_set_bits(void *bm, int cur, int len);/*两个文件系统检查之间的最大挂载计数*/
#define EXT4_DFL_MAX_MNT_COUNT      20  /* Allow 20 mounts */
#define EXT4_DFL_CHECKINTERVAL      0   /* Don't use interval check *//*检测错误时的行为*/
#define EXT4_ERRORS_CONTINUE        1   /* Continue execution */
#define EXT4_ERRORS_RO          2   /* Remount fs read-only */
#define EXT4_ERRORS_PANIC       3   /* Panic */
#define EXT4_ERRORS_DEFAULT     EXT4_ERRORS_CONTINUE/*元数据校验和算法代码*/
#define EXT4_CRC32C_CHKSUM      1

相对与ext2文件系统来说,ext4增加了元数据校验操作,方法是循环冗余校验。

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

  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 内核文件系统模块结构体关系图

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

  8. Linux内核文件系统12

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

  9. Linux内核文件系统8

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

最新文章

  1. PaddleFluid和TensorFlow基本使用概念对比 | PaddlePaddle专栏
  2. linux cp 时 略过文件,CentOS下执行cp命令式提示略过文件夹
  3. 为什么说拥抱.NET CORE的时候到了
  4. HDU 3397 线段树 双懒惰标记
  5. 本硕985非科班渣硕2020腾讯计算机视觉算法实习面经(已获Offer)
  6. iOS h264硬编码
  7. 蓝牙耳机哪款适合玩枪战类手游?低延迟听声辨位五款蓝牙耳机推荐
  8. 一些自己收藏的有用的资料
  9. 集群语言 Python 入门 脚本工具
  10. 谷歌服务框架_谷歌服务框架下载_谷歌服务框架全版本整理
  11. 在线vip全网音乐搜索下载源码
  12. struts1的actionform
  13. ckplayer6.8 php播放,ckplayer官方版下载-ckplayer播放器v6.8 最新版 - 极光下载站
  14. 2018年面经大合集
  15. 三维计算机动画的特征是真实性,3D动画电影的应用特点及制作管理内容
  16. 中企海外周报 | 中国品牌闪耀亮相2019 IFA
  17. 电脑连接不上手机热点-始终显示无法连接到该网络的解决办法(亲测管用)
  18. 京东移动端首页-流式布局
  19. iframe简单使用
  20. SAP中供应商寄售库存返回操作实例

热门文章

  1. 浅谈 NATIVE SQL
  2. openwrt添加lcd4linux,openwrt添加新设备支持(定制固件一)
  3. 苹果手机上滑动会卡顿_苹果手机用久了出现卡顿,学会这几招,手机变得非常流畅...
  4. Intellij 查看所有断点
  5. Nginx 负载均衡 初步配置验证 笔记
  6. 提供一个0day(CVE)挖掘思路
  7. 计算机及其应用专业自考停考,自考专业名称调整及停考 有你报名的专业吗?
  8. Maven中央仓库连接不上的问题解决
  9. mysql checksum_mysql8 参考手册--CHECKSUM TABLE语句
  10. SVG矢量图及其制作工具