📄 inode.c
字号:
* write_inode_now - write an inode to disk
* @inode: inode to write to disk
* @sync: whether the write should be synchronous or not
*
* This function commits an inode to disk immediately if it is
* dirty. This is primarily needed by knfsd.
*/
/*写inode到磁盘*/
void write_inode_now(struct inode *inode, int sync)
{
struct super_block * sb = inode->i_sb;/*声明一个超块指针,指向inode->i_sb*/
if (sb) {/*如果sb不为空*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
while (inode->i_state & I_DIRTY)/*当inode脏时*/
sync_one(inode, sync);
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
if (sync)/*需要同步写*/
wait_on_inode(inode);/*测试一个inode对象是否已经被加锁,加锁则等待其被解锁*/
}
else/*sb不存在*/
printk(KERN_ERR "write_inode_now: no super block\n");/*输出错误提示*/
}
/**
* generic_osync_inode - flush all dirty data for a given inode to disk
* @inode: inode to write
* @datasync: if set, don't bother flushing timestamps
*
* This can be called by file_write functions for files which have the
* O_SYNC flag set, to flush dirty writes to disk.
*/
/*刷新所给inode的脏数据到磁盘*/
int generic_osync_inode(struct inode *inode, int what)
{
int err = 0, err2 = 0, need_write_inode_now = 0;
/*
* WARNING
*
* Currently, the filesystem write path does not pass the
* filp down to the low-level write functions. Therefore it
* is impossible for (say) __block_commit_write to know if
* the operation is O_SYNC or not.
*
* Ideally, O_SYNC writes would have the filesystem call
* ll_rw_block as it went to kick-start the writes, and we
* could call osync_inode_buffers() here to wait only for
* those IOs which have already been submitted to the device
* driver layer. As it stands, if we did this we'd not write
* anything to disk since our writes have not been queued by
* this point: they are still on the dirty LRU.
*
* So, currently we will call fsync_inode_buffers() instead,
* to flush _all_ dirty buffers for this inode to disk on
* every O_SYNC write, not just the synchronous I/Os. --sct
*/
if (what & OSYNC_METADATA)
err = fsync_inode_buffers(inode);/*同步所有inode的脏缓冲区到磁盘*/
/* Synchronise all the inode's dirty buffers to the disk.*/
if (what & OSYNC_DATA)
err2 = fsync_inode_data_buffers(inode);/*同步所有inode的脏数据缓冲区到磁盘*/
if (!err)/*err==0*/
err = err2;/*err赋值为err2*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
if ((inode->i_state & I_DIRTY) &&
((what & OSYNC_INODE) || (inode->i_state & I_DIRTY_DATASYNC)))
need_write_inode_now = 1;
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
if (need_write_inode_now)/*如果需要现在写inode到磁盘*/
write_inode_now(inode, 1); /*写inode到磁盘*/
else/*不需要现在就写inode*/
wait_on_inode(inode);/*测试一个inode对象是否已经被加锁,
*加锁则等待其被解锁
*/
return err;
}
/**
* clear_inode - clear an inode
* @inode: inode to clear
*
* This is called by the filesystem to tell us
* that the inode is no longer useful. We just
* terminate it with extreme prejudice.
*/
/*清除一个inode对象中的内容*/
/*
在调用destroy_inode()函数释放一个inode对象之前,
通常调用该函数来清除该inode对象中内容,
如:使inode引用的缓冲区无效、解除对其它对象的引用等。
*/
void clear_inode(struct inode *inode)
{
invalidate_inode_buffers(inode);/*使inode中任何且所有的脏缓冲链表无效,即清除*/
/*
* Invalidate any and all dirty buffers on a given inode. We are
* probably unmounting the fs, but that doesn't mean we have already
* done a sync(). Just drop the buffers from the inode list.
*/
if (inode->i_data.nrpages)/*总页数不等于0*/
BUG();/*调用BUG()*/
if (!(inode->i_state & I_FREEING))/*inode不是正在被释放*/
BUG();/*调用BUG()*/
if (inode->i_state & I_CLEAR)/*inode->i_state是I_CLEAR态*/
BUG();/*调用BUG()*/
wait_on_inode(inode);/*测试一个inode对象是否已经被加锁,加锁则等待其被解锁*/
DQUOT_DROP(inode);/*对inode相应的文件系统限额停止*/
if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)
/*inode->i_sb 存在,inode->i_sb->s_op 存在,i_sb->s_op->clear_inode函数存在*/
inode->i_sb->s_op->clear_inode(inode);/*调用clear_inode()函数,
*释放inode,并清空包含相关数据的所有页面
*/
if (inode->i_bdev)/*inode->i_bdev块设备驱动存在*/
bd_forget(inode);/*删除inode->i_devices,并重新初始化,
*置inode->i_bdev块设备驱动为空,
*inode->i_mapping 指向inode->i_data
*/
/*
list_del_init(&inode->i_devices);list_del_init - deletes entry from list and reinitialize it.
inode->i_bdev = NULL;
inode->i_mapping = &inode->i_data;*/
else if (inode->i_cdev) {/*inode->i_cdev字符设备存在,inode->i_bdev块设备驱动不存在*/
cdput(inode->i_cdev);/*原子操作cdev->count减一,给cdev_lock上锁,
*删除cdev->hash,解锁,释放已分配的缓冲
*/
inode->i_cdev = NULL;/*清空i_cdev */
}
inode->i_state = I_CLEAR;/*设置i_state为清除态,即该inode中内容已被清除*/
}
/*
* Dispose-list gets a local list with local inodes in it, so it doesn't
* need to worry about list corruption and SMP locks.
*/
/*清理处置一个inode链表*/
static void dispose_list(struct list_head * head)
{
struct list_head * inode_entry;/*声明list_head型指针inode_entry*/
struct inode * inode;/*声明inode指针*/
/*inode_entry赋值为head->next,当inode_entry不指向head时,持续循环*/
while ((inode_entry = head->next) != head)
{
list_del(inode_entry);/*将该inode_entry对象从原来的链表中删除*/
inode = list_entry(inode_entry, struct inode, i_list);/*inode指向从inode_entry的域找到inode类型的域*/
if (inode->i_data.nrpages)/*inode的地址空间总页数不为0*/
truncate_inode_pages(&inode->i_data, 0);
/*截短inode的页缓冲,从超过偏移量的部分移出,
*如果该页被锁,那么等待该页被解锁
*/
clear_inode(inode); /*清除一个inode对象中的内容*/
destroy_inode(inode);/*释放inode指针指向的inode对象*/
inodes_stat.nr_inodes--;/*cache中的inode对象总数减一*/
}
}
/*
* Invalidate all inodes for a device.
*/
/*清理回收一个设备的所有inode*/
static int invalidate_list(struct list_head *head, struct super_block * sb, struct list_head * dispose)
{
struct list_head *next;/*声明list_head 型指针next*/
int busy = 0, count = 0;/*声明int型busy、count,并均赋初值为0*/
next = head->next;/*next指向head->next*/
for (;;) {/*无条件循环*/
struct list_head * tmp = next;/*声明list_head 型指针tmp*/
struct inode * inode;/*声明inode指针*/
next = next->next;/*next指向next->next*/
if (tmp == head)/*如果tmp指向head*/
break;/*跳出循环*/
inode = list_entry(tmp, struct inode, i_list);/*inode指向从list_head的域找到inode类型的域*/
if (inode->i_sb != sb)/*inode的相应块设备i_sb 指针不指向sb*/
continue;/*跳过本次循环剩余的部分,直接执行下次循环*/
invalidate_inode_buffers(inode);/*使任何所有inode上的脏缓冲区无效*/
if (!atomic_read(&inode->i_count)) {/*原子操作读inode->i_count,且inode->i_count为0*/
list_del_init(&inode->i_hash);/*删除inode->i_hash,并将其初始化*/
list_del(&inode->i_list);/*将该 inode对象从原来的“类型”链表中删除*/
list_add(&inode->i_list, dispose);/*并将其链到链表dispose上*/
inode->i_state |= I_FREEING;/*设置inode->i_state为I_FREEING空闲态*/
count++;/*count加一*/
continue;/*跳过本次循环剩余的部分,直接执行下次循环*/
}
busy = 1;/*置busy为1*/
}
/* only unused inodes may be cached with i_count zero */
inodes_stat.nr_unused -= count;/*cache中的未使用的inode个数=nr_unused -count*/
return busy;/*返回busy*/
}
/*
* This is a two-stage process. First we collect all
* offending inodes onto the throw-away list, and in
* the second stage we actually dispose of them. This
* is because we don't want to sleep while messing
* with the global lists..
*/
/**
* invalidate_inodes - discard the inodes on a device
* @sb: superblock
*
* Discard all of the inodes for a given superblock. If the discard
* fails because there are busy inodes then a non zero value is returned.
* If the discard is successful all the inodes have been discarded.
*/
/*丢弃一个设备上的inode*/
int invalidate_inodes(struct super_block * sb)
{
int busy;/*声明int型busy*/
LIST_HEAD(throw_away);/*创建一个throw_away队列*/
spin_lock(&inode_lock);/*持有自旋锁inode_lock*/
/*顺序搜索队列inode_in_use,
*将其中属于sb、引用计数为0的inode从hash表中摘下,
*从inode_in_use队列中摘下,加入throw_away队列
*/
busy = invalidate_list(&inode_in_use, sb, &throw_away);
/*顺序搜索队列inode_unused,
*将其中属于sb、引用计数为0的inode从hash表中摘下,
*从inode_unused队列中摘下,加入throw_away队列
*/
busy |= invalidate_list(&inode_unused, sb, &throw_away);
/*顺序搜索队列sb->s_dirty,
*将其中属于sb、引用计数为0的inode从hash表中摘下,
*从sb->s_dirty队列中摘下,加入throw_away队列
*/
busy |= invalidate_list(&sb->s_dirty, sb, &throw_away);
/*顺序搜索队列sb->s_locked_inodes,,
*将其中属于sb、引用计数为0的inode从hash表中摘下,
*从sb->s_locked_inodes,队列中摘下,加入throw_away队列
*/
busy |= invalidate_list(&sb->s_locked_inodes, sb, &throw_away);
spin_unlock(&inode_lock);/*释放自旋锁inode_lock*/
dispose_list(&throw_away);/*清理throw_away队列中的所有inode*/
return busy;
}
/*整理一个设备*/
int invalidate_device(kdev_t dev, int do_sync)
{
struct super_block *sb;/*声明super_block型指针sb*/
int res;/*声明int型res*/
if (do_sync)/*做同步处理,do_sync==1*/
fsync_dev(dev);/*同步缓冲区、inode同步回写、
*inode限额同步、同步文件系统
*/
res = 0;/*置res为0*/
sb = get_super(dev);/*获得一个设备的超块*/
/**
* get_super - get the superblock of a device
* @dev: device to get the superblock for
*
* Scans the superblock list and finds the superblock of the file system
* mounted on the device given. %NULL is returned if no match is found.
*/
if (sb) {
/*
* no need to lock the super, get_super holds the
* read semaphore so the filesystem cannot go away
* under us (->put_super runs with the write lock
* hold).
*/
shrink_dcache_sb(sb);/*缩短超块sb的目录项缓存*/
/**
* shrink_dcache_sb - shrink dcache for a superblock
* @sb: superblock
*
* Shrink the dcache for the specified super block. This
* is used to free the dcache before unmounting a file
* system
*/
res = invalidate_inodes(sb); /*丢弃一个设备上的inode*/
drop_super(sb);/*卸载超块,读引用模块的信号量加一,减少一个超块的引用*/
}
invalidate_buffers(dev);/*使缓冲区无效*/
return res;/*返回res*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -