diff --git a/fs/hmfs/Makefile b/fs/hmfs/Makefile new file mode 100644 index 00000000..11542ca4 --- /dev/null +++ b/fs/hmfs/Makefile @@ -0,0 +1,20 @@ +ccflags-y += -DCONFIG_HMFS_DEBUG +ccflags-y += -DCONFIG_HMFS_DEBUG_GC +ccflags-y += -DCONFIG_HMFS_XATTR +#ccflags-y += -DCONFIG_HMFS_FAST_READ +ccflags-y += -DCONFIG_HMFS_ACL +ccflags-y += -DCONFIG_HMFS_DEBUG_RW_LOCK + +obj-m += hmfs.o + +hmfs-objs := super.o node.o inode.o checkpoint.o file.o data.o namei.o segment.o hash.o dir.o symlink.o gc.o recovery.o + +hmfs-objs += debug.o +hmfs-objs += xattr.o +hmfs-objs += util.o +hmfs-objs += acl.o + +all: + make -C /lib/modules/`uname -r`/build M=`pwd` modules +clean: + make -C /lib/modules/`uname -r`/build M=`pwd` clean diff --git a/fs/hmfs/acl.c b/fs/hmfs/acl.c index f7eb218b..0467043d 100644 --- a/fs/hmfs/acl.c +++ b/fs/hmfs/acl.c @@ -19,7 +19,10 @@ #include "hmfs.h" #include "xattr.h" #include "acl.h" - +/** + * @param[in] count 字节数 + * @return 返回count个acl_entry对应的字节数 + */ static inline size_t hmfs_acl_size(int count) { if (count <= 4) { @@ -29,7 +32,10 @@ static inline size_t hmfs_acl_size(int count) (count - 4) * ACL_ENTRY_SIZE; } } - +/** + * @param[in] size entry数 + * @return 返回size个字节对应的访问控制表entry数 + */ static inline int hmfs_acl_count(size_t size) { ssize_t s; @@ -46,7 +52,11 @@ static inline int hmfs_acl_count(size_t size) return s / ACL_ENTRY_SIZE + 4; } } - +/** + * 获取文件访问控制表的地址 + * @param[in] inode 为该文件inode + * @return 成功则返回访问控制表地址,否则返回NULL + */ static void *get_acl_block(struct inode *inode) { struct hmfs_sb_info *sbi = HMFS_I_SB(inode); @@ -62,7 +72,12 @@ static void *get_acl_block(struct inode *inode) return ADDR(sbi, acl_addr); return NULL; } - +/** + * 读取访问控制表内容 + * @param[in] base_addr 为要读取的ACL的起始地址 + * @param[in] size 为要读取的字节数 + * @return 返回值为指向存储了访问控制表内容的新建ACL表的指针 + */ static struct posix_acl *hmfs_read_acl(const char *base_addr, size_t size) { int i, count; @@ -117,7 +132,12 @@ static struct posix_acl *hmfs_read_acl(const char *base_addr, size_t size) posix_acl_release(acl); return ERR_PTR(-EINVAL); } - +/** + * 获取文件访问控制表内容 + * @param[in] inode 为该文件inode + * @param[in] type 定义获取类型为ACL_TYPE_ACCESS或是ACL_TYPE_DEFAULT,从而读取不同的内容 + * @return 成功时返回指向存储获取到内容的ACL表的指针 + */ struct posix_acl *hmfs_get_acl(struct inode *inode, int type) { struct hmfs_acl_header *acl_header = NULL; @@ -160,7 +180,12 @@ struct posix_acl *hmfs_get_acl(struct inode *inode, int type) return acl; } - +/** + * 初始化@base_addr指向的acl块 + * 修改其h_magic值为HMFS_X_BLOCK_TAG_ACL + * 修改a_version值为HMFS_ACL_VERSION + * @param[in] base_addr 指向acl块 + */ static void init_acl_block(void *base_addr) { struct hmfs_acl_header *acl_header = ACL_HEADER(base_addr); @@ -168,7 +193,14 @@ static void init_acl_block(void *base_addr) XATTR_HDR(base_addr)->h_magic = cpu_to_le16(HMFS_X_BLOCK_TAG_ACL); acl_header->a_version = cpu_to_le32(HMFS_ACL_VERSION); } - +/** + * 写文件访问控制表 + * @param[in] inode 为该文件的inode + * @param[in] acl 指向的结构体存储了要写入文件ACL的值 + * @param[in] size 用于存储写入后的ACL大小 + * @param[in] type 定义ACL类型为ACL_TYPE_ACCESS还是ACL_TYPE_DEFAULT + * @return 成功则返回写入的访问控制表地址 + */ static void *hmfs_write_acl(struct inode *inode, const struct posix_acl *acl, size_t *size, int type) { @@ -249,7 +281,13 @@ static void *hmfs_write_acl(struct inode *inode, const struct posix_acl *acl, fail: return ERR_PTR(-EINVAL); } - +/** + * 设置文件访问控制表 + * @param[in] inode 为该文件的inode + * @param[in] acl 指向的结构体存储了要写入文件ACL的值 + * @param[in] type 定义ACL类型为ACL_TYPE_ACCESS还是ACL_TYPE_DEFAULT + * @return 成功则返回0 + */ int hmfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { struct hmfs_inode_info *fi = HMFS_I(inode); @@ -292,7 +330,12 @@ int hmfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) clear_inode_flag(fi, FI_ACL_MODE); return error; } - +/** + * 复制访问控制表 + * @param[in] acl 为要复制的访问控制表 + * @param[in] flags 为复制时使用的gfp掩码 + * @return 返回复制的访问控制表 + */ static struct posix_acl *hmfs_acl_clone(const struct posix_acl *acl, gfp_t flags) { @@ -308,7 +351,10 @@ static struct posix_acl *hmfs_acl_clone(const struct posix_acl *acl, } return clone; } - +/** + * 创建新节点时修改文件acl + * @return 成功则返回0 + */ static int hmfs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) { struct posix_acl_entry *pa, *pe; @@ -360,7 +406,14 @@ static int hmfs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) *mode_p = (*mode_p & ~S_IRWXUGO) | mode; return not_equiv; } - +/** + * 创建一个访问控制表 + * @param[in] dir为参照的已有文件inode + * @param[in] mode对应文件类型 + * @param[in] *default_acl指向dir文件的acl + * @param[in] *acl指向新建的文件acl + * @return 成功则返回0 + */ static int hmfs_acl_create(struct inode *dir, umode_t *mode, struct posix_acl **default_acl, struct posix_acl **acl) { @@ -407,7 +460,12 @@ static int hmfs_acl_create(struct inode *dir, umode_t *mode, posix_acl_release(p); return -ENOMEM; } - +/** + * 初始化访问控制表 + * @param[in] inode 为需要初始化的文件inode + * @param[in] dir 为参照的文件inode + * @return 成功则返回0 + */ int hmfs_init_acl(struct inode *inode, struct inode *dir) { struct posix_acl *default_acl = NULL, *acl = NULL; @@ -430,7 +488,13 @@ int hmfs_init_acl(struct inode *inode, struct inode *dir) return error; } - +/** + * 列出文件POSIX_ACL_XATTR_ACCESS属性值 + * @param[in] dentry用于索引超级块 + * @param[in] list用于存储字符串 + * @param[in] list_size为list存储的最大空间 + * @return 返回属性值的字节长度 + */ size_t hmfs_acl_access_xattr_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len, int type) @@ -444,7 +508,13 @@ size_t hmfs_acl_access_xattr_list(struct dentry *dentry, char *list, memcpy(list, POSIX_ACL_XATTR_ACCESS, size); return size; } - +/** + * 列出文件POSIX_ACL_XATTR_DEFAULT属性值 + * @param[in] dentry 用于索引超级块 + * @param[in] list 用于存储字符串 + * @param[in] list_size 为list存储的最大空间 + * @return 返回属性值的字节长度 + */ size_t hmfs_acl_default_xattr_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t name_len, int type) @@ -458,7 +528,13 @@ size_t hmfs_acl_default_xattr_list(struct dentry *dentry, char *list, memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); return size; } - +/** + * 获取文件acl扩展属性 + * @param[in] dentry 为该文件目录项 + * @param[in] buffer 为属性复制到的目标缓冲区地址 + * @param[in] size 为目标缓冲区最大大小 + * @return 成功则返回acl属性字节长度 + */ int hmfs_acl_xattr_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int type) { @@ -483,7 +559,13 @@ int hmfs_acl_xattr_get(struct dentry *dentry, const char *name, void *buffer, return error; } - +/** + * 设置文件acl扩展属性 + * @param[in] dentry 为该文件目录项 + * @param[in] value 为要设置的属性值 + * @param[in] size 为要设置的属性值字节数 + * @return 成功则返回0 + */ static int hmfs_acl_xattr_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { diff --git a/fs/hmfs/build.sh b/fs/hmfs/build.sh new file mode 100755 index 00000000..ea169ef6 --- /dev/null +++ b/fs/hmfs/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +if [ "$1" == "hmfs" ] + then + insmod ./hmfs.ko + sudo mount -t hmfs -o physaddr=0x4B000000,init=100M none ~/mount_hmfs/ +elif [ "$1" == "nohmfs" ] + then + umount ~/mount_hmfs + rmmod hmfs +fi \ No newline at end of file diff --git a/fs/hmfs/checkpoint.c b/fs/hmfs/checkpoint.c index 3a6a0cf4..d6b68a71 100644 --- a/fs/hmfs/checkpoint.c +++ b/fs/hmfs/checkpoint.c @@ -8,6 +8,24 @@ static struct kmem_cache *orphan_entry_slab; static struct kmem_cache *cp_info_entry_slab; +/** + *cc1 modify_checkpoint_version:当发生修改时,修改NAT树种各类块的子节点的版本信息 + *@sbi:指向当前版本下超级块信息的实例 + *@block:块号 + *@prev_ver:以前的版本号 + *@new_ver:新的版本号 + */ +/** + * modify_checkpoint_version:当发生修改时,修改NAT树种各类块的子节点的版本信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] block:块号 + * @param[in] prev_ver:以前的版本号 + * @param[in] prev_ver:以前的版本号 + * @return new_ver:新的版本号 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, ver_t prev_ver, ver_t new_ver) { @@ -17,6 +35,9 @@ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, void *child_block; int i; + /** + *根据块号获取块地址,进而获取块的信息表没,从而获得该块的当前版本 + */ block_addr = L_ADDR(sbi, block); summary = get_summary_by_addr(sbi, block_addr); cur_ver = get_summary_start_version(summary); @@ -29,6 +50,9 @@ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, set_summary_start_version(summary, new_ver); switch (get_summary_type(summary)) { + /** + *用新的版本信息修改当前nat node block的孩子节点的版本号 + */ case SUM_TYPE_NATN: { __le64 *child = HMFS_NAT_NODE(block)->addr; @@ -41,7 +65,9 @@ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, } break; } - + /** + *如果是NAT树的数据块,且entry结点发生了改变,则相应地修改各类结点的的子节点的版本号为最新版本号 + */ case SUM_TYPE_NATD: { struct hmfs_nat_entry *entry; @@ -56,6 +82,9 @@ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, break; } + /** + * 如果是inode块,修改inode块里面扩展块的子节点块的版本信息和数据块的版本信息 + */ case SUM_TYPE_INODE: { __le64 *child; struct hmfs_inode *inode_block; @@ -82,6 +111,9 @@ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, break; } + /** + * 如果是direct块,则修改指向数据块的孩子节点的版本号 + */ case SUM_TYPE_DN: { __le64 *child = DIRECT_NODE(block)->addr; @@ -95,6 +127,10 @@ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, break; } + /** + *如果是checkpoint块,则并且不是孤立节点,则修改检查点的版本号 + *如果是孤立节点,记录当前检查点下所有的孤立节点,相应地修改版本信息 + */ case SUM_TYPE_CP: { struct hmfs_checkpoint *cur_cp; @@ -125,6 +161,17 @@ static void modify_checkpoint_version(struct hmfs_sb_info *sbi, void *block, } //TODO: What if crash in this process +/** + *cc2 recycle_version_number:回收当前的版本号 + *@sbi:指向当前版本下超级块信息的实例 + */ +/** + * recycle_version_number:回收当前的版本号 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void recycle_version_number(struct hmfs_sb_info *sbi) { struct hmfs_checkpoint *cur_cp, *last_cp; @@ -137,6 +184,9 @@ void recycle_version_number(struct hmfs_sb_info *sbi) /* * We first calculate how many checkpoint there are */ + /** + *简单统计下已有的checkpoint的数目 + */ do { cur_cp = ADDR(sbi, le64_to_cpu(cur_cp->next_cp_addr)); version++; @@ -150,6 +200,9 @@ void recycle_version_number(struct hmfs_sb_info *sbi) * checkpoint to oldest checkpoint. It's ok because we cannot * reach newer block from older checkpoint block. */ + /** + * 修改版本号从最新的检查点到最旧的检查点 + */ cur_cp = CM_I(sbi)->last_cp_i->cp; while (version >= HMFS_DEF_CP_VER) { last_cp = ADDR(sbi, le64_to_cpu(cur_cp->prev_cp_addr)); @@ -159,12 +212,32 @@ void recycle_version_number(struct hmfs_sb_info *sbi) cur_cp = last_cp; } } - +/** + *cc3 next_checkpoint_ver:得到下一个版本号 + */ +/** + * next_checkpoint_ver:得到下一个版本号 + * @param[in] version:版本号 + * @return new_ver:下一个版本号 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static ver_t next_checkpoint_ver(ver_t version) { return version + 1; } - +/** + *cc4 init_orphan_manager:初始化管理孤立点的实例 + *@cm_i:初始化检查点管理器的实例 + */ +/** + * init_orphan_manager:初始化管理孤立点的实例 + * @param[in] cm_i:初始化检查点管理器的实例 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void init_orphan_manager(struct hmfs_cm_info *cm_i) { /* init orphan manager */ @@ -172,13 +245,28 @@ static void init_orphan_manager(struct hmfs_cm_info *cm_i) INIT_LIST_HEAD(&cm_i->orphan_inode_list); cm_i->n_orphans = 0; } - +/** + *cc5 add_orphan_inode:增加孤立节点的inode到链表队尾 + *@sbi:指向当前版本下超级块信息的实例 + *@ino:节点的inode号 + */ +/** + * add_orphan_inode:增加孤立节点的inode到链表队尾 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] ino:节点的inode号 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void add_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) { struct list_head *head, *this; struct orphan_inode_entry *new = NULL, *orphan = NULL; struct hmfs_cm_info *cm_i = CM_I(sbi); + /** + *获取检查点管理器下孤立节点的链表,判断给定节点的inode和孤立节点里边中的节点号是否相同 + */ lock_orphan_inodes(cm_i); head = &cm_i->orphan_inode_list; list_for_each(this, head) { @@ -189,6 +277,9 @@ void add_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) break; orphan = NULL; } + /** + *如果不同,增加新的孤立节点到孤立节点的队尾。并且对孤立节点数加1 + */ retry: new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC); if (!new) { @@ -205,7 +296,19 @@ void add_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) out: unlock_orphan_inodes(cm_i); } - +/** + *cc6 remove_orphan_inode:删除不再需要的孤立节点的inode + *@sbi:指向当前版本下超级块信息的实例 + *@ino:节点的inode号 + */ +/** + * remove_orphan_inode:删除不再需要的孤立节点的inode + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] ino:节点的inode号 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void remove_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) { struct list_head *this, *next, *head; @@ -214,6 +317,9 @@ void remove_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) lock_orphan_inodes(cm_i); head = &cm_i->orphan_inode_list; + /** + * 遍历当前孤立节点链表的inode号,如果等于要删除的节点的inode号,则释放该孤立点所占据的空间,同时孤立节点数减一 + */ list_for_each_safe(this, next, head) { orphan = list_entry(this, struct orphan_inode_entry, list); if (orphan->ino == ino) { @@ -226,7 +332,19 @@ void remove_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) } unlock_orphan_inodes(cm_i); } - +/** + *cc7 check_orphan_space:如果当前检查点管理器下孤立点所占空间是否大于最大孤立点空间 + *@sbi:指向当前版本下超级块信息的实例 + *@return:,如果是,则返回错误信息 + */ +/** + * recycle_version_number:回收当前的版本号 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 错误标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int check_orphan_space(struct hmfs_sb_info *sbi) { struct hmfs_cm_info *cm_i = CM_I(sbi); @@ -239,7 +357,21 @@ int check_orphan_space(struct hmfs_sb_info *sbi) unlock_orphan_inodes(cm_i); return err; } - +/** + *cc8 sync_checkpoint_info:用给定检查点的版本信息和NAT树的根节点信息更新当前检查点信息 + *@sbi:指向当前版本下超级块信息的实例 + *@hmfs_cp:指向整个超级块的全局检查点的指针实例 + *@cp:指向当前版本下检查点的信息实例 + */ +/** + * sync_checkpoint_info:用给定检查点的版本信息和NAT树的根节点信息更新当前检查点信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] hmfs_cp:指向整个超级块的全局检查点的指针实例 + * @param[in] cp:指向当前版本下检查点的信息实例 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void sync_checkpoint_info(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *hmfs_cp, struct checkpoint_info *cp) @@ -248,7 +380,18 @@ static void sync_checkpoint_info(struct hmfs_sb_info *sbi, cp->nat_root = ADDR(sbi, le64_to_cpu(hmfs_cp->nat_addr)); cp->cp = hmfs_cp; } - +/** + *cc9 move_to_next_checkpoint:将新的检查点插入到CP树中 + *@sbi:指向当前版本下超级块信息的实例 + */ +/** + * move_to_next_checkpoint(struct hmfs_sb_info *sbi,struct hmfs_checkpoint *prev_checkpoint) + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] prev_checkpoint:前一个检查点 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void move_to_next_checkpoint(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *prev_checkpoint) { @@ -256,6 +399,9 @@ static void move_to_next_checkpoint(struct hmfs_sb_info *sbi, lock_cp_tree(cm_i); + /** + *用给出的前一个检查点的信息更新当前检查点管理器的信息,插入新的版本号给当前检查点下的CP树的根节点,同时将当前检查点插入到CP树中 + */ sync_checkpoint_info(sbi, prev_checkpoint, cm_i->cur_cp_i); radix_tree_insert(&cm_i->cp_tree_root, cm_i->new_version, cm_i->cur_cp_i); @@ -276,7 +422,21 @@ static void move_to_next_checkpoint(struct hmfs_sb_info *sbi, unlock_cp_tree(cm_i); } - +/** + *cc10 get_next_checkpoint_info:从当前CP树种得到下一个检查点的信息 + *@sbi:指向当前版本下超级块信息的实例 + *@cp:指向当前版本下检查点的信息实例 + *@return:返回下一个检查点的实例 + */ +/** + * checkpoint_info *get_next_checkpoint_info(struct hmfs_sb_info *sbi,struct checkpoint_info *cp_i) + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] cp_i:检查点信息 + * @return 指向下一个检查点信息的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ struct checkpoint_info *get_next_checkpoint_info(struct hmfs_sb_info *sbi, struct checkpoint_info *cp_i) { @@ -286,6 +446,9 @@ struct checkpoint_info *get_next_checkpoint_info(struct hmfs_sb_info *sbi, struct checkpoint_info *next_cp_i; struct hmfs_cm_info *cm_i = CM_I(sbi); + /** + *找到当前检查点的下一个检查点的版本号是否与当前检查点树的根节点相同 + */ this_cp = cp_i->cp; next_addr = le64_to_cpu(this_cp->next_cp_addr); next_cp = ADDR(sbi, next_addr); @@ -300,6 +463,9 @@ struct checkpoint_info *get_next_checkpoint_info(struct hmfs_sb_info *sbi, goto retry; } + /** + *找到下一个版本号信息后相应地更新检查点信息,同时加入到CP树中,并且将下一个检查点的版本号插入到CP树中 + */ sync_checkpoint_info(sbi, next_cp, next_cp_i); //TODO: sort cp_i according to version list_add(&next_cp_i->list, &cm_i->last_cp_i->list); @@ -313,6 +479,21 @@ struct checkpoint_info *get_next_checkpoint_info(struct hmfs_sb_info *sbi, * no_fail: If checkpoint with version is miss, return the checkpoint * whose version is slightly greater than version */ +/** + *cc11 get_checkpoint_info:如果不能给定版本的检查点,即视为丢失,则返回版本号距离跟定版本号最近的检查点 + *@sbi:指向当前版本下超级块信息的实例 + *@version:版本号 + *@no_fail:是否找到给定版本的检查点 + */ +/** + * get_checkpoint_info:如果不能给定版本的检查点,即视为丢失,则返回版本号距离跟定版本号最近的检查点 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] no_fail:失败标志 + * @return 指向下一个检查点信息的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ struct checkpoint_info *get_checkpoint_info(struct hmfs_sb_info *sbi, ver_t version, bool no_fail) { @@ -322,6 +503,9 @@ struct checkpoint_info *get_checkpoint_info(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *hmfs_cp; block_t next_addr; + /** + * 返回当前最新的检查点信息,并且在CP树种查找给定版本号的检查点,如果没找到,就把上一个检查点的信息赋值给它 + */ if (version == cm_i->new_version) return cm_i->cur_cp_i; @@ -331,6 +515,9 @@ struct checkpoint_info *get_checkpoint_info(struct hmfs_sb_info *sbi, cp_i = cm_i->last_cp_i; hmfs_bug_on(sbi, version > cp_i->version); + /** + * 如果当前的检查点的版本号丢失了,则找到改离该检查点最近的检查点信息,并且把其版本号赋值给丢失的版本号 + */ head = &cp_i->list; /* Search a checkpoint_info whose version is closest to given version */ cp_i = NULL; @@ -357,6 +544,9 @@ struct checkpoint_info *get_checkpoint_info(struct hmfs_sb_info *sbi, goto retry; } + /** + *同步下一个检查点及其entry信息,同时根据entry信息添加版本号到CP树 + */ sync_checkpoint_info(sbi, hmfs_cp, entry); list_add(&entry->list, &cm_i->last_cp_i->list); @@ -375,14 +565,32 @@ struct checkpoint_info *get_checkpoint_info(struct hmfs_sb_info *sbi, unlock_cp_tree(cm_i); return cp_i; } - +/** + *cc12 get_mnt_checkpoint:找到给出的版本号,并且返回其检查点所在的位置 + *@sbi:指向当前版本下超级块信息的实例 + *@cp:检查点实例 + *@version:版本号 + *@return:返回给定版本所在的检查点 + */ +/** + * get_mnt_checkpoint:找到给出的版本号,并且返回其检查点所在的位置 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] cp:检查点实例 + * @param[in] version:版本号 + * @return 指向下一个检查点信息的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static struct hmfs_checkpoint *get_mnt_checkpoint(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *cp, ver_t version) { struct hmfs_checkpoint *entry = cp; ver_t current_version; block_t addr; - + /** + *如果给出的版本号不等于下一个检查点中记录的版本号,就一直沿着当前版本号向下查找 + */ do { addr = le64_to_cpu(entry->next_cp_addr); entry = ADDR(sbi, addr); @@ -393,7 +601,17 @@ static struct hmfs_checkpoint *get_mnt_checkpoint(struct hmfs_sb_info *sbi, return entry; return NULL; } - +/** + *cc13 check_checkpoint_state:检查当前检查点的状态,并采取相应操作 + *@sbi:指向当前版本下超级块信息的实例 + */ +/** + * check_checkpoint_state:检查当前检查点的状态,并采取相应操作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void check_checkpoint_state(struct hmfs_sb_info *sbi) { struct hmfs_cm_info *cm_i = CM_I(sbi); @@ -402,6 +620,11 @@ void check_checkpoint_state(struct hmfs_sb_info *sbi) sbi->recovery_doing = 1; state = hmfs_cp->state; + /** + *根据上一个检查点的状态信息,如果是正常状态,什么都不做;如果是收集垃圾的状态, + *则根据当前状态和上一个检查点恢复上一次垃圾收集,如果是redo,则重做上一次检查点以来的检查点工作; + *如果是删除一个检查点状态,则重做删除检查点操作 + */ switch(state) { case HMFS_NONE: goto out; @@ -419,7 +642,18 @@ void check_checkpoint_state(struct hmfs_sb_info *sbi) out: sbi->recovery_doing = 0; } - +/** + *cc14 init_checkpoint_manager:初始化检查点管理器的各项信息 + *@sbi:指向当前版本下超级块信息的实例 + */ +/** + * init_checkpoint_manager:初始化检查点管理器的各项信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 初始化检查点管理器 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int init_checkpoint_manager(struct hmfs_sb_info *sbi) { struct hmfs_cm_info *cm_i; @@ -432,6 +666,9 @@ int init_checkpoint_manager(struct hmfs_sb_info *sbi) cp_addr = le64_to_cpu(super->cp_page_addr); hmfs_cp = ADDR(sbi, cp_addr); + /** + * 如果超级块信息中的ro-mount版本号与起始检查点的版本号不相符,则找到其版本号所在的检查点,如果找不到返回参数无效 + */ if (sbi->mnt_cp_version && sbi->mnt_cp_version != le32_to_cpu(hmfs_cp->checkpoint_ver)) { hmfs_cp = get_mnt_checkpoint(sbi, hmfs_cp, sbi->mnt_cp_version); @@ -446,12 +683,17 @@ int init_checkpoint_manager(struct hmfs_sb_info *sbi) } /* allocate and init last checkpoint_info */ + /** + *分配并且初始化上一次检查点的CP树链表信息 + */ cp_i = kmem_cache_alloc(cp_info_entry_slab, GFP_ATOMIC); if (!cp_i) { goto out_cp_i; } - + /** + *包括有效的inode,node,块数以及用户块数,用来初始化检查点管理器的信息,同时同步到检查点CP树 + */ cm_i->valid_inode_count = le32_to_cpu(hmfs_cp->valid_inode_count); cm_i->valid_node_count = le32_to_cpu(hmfs_cp->valid_node_count); cm_i->valid_block_count = le32_to_cpu(hmfs_cp->valid_block_count); @@ -470,6 +712,9 @@ int init_checkpoint_manager(struct hmfs_sb_info *sbi) unlock_cp_tree(cm_i); /* Allocate and Init current checkpoint_info */ + /** + *分配并且初始化当前的检查点树 + */ cp_i = kmem_cache_alloc(cp_info_entry_slab, GFP_KERNEL); INIT_LIST_HEAD(&cp_i->list); cm_i->new_version = next_checkpoint_ver(le32_to_cpu(hmfs_cp->checkpoint_ver)); @@ -489,12 +734,25 @@ int init_checkpoint_manager(struct hmfs_sb_info *sbi) out_cm_i: return -ENOMEM; } - +/** + * cc15 destroy_checkpoint_info:销毁处理删除链表的检查点信息 + *cm_i:检查点管理器的实例 + */ +/** + * destroy_checkpoint_info:销毁处理删除链表的检查点信息 + * @param[in] cm_i:检查点管理器的实例 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void destroy_checkpoint_info(struct hmfs_cm_info *cm_i) { struct checkpoint_info *cp_i = cm_i->last_cp_i, *entry; struct list_head *head, *this, *tmp; + /** + *删除处于移除链表队列的检查点entry,同时从CP树中删除其版本号, + */ head = &cp_i->list; list_for_each_safe(this, tmp, head) { entry = list_entry(this, struct checkpoint_info, list); @@ -507,7 +765,19 @@ static void destroy_checkpoint_info(struct hmfs_cm_info *cm_i) radix_tree_delete(&cm_i->cp_tree_root, cp_i->version); kmem_cache_free(cp_info_entry_slab, cm_i->cur_cp_i); } - +/** + *cc16 destroy_checkpoint_manager:销毁检查点管理器所占的空间并且释放其所占空间 + *@sbi:指向当前版本下超级块信息的实例 + *@return:成功返回0 + */ +/** + * destroy_checkpoint_manager:销毁检查点管理器所占的空间并且释放其所占空间 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 成功返回0 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int destroy_checkpoint_manager(struct hmfs_sb_info *sbi) { struct hmfs_cm_info *cm_i = sbi->cm_info; @@ -519,7 +789,17 @@ int destroy_checkpoint_manager(struct hmfs_sb_info *sbi) kfree(cm_i); return 0; } - +/** + *cc17 create_checkpoint_caches:创建检查点缓存实例 + *@return:成功返回0;出错返回超出内存 + */ +/** + * create_checkpoint_caches:创建检查点缓存实例 + * @return 返回错误标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int create_checkpoint_caches(void) { orphan_entry_slab = hmfs_kmem_cache_create("hmfs_orphan_entry", @@ -540,19 +820,41 @@ int create_checkpoint_caches(void) return -ENOMEM; } - +/** + *cc18 destroy_checkpoint_caches:释放孤立entry集合和检查点信息entry集合所占空间 + */ +/** + * destroy_checkpoint_caches:释放孤立entry集合和检查点信息entry集合所占空间 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void destroy_checkpoint_caches(void) { kmem_cache_destroy(orphan_entry_slab); kmem_cache_destroy(cp_info_entry_slab); } - +/** + *cc19 sync_dirty_inodes:同步处于链表中的脏的inode信息 + *@sbi:指向当前版本下超级块信息的实例 + *@return:成功返回0,失败返回错误标识 + */ +/** + * sync_dirty_inodes:同步处于链表中的脏的inode信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 成功返回0,失败返回错误标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int sync_dirty_inodes(struct hmfs_sb_info *sbi) { struct list_head *head, *this, *next; struct hmfs_inode_info *fi; int ret; - + /** + * 获取脏的inode链表的队头,并且从inode链表中写入脏的inode + */ head = &sbi->dirty_inodes_list; list_for_each_safe(this, next, head) { fi = list_entry(this, struct hmfs_inode_info, list); @@ -562,11 +864,26 @@ static int sync_dirty_inodes(struct hmfs_sb_info *sbi) } return 0; } - +/** + *cc20 block_operations: 对脏的inode块进行处理 + *@sbi:指向当前版本下超级块信息的实例 + *@return:成功返回0 + */ +/** + * block_operations: 对脏的inode块进行处理 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 同步脏的inode是否成功的标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int block_operations(struct hmfs_sb_info *sbi) { int ret = 0; + /** + *依次处理脏的inode链表上的块,并且同步脏的inode块的信息,如果成功,返回标识,依次进行处理 + */ retry: mutex_lock_all(sbi); @@ -580,7 +897,16 @@ static int block_operations(struct hmfs_sb_info *sbi) return 0; } - +/** + *cc21 unblock_operations:释放处于超级块环境中所有的mutex + */ +/** + * unblock_operations:释放处于超级块环境中所有的mutex + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void unblock_operations(struct hmfs_sb_info *sbi) { mutex_unlock_all(sbi); @@ -594,6 +920,19 @@ static void unblock_operations(struct hmfs_sb_info *sbi) * orphan blocks, we would write address to older checkpoint instead * of new checkpoint */ +/** + *cc22 flush_orphan_inodes: + *@sbi:指向当前版本下超级块信息的实例 + */ +/** + * flush_orphan_inodes:刷新孤立inode + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] orphan_addrs:孤立节点的位置 + * @return 返回是否成功标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int flush_orphan_inodes(struct hmfs_sb_info *sbi, block_t *orphan_addrs) { struct list_head *head, *this; @@ -610,6 +949,9 @@ static int flush_orphan_inodes(struct hmfs_sb_info *sbi, block_t *orphan_addrs) lock_orphan_inodes(cm_i); head = &cm_i->orphan_inode_list; list_for_each(this, head) { + /** + *找到孤立链表中的每一个inode点,并未它们分配新的块 + */ entry = list_entry(this, struct orphan_inode_entry, list); if (!orphan_addr) { orphan_block = alloc_new_node(sbi, 0, NULL, SUM_TYPE_CP, true); @@ -617,6 +959,9 @@ static int flush_orphan_inodes(struct hmfs_sb_info *sbi, block_t *orphan_addrs) ret = -ENOMEM; goto out; } + /** + *为每一个孤立块做相同的操作,找到孤立块的summary表,并为其更新最新的版本号 + */ orphan_addr = L_ADDR(sbi, orphan_block); summary = get_summary_by_addr(sbi, orphan_addr); make_summary_entry(summary, 0, cm_i->new_version, i, @@ -624,8 +969,8 @@ static int flush_orphan_inodes(struct hmfs_sb_info *sbi, block_t *orphan_addrs) orphan_addrs[i++] = orphan_addr; orphan_block = ADDR(sbi, orphan_addr); /* Reseverd for checkpoint address */ - orphan_block = (__le32 *)JUMP(orphan_block, sizeof(__le64)); end = (__le32 *)JUMP(orphan_block, HMFS_PAGE_SIZE); + orphan_block = (__le32 *)JUMP(orphan_block, sizeof(__le64)); } *orphan_block = cpu_to_le32(entry->ino); orphan_block++; @@ -638,7 +983,21 @@ static int flush_orphan_inodes(struct hmfs_sb_info *sbi, block_t *orphan_addrs) unlock_orphan_inodes(cm_i); return ret; } - +/** + * cc23 flush_orphan_inodes_finish:刷新回所有的孤立节点 + *@sbi:指向当前版本下超级块信息的实例 + *@orphan_addrs:所有孤立节点的集合 + *@cp_addr:检查点的地址 + */ +/** + * check_checkpoint_state:刷新回所有的孤立节点 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] orphan_addrs:所有孤立节点的集合 + * @param[in] cp_addr:检查点的地址 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void flush_orphan_inodes_finish(struct hmfs_sb_info *sbi, block_t *orphan_addrs, block_t cp_addr) { @@ -646,6 +1005,9 @@ static void flush_orphan_inodes_finish(struct hmfs_sb_info *sbi, __le64 *orphan_block; struct hmfs_checkpoint *hmfs_cp = ADDR(sbi, cp_addr); + /** + *依次遍历所有孤立节点的地址,并且将它们对应刷新回检查点下孤立节点集合中 + */ for (i = 0; i < NUM_ORPHAN_BLOCKS; ++i, orphan_addrs++) { if (*orphan_addrs) { orphan_block = ADDR(sbi, *orphan_addrs); @@ -655,7 +1017,19 @@ static void flush_orphan_inodes_finish(struct hmfs_sb_info *sbi, break; } } - +/** + *cc24 recover_orphan_inode:根据inode号获取inode,并且清零链表 + *@sbi:指向当前版本下超级块信息的实例 + *@ino:inode ID号 + */ +/** + * recover_orphan_inode:根据inode号获取inode,并且清零链表 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] ino:inode号 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void recover_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) { struct inode *inode = hmfs_iget(sbi->sb, ino); @@ -666,6 +1040,19 @@ static void recover_orphan_inode(struct hmfs_sb_info *sbi, nid_t ino) } /* Now we delete the orphan inodes */ +/** + *cc25 recover_orphan_inodes:根据当前超级块地址相应删除对应的孤立节点 + *@sbi:指向当前版本下超级块信息的实例 + *@return:成功返回0 + */ +/** + * check_checkpoint_state:检查当前检查点的状态,并采取相应操作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 成功返回0 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int recover_orphan_inodes(struct hmfs_sb_info *sbi) { int i; @@ -675,6 +1062,9 @@ int recover_orphan_inodes(struct hmfs_sb_info *sbi) nid_t ino; struct hmfs_checkpoint *hmfs_cp = CM_I(sbi)->last_cp_i->cp; + /** + *依次找到孤立节点地址中的每一个孤立块,并且删除相应的孤立节点 + */ for (i = 0; i < NUM_ORPHAN_BLOCKS; ++i) { orphan_addr = le64_to_cpu(hmfs_cp->orphan_addrs[i]); if (!orphan_addr) @@ -691,7 +1081,19 @@ int recover_orphan_inodes(struct hmfs_sb_info *sbi) return 0; } - +/** + *cc26 do_checkpoint: 进行相应地检查点备份工作 + *@sbi:指向当前版本下超级块信息的实例 + *@return:成功返回0 + */ +/** + * do_checkpoint: 进行相应地检查点备份工作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 成功返回0,失败错误标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int do_checkpoint(struct hmfs_sb_info *sbi) { struct hmfs_cm_info *cm_i = CM_I(sbi); @@ -713,6 +1115,9 @@ static int do_checkpoint(struct hmfs_sb_info *sbi) next_checkpoint = ADDR(sbi, le64_to_cpu(prev_checkpoint->next_cp_addr)); /* 1. set new cp block */ + /** + * 设置并分配新的检查点块,记录新的检查点版本号 + */ ret = flush_orphan_inodes(sbi, orphan_addrs); store_version = cm_i->new_version; @@ -722,19 +1127,26 @@ static int do_checkpoint(struct hmfs_sb_info *sbi) hmfs_dbg("\n"); return -ENOSPC; } - + /** + *根据检查点的地址相应地更新summary表中的版本号 + */ store_checkpoint_addr = L_ADDR(sbi, store_checkpoint); summary = get_summary_by_addr(sbi, store_checkpoint_addr); make_summary_entry(summary, 0, cm_i->new_version, 0, SUM_TYPE_CP); /* GC process should not update nat tree */ + /** + *垃圾收集过程中不应该更新NAT树 + */ nat_root = flush_nat_entries(sbi, store_checkpoint); if (IS_ERR(nat_root)) return PTR_ERR(nat_root); nat_root_addr = L_ADDR(sbi, nat_root); flush_orphan_inodes_finish(sbi, orphan_addrs, store_checkpoint_addr); - + /** + * 更新新的检查点的前后检查点信息和NAT根的信息,将检查点管理器中的有效inode数、块数、分配块数等信息更新会最新的检查点中 + */ store_checkpoint = ADDR(sbi, store_checkpoint_addr); store_checkpoint->next_cp_addr = prev_checkpoint->next_cp_addr; store_checkpoint->prev_cp_addr = next_checkpoint->prev_cp_addr; @@ -758,10 +1170,16 @@ static int do_checkpoint(struct hmfs_sb_info *sbi) set_struct(store_checkpoint, elapsed_time, get_mtime(sbi)); /* 2. flush SIT to cp */ + /** + * 刷新SIT信息回检查点中 + */ flush_sit_entries(sbi, store_checkpoint_addr, nat_root); set_summary_valid_bit(summary); /* 6. connect to super */ + /** + * 连接回超级块中 + */ hmfs_memcpy_atomic(&prev_checkpoint->next_cp_addr, &store_checkpoint_addr, 8); hmfs_memcpy_atomic(&next_checkpoint->prev_cp_addr, @@ -776,11 +1194,17 @@ static int do_checkpoint(struct hmfs_sb_info *sbi) hmfs_memcpy(raw_super, HMFS_RAW_SUPER(sbi), sizeof(struct hmfs_super_block)); /* clear last checkpoint state and logs */ + /** + *最后清楚上一个检查点状态及相应日志 + */ set_fs_state(prev_checkpoint, HMFS_NONE); if (prev_checkpoint->nr_gc_segs) prev_checkpoint->nr_gc_segs = 0; //FIXME: + /** + 对下一个检查点做类似炒作,并且释放空间 + */ migrate_mmap_block(sbi); move_to_next_checkpoint(sbi, store_checkpoint); @@ -788,16 +1212,33 @@ static int do_checkpoint(struct hmfs_sb_info *sbi) reinit_gc_logs(sbi); return 0; } - +/** + *cc27 write_checkpoint:对所有脏的inode进行检查点写的操作,返回要写入检查点的entry的数目 + *@sbi:指向当前版本下超级块信息的实例 + *@return:成功返回0 + */ +/** + * check_checkpoint_state:检查当前检查点的状态,并采取相应操作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] unlock:是否锁定标识 + * @return 是否对块处理成功标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int write_checkpoint(struct hmfs_sb_info *sbi, bool unlock) { struct sit_info *sit_i = SIT_I(sbi); int ret; - + /** + * 对所有脏的inode进行记录和信息同步处理 + */ ret = block_operations(sbi); if (ret) return ret; - + /** + *如果脏的entry的数目为0,则返回要写检查点的entry数为0 + */ if (!sit_i->dirty_sentries) { ret = 0; goto unlock; @@ -811,7 +1252,21 @@ int write_checkpoint(struct hmfs_sb_info *sbi, bool unlock) } return ret; } - +/** + *cc28 redo_checkpoint:根据前一个检查点的信息,重做上一次检查点的工作,以恢复系统 + *@sbi:指向当前版本下超级块信息的实例 + *@prev_cp:前一个检查点 + *@return:成功返回0 + */ +/** + * redo_checkpoint:根据前一个检查点的信息,重做上一次检查点的工作,以恢复系统 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] prev_cp:前一个检查点 + * @return 成功返回0 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int redo_checkpoint(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *prev_cp) { //XXX:after sbi initilization? @@ -825,6 +1280,9 @@ int redo_checkpoint(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *prev_cp) void *nat_root; /* 1. restore addr */ + /** + * 根据前一个检查点存储其地址,同时获取其所在的summary表,并且设置有效位 + */ store_cp_addr = le64_to_cpu(prev_cp->state_arg_2); store_cp = ADDR(sbi, store_cp_addr); @@ -835,14 +1293,23 @@ int redo_checkpoint(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *prev_cp) set_summary_valid_bit(summary); /* 2. flush cp-inlined SIT journal */ + /** + *根据前一个检查点重做之前SIT日志的记录工作 + */ recovery_sit_entries(sbi, prev_cp); /* 3. mark valid */ + /** + * 根据前一个检查点的版本记录当前版本,同时记录NAT表的根节点所在的块,并且根据当前环境下的NAT和检查点记录哪些块时有效的 + */ store_version = le32_to_cpu(store_cp->checkpoint_ver); nat_root = ADDR(sbi, le32_to_cpu(store_cp->nat_addr)); mark_block_valid(sbi, nat_root, store_cp); /* 4. connect to super */ + /** + * 记录下一个检查点,将检查点的信息写入超级块,并进行相应地校验 + */ next_cp = ADDR(sbi, le64_to_cpu(store_cp->next_cp_addr)); hmfs_memcpy_atomic(&prev_cp->next_cp_addr, &store_cp_addr, 8); hmfs_memcpy_atomic(&next_cp->prev_cp_addr, &store_cp_addr, 8); @@ -851,6 +1318,9 @@ int redo_checkpoint(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *prev_cp) set_struct(raw_super, checksum, sb_checksum); //TODO: memory barrier? + /** + *将当前检查点信息存入CP树中 + */ raw_super = next_super_block(raw_super); hmfs_memcpy(raw_super, ADDR(sbi, 0), sizeof(struct hmfs_super_block)); @@ -863,13 +1333,48 @@ int redo_checkpoint(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *prev_cp) } /* Clear summary bit and update SIT valid blocks */ +/** + *cc29 invalidate_block:根据块的summary表,清除有效位,更新SIT表的entry信息 + *@sbi:指向当前版本下超级块信息的实例 + *@addr:块的地址 + *@summary:块的summary表信息 + */ +/** + * invalidate_block:根据块的summary表,清除有效位,更新SIT表的entry信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] addr:块的地址 + * @param[in] summary:块的summary表信息 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void invalidate_block(struct hmfs_sb_info *sbi, block_t addr, struct hmfs_summary *summary) { clear_summary_valid_bit(summary); update_sit_entry(sbi, GET_SEGNO(sbi, addr), -1); } - +/** + *cc30 __delete_checkpoint:删除当前检查点信息,恢复上一个检查点的状态 + *@sbi:指向当前版本下超级块信息的实例 + *@cur_node:当前节点 + *@next_node:下一个节点 + *@prev_ver:以前的版本 + *@next_ver:下一个版本 + *@return:成功返回0,失败返回1 + */ +/** + * __delete_checkpoint:删除当前检查点信息,恢复上一个检查点的状态 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] cur_node:当前节点 + * @param[in] next_node:下一个节点 + * @param[in] prev_ver:以前的版本 + * @param[in] next_ver:下一个版本 + * @return 成功返回0,失败返回1 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, void *next_node, ver_t prev_ver, ver_t next_ver) { @@ -877,7 +1382,9 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, struct hmfs_summary *cur_sum, *next_sum; bool delete_this = false; int i; - + /** + *获取当前节点块的版本号,如果现在的版本号大于了以前的版本号,就给删除标识置为1 + */ cur_sum = get_summary_by_addr(sbi, L_ADDR(sbi, cur_node)); cur_node_ver = get_summary_start_version(cur_sum); if (!next_node) { @@ -890,6 +1397,10 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, next_node_ver = get_summary_start_version(next_sum); /* this block is COW */ + /** + *删除当前节点的版本号不等于下一个节点的版本号,且现在的版本号大于了以前的版本号,就给删除标识置为1 + *否则这如果没有任何先前的检查点指向了该块,下一个节点所在的版本号赋值给当前节点的版本号 + */ if (cur_node_ver != next_node_ver) { hmfs_bug_on(sbi, cur_node_ver > next_node_ver); /* Not any previous checkpoint refer to this block */ @@ -909,7 +1420,10 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, /* Invalidate this block */ invalidate_block(sbi, L_ADDR(sbi, cur_node), cur_sum); } - + /** + *获取当前块的summary表的类型,如果是NAT节点块,分别获取当前节点的地址传给孩子节点,和下一个节点的地址 + *删除当前NATnode块中所有孩子节点及其邻近节点 + */ switch (get_summary_type(cur_sum)) { case SUM_TYPE_NATN: { __le64 *cur_child, *next_child; @@ -928,7 +1442,9 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, } return 0; } - + /** + *如果是NAT的数据块,删除当前NAT数据块中所有孩子节点及其邻近节点 + */ case SUM_TYPE_NATD: { struct hmfs_nat_entry *cur_entry, *next_entry; void *cur_child, *next_child; @@ -948,7 +1464,9 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, } return 0; } - + /** + *如果是NATinode块,如果下一个nide不是inode,则基于前一个检查点,删除当前节点的孩子节点 + */ case SUM_TYPE_INODE: { struct hmfs_inode *cur_inode, *next_inode; void *cur_child, *next_child; @@ -966,6 +1484,9 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, next_inode = (struct hmfs_inode *)next_node; /* Delete extended data block */ + /** + *删除扩展的数据块 + */ for_each_xblock(cur_inode, xaddr, i) { if (!xaddr) continue; @@ -977,6 +1498,9 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, } /* Delete data blocks */ + /** + *删除数据块 + */ cur_db = cur_inode->i_addr; next_db = next_node ? next_inode->i_addr : NULL; for (i = 0; i < NORMAL_ADDRS_PER_INODE; i++, @@ -991,7 +1515,9 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, /* We don't need to handle nid. Because they are in NAT entry block, too */ } - + /** + *如果下一个node不是direct node,那么在下一个检查的中删除这个node,孩子节点也基于以前的检查点信息删除掉 + */ case SUM_TYPE_DN: { __le64 *cur_db, *next_db; struct direct_node *cur_dn, *next_dn; @@ -1034,7 +1560,21 @@ static int __delete_checkpoint(struct hmfs_sb_info *sbi, void *cur_node, return 1; } } - +/** + *cc31 do_delete_checkpoint:做删除检查点的操作 + *@sbi:指向当前版本下超级块信息的实例 + *@cur_addr:当前地址 + *@return:成功返回0,失败,返回错误标识 + */ +/** + * do_delete_checkpoint:做删除检查点的操作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] cur_addr:当前地址 + * @return 成功返回0,失败,返回错误标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int do_delete_checkpoint(struct hmfs_sb_info *sbi, block_t cur_addr) { struct hmfs_checkpoint *next_cp, *prev_cp, *last_cp, *cur_cp; @@ -1051,13 +1591,17 @@ static int do_delete_checkpoint(struct hmfs_sb_info *sbi, block_t cur_addr) next_cp = ADDR(sbi, le64_to_cpu(cur_cp->next_cp_addr)); prev_cp = ADDR(sbi, le64_to_cpu(cur_cp->prev_cp_addr)); last_cp = CM_I(sbi)->last_cp_i->cp; - + /** + * 如果只有1个有效的检查点,则返回出错信息 + */ if (cur_cp == prev_cp) { /* Only 1 valid checkpoint */ hmfs_bug_on(sbi, cur_cp != next_cp); return -ENODATA; } - + /** + *如果当前检查点等于上一个检查点,则删除最新的检查点 + */ if (cur_cp == last_cp) { /* We want to delete the newest checkpoint */ next_root = NULL; @@ -1066,7 +1610,9 @@ static int do_delete_checkpoint(struct hmfs_sb_info *sbi, block_t cur_addr) next_root = ADDR(sbi, le64_to_cpu(next_cp->nat_addr)); next_ver = le32_to_cpu(next_cp->checkpoint_ver); } - + /** + *如果当前检查点的前一个检查点等于超级块记录里的上一个检查点,则删除最旧的检查点 + */ if (prev_cp == last_cp) { /* We want to delete the oldest checkpoint */ prev_ver = HMFS_DEF_DEAD_VER; @@ -1082,6 +1628,9 @@ static int do_delete_checkpoint(struct hmfs_sb_info *sbi, block_t cur_addr) prev_ver, next_ver); /* Delete orphan blocks */ + /** + *删除孤立的块 + */ for (i = 0; i < NUM_ORPHAN_BLOCKS; i++) { if (!cur_cp->orphan_addrs[i]) break; @@ -1091,19 +1640,31 @@ static int do_delete_checkpoint(struct hmfs_sb_info *sbi, block_t cur_addr) } /* Delete checkpoint block */ + /** + *删除检查点所在的块 + */ summary = get_summary_by_addr(sbi, cur_addr); invalidate_block(sbi, cur_addr, summary); /* Set valid bit of deleted blocks */ + /** + *设置被删除块的有效位 + */ flush_sit_entries_rmcp(sbi); /* Link cp list */ + /** + *链接检查点所在的链表 + */ prev_addr = cur_cp->prev_cp_addr; next_addr = cur_cp->next_cp_addr; next_cp->prev_cp_addr = cur_cp->prev_cp_addr; prev_cp->next_cp_addr = cur_cp->next_cp_addr; /* If delete newest checkpoint, we should modify super block */ + /** + *如果删除了最新的检查点,应该修改超级块 + */ if (next_root == NULL) { set_fs_state(prev_cp, HMFS_NONE); raw_super = HMFS_RAW_SUPER(sbi); @@ -1116,16 +1677,34 @@ static int do_delete_checkpoint(struct hmfs_sb_info *sbi, block_t cur_addr) return 0; } - +/** + *cc32 delete_checkpoint:删除检查点,并返回标识 + *@sbi:指向当前版本下超级块信息的实例 + *@version:版本号 + *@return:如果成功,返回删除标识;如果失败,返回错误标识 + */ +/** + * delete_checkpoint:删除检查点,并返回标识 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] version:版本号 + * @return 如果成功,返回删除标识;如果失败,返回错误标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int delete_checkpoint(struct hmfs_sb_info *sbi, ver_t version) { struct checkpoint_info *del_cp_i = NULL; int ret = 0; - + /** + *获取checkpoint链表的信息,如果失败,返回错误标识 + */ del_cp_i = get_checkpoint_info(sbi, version, false); if (!del_cp_i) return -EINVAL; - + /** + *写检查点的对所有脏的entry所在的检查点做相应的删除工作 + */ lock_gc(sbi); ret = write_checkpoint(sbi, false); ret = do_delete_checkpoint(sbi, L_ADDR(sbi, del_cp_i->cp)); @@ -1133,7 +1712,19 @@ int delete_checkpoint(struct hmfs_sb_info *sbi, ver_t version) unlock_gc(sbi); return ret; } - +/** + *cc33 redo_delete_checkpoint:根据前一个检查点的状态信息,重做相应的删除检查点工作 + *@sbi:指向当前版本下超级块信息的实例 + *@return:如果成功,返回删除标识;如果失败,返回错误标识 + */ +/** + * redo_delete_checkpoint:根据前一个检查点的状态信息,重做相应的删除检查点工作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @return 如果成功,返回删除标识;如果失败,返回错误标识 + * @ref segment.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int redo_delete_checkpoint(struct hmfs_sb_info *sbi) { block_t cp_addr; diff --git a/fs/hmfs/data.c b/fs/hmfs/data.c index 57e9c105..8e3a9c3a 100644 --- a/fs/hmfs/data.c +++ b/fs/hmfs/data.c @@ -5,6 +5,11 @@ /* * return the last block index in current node/inode */ + /** + * 当前目录层次最后一个块块号 + * @block 当前目录所有的一个块块号 + * @level 当前层次 + */ static int get_end_blk_index(int block, int level) { int start_blk; @@ -16,7 +21,10 @@ static int get_end_blk_index(int block, int level) } return NORMAL_ADDRS_PER_INODE - 1; } - +/** + * 改变系统和inode的有效块数量 + * @count 改变的数量 + */ static bool inc_valid_block_count(struct hmfs_sb_info *sbi, struct inode *inode, int count) { @@ -52,6 +60,12 @@ static bool inc_valid_block_count(struct hmfs_sb_info *sbi, * -ALLOC_NODE: If node in the path is not exist, create it * -LOOKUP_NODE: If not exist, stop. */ + /** + * 获取数据块的dnode_of_data结构 + * @dn 所填充结构指针 + * @index 第index数据块 + * @mode ALLOC_NODE创建块 LOOK_UP只查询不创建 + */ int get_dnode_of_data(struct dnode_of_data *dn, int index, int mode) { struct hmfs_sb_info *sbi = HMFS_I_SB(dn->inode); @@ -143,6 +157,12 @@ int get_dnode_of_data(struct dnode_of_data *dn, int index, int mode) * @blocks: pointer buffer, data blocks address * @mode: read ahead mode */ + /** + * 获取inode的start到end的数据块地址 + * @blocks 数据块地址返回 + * @size 成功返回数据块个数 + + */ int get_data_blocks(struct inode *inode, int start, int end, void **blocks, int *size, int mode) { @@ -193,7 +213,9 @@ int get_data_blocks(struct inode *inode, int start, int end, void **blocks, } return err; } - +/** + * 为数据块设置hmfs_summary + */ static void setup_summary_of_new_data_block(struct hmfs_sb_info *sbi, block_t new_addr, unsigned int ino, unsigned int ofs_in_node) { @@ -210,6 +232,11 @@ static void setup_summary_of_new_data_block(struct hmfs_sb_info *sbi, * copy its data with range [start,start+size) to newly allocated * block */ + /** + * 申请一个数据块并拷贝[0,left],[right,pagesize]数据 + * @block 申请的数据块偏移 + * @fill_zero true 申请数据块清零 false 拷贝 + */ void *alloc_new_data_partial_block(struct inode *inode, int block, int left, int right, bool fill_zero) { @@ -285,7 +312,10 @@ void *alloc_new_data_partial_block(struct inode *inode, int block, int left, dn.ofs_in_node); return dest; } - +/** + * 为inode分配一个数据块 + * @block 数据块在总数据块中的偏移 + */ static void *__alloc_new_data_block(struct inode *inode, int block) { struct hmfs_sb_info *sbi = HMFS_I_SB(inode); @@ -351,7 +381,10 @@ static void *__alloc_new_data_block(struct inode *inode, int block) dn.ofs_in_node); return dest; } - +/** + * 分配一个数据块 + * @inode 可为NULL + */ void *alloc_new_data_block(struct hmfs_sb_info *sbi, struct inode *inode, int block) { @@ -371,6 +404,10 @@ void *alloc_new_data_block(struct hmfs_sb_info *sbi, struct inode *inode, * Return the extended block of inode * @x_tag: is the member offset base on start address of inode block */ + /** + * 分配一个数据块 拷贝inode偏移x_tag字节的块数据 + * @need_copy true 拷贝 false 清零 + */ void *alloc_new_x_block(struct inode *inode, int x_tag, bool need_copy) { struct hmfs_sb_info *sbi = HMFS_I_SB(inode); diff --git a/fs/hmfs/debug.c b/fs/hmfs/debug.c index f85e286c..f1cff467 100644 --- a/fs/hmfs/debug.c +++ b/fs/hmfs/debug.c @@ -41,7 +41,9 @@ static LIST_HEAD(hmfs_stat_list); static struct dentry *debugfs_root; static int hmfs_dispatch_cmd(struct hmfs_sb_info *, const char *cmd, int len); - +/** + * 更新文件系统的NAT统计信息 + */ void update_nat_stat(struct hmfs_sb_info *sbi, int flush_count) { struct hmfs_stat_info *stat_i = STAT_I(sbi); @@ -52,7 +54,9 @@ void update_nat_stat(struct hmfs_sb_info *sbi, int flush_count) stat_i->nr_flush_nat_per_block[div64_u64(flush_count, 50)]++; unlock_hmfs_stat(stat_i); } - +/** + * 打印文件系统相关信息 + */ static int stat_show(struct seq_file *s, void *v) { struct hmfs_stat_info *si = s->private; @@ -92,6 +96,8 @@ static int stat_show(struct seq_file *s, void *v) seq_printf(s, "main area range:%lu - %lu\n", (unsigned long)si->sbi->main_addr_start, (unsigned long)si->sbi->main_addr_end); + seq_printf(s, "GC Logs Segment Number:%lu\n", GET_SEGNO(si->sbi, + L_ADDR(si->sbi, si->sbi->gc_logs))); seq_printf(s, "max file size:%luk %luM %luG\n", max_file_size / 1024, max_file_size / 1024 / 1024, max_file_size / 1024 / 1024 / 1024); @@ -128,14 +134,32 @@ static int stat_show(struct seq_file *s, void *v) return 0; } +/** + * 获取指定segment的状态 + * @param[in] sbi 文件系统超级块 + * @param[in]i 段号 + */ +static char get_segment_state(struct hmfs_sb_info *sbi, seg_t i) +{ + struct free_segmap_info *free_i = FREE_I(sbi); + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + if (test_bit(i, dirty_i->dirty_segmap)) + return '*'; + else if (!test_bit(i, free_i->free_segmap)) + return '#'; + else if (test_bit(i, free_i->prefree_segmap)) + return '^'; + else return '@'; +} +/** + * 打印所有段状态信息 + */ static int vb_show(struct seq_file *s, void *v) { struct hmfs_stat_info *si = s->private; struct hmfs_sb_info *sbi = si->sbi; int i, j; - struct free_segmap_info *free_i = FREE_I(sbi); - struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); seq_printf(s, "# free\n* dirty\n^ prefree\n@ in use\n"); for (i = 0, j = 0; i < TOTAL_SEGS(sbi); i++, j++) { @@ -143,31 +167,27 @@ static int vb_show(struct seq_file *s, void *v) seq_printf(s, "\n"); j = 0; } - if (test_bit(i, dirty_i->dirty_segmap)) - seq_printf(s, "*"); - else if (!test_bit(i, free_i->free_segmap)) - seq_printf(s, "#"); - else if (test_bit(i, free_i->prefree_segmap)) - seq_printf(s, "^"); - else seq_printf(s, "@"); + seq_printf(s, "%c", get_segment_state(sbi, i)); } seq_printf(s, "\n"); for (i = 0; i < TOTAL_SEGS(sbi); i++) { - seq_printf(s, "%d:%d %lu\n", i, get_valid_blocks(sbi, i), - get_seg_vblocks_in_summary(sbi, i)); - hmfs_bug_on(sbi, get_valid_blocks(sbi, i) != - get_seg_vblocks_in_summary(sbi, i)); + seq_printf(s, "%d(%c):%d %lu\n", i, get_segment_state(sbi, i), + get_valid_blocks(sbi, i), get_seg_vblocks_in_summary(sbi, i)); } return 0; } - +/** + * seq_file的接口函数, 实现stat信息的查询 + */ static int stat_open(struct inode *inode, struct file *file) { return single_open(file, stat_show, inode->i_private); } - +/** + * seq_file的接口函数,实现段信息的查询 + */ static int vb_open(struct inode *inode, struct file *file) { return single_open(file, vb_show, inode->i_private); @@ -191,7 +211,13 @@ static int info_open(struct inode *inode, struct file *file) { return 0; } - +/** + * 从内核区往用户区读取debug文件 + * @param[in] file 读取的文件 + * @param[out] buffer 用户区读取缓存 + * @param[in] count 读取的大小 + * @param[in] ppos buffer的开始偏移 + */ static ssize_t info_read(struct file *file, char __user * buffer, size_t count, loff_t * ppos) { @@ -206,7 +232,7 @@ static ssize_t info_read(struct file *file, char __user * buffer, size_t count, if (count + *ppos > si->buf_size) count = si->buf_size - *ppos; - if (copy_to_user(buffer, si->buffer, count)) { + if (copy_to_user(buffer, si->buffer + *ppos, count)) { return -EFAULT; } @@ -215,6 +241,9 @@ static ssize_t info_read(struct file *file, char __user * buffer, size_t count, } //'buffer' being added "\n" at the tail automatically. +/** + *写debug文件 + */ static ssize_t info_write(struct file *file, const char __user * buffer, size_t count, loff_t * ppos) { @@ -245,7 +274,10 @@ struct file_operations info_fops = { .read = info_read, .write = info_write, }; - +/** + *为 hmfs_stat_info申请缓存空间 + *@param[in] c 缓存的大小 + */ static int hmfs_build_info(struct hmfs_sb_info *sbi, size_t c) { struct hmfs_stat_info *si = STAT_I(sbi); @@ -258,7 +290,9 @@ static int hmfs_build_info(struct hmfs_sb_info *sbi, size_t c) return -ENOMEM; return 0; } - +/** + * 释放 hmfs_stat_info申请的缓存 + */ static void hmfs_destroy_info(struct hmfs_sb_info *sbi) { struct hmfs_stat_info *si = STAT_I(sbi); @@ -268,7 +302,9 @@ static void hmfs_destroy_info(struct hmfs_sb_info *sbi) kfree(si->buffer); si->buffer = NULL; } - +/** + * 建立hmfs_stat_info结构 + */ int hmfs_build_stats(struct hmfs_sb_info *sbi) { struct hmfs_stat_info *si; @@ -306,7 +342,9 @@ int hmfs_build_stats(struct hmfs_sb_info *sbi) return 0; } - +/** + * 销毁hmfs_stat_info结构 + */ void hmfs_destroy_stats(struct hmfs_sb_info *sbi) { struct hmfs_stat_info *si = sbi->stat_info; @@ -318,12 +356,16 @@ void hmfs_destroy_stats(struct hmfs_sb_info *sbi) kfree(si); } - +/** + * 创建debug文件目录 + */ void hmfs_create_root_stat(void) { debugfs_root = debugfs_create_dir("hmfs", NULL); } - +/** + * 删除debug文件目录 + */ void hmfs_destroy_root_stat(void) { debugfs_remove_recursive(debugfs_root); @@ -336,6 +378,10 @@ void hmfs_destroy_root_stat(void) * @mode : 1 means appending, 0 will erase all data in the buffer. * @return : number of bytes written to file buffer */ +/** + *打印消息至hmfs_stat_info缓存中 + *@param[in] mode 0 擦除原有数据写 1接着原有数据写 + */ int hmfs_print(struct hmfs_stat_info *si, int mode, const char *fmt, ...) { size_t start, len; @@ -355,6 +401,10 @@ int hmfs_print(struct hmfs_stat_info *si, int mode, const char *fmt, ...) } //return how many bytes written to file buffer +/** + * 打印hmfs_checkpoint信息至hmfs_stat_info缓存中 + * @param[in] detail 0 只打印CP版本信息 1打印CP所有信息 + */ static int print_cp_one(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *cp, int detail) { @@ -410,7 +460,10 @@ static int print_cp_one(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *cp, } return len; } - +/** + * 打印第n个CP信息 + * @param[in] detail 0 只打印CP版本信息 1打印CP所有信息 + */ static int print_cp_nth(struct hmfs_sb_info *sbi, int n, int detail) { size_t i = 0; @@ -428,7 +481,10 @@ static int print_cp_nth(struct hmfs_sb_info *sbi, int n, int detail) } return print_cp_one(sbi, hmfs_cp, detail); } - +/** + * 打印所有CP信息 + * @param[in] detail 0 只打印CP版本信息 1打印CP所有信息 + */ static int print_cp_all(struct hmfs_sb_info *sbi, int detail) { size_t len = 0; @@ -457,6 +513,9 @@ static int print_cp_all(struct hmfs_sb_info *sbi, int detail) cp -- print this usage. set option 'd' 0 will not give the detail info, default is 1 */ +/** + * CP命令行解析函数 + */ static int hmfs_print_cp(struct hmfs_sb_info *sbi, int args, char argv[][MAX_ARG_LEN + 1]) { @@ -485,6 +544,10 @@ static int hmfs_print_cp(struct hmfs_sb_info *sbi, int args, * print_ssa_one -- dump a segment summary entry to file buffer. * @blk_idx : the index of summary block. */ +/** + * 打印块的SSA消息 + * @param[in] blk_addr块地址 + */ static size_t print_ssa_one(struct hmfs_sb_info *sbi, block_t blk_addr) { size_t len = 0; @@ -497,8 +560,7 @@ static size_t print_ssa_one(struct hmfs_sb_info *sbi, block_t blk_addr) } sum_entry = get_summary_by_addr(sbi, blk_addr); - - len += hmfs_print(si, 1, "-- [%016x] --\n", blk_addr >> HMFS_PAGE_SIZE_BITS); + len += hmfs_print(si, 1, "-- [%d %d] --\n", GET_SEGNO(sbi, blk_addr), GET_SEG_OFS(sbi, blk_addr)); len += hmfs_print(si, 1, " nid: %u\n", le32_to_cpu(sum_entry->nid)); len += hmfs_print(si, 1, " start_version: %u\n", le32_to_cpu(sum_entry->start_version)); @@ -509,7 +571,11 @@ static size_t print_ssa_one(struct hmfs_sb_info *sbi, block_t blk_addr) return len; } - +/** + * 打印范围数据块的SSA消息 + * @param[in] idx_from 起始数据块偏移 + * @param[in] idx_to 结束数据块偏移 + */ static int print_ssa_range(struct hmfs_sb_info *sbi, block_t idx_from, block_t idx_to) { @@ -525,7 +591,10 @@ static int print_ssa_range(struct hmfs_sb_info *sbi, block_t idx_from, } return len; } - +/** + * 打印segment中所有块的SSA + * @param[in] segno segment号 + */ static size_t print_ssa_per_seg(struct hmfs_sb_info *sbi, block_t segno) { block_t idx_from = segno << HMFS_PAGE_PER_SEG_BITS; @@ -537,6 +606,9 @@ static size_t print_ssa_per_seg(struct hmfs_sb_info *sbi, block_t segno) ssa -- dump summary of [idx1, idx2]th block ssa -- dump summary of all blocks in [segno]th segment */ +/** + * 打印ssa的命令行解析函数 + */ static int hmfs_print_ssa(struct hmfs_sb_info *sbi, int args, char argv[][MAX_ARG_LEN + 1]) { @@ -560,19 +632,25 @@ static int hmfs_print_ssa(struct hmfs_sb_info *sbi, int args, len += cnt; return len; } - +/** + * 获取segment相对应sit中vblocks变量 + */ static inline int get_vblocks_from_sit(struct hmfs_sb_info *sbi, seg_t segno) { return __le16_to_cpu(get_sit_entry(sbi, segno)->vblocks); } - +/** + * 打印segment错误提示 + */ static inline int print_error_segment(struct hmfs_sb_info *sbi, seg_t segno, int sit_blk_cnt, int ssa_blk_cnt) { return hmfs_print(STAT_I(sbi), 1, "segment #%d *ERROR*, cnt in SIT: %d" "cnt in SSA: %d\n", segno, sit_blk_cnt, ssa_blk_cnt); } - +/** + *扫描所有segment的sit和其中块的ssa,统计两者有效块是否相等, 打印第一个出错的块或打印无错误 + */ static int hmfs_print_sit(struct hmfs_sb_info *sbi, int args, char argv[][MAX_ARG_LEN + 1]) { @@ -619,7 +697,9 @@ static int hmfs_print_data(struct hmfs_sb_info *sbi, int args, { return 0; } - +/** + * 检测块的SSA信息,并输出其与输入参数的不同 + */ static int hmfs_check_ssa(struct hmfs_sb_info *sbi, block_t cp_addr, block_t blk_addr, size_t h, size_t offset, block_t nid) @@ -668,7 +748,9 @@ static int hmfs_check_ssa(struct hmfs_sb_info *sbi, block_t cp_addr, return ret_val; } - +/** + * 遍历检查NAT树所有节点的SSA信息是否有错 + */ static int traverse_nat(struct hmfs_sb_info *sbi, block_t cp_addr, block_t root_addr, size_t h, block_t nid) { @@ -715,6 +797,9 @@ static int traverse_nat(struct hmfs_sb_info *sbi, block_t cp_addr, * check consistency of meta info on NVM. * @return: return the error code; 0, no error. */ +/** + * 打印所有cp信息,并检验其NAT树 + */ static int hmfs_consis(struct hmfs_sb_info *sbi) { int err = 0; @@ -757,6 +842,11 @@ static int hmfs_consis(struct hmfs_sb_info *sbi) #define IS_BLANK(ch) (' ' == (ch) || '\t' == (ch) || '\n' == (ch)) //return: < 0, error; else, args; +/** + *解析分解命令行指令 + *@param[in] len 指令长度 + *@param[out] argv 分解后的命令字符串 + */ static int hmfs_parse_cmd(const char *cmd, size_t len, char argv[][MAX_ARG_LEN + 1]) { @@ -799,6 +889,11 @@ static int hmfs_parse_cmd(const char *cmd, size_t len, * RETURN VALUE: * success with the length of written file buffer, else -EFAULT; */ +/** + * 根据不同的cmd命令调用不同的函数 + *@param[in] cmd 字符串命令 + *@param[in] len 字符串长度 + */ static int hmfs_dispatch_cmd(struct hmfs_sb_info *sbi, const char *cmd, int len) { diff --git a/fs/hmfs/dir.c b/fs/hmfs/dir.c index 0fa2399d..14841826 100644 --- a/fs/hmfs/dir.c +++ b/fs/hmfs/dir.c @@ -17,6 +17,9 @@ #include "hmfs.h" /* calculate how many blocks does a file have. */ +/** + * 计算一个inode有多少数据块 + */ static unsigned long dir_blocks(struct inode *inode) { return ((unsigned long long)(i_size_read(inode) + HMFS_PAGE_SIZE - 1)) @@ -24,6 +27,9 @@ static unsigned long dir_blocks(struct inode *inode) } /* calculate how many buckets in a level. */ +/** + *计算level层有多少buckets + */ static unsigned int dir_buckets(unsigned int level) { if (level < MAX_DIR_HASH_DEPTH / 2) @@ -33,6 +39,9 @@ static unsigned int dir_buckets(unsigned int level) } /* calculate the number of blocks in a bucket. */ +/** + * 计算level层bucket有多少数据块 + */ static unsigned int bucket_blocks(unsigned int level) { if (level < MAX_DIR_HASH_DEPTH / 2) @@ -62,7 +71,11 @@ static unsigned char hmfs_type_by_mode[S_IFMT >> S_SHIFT] = { [S_IFSOCK >> S_SHIFT] = HMFS_FT_SOCK, [S_IFLNK >> S_SHIFT] = HMFS_FT_SYMLINK, }; - +/** + *设置文件;类型 + *@param[in] de 文件的hmfs_dir_entry + *@param[in] mode 文件类型flag + */ static void set_de_type(struct hmfs_dir_entry *de, umode_t mode) { de->file_type = hmfs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; @@ -72,6 +85,11 @@ static void set_de_type(struct hmfs_dir_entry *de, umode_t mode) * Return a hmfs_dentry_block for writing. We should not call * alloc_new_data_block directly in case of dir might be an inline inode */ +/** + * 返回文件的目录数据结构 + * @param[in] dir vfs inode + * @param[in] old_bidx 数据块索引 + */ struct hmfs_dentry_block *get_dentry_block_for_write(struct inode *dir, int old_bidx) { @@ -90,7 +108,9 @@ struct hmfs_dentry_block *get_dentry_block_for_write(struct inode *dir, hmfs_dbg("%d\n",old_bidx); return alloc_new_data_block(sbi, dir, old_bidx); } - +/** + *计算level层的第idx个bucket的起始块偏移 + */ static unsigned long dir_block_index(unsigned int level, unsigned int idx) { unsigned long i; @@ -101,7 +121,10 @@ static unsigned long dir_block_index(unsigned int level, unsigned int idx) bidx += idx * bucket_blocks(level); return bidx; } - +/** + * 检测namelen 和namehash 与de中结构数据是否相同 + * @return 相同返回true,否则false + */ static bool early_match_name(size_t namelen, hmfs_hash_t namehash, struct hmfs_dir_entry *de) { @@ -113,7 +136,12 @@ static bool early_match_name(size_t namelen, hmfs_hash_t namehash, return true; } - +/** + *从目录中寻找hmfs_dir_entry + *@param[in] name 文件名哈希结构 + *@param[in] max_slots 目录中最大有效文件数 + *@param[in] d 内存目录结构指针 + */ static struct hmfs_dir_entry *find_target_dentry(struct qstr *name, int *max_slots, struct hmfs_dentry_ptr *d) { @@ -131,7 +159,7 @@ static struct hmfs_dir_entry *find_target_dentry(struct qstr *name, continue; } - de = &d->dentry[bit_pos]; + de = &d->den t ry[bit_pos]; if (early_match_name(name->len, namehash, de) && !memcmp(d->filename[bit_pos], name->name, name->len)) goto found; @@ -161,6 +189,12 @@ static struct hmfs_dir_entry *find_target_dentry(struct qstr *name, * @max_slots: the maximum index of slot to store dentry * @is_normal_inode: whether is a normal inode or inline inode */ +/** + * 从目录结构块中寻找hmfs_dir_entry + * @param[in] name 文件名哈希结构 + * @param[in] max_slots 目录块的最大有效文件数 + * @param[in] is_normal_inode 0 内联数据inode + */ static struct hmfs_dir_entry *find_in_block(struct hmfs_dentry_block *dentry_blk, struct qstr *name, int *max_slots, int is_normal_inode) { @@ -187,6 +221,14 @@ static struct hmfs_dir_entry *find_in_block(struct hmfs_dentry_block *dentry_blk * it's an inline inode, res_bidx should be -1 * @ofs_in_blk: return value, dentry offset in dentry data block(res_bidx) */ +/** + *在level层找文件,放回其hmfs_dir_entry + *@param[in] dir 搜索所在目录 + *@param[in] name 找的文件名 + *@param[in] namehash 找的文件名的hash + *@param[out] res_bidx 搜寻结果数据块在inode内的偏移 + *@param[out] ofs_in_blk 搜寻结果在数据块内的偏移 + */ static struct hmfs_dir_entry *find_in_level(struct inode *dir, unsigned int level, struct qstr *name, hmfs_hash_t namehash, int *res_bidx, int *ofs_in_blk) @@ -244,6 +286,13 @@ static struct hmfs_dir_entry *find_in_level(struct inode *dir, * It returns the block index and entry offset where the entry was found , * and the entry itself. And if it's an inline dir, bidx should be -1 */ +/** + * 从一个目录中找某文件名的hmfs_dir_entry + * @param[in] dir 目录inode + * @param[in] child 文件名 + * @param[out] bidx 返回数据块偏移量 + * @param[out] ofs_in_blk 返回数据块内偏移量 + */ struct hmfs_dir_entry *hmfs_find_entry(struct inode *dir, struct qstr *child, int *bidx, int *ofs_in_blk) { @@ -297,6 +346,9 @@ struct hmfs_dir_entry *hmfs_find_entry(struct inode *dir, struct qstr *child, * It's the first block of normal inode or the inline_content * of inline inode */ +/** + * 返回上级目录的hmfs_dir_entry + */ struct hmfs_dir_entry *hmfs_parent_dir(struct inode *dir) { struct hmfs_dir_entry *de = NULL; @@ -313,6 +365,12 @@ struct hmfs_dir_entry *hmfs_parent_dir(struct inode *dir) /* * de should be writable */ +/** + * 设置目录文件中的一个hmfs_dir_entry + * @param[in] dir 目录文件inode + * @param[in] de 设置的hmfs_dir_entry地址 + * @param[in] inode 设置文件的inode + */ void hmfs_set_link(struct inode *dir, struct hmfs_dir_entry *de, struct inode *inode) { @@ -321,14 +379,21 @@ void hmfs_set_link(struct inode *dir, struct hmfs_dir_entry *de, dir->i_mtime = dir->i_ctime = CURRENT_TIME; mark_inode_dirty(dir); } - +/** + * 设置inode的文件名 + * @param[in] name 要设置的文件名 + * @param[in] hi 要设置的hmfs_inode + */ static void init_dent_inode(const struct qstr *name, struct hmfs_inode *hi) { /* copy name info. to this inode page */ hi->i_namelen = cpu_to_le32(name->len); memcpy(hi->i_name, name->name, name->len); } - +/** + * 更新inode文件名 + * @param[in] name 更新后的文件名 + */ int update_dent_inode(struct inode *inode, const struct qstr *name) { struct super_block *sb = inode->i_sb; @@ -344,7 +409,12 @@ int update_dent_inode(struct inode *inode, const struct qstr *name) return 0; } - +/** + * 设置初始化(空的)目录文件 + * @param[in] inode 目录文件vfs inode + * @param[in] parent 上级目录 vfs inode + * @param[in] hmfs_dentry_ptr 内存目录结构 + */ static void do_make_empty_dir(struct inode *inode, struct inode *parent, struct hmfs_dentry_ptr *d) { @@ -368,7 +438,9 @@ static void do_make_empty_dir(struct inode *inode, struct inode *parent, test_and_set_bit_le(0, (void *)d->bitmap); test_and_set_bit_le(1, (void *)d->bitmap); } - +/** + *设置目录文件为空 + */ static int make_empty_dir(struct inode *inode, struct inode *parent, struct hmfs_node *hn) { @@ -384,7 +456,12 @@ static int make_empty_dir(struct inode *inode, struct inode *parent, return 0; } - +/** + * 初始化目录文件元数据 + * @param[in] inode 目录文件 vfs inode + * @param[in] dir 上层目录文件vfs inode + * @param[in] name 目录文件名 + */ static struct hmfs_node *init_inode_metadata(struct inode *inode, struct inode *dir, const struct qstr *name) { @@ -426,7 +503,9 @@ static struct hmfs_node *init_inode_metadata(struct inode *inode, struct inode * error: return ERR_PTR(err); } - +/** + * 更新inode父目录的元数据,设置flag,更新修改时间 + */ static void update_parent_metadata(struct inode *dir, struct inode *inode, unsigned int current_depth) { @@ -450,6 +529,12 @@ static void update_parent_metadata(struct inode *dir, struct inode *inode, } /* Test whether dir has enough space for new dentry */ +/** + *从位图中找连续slots个为0的段 + *@param[in] bitmap 位图 + *@param[in] slots 连续有效位数量 + *@param[in] max_slots 位图长度 + */ static int room_for_filename(const void *bitmap, int slots, int max_slots) { int bit_start = 0; @@ -472,7 +557,16 @@ static int room_for_filename(const void *bitmap, int slots, int max_slots) } /* Update dentry structure after adding a new dentry */ -static void hmfs_update_dentry(nid_t ino, umode_t mode, struct hmfs_dentry_ptr *d, +/** + * 给目录文件加一个hmfs_dir_entry + * @param[in] ino 新加文件的node_ID + * @param[in] mode 新加文件的模式 + * @param[in] name 新加文件的文件名 + * @param[in] name_hash 新加文件名的哈希码 + * @param[in] bit_pos 新加文件的位图位置 + */ + +static void hmfs_update_dentry(nid_t ino, umode_t mode, struct hmfs_dentr y_ptr *d, const struct qstr *name, hmfs_hash_t name_hash, unsigned int bit_pos) { @@ -494,6 +588,12 @@ static void hmfs_update_dentry(nid_t ino, umode_t mode, struct hmfs_dentry_ptr * * Caller should grab and release a rwsem by calling mutex_lock_op() and * mutex_unlock_op(). */ +/** + * 将文件加入目录,同时修改了inode和dir + * @param[in] dir 目录inode + * @param[in] inode 文件inode + * @param[in] name 文件名 + */ int __hmfs_add_link(struct inode *dir, const struct qstr *name, struct inode *inode) { @@ -626,7 +726,9 @@ int __hmfs_add_link(struct inode *dir, const struct qstr *name, } return err; } - +/** + * 减少inode引用数, 可能减少dir引用数,inode size清零 + */ void hmfs_drop_nlink(struct inode *dir, struct inode *inode, struct page *page) { if (S_ISDIR(inode->i_mode)) { @@ -650,6 +752,12 @@ void hmfs_drop_nlink(struct inode *dir, struct inode *inode, struct page *page) * @inode: vfs inode of entry * @bidx: block index of dentry_blk in dir */ +/** + * 从目录dir中删除文件inode + * 减少dir和inode的链接数, + * @param[in] dentry 删除文件hmfs_dir_dentry地址 + * @param[in] dentry_blk dentry所在块地址 + */ void hmfs_delete_entry(struct hmfs_dir_entry *dentry, struct hmfs_dentry_block *dentry_blk, struct inode *dir, struct inode *inode, int bidx) @@ -692,7 +800,6 @@ void hmfs_delete_entry(struct hmfs_dir_entry *dentry, /* Inline directory should never reach here */ hmfs_bug_on(sbi, is_inline_inode(dir)); - hmfs_dbg("%d\n",bidx); dir_i_size = i_size_read(dir); truncate_hole(dir, bidx, bidx + 1); if (dir_i_size >> HMFS_PAGE_SIZE_BITS == bidx + 1) { @@ -702,7 +809,10 @@ void hmfs_delete_entry(struct hmfs_dir_entry *dentry, } } } - +/** + * 检查目录是否为空 + * @return true 目录为空 false 目录非空 + */ bool hmfs_empty_dir(struct inode *dir) { unsigned long bidx; @@ -754,7 +864,9 @@ bool hmfs_empty_dir(struct inode *dir) } return true; } - +/** + * 填充dir_context + */ static bool hmfs_fill_dentries(struct hmfs_sb_info *sbi, struct dir_context *ctx, struct hmfs_dentry_ptr *d, unsigned int start_pos) { @@ -785,7 +897,10 @@ static bool hmfs_fill_dentries(struct hmfs_sb_info *sbi, struct dir_context *ctx } return false; } - +/** + * 显示目录下的所有文件 + * @param[in] file 目录文件 + */ static int hmfs_readdir(struct file *file, struct dir_context *ctx) { struct inode *inode = file_inode(file); diff --git a/fs/hmfs/file.c b/fs/hmfs/file.c index 71eeb991..5cb21a2a 100644 --- a/fs/hmfs/file.c +++ b/fs/hmfs/file.c @@ -30,16 +30,29 @@ #ifdef CONFIG_HMFS_FAST_READ static struct kmem_cache *ro_file_address_cachep; #endif - +/* + * 程威宇的注释 + */ static struct kmem_cache *mmap_block_slab; - +/** + * 返回块的起始地址 + * @param[in] i 地址数 + * @param[in] level 地址所处的层级,在inode中时为0 + * @return 当@level为0时(即数据地址直接存储在inode里时)返回0 否则返回除存储第@i个块地址的块以外,之前所有块里存储的地址总数 + */ static unsigned int start_block(unsigned int i, int level) { if (level) return i - ((i - NORMAL_ADDRS_PER_INODE) % ADDRS_PER_BLOCK); return 0; } - +/** + * 减小有效块数,将inode指向文件的占有块数减小count个,同时使sbi对应超级块占有的有效块数减小count个 + * @param[in] sbi 对应文件超级块信息 + * @param[in] inode 对应文件inode + * @param[in] count 减小的个数 + * @return 成功则返回0 + */ static int dec_valid_block_count(struct hmfs_sb_info *sbi, struct inode *inode, int count) { @@ -54,6 +67,12 @@ static int dec_valid_block_count(struct hmfs_sb_info *sbi, } /* Find the last index of data block which is meaningful*/ +/** + * 寻找某文件在一定范围内的最后一个有效块 + * @param[in] dir 指向对应文件 + * @param[in] end_blk 查找范围为@end_blk之前的所有块 + * @return 成功则返回0 + */ unsigned int hmfs_dir_seek_data_reverse(struct inode *dir, unsigned int end_blk) { struct dnode_of_data dn; @@ -106,6 +125,15 @@ unsigned int hmfs_dir_seek_data_reverse(struct inode *dir, unsigned int end_blk) * I think it's ok to seek hole or data but not to obtain a fs lock, * i.e. user could seek hole or data of file when fs is doing checkpoint */ +/** + *寻找文件中的非孔区域或孔区域的位置 + *@param[in] inode 对应文件 + *@param[in] end_blk 文件占用block数 + *@param[in] start_pos 开始搜索的位置相对于文件开头的偏移量 + *@param[in] type 为SEEK_HOLE时搜索孔位置,为SEEK_DATA时搜索非孔位置 + *@return 返回对应位置起始处相对于文件起始处的块偏移数 + */ + static unsigned int hmfs_file_seek_hole_data(struct inode *inode, unsigned int end_blk, unsigned int start_pos, char type) { @@ -163,7 +191,14 @@ static unsigned int hmfs_file_seek_hole_data(struct inode *inode, found: return start_blk + j < end_blk? start_blk + j : end_blk; } - +/** + * 读取文件,实现时先通过inode判断是否为inode内嵌文件,再分别通过不同过程进行读取 + * @param[in] filp 指向文件 + * @param[in] buf 指向缓冲区 + * @param[in] len 读取的长度 + * @param[in] ppos 指向读取位置的偏移量 + * @return 返回读取长度 + */ static ssize_t __hmfs_xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) { @@ -184,12 +219,17 @@ static ssize_t __hmfs_xip_file_read(struct file *filp, char __user *buf, error = PTR_ERR(inode_block); goto out; } - +/** + * 若读取位置加上长度不大于文件大小,则读取对应长度的内容 + * 否则只读取该位置之后的所有内容 + */ if (pos + len > isize) copied = isize - pos; else copied = len; - +/** + *将inode内嵌文件的指定位置和长度的内容加载到缓冲区 + */ if (__copy_to_user(buf, (__u8 *)inode_block->inline_content + pos, copied)) { copied = 0; @@ -203,12 +243,15 @@ static ssize_t __hmfs_xip_file_read(struct file *filp, char __user *buf, end_index = (isize - 1) >> HMFS_PAGE_SIZE_BITS; - /* + /** * nr : read length for this loop * offset : start inner-blk offset this loop * index : start inner-file blk number this loop * copied : read length so far */ + /** + *根据pos和len,计算出块索引和偏移量,再按块进行读取直到全部读取完 + */ do { unsigned long nr, left; void *xip_mem[1]; @@ -265,11 +308,22 @@ static ssize_t __hmfs_xip_file_read(struct file *filp, char __user *buf, } #ifdef CONFIG_HMFS_FAST_READ +/** + * 判断只读文件是否可快速读取 + * @param[in] addr_struct 指向该只读文件 + * @return 返回true表示可快速读取,否则不能 + */ static inline bool is_fast_read_file(struct ro_file_address *addr_struct) { return addr_struct && (addr_struct->magic == HMFS_SUPER_MAGIC); } - +/** + * 创建一存储只读文件地址的结构体 + * 该结构体存储于slab高速缓存中 + * @param[in] addr 结构体中文件起始地址 + * @param[in] count 结构体中计数 + * @return 返回结构体指针 + */ static struct ro_file_address *new_ro_file_address(void *addr, unsigned int count) { struct ro_file_address *addr_struct; @@ -283,13 +337,22 @@ static struct ro_file_address *new_ro_file_address(void *addr, unsigned int coun } return addr_struct; } - +/** + * 从slab高速缓存中释放只读文件地址结构体 + * @param[in] filp 指向该文件 + */ static void free_ro_file_address(struct file *filp) { kmem_cache_free(ro_file_address_cachep, filp->private_data); filp->private_data = NULL; } - +/** + * 重映射文件到VMALLOC区域,用于只读文件加快读取 + * @param[in] inode 指向文件 + * @param[in] pages 指向VMALLOC区域中对应文件块地址 + * @param[in] count 规定映射的文件数据块范围为count之前的块 + * @return 成功则返回0 + */ static int remap_file_range(struct inode *inode, struct page **pages, int count) { void **blocks_buf; @@ -331,10 +394,17 @@ static int remap_file_range(struct inode *inode, struct page **pages, int count) return err; } -/* +/** * Open file for hmfs, if it's a read-only file, then remap it into * VMALLOC area to accelerate reading */ +/** + * 打开文件 + * 若该文件为只读文件,则重映射到VMALLOC区域从而加快读取 + * @param[in] inode 指向文件inode + * @param[in] file 指向文件file结构体 + * @return 成功则返回0 + */ int hmfs_file_open(struct inode *inode, struct file *filp) { int ret; @@ -375,7 +445,14 @@ int hmfs_file_open(struct inode *inode, struct file *filp) kfree(pages); return 0; } - +/** + * 释放文件 + * 若为映射到VMALLOC区域中的文件还需释放对应缓存 + * 若inode标记为脏还需同步到存储介质 + * @param[in] inode 指向文件inode + * @param[in] file 指向文件file结构体 + * @return 成功则返回0 + */ static int hmfs_release_file(struct inode *inode, struct file *filp) { int ret = 0; @@ -404,7 +481,14 @@ static int hmfs_release_file(struct inode *inode, struct file *filp) return ret; } - +/** + * 读取映射到VMALLOC区域的只读文件 + * @param[in] filp 指向文件 + * @param[in] buf 指向缓冲区地址 + * @param[in] len为读取长度 + * @param[in] ppos指向读取区域偏移量 + * @return 返回读取长度 + */ static ssize_t hmfs_file_fast_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) { @@ -430,7 +514,15 @@ static ssize_t hmfs_file_fast_read(struct file *filp, char __user *buf, *ppos = *ppos + copied; return err ? err : copied - left; } - +/** + * 读取普通文件 + * 先判断是否为快速读取文件再分别调用相应函数进行读取 + * @param[in] filp 指向文件 + * @param[in] buf 指向缓冲区地址 + * @param[in] len为读取长度 + * @param[in] ppos指向读取区域偏移量 + * @return 返回读取长度 + */ static ssize_t hmfs_xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) { @@ -450,7 +542,11 @@ static ssize_t hmfs_xip_file_read(struct file *filp, char __user *buf, inode_read_unlock(filp->f_inode); return ret; } - +/** + * 初始化快速读取文件的地址缓存 + * 使全局变量ro_file_address_cachep等于对应slab缓冲区地址 + * @return 成功分配则返回0否则返回-ENOMEM + */ int init_ro_file_address_cache(void) { ro_file_address_cachep = hmfs_kmem_cache_create("hmfs_ro_address_cache", @@ -459,14 +555,27 @@ int init_ro_file_address_cache(void) return -ENOMEM; return 0; } - +/** + * 释放快速读取文件的地址缓存 + * 调用kmem_cache_destroy + * 释放全局变量ro_file_address_cachep在slab中的高速缓存 + */ void destroy_ro_file_address_cache(void) { kmem_cache_destroy(ro_file_address_cachep); } #else - +/** + * 读取filp指向文件的内容 + * 若文件长度为0则直接返回 + * 否则调用函数__hmfs_xip_file_read进行读取 + * @param[in] filp 指向文件 + * @param[in] buf 指向缓冲区地址 + * @param[in] len为读取长度 + * @param[in] ppos指向读取区域偏移量 + * @return 返回读取长度 + */ static ssize_t hmfs_xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) { @@ -482,12 +591,21 @@ static ssize_t hmfs_xip_file_read(struct file *filp, char __user *buf, mutex_unlock(&filp->f_inode->i_mutex); return ret; } - +/** + *直接调用通用的file_open函数 + */ int hmfs_file_open(struct inode *inode, struct file *filp) { return generic_file_open(inode, filp); } - +/** + * 释放文件 + * 并根据文件inode的flag标志判断inode是否为脏 + * 若为脏,将文件内容同步到介质上 + * @param[in] filp 指向文件file结构 + * @param[in] inode 指向文件inode + * @return 成功则返回0 + */ static int hmfs_release_file(struct inode *inode, struct file *filp) { int ret = 0; @@ -512,6 +630,18 @@ static int hmfs_release_file(struct inode *inode, struct file *filp) * filesystems. It just updates the file offset to the value specified by * @offset and @whence. */ +/** + * 重新定位读/写文件的偏移量 + * whence为SEEK_END时将新位置指定成从文件结尾开始的的一个偏移距离 + * whence为SEEK_CUR时将新位置指定成从当前文件位置开始的一个偏移距离 + * whence为SEEK_DATA时将新位置指定成下一个大于等于偏移量的非孔文件区域的起始处 + * whence为SEEK_HOLE时将新位置指定成下一个大于等于偏移量的孔区域的起始处 + * @param[in] file 指向目标文件 + * @param[in] offset 偏移量 + * @param[in] whence 指定偏移类型 + * @return 成功则返回0 + */ + loff_t hmfs_file_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file->f_mapping->host; @@ -522,6 +652,7 @@ loff_t hmfs_file_llseek(struct file *file, loff_t offset, int whence) mutex_lock(&inode->i_mutex); + /*文件占用的block数*/ end_blk = (eof + HMFS_PAGE_SIZE - 1) >> HMFS_PAGE_SIZE_BITS; switch (whence) { @@ -572,7 +703,16 @@ loff_t hmfs_file_llseek(struct file *file, loff_t offset, int whence) mutex_unlock(&inode->i_mutex); return ret; } - +/** + * 对filp指向文件进行写操作 + * 先进行各类访问、权限等的检查后调用__hmfs_xip_file_write进行写操作 + * @param[in] filp 指向文件 + * @param[in] buf 指向缓冲区地址 + * @param[in] count 为写的长度 + * @param[in] ppos 指向写的位置相对文件的偏移量 + * @param[in] pos 偏移量 + * @return 返回写的长度 + */ static ssize_t __hmfs_xip_file_write(struct file *filp, const char __user *buf, size_t count, loff_t pos, loff_t *ppos) { @@ -584,6 +724,11 @@ static ssize_t __hmfs_xip_file_write(struct file *filp, const char __user *buf, struct hmfs_inode *inode_block; if (is_inline_inode(inode)) { +/** + * 若写入之后的文件长度大于内嵌文件最大长度 + * 将文件由内嵌文件转化为普通文件 + * 并进行普通文件写 + */ if (pos + count > HMFS_INLINE_SIZE) { status = hmfs_convert_inline_inode(inode); if (status) { @@ -591,6 +736,10 @@ static ssize_t __hmfs_xip_file_write(struct file *filp, const char __user *buf, } goto normal_write; } +/** + * 否则分配新的inode block + * 并调用__copy_from_user_nocache将缓冲区内容写到内嵌文件对应位置 + */ inode_block = alloc_new_node(HMFS_I_SB(inode), inode->i_ino, inode, SUM_TYPE_INODE, false); if (IS_ERR(inode_block)) { @@ -620,7 +769,11 @@ static ssize_t __hmfs_xip_file_write(struct file *filp, const char __user *buf, bytes = HMFS_PAGE_SIZE - offset; if (bytes > count) bytes = count; - +/** + * 普通文件写 + * 分配新的数据块再调用__copy_from_user_nocache将缓冲区写到数据块对应位置 + * 根据偏移量offset和输入长度count,依次按块写直到全部写完 + */ xip_mem = alloc_new_data_block(sbi, inode, index); if (unlikely(IS_ERR(xip_mem))) { status = -ENOSPC; @@ -657,7 +810,16 @@ static ssize_t __hmfs_xip_file_write(struct file *filp, const char __user *buf, } return written ? written : status; } - +/** + * 对filp指向文件进行写操作 + * 先进行各类访问、权限等的检查后调用__hmfs_xip_file_write进行写操作 + * @param[in] filp 指向文件 + * @param[in] buf 指向缓冲区地址 + * @param[in] count 为写的长度 + * @param[in] ppos 指向写的位置相对文件的偏移量 + * @param[in] pos 偏移量 + * @return 返回写的长度 + */ ssize_t hmfs_xip_file_write(struct file * filp, const char __user * buf, size_t len, loff_t * ppos) { @@ -667,7 +829,9 @@ ssize_t hmfs_xip_file_write(struct file * filp, const char __user * buf, size_t count = 0, ret; loff_t pos; int ilock; - +/** + *检查缓冲区对应长度的内容是否能访问 + */ if (!access_ok(VERIFY_READ, buf, len)) { ret = -EFAULT; goto out_up; @@ -677,12 +841,17 @@ ssize_t hmfs_xip_file_write(struct file * filp, const char __user * buf, count = len; current->backing_dev_info = mapping->backing_dev_info; - +/** + * 边界检查,需要判断写入数据是否超界、小文件边界检查以及设备是否是read-only。 + * 如果超界,那么降低写入数据长度 + */ ret = generic_write_checks(filp, &pos, &count, S_ISBLK(inode->i_mode)); if (ret) goto out_backing; - +/** + * count为实际可以写入的数据长度,如果可以写入数据长度为0,直接结束 + */ if (count == 0) goto out_backing; @@ -713,6 +882,13 @@ ssize_t hmfs_xip_file_write(struct file * filp, const char __user * buf, } /* dn->node_block should be writable */ +/** + * 截断dn指向的direct node中的数据 + * 检查dn->ofs_in_node之后一共count个地址指向的块是否为最新版本,若不是则删除无效块 + * 再将删除后的有效块数量更新到inode和超级块中,并将inode标记为脏 + * @param[in] dn 指向direct node + * @param[in] count 地址计数 + */ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) { int nr_free = 0, ofs = dn->ofs_in_node; @@ -750,6 +926,7 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) new_node->i.i_addr[ofs] = NULL_ADDR; } + if (nr_free) { dec_valid_block_count(sbi, dn->inode, nr_free); mark_inode_dirty(dn->inode); @@ -763,6 +940,12 @@ int truncate_data_blocks_range(struct dnode_of_data *dn, int count) * addr in direct node. Instead, we set the address of direct node * in its parent indirect node to be NULL_ADDR */ +/** + * 截断dn指向的direct node中的数据 + * 检查dn->node_block中的每个地址指向的块是否为最新版本,若不是则删除无效块 + * 再将删除后的有效块数量更新到inode和超级块中,并将inode标记为脏 + * @param[in] dn 指向direct node + */ void truncate_data_blocks(struct dnode_of_data *dn) { struct direct_node *node_block = dn->node_block; @@ -782,7 +965,11 @@ void truncate_data_blocks(struct dnode_of_data *dn) mark_inode_dirty(dn->inode); } } - +/** + * 将文件某个偏移量from所对应块在from之后的内容清零(只清除该块内容) + * @param[in] inode 对应文件inode + * @param[in] from 对应在文件中的偏移量 + */ static void truncate_partial_data_page(struct inode *inode, block_t from) { unsigned offset = from & (HMFS_PAGE_SIZE - 1); @@ -793,7 +980,12 @@ static void truncate_partial_data_page(struct inode *inode, block_t from) HMFS_PAGE_SIZE, true); return; } - +/** + * 清除普通文件某个偏移量之后的全部内容 + * @param[in] inode 对应文件 + * @param[in] from 对应偏移量 + * @return 成功则返回0 + */ static int __truncate_blocks(struct inode *inode, block_t from) { struct dnode_of_data dn; @@ -823,12 +1015,23 @@ static int __truncate_blocks(struct inode *inode, block_t from) } free_next: +/** + * 先调用truncate_inode_blocks删除偏移量之后的所有块内容 + * 再调用truncate_partial_data_page删除偏移量所在的块在其之后的内容 + */ err = truncate_inode_blocks(inode, free_from); truncate_partial_data_page(inode, from); return err; } - +/** + * 清除文件某个偏移量之后的全部内容 + * 若为内嵌型文件直接在本函数处理 + * 否则调用__truncate_blocks处理普通文件 + * @param[in] inode 对应文件 + * @param[in] from 对应偏移量 + * @return 成功则返回0 + */ static int truncate_blocks(struct inode *inode, block_t from) { struct hmfs_inode *inode_block; @@ -845,7 +1048,11 @@ static int truncate_blocks(struct inode *inode, block_t from) return __truncate_blocks(inode, from); } - +/** + * 清除@inode对应文件在i_size之后的内容 + * 再修改i_mtime及i_ctime并将inode标记为脏 + * @param[in] inode 对应文件 + */ void hmfs_truncate(struct inode *inode) { if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) @@ -858,7 +1065,15 @@ void hmfs_truncate(struct inode *inode) } } - +/** + * 截断孔 + * 在inode指向文件的第start块与第end块之间截断出孔区域 + * 用于对可能占用多块的普通文件预分配空间 + * @param[in] inode 对应文件 + * @param[in] start 起始块 + * @param[in] end 终止块 + * @return 成功则返回0 + */ int truncate_hole(struct inode *inode, pgoff_t start, pgoff_t end) { pgoff_t index; @@ -877,7 +1092,14 @@ int truncate_hole(struct inode *inode, pgoff_t start, pgoff_t end) } return 0; } - +/** + * 填充零,即在inode指向文件第index个块偏移量为start处 + * 填充一长度为len的孔区域 + * @param[in] inode 指向文件 + * @param[in] index 块号 + * @param[in] len 孔长度 + * @return 成功则返回0 + */ static void fill_zero(struct inode *inode, pgoff_t index, loff_t start, loff_t len) { @@ -886,7 +1108,14 @@ static void fill_zero(struct inode *inode, pgoff_t index, loff_t start, alloc_new_data_partial_block(inode, index, start, start + len, true); } - +/** + * 打孔,对于inode指向文件在offset偏移量处增加一长度为len的孔 + * 用于fallocate函数预分配空间 + * @param[in] inode 指向文件 + * @param[in] offset 文件偏移量 + * @param[in] start 块偏移量 + * @param[in] len 孔长度 + */ static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode) { pgoff_t pg_start, pg_end; @@ -898,7 +1127,11 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode) pg_end = ((unsigned long long) offset + len) >> HMFS_PAGE_SIZE_BITS; off_start = offset & (HMFS_PAGE_SIZE - 1); off_end = (offset + len) & (HMFS_PAGE_SIZE - 1); - +/** + * 若为inode内嵌文件,且增加孔后长度仍符合内嵌文件,则不需打孔 + *(因inode内嵌文件创建时内容已经初始化为0) + * 否则若增加孔后长度大于内嵌文件限制,则转化文件类型为普通文件再打孔 + */ if (is_inline_inode(inode)) { if (offset + len > HMFS_INLINE_SIZE) { ret = hmfs_convert_inline_inode(inode); @@ -939,7 +1172,13 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode) return ret; } - +/** + * 扩展文件大小为@offset+@len,并将@inode的flag标记为FI_DIRTY_SIZE + * @param[in] inode 指向文件 + * @param[in] offset 文件偏移量 + * @param[in] len 字节长度 + * @return 成功则返回0 + */ static int expand_inode_data(struct inode *inode, loff_t offset, loff_t len, int mode) { @@ -996,7 +1235,14 @@ static int expand_inode_data(struct inode *inode, loff_t offset, loff_t len, return ret; } - +/** + * 使@pfn指向mmap的@inode文件第@index个页面在实际存储介质当中所在的块号 + * @param[in] inode 指向文件 + * @param[in] index 页面数 + * @param[out] pfn inode指针 + * @param[in] vm_type 若@vm_type为VM_WRITE则是创建第@index个页面,再使pfn指向其块号 + * @return 成功则返回0 + */ static int hmfs_get_mmap_block(struct inode *inode, pgoff_t index, unsigned long *pfn, int vm_type) { @@ -1029,7 +1275,11 @@ static int hmfs_get_mmap_block(struct inode *inode, pgoff_t index, out: return 0; } - +/** + * 释放@vma指向的vm_area_struct结构体中 + * 从vm_start到vm_end之间的虚拟内存对应的内存块 + * @param[in] vma 指向vm_area_struct结构体 + */ static void hmfs_filemap_close(struct vm_area_struct *vma) { struct address_space *mapping = vma->vm_file->f_mapping; @@ -1051,7 +1301,12 @@ static void hmfs_filemap_close(struct vm_area_struct *vma) pg_start++; } } - +/** + * 新建一个mmap块 + * 并将@mm,@vaddr,@pgoff赋值到其所在的hmfs_mmap_block结构体当中 + * 再将此结构体添加到@sbi的mmap_block_list中 + * @return 成功则返回0 + */ int add_mmap_block(struct hmfs_sb_info *sbi, struct mm_struct *mm, unsigned long vaddr, unsigned long pgoff) { @@ -1072,7 +1327,13 @@ int add_mmap_block(struct hmfs_sb_info *sbi, struct mm_struct *mm, unlock_mmap(sbi); return 0; } - +/** + * 移除mmap块 + * @param[in] sbi 存储对应超级块信息 + * @param[in] *mm 表示要移除的vm区域 + * @param[in] pgoff 表示要移除的块号 + * return 成功则返回0 + */ int remove_mmap_block(struct hmfs_sb_info *sbi, struct mm_struct *mm, unsigned long pgoff) { @@ -1091,7 +1352,11 @@ int remove_mmap_block(struct hmfs_sb_info *sbi, struct mm_struct *mm, unlock_mmap(sbi); return 0; } - +/** + * 移动mmap块 + * @param[in] sbi 对应超级块信息 + * @return 成功则返回0 + */ int migrate_mmap_block(struct hmfs_sb_info *sbi) { struct hmfs_mmap_block *entry; @@ -1120,7 +1385,12 @@ int migrate_mmap_block(struct hmfs_sb_info *sbi) unlock_mmap(sbi); return 0; } - +/** + * 返回文件映射错误信息 + * @param[in] vma 指向对应虚拟地址空间 + * @param[in] vmf 存储出错信息 + * @return 返回错误信息 + */ static int hmfs_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct address_space *mapping = vma->vm_file->f_mapping; @@ -1160,7 +1430,14 @@ static const struct vm_operations_struct hmfs_file_vm_ops = { .close = hmfs_filemap_close, .fault = hmfs_filemap_fault, }; - +/** + * 文件映射,将file指向文件映射到vma指向的地址空间 + * 修改文件访问信息 + * 设置vma的flag标志并将其操作指针指向hmfs_file_vm_ops + * @param[in] file 指向文件 + * @param[in] vma 指向地址空间 + * @return 成功则返回0 + */ static int hmfs_file_mmap(struct file *file, struct vm_area_struct *vma) { file_accessed(file); @@ -1168,7 +1445,14 @@ static int hmfs_file_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_ops = &hmfs_file_vm_ops; return 0; } - +/** + * 根据file指针同步文件 + * 若为只读文件不能同步直接返回 + * 否则根据inode状态是为FI_DIRTY_INODE还是FI_DIRTY_SIZE + * 分别选择对应函数同步inode信息 + * @param[in] file 指向文件 + * @return 正常结束则返回0 + */ int hmfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) { struct inode *inode = file->f_mapping->host; @@ -1195,6 +1479,14 @@ int hmfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) } /* Pre-allocate space for file from offset to offset + len */ +/** + * 预分配空间 + * @param[in] file 指向对应文件 + * @param[in] offset 为预分配空间的起始处 + * @param[in] len 为预分配的空间长度 + * @param[in] mode mode&FALLOC_FL_PUNCH_HOLE不为零时,调用punch_hole函数在对应位置处打孔,否则调用expand_inode_data函数直接增加文件大小 + * @return 成功时返回0 + */ static long hmfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { @@ -1228,7 +1520,11 @@ static long hmfs_fallocate(struct file *file, int mode, loff_t offset, #define HMFS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL)) #define HMFS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL) - +/** + * 对于@flags进行掩码处理 + * @param[in] mode 文件类型 + * @return mode对应目录文件时直接返回falgs,对应普通文件时返回flags & HMFS_REG_FLMASK,其他情况时返回flags & HMFS_OTHER_FLMASK + */ static inline __u32 hmfs_mask_flags(umode_t mode, __u32 flags) { if (S_ISDIR(mode)) @@ -1238,7 +1534,13 @@ static inline __u32 hmfs_mask_flags(umode_t mode, __u32 flags) else return flags & HMFS_OTHER_FLMASK; } - +/** + * 向设备发送或接收控制信息 + * @param[in] filp 指向设备文件标识符 + * @param[in] arg 指向用户空间目标地址 + * @param[in] cmd 为HMFS_IOC_GETFLAGS时,将i_flags中用户可见位发送到用户空间目标地址;为HMFS_IOC_SETFLAGS时,将用户空间目标地址的值复制到flags中;为HMFS_IOC_GETVERSION时,将i_generation发送到用户空间目标地址 + * @return 若不符合以上任何一种情况则返回-ENOTTY + */ long hmfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -1297,6 +1599,13 @@ long hmfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_COMPAT +/** + * hmfs_ioctl函数的兼容性包装函数 + * 向设备发送或接收控制信息 + * 调整@cmd的值再调用hmfs_ioctl发送或接收控制信息 + * @param[in] filp 指向设备文件标识符 + * @param[in] arg 指向用户空间目标地址 + */ long hmfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { @@ -1344,7 +1653,10 @@ const struct inode_operations hmfs_file_inode_operations = { .removexattr = generic_removexattr, #endif }; - +/** + * 创建slab高速缓存,使mmap_block_slab指向缓存 + * @return 成功返回0,失败返回-ENOMEM + */ int create_mmap_struct_cache(void) { mmap_block_slab = hmfs_kmem_cache_create("hmfs_mmap_block", @@ -1353,7 +1665,9 @@ int create_mmap_struct_cache(void) return -ENOMEM; return 0; } - +/** + * 销毁mmap_block_slab指向的slab高速缓存 + */ void destroy_mmap_struct_cache(void) { kmem_cache_destroy(mmap_block_slab); diff --git a/fs/hmfs/gc.c b/fs/hmfs/gc.c index ee2ad3c9..0aed0b38 100644 --- a/fs/hmfs/gc.c +++ b/fs/hmfs/gc.c @@ -12,21 +12,56 @@ /* * Setup arguments for GC and GC recovery */ +/* + *cc1 prepare_move_argument:为垃圾收集及垃圾收集的恢复设置并初始化参数 + *@arg:初始化参数实例 + *@sbi:指向超级块信息的指针实例 + *@mv_segno:段号 + *@mv_offset:偏移量 + *@sum:summary的地址参数 + *@type:段的数据类型 + */ +/** + * prepare_move_argument:为垃圾收集及垃圾收集的恢复设置并初始化参数 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] arg 初始化参数实例 + * @param[in] mv_segno 段号 + * @param[in] mv_offset 偏移量 + * @param[in] sum summary的地址参数 + * @param[in] type 段的数据类型 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void prepare_move_argument(struct gc_move_arg *arg, struct hmfs_sb_info *sbi, seg_t mv_segno, unsigned mv_offset, struct hmfs_summary *sum, int type) { + /** + * 根据summary获取起始版本号,初始化参数的开始版本,nodeid,起始偏移量 + */ arg->start_version = get_summary_start_version(sum); arg->nid = get_summary_nid(sum); arg->ofs_in_node = get_summary_offset(sum); + /** + * 根据超级块的段的偏移量计算当前偏移地址,初始化参数中的指针所指向的地址 + */ arg->src_addr = __cal_page_addr(sbi, mv_segno, mv_offset); arg->src = ADDR(sbi, arg->src_addr); - + /** + * 根据起始版本信息,获取检查点信息 + */ arg->cp_i = get_checkpoint_info(sbi, arg->start_version, true); + /** + * 判断是否需要进行修复 + */ if (sbi->recovery_doing) return; + /** + * 目标指针指向分配的新的数据块和节点的空间 + */ if (type == TYPE_DATA) { arg->dest = alloc_new_data_block(sbi, NULL, 0); } else { @@ -35,25 +70,52 @@ void prepare_move_argument(struct gc_move_arg *arg, hmfs_bug_on(sbi, IS_ERR(arg->dest)); + /** + *地址转换后返回目的地址,根据地址返回目的summary表 + */ arg->dest_addr = L_ADDR(sbi, arg->dest); arg->dest_sum = get_summary_by_addr(sbi, arg->dest_addr); + /** + * 将数据从源地址复制到目的地址 + */ hmfs_memcpy(arg->dest, arg->src, HMFS_PAGE_SIZE); } +/* + *2cc get_cb_cost:返回得到回收当前SIT中段的时间开销 + *@sbi:指向超级块信息的指针实例 + *@segno:段号 + */ +/** + * get_cb_cost:返回得到回收当前SIT中段的时间开销 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] segno 段号 + * @return 返回值 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static unsigned int get_cb_cost(struct hmfs_sb_info *sbi, unsigned int segno) { + struct sit_info *sit_i = SIT_I(sbi); unsigned long long mtime = 0; unsigned int vblocks; unsigned char age = 0; unsigned char u; + /** + * 初始化段entry的修改时间和有效块的个数 + */ mtime = get_seg_entry(sbi, segno)->mtime; vblocks = get_seg_entry(sbi, segno)->valid_blocks; u = (vblocks * 100) >> HMFS_PAGE_PER_SEG_BITS; + /** + * 更新SIT表的最小和最大修改时间为最新,如果最小时间大于最大时间,则更新SIT表的age + */ if (mtime < sit_i->min_mtime) sit_i->min_mtime = mtime; if (mtime > sit_i->max_mtime) @@ -64,10 +126,27 @@ static unsigned int get_cb_cost(struct hmfs_sb_info *sbi, unsigned int segno) return UINT_MAX - ((100 * (100 - u) * age) / (100 + u)); } - +/* + * cc3 get_max_cost:返回要遍历的段的大小 + * @sbi:指向超级块信息的指针实例 + * @p:记录块回收的实例 + * @return:返回要遍历的段的大小 + */ +/** + * get_max_cost:返回要遍历的段的大小 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] p 记录块回收的实例 + * @return 返回要遍历的段的大小 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static unsigned int get_max_cost(struct hmfs_sb_info *sbi, struct victim_sel_policy *p) { + /** + *如果垃圾回收的类型是贪婪类型,则从头遍历段的大小,即2M的段大小 + */ if (p->gc_mode == GC_GREEDY) return HMFS_PAGE_PER_SEG; else if (p->gc_mode == GC_CB) @@ -75,7 +154,20 @@ static unsigned int get_max_cost(struct hmfs_sb_info *sbi, else return 0; } - +/* + *cc4 get_gc_cost:通过该段的入口地址返回有效的块的个数 + *@sbi:指向超级块信息的指针实例 + *@p:记录块回收的实例 + */ +/** + * get_gc_cost:通过该段的入口地址返回有效的块的个数 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] p 记录块回收的实例 + * @return 返回值 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static unsigned int get_gc_cost(struct hmfs_sb_info *sbi, unsigned int segno, struct victim_sel_policy *p) { @@ -92,8 +184,25 @@ static unsigned int get_gc_cost(struct hmfs_sb_info *sbi, unsigned int segno, * we take down the first victim segment as start_segno */ //TODO: We might need to collect many segments in one victim searching +/* + *cc5 get_victim: + *@sbi:指向超级块信息的指针实例 + *@gc_type:垃圾回收的类型 + */ +/** + * get_victim: + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] gc_type 垃圾回收的类型 + * @return 返回是否是被选中为回收段的标识 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int get_victim(struct hmfs_sb_info *sbi, seg_t *result, int gc_type) { + /** + *定义脏的段的实例,检查点的实例 + */ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct hmfs_checkpoint *hmfs_cp = CM_I(sbi)->last_cp_i->cp; struct victim_sel_policy p; @@ -102,18 +211,30 @@ static int get_victim(struct hmfs_sb_info *sbi, seg_t *result, int gc_type) seg_t segno; int nsearched = 0; int total_segs = TOTAL_SEGS(sbi); + /** + * 定义当前记录的日志信息中段的情况 + */ struct curseg_info *seg_i0 = &(CURSEG_I(sbi)[0]); struct curseg_info *seg_i1 = &(CURSEG_I(sbi)[1]); + /** + *判断得到当前垃圾回收的类型,根据上一次垃圾回收时victim类型返回当前偏移量,以及返回当前便利的段的开销 + */ p.gc_mode = gc_type == BG_GC ? GC_CB : GC_GREEDY; p.offset = sbi->last_victim[p.gc_mode]; p.min_segno = NULL_SEGNO; p.min_cost = max_cost = get_max_cost(sbi, &p); while (1) { + /** + *根据脏段的为题情况,偏移量等找到下一个脏的段 + */ segno = find_next_bit(dirty_i->dirty_segmap, total_segs, p.offset); if (segno >= total_segs) { + /** + *如果垃圾回收的类型是贪婪的,就更新偏移量和类型,否则遍历下一个段 + */ if (sbi->last_victim[p.gc_mode]) { sbi->last_victim[p.gc_mode] = 0; p.offset = 0; @@ -133,11 +254,17 @@ static int get_victim(struct hmfs_sb_info *sbi, seg_t *result, int gc_type) * It's not allowed to move node segment where last checkpoint * locate. Because we need to log GC segments in it. */ + /** + *不移动node段的信息,根据上一次检查点的位置 + */ if (segno == le32_to_cpu(hmfs_cp->cur_node_segno)) { continue; } /* Stop if we find a segment whose cost is small enough */ + /** + * 如果某段有效块的个数少于100,即开销很小,则对回收类型进行定义 + */ if (get_seg_entry(sbi, segno)->valid_blocks < NR_GC_MIN_BLOCK) { p.min_segno = segno; hmfs_dbg("Get victim:%lu vblocks:%d gc_type:%s\n", (unsigned long)segno, get_seg_entry(sbi, segno)->valid_blocks, @@ -147,6 +274,9 @@ static int get_victim(struct hmfs_sb_info *sbi, seg_t *result, int gc_type) cost = get_gc_cost(sbi, segno, &p); // hmfs_dbg("%lu %lu %s\n", (unsigned long)segno, cost, gc_type == BG_GC ? "BG" : "FG"); + /** + *如果当前开销低于记录的最低开销,则更新,并且寻找下一块 + */ if (p.min_cost > cost) { p.min_segno = segno; p.min_cost = cost; @@ -165,20 +295,53 @@ static int get_victim(struct hmfs_sb_info *sbi, seg_t *result, int gc_type) if (p.min_segno != NULL_SEGNO) { *result = p.min_segno; } - + /** + * 判断是否是空段。 + */ hmfs_dbg("Select %d\n", p.min_segno == NULL_SEGNO ? -1 : p.min_segno); return (p.min_segno == NULL_SEGNO) ? 0 : 1; } - +/* + *cc6 update_dest_summary:复制块 + *@src_sum:段中大小是4KB的块summary entry实例,作为源块 + *@dest_sum:段中大小是4KB的块summary entry实例,作为目的块 + */ +/** + * update_dest_summary:复制块 + * @param[in] src_sum:段中大小是4KB的块summary entry实例,作为源块 + * @param[in] dest_sum:段中大小是4KB的块summary entry实例,作为目的块 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void update_dest_summary(struct hmfs_summary *src_sum, struct hmfs_summary *dest_sum) { hmfs_memcpy(dest_sum, src_sum, sizeof(struct hmfs_summary)); } +/* + *cc7 move_data_block: + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号类型 + *@src_off: + *@src_sum:summary entry的实例 + */ +/** + * move_data_block:移动数据块 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] src_segno 源段号类型 + * @param[in] src_off 源地址 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void move_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { + /** + * 检查点管理器的实例 + */ struct gc_move_arg args; struct hmfs_node *last = NULL, *this = NULL; struct hmfs_summary *par_sum = NULL; @@ -187,24 +350,37 @@ static void move_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, block_t addr_in_par; int par_type; + /** + *根据summary入口信息获取版本信息,并且判断是否等于检查点管理器记录的最新版本 + */ is_current = get_summary_start_version(src_sum) == cm_i->new_version; /* 1. read summary of source blocks */ /* 2. move blocks */ + /** + *为垃圾回收准备参数 + */ prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_DATA); while (1) { /* 3. get the parent node which hold the pointer point to source node */ + /** + *得到指向段节点的node的父节点 + */ this = __get_node(sbi, args.cp_i, args.nid); par_sum = get_summary_by_addr(sbi, L_ADDR(sbi, this)); + /** + * 判断该节点是否已经被删除 + */ if (IS_ERR(this)) { /* the node(args.nid) has been deleted */ break; } + hmfs_dbg_on(get_summary_type(par_sum) != SUM_TYPE_INODE && get_summary_type(par_sum) != SUM_TYPE_DN, "Invalid summary type:" " nid(%u) Address(%p)[%lu %d] Version(%d) Type(%d)\n", args.nid, @@ -215,12 +391,18 @@ static void move_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, get_summary_type(par_sum) != SUM_TYPE_DN); /* Now the pointer contains in direct node have been changed last time */ + /** + *判断直接节点里的指针是否已经被修改了 + */ if (this == last) goto next; par_type = get_summary_type(par_sum); /* Now src data block has been COW or parent node has been removed */ + /** + *判断父节点的类型是否是inode的块 + */ if (par_type == SUM_TYPE_INODE) { addr_in_par = le64_to_cpu(this->i.i_addr[args.ofs_in_node]); } else { @@ -232,6 +414,9 @@ static void move_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, * now direct node or inode in laster checkpoint would never * refer to this data block */ + /** + *在正常的垃圾回收的过程中,如果父节点的块类型等于了源类型,就停止。因为后来的检查点中的直接节点和inode一定不会指向这个数据块 + */ if (addr_in_par != args.src_addr) break; @@ -241,6 +426,9 @@ static void move_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, * whose value is neither args.dest_addr nor args.src_addr. Therefore, * if recovery process, it would terminate in this checkpoint */ + /** + *如果系统崩溃了,在写地址的时候,i.i_addr和dn.addr都会是无效的,所以应该用原子写,因此,如果是恢复过程,在检查点钟将会终止 + */ if (par_type == SUM_TYPE_INODE) { hmfs_memcpy_atomic(&this->i.i_addr[args.ofs_in_node], &args.dest_addr, 8); @@ -253,6 +441,9 @@ static void move_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, next: /* cp_i is the lastest checkpoint, stop */ + /** + * 判断当前检查点是否是最新的检查点,如果是,则停止 + */ if (args.cp_i == cm_i->last_cp_i || is_current) { break; } @@ -260,9 +451,27 @@ static void move_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, } /* 5. Update summary infomation of dest block */ + /** + * 更新目标块的summary信息 + */ update_dest_summary(src_sum, args.dest_sum); } +/* + * cc8 recycle_segment:回收无效的段 + * @sbi:指向超级块信息的指针实例 + * @segno:段号类型 + * @none_valid:判断块是否无效 + */ +/** + * recycle_segment:回收无效的段 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] segno 段号类型 + * @param[in] none_valid 判断块是否无效 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void recycle_segment(struct hmfs_sb_info *sbi, seg_t segno, bool none_valid) { struct sit_info *sit_i = SIT_I(sbi); @@ -271,9 +480,15 @@ static void recycle_segment(struct hmfs_sb_info *sbi, seg_t segno, bool none_val struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct seg_entry *seg_entry; + /** + *根据SIT表信息先锁定入口 + */ lock_sentry(sit_i); /* clean dirty bit */ + /** + *根据SIT表中脏段的位图信息,清理脏的sentries,同时初始化有效的块数和时间 + */ if (!test_and_set_bit(segno, sit_i->dirty_sentries_bitmap)) { sit_i->dirty_sentries++; } @@ -284,9 +499,15 @@ static void recycle_segment(struct hmfs_sb_info *sbi, seg_t segno, bool none_val unlock_sentry(sit_i); /* clear dirty bit */ + /** + * 清理脏的比特 + */ if (!test_and_clear_bit(segno, dirty_i->dirty_segmap)) hmfs_bug_on(sbi, 1); + /** + * 如果是无效的块,锁定写的段位图,,遍历并清理所有空闲段的信息 + */ if (none_valid) { lock_write_segmap(free_i); if (test_and_clear_bit(segno, free_i->free_segmap)) { @@ -295,16 +516,37 @@ static void recycle_segment(struct hmfs_sb_info *sbi, seg_t segno, bool none_val unlock_write_segmap(free_i); } else { /* set prefree bit */ + /** + *测试所有无效块的空闲段信息 + */ if (test_and_set_bit(segno, free_i->prefree_segmap)) hmfs_bug_on(sbi, 1); } /* Now we have recycle HMFS_PAGE_PER_SEG blocks and update cm_i */ + /** + *现在根据检查点管理器清理每个段的中无效的段,同时更新检查点管理器 + */ lock_cm(cm_i); cm_i->alloc_block_count -= HMFS_PAGE_PER_SEG; unlock_cm(cm_i); } +/* + *cc 9 move_xdata_block:移动并更新数据块信息 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号类型 + *@src_sum:源summary信息 + */ +/** + * move_xdata_block:移动并更新数据块信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] src_segno:源段号类型 + * @param[in] src_sum:源summary信息 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void move_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -321,6 +563,9 @@ static void move_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, TYPE_DATA); while(1) { + /** + * 根据检查点和node id获取这个阶段,判断这个节点是否被删除了 + */ this = __get_node(sbi, arg.cp_i, arg.nid); if (IS_ERR(this)) @@ -335,10 +580,15 @@ static void move_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, x_tag = le64_to_cpu(XATTR_HDR(arg.src)->h_magic); addr_in_par = XBLOCK_ADDR(this, x_tag); + /** + *判断当前地址是否等于源地址 + */ if (addr_in_par != arg.src_addr) { break; } - + /** + *copy调至源类型 + */ hmfs_memcpy_atomic(JUMP(this, x_tag), &arg.dest_addr, 8); last = this; @@ -346,12 +596,31 @@ static void move_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, next: if (arg.cp_i == cm_i->last_cp_i || is_current) break; + /** + * 判断当前检查点是否等于下一个检查点 + */ arg.cp_i = get_next_checkpoint_info(sbi, arg.cp_i); } - + /** + *用目的summary信息更新源summary信息 + */ update_dest_summary(src_sum, arg.dest_sum); } - +/* + *cc10 move_node_block:移动node块信息 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号类型 + *@src_sum:源summary信息 + */ +/** + * move_node_block:移动node块信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] src_segno 源段号类型 + * @param[in] src_sum 源summary信息 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void move_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, unsigned int src_off, struct hmfs_summary *src_sum) { @@ -367,11 +636,17 @@ static void move_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, if (is_current) { //update NAT cache + /** + * 更新NAT缓存信息 + */ gc_update_nat_entry(NM_I(sbi), args.nid, args.dest_addr); return; } while (1) { + /** + *根据检查点的版本和node id获取NAT表的入口块信息 + */ this = get_nat_entry_block(sbi, args.cp_i->version, args.nid); if (IS_ERR(this)) break; @@ -381,6 +656,9 @@ static void move_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, addr_in_par = le64_to_cpu(this->entries[args.ofs_in_node].block_addr); /* Src node has been COW or removed */ + /** + *判断源节点是否已经删除 + */ if (addr_in_par != args.src_addr) { break; } @@ -390,6 +668,9 @@ static void move_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, last = this; next: + /** + *判断当前检查点是否和上一次的检查点相同 + */ if (args.cp_i == CM_I(sbi)->last_cp_i) break; args.cp_i = get_next_checkpoint_info(sbi, args.cp_i); @@ -397,7 +678,21 @@ static void move_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, update_dest_summary(src_sum, args.dest_sum); } - +/* + *cc11 move_nat_block:移动NAT块 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号类型 + *@src_sum:源summary信息 + */ +/** + * move_nat_block:移动NAT块 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] src_segno 源段号类型 + * @param[in] src_sum 源summary信息 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void move_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -411,6 +706,9 @@ static void move_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_of prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_NODE); while (1) { + /** + *根据节点ID判断是否为NAT表的根节点,如果是,更新检查点信息,如果不是,更新父节点信息,同时获取指向NAT表节点的实例 + */ if (IS_NAT_ROOT(args.nid)) this = args.cp_i->cp; else { @@ -423,6 +721,9 @@ static void move_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_of if (this == last) goto next; + /** + *判断是否是NAT表的根节点。判断是否是NAT表的根节点,同时更新检查点和父节点地址信息 + */ if (IS_NAT_ROOT(args.nid)) { hmfs_cp = HMFS_CHECKPOINT(this); addr_in_par = le64_to_cpu(hmfs_cp->nat_addr); @@ -434,6 +735,9 @@ static void move_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_of if (addr_in_par != args.src_addr) { break; } + /** + *写入地址信息到NAT节点表中 + */ if (IS_NAT_ROOT(args.nid)) { hmfs_memcpy_atomic(&hmfs_cp->nat_addr, &args.dest_addr, 8); @@ -454,6 +758,21 @@ static void move_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_of } /* Orphan blocks is not shared */ +/* + *cc12 move_orphan_block:移动孤立的块 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号类型 + *@src_sum:源summary信息 + */ +/** + * move_orphan_block:移动孤立的块 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] src_segno 源段号类型 + * @param[in] src_sum 源summary信息 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void move_orphan_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -462,15 +781,31 @@ static void move_orphan_block(struct hmfs_sb_info *sbi, seg_t src_segno, block_t cp_addr; prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_NODE); - hmfs_cp = args.cp_i->cp; - cp_addr = le64_to_cpu(hmfs_cp->orphan_addrs[get_summary_offset(src_sum)]); - hmfs_bug_on(sbi, cp_addr != L_ADDR(args.src)); + cp_addr = le64_to_cpu(*((__le64 *)args.src)); + /** + *初始化检查点的地址信息,以及孤立点的信息 + */ + hmfs_cp = ADDR(sbi, cp_addr); hmfs_cp->orphan_addrs[get_summary_offset(src_sum)] = cpu_to_le64(args.dest_addr); update_dest_summary(src_sum, args.dest_sum); } - +/* + *cc13 move_checkpoint_block:迁移检查点块 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号类型 + *@src_sum:源summary信息 + */ +/** + * move_checkpoint_block:迁移检查点块 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] src_segno 源段号类型 + * @param[in] src_sum 源summary信息 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void move_checkpoint_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -483,18 +818,30 @@ static void move_checkpoint_block(struct hmfs_sb_info *sbi, seg_t src_segno, prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_NODE); + /** + *获取当前检查点信息 + */ cp_i = get_checkpoint_info(sbi, args.start_version, false); hmfs_bug_on(sbi, !cp_i); this_cp = HMFS_CHECKPOINT(args.src); + /** + * 分别获取前一个和下一个检查点的地址,并用指针指向她们 + */ next_cp = ADDR(sbi, le64_to_cpu(this_cp->next_cp_addr)); prev_cp = ADDR(sbi, le64_to_cpu(this_cp->prev_cp_addr)); + /** + *将前后检查点的地址信息放入目标地址中 + */ hmfs_memcpy_atomic(&next_cp->prev_cp_addr, &args.dest_addr, 8); hmfs_memcpy_atomic(&prev_cp->next_cp_addr, &args.dest_addr, 8); cp_i->cp = HMFS_CHECKPOINT(args.dest); + /** + *遍历要在两个孤立块中写的地址,同时对孤立地址也写到目的地址中 + */ for (i = 0; i < NUM_ORPHAN_BLOCKS; i++) { orphan_addr = le64_to_cpu(this_cp->orphan_addrs[i]); if (orphan_addr == NULL_ADDR) @@ -506,43 +853,73 @@ static void move_checkpoint_block(struct hmfs_sb_info *sbi, seg_t src_segno, update_dest_summary(src_sum, args.dest_sum); } +/* + *cc14 garbage_collect:进行垃圾收集 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号类型 + *@segno:段号的类型 + */ +/** + * garbage_collect:进行垃圾收集 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] src_segno 源段号类型 + * @param[in] segno 段号的类型 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static void garbage_collect(struct hmfs_sb_info *sbi, seg_t segno) { int off = 0; struct hmfs_cm_info *cm_i = CM_I(sbi); bool is_current, none_valid; nid_t nid; + /** + *定义summary的块的实例 + */ struct hmfs_summary_block *sum_blk; struct hmfs_summary *sum; - int tmp=0; + /** + * 判断当前段中是否有有效块 + */ none_valid = !get_seg_entry(sbi, segno)->valid_blocks; if (none_valid) goto recycle; + /** + * 返回summary入口地址 + */ sum_blk = get_summary_block(sbi, segno); sum = sum_blk->entries; + //#ERROR: inconsistent of segno->valid_blocks for (off = 0; off < HMFS_PAGE_PER_SEG; ++off, sum++) { is_current = get_summary_start_version(sum) == cm_i->new_version; - + /* * We ignore two kinds of blocks: * - invalid blocks in older version * - newest blocks in newest version(checkpoint is not written) */ + /** + * 如果是旧版本的无效块,或者最新版本中最新的块(即检查点还未完成则不清理) + */ if (!get_summary_valid_bit(sum) && !is_current) continue; if (is_current) { nid = get_summary_nid(sum); - if (IS_ERR(get_node(sbi, nid))) + if (IS_ERR(get_node(sbi, nid))){ continue; + } } + /** + *根据summaryr入口地址的信息获取summary表的类型,并且在清理段之前作相应的转移工作,比如迁移有效的块和数据 + */ hmfs_bug_on(sbi, get_summary_valid_bit(sum) && is_current); - switch (get_summary_type(sum)) { case SUM_TYPE_DATA: move_data_block(sbi, segno, off, sum); @@ -552,18 +929,30 @@ static void garbage_collect(struct hmfs_sb_info *sbi, seg_t segno) break; case SUM_TYPE_INODE: case SUM_TYPE_DN: + /** + *如果是不直接的块进行节点迁移处理 + */ case SUM_TYPE_IDN: move_node_block(sbi, segno, off, sum); break; case SUM_TYPE_NATN: + /** + * 如果是NAT的数据块,也进行相应移动NAT块的处理 + */ case SUM_TYPE_NATD: hmfs_bug_on(sbi, is_current); move_nat_block(sbi, segno, off, sum); continue; + /** + *处理迁移孤立的块 + */ case SUM_TYPE_ORPHAN: hmfs_bug_on(sbi, is_current); move_orphan_block(sbi, segno, off, sum); continue; + /** + * 处理进行检查点迁移的块 + */ case SUM_TYPE_CP: hmfs_bug_on(sbi, is_current); move_checkpoint_block(sbi, segno, off, sum); @@ -574,11 +963,26 @@ static void garbage_collect(struct hmfs_sb_info *sbi, seg_t segno) } } - hmfs_dbg("tmp:%d\n",tmp); recycle: +/** + *回收无效的块 + */ recycle_segment(sbi, segno, none_valid); } - +/* + *cc15 hmfs_gc: + *@sbi:指向超级块信息的指针实例 + *@gc_type:垃圾回收的类型 + */ +/** + * hmfs_gc: 垃圾收集 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] gc_type:垃圾回收的类型 + * @return 返回写检查点标识 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) { int ret = -1; @@ -587,6 +991,9 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) bool do_cp = false; int total_segs = TOTAL_SEGS(sbi); int time_retry = 0; + /** + * 定义最大的要尝试回收的段数 + */ int max_retry = (total_segs + MAX_SEG_SEARCH - 1) / MAX_SEG_SEARCH; hmfs_dbg("Enter GC\n"); @@ -594,9 +1001,15 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) if (!(sbi->sb->s_flags & MS_ACTIVE)) goto out; + /** + *设置文件系统收集的类型 + */ if (hmfs_cp->state == HMFS_NONE) set_fs_state(hmfs_cp, HMFS_GC); + /** + * 处理垃圾收集的类型是BG或者没有足够的空闲的段 + */ if (gc_type == BG_GC && has_not_enough_free_segs(sbi)) { gc_type = FG_GC; } @@ -605,6 +1018,9 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) hmfs_dbg("Before get victim:%ld %ld %ld\n", (unsigned long)total_valid_blocks(sbi), (unsigned long)CM_I(sbi)->alloc_block_count, (unsigned long)CM_I(sbi)->valid_block_count); + /** + * 获取段里面victim的块 + */ if (!get_victim(sbi, &segno, gc_type)) goto out; ret = 0; @@ -617,6 +1033,9 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) * need to set it as PREFREE. And we could reuse it right now, which * could improve GC efficiency */ + /** + *根据段的入口块获取有效的块数,垃圾收集时的日志域加1,已经收集的段数也加1 + */ if (get_seg_entry(sbi, segno)->valid_blocks) { hmfs_memcpy_atomic(sbi->gc_logs, &segno, 4); sbi->gc_logs++; @@ -624,6 +1043,9 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) hmfs_memcpy_atomic(&hmfs_cp->nr_gc_segs, &sbi->nr_gc_segs, 4); } + /** + *统计当前超级块实例下每段中要进行垃圾收集的块数,并且收集它们 + */ COUNT_GC_BLOCKS(STAT_I(sbi), HMFS_PAGE_PER_SEG - get_valid_blocks(sbi, segno)); @@ -639,6 +1061,9 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) start_segno = segno; /* If space is limited, we might need to scan the whole NVM */ + /** + * 如果空间有限,则重新扫描整个NVM + */ if (need_deep_scan(sbi)) { do_cp = true; time_retry++; @@ -648,10 +1073,16 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) } /* In FG_GC, we atmost scan sbi->nr_max_fg_segs segments */ + /** + *在FG类型的垃圾收集总,最多扫描当前环境下一定数量的段 + */ if (has_not_enough_free_segs(sbi) && need_more_scan(sbi, segno, start_segno)) goto gc_more; out: + /** + *处理victim的段,进行检查点信息的设置 + */ if (do_cp) { ret= write_checkpoint(sbi, true); hmfs_bug_on(sbi, ret); @@ -664,7 +1095,19 @@ int hmfs_gc(struct hmfs_sb_info *sbi, int gc_type) (unsigned long)CM_I(sbi)->valid_block_count); return ret; } - +/** + * cc16 gc_thread_func:实时更新在超级块信息中垃圾回收进程的等待时间 + *@data:初始化当前超级块的信息 + *@return:成功,返回0 + */ +/** + * gc_thread_func:实时更新在超级块信息中垃圾回收进程的等待时间 + * @param[in] data:初始化当前超级块的信息 + * @return 返回0 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ static int gc_thread_func(void *data) { struct hmfs_sb_info *sbi = data; @@ -677,12 +1120,18 @@ static int gc_thread_func(void *data) if (try_to_freeze()) continue; else + /** + *如果超时或者条件满足时,就启动垃圾回收的进程 + */ wait_event_interruptible_timeout(*wq, kthread_should_stop(), msecs_to_jiffies(wait_ms)); if (kthread_should_stop()) break; + /** + * 如果当前超级块记录中空闲写的时间与记录不符合,则更新相应的垃圾回收最大睡眠时间 + */ if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) { wait_ms = sbi->gc_thread_max_sleep_time; continue; @@ -690,7 +1139,9 @@ static int gc_thread_func(void *data) if (!trylock_gc(sbi)) continue; - + /** + * 如果当前超级块记录中已经有了足够多无效的块,就可以释放等待时间,准备进行垃圾回收了 + */ if (has_enough_invalid_blocks(sbi)) wait_ms = decrease_sleep_time(sbi, wait_ms); else @@ -703,7 +1154,19 @@ static int gc_thread_func(void *data) } while (!kthread_should_stop()); return 0; } - +/** + * cc17 start_gc_thread: 开始处理垃圾回收进程时,先判断当前进程是否出错 + * @sbi:指向超级块信息的指针实例 + * @return:如果出错,返回错误标识 + */ +/** + * start_gc_thread:开始处理垃圾回收进程时,先判断当前进程是否出错 + * @param[in] sbi 指向超级块信息的指针实例 + * @return 如果出错,返回错误标识 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ int start_gc_thread(struct hmfs_sb_info *sbi) { struct hmfs_gc_kthread *gc_thread = NULL; @@ -721,11 +1184,17 @@ int start_gc_thread(struct hmfs_sb_info *sbi) goto out; } + /** + * 初始化垃圾回收进程的等待队列队头,同时初始化垃圾回收进程的回收任务 + */ sbi->gc_thread = gc_thread; init_waitqueue_head(&(sbi->gc_thread->gc_wait_queue_head)); sbi->gc_thread->hmfs_gc_task = kthread_run(gc_thread_func, sbi, "hmfs_gc-%lu:->%lu", start_addr, end_addr); + /** + *如果出错,释放当前进程 + */ if (IS_ERR(gc_thread->hmfs_gc_task)) { err = PTR_ERR(gc_thread->hmfs_gc_task); kfree(gc_thread); @@ -734,7 +1203,17 @@ int start_gc_thread(struct hmfs_sb_info *sbi) out: return err; } - +/** + * cc18 stop_gc_thread: 根据垃圾回收进程的任务信息,停止当前进程 + * @sbi:指向超级块信息的指针实例 + */ +/** + * stop_gc_thread: 根据垃圾回收进程的任务信息,停止当前进程 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void stop_gc_thread(struct hmfs_sb_info *sbi) { struct hmfs_gc_kthread *gc_thread = sbi->gc_thread; @@ -745,13 +1224,21 @@ void stop_gc_thread(struct hmfs_sb_info *sbi) sbi->gc_thread = NULL; } +/** + *cc19 init_gc_logs:初始化垃圾回收的日志信息 + * @sbi:指向超级块信息的指针实例 + * @return:返回是否能获取一个新的空闲段标识 + */ int init_gc_logs(struct hmfs_sb_info *sbi) { seg_t segno; int ret; block_t addr; struct hmfs_checkpoint *hmfs_cp = CM_I(sbi)->last_cp_i->cp; - + /** + * 判断是否能从超级块信息中获取一个新的空闲段,如果成功了该段用来记录垃圾回收的日志信息, + * + */ ret = get_new_segment(sbi, &segno); if (!ret) { addr = __cal_page_addr(sbi, segno, 0); @@ -765,6 +1252,18 @@ int init_gc_logs(struct hmfs_sb_info *sbi) } /* Must call move_to_next_checkpoint() before this function */ +/** + *cc20 reinit_gc_logs: 在最新的检查点中重新初始化垃圾回收的日志记录 + * @sbi:指向超级块信息的指针实例 + * + */ +/** + * reinit_gc_logs: 在最新的检查点中重新初始化垃圾回收的日志记录 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void reinit_gc_logs(struct hmfs_sb_info *sbi) { seg_t old_segno; @@ -780,6 +1279,10 @@ void reinit_gc_logs(struct hmfs_sb_info *sbi) * NVM area. And we have make a checkpoint now. We need to set gc_logs * and nr_gc_segs for new 'last checkpoint' */ + /** + * 如果不能从NVM的Main Area中获取新的空闲段,则清除旧的段号名,同时对新的空闲段加1,否则将垃圾回收 + * 的旧的日志信息和段号更新最新的检查点信息 + */ if (!init_gc_logs(sbi)) { lock_write_segmap(free_i); if (test_and_clear_bit(old_segno, free_i->free_segmap)) @@ -791,6 +1294,17 @@ void reinit_gc_logs(struct hmfs_sb_info *sbi) } } +/** + *cc20 init_gc_stat:强垃圾回收的回收信息清零 + *@sbi:指向超级块信息的指针实例 + */ +/** + * init_gc_stat:强垃圾回收的回收信息清零 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref gc.h,node.h,segment.h,xattr.h,hmfs.h,hmfs_fs.h + * @see + * @note + */ void init_gc_stat(struct hmfs_sb_info *sbi) { struct hmfs_stat_info *si = STAT_I(sbi); int i; diff --git a/fs/hmfs/hash.c b/fs/hmfs/hash.c index 9ae67cbc..9780316e 100644 --- a/fs/hmfs/hash.c +++ b/fs/hmfs/hash.c @@ -20,7 +20,11 @@ * Hashing code copied from ext3 */ #define DELTA 0x9E3779B9 - +/** + * TEA加密算法 + * @param[in] buf buf[0],buf[1] 明文 + * @param[in] in 秘钥 + */ static void TEA_transform(unsigned int buf[4], unsigned int const in[]) { __u32 sum = 0; @@ -37,7 +41,13 @@ static void TEA_transform(unsigned int buf[4], unsigned int const in[]) buf[0] += b0; buf[1] += b1; } - +/** + *字符串转int + *@param[in] msg 输入字符串 + *@param[in] size_t len 字符串长度 + *@param[in] buf 输出int数组 + *@param[in] num 输出缓冲区长度 + */ static void str2hashbuf(const unsigned char *msg, size_t len, unsigned int *buf, int num) { @@ -65,7 +75,9 @@ static void str2hashbuf(const unsigned char *msg, size_t len, while (--num >= 0) *buf++ = pad; } - +/** + *文件名哈希函数 + */ hmfs_hash_t hmfs_dentry_hash(const struct qstr *name_info) { __u32 hash; diff --git a/fs/hmfs/hmfs.h b/fs/hmfs/hmfs.h index 297dec59..45a8023b 100644 --- a/fs/hmfs/hmfs.h +++ b/fs/hmfs/hmfs.h @@ -287,6 +287,7 @@ struct hmfs_stat_info { * all the information are dedicated to a given direct node block determined * by the data offset in a file. */ +/*存储文件对应的direct node的ID,node地址,文件数据指针在node中的偏移量等*/ struct dnode_of_data { struct inode *inode; /* vfs inode pointer */ struct hmfs_inode *inode_block; /* its inode, NULL is possible */ @@ -337,7 +338,7 @@ static inline int check_nid_range(struct hmfs_sb_info *sbi, nid_t nid) return -EINVAL; return 0; } - +/*返回superblock指向的fs_info结构体*/ static inline struct hmfs_sb_info *HMFS_SB(struct super_block *sb) { return sb->s_fs_info; @@ -549,6 +550,7 @@ static inline void clear_inode_flag(struct hmfs_inode_info *fi, int flag) clear_bit(flag, &fi->flags); } +/*判断inode指向的文件是否为inode内嵌类型的文件*/ static inline bool is_inline_inode(struct inode *inode) { return is_inode_flag_set(HMFS_I(inode), FI_INLINE_DATA); diff --git a/fs/hmfs/inode.c b/fs/hmfs/inode.c index cc03c974..35cd47e7 100644 --- a/fs/hmfs/inode.c +++ b/fs/hmfs/inode.c @@ -5,7 +5,11 @@ struct backing_dev_info hmfs_backing_dev_info __read_mostly = { .ra_pages = 0, .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, }; - +/** + * 根据文件inode对应hmfs_inode_info结构体中的i_flags值 + * 来设置inode结构体中的i_flags值 + * @param[in] inode 指向要修改的文件inode + */ void hmfs_set_inode_flags(struct inode *inode) { unsigned int flags = HMFS_I(inode)->i_flags; @@ -24,7 +28,12 @@ void hmfs_set_inode_flags(struct inode *inode) if (flags & FS_DIRSYNC_FL) inode->i_flags |= S_DIRSYNC; } - +/** + * 将内联文件的inode转化为普通文件inode + * 并将原先的内嵌数据复制到新分配的数据块 + * @param[in] inode 指向要转化的文件inode + * @return 成功则返回0 + */ int hmfs_convert_inline_inode(struct inode *inode) { struct hmfs_inode *old_inode_block, *new_inode_block; @@ -64,7 +73,11 @@ int hmfs_convert_inline_inode(struct inode *inode) clear_inode_flag(HMFS_I(inode), FI_INLINE_DATA); return 0; } - +/** + * 将inode属性由NVM读取到DRAM中 + * @param[in] inode指向要读取的inode结构体 + * @return 成功则返回0 + */ static int do_read_inode(struct inode *inode) { struct hmfs_sb_info *sbi = HMFS_I_SB(inode); @@ -102,7 +115,11 @@ static int do_read_inode(struct inode *inode) fi->i_pino = le32_to_cpu(hi->i_pino); return 0; } - +/** + * 修改inode存储的i_size,并将其flag标记为FI_DIRTY_SIZE + * @param[in] inode 指向要修改的inode + * @param[in] size 表示要修改为的大小 + */ void mark_size_dirty(struct inode *inode, loff_t size) { struct hmfs_inode_info *hi = HMFS_I(inode); @@ -116,7 +133,12 @@ void mark_size_dirty(struct inode *inode, loff_t size) list_add_tail(&hi->list, &sbi->dirty_inodes_list); spin_unlock(&sbi->dirty_inodes_lock); } - +/** + * 申请一个node block,将仅仅是i_size和i_block改变的inode的改变信息同步 + * 并清除FI_DIRTY_SIZE状态 + * @param[in] inode 指向要修改的inode + * @return 成功则返回0 + */ int sync_hmfs_inode_size(struct inode *inode, bool force) { struct hmfs_inode_info *inode_i = HMFS_I(inode); @@ -140,7 +162,12 @@ int sync_hmfs_inode_size(struct inode *inode, bool force) } return 0; } - +/** + * 申请一个node block,将脏的inode信息全部同步到NVM上 + * 并清除inode的脏状态 + * @param[in] inode 指向要同步的inode + * @return 成功则返回0 + */ int sync_hmfs_inode(struct inode *inode, bool force) { struct super_block *sb = inode->i_sb; @@ -182,6 +209,12 @@ int sync_hmfs_inode(struct inode *inode, bool force) } /* allocate an inode */ +/** + * 读取inode编号对应的inode + * @param[in] sb 指向inode所在的超级块 + * @param[in] ino 为要读取的编号 + * @return 成功则返回0 + */ struct inode *hmfs_iget(struct super_block *sb, unsigned long ino) { struct inode *inode; diff --git a/fs/hmfs/namei.c b/fs/hmfs/namei.c index 14cd0dfa..5b962eb4 100644 --- a/fs/hmfs/namei.c +++ b/fs/hmfs/namei.c @@ -15,12 +15,21 @@ #include #include "hmfs.h" #include "hmfs_fs.h" - +/** + * 判断@dir指向文件是否能插入内嵌数据 + * @param[in] dir 指向文件inode + * @return 返回是否可内嵌 + */ static bool hmfs_may_set_inline_data(struct inode *dir) { return test_opt(HMFS_I_SB(dir), INLINE_DATA); } - +/** + * 申请一个新的inode + * @param[in] dir 指向新的inode所在的目录 + * @param[in] mode 表明新的inode所对应的文件类型 + * @return 成功则返回申请的inode的结构体指针,否则返回错误信息 + */ static struct inode *hmfs_new_inode(struct inode *dir, umode_t mode) { struct super_block *sb = dir->i_sb; @@ -92,7 +101,13 @@ static struct inode *hmfs_new_inode(struct inode *dir, umode_t mode) alloc_nid_failed(sbi, ino); return ERR_PTR(err); } - +/** + * 在已有目录下新建目录项 + * @param[in] dir 指向现有目录文件inode + * @param[in] dentry 指向要新建的目录项结构体 + * @param[in] mode 对应文件类型 + * @return 成功时返回新建目录项的inode指针,否则返回错误信息 + */ struct inode *hmfs_make_dentry(struct inode *dir, struct dentry *dentry, umode_t mode) { @@ -123,7 +138,14 @@ struct inode *hmfs_make_dentry(struct inode *dir, struct dentry *dentry, alloc_nid_failed(sbi, inode->i_ino); return ERR_PTR(err); } - +/** + * 创建新的设备文件目录项并将其与其special inode关联 + * @param[in] dir 指向现有目录 + * @param[in] dentry 指向新目录项 + * @param[in] mode 表明文件类型 + * @param[in] rdev 对应设备文件号 + * @return 成功时返回0 + */ static int hmfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) { @@ -144,7 +166,14 @@ static int hmfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, return 0; } - +/** + * 创建新的普通文件目录项并将其与其inode关联 + * @param[in] dir 指向现有目录 + * @param[in] dentry 指向新目录项 + * @param[in] mode 表明文件类型 + * @param[in] excl 无意义 + * @return 成功时返回0 + */ static int hmfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { @@ -162,7 +191,13 @@ static int hmfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, return 0; } - +/** + * 创建新的目录文件目录项并将其与其inode关联 + * @param[in] dir 指向现有目录 + * @param[in] dentry 指向新目录项 + * @param[in] mode 表明文件类型 + * @return 成功时返回0 + */ static int hmfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct inode *inode; @@ -180,7 +215,13 @@ static int hmfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) return 0; } - +/** + * 创建硬链接 + * @param[in] old_dentry 为文件原目录项 + * @param[in] dir 无意义 + * @param[in] dentry 为文件新目录项 + * @return 成功时返回0 + */ static int hmfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) { @@ -204,7 +245,12 @@ static int hmfs_link(struct dentry *old_dentry, struct inode *dir, iput(inode); return err; } - +/** + * 删除硬链接 + * @param[in] dir 指向文件inode + * @param[in] dentry 指向要删除的目录项 + * @return 成功时返回0 + */ static int hmfs_unlink(struct inode *dir, struct dentry *dentry) { struct super_block *sb = dir->i_sb; @@ -238,11 +284,16 @@ static int hmfs_unlink(struct inode *dir, struct dentry *dentry) inode_write_unlock(dir); mutex_unlock_op(sbi, ilock); - mark_inode_dirty(inode); + mark_inode_dirty(dir); fail: return err; } - +/** + * 检查目录项是否为空,是则删除硬链接,否则返回错误信息 + * @param[in] dir 指向文件inode + * @param[in] dentry 指向要检查的目录项 + * @return 成功时返回0 + */ static int hmfs_rmdir(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; @@ -252,7 +303,14 @@ static int hmfs_rmdir(struct inode *dir, struct dentry *dentry) return -ENOTEMPTY; } - +/** + * 重命名文件,由于采用log-structured,文件目录项和inode都会改变 + * @param[in] old_dir 指向旧的文件inode + * @param[in] old_dentry 指向旧的目录项 + * @param[in] new_dir 指向新的文件inode + * @param[in] new_dentry 指向新的文件目录项 + * @return 成功时返回0 + */ static int hmfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { @@ -356,7 +414,14 @@ static int hmfs_rename(struct inode *old_dir, struct dentry *old_dentry, out: return err; } - +/** + * 获取dentry->d_inode的文件属性 + * 将其复制到stat指向的kstat结构体里 + * 并将stat->blocks左移3位 + * @param[in] dentry 指向文件目录项 + * @param[out] stat 存储文件属性 + * @return 成功则返回0 + */ int hmfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { @@ -367,6 +432,12 @@ int hmfs_getattr(struct vfsmount *mnt, struct dentry *dentry, } #ifdef CONFIG_HMFS_ACL +/** + * 更新@inode属性 + * @attr指向存储要更新的属性的结构体 + * @param[in] attr 存储要更新的属性 + * @param[out] inode 需要更新的文件inode + */ static void __setattr_copy(struct inode *inode, const struct iattr *attr) { unsigned int ia_valid = attr->ia_valid; @@ -394,7 +465,13 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr) #else #define __setattr_copy setattr_copy #endif - +/** + * 更新文件inode属性的包装函数 + * 先判断inode权限决定是否可更新相应属性,再调用__setattr_copy更新属性 + * @param[in] dentry 指向对应文件inode + * @param[in] attr 指向存储要更新的属性的结构体 + * @return 成功则返回0 + */ int hmfs_setattr(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; @@ -438,7 +515,13 @@ int hmfs_setattr(struct dentry *dentry, struct iattr *attr) mark_inode_dirty(inode); return err; } - +/** + * 寻找某个孤立目录项对应的inode并将其链接起来 + * @param[in] dir 指向父目录inode + * @param[in] dentry 指向要寻找的孤立目录项 + * @param[in] flags 无意义 + * @return 若找到了则返回对应目录项,没找到则返回NULL + */ static struct dentry *hmfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { @@ -459,7 +542,9 @@ static struct dentry *hmfs_lookup(struct inode *dir, struct dentry *dentry, return d_splice_alias(inode, dentry); } - +/** + * 定义hmfs对目录文件inode操作的接口 + */ const struct inode_operations hmfs_dir_inode_operations = { .create = hmfs_create, .mkdir = hmfs_mkdir, @@ -480,7 +565,11 @@ const struct inode_operations hmfs_dir_inode_operations = { .removexattr = generic_removexattr, #endif }; - +/** + *定义hmfs对于special inode的操作与VFS的接口 + *主要包括getattr,setattr,listxattr等 + *其他采用通用接口 + */ const struct inode_operations hmfs_special_inode_operations = { .getattr = hmfs_getattr, .setattr = hmfs_setattr, diff --git a/fs/hmfs/node.c b/fs/hmfs/node.c index 1ef90887..8a0c222d 100644 --- a/fs/hmfs/node.c +++ b/fs/hmfs/node.c @@ -9,7 +9,11 @@ static struct kmem_cache *nat_entry_slab; const struct address_space_operations hmfs_nat_aops; - +/** + * 为inode增加blocks(修改元数据,未实现分配) + * @param[in] inode 文件inode + * @param[in] count 增加的block个数 + */ static inline bool inc_valid_node_count(struct hmfs_sb_info *sbi, struct inode *inode, int count, bool force) { @@ -36,7 +40,12 @@ static inline bool inc_valid_node_count(struct hmfs_sb_info *sbi, return true; } - +/** + * 减少inode的@blocks(修改元数据) + * @param[in] inode 文件inode + * @param[in] count 减少的block个数 + * @param[in] dec_valid 1 同时减少hmfs_cm_info的有效block + */ static inline void dec_valid_node_count(struct hmfs_sb_info *sbi, struct inode *inode, int count, bool dec_valid) { @@ -49,7 +58,9 @@ static inline void dec_valid_node_count(struct hmfs_sb_info *sbi, cm_i->valid_block_count -= count; unlock_cm(cm_i); } - +/** + * 返回系统最大可能的NODE_ID + */ static nid_t hmfs_max_nid(struct hmfs_sb_info *sbi) { nid_t nid = 1; @@ -60,7 +71,10 @@ static nid_t hmfs_max_nid(struct hmfs_sb_info *sbi) nid *= NAT_ENTRY_PER_BLOCK; return nid; } - +/* + * 设置一个dnode_of_data结构体 + * 用于存储文件对应的direct node的node ID以及node地址 + */ void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, struct hmfs_inode *hi, struct direct_node *db, nid_t nid) { @@ -73,6 +87,14 @@ void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, /** * The maximum depth is 4. */ + /** + * 寻找block在inode中的索引路径,即从inode找到block需经过的的NODE。 + * @param[in] block 块偏移 + * @param[out] offset 指针相对于节点起始地址的便宜 + * @param[out] noffset 指针在所有指针中的便宜 + */ + + int get_node_path(long block, int offset[4], unsigned int noffset[4]) { const long direct_index = NORMAL_ADDRS_PER_INODE; @@ -155,12 +177,16 @@ int get_node_path(long block, int offset[4], unsigned int noffset[4]) got: return level; } - +/** + * 返回n为NODE_ID的NAT_ENTRYT在内存中的地址 + */ static struct nat_entry *__lookup_nat_cache(struct hmfs_nm_info *nm_i, nid_t n) { return radix_tree_lookup(&nm_i->nat_root, n); } - +/** + * NODE_MANAGER销毁 + */ void destroy_node_manager(struct hmfs_sb_info *sbi) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -189,7 +215,9 @@ void destroy_node_manager(struct hmfs_sb_info *sbi) kfree(nm_i->free_nids); kfree(nm_i); } - +/** + * 初始化node_manager + */ static int init_node_manager(struct hmfs_sb_info *sbi) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -215,7 +243,10 @@ static int init_node_manager(struct hmfs_sb_info *sbi) mutex_init(&nm_i->build_lock); return 0; } - +/** + * 空闲node分配失败恢复 + * @nid 分配失败的节点ID + */ void alloc_nid_failed(struct hmfs_sb_info *sbi, nid_t nid) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -230,7 +261,10 @@ void alloc_nid_failed(struct hmfs_sb_info *sbi, nid_t nid) nm_i->fcnt++; unlock_free_nid(nm_i); } - +/** + * 在NAT树中加入nat_entry + * @param[in] nid 加入nat_entry的节点ID + */ static struct nat_entry *grab_nat_entry(struct hmfs_nm_info *nm_i, nid_t nid) { struct nat_entry *new; @@ -248,7 +282,9 @@ static struct nat_entry *grab_nat_entry(struct hmfs_nm_info *nm_i, nid_t nid) nm_i->nat_cnt++; return new; } - +/** + * 删除dnode + */ void truncate_node(struct dnode_of_data *dn) { struct hmfs_sb_info *sbi = HMFS_I_SB(dn->inode); @@ -279,7 +315,9 @@ void truncate_node(struct dnode_of_data *dn) invalidate: dn->node_block = NULL; } - +/** + * 删除dnode及其索引的data node + */ static int truncate_dnode(struct dnode_of_data *dn) { struct hmfs_sb_info *sbi = HMFS_I_SB(dn->inode); @@ -305,6 +343,10 @@ static int truncate_dnode(struct dnode_of_data *dn) * We're about to truncate the whole nodes. Therefore, we don't need to COW * the old node. We just mark the its nid slot in parent node to be 0 */ + /** + * 层层释放Indirect node + */ + static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, int ofs, int depth) { @@ -376,6 +418,9 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, int ofs, } /* return address of node in historic checkpoint */ +/** + * 获取特定CP版本的@nid的hmfs_node + */ struct hmfs_node *__get_node(struct hmfs_sb_info *sbi, struct checkpoint_info *cp_i, nid_t nid) { @@ -392,7 +437,9 @@ struct hmfs_node *__get_node(struct hmfs_sb_info *sbi, return ADDR(sbi, node_addr); } - +/** + * 释放inode中block之后的块 + */ static int truncate_partial_nodes(struct dnode_of_data *dn, struct hmfs_inode *hi, int *offset, int depth) { @@ -457,7 +504,10 @@ static int truncate_partial_nodes(struct dnode_of_data *dn, fail: return err; } - +/** + * 删除inode中from之后的block + * @param[in] from 删除起始偏移 + */ int truncate_inode_blocks(struct inode *inode, pgoff_t from) { struct hmfs_sb_info *sbi = HMFS_I_SB(inode); @@ -535,7 +585,11 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from) fail: return err > 0 ? 0 : err; } - +/** + * 更新内存中nid的nat_entry的块地址为blk_addr + * @param[in] nid NODE ID + * @param[in] blk_addr 更新后的块地址 + */ void gc_update_nat_entry(struct hmfs_nm_info *nm_i, nid_t nid, block_t blk_addr) { @@ -549,7 +603,9 @@ void gc_update_nat_entry(struct hmfs_nm_info *nm_i, nid_t nid, unlock_write_nat(nm_i); } - +/** + * 更新nid的nat_entry,检查是否为脏页 + */ void update_nat_entry(struct hmfs_nm_info *nm_i, nid_t nid, nid_t ino, block_t blk_addr, bool dirty) { @@ -593,6 +649,9 @@ void update_nat_entry(struct hmfs_nm_info *nm_i, nid_t nid, nid_t ino, * return node address in NVM by nid, would not allocate * new node */ + /** + * 返回Node ID为@nid的节点NVM地址 + */ void *get_node(struct hmfs_sb_info *sbi, nid_t nid) { struct node_info ni; @@ -616,7 +675,9 @@ void *get_node(struct hmfs_sb_info *sbi, nid_t nid) return ADDR(sbi, ni.blk_addr); } - +/** + * 为新NODE设置summary_entry + */ static void setup_summary_of_new_node(struct hmfs_sb_info *sbi, block_t new_node_addr, block_t src_addr, nid_t ino, unsigned int ofs_in_node, char sum_type) @@ -628,7 +689,9 @@ static void setup_summary_of_new_node(struct hmfs_sb_info *sbi, make_summary_entry(dest_sum, ino, cm_i->new_version, ofs_in_node, sum_type); } - +/** + * 为@inode分配一个节点,Node ID为@nid ,返回节点地址 (COW) + */ static struct hmfs_node *__alloc_new_node(struct hmfs_sb_info *sbi, nid_t nid, struct inode *inode, char sum_type, bool force) { @@ -677,7 +740,9 @@ static struct hmfs_node *__alloc_new_node(struct hmfs_sb_info *sbi, nid_t nid, return dest; } - +/** + * 分配一个块 + */ void *alloc_new_node(struct hmfs_sb_info *sbi, nid_t nid, struct inode *inode, char sum_type, bool force) { @@ -700,7 +765,9 @@ void *alloc_new_node(struct hmfs_sb_info *sbi, nid_t nid, struct inode *inode, addr = alloc_free_node_block(sbi, true); return ADDR(sbi, addr); } - +/** + * 填充@nid的node_info @ni + */ int get_node_info(struct hmfs_sb_info *sbi, nid_t nid, struct node_info *ni) { struct hmfs_nat_entry *ne_local; @@ -726,7 +793,9 @@ int get_node_info(struct hmfs_sb_info *sbi, nid_t nid, struct node_info *ni) update_nat_entry(nm_i, nid, ni->ino, ni->blk_addr, false); return 0; } - +/** + * 将nid置为free (0,1有什么区别,可能不是空闲????) + */ static void add_free_nid(struct hmfs_nm_info *nm_i, nid_t nid, u64 free, int *pos) { @@ -734,6 +803,9 @@ static void add_free_nid(struct hmfs_nm_info *nm_i, nid_t nid, u64 free, } /* Get free nid from journals of loaded checkpoint */ +/** + * 用NAT_JOURNAL初始化NODE_MANAGER的free nid + */ static void init_free_nids(struct hmfs_sb_info *sbi) { struct hmfs_cm_info *cm_i = CM_I(sbi); @@ -761,6 +833,9 @@ static void init_free_nids(struct hmfs_sb_info *sbi) } /* Check whether block_addr of nid in journal is NULL_ADDR */ +/** + * 检查@NID是否可用 (???) + */ static int is_valid_free_nid(struct hmfs_sb_info *sbi, nid_t nid) { struct hmfs_cm_info *cm_i = CM_I(sbi); @@ -799,7 +874,9 @@ static int is_valid_free_nid(struct hmfs_sb_info *sbi, nid_t nid) check_value: return nid > HMFS_ROOT_INO; } - +/** + * 扫描一个nat block,将其中pos个未使用的nid放入未分配链表 + */ static nid_t scan_nat_block(struct hmfs_sb_info *sbi, struct hmfs_nat_block *nat_blk, nid_t start_nid, int *pos) { @@ -828,6 +905,9 @@ static nid_t scan_nat_block(struct hmfs_sb_info *sbi, } /* Scan free nid from dirty nat entries */ +/** + * 脏NAT链表找@pos个 free nid + */ static int scan_delete_nid(struct hmfs_sb_info *sbi, int *pos) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -861,7 +941,9 @@ static int scan_delete_nid(struct hmfs_sb_info *sbi, int *pos) unlock_write_nat(nm_i); return *pos; } - +/** + * 构造可用的fre nid链表 + */ static int build_free_nids(struct hmfs_sb_info *sbi) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -898,7 +980,9 @@ static int build_free_nids(struct hmfs_sb_info *sbi) nm_i->next_scan_nid = nid; return count; } - +/** + * 从free nid 链表分配nid + */ bool alloc_nid(struct hmfs_sb_info *sbi, nid_t *nid) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -929,7 +1013,9 @@ bool alloc_nid(struct hmfs_sb_info *sbi, nid_t *nid) goto retry; } - +/** + * 创建node_manager的nat_entry slab缓存 + */ int create_node_manager_caches(void) { nat_entry_slab = hmfs_kmem_cache_create("hmfs_nat_entry", @@ -939,13 +1025,18 @@ int create_node_manager_caches(void) return 0; } - +/** + * 销毁nat_entry slab缓存 + */ void destroy_node_manager_caches(void) { kmem_cache_destroy(nat_entry_slab); } /* get a nat/nat page from nat/nat in-NVM tree */ +/** + * 返回树中第@order个节点地址 + */ static void *__get_nat_page(struct hmfs_sb_info *sbi, block_t cur_node_addr, unsigned int order, unsigned char height) { @@ -967,7 +1058,9 @@ static void *__get_nat_page(struct hmfs_sb_info *sbi, block_t cur_node_addr, return __get_nat_page(sbi, child_node_addr, order & ((1 << ofs) - 1), height - 1); } - +/** + * 返回cp版本@version中node id为@nid的NAT块地址 + */ struct hmfs_nat_block *get_nat_entry_block(struct hmfs_sb_info *sbi, ver_t version, nid_t nid) { @@ -979,7 +1072,9 @@ struct hmfs_nat_block *get_nat_entry_block(struct hmfs_sb_info *sbi, hmfs_bug_on(sbi, !cp_i); return __get_nat_page(sbi, L_ADDR(sbi, nat_root), blk_id, nat_height); } - +/** + * 返回cp版本@version中node id为@nid的hmfs_nat_entry地址 + */ struct hmfs_nat_entry *get_nat_entry(struct hmfs_sb_info *sbi, ver_t version, nid_t nid) { @@ -991,7 +1086,11 @@ struct hmfs_nat_entry *get_nat_entry(struct hmfs_sb_info *sbi, return NULL; return &nat_block->entries[rem]; } - +/** + * 获取NAT树中第index个节点 + * @version NAT树的CP版本 + * @index 节点编号 + */ struct hmfs_nat_node *get_nat_node(struct hmfs_sb_info *sbi, ver_t version, unsigned int index) { @@ -1005,7 +1104,15 @@ struct hmfs_nat_node *get_nat_node(struct hmfs_sb_info *sbi, return __get_nat_page(sbi, L_ADDR(sbi, nat_root), block_id, height); } - +/** + * 更新NAT树 + * @old_nat_node 老的NAT节点 + * @cur_nat_node 更新后的NAT节点 + * @blk_order 需更新的NAT叶子节点相对于当前树的偏移 + * @height 当前树高 + * @nat_entry_page 需更新的叶子节点内容 + * @ofs_in_pair 下一级孩子节点对父节点的偏移 + */ static block_t __flush_nat_entries(struct hmfs_sb_info *sbi, struct hmfs_nat_node *old_nat_node, struct hmfs_nat_node *cur_nat_node, unsigned int blk_order, @@ -1100,7 +1207,9 @@ static block_t __flush_nat_entries(struct hmfs_sb_info *sbi, } return cur_stored_addr; } - +/** + * 将free_nids链表中的nid置为可用 + */ static void clean_free_nid(struct hmfs_sb_info *sbi, nid_t nid) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -1115,7 +1224,9 @@ static void clean_free_nid(struct hmfs_sb_info *sbi, nid_t nid) } hmfs_bug_on(sbi, 1); } - +/** + * 处理node_manage——info的两个nat-entry链表 + */ static inline void clean_dirty_nat_entries(struct hmfs_sb_info *sbi) { struct hmfs_nm_info *nm_i = NM_I(sbi); @@ -1152,7 +1263,9 @@ static inline void clean_dirty_nat_entries(struct hmfs_sb_info *sbi) } } } - +/** + * 读取当前CP的journal中的使用的nat_entry + */ static void cache_nat_journals_entries(struct hmfs_sb_info *sbi) { struct hmfs_checkpoint *hmfs_cp = CM_I(sbi)->last_cp_i->cp; @@ -1172,7 +1285,9 @@ static void cache_nat_journals_entries(struct hmfs_sb_info *sbi) update_nat_entry(nm_i, nid, ino, blk_addr, true); } } - +/** + * 构造node_manager + */ int build_node_manager(struct hmfs_sb_info *sbi) { struct hmfs_nm_info *info; @@ -1196,7 +1311,12 @@ int build_node_manager(struct hmfs_sb_info *sbi) kfree(info); return err; } - +/** + * 将nat_entry写入journal + * @entry 写入的nat_entry地址 + * @nr_dirty_nat 写入的个数 + * @journal_pos journal写入位置 + */ static int __flush_nat_journals(struct hmfs_checkpoint *hmfs_cp, struct nat_entry *entry, int nr_dirty_nat, int* journal_pos) { @@ -1207,6 +1327,7 @@ static int __flush_nat_journals(struct hmfs_checkpoint *hmfs_cp, nat_journal = &hmfs_cp->nat_journals[*journal_pos]; + *journal_pos = *journal_pos + nr_dirty_nat; while (nr_dirty_nat > 0) { entry = list_entry(entry->list.prev, struct nat_entry, list); nat_journal->nid = cpu_to_le32(entry->ni.nid); @@ -1216,7 +1337,6 @@ static int __flush_nat_journals(struct hmfs_checkpoint *hmfs_cp, nat_journal++; entry->ni.flag |= NAT_FLAG_JOURNAL; } - *journal_pos = *journal_pos + nr_dirty_nat; return 0; } @@ -1227,6 +1347,10 @@ static int __flush_nat_journals(struct hmfs_checkpoint *hmfs_cp, * list in runtime of fs. When flushing nat journals, we just move some * of them to nat_entries temporary */ + /** + * 清除dirty_nat_entry链表中flag为NAT_FLAG_FREE_NID的entry其余移入nat_entry链表 + */ + static void flush_nat_journals(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *hmfs_cp) { @@ -1312,7 +1436,10 @@ static void flush_nat_journals(struct hmfs_sb_info *sbi, } } } - +/** + *将cp的NAT树写入NVM + * @hmfs_cp NAT树所属cp + */ struct hmfs_nat_node *flush_nat_entries(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *hmfs_cp) { @@ -1425,7 +1552,10 @@ struct hmfs_nat_node *flush_nat_entries(struct hmfs_sb_info *sbi, __free_page(empty_page); return new_root_node; } - +/** + * 将块的hmfs_summary置为有效 + * @addr 块地址 + */ void mark_block_valid_type(struct hmfs_sb_info *sbi, block_t addr) { struct hmfs_summary *summary; @@ -1463,7 +1593,11 @@ void mark_block_valid_type(struct hmfs_sb_info *sbi, block_t addr) } } } - +/** + * 递归将NAT中所有节点的hmfs_summary设置为有效 + * @cur_nat_node 当前设置节点 + * @height 当前树高 + */ static void __mark_block_valid(struct hmfs_sb_info *sbi, struct hmfs_nat_node *cur_nat_node, unsigned int blk_order, unsigned int version, u8 height) @@ -1483,6 +1617,7 @@ static void __mark_block_valid(struct hmfs_sb_info *sbi, return; } + set_summary_valid_bit(raw_summary); //leaf, alloc & copy nat entry block if (!height) { hmfs_bug_on(sbi, get_summary_type(raw_summary) != SUM_TYPE_NATD); @@ -1513,7 +1648,11 @@ static void __mark_block_valid(struct hmfs_sb_info *sbi, } } } - +/** + * 将NAT树的summary置为有效 + * @nat_root NAT树根节点 + * @hmfs_cp NAT树所属cp + */ void mark_block_valid(struct hmfs_sb_info *sbi, struct hmfs_nat_node *nat_root, struct hmfs_checkpoint *hmfs_cp) { diff --git a/fs/hmfs/recovery.c b/fs/hmfs/recovery.c index 40c89258..da91d3f9 100644 --- a/fs/hmfs/recovery.c +++ b/fs/hmfs/recovery.c @@ -14,7 +14,23 @@ #include "segment.h" #include "node.h" #include "xattr.h" - +/** + *cc1 recovery_data_block:依次恢复数据块的相关数据 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号 + *@src_off:偏移量 + *@src_sum:指向父节点的summary表的指针 + */ +/** + * recovery_data_block:依次恢复数据块的相关数据 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] src_segno:源段号 + * @param[in] src_off:偏移量 + * @param[in] src_sum:指向父节点的summary表的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ static void recovery_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -30,6 +46,10 @@ static void recovery_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, TYPE_DATA); while (1) { + /** + * 根据参数集里的检查点信息和node id得到其summary表,如果该node已经被删除了,则停止; + * 如果是空的节点,则获取上一个检查点中的信息 + */ this = __get_node(sbi, args.cp_i, args.nid); par_sum = get_summary_by_addr(sbi, L_ADDR(sbi, this)); @@ -41,7 +61,9 @@ static void recovery_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, if (this == last) goto next; - + /** + *获取该块的类型,如果是inode块,则获取inode块的偏移量,并赋值给块号,否则把direct node赋值给块号 + */ par_type = get_summary_type(par_sum); if (par_type == SUM_TYPE_INODE) { addr_in_par = le64_to_cpu(this->i.i_addr[args.ofs_in_node]); @@ -60,11 +82,17 @@ static void recovery_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, * Luckly, the child block in that node is valid and we could * judge this case by the value of address. */ + /** + * 如果地址等于了参数集中父节点的node地址并且还是有效地址,则停止恢复 + */ if (addr_in_par != args.src_addr && is_valid_address(sbi, addr_in_par)) break; if (addr_in_par != args.src_addr) { /* Recover address in parent node */ + /** + *恢复父节点中inode或者direct node的父节点地址 + */ if (par_type == SUM_TYPE_INODE) { hmfs_memcpy_atomic(&this->i.i_addr[args.ofs_in_node], &args.src_addr, 8); @@ -72,7 +100,9 @@ static void recovery_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, hmfs_memcpy_atomic(&this->dn.addr[args.ofs_in_node], &args.src_addr, 8); } - + /** + *清除目的summary块的有效位地址 + */ if (!modify_vb) { args.dest_sum = get_summary_by_addr(sbi, addr_in_par); clear_summary_valid_bit(args.dest_sum); @@ -87,7 +117,23 @@ static void recovery_data_block(struct hmfs_sb_info *sbi, seg_t src_segno, args.cp_i = get_next_checkpoint_info(sbi, args.cp_i); } } - +/** + *cc2 recovery_xdata_block:恢复额外数据块的数据信息 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号 + *@src_off:偏移量 + *@src_sum:指向父节点的summary表的指针 + */ +/** + * recovery_xdata_block:恢复额外数据块的数据信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] src_segno:源段号 + * @param[in] src_off:偏移量 + * @param[in] src_sum:指向父节点的summary表的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ static void recovery_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -102,6 +148,10 @@ static void recovery_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, TYPE_DATA); while (1) { + /** + * 根据参数集里的检查点信息和node id得到其summary表,如果该node已经被删除了,则停止; + * 如果是空的节点,则获取上一个检查点中的信息 + */ this = __get_node(sbi, arg.cp_i, arg.nid); if (IS_ERR(this)) @@ -109,17 +159,23 @@ static void recovery_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, if (this == last) goto next; - + /** + *获取额外数据块的地址 + */ x_tag = le64_to_cpu(XATTR_HDR(arg.src)->h_magic); addr_in_par = XBLOCK_ADDR(this, x_tag); - + /** + * 如果地址等于了参数集中父节点的node地址并且还是有效地址,则停止恢复 + */ if (addr_in_par != arg.src_addr && is_valid_address(sbi, addr_in_par)) { break; } if (addr_in_par != arg.src_addr) { hmfs_memcpy_atomic(JUMP(this, x_tag), &arg.src_addr, 8); - + /** + *清除目的summary块的有效位地址 + */ if (!modify_vb) { arg.dest_sum = get_summary_by_addr(sbi, addr_in_par); clear_summary_valid_bit(arg.dest_sum); @@ -135,7 +191,23 @@ static void recovery_xdata_block(struct hmfs_sb_info *sbi, seg_t src_segno, arg.cp_i = get_next_checkpoint_info(sbi, arg.cp_i); } } - +/** + *cc3 recovery_node_block:恢复node块的数据信息 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号 + *@src_off:偏移量 + *@src_sum:指向父节点的summary表的指针 + */ +/** + * recovery_node_block:恢复node块的数据信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] src_segno:源段号 + * @param[in] src_off:偏移量 + * @param[in] src_sum:指向父节点的summary表的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ static void recovery_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, unsigned int src_off, struct hmfs_summary *src_sum) { @@ -147,6 +219,11 @@ static void recovery_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_NODE); while (1) { + /** + * 根据参数集里的检查点版本信息和node id得到其NAT entry表, + * 如果该node已经被删除了,则停止; + * 如果是空的节点,则获取上一个检查点中的信息 + */ this = get_nat_entry_block(sbi, args.cp_i->version, args.nid); if (IS_ERR(this)) break; @@ -156,6 +233,9 @@ static void recovery_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, addr_in_par = le64_to_cpu(this->entries[args.ofs_in_node].block_addr); /* Src node has been COW or removed */ + /** + * 如果源节点是COW的或者被移除了 + */ if (addr_in_par != args.src_addr && is_valid_address(sbi, addr_in_par)) { break; } @@ -164,6 +244,9 @@ static void recovery_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, hmfs_memcpy_atomic(&this->entries[args.ofs_in_node].block_addr, &args.src_addr, 8); if (!modify_vb) { + /** + *清除目的summary块的有效位地址 + */ args.dest_sum = get_summary_by_addr(sbi, addr_in_par); clear_summary_valid_bit(args.dest_sum); modify_vb = true; @@ -178,7 +261,23 @@ static void recovery_node_block(struct hmfs_sb_info *sbi, seg_t src_segno, args.cp_i = get_next_checkpoint_info(sbi, args.cp_i); } } - +/** + *cc4 recovery_nat_block:恢复NAT块的数据信息 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号 + *@src_off:偏移量 + *@src_sum:指向父节点的summary表的指针 + */ +/** + * recovery_nat_block:恢复NAT块的数据信息 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] src_segno:源段号 + * @param[in] src_off:偏移量 + * @param[in] src_sum:指向父节点的summary表的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ static void recovery_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -193,9 +292,16 @@ static void recovery_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int sr prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_NODE); while (1) { + /** + *根据参数集中的node id信息判断其是否是NAT表的根节点,如果是,记录该检查点信息 + */ if (IS_NAT_ROOT(args.nid)) this = args.cp_i->cp; else { + /** + *否则根据NAT树的高和偏移量求得该node块的父节点的node id号,并且根据父节点的检查点和node ID + *号得到该node block号码 + */ par_nid = MAKE_NAT_NODE_NID(GET_NAT_NODE_HEIGHT(args.nid) - 1, GET_NAT_NODE_OFS(args.nid)); this = get_nat_node(sbi, args.cp_i->version, par_nid); @@ -204,7 +310,9 @@ static void recovery_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int sr hmfs_bug_on(sbi, !this); if (this == last) goto next; - + /** + *如果是NAT树的根节点,则得到其nat地址,否则根据偏移量得到地址 + */ if (IS_NAT_ROOT(args.nid)) { hmfs_cp = HMFS_CHECKPOINT(this); addr_in_par = le64_to_cpu(hmfs_cp->nat_addr); @@ -212,7 +320,9 @@ static void recovery_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int sr nat_node = HMFS_NAT_NODE(this); addr_in_par = le64_to_cpu(nat_node->addr[args.ofs_in_node]); } - + /** + * 如果地址等于了参数集中父节点的node地址并且还是有效地址,则停止恢复 + */ if (addr_in_par != args.src_addr && is_valid_address(sbi, addr_in_par)) { break; } @@ -226,6 +336,9 @@ static void recovery_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int sr } if (!modify_vb) { + /** + *清除目的summary块的有效位地址 + */ args.dest_sum = get_summary_by_addr(sbi, addr_in_par); clear_summary_valid_bit(args.dest_sum); modify_vb = true; @@ -240,7 +353,23 @@ static void recovery_nat_block(struct hmfs_sb_info *sbi, seg_t src_segno, int sr args.cp_i = get_next_checkpoint_info(sbi, args.cp_i); } } - +/** + *cc5 recovery_orphan_block:恢复孤立块的地址 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号 + *@src_off:偏移量 + *@src_sum:指向父节点的summary表的指针 + */ +/** + * recovery_orphan_block:恢复孤立块的地址 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] src_segno:源段号 + * @param[in] src_off:偏移量 + * @param[in] src_sum:指向父节点的summary表的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ static void recovery_orphan_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -250,10 +379,16 @@ static void recovery_orphan_block(struct hmfs_sb_info *sbi, seg_t src_segno, prepare_move_argument(&args, sbi, src_segno, src_off, src_sum, TYPE_NODE); + /** + *获取源地址、检查点地址、孤立点的地址 + */ cp_addr = le64_to_cpu(*((__le64 *)args.src)); hmfs_cp = ADDR(sbi, cp_addr); orphan_addr = le64_to_cpu(hmfs_cp->orphan_addrs[get_summary_offset(src_sum)]); - + /** + *如果孤立节点的地址不等于父节点的node地址, + *重新记录孤立节点的偏移量,同时得到其summary表后清除summary块的有效位地址 + */ if (orphan_addr != args.src_addr) { hmfs_cp->orphan_addrs[get_summary_offset(src_sum)] = cpu_to_le64(args.src_addr); @@ -261,7 +396,23 @@ static void recovery_orphan_block(struct hmfs_sb_info *sbi, seg_t src_segno, clear_summary_valid_bit(args.dest_sum); } } - +/** + *cc6 recovery_checkpoint_block:根据检查点的信息恢复CP块 + *@sbi:指向超级块信息的指针实例 + *@src_segno:源段号 + *@src_off:偏移量 + *@src_sum:指向父节点的summary表的指针 + */ +/** + * recovery_checkpoint_block:根据检查点的信息恢复CP块 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] src_segno:源段号 + * @param[in] src_off:偏移量 + * @param[in] src_sum:指向父节点的summary表的指针 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ static void recovery_checkpoint_block(struct hmfs_sb_info *sbi, seg_t src_segno, int src_off, struct hmfs_summary *src_sum) { @@ -277,19 +428,29 @@ static void recovery_checkpoint_block(struct hmfs_sb_info *sbi, seg_t src_segno, * break the checkpoint list due to checkpoint list is inconsistent * in NVM */ + /** + *这里我们不用prepare_move_argument函数,因为可能会打破检查点链表,因为检查点链表在NVM中是不稳定的 + *获取检查点地址和下一个前一个检查点的地址 + */ cp_addr = __cal_page_addr(sbi, src_segno, src_off); this_cp = HMFS_CHECKPOINT(cp_addr); next_cp = ADDR(sbi, le64_to_cpu(this_cp->next_cp_addr)); prev_cp = ADDR(sbi, le64_to_cpu(this_cp->prev_cp_addr)); addr_in_other = le64_to_cpu(next_cp->prev_cp_addr); + /** + *如果链表中下一个检查点的地址的前一个不等于当前检查点的地址,则调节对应关系 + *另外根据地址获得summary表,同时清除有效位 + */ if (addr_in_other != cp_addr) { next_cp->prev_cp_addr = cpu_to_le64(cp_addr); prev_cp->next_cp_addr = cpu_to_le64(cp_addr); dest_sum = get_summary_by_addr(sbi, addr_in_other); clear_summary_valid_bit(dest_sum); } - + /** + *依次检查所有孤立的块,如果有孤立的块,记录 + */ for (i = 0; i < NUM_ORPHAN_BLOCKS; i++) { orphan_addr = le64_to_cpu(this_cp->orphan_addrs[i]); if (orphan_addr == NULL_ADDR) @@ -298,7 +459,19 @@ static void recovery_checkpoint_block(struct hmfs_sb_info *sbi, seg_t src_segno, hmfs_memcpy_atomic(orphan, &cp_addr, 8); } } - +/** + *cc7 recovery_gc_segment:根据段号summary表的类型做相应的恢复操作 + *@sbi:指向超级块信息的指针实例 + *@segno:要回收垃圾的段号 + */ +/** + * recovery_gc_segment:根据段号summary表的类型做相应的恢复操作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] segno:要回收垃圾的段号 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ static void recovery_gc_segment(struct hmfs_sb_info *sbi, seg_t segno) { int off = 0; @@ -306,16 +479,24 @@ static void recovery_gc_segment(struct hmfs_sb_info *sbi, seg_t segno) bool is_current; struct hmfs_summary *sum; block_t seg_addr; - + /** + *记录段地址,并用词找到summary表 + */ seg_addr = __cal_page_addr(sbi, segno, 0); sum = get_summary_by_addr(sbi, seg_addr); for (off = 0; off < HMFS_PAGE_PER_SEG; ++off, sum++) { + /** + *判断summary表的版本信息和检查点管理器的最新版本信息是否吻合 + *如果是不是吻合的或者summary表中没有有效位 + */ is_current = get_summary_start_version(sum) == cm_i->new_version; if ((!get_summary_valid_bit(sum) && !is_current) || is_current) continue; - + /** + *根据summary表判断其类型 + */ switch (get_summary_type(sum)) { case SUM_TYPE_DATA: recovery_data_block(sbi, segno, off, sum); @@ -326,10 +507,16 @@ static void recovery_gc_segment(struct hmfs_sb_info *sbi, seg_t segno) case SUM_TYPE_INODE: case SUM_TYPE_DN: case SUM_TYPE_IDN: + /** + *如果是indirect块,则根据节点块的恢复方式进行 + */ recovery_node_block(sbi, segno, off, sum); break; case SUM_TYPE_NATN: case SUM_TYPE_NATD: + /** + *如果是NAT数据块,则根据NAT块的恢复方式进行 + */ recovery_nat_block(sbi, segno, off, sum); break; case SUM_TYPE_ORPHAN: @@ -349,6 +536,19 @@ static void recovery_gc_segment(struct hmfs_sb_info *sbi, seg_t segno) * to redo GC process. But we have an idea which block is mark as * valid and we need to reset the valid its of them. */ +/** + *cc8 recovery_gc_crash:根据检查点记录依次进行垃圾回收操作 + *@sbi:指向超级块信息的指针实例 + *@hmfs_cp:指向当前检查点的实例 + */ +/** + * recovery_gc_crash:根据检查点记录依次进行垃圾回收操作 + * @param[in] sbi:指向当前版本下超级块信息的实例 + * @param[in] hmfs_cp:指向当前检查点的实例 + * @ref segment.h,hmfs.h,hmfs_fs.h,gc.h,node.h,xattr.h + * @see + * @note + */ void recovery_gc_crash(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *hmfs_cp) { void *new_gc_logs; @@ -356,12 +556,16 @@ void recovery_gc_crash(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *hmfs_cp block_t log_addr; int i; seg_t segno; - + /** + *记录垃圾回收的日志区域,得到垃圾回收的日志区域所在的地址 + */ new_gc_logs = sbi->gc_logs; nr_gc_segs = le32_to_cpu(hmfs_cp->nr_gc_segs); log_addr = __cal_page_addr(sbi, le32_to_cpu(hmfs_cp->gc_logs), 0); sbi->gc_logs = ADDR(sbi, log_addr); - + /** + *依次遍历所有的段,根据每一段做相应的垃圾回收操作 + */ for (i = 0; i < nr_gc_segs; i++, sbi->gc_logs++) { segno = le32_to_cpu(*sbi->gc_logs); recovery_gc_segment(sbi, segno); diff --git a/fs/hmfs/segment.c b/fs/hmfs/segment.c index 46218ec1..5ad19d48 100644 --- a/fs/hmfs/segment.c +++ b/fs/hmfs/segment.c @@ -6,6 +6,17 @@ * it fall into space where we have actually writen data * into. It's different from valid bits in summary entry */ +/** + * is_valid_address:先根据参数获取当前指针指向的对象所在的段号 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] addr 块地址 + * @param[out] 如果该段号等于检查点指针的数据块所在的段号,则返回当前检查点所在的数据的偏移,证明该地址有效, + * 同理,如果等于当前node所在的段号,则返回当前检查点所在的node的偏移,也证明该地址有效,否则,为无效地址,置为0 + * @return 0,执行成功,非0,失败, + * @ref segment.h + * @see + * @note + */ bool is_valid_address(struct hmfs_sb_info *sbi, block_t addr) { seg_t segno = GET_SEGNO(sbi, addr); @@ -18,7 +29,19 @@ bool is_valid_address(struct hmfs_sb_info *sbi, block_t addr) else return get_seg_entry(sbi, segno)->valid_blocks > 0; } - +/* + *cc2 +- *@ sbi:指向超级块信息的指针实例 +- *@ return:总的有效块的个数 + */ +/** + * total_valid_blocks:遍历main area区域所有段,计算某个超级块中用到的有效块的个数 + * @param[in] sbi 指向超级块信息的指针实例 + * @return 总的有效快的个数 + * @ref segment.h + * @see + * @note + */ unsigned long total_valid_blocks(struct hmfs_sb_info *sbi) { int i; @@ -30,7 +53,21 @@ unsigned long total_valid_blocks(struct hmfs_sb_info *sbi) return sum; } - +/* + *cc3 get_seg_vblocks_in_summary:遍历SSA区域的当前段下,遍历每段每页每块的有效节点的个数 +- *@ sbi:指向超级块信息的指针实例 +- *@ segno:段号的类型 +- *@ return:返回当前有效节点的个数 + */ +/** + * get_seg_vblocks_in_summary:遍历SSA区域的当前段下,遍历每段每页每块的有效节点的个数 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] segno 段号的类型 + * @return 返回当前有效节点的个数 + * @ref segment.h + * @see + * @note + */ unsigned long get_seg_vblocks_in_summary(struct hmfs_sb_info *sbi, seg_t segno) { struct hmfs_summary_block *sum_blk; @@ -62,6 +99,21 @@ unsigned long get_seg_vblocks_in_summary(struct hmfs_sb_info *sbi, seg_t segno) return count; } +/* + *cc4 __mark_sit_entry_dirty:记录当前段中SIT中脏的entry的个数 +- *@sit_i:指向 SIT表的实例 +- *@segno:段号的类型 +- *@return:返回当前当前SIT总脏的entry的个数 + */ +/** + * __mark_sit_entry_dirty:记录当前段中SIT中脏的entry的个数 + * @param[in] sit_i:指向 SIT表的实例 + * @param[in] segno:段号的类型 + * @return 返回当前当前SIT总脏的entry的个数 + * @ref segment.h + * @see + * @note + */ static void __mark_sit_entry_dirty(struct sit_info *sit_i, seg_t segno) { if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap)) @@ -69,6 +121,24 @@ static void __mark_sit_entry_dirty(struct sit_info *sit_i, seg_t segno) } /* Return amount of blocks which has been invalidated */ + +/* + *cc5 invalidate_delete_block:先判断当前块是否是最新版本的块,如果不是,根据块地址获取段号,同时将该段标记为脏 +- *@sbi:指向超级块信息的指针实例 +- *@addr:当前块的地址 +- *@return:返回无效的块的数量 + */ +/** + * invalidate_delete_block:先判断当前块是否是最新版本的块,如果不是,根据块地址获取段号,同时将该段标记为脏 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] addr 当前块的地址 + * @param[out] 如果该段号等于检查点指针的数据块所在的段号,则返回当前检查点所在的数据的偏移,证明该地址有效, + * 同理,如果等于当前node所在的段号,则返回当前检查点所在的node的偏移,也证明该地址有效,否则,为无效地址,置为0 + * @return 返回无效的块的数量 + * @ref segment.h + * @see + * @note + */ int invalidate_delete_block(struct hmfs_sb_info *sbi, block_t addr) { struct sit_info *sit_i = SIT_I(sbi); @@ -89,6 +159,17 @@ int invalidate_delete_block(struct hmfs_sb_info *sbi, block_t addr) return 1; } +/* + - *cc6 init_min_max_mtime:先锁定当前entry的表,然后遍历当前超级块中所有的段,同时设置所有段SIT的最大、最小mtime +- *@sbi:指向超级块信息的指针实例 + */ +/** + * init_min_max_mtime:先锁定当前entry的表,然后遍历当前超级块中所有的段,同时设置所有段SIT的最大、最小mtime + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ static void init_min_max_mtime(struct hmfs_sb_info *sbi) { struct sit_info *sit_i = SIT_I(sbi); @@ -108,7 +189,21 @@ static void init_min_max_mtime(struct hmfs_sb_info *sbi) sit_i->max_mtime = get_mtime(sbi); unlock_sentry(sit_i); } - +/* + - *cc7 update_sit_entry:记录当前段的有效的块数,同时记录当前段的空闲的和脏的大小,并且根据新的有效块SITentry,更新当前段的entry信息 +- *@sbi:指向超级块信息的指针实例 +- *@segno:段号的类型 +- *@del:段偏移 + */ +/** + * update_sit_entry:记录当前段的有效的块数,同时记录当前段的空闲的和脏的大小,并且根据新的有效块SITentry,更新当前段的entry信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] segno 段号的类型 + * @param[in] del 段偏移 + * @ref segment.h + * @see + * @note + */ void update_sit_entry(struct hmfs_sb_info *sbi, seg_t segno, int del) { @@ -131,6 +226,17 @@ void update_sit_entry(struct hmfs_sb_info *sbi, seg_t segno, __mark_sit_entry_dirty(sit_i, segno); } +/* + - *cc8 reset_curseg:重置当前段的未分配块的起始位置 +- *@seg_i:当前段的段号 + */ +/** + * reset_curseg:重置当前段的未分配块的起始位置 + * @param[in] seg_i 当前段的段号 + * @ref segment.h + * @see + * @note + */ static void reset_curseg(struct curseg_info *seg_i) { atomic_set(&seg_i->segno, seg_i->next_segno); @@ -138,6 +244,23 @@ static void reset_curseg(struct curseg_info *seg_i) seg_i->next_segno = NULL_SEGNO; } +/* + - *cc9 __cal_page_addr:根据段号和块偏移,返回当前mainarea的起始位置 +- *@sbi:指向超级块信息的指针实例 +- *@segno:当前段的段号 +- *@blkoff:块偏移 +- *@return:返回当前mainarea的起始位置 + */ +/** + * __cal_page_addr:根据段号和块偏移,返回当前mainarea的起始位置 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] segno 当前段的段号 + * @param[in] blkoff 块偏移 + * @return 返回当前mainarea的起始位置 + * @ref segment.h + * @see + * @note + */ inline block_t __cal_page_addr(struct hmfs_sb_info *sbi, seg_t segno, int blkoff) { @@ -145,7 +268,21 @@ inline block_t __cal_page_addr(struct hmfs_sb_info *sbi, seg_t segno, (blkoff << HMFS_PAGE_SIZE_BITS) + sbi->main_addr_start; } - +/* + - *cc10 cal_page_addr:根据当前段号和要写的下一块偏移计算当前页的起始地址 +- *@sbi:指向超级块信息的指针实例 +- *@seg_i:当前段的段号 +- *@return:计算当前页的起始地址ַ + */ +/** + * cal_page_addr:根据当前段号和要写的下一块偏移计算当前页的起始地址 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] seg_i 当前段的段号 + * @return 计算当前页的起始地址 + * @ref segment.h + * @see + * @note + */ static inline unsigned long cal_page_addr(struct hmfs_sb_info *sbi, struct curseg_info *seg_i) { @@ -158,8 +295,26 @@ static inline unsigned long cal_page_addr(struct hmfs_sb_info *sbi, * @newseg returns the found segment * must be success (otherwise cause error) */ +/* +- *cc11 get_new_segment:遍历当前超级块下所有段,从空闲段的bitmap中,获取当前新的空闲的段的位置 +- *@sbi:指向超级块信息的指针实例 +- *@newseg:段号的类型 +- *@return:每段空闲的位置 + */ +/** + * get_new_segment:遍历当前超级块下所有段,从空闲段的bitmap中,获取当前新的空闲的段的位置 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] newseg 段号的类型 + * @return 每段空闲的位置 + * @ref segment.h + * @see + * @note + */ int get_new_segment(struct hmfs_sb_info *sbi, seg_t *newseg) { + /* + * free_i:获取完全空闲的块的实例(没有有效的块) + */ struct free_segmap_info *free_i = FREE_I(sbi); seg_t segno; bool retry = false; @@ -183,38 +338,86 @@ int get_new_segment(struct hmfs_sb_info *sbi, seg_t *newseg) hmfs_bug_on(sbi, test_bit(segno, free_i->free_segmap)); __set_inuse(sbi, segno); *newseg = segno; - /* Need to clear SSA */ + /* TODO: Need not to clear SSA */ ssa = get_summary_block(sbi, segno); memset_nt(ssa, 0, HMFS_SUMMARY_BLOCK_SIZE); unlock: +/* + - * unlock_write_segmap:锁定要写的段 + */ unlock_write_segmap(free_i); return ret; } - +/* + - *cc12 move_to_new_segment:返回新的段的起始位置 +- *@sbi:指向超级块信息的指针实例 +- *@seg_i:获取当前active的段日志信息实例 +- *@return:返回当前新的空闲段的起始位置 + */ +/** + * move_to_new_segment:返回新的段的起始位置 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] seg_i 获取当前active的段日志信息实例 + * @return 返回当前新的空闲段的起始位置 + * @ref segment.h + * @see + * @note + */ static int move_to_new_segment(struct hmfs_sb_info *sbi, struct curseg_info *seg_i) { + /* + * ��ȡ��ǰ�Ķκ� + */ seg_t segno = atomic_read(&seg_i->segno); int ret = get_new_segment(sbi, &segno); if (ret) return ret; + /** + * 获取当前的段号 + */ seg_i->next_segno = segno; reset_curseg(seg_i); return 0; } - +/* + *cc13 get_free_block: +- *@sbi:指向超级块信息的指针实例 +- *@seg_type:当前段的类型 +- *@sit_lock:记录当前SIT表是否锁定 +- *@return:返回当前块的页的起始位置 + */ +/** + * get_free_block:获得空闲块的块号 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] seg_type 当前段的类型 + * @param[in] sit_lock 记录当前SIT表是否锁定 + * @return 返回当前块的页的起始位置 + * @ref segment.h + * @see + * @note + */ static block_t get_free_block(struct hmfs_sb_info *sbi, int seg_type, bool sit_lock) { block_t page_addr = 0; + /** + * SIT表的信息 + */ struct sit_info *sit_i = SIT_I(sbi); struct curseg_info *seg_i = &(CURSEG_I(sbi)[seg_type]); int ret; lock_curseg(seg_i); + /** + *判断当前段的下一个块偏移是不是已经是块的最后 + */ if (seg_i->next_blkoff == HMFS_PAGE_PER_SEG) { + /** + *如果扫到块的尽头,则扫描下一个块 + */ ret = move_to_new_segment(sbi, seg_i); if (ret) { unlock_curseg(seg_i); @@ -223,31 +426,74 @@ static block_t get_free_block(struct hmfs_sb_info *sbi, int seg_type, } page_addr = cal_page_addr(sbi, seg_i); - + /** + *如果当前块为脏,,更新当前entry的位置 + */ if (sit_lock) lock_sentry(sit_i); update_sit_entry(sbi, atomic_read(&seg_i->segno), 1); if (sit_lock) unlock_sentry(sit_i); - + /** + * 继续移动到下面active的块的偏移位置 + */ seg_i->next_blkoff++; unlock_curseg(seg_i); return page_addr; } - +/* +- * cc14 alloc_free_data_block:遍历当前active的数据 +- * @sbi:指向超级块信息的指针实例 +- * @return:遍历当前所有的超级块,依次移到下一个active的块 + */ +/** + * alloc_free_data_block:遍历当前active的数据 + * @param[in] sbi 指向超级块信息的指针实例 + * @return 遍历当前所有的超级块,依次移到下一个active的块 + * @ref segment.h + * @see + * @note + */ block_t alloc_free_data_block(struct hmfs_sb_info * sbi) { return get_free_block(sbi, CURSEG_DATA, true); } - +/* + - *cc15 alloc_free_node_block:遍历当前active的node +- *@sbi:指向超级块信息的指针实例 +- *@sit_lock:依次移到下一个active的块 + */ +/** + * alloc_free_node_block:遍历当前active的node + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] sit_lock 依次移到下一个active的块 + * @return 遍历当前所有的超级块,依次移到下一个active的块 + * @ref segment.h + * @see + * @note + */ block_t alloc_free_node_block(struct hmfs_sb_info * sbi, bool sit_lock) { return get_free_block(sbi, CURSEG_NODE, sit_lock); } +/* + - *cc16 recovery_sit_entries:从日志记录中恢复SIT入口块的信息 +- *@sbi:指向超级块信息的指针实例 +- *@hmfs_cp:管理检查点的实例 + */ +/** + * cc16 recovery_sit_entries:从日志记录中恢复SIT入口块的信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] hmfs_cp 管理检查点的实例 + * @return 从日志记录中恢复SIT入口块的信息, + * @ref segment.h + * @see + * @note + */ void recovery_sit_entries(struct hmfs_sb_info *sbi, struct hmfs_checkpoint *hmfs_cp) { @@ -255,14 +501,23 @@ void recovery_sit_entries(struct hmfs_sb_info *sbi, struct hmfs_sit_log_entry *sit_log; struct hmfs_sit_entry *sit_entry; block_t seg_addr; + /** + * 定义段号的类型 + */ seg_t sit_segno, segno; nr_logs = le16_to_cpu(hmfs_cp->nr_logs); nr_segs = hmfs_cp->nr_segs; for (i = 0; i < nr_segs; i++) { + /** + *依次转化获取了SIT日志的段号,计算当前mainarea的段地址ַ + */ sit_segno = le32_to_cpu(hmfs_cp->sit_logs[i]); seg_addr = __cal_page_addr(sbi, sit_segno, 0); sit_log = ADDR(sbi, seg_addr); + /** + * 遍历完当前所有的检查点指向段,获取当前SIT的入口地址,用日志时间等信息更新entry信息 + */ while (num < nr_logs) { segno = le32_to_cpu(sit_log->segno); sit_entry = get_sit_entry(sbi, segno); @@ -276,15 +531,34 @@ void recovery_sit_entries(struct hmfs_sb_info *sbi, } } } - +/* + - *cc17 flush_sit_entries_rmcp:在删除一个检查点后更新SIT area的信息,刷新空闲SIT信息 +- *@sbi:指向超级块信息的指针实例 + */ +/** + * cc17 flush_sit_entries_rmcp:在删除一个检查点后更新SIT area的信息,刷新空闲SIT信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ /* Update SIT area after deleting a checkpoint */ void flush_sit_entries_rmcp(struct hmfs_sb_info *sbi) { struct sit_info *sit_i = SIT_I(sbi); + /** + *记录当前超级块中主存区肿块的个数 + */ pgc_t total_segs = TOTAL_SEGS(sbi); struct hmfs_sit_entry *sit_entry; struct seg_entry *seg_entry; + /** + * 获取当前脏的entry的bitmap + */ unsigned long *bitmap = sit_i->dirty_sentries_bitmap; + /** + *获取某个段里面指向4KB大小的块的入口以及没有有效块的段的实例 + */ struct hmfs_summary *summary; struct free_segmap_info *free_i = FREE_I(sbi); int i; @@ -293,14 +567,20 @@ void flush_sit_entries_rmcp(struct hmfs_sb_info *sbi) while(1) { offset = find_next_bit(bitmap, total_segs, offset); if (offset < total_segs) { + /** + *根据偏移和超级块信息获取段入口SIT缓存入口地址 + */ seg_entry = get_seg_entry(sbi, offset); sit_entry = get_sit_entry(sbi, offset); - /* + /** * In recovery process, the valid blocks in original * SIT area might be invalid. Because system might crash during * writing SIT. Thus, we need to calculate valid blocks by * scaning SSA area */ + /** + * 如果系统崩溃,通过扫描SSA区域计算有效块的个数 + */ if (sbi->recovery_doing) { seg_entry->valid_blocks = 0; summary = get_summary_block(sbi, offset)->entries; @@ -309,6 +589,9 @@ void flush_sit_entries_rmcp(struct hmfs_sb_info *sbi) seg_entry->valid_blocks++; } } + /** + *如果段的入口不是有效块,则记录空闲段的数量加1 + */ if (!seg_entry->valid_blocks) { lock_write_segmap(free_i); clear_bit(offset, free_i->free_segmap); @@ -325,10 +608,23 @@ void flush_sit_entries_rmcp(struct hmfs_sb_info *sbi) memset_nt(sit_i->dirty_sentries_bitmap, 0, sit_i->bitmap_size); } - +/* + *18cc: flush_sit_entries:刷新SIT表的entry信息 + *@sbi:指向超级块信息的指针实例 + */ +/** + * flush_sit_entries:刷新SIT表的entry信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, void *new_nat_root) { + /** + * 初始化SIT信息表的整体段信息指针,SIT entry,位图指针,日志entry,检查点,空闲段信息指针 + */ struct sit_info *sit_i = SIT_I(sbi); unsigned long offset = 0; pgc_t total_segs = TOTAL_SEGS(sbi); @@ -341,7 +637,9 @@ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, struct free_segmap_info *free_i = FREE_I(sbi); seg_t sit_segno; block_t seg_addr; - +/** + * 遍历所有段信息,记录并配置当前超级块实例中脏的块数 + */ #ifdef CONFIG_HMFS_DEBUG pgc_t nrdirty = 0; @@ -358,11 +656,17 @@ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, #endif /* First, prepare free segments to store dirty sit logs */ + /** + *首先准备空闲的段来存储脏的SIT表日志信息 + */ nr_logs = sit_i->dirty_sentries; nr_segs = (nr_logs + LOGS_ENTRY_PER_SEG - 1) / LOGS_ENTRY_PER_SEG - 1; sit_segno = le32_to_cpu(hmfs_cp->cur_data_segno); do { retry: + /** + * 找到空闲段里所有段里空闲的部分,并且记录保存了SIT日志的段的信息 + */ sit_segno = find_next_zero_bit(free_i->free_segmap, total_segs, sit_segno); if (sit_segno >= total_segs) { @@ -374,6 +678,9 @@ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, } while(nr_segs >= 0); /* Then, copy all dirty seg_entry to cp */ + /** + *拷贝所有脏的段entry到检查点,记录段的地址,根据地址计算SIT日志的地址,接着对下一个段进行相同的操作 + */ i = 0; nr_segs = 0; nr_logs = 0; @@ -387,6 +694,9 @@ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, i = LOGS_ENTRY_PER_SEG; nr_segs++; } + /** + * 获取段的缓存entry,在SIT日志表,记录段entry的修改时间,同时记录有效的块, + */ if (offset < total_segs) { seg_entry = get_seg_entry(sbi, offset); sit_log->segno = cpu_to_le32(offset); @@ -399,6 +709,9 @@ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, } else break; } + /** + * 同时更新检查点的日志信息和段信息 + */ offset = 0; hmfs_cp->nr_logs = cpu_to_le16(nr_logs); hmfs_cp->nr_segs = nr_segs; @@ -407,6 +720,9 @@ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, set_fs_state(hmfs_cp, HMFS_ADD_CP); /* Then, copy all dirty seg_entry to SIT area */ + /** + * 把所有脏的段的entry写到SIT域,获取SIT entry和缓存信息,将信息更新到段信息SIT表中 + */ while (1) { offset = find_next_bit(bitmap, total_segs, offset); if (offset < total_segs) { @@ -419,11 +735,26 @@ void flush_sit_entries(struct hmfs_sb_info *sbi, block_t new_cp_addr, } /* Finally, set valid bit in SSA */ + /** + * 最后在SSA区域设置有效的字节,重置脏的entry的位图大小 + */ mark_block_valid(sbi, new_nat_root, ADDR(sbi, new_cp_addr)); sit_i->dirty_sentries = 0; memset_nt(sit_i->dirty_sentries_bitmap, 0, sit_i->bitmap_size); } - +/* + - *cc19 __set_test_and_inuse:处理并设置当前空闲段为未使用过 +- *@sbi:指向超级块信息的指针实例 +- *@segno:段号的类型 + */ +/** + * __set_test_and_inuse:处理并设置当前空闲段为未使用过 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] segno 段号的类型 + * @ref segment.h + * @see + * @note + */ static inline void __set_test_and_inuse(struct hmfs_sb_info *sbi, seg_t segno) { @@ -439,24 +770,47 @@ static inline void __set_test_and_inuse(struct hmfs_sb_info *sbi, /* * routines for build segment manager */ +/* + *20cc build_sit_info: +- *@sbi:指向超级块信息的指针实例 + *@return: + */ +/** + * build_sit_info:保护SIT缓存 + * @param[in] sbi 指向超级块信息的指针实例 + * @return 0,执行成功,非0,失败, + * @ref segment.h + * @see + * @note + */ static int build_sit_info(struct hmfs_sb_info *sbi) { + /** + * 定义检查点管理器的实例和检查点的实例 + */ struct hmfs_cm_info *cm_i = CM_I(sbi); struct hmfs_checkpoint *hmfs_cp = cm_i->last_cp_i->cp; struct sit_info *sit_i; unsigned long long bitmap_size; + /** + *为SIT信息表分配内存 + */ /* allocate memory for SIT information */ sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL); if (!sit_i) return -ENOMEM; - + /** + * 获取段管理器下整个段的信息 + */ SM_I(sbi)->sit_info = sit_i; sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry)); if (!sit_i->sentries) return -ENOMEM; - + /** + * 初始化当前脏的段的bitmap + */ bitmap_size = hmfs_bitmap_size(TOTAL_SEGS(sbi)); sit_i->bitmap_size = bitmap_size; sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL); @@ -467,18 +821,39 @@ static int build_sit_info(struct hmfs_sb_info *sbi) sit_i->dirty_sentries = 0; + /** + * 更新文件系统的生存时间和装载时间 + */ sit_i->elapsed_time = le32_to_cpu(hmfs_cp->elapsed_time); sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec; + /** + * 保护SIT的缓存 + */ mutex_init(&sit_i->sentry_lock); return 0; } +/* + *21cc free_prefree_segments: + *@sbi:指向超级块信息的指针实例 + */ +/** + * free_prefree_segments:处理空闲段 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ void free_prefree_segments(struct hmfs_sb_info *sbi) { + /** + * 定义空闲块的实例 + */ struct free_segmap_info *free_i = FREE_I(sbi); int total_segs = TOTAL_SEGS(sbi); unsigned long *bitmap = free_i->prefree_segmap; seg_t segno = 0; + void *ssa; lock_write_segmap(free_i); while (1) { @@ -486,26 +861,56 @@ void free_prefree_segments(struct hmfs_sb_info *sbi) if (segno >= total_segs) break; clear_bit(segno, bitmap); + /** + *刷新所有空闲段的信息,并且计数加1 + */ if (test_and_clear_bit(segno, free_i->free_segmap)) { free_i->free_segments++; } + /** + *根据当前段号获取SSA信息 + */ + ssa = get_summary_block(sbi, segno); + memset_nt(ssa, 0, HMFS_SUMMARY_BLOCK_SIZE); segno++; } unlock_write_segmap(free_i); } - +/* + *cai22:build_free_segmap:生成空闲段的若干操作 + *@sbi:指向hmfs超级块信息的实例 + *@return:操作正确返回0,否则返回超出内存范围 + */ +/** + * build_free_segmap:生成空闲段的若干操作 + * @param[in] sbi 指向超级块信息的指针实例 + * @return 操作正确返回0,否则返回超出内存范围 + * @ref segment.h + * @see + * @note + */ static int build_free_segmap(struct hmfs_sb_info *sbi) { struct free_segmap_info *free_i; unsigned int bitmap_size; /* allocate memory for free segmap information */ + /** + * 回收GFP_KERNEL类型的内存空间 + */ free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL); if (!free_i) + /** + * 超出内存范围 + */ return -ENOMEM; - + /* + *实例化当前超级块实例下的段管理器信息,将空段信息置为回收后的空间 + */ SM_I(sbi)->free_info = free_i; - + /** + *求main area段的大小,同时回收该段大小,同时实例化空段指针实例中的位图信息,如果有预留空间,返回预留空间 + */ bitmap_size = hmfs_bitmap_size(TOTAL_SEGS(sbi)); free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL); if (!free_i->free_segmap) { @@ -516,10 +921,16 @@ static int build_free_segmap(struct hmfs_sb_info *sbi) goto free_segmap; /* set all segments as dirty temporarily */ + /** + * 将所有的空闲段暂时置为脏 + */ memset(free_i->free_segmap, 0xff, bitmap_size); memset(free_i->prefree_segmap, 0, bitmap_size); /* init free segmap information */ + /** + *初始化空闲段的信息,同时初始化读写的锁 + */ free_i->free_segments = 0; rwlock_init(&free_i->segmap_lock); return 0; @@ -531,13 +942,32 @@ static int build_free_segmap(struct hmfs_sb_info *sbi) return -ENOMEM; } +/* + *cc23 build_curseg:生成active段缓存信息 + *@sbi:指向hmfs超级块信息的实例 + *@return:操作正确返回0,否则返回超出内存范围 + */ +/** + * build_curseg:生成active段缓存信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @return 操作正确返回0,否则返回超出内存范围 + * @ref segment.h + * @see + * @note + */ static int build_curseg(struct hmfs_sb_info *sbi) { + /** + *定义active日志指针实例,初始化检查点的管理器信息,检查点 + */ struct curseg_info *array; struct hmfs_cm_info *cm_i = CM_I(sbi); struct hmfs_checkpoint *hmfs_cp = cm_i->last_cp_i->cp; unsigned short node_blkoff, data_blkoff; + /** + * 根据段日志分配内存大小 + */ array = kzalloc(sizeof(struct curseg_info) * NR_CURSEG_TYPE, GFP_KERNEL); if (!array) @@ -545,9 +975,15 @@ static int build_curseg(struct hmfs_sb_info *sbi) SM_I(sbi)->curseg_array = array; + /** + * 锁的一致性 + */ mutex_init(&array[CURSEG_NODE].curseg_mutex); mutex_init(&array[CURSEG_DATA].curseg_mutex); + /** + * 先锁定当前的段,并且将当前node段的信息,写下一个要写的段偏移,再解锁当前段,设置当前段信息,同时将下一个段先置为空 + */ lock_curseg(&array[CURSEG_NODE]); node_blkoff = le16_to_cpu(hmfs_cp->cur_node_blkoff); array[CURSEG_NODE].next_blkoff = node_blkoff; @@ -555,6 +991,9 @@ static int build_curseg(struct hmfs_sb_info *sbi) array[CURSEG_NODE].next_segno = NULL_SEGNO; unlock_curseg(&array[CURSEG_NODE]); + /** + *将当前数据段的信息写到写到日志信息中,同时重复上述操作 + */ lock_curseg(&array[CURSEG_DATA]); data_blkoff = le16_to_cpu(hmfs_cp->cur_data_blkoff); array[CURSEG_DATA].next_blkoff = data_blkoff; @@ -565,6 +1004,17 @@ static int build_curseg(struct hmfs_sb_info *sbi) return 0; } +/* + *cc24 build_sit_entries:重写SIT表entry的信息 + *@sbi:指向hmfs超级块信息的实例 + */ +/** + * build_sit_entries:重写SIT表entry的信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ static void build_sit_entries(struct hmfs_sb_info *sbi) { struct sit_info *sit_i = SIT_I(sbi); @@ -572,6 +1022,9 @@ static void build_sit_entries(struct hmfs_sb_info *sbi) struct hmfs_sit_entry *sit_entry; unsigned int start; + /** + *处理SIT的entry信息,获取当前段缓存entry和SIT表entry信息,用作SIT表entry信息的更新 + */ lock_sentry(sit_i); for (start = 0; start < TOTAL_SEGS(sbi); start++) { seg_entry = get_seg_entry(sbi, start); @@ -581,6 +1034,17 @@ static void build_sit_entries(struct hmfs_sb_info *sbi) unlock_sentry(sit_i); } +/* + *cc25 init_free_segmap:根据当前超级块实例信息,初始化所有空闲段 + *@sbi:指向hmfs超级块信息的实例 + */ +/** + * init_free_segmap:根据当前超级块实例信息,初始化所有空闲段 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ static void init_free_segmap(struct hmfs_sb_info *sbi) { struct free_segmap_info *free_i = FREE_I(sbi); @@ -589,6 +1053,9 @@ static void init_free_segmap(struct hmfs_sb_info *sbi) struct seg_entry *sentry = NULL; int i; + /** + * 对所有的段,先获取段的入口地址,接下来释放所有空闲的段中失效的块所占有的空间 + */ for (start = 0; start < TOTAL_SEGS(sbi); start++) { sentry = get_seg_entry(sbi, start); if (!sentry->valid_blocks) { @@ -600,13 +1067,30 @@ static void init_free_segmap(struct hmfs_sb_info *sbi) } /* set use the current segments */ + /** + *处理当前active的段信息 + */ curseg_t = CURSEG_I(sbi); for (i = 0; i < NR_CURSEG_TYPE; i++) __set_test_and_inuse(sbi, atomic_read(&curseg_t[i].segno)); } +/* + *26cc init_dirty_segmap:初始化脏的段的信息 + *@sbi:指向hmfs超级块信息的实例 + */ +/** + * init_dirty_segmap:初始化脏的段的信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ static void init_dirty_segmap(struct hmfs_sb_info *sbi) { + /** + * 初始化既有有效块又有无效的块的段的实例及信息,活跃的日志段 + */ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct free_segmap_info *free_i = FREE_I(sbi); struct curseg_info *curseg_t = CURSEG_I(sbi); @@ -616,6 +1100,9 @@ static void init_dirty_segmap(struct hmfs_sb_info *sbi) while (1) { /* find dirty segmap based on free segmap */ + /** + *基于空闲段找到脏的段,同时根据SIT段缓存记录有效块的数量 + */ segno = find_next_inuse(free_i, total_segs, offset); if (segno >= total_segs) break; @@ -623,25 +1110,49 @@ static void init_dirty_segmap(struct hmfs_sb_info *sbi) valid_blocks = get_seg_entry(sbi, segno)->valid_blocks; if (valid_blocks >= HMFS_PAGE_PER_SEG || !valid_blocks) continue; + /** + * 同时获取脏的段的bitmap + */ test_and_set_bit(segno, dirty_i->dirty_segmap); } /* Clear the current segments */ + /** + *清楚当前脏的段的位图信息 + */ for (i = 0; i < NR_CURSEG_TYPE; i++) clear_bit(atomic_read(&curseg_t[i].segno), dirty_i->dirty_segmap); } - +/* + *27cc build_dirty_segmap:处理脏的段的位图信息 + *@sbi:指向hmfs超级块信息的实例 + *@return:异常报错超出内存,正常执行返回0 + */ +/** + * build_dirty_segmap:处理脏的段的位图信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @return:异常报错超出内存,正常执行返回0 + * @ref segment.h + * @see + * @note + */ static int build_dirty_segmap(struct hmfs_sb_info *sbi) { struct dirty_seglist_info *dirty_i; unsigned int bitmap_size; + /** + * 回收脏的段所占的空间,同时设置当前脏段的信息 + */ dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL); if (!dirty_i) return -ENOMEM; SM_I(sbi)->dirty_info = dirty_i; + /** + * 回收脏的段的位图所占的空间,同时初始化葬断脏段的信息 + */ bitmap_size = (BITS_TO_LONGS(TOTAL_SEGS(sbi)) * sizeof(unsigned long)); dirty_i->dirty_segmap = kzalloc(bitmap_size, GFP_KERNEL); @@ -652,25 +1163,53 @@ static int build_dirty_segmap(struct hmfs_sb_info *sbi) init_dirty_segmap(sbi); return 0; } - +/* + *cc8 build_segment_manager:处理段管理器的信息 + *@sbi:指向hmfs超级块信息的实例 + *@return: + */ +/** + * build_segment_manager:处理段管理器的信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] addr 块地址 + * @return 0,执行成功,非0,失败, + * @ref segment.h + * @see + * @note + */ int build_segment_manager(struct hmfs_sb_info *sbi) { + /** + *获取当前超级块的物理地址,同时初始化段管理器的实例 + */ struct hmfs_super_block *raw_super = HMFS_RAW_SUPER(sbi); struct hmfs_sm_info *sm_info; int err; pgc_t user_segments, main_segments; + /** + *回收段管理器的内存信息 + */ sm_info = kzalloc(sizeof(struct hmfs_sm_info), GFP_KERNEL); if (!sm_info) return -ENOMEM; /* init sm info */ + /** + * 初始化段管理器的信息,例如段的总数,main area段数 + */ sbi->sm_info = sm_info; sm_info->segment_count = le64_to_cpu(raw_super->segment_count); main_segments = le64_to_cpu(raw_super->segment_count_main); sm_info->main_segments = main_segments; + /** + * main area区预先给user分区的段数和其他段数 + */ user_segments = sm_info->main_segments * (100 - DEF_OP_SEGMENTS) / 100; sm_info->ovp_segments = sm_info->main_segments - user_segments; + /** + *定义无效的块数的上限以及空闲块的上限,以及在危急情况下空闲块的上限 + */ sm_info->limit_invalid_blocks = main_segments * HMFS_PAGE_PER_SEG * LIMIT_INVALID_BLOCKS / 100; sm_info->limit_free_blocks = main_segments * HMFS_PAGE_PER_SEG @@ -678,6 +1217,9 @@ int build_segment_manager(struct hmfs_sb_info *sbi) sm_info->severe_free_blocks = main_segments * HMFS_PAGE_PER_SEG * SEVERE_FREE_BLOCKS / 100; + /** + *生成SIT信息,空闲段位图信息等 + */ err = build_sit_info(sbi); if (err) return err; @@ -689,6 +1231,9 @@ int build_segment_manager(struct hmfs_sb_info *sbi) return err; /* reinit free segmap based on SIT */ + /** + * 基于SIT表信息,重新初始化空闲段的位图,脏的段的位图信息 + */ build_sit_entries(sbi); init_free_segmap(sbi); @@ -699,60 +1244,135 @@ int build_segment_manager(struct hmfs_sb_info *sbi) init_min_max_mtime(sbi); return 0; } - +/* + *cc29 destroy_dirty_segmap:销毁脏的段的位图信息 + *@sbi:指向hmfs超级块信息的实例 + */ +/** + * 先根据参数获取当前指针指向的对象所在的段号 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] addr 块地址 + * @param[out] 如果该段号等于检查点指针的数据块所在的段号,则返回当前检查点所在的数据的偏移,证明该地址有效, + * 同理,如果等于当前node所在的段号,则返回当前检查点所在的node的偏移,也证明该地址有效,否则,为无效地址,置为0 + * @return 0,执行成功,非0,失败, + * @ref segment.h + * @see + * @note + */ static void destroy_dirty_segmap(struct hmfs_sb_info *sbi) { + /** + * 初始化脏段的信息 + */ struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); if (!dirty_i) return; + /** + * 释放脏段的位图信息,并将脏段的信息置为空 + */ kfree(dirty_i->dirty_segmap); SM_I(sbi)->dirty_info = NULL; kfree(dirty_i); } +/* + *cc30 destroy_curseg:销毁当前active的段信息 + *@sbi:指向hmfs超级块信息的实例 + */ +/** + * destroy_curseg:销毁当前active的段信息 + * @param[in] sbi 指向超级块信息的指针实例 + * @ref segment.h + * @see + * @note + */ static void destroy_curseg(struct hmfs_sb_info *sbi) { struct curseg_info *array = SM_I(sbi)->curseg_array; if (!array) return; + /** + *将*脏的active段置为空 + */ SM_I(sbi)->curseg_array = NULL; kfree(array); } - +/* + *31cc destroy_free_segmap: + *@sbi:指向hmfs超级块信息的实例 + */ +/** + * destroy_free_segmap:收回空闲段 + * @param[in] sbi 指向hmfs超级块信息的实例 + * @ref segment.h + * @see + * @note + */ static void destroy_free_segmap(struct hmfs_sb_info *sbi) { struct free_segmap_info *free_i = SM_I(sbi)->free_info; if (!free_i) return; + /** + * 释放空段及预分配的空段的信息 + */ + SM_I(sbi)->free_info = NULL; kfree(free_i->free_segmap); kfree(free_i->prefree_segmap); kfree(free_i); } +/* + * cc32 destroy_sit_info: + * @sbi:指向hmfs超级块信息的实例 + */ static void destroy_sit_info(struct hmfs_sb_info *sbi) { + /** + *获取SIT信息表的实例 + */ struct sit_info *sit_i = SIT_I(sbi); if (!sit_i) return; + /** + * 释放SIT表的段缓存对象和entry位图对象,同时将SIT信息表内容置为空 + */ vfree(sit_i->sentries); kfree(sit_i->dirty_sentries_bitmap); SM_I(sbi)->sit_info = NULL; kfree(sit_i); } - +/* + *cc33: destroy_segment_manager:释放段管理器 + *@sbi:指向hmfs超级块信息的实例 + */ +/** + * 先根据参数获取当前指针指向的对象所在的段号 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] addr 块地址 + * @param[out] 如果该段号等于检查点指针的数据块所在的段号,则返回当前检查点所在的数据的偏移,证明该地址有效, + * 同理,如果等于当前node所在的段号,则返回当前检查点所在的node的偏移,也证明该地址有效,否则,为无效地址,置为0 + * @return 0,执行成功,非0,失败, + * @ref segment.h + * @see + * @note + */ void destroy_segment_manager(struct hmfs_sb_info *sbi) { struct hmfs_sm_info *sm_info = SM_I(sbi); + /** + * 释放段管理器,同时将段管理器的信息置为空 + */ destroy_dirty_segmap(sbi); destroy_curseg(sbi); destroy_free_segmap(sbi); @@ -760,16 +1380,49 @@ void destroy_segment_manager(struct hmfs_sb_info *sbi) sbi->sm_info = NULL; kfree(sm_info); } - +/* + * cc34:get_summary_block:返回指定块的entry的入口地址 + * @sbi:指向hmfs超级块信息的实例 + * @return:返回入口地址 + */ +/** + * 先根据参数获取当前指针指向的对象所在的段号 + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] addr 块地址 + * @param[out] 如果该段号等于检查点指针的数据块所在的段号,则返回当前检查点所在的数据的偏移,证明该地址有效, + * 同理,如果等于当前node所在的段号,则返回当前检查点所在的node的偏移,也证明该地址有效,否则,为无效地址,置为0 + * @return 0,执行成功,非0,失败, + * @ref segment.h + * @see + * @note + */ struct hmfs_summary_block *get_summary_block(struct hmfs_sb_info *sbi, seg_t segno) { + /** + *总结块,获取SSA entry块的地址 + */ struct hmfs_summary_block *summary_blk; summary_blk = HMFS_SUMMARY_BLOCK(sbi->ssa_entries); return &summary_blk[segno]; } +/* + *cc35: get_summary_by_addr + *@sbi:指向hmfs超级块信息的实例 + *@blk_addr + *@return:返回主存开始地址 + */ +/** + * get_summary_by_addr + * @param[in] sbi 指向超级块信息的指针实例 + * @param[in] blk_addr 块地址 + * @return 返回主存开始地址 + * @ref segment.h + * @see + * @note + */ struct hmfs_summary *get_summary_by_addr(struct hmfs_sb_info *sbi, block_t blk_addr) { @@ -777,6 +1430,9 @@ struct hmfs_summary *get_summary_by_addr(struct hmfs_sb_info *sbi, unsigned int blkoff; struct hmfs_summary_block *summary_blk = NULL; + /** + *根据当前超级块的SSA入口地址 + */ segno = GET_SEGNO(sbi, blk_addr); blkoff = GET_SEG_OFS(sbi, blk_addr); summary_blk = get_summary_block(sbi, segno); diff --git a/fs/hmfs/super.c b/fs/hmfs/super.c index 17833149..9a807b05 100644 --- a/fs/hmfs/super.c +++ b/fs/hmfs/super.c @@ -63,10 +63,16 @@ static const match_table_t tokens = { /* * ioremap & iounmap + * @param[in] phys_addr 映射起始物理地址 + * @param[in] size 映射大小 + * @return 映射后的虚拟地址的起始地址 */ /** * 将NVM物理地址@phys_addr 建立到内核虚拟空间大小为@size的映射,并返回映射的初始地址 - * / + * @param[in] phys_addr 映射起始物理地址 + * @param[in] size 映射大小 + * @return 映射后的虚拟地址的起始地址 + */ static inline void *hmfs_ioremap(struct super_block *sb, phys_addr_t phys_addr, ssize_t size) { @@ -75,8 +81,9 @@ static inline void *hmfs_ioremap(struct super_block *sb, phys_addr_t phys_addr, return (void __force *)retval; } /** - * 解除虚拟地址@virt_addr的物理地址映射 - * / + * 解除虚拟地址与物理地址的映射 + * @param[in] virt_addr 映射的虚拟地址 + */ static inline int hmfs_iounmap(void *virt_addr) { iounmap((void __iomem __force *)virt_addr); @@ -90,8 +97,11 @@ static inline int hmfs_iounmap(void *virt_addr) * @remount: is remount */ /** - * 解析并执行挂载时输入的相关数据@option - * / + * 解析并执行挂载时输入的相关配置选项 + * param[in] options 配置字符串 + * param[in] remount 是否再次挂载 + * @return 0,执行成功 其它,失败 + */ static int hmfs_parse_options(char *options, struct hmfs_sb_info *sbi, bool remount) { @@ -239,8 +249,10 @@ static int hmfs_parse_options(char *options, struct hmfs_sb_info *sbi, } /** - *以@sb为文件系统起始地址,格式化NVM介质,初始文件系统元数据 - * / + *格式化NVM介质,初始文件系统元数据 + *@param[in] sb 超级块地址,即文件系统起始地址 + *return 0,执行成功 其它,失败 + */ static int hmfs_format(struct super_block *sb) { @@ -477,8 +489,10 @@ static int hmfs_format(struct super_block *sb) } /** - * 验证@start_addr地址处的SB是否有效,返回有效SB地址,同时处理无效SB - * / + * 检验SB是否有效,返回有效SB地址,同时处理无效SB + * @param[in] start_addr 超级块起始地址 + * @return 有效的超级块地址 + */ static struct hmfs_super_block *get_valid_super_block(void *start_addr) { struct hmfs_super_block *super_1, *super_2; @@ -515,8 +529,9 @@ static struct hmfs_super_block *get_valid_super_block(void *start_addr) * sop */ /** - * 初始化(分配)@foo指针所指的hmfs_inode的vfs inode部分 - * / + * 初始化vfs inode + * @param[in] foo hmfs_inode_info指针 + */ static void init_once(void *foo) { struct hmfs_inode_info *fi = (struct hmfs_inode_info *)foo; @@ -525,8 +540,9 @@ static void init_once(void *foo) } /** - * 从超级块@sb中分配一个新的hmfs_inode,返回其vfs inode指针 - * / + * 分配一个新的hmfs_inode + * @return vfs inode指针 + */ static struct inode *hmfs_alloc_inode(struct super_block *sb) { struct hmfs_inode_info *fi; @@ -549,7 +565,7 @@ static struct inode *hmfs_alloc_inode(struct super_block *sb) /** * 释放hmfs_inode相应slab的回调函数 - * / + */ static void hmfs_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); @@ -565,7 +581,7 @@ static void hmfs_destroy_inode(struct inode *inode) } /** * 将inode写回存储介质 - * / + */ int __hmfs_write_inode(struct inode *inode, bool force) { int err = 0, ilock; @@ -588,8 +604,8 @@ int __hmfs_write_inode(struct inode *inode, bool force) return err; } /** - * 写回@inode - * / + * 判断inode是否为脏, 脏则写回NVM + */ static int hmfs_write_inode(struct inode *inode, struct writeback_control *wbc) { if (inode->i_ino < HMFS_ROOT_INO) @@ -603,7 +619,7 @@ static int hmfs_write_inode(struct inode *inode, struct writeback_control *wbc) } /** * 将@inode相应的hmfs_inode标记为DIRTY并加入DIRTY链表 - * / + */ static void hmfs_dirty_inode(struct inode *inode, int flags) { struct hmfs_inode_info *hi = HMFS_I(inode); @@ -618,8 +634,8 @@ static void hmfs_dirty_inode(struct inode *inode, int flags) } /** - * 从NVM删除@inode及相应文件(可能有误,有待进一步确认) - * / + * 从NVM删除inode及相应文件 + */ static void hmfs_evict_inode(struct inode *inode) { struct hmfs_sb_info *sbi = HMFS_I_SB(inode); @@ -662,8 +678,8 @@ static void hmfs_evict_inode(struct inode *inode) clear_inode(inode); } /** - * 为@sbi生成全零页 - * / + * 为sbi生成全零页 + */ static int init_map_zero_page(struct hmfs_sb_info *sbi) { sbi->map_zero_page = alloc_page((GFP_KERNEL | __GFP_ZERO)); @@ -677,7 +693,7 @@ static int init_map_zero_page(struct hmfs_sb_info *sbi) /** * 删除@sbi相应的全零页 - * / + */ static void destroy_map_zero_page(struct hmfs_sb_info *sbi) { hmfs_bug_on(sbi, !PageLocked(sbi->map_zero_page)); @@ -688,7 +704,7 @@ static void destroy_map_zero_page(struct hmfs_sb_info *sbi) } /** * 从内存中删除文件系统相关信息 - * / + */ static void hmfs_put_super(struct super_block *sb) { @@ -714,7 +730,7 @@ static void hmfs_put_super(struct super_block *sb) } /** * 统计文件系统状态 - * / + */ static int hmfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct hmfs_sb_info *sbi = HMFS_SB(dentry->d_sb); @@ -738,7 +754,7 @@ static int hmfs_statfs(struct dentry *dentry, struct kstatfs *buf) } /** * 写文件系统CP - * / + */ int hmfs_sync_fs(struct super_block *sb, int sync) { struct hmfs_sb_info *sbi = HMFS_SB(sb); @@ -758,7 +774,7 @@ int hmfs_sync_fs(struct super_block *sb, int sync) } /** * 写文件系统CP - * / + */ static int hmfs_freeze(struct super_block *sb) { int err; @@ -787,8 +803,9 @@ static struct super_operations hmfs_sops = { .unfreeze_fs = hmfs_unfreeze, }; /** - * 由@sb生成super_block_info - * / + * 由超级块生成super_block_info + * @param[in] 挂载文件系统配置信息 + */ static int hmfs_fill_super(struct super_block *sb, void *data, int slient) { struct inode *root = NULL; @@ -968,7 +985,7 @@ static int hmfs_fill_super(struct super_block *sb, void *data, int slient) } /** * hmfs挂载 - * / + */ struct dentry *hmfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { @@ -988,8 +1005,8 @@ struct file_system_type hmfs_fs_type = { #define AUTHOR_INFO "RADLAB SJTU" #define DEVICE_TYPE "Hybrid in-Memory File System" /** - * 创建hmfs_inode的slab - * / + * 创建hmfs_inode的slab缓存 + */ static int __init init_inodecache(void) { hmfs_inode_cachep = hmfs_kmem_cache_create("hmfs_inode_cache", @@ -1000,7 +1017,7 @@ static int __init init_inodecache(void) } /** * 销毁hmfs_inode的slab - * / + */ static void destroy_inodecache(void) { /* @@ -1012,7 +1029,7 @@ static void destroy_inodecache(void) } /** * 测试文件系统元数据大小 - * / + */ static void hmfs_check_struct_size(void) { BUG_ON(sizeof(struct hmfs_super_block) > HMFS_PAGE_SIZE); @@ -1027,7 +1044,7 @@ static void hmfs_check_struct_size(void) } /** * hmfs模块载入初始化 - * / + */ int init_hmfs(void) { int err; @@ -1073,7 +1090,7 @@ int init_hmfs(void) } /** * hmfs模块退出函数 - * / + */ void exit_hmfs(void) { destroy_mmap_struct_cache(); diff --git a/fs/hmfs/symlink.c b/fs/hmfs/symlink.c index f018ef31..0f16a1da 100644 --- a/fs/hmfs/symlink.c +++ b/fs/hmfs/symlink.c @@ -3,7 +3,9 @@ #include #include "hmfs_fs.h" #include "hmfs.h" - +/** + * 在dir内建立一个符号链接文件并将其内容赋值为symname + */ int hmfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { struct inode *inode; @@ -38,7 +40,9 @@ int hmfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) return 0; } - +/** + *读取符号链接文件的内容 + */ static int hmfs_readlink(struct dentry *dentry, char __user * buffer, int buflen) { @@ -55,7 +59,9 @@ static int hmfs_readlink(struct dentry *dentry, char __user * buffer, return vfs_readlink(dentry, buffer, buflen, data_blk[0]); } - +/** + * 找到符号链接所代表的文件 + */ static void *hmfs_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; @@ -68,7 +74,7 @@ static void *hmfs_follow_link(struct dentry *dentry, struct nameidata *nd) inode_read_unlock(inode); if (err || size != 1 || data_blk[0] == NULL) return ERR_PTR(-ENODATA); - nd_set_link(nd, data_blk[0]); + nd_set_link(nd, [0]); return 0; } diff --git a/fs/hmfs/test/create.sh b/fs/hmfs/test/create.sh new file mode 100755 index 00000000..84d00e16 --- /dev/null +++ b/fs/hmfs/test/create.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +num_file=2048 + +#create testing files, they will be orphan files later +for ((i=0; i<$num_file; i++)); do + touch ~/mount_hmfs/orphan_$i.txt + echo "this is a test file" > ~/mount_hmfs/orphan_$i.txt +done + +echo "$num_file files created..." \ No newline at end of file diff --git a/fs/hmfs/test/delete.sh b/fs/hmfs/test/delete.sh new file mode 100755 index 00000000..2981095f --- /dev/null +++ b/fs/hmfs/test/delete.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +num_file=2048 +for ((i=0; i<$num_file; i++)); do + #remove the file will create an orhan file + rm ~/mount_hmfs/orphan_$i.txt +done + +echo "$num_file files deleted..." + +#check the cmi info +. ./info.sh "cmi" + +#sync the file to enforce doing checkpoint +sync diff --git a/fs/hmfs/test/hold_file_open.py b/fs/hmfs/test/hold_file_open.py new file mode 100644 index 00000000..43401372 --- /dev/null +++ b/fs/hmfs/test/hold_file_open.py @@ -0,0 +1,14 @@ +#!/usr/bin/python3 +from os.path import expanduser + + +home = expanduser('~') +file_list = [] +for i in range(2048): + with open(home + "/mount_hmfs/orphan_{:d}.txt".format(i), 'w') as file: + file_list.append(file) + file.write("ssssssssssssssssssss") + +#hold files +while True: + pass diff --git a/fs/hmfs/test/info.sh b/fs/hmfs/test/info.sh new file mode 100755 index 00000000..6d24a2ed --- /dev/null +++ b/fs/hmfs/test/info.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +hmfs_debug_dir=/sys/kernel/debug/hmfs/1258291200/info +echo "$1" > ${hmfs_debug_dir} & cat ${hmfs_debug_dir} \ No newline at end of file diff --git a/fs/hmfs/test/mount_f2fs.sh b/fs/hmfs/test/mount_f2fs.sh new file mode 100755 index 00000000..f1d13e91 --- /dev/null +++ b/fs/hmfs/test/mount_f2fs.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# create a 100M file +dd if=/dev/zero of=/opt/dev0-backstore bs=1M count=100 + +# create the loopback block device +mknod /dev/fake-dev0 b 7 200 + +losetup /dev/fake-dev0 /opt/dev0-backstore +mount -t f2fs /dev/fake-dev0 ~/mount_f2fs/ \ No newline at end of file diff --git a/fs/hmfs/test/open.c b/fs/hmfs/test/open.c new file mode 100644 index 00000000..d2cd40e5 --- /dev/null +++ b/fs/hmfs/test/open.c @@ -0,0 +1,17 @@ +#include +#include + +int main(void) +{ + FILE* fps[2048]; + char filename[100]; + for (int i = 0; i < 2048; i++) { + sprintf(filename, "/home/wgtdkp/mount_hmfs/orphan_%d.txt", i); + printf("%s\n", filename); + fps[i] = fopen(filename, "r"); + if (!fps[i]) + printf("error!\n"); + } + while (1) {} + return 0; +} \ No newline at end of file diff --git a/fs/hmfs/test/orphan_test.sh b/fs/hmfs/test/orphan_test.sh new file mode 100755 index 00000000..e4105941 --- /dev/null +++ b/fs/hmfs/test/orphan_test.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +num_file=2048 +cd ~/mount_hmfs/ + +#create testing files, they will be orphan files later +for ((i=0; i<$num_file; i++)); do + touch orphan_$i.txt + echo "this is a test file" > orphan_$i.txt +done + +echo ${num_file} "file created" + +#python3 $HOME/hmfs/fs/hmfs/test/hold_file_open.py & + +#for ((i=0; i<$num_file; i++)); do + #remove the file will create an orhan file +# rm orphan_$i.txt +#done + +#cd $HOME/hmfs/fs/hmfs/test/ +#check the cmi info +#. ./info.sh "cmi" + +#sync the file to enforce doing checkpoint +#sync + + + + + diff --git a/fs/hmfs/test/reproduce.sh b/fs/hmfs/test/reproduce.sh new file mode 100755 index 00000000..db99fe55 --- /dev/null +++ b/fs/hmfs/test/reproduce.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cd $HOME/hmfs/fs/hmfs/test/ + +. ./create.sh +. ./delete.sh +. ./create.sh +. ./delete.sh +. ./create.sh +#. ./delete.sh diff --git a/fs/hmfs/util.c b/fs/hmfs/util.c index 6b990fbd..da824af3 100644 --- a/fs/hmfs/util.c +++ b/fs/hmfs/util.c @@ -9,6 +9,10 @@ pte_t * (*hmfs_get_locked_pte) (struct mm_struct *, unsigned long, * FIXME: Any good idea to call the function which is not exported * by macro EXPORT_SYMBOL */ +/** + * 将函数hmfs_get_locked_pte地址值设为内核函数__get_locked_pte的地址 + * @return 成功则返回0,否则返回并打印错误信息 + */ int init_util_function(void) { unsigned long sym_addr = 0; diff --git a/fs/hmfs/xattr.c b/fs/hmfs/xattr.c index 1ac6e3a3..9e74d026 100644 --- a/fs/hmfs/xattr.c +++ b/fs/hmfs/xattr.c @@ -26,7 +26,14 @@ #include "hmfs_fs.h" static const struct xattr_handler *hmfs_xattr_handler_map[]; - +/** + * 寻找存储扩展属性的结构体hmfs_xattr_entry + * @param[in] base_addr 表示遍历的起始地址 + * @param[in] index 表示要寻找的结构体的e_name_index + * @param[in] name_len 表示要寻找的属性的名称长度 + * @param[in] name 表示要寻找的属性的名称 + * @return 返回值为找到的该属性的hmfs_xattr_entry结构体 + */ static struct hmfs_xattr_entry *__find_xattr(void *base_addr, int index, size_t name_len, const char *name) { @@ -43,7 +50,11 @@ static struct hmfs_xattr_entry *__find_xattr(void *base_addr, int index, return entry; } - +/** + * 得到存储文件扩展属性的块在DRAM中的地址 + * @param[in] inode 指向该文件 + * @return 正常时返回其地址,否则返回NULL + */ static void *get_xattr_block(struct inode *inode) { struct hmfs_sb_info *sbi = HMFS_I_SB(inode); @@ -59,7 +70,16 @@ static void *get_xattr_block(struct inode *inode) return ADDR(sbi, xattr_addr); return NULL; } - +/** + * 将扩展属性句柄的prefix字符串,以及参数中的name字符串复制到list中 + * @param[in] dentry 用于索引超级块 + * @param[in] list 用于存储字符串 + * @param[in] list_size 为list存储的最大空间 + * @param[in] name 为拷贝到prefix之后的字符串 + * @param[in] len 为将name拷贝到prefix之后的字符串的长度 + * @param[in] flag 对应扩展属性句柄的种类 + * @return 返回复制的字符串长度 + */ static size_t hmfs_xattr_generic_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t len, int flags) { @@ -92,7 +112,15 @@ static size_t hmfs_xattr_generic_list(struct dentry *dentry, char *list, } return total_len; } - +/** + * 得到扩展属性的属性值 + * @param[in] inode 为要获取扩展属性值得文件inode + * @param[in] index 为要获取的扩展属性的e_name_index + * @param[in] name 为要获取的扩展属性的名称 + * @param[in] buffer 为将属性值复制到的目标地址 + * @param[in] buffer_size 为目标缓冲区最大长度 + * @return 返回值为属性值的字符长度或错误信息 + */ static int __hmfs_getxattr(struct inode *inode, int index, const char *name, void *buffer, size_t buffer_size) { @@ -134,7 +162,16 @@ static int __hmfs_getxattr(struct inode *inode, int index, const char *name, out: return error; } - +/** + * 获取文件扩展属性的属性值的包装函数 + * 调用__hmfs_getxattr函数进行读取 + * @param[in] inode 为要获取扩展属性值得文件inode + * @param[in] index 为要获取的扩展属性的e_name_index + * @param[in] name 为要获取的扩展属性的名称 + * @param[in] buffer 为将属性值复制到的目标地址 + * @param[in] buffer_size 为目标缓冲区最大长度 + * @return 返回值为属性值的字符长度或错误信息 + */ int hmfs_getxattr(struct inode *inode, int index, const char *name, void *buffer, size_t buffer_size) { @@ -145,7 +182,16 @@ int hmfs_getxattr(struct inode *inode, int index, const char *name, inode_read_unlock(inode); return ret; } - +/** + * 获取文件扩展属性 + * 调用函数hmfs_getxattr进行读取 + * @param[in] dentry 为要获取扩展属性值得文件目录项 + * @param[in] flags 为要获取的扩展属性的e_name_index + * @param[in] name 为要获取的扩展属性的名称 + * @param[in] buffer 为将属性值复制到的目标地址 + * @param[in] size 为目标缓冲区最大长度 + * @return 返回值为属性值的字符长度或错误信息 + */ static int hmfs_xattr_generic_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int flags) { @@ -170,12 +216,24 @@ static int hmfs_xattr_generic_get(struct dentry *dentry, const char *name, return hmfs_getxattr(dentry->d_inode, flags, name, buffer, size); } - +/** + * 使base_addr指向的hmfs_xattr_header结构体的h_magic值等于HMFS_X_BLOCK_TAG_XATTR + */ static void init_xattr_block(void *base_addr) { XATTR_HDR(base_addr)->h_magic = cpu_to_le16(HMFS_X_BLOCK_TAG_XATTR); } - +/** + * 设置文件扩展属性值 + * @param[in] inode 为要设置的文件inode + * @param[in] index 为要设置的扩展属性的e_name_index + * @param[in] name 为要设置的属性名 + * @param[in] value 为要设置为的属性值 + * @param[in] size 为该属性值的字符长度 + * @param[in] flags 为XATTR_CREATE时为创建新属性 + * @param[in] flags 为XATTR_REPLACE时为替代已有属性 + * @return 返回值为错误信息 + */ static int __hmfs_setxattr(struct inode *inode, int index, const char *name, const void *value, size_t size, int flags) @@ -285,7 +343,17 @@ static int __hmfs_setxattr(struct inode *inode, int index, out: return error; } - +/** + * 设置文件扩展属性值的包装函数 + * 调用__hmfs_setxattr设置属性 + * @param[in] inode 为要设置的文件inode + * @param[in] index 为要设置的扩展属性的e_name_index + * @param[in] name 为要设置的属性名 + * @param[in] value 为要设置为的属性值 + * @param[in] size 为该属性值的字符长度 + * @param[in] flags 为XATTR_CREATE时为创建新属性,为XATTR_REPLACE时为替代已有属性 + * @return 返回值为错误信息 + */ static int hmfs_setxattr(struct inode *inode, int index, const char *name, const void *value, size_t size, int flags) { @@ -300,7 +368,17 @@ static int hmfs_setxattr(struct inode *inode, int index, const char *name, return err; } - +/** + * 设置文件扩展属性值的包装函数 + * 调用函数hmfs_setxattr设置属性 + * @param[in] dentry 为要设置的文件目录项 + * @param[in] handler_flags 为要设置的扩展属性的e_name_index + * @param[in] name 为要设置的属性名 + * @param[in] value 为要设置为的属性值 + * @param[in] size 为该属性值的字符长度 + * @param[in] flags 为XATTR_CREATE时为创建新属性,为XATTR_REPLACE时为替代已有属性 + * @return 返回值为错误信息 + */ static int hmfs_xattr_generic_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int handler_flags) { @@ -325,19 +403,30 @@ static int hmfs_xattr_generic_set(struct dentry *dentry, const char *name, return hmfs_setxattr(dentry->d_inode, handler_flags, name, value, size, flags); } - +/** + * 将list字符串值设置为系统建议值 + * @param[in] list 为字符串起始地址 + * @param[in] list_size 为list存储的最大长度 + * 其他参数无意义 + * @return 返回设置后的list字符串长度 + */ static size_t hmfs_xattr_advise_list(struct dentry *dentry, char *list, size_t list_size, const char *name, size_t len, int flags) { const char *xname = HMFS_SYSTEM_ADVISE_PREFIX; size_t size; - size = strlen(xname) + 1; if (list && size <= list_size) memcpy(list, xname, size); return size; } - +/** + * 获取文件扩展属性建议值 + * @param[in] dentry 为该文件目录项 + * @param[in] name 为扩展属性名 + * @param[out] buffer 被设置为指向文件i_advise值的地址 + * @return char型数据长度 + */ static int hmfs_xattr_advise_get(struct dentry *dentry, const char *name, void *buffer, size_t size, int flags) { @@ -352,7 +441,14 @@ static int hmfs_xattr_advise_get(struct dentry *dentry, const char *name, inode_read_unlock(inode); return sizeof(char); } - +/** + * 设置文件扩展属性建议值 + * @param[in] dentry 为该文件目录项 + * @param[in] name 为扩展属性名 + * @param[in] value 指向要设置的属性建议值 + * 其他参数无意义 + * @return 成功时返回0,否则返回错误信息 + */ static int hmfs_xattr_advise_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int handler_flag) { @@ -371,7 +467,13 @@ static int hmfs_xattr_advise_set(struct dentry *dentry, const char *name, mark_inode_dirty(inode); return 0; } - +/** + * 初始化文件扩展属性 + * @param[in] inode 为该文件inode + * @param[in] xattr_array 为要设置的扩展属性初始值的结构体数组初始地址 + * @param[in] page 无意义 + * @return 成功时返回0,否则返回错误信息 + */ static int hmfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, void *page) { @@ -386,7 +488,10 @@ static int hmfs_initxattrs(struct inode *inode, const struct xattr *xattr_array, } return err; } - +/** + * 安全模式初始化扩展属性 + * 调用内核函数security_inode_init_security完成 + */ int hmfs_init_security(struct inode *inode ,struct inode *dir, const struct qstr *qstr, struct page *ipage) { @@ -446,7 +551,9 @@ const struct xattr_handler *hmfs_xattr_handlers[] = { &hmfs_acl_default_handler, NULL, }; - +/** + * @return 返回第index个扩展属性句柄 + */ static inline const struct xattr_handler *hmfs_xattr_handler(int index) { const struct xattr_handler *handler = NULL; @@ -454,7 +561,13 @@ static inline const struct xattr_handler *hmfs_xattr_handler(int index) handler = hmfs_xattr_handler_map[index]; return handler; } - +/** + *将文件的扩展属性名称复制到列表中 + *@param[in] dentry 指向文件目录项 + *@param[in] buffer 指向列表所在缓冲区指针 + *@param[in] buffer_size 为缓冲区大小 + *@return 返回值为正时表示所使用的缓冲区空间大小,返回值为负时表示缓冲区空间不够存储该列表 + */ ssize_t hmfs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) { struct inode *inode =dentry->d_inode;