1、page
结构体struct page定义在/include/linux/mm_types.h。page描述的是一片实际物理内存信息,一般是4K大小,简称页。在page中保存有状态信息,和文件系统,内存交换等方面的信息,唯独没有保存物理内存的偏移,即其代表4K是物理内存什么位置的4K。
这个信息实际是被隐式保存起来了,因为所有的struct page结构体都共同保存在同一个mem_map数组里面,数组下标实际就是物理内存位置。因此page就代表了内存。
2、Buffer Head
Buffer Head的结构体定义在/include/linux/buffer_head.h。一般不容易理解其作用,代码上也经常和page混在一起。它其实表针的不是内存,虽然名称里面有buffer字眼。它实际代表的是物理内存映射的块设备偏移位置。
struct buffer_head {
unsigned long b_state; /* buffer state bitmap (see above) */
struct buffer_head *b_this_page;/* circular list of page's buffers */
struct page *b_page; /* the page this bh is mapped to */
sector_t b_blocknr; /* start block number */
size_t b_size; /* size of mapping */
char *b_data; /* pointer to data within the page */
struct block_device *b_bdev;
bh_end_io_t *b_end_io; /* I/O completion */
void *b_private; /* reserved for b_end_io */
struct list_head b_assoc_buffers; /* associated with another mapping */
struct address_space *b_assoc_map; /* mapping this buffer is
associated with */
atomic_t b_count; /* users using this buffer_head */
};
举个简单例子,从块设备/dev/block/sda的第512 sector上的读取一个4K大小的数据,需要用一个page结构来缓存这个数据,而这个512 sector偏移这个信息则由buffer_head来保存。
所以page是存数据,buffer_head是存偏移。两个结构体内部互有指针保存相互的地址。一般一个buffer_head也表征4K大小,这样一个buffer_head正好对应一个page。某些文件系统可能采用更小的block size,例如1K,或者512字节。这样一个page最多可以用4或者8个buffer_head结构体来描述其内存对应的物理磁盘位置。
buffer_head是内核page与磁盘上物理数据块之间的桥梁。
3、原子操作handle
修改文件系统的任一系统调用通常都被划分为操作磁盘数据结构的一系列低级操作。
ext4需保证系统调用以原子地方式进行处理。原子操作处理(atomic operation handle)是对磁盘数据结构的一组低级操作,这组低级操作对应一个单独的高级操作。当从系统故障中恢复时,文件系统确保要么整个高级操作起作用,要么没有一个低级操作起作用。
任何原子操作处理都用类型为handle_t的描述符来表示。该描述符定义在include\linux\jdb2.h中:
typedef struct jbd2_journal_handle handle_t; /* Atomic operation type */
它实际为jdb2_journal_handle类型,查看该类型定义:
struct jbd2_journal_handle
{
union {
/* Which compound transaction is this update a part of? */
transaction_t *h_transaction;
/* Which journal handle belongs to - used iff h_reserved set */
journal_t *h_journal;
};
/* Handle reserved for finishing the logical operation */
handle_t *h_rsv_handle;
/* Number of remaining buffers we are allowed to dirty: */
int h_buffer_credits;
/* Reference count on this handle */
int h_ref;
/* Field for caller's use to track errors through large fs */
/* operations */
int h_err;
/* Flags [no locking] */
unsigned int h_sync: 1; /* sync-on-close */
unsigned int h_jdata: 1; /* force data journaling */
unsigned int h_reserved: 1; /* handle with reserved credits */
unsigned int h_aborted: 1; /* fatal error on handle */
unsigned int h_type: 8; /* for handle statistics */
unsigned int h_line_no: 16; /* for handle statistics */
unsigned long h_start_jiffies;
unsigned int h_requested_credits;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map h_lockdep_map;
#endif
};
在linux\jdb2\transaction.c中,函数jdb2_journal_start函数,其注释如下图所示

获取当前的handle:
handle_t *handle = journal_current_handle();
4、事务transaction
处于效率的原因,JDB2对日志的处理采用分组的方式,把属于几个原子操作处理的日志记录分组放在一个单独的事务(transaction)中。此外,与一个处理相关的所有日志记录都必须包含在同一个事务中。
一个事务的所有日志记录存放在日志的连续块中。JDB把每个事务作为整体来处理。只有当包含在一个事务的日志记录中的所有数据都提交给文件系统时才回收该事务所有块。
事务一旦被创建,它就能接收新处理的日志记录。当下列情况之一发生时,事务就停止接受新处理:
(1)固定的时间已经过去,例如5s
(2)日志中没有空闲块留给新处理。
事务由transaction_t描述符来表示,transaction_t定义在文件include\linux\journal-head.h中:
typedef struct transaction_s transaction_t; /* Compound transaction type */
可以看到transaction_t实际上是transaction_s,查看transaction_s的内容。
struct transaction_s
{
/* Pointer to the journal for this transaction. [no locking] */
journal_t *t_journal;
/* Sequence number for this transaction [no locking] */
tid_t t_tid;
/*
* Transaction's current state
* [no locking - only kjournald2 alters this]
* [j_list_lock] guards transition of a transaction into T_FINISHED
* state and subsequent call of __jbd2_journal_drop_transaction()
* FIXME: needs barriers
* KLUDGE: [use j_state_lock]
*/
enum {
T_RUNNING,
T_LOCKED,
T_FLUSH,
T_COMMIT,
T_COMMIT_DFLUSH,
T_COMMIT_JFLUSH,
T_COMMIT_CALLBACK,
T_FINISHED
} t_state;
/*
* Where in the log does this transaction's commit start? [no locking]
*/
unsigned long t_log_start;
/* Number of buffers on the t_buffers list [j_list_lock] */
int t_nr_buffers;
/*
* Doubly-linked circular list of all buffers reserved but not yet
* modified by this transaction [j_list_lock]
*/
struct journal_head *t_reserved_list;
/*
* Doubly-linked circular list of all metadata buffers owned by this
* transaction [j_list_lock]
*/
struct journal_head *t_buffers;
/*
* Doubly-linked circular list of all forget buffers (superseded
* buffers which we can un-checkpoint once this transaction commits)
* [j_list_lock]
*/
struct journal_head *t_forget;
/*
* Doubly-linked circular list of all buffers still to be flushed before
* this transaction can be checkpointed. [j_list_lock]
*/
struct journal_head *t_checkpoint_list;
/*
* Doubly-linked circular list of all buffers submitted for IO while
* checkpointing. [j_list_lock]
*/
struct journal_head *t_checkpoint_io_list;
/*
* Doubly-linked circular list of metadata buffers being shadowed by log
* IO. The IO buffers on the iobuf list and the shadow buffers on this
* list match each other one for one at all times. [j_list_lock]
*/
struct journal_head *t_shadow_list;
/*
* List of inodes whose data we've modified in data=ordered mode.
* [j_list_lock]
*/
struct list_head t_inode_list;
/*
* Protects info related to handles
*/
spinlock_t t_handle_lock;
/*
* Longest time some handle had to wait for running transaction
*/
unsigned long t_max_wait;
/*
* When transaction started
*/
unsigned long t_start;
/*
* When commit was requested
*/
unsigned long t_requested;
/*
* Checkpointing stats [j_checkpoint_sem]
*/
struct transaction_chp_stats_s t_chp_stats;
/*
* Number of outstanding updates running on this transaction
* [t_handle_lock]
*/
atomic_t t_updates;
/*
* Number of buffers reserved for use by all handles in this transaction
* handle but not yet modified. [t_handle_lock]
*/
atomic_t t_outstanding_credits;
/*
* Forward and backward links for the circular list of all transactions
* awaiting checkpoint. [j_list_lock]
*/
transaction_t *t_cpnext, *t_cpprev;
/*
* When will the transaction expire (become due for commit), in jiffies?
* [no locking]
*/
unsigned long t_expires;
/*
* When this transaction started, in nanoseconds [no locking]
*/
ktime_t t_start_time;
/*
* How many handles used this transaction? [t_handle_lock]
*/
atomic_t t_handle_count;
/*
* This transaction is being forced and some process is
* waiting for it to finish.
*/
unsigned int t_synchronous_commit:1;
/* Disk flush needs to be sent to fs partition [no locking] */
int t_need_data_flush;
/*
* For use by the filesystem to store fs-specific data
* structures associated with the transaction
*/
struct list_head t_private_list;
};
其中比较重要的字段为t_state,t_state描述了事务当前的状态。
720



被折叠的 条评论
为什么被折叠?



