📄 inode.c
字号:
filemap_fdatasync(inode->i_mapping);/*分析一遍inode->i_mapping的dirty pages,
*并写每一页
*/
/**
* filemap_fdatasync - walk the list of dirty pages of the given address space
* and writepage() all of them.
*
* @mapping: address space structure to write
*
*/
/* Don't write the inode if only I_DIRTY_PAGES was set */
if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))/*判断是不只设置了I_DIRTY_PAGES 位脏*/
write_inode(inode, sync);/*调用write_inode()写inode到设备上*/
filemap_fdatawait(inode->i_mapping);/*分析一遍inode->i_mapping的dirty pages,
*并等待每一页被解锁
*/
/**
* filemap_fdatawait - walk the list of locked pages of the given address space
* and wait for all of them.
*
* @mapping: address space structure to wait for
*
*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
inode->i_state &= ~I_LOCK;/*清除该inode上的锁*/
if (!(inode->i_state & I_FREEING)) {/*inode不是空闲的*/
struct list_head *to;/*声明一个链表指针to*/
if (inode->i_state & I_DIRTY)/*inode为脏*/
to = &inode->i_sb->s_dirty;/*to链表指针指向inode的超块的s_dirty链表头*/
else if (atomic_read(&inode->i_count))/*inode不为脏,且原子操作读引用计数不为0*/
to = &inode_in_use;/*to链表指针指向inode_in_use*/
else/*inode不为脏,但原子操作读引用计数为0*/
to = &inode_unused;/*to链表指针指向inode_unused*/
list_del(&inode->i_list);/*将该 inode对象从原来的“类型”链表中删除*/
list_add(&inode->i_list, to);/*并将其链入到to链表中*/
}
wake_up(&inode->i_wait);/*唤醒在该inode上等待的进程*/
}
/*等待被上锁的inode解锁,对未上锁的inode同步写回块设备*/
static inline void sync_one(struct inode *inode, int sync)
{
if (inode->i_state & I_LOCK) {/*inode被上锁*/
__iget(inode);/*增加一个inode对象的引用计数*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
__wait_on_inode(inode);/*等待一个inode对象被解锁*/
iput(inode); /*释放对一个inode对象的引用*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
} else {/*inode未被上锁*/
__sync_one(inode, sync);/*将一个指定的脏inode同步写回块设备*/
}
}
/*将一个脏inode队列中的所有inode同步写回块设备*/
static inline void sync_list(struct list_head *head)
{
struct list_head * tmp;/*声明list_head指针tmp*/
while ((tmp = head->prev) != head) /*tmp赋值为head->prev,并当tmp不为head时,
*持续循环,顺序搜索队列head
*/
__sync_one(list_entry(tmp, struct inode, i_list), 0);/*将一个指定的脏inode同步写回块设备*/
}
/*等待将一个链表上锁*/
static inline void wait_on_locked(struct list_head *head)
{
struct list_head * tmp;/*声明一个list_head类型指针tmp*/
while ((tmp = head->prev) != head) {/*tmp赋值为head->prev,并判断是否等于head,
*不相等时进入循环体执行,
*顺序搜索队列head
*/
struct inode *inode = list_entry(tmp, struct inode, i_list);/*inode指向从list_head类型的域找到inode类型的域*/
/*
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
__iget(inode);/*增加一个对inode的引用计数*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
__wait_on_inode(inode);/*等待inode被解锁*/
iput(inode);/*释放对inode的引用*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
}
}
/*试图同步未使用 的inode链表*/
static inline int try_to_sync_unused_list(struct list_head *head, int nr_inodes)
{
struct list_head *tmp = head;/*声明list_head指针tmp,指向head*/
struct inode *inode;/*声明inode指针*/
/*当cache中的inode对象总数不为0,
*且将tmp赋值为tmp->prev后,tmp不指向head,
*则持续循环,搜索head
*/
while (nr_inodes && (tmp = tmp->prev) != head) {
inode = list_entry(tmp, struct inode, i_list);/*inode指向从list_head类型的域找到inode类型的域*/
if (!atomic_read(&inode->i_count)) {/*原子操作读inode->i_count,inode->i_count为0*/
__sync_one(inode, 0);/*将inode写回块设备*/
nr_inodes--;/*参数中的inode对象数减一*/
/*
* __sync_one moved the inode to another list,
* so we have to start looking from the list head.
*/
/*对上面注释的翻译:
*__sync_one将inode移到另一个链表上,
*所以需要从表头开始继续查找
*/
tmp = head;/*tmp指向head*/
}
}
return nr_inodes;/*返回参数中的inode对象数*/
}
/*单个节点同步回写操作函数*/
/*执行回写操作并等待在文件系统的脏节点上*/
void sync_inodes_sb(struct super_block *sb)
{
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
/*sb->s_dirty不空,或sb->s_locked_inodes不空*/
while (!list_empty(&sb->s_dirty)||!list_empty(&sb->s_locked_inodes)) {
sync_list(&sb->s_dirty);/*将sb->s_dirty中的所有inode同步写回块设备*/
wait_on_locked(&sb->s_locked_inodes);/*等待将sb->s_locked_inodes上锁*/
}
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
}
/*
* Note:
* We don't need to grab a reference to superblock here. If it has non-empty
* ->s_dirty it's hadn't been killed yet and kill_super() won't proceed
* past sync_inodes_sb() until both ->s_dirty and ->s_locked_inodes are
* empty. Since __sync_one() regains inode_lock before it finally moves
* inode from superblock lists we are OK.
*/
/*同步未上锁的inode*/
void sync_unlocked_inodes(void)
{
struct super_block * sb;/*声明super_block指针sb*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
spin_lock(&sb_lock);/*持有自旋锁sb_lock*/
sb = sb_entry(super_blocks.next);/*sb指向从super_blocks.next的域找到super_block类型的域*/
/*sb指向从sb->s_list.next的域找到super_block类型的域,
*只要它与从super_blocks的域找到super_block类型的域不符,
*则持续循环
*/
for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) {
if (!list_empty(&sb->s_dirty)) {/*如果sb->s_dirty不空*/
spin_unlock(&sb_lock);/*释放自旋锁sb_lock*/
sync_list(&sb->s_dirty);/*将sb->s_dirty中的所有inode同步写回块设备*/
spin_lock(&sb_lock);/*持有自旋锁sb_lock*/
}
}
spin_unlock(&sb_lock);/*释放自旋锁sb_lock*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
}
/*
* Find a superblock with inodes that need to be synced
*/
/*获得需要同步的脏的超块结构*/
static struct super_block *get_super_to_sync(void)
{
struct list_head *p;/*声明list_head型指针p*/
restart:
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
spin_lock(&sb_lock);/*持有自旋锁sb_lock*/
/*
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
#define list_for_each(pos, head) \
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
pos = pos->next, prefetch(pos->next))
*/
/*遍历一遍链表super_blocks*/
list_for_each(p, &super_blocks) {
/*从list_head类型的域找到super_block类型的域,
*并赋值给super_block指针型的s
*/
struct super_block *s = list_entry(p,struct super_block,s_list);
/*如果s->s_dirty为空,且s->s_locked_inodes为空*/
if (list_empty(&s->s_dirty) && list_empty(&s->s_locked_inodes))
continue;/*跳过本次循环剩下的部分,直接进入下次循环*/
s->s_count++;/*超块引用计数加一*/
spin_unlock(&sb_lock);/*释放自旋锁sb_lock*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
down_read(&s->s_umount);/*读模块的引用的信号量减一*/
/*
* down_read - lock for reading
*/
/*
* __down_read - get a read lock on the semaphore
*/
if (!s->s_root) {/*超块的根目录为空*/
drop_super(s);/*卸载超块,读引用模块的信号量加一,减少一个超块的引用*/
goto restart;/*跳转到restart程序段*/
}
return s;/*返回找到的需要同步的脏的超块结构*/
}
/*遍历super_blocks都没有找到需要同步的脏块,则执行下面语句*/
spin_unlock(&sb_lock);/*释放自旋锁sb_lock*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
return NULL;/*返回空*/
}
/**
* sync_inodes
* @dev: device to sync the inodes from.
*
* sync_inodes goes through the super block's dirty list,
* writes them out, and puts them back on the normal list.
*/
/*多个节点同步回写操作函数*/
/*遍历每个超级块的脏节点链表,把节点写回到块设备,
*并等待回写的完成,写完成后把节点放回到正常的链表中*/
void sync_inodes(kdev_t dev)
{
struct super_block * s;/*声明一个super_block型指针s*/
/*
* Search the super_blocks array for the device(s) to sync.
*/
if (dev) {/*dev不等于0,同步回写一个设备的超块*/
if ((s = get_super(dev)) != NULL) {/*从块设备上获得了超块*/
sync_inodes_sb(s);/*对单个节点同步回写操作*/
drop_super(s);/*卸载超块,读引用模块的信号量加一,减少一个超块的引用*/
}
} else {/*dev等于0,同步所有需要同步的超块*/
/*当可以得到脏的超块结构,持续循环*/
while ((s = get_super_to_sync()) != NULL) {
sync_inodes_sb(s);/*对单个节点同步回写操作*/
drop_super(s);/*卸载超块,读引用模块的信号量加一,减少一个超块的引用*/
}
}
}
/*试图同步未使用的inode*/
static void try_to_sync_unused_inodes(void * arg)
{
struct super_block * sb;/*声明super_block指针sb*/
int nr_inodes = inodes_stat.nr_unused;/*声明int型nr_inodes ,赋值为inodes_stat.nr_unused
*cache中未使用的inode个数
*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
spin_lock(&sb_lock);/*持有自旋锁sb_lock*/
sb = sb_entry(super_blocks.next);/*sb赋值为从super_blocks.next的域找到super_block类型的域*/
/*sb指向从sb->s_list.next的域找到super_block类型的域,
*只要它与从super_blocks的域找到super_block类型的域不符,
*且cache中总的inode个数不为0
*则持续循环
*/
for (; nr_inodes && sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) {
if (list_empty(&sb->s_dirty))/*如果sb->s_dirty为空*/
continue;/*跳过本次循环的剩余部分,继续下次循环*/
spin_unlock(&sb_lock);/*释放自旋锁sb_lock*/
nr_inodes = try_to_sync_unused_list(&sb->s_dirty, nr_inodes);/*试图同步未使用 的inode链表sb->s_dirty*/
spin_lock(&sb_lock);/*持有自旋锁sb_lock*/
}
spin_unlock(&sb_lock);/*释放自旋锁sb_lock*/
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
}
/*定义静态tq_struct型结构体unused_inodes_flush_task,
*用于链接需要刷新的未使用的inode
*/
static struct tq_struct unused_inodes_flush_task;
/*
struct tq_struct {
struct list_head list; linked list of active bh's
unsigned long sync; must be initialized to zero
void (*routine)(void *); function to call
void *data; argument to function
};
*/
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -