📄 commit.c.txt
字号:
any problems, send mails to sindybear@163.com
相关文件
/fs/jbd/journal.c
void journal_commit_transaction(journal_t *journal)
lock_journal(journal); //锁定日志 保护journal->j_running_transaction
commit_transaction = journal->j_running_transaction; //得到正在运行的事务
commit_transaction->t_state = T_LOCKED; //事务的状态置为lock
while (commit_transaction->t_updates != 0) { //如果事务中还有没有完成的写操作
unlock_journal(journal);
sleep_on(&journal->j_wait_updates); //等待日志中的更新操作完成
lock_journal(journal);
}
if (journal->j_flags & JFS_FLUSHED) {
journal_update_superblock(journal, 1); //更新超级块 ???
while (commit_transaction->t_reserved_list) { //如果还有reserved的buffer,先处理
jh = commit_transaction->t_reserved_list;
journal_refile_buffer(jh);
}
/*
* 先对checkpointing_list进行处理,这样可以释放一定的内存
*/
__journal_clean_checkpoint_list(journal);
journal_write_revoke_records(journal, commit_transaction); //???
// 将transaction从running_transaction队列搬到committing_transaction队列
journal->j_committing_transaction = commit_transaction;
journal->j_running_transaction = NULL;
//设置这个事务在日志区的开始块,其实也就是日志的head
commit_transaction->t_log_start = journal->j_head;
…… //将这个事务的t_sync_datalist中的数据写到磁盘上
…… //将这个事务的t_async_datalist中的数据写到磁盘上
/*=====设置事务的状态为提交状态,这是开始真正的工作了========*/
commit_transaction->t_state = T_COMMIT;
descriptor = 0; //将descriptor的jh初始化为0
bufs = 0; //写出的buf数目设置为0
while (commit_transaction->t_buffers) { //如果这个事务的t_buffers队列不是空
jh = commit_transaction->t_buffers; //取下来一个jh
if (!descriptor) { //如果还没有一个descriptor
descriptor = journal_get_descriptor_buffer(journal);//生成一个。
bh = jh2bh(descriptor); //取出相应的bh结构
header = (journal_header_t *)&bh->b_data[0];//数据区的开始是header结构
header->h_magic = htonl(JFS_MAGIC_NUMBER); //设置magic
header->h_blocktype = htonl(JFS_DESCRIPTOR_BLOCK); //设置块类型--开始标记
header->h_sequence = htonl(commit_transaction->t_tid);//序列号
tagp = &bh->b_data[sizeof(journal_header_t)];//header后面是tag信息
wbuf[bufs++] = bh; //加入到写出的bh的数组中
journal_file_buffer(descriptor, commit_transaction,
BJ_LogCtl);//将这个控制jh加入到事务的t_log_list中
}
//找到下一个块要写到日志的哪一个块中,blocknr种就包含这个块号
journal_next_log_block(journal, &blocknr);
/*
* 这个是整个函数中最为重要的一个地方,他将从t_buffers中取下来的
* jh分成两份,也就是生成了new_jh,然后将原来的jh加入到这个事务的
* t_iobuf_list中,新生成的new_jh加入到t_shadow_list中。
*/
flags = journal_write_metadata_buffer(commit_transaction,
jh, &new_jh, blocknr);
wbuf[bufs++] = jh2bh(new_jh); //加入到写出的bh的数组中
tag = (journal_block_tag_t *) tagp;
…… //设置这个bh所对应的tag信息。
/*
* 如果这个数组满了,或者前面的descriptor满了,就要重新换一个
* 新的descriptor,将现在的数组中的bh都写处到磁盘上。
*/
if (bufs == ARRAY_SIZE(wbuf) ||
commit_transaction->t_buffers == NULL ||
space_left < sizeof(journal_block_tag_t) + 16) {
for (i=0; i<bufs; i++) { //写出到磁盘上
struct buffer_head *bh = wbuf[i];
clear_bit(BH_Dirty, &bh->b_state);
bh->b_end_io = journal_end_buffer_io_sync;
submit_bh(WRITE, bh);
}
descriptor = NULL; //重新设置descriptor
bufs = 0; //重新设置数组指针。
}
}
/*
* 如果t_iobuf_list中的数据还没有写完,就等待这些bh写完,然后
* 将他们方如t_forget_list队列中??
*/
while (commit_transaction->t_iobuf_list != NULL) {
jh = commit_transaction->t_iobuf_list->b_tprev; //得到一个jh。
bh = jh2bh(jh); //取出bh
if (buffer_locked(bh)) { //如果bh是锁定的
unlock_journal(journal);
wait_on_buffer(bh); //等待解锁
lock_journal(journal);
goto wait_for_iobuf; //下一个
}
journal_unfile_buffer(jh); //将这个jh从t_iobuf_list中去掉
jh->b_transaction = NULL;
bh = jh2bh(jh);
__brelse(bh); //释放这个bh
jh = commit_transaction->t_shadow_list->b_tprev;//得到t_shadows_list中的jh
bh = jh2bh(jh);
clear_bit(BH_JWrite, &bh->b_state);
__brelse(bh); //释放
}
/*
* 等待t_iobuf_list中的数据写到磁盘上去,也就是等待那个descriptor写到磁盘上去
*/
while (commit_transaction->t_log_list != NULL) {
jh = commit_transaction->t_log_list->b_tprev;
bh = jh2bh(jh);
if (buffer_locked(bh)) {
unlock_journal(journal);
wait_on_buffer(bh);
lock_journal(journal);
goto wait_for_ctlbuf;
}
journal_unfile_buffer(jh); //从t_log_list中去掉
}
/*
* 写这个事务的commit纪录,也就是标记这个事务结束了
*/
descriptor = journal_get_descriptor_buffer(journal); //生成一个descriptor
/*
* 只写512个字节,也就是一个扇区,这样操作可以保证原子性
*/
for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
journal_header_t *tmp =
(journal_header_t*)jh2bh(descriptor)->b_data;
tmp->h_magic = htonl(JFS_MAGIC_NUMBER); //表明是一个header
tmp->h_blocktype = htonl(JFS_COMMIT_BLOCK); //表明是一个事务的结束
tmp->h_sequence = htonl(commit_transaction->t_tid);//这个事务的序列号
}
struct buffer_head *bh = jh2bh(descriptor);
clear_bit(BH_Dirty, &bh->b_state);
bh->b_end_io = journal_end_buffer_io_sync;
submit_bh(WRITE, bh); //提交这个bh
wait_on_buffer(bh); //等待完成
put_bh(bh);
journal_unlock_journal_head(descriptor);
/*================核心工作完成了=============================*/
while (commit_transaction->t_forget) {
……
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -