BDI机制原本主要是用于检测磁盘的繁忙程度等作用,从2.6.19内核开始,将此部分功能整合到了mm/backing_dev.c中,一直到2.6.31内核为止,其功能也只是在不段的完善,但是脏数据的下刷依然是依靠pdflush。自2.6.32内核开始,彻底取消了pdflush,而是将此部分功能添加到BDI机制中,并且是为每个设备创建了一个名为“flush-设备主次设备号”的线程,用于脏数据的下刷。
2 结构backing_dev_info
了解BDI机制,首先得清楚结构backing_dev_info,其定义在描述设备的结构gendisk->request_queue内。
2.1 Kernel-2.6.18
在2.6.18内核中其定义如下:
struct backing_dev_info {
unsigned long ra_pages; /* maxreadahead in PAGE_CACHE_SIZE units */
unsigned long state; /* Always use atomic bitops on this */
unsigned int capabilities; /*Device capabilities */
congested_fn *congested_fn; /*Function pointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
void (*unplug_io_fn)(structbacking_dev_info *, struct page *);
void *unplug_io_data;
};
其对应的state状态有:
enum bdi_state {
BDI_pdflush, /* A pdflush thread is working thisdevice */
BDI_write_congested, /* Thewrite queue is getting full */
BDI_read_congested, /* Theread queue is getting full */
BDI_unused, /* Available bits start here */
};
其初始化在:
a) 函数blk_queue_make_request:初始化ra_pages、state、capabilities
b) 函数blk_alloc_queue_node:初始化unplug_io_fn、unplug_io_data
2.2 Kernel-2.6.32
在2.6.32内核中其定义如下:
struct backing_dev_info {
struct list_head bdi_list;
struct rcu_head rcu_head;
unsigned long ra_pages; /* maxreadahead in PAGE_CACHE_SIZE units */
unsigned long state; /* Always use atomic bitops on this */
unsigned int capabilities; /*Device capabilities */
congested_fn *congested_fn; /* Functionpointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
void (*unplug_io_fn)(structbacking_dev_info *, struct page *);
void *unplug_io_data;
char *name; /* device_name */
struct percpu_counterbdi_stat[NR_BDI_STAT_ITEMS];
struct prop_local_percpucompletions;
int dirty_exceeded;
unsigned int min_ratio;
unsigned int max_ratio, max_prop_frac;
struct bdi_writeback wb; /* default writeback info for this bdi */
spinlock_t wb_lock; /* protects update side of wb_list */
struct list_head wb_list; /* theflusher threads hanging off this bdi */
struct list_head work_list;
struct device *dev;
#ifdef CONFIG_DEBUG_FS
struct dentry *debug_dir;
struct dentry *debug_stats;
#endif
};
其对应的state状态有:
enum bdi_state {
BDI_pending, /* On its way to being activated */
BDI_wb_alloc, /* Default embedded wb allocated */
BDI_async_congested, /* Theasync (write) queue is getting full */
BDI_sync_congested, /* Thesync queue is getting full */
BDI_registered, /* bdi_register() was done */
BDI_unused, /* Available bits start here */
};
用于sys接口计数统计的数值:
enum bdi_stat_item {
BDI_RECLAIMABLE,
BDI_WRITEBACK,
NR_BDI_STAT_ITEMS
};
其初始化在:
a) 函数blk_alloc_queue_node:初始化ra_pages、state、capabilities、unplug_io_fn、unplug_io_data、name
b) 函数blk_alloc_que