`
sunzixun
  • 浏览: 74863 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

<linux kernel> 3.2 pdflush change

阅读更多

 

sync_inode - write an inode and its pages to disk.

 * @inode: the inode to sync

 

 

The function is responsible to synchronize all dirty inodes belongings to a given superblock 

 

 

task = kthread_create(bdi_writeback_thread, &bdi->wb,

     "flush-%s", dev_name(bdi->dev));

 

root@szx3:/home/szx# ps -ef|grep flush

root       950     2  0 08:55 ?        00:00:00 [flush-8:0]

bdi_writeback_thread

 

 

struct bdi_writeback {

struct backing_dev_info *bdi; /* our parent bdi */

unsigned int nr;

 

unsigned long last_old_flush; /* last old data flush */

unsigned long last_active; /* last time bdi thread was active */

 

struct task_struct *task; /* writeback thread */

struct timer_list wakeup_timer; /* used for delayed bdi thread wakeup */

struct list_head b_dirty; /* dirty inodes */

struct list_head b_io; /* parked for writeback */

struct list_head b_more_io; /* parked for more writeback */

spinlock_t list_lock; /* protects the b_* lists */

};

 

 

struct backing_dev_info {

struct list_head bdi_list;

unsigned long ra_pages; /* max readahead 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 */

 

char *name;

 

struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];

 

unsigned long bw_time_stamp; /* last time write bw is updated */

unsigned long dirtied_stamp;

unsigned long written_stamp; /* pages written at bw_time_stamp */

unsigned long write_bandwidth; /* the estimated write bandwidth */

unsigned long avg_write_bandwidth; /* further smoothed write bw */

 

/*

 * The base dirty throttle rate, re-calculated on every 200ms.

 * All the bdi tasks' dirty rate will be curbed under it.

 * @dirty_ratelimit tracks the estimated @balanced_dirty_ratelimit

 * in small steps and is much more smooth/stable than the latter.

 */

unsigned long dirty_ratelimit;

unsigned long balanced_dirty_ratelimit;

 

struct prop_local_percpu completions;

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 work_list */

 

struct list_head work_list;

 

struct device *dev;

 

struct timer_list laptop_mode_wb_timer;

 

#ifdef CONFIG_DEBUG_FS

struct dentry *debug_dir;

struct dentry *debug_stats;

#endif

};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

/*

 * Passed into wb_writeback(), essentially a subset of writeback_control

 */

struct wb_writeback_work {

long nr_pages;

struct super_block *sb;

unsigned long *older_than_this;

enum writeback_sync_modes sync_mode;

unsigned int tagged_writepages:1;

unsigned int for_kupdate:1;

unsigned int range_cyclic:1;

unsigned int for_background:1;

enum wb_reason reason; /* why was writeback initiated? */

 

struct list_head list; /* pending work list */

struct completion *done; /* set if the caller waits */

};

 

 

long wb_do_writeback(struct bdi_writeback *wb, int force_wait)

{

struct backing_dev_info *bdi = wb->bdi;

struct wb_writeback_work *work;

long wrote = 0;

 

set_bit(BDI_writeback_running, &wb->bdi->state);

while ((work = get_next_work_item(bdi)) != NULL) {

/*

 * Override sync mode, in case we must wait for completion

 * because this thread is exiting now.

 */

if (force_wait)

work->sync_mode = WB_SYNC_ALL;

 

trace_writeback_exec(bdi, work);

 

wrote += wb_writeback(wb, work);

 

/*

 * Notify the caller of completion if this is a synchronous

 * work item, otherwise just free it.

 */

if (work->done)

complete(work->done);

else

kfree(work);

}

 

/*

 * Check for periodic writeback, kupdated() style

 */

wrote += wb_check_old_data_flush(wb);

wrote += wb_check_background_flush(wb);

clear_bit(BDI_writeback_running, &wb->bdi->state);

 

return wrote;

}

 

 

 the first time one of an inode's pages is dirtied, we mark the dirtying-time in the inode's address_space So this periodic writeback code just walks the superblock inode list, writing back any inodes which are older than a specific point in time.

 

 

__wait_on_bit

 

 

wait_queue_head_t *bit_waitqueue(void *word, int bit)

{

const int shift = BITS_PER_LONG == 32 ? 5 : 6;

const struct zone *zone = page_zone(virt_to_page(word));

unsigned long val = (unsigned long)word << shift | bit;

 

return &zone->wait_table[hash_long(val, zone->wait_table_bits)];

}

 

Zone -> wait_table

 

Zone ->  wait_table_bits

Power-of-2 order of the size of the wait queue hash table array

 

The purpose of all there is to keep track of the people waiting for a page to become available and make them runnable again when possible . The trouble is that this consumes a lot of space ,especially when so few things wait on pages at a given time.

So instead of using per-page wait-queues  , we use a waitqueue hash table.

 

 

 

 

 

BSF - Bit Scan Forward (386+)

        Usage:  BSF     dest,src

        Modifies flags: ZF

        Scans source operand for first bit set.  Sets ZF if a bit is found set and loads the destination with an index to first set bit.  Clears ZF is no bits are found set.  BSF scans forward across bit pattern (0-n) while BSR scans in reverse (n-0).

 

int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)

{

int i;

struct pglist_data *pgdat = zone->zone_pgdat;

size_t alloc_size;

 

/*

 * The per-page waitqueue mechanism uses hashed waitqueues

 * per zone.

 */

zone->wait_table_hash_nr_entries =

 wait_table_hash_nr_entries(zone_size_pages);

zone->wait_table_bits =

wait_table_bits(zone->wait_table_hash_nr_entries);

//....

}

 

 

 

 

 低位 开始搜索 

static inline unsigned long __ffs(unsigned long word)

{

asm("bsf %1,%0"

: "=r" (word)

: "rm" (word));

return word;

}

 

 

 

 

 

 

 */

static void inode_wait_for_writeback(struct inode *inode,

     struct bdi_writeback *wb)

{

DEFINE_WAIT_BIT(wq, &inode->i_state, __I_SYNC);

wait_queue_head_t *wqh;

 

wqh = bit_waitqueue(&inode->i_state, __I_SYNC);

while (inode->i_state & I_SYNC) {

spin_unlock(&inode->i_lock);

spin_unlock(&wb->list_lock);

__wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE);

spin_lock(&wb->list_lock);

spin_lock(&inode->i_lock);

}

}

 

 

The kernel can start to synchronize data from various different places , but all paths save one end up in 

[sysc_sb_inodes] The function is responsible to synchronize all dirty inodes belonging to a given superblock , 

[writeback_single_inode ] is used for each inode . 

 

static int

writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,

       struct writeback_control *wbc)

{

struct address_space *mapping = inode->i_mapping;

long nr_to_write = wbc->nr_to_write;

unsigned dirty;

int ret;

 

assert_spin_locked(&wb->list_lock);

assert_spin_locked(&inode->i_lock);

 

if (!atomic_read(&inode->i_count))

WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING)));

else

WARN_ON(inode->i_state & I_WILL_FREE);

 

if (inode->i_state & I_SYNC) {

/*

 * If this inode is locked for writeback and we are not doing

 * writeback-for-data-integrity, move it to b_more_io so that

 * writeback can proceed with the other inodes on s_io.

 *

 * We'll have another go at writing back this inode when we

 * completed a full scan of b_io.

 */

if (wbc->sync_mode != WB_SYNC_ALL) {

requeue_io(inode, wb);

trace_writeback_single_inode_requeue(inode, wbc,

     nr_to_write);

return 0;

}

 

/*

 * It's a data-integrity sync.  We must wait.

 */

inode_wait_for_writeback(inode, wb);

}

 

BUG_ON(inode->i_state & I_SYNC);

 

/* Set I_SYNC, reset I_DIRTY_PAGES */

inode->i_state |= I_SYNC;

inode->i_state &= ~I_DIRTY_PAGES;

spin_unlock(&inode->i_lock);

spin_unlock(&wb->list_lock);

 

ret = do_writepages(mapping, wbc);

 

/*

 * Make sure to wait on the data before writing out the metadata.

 * This is important for filesystems that modify metadata on data

 * I/O completion.

 */

if (wbc->sync_mode == WB_SYNC_ALL) {

int err = filemap_fdatawait(mapping);

if (ret == 0)

ret = err;

}

 

/*

 * Some filesystems may redirty the inode during the writeback

 * due to delalloc, clear dirty metadata flags right before

 * write_inode()

 */

spin_lock(&inode->i_lock);

dirty = inode->i_state & I_DIRTY;

inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC);

spin_unlock(&inode->i_lock);

/* Don't write the inode if only I_DIRTY_PAGES was set */

if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {

int err = write_inode(inode, wbc);

if (ret == 0)

ret = err;

}

 

spin_lock(&wb->list_lock);

spin_lock(&inode->i_lock);

inode->i_state &= ~I_SYNC;

if (!(inode->i_state & I_FREEING)) {

/*

 * Sync livelock prevention. Each inode is tagged and synced in

 * one shot. If still dirty, it will be redirty_tail()'ed below.

 * Update the dirty time to prevent enqueue and sync it again.

 */

if ((inode->i_state & I_DIRTY) &&

    (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages))

inode->dirtied_when = jiffies;

 

if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {

/*

 * We didn't write back all the pages.  nfs_writepages()

 * sometimes bales out without doing anything.

 */

inode->i_state |= I_DIRTY_PAGES;

if (wbc->nr_to_write <= 0) {

/*

 * slice used up: queue for next turn

 */

requeue_io(inode, wb);

} else {

/*

 * Writeback blocked by something other than

 * congestion. Delay the inode for some time to

 * avoid spinning on the CPU (100% iowait)

 * retrying writeback of the dirty page/inode

 * that cannot be performed immediately.

 */

redirty_tail(inode, wb);

}

} else if (inode->i_state & I_DIRTY) {

/*

 * Filesystems can dirty the inode during writeback

 * operations, such as delayed allocation during

 * submission or metadata updates after data IO

 * completion.

 */

redirty_tail(inode, wb);

} else {

/*

 * The inode is clean.  At this point we either have

 * a reference to the inode or it's on it's way out.

 * No need to add it back to the LRU.

 */

list_del_init(&inode->i_wb_list);

}

}

inode_sync_complete(inode);

trace_writeback_single_inode(inode, wbc, nr_to_write);

return ret;

}

 

 

 

 

 

分享到:
评论

相关推荐

    linux操作系统内核技术-uestc课件

    教学内容与要求  1掌握处理器在进程地址空间上的三种运行位置,了解内核编程不能使用C库函数和FPU,以及可能产生内存故障、核心栈溢出... 13熟悉页cache和radix_tree,缓冲区cache,和pdflush内核线程原理。(2小时)

    Linux Page Cache参数调优

    (2)脏数据所占内存 /(MemFree + Cached – Mapped) &gt; dirty_background_ratio。也就是说当脏数据所占用的内存占(MemFree + Cached – Mapped)内存的内存的比例超过dirty_background_ratio的时候会触发pdflush...

    oscon2009-linux-monitoring1.pdf

    5.5 Kernel Paging with pdflush ..................................................................................... 17 5.6 Case Study: Large Inbound I/O .................................................

    疯狂内核之——虚拟文件系统

    3.2 VFS接口数据结构 110 3.2.1 Ext2 超级块对象 110 3.2.2 Ext2 的索引节点对象 121 3.2.3 创建Ext2文件系统 124 3.2.4 Ext2的方法总结 126 3.3 Ext2索引节点分配 129 3.3.1 创建索引节点 130 3.3.2 删除索引节点 ...

    安装NumPy教程-详细版

    附件是安装NumPy教程_详细版,文件绿色安全,请大家放心下载,仅供交流学习使用,无任何商业目的!

    语音端点检测及其在Matlab中的实现.zip

    语音端点检测及其在Matlab中的实现.zip

    C#文档打印程序Demo

    使用C#完成一般文档的打印,带有页眉,页脚文档打印,表格打印,打印预览等

    DirectX修复工具-4-194985.zip

    directx修复工具 DirectX修复工具(DirectX repair)是系统DirectX组件修复工具,DirectX修复工具主要是用于检测当前系统的DirectX状态,若发现异常情况就可以马上进行修复,非常快捷,使用效果也非常好。

    Python手动实现人脸识别算法

    人脸识别的主要算法 其核心算法是 欧式距离算法使用该算法计算两张脸的面部特征差异,一般在0.6 以下都可以被认为是同一张脸 人脸识别的主要步骤 1 获得人脸图片 2 将人脸图片转为128D的矩阵(这个也就是人脸特征的一种数字化表现) 3 保存人脸128D的特征到文件中 4 获取其他人脸转为128D特征通过欧式距离算法与我们保存的特征对比,如果差距在0.6以下就说明两张脸差距比较小

    全国大学生信息安全竞赛知识问答-CISCN 题库.zip

    ciscn 全国大学生信息安全竞赛知识问答-CISCN 题库.zip

    JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译).zip

    JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)JAVA+SQL离散数学题库管理系统(源代码+LW+外文翻译)

    strcmp函数应用.zip

    strcmp函数应用.zip

    蓝桥杯单片机第十一届国赛设计题试做

    蓝桥杯单片机第十一届国赛设计题试做

    基于MATLAB的pca人脸识别.zip

    基于MATLAB的pca人脸识别.zip

    520.html

    520.html

    JAVA在线考试管理系统(源代码+LW+开题报告+外文翻译+英文文献+答辩PPT).zip

    JAVA在线考试管理系统(源代码+LW+开题报告+外文翻译+英文文献+答辩PPT)

    STR710的定时器编程C语言例子,开发环境为IAR EWARM。.zip

    STR710的定时器编程C语言例子,开发环境为IAR EWARM。.zip

    基于物品的协同过滤推荐算法(Python).zip

    协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐。 协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户的协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐与用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。

    JAVA文件传输(lw+源代码).zip

    FTP(File Transfer Protocol)是文件传输协议的简称。 FTP的主要作用,就是让用户连接上一个远程计算机(这些计算机上运行着FTP服务器程序)查看远程计算机有哪些文件,然后把文件从远程计算机上拷到本地计算机,或把本地计算机的文件送到远程计算机去。 目前FTP服务器软件都为国外作品,例如Server_U、IIS,国内成熟的FTP服务器软件很少,有一些如(Crob FTP Server),但从功能上看来远不能和那些流行的服务器软件媲美。

    python项目源码-深度学习tensorflow的滚动轴承故障诊断方法源码(高分大作业).rar

    本项目基于深度学习TensorFlow框架,针对滚动轴承故障诊断方法进行研究。项目采用了卷积神经网络(CNN)对轴承振动信号进行特征提取和分类,实现了对滚动轴承不同故障类型的自动诊断。 在技术实现上,项目利用TensorFlow搭建了一个高效的CNN模型,通过多层卷积、池化操作以及全连接层,自动学习轴承振动信号中的故障特征。同时,采用交叉熵损失函数优化模型参数,提高故障识别率。此外,项目还集成了数据预处理、模型训练、测试评估等功能模块,方便用户快速上手并进行实验研究。 经过运行测试,该项目代码运行稳定,诊断效果良好,可广泛应用于滚动轴承故障诊断领域。对于计算机相关专业的在校学生、老师或企业员工来说,该项目是一份难得的高分大作业资源,同时也是小白学习和实际项目借鉴的优秀参考资料。请放心下载使用,为您的学习和工作提供帮助!

Global site tag (gtag.js) - Google Analytics