结构体代码
struct r5l_log {
struct md_rdev *rdev;
u32 uuid_checksum;
sector_t device_size; /* log device size, round to
* BLOCK_SECTORS */
sector_t max_free_space; /* reclaim run if free space is at
* this size */
sector_t last_checkpoint; /* log tail. where recovery scan
* starts from */
u64 last_cp_seq; /* log tail sequence */
sector_t log_start; /* log head. where new data appends */
u64 seq; /* log head sequence */
sector_t next_checkpoint;
u64 next_cp_seq;
struct mutex io_mutex;
struct r5l_io_unit *current_io; /* current io_unit accepting new data */
spinlock_t io_list_lock;
struct list_head running_ios; /* io_units which are still running,
* and have not yet been completely
* written to the log */
struct list_head io_end_ios; /* io_units which have been completely
* written to the log but not yet written
* to the RAID */
struct list_head flushing_ios; /* io_units which are waiting for log
* cache flush */
struct list_head finished_ios; /* io_units which settle down in log disk */
struct bio flush_bio;
struct kmem_cache *io_kc;
struct md_thread *reclaim_thread;
unsigned long reclaim_target; /* number of space that need to be
* reclaimed. if it's 0, reclaim spaces
* used by io_units which are in
* IO_UNIT_STRIPE_END state (eg, reclaim
* dones't wait for specific io_unit
* switching to IO_UNIT_STRIPE_END
* state) */
wait_queue_head_t iounit_wait;
struct list_head no_space_stripes; /* pending stripes, log has no space */
spinlock_t no_space_stripes_lock;
bool need_cache_flush;
bool in_teardown;
};
一、几个重要的元素
log_start
功能:新数据在log中的起始扇区
变化:向磁盘写新页的时候,扇区加8(为什么是8呢,因为默认一页是8个扇区呀)
current_io
功能:正在接收数据的结构体
初始化:创建meta时,log->current_io = r5l_new_meta(log)
删除:写log的时候,log->current_io = NULL
二、链表
running_ios:
功能:组织接收数据,没有完全写入log的io
初始化:初始化log的时候,INIT_LIST_HEAD(&log->running_ios)
进:创建meta的时候,io加入list_add_tail(&io->log_sibling, &log->running_ios)
出:如果io的state位是IO_UNIT_IO_END,io就会从running_ios移到finished_ios
io_end_ios:
功能:组织写入log,没有写入RAID的io(need_cache_flush)
初始化:初始化log的时候,INIT_LIST_HEAD(&log->io_end_ios)
进:当log->need_cache_flush为真的时候,r5l_move_io_unit_list(&log->running_ios, &log->io_end_ios, IO_UNIT_IO_END);
出:加到flushing_ios ;list_splice_tail_init(&log->io_end_ios, &log->flushing_ios)
flushing_ios
功能:组织flush的io
初始化:初始化log的时候,INIT_LIST_HEAD(&log->flushing_ios)
进:
出:从io->stripe_list取下来后,提交sh,list_splice_tail_init(&log->flushing_ios, &log->finished_ios)
finished_ios
功能:组织已经写入log的io
初始化:初始化log的时候,INIT_LIST_HEAD(&log->finished_ios)
进;
出:r5l_complete_finished_ios,
no_space_stripes
功能:因log没有空间而pending的条带
初始化:
进:准备写log时,log没有空间存放,list_add_tail(&sh->log_list, &log->no_space_stripes)
出:log空间回收后,sh = list_first_entry(&log->no_space_stripes, struct stripe_head, log_list); list_del_init(&sh->log_list); 接着set_bit(STRIPE_HANDLE, &sh->state); raid5_release_stripe(sh)
三、几个有点难的元素
struct kmem_cache *io_kc:
赋值:log->io_kc = KMEM_CACHE(r5l_io_unit, 0)
使用:申请io,io = kmem_cache_zalloc(log->io_kc, GFP_NOIO | __GFP_NOFAIL)
释放:kmem_cache_destroy(log->io_kc)
struct md_thread *reclain_target
功能:回收的线程
wait_queue_head_t iounit_wait
初始化:init_waitqueue_head(&log->iounit_wait)
唤醒:wake_up(&log->iounit_wait)
使用:回收的时候wait_event_lock_irq(log->iounit_wait, r5l_reclaimable_space(log) > reclaimable, log->io_list_lock);