⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commit.c.txt

📁 linux内核学习笔记 希望想看的人可以很快下载到
💻 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 + -