linux内核md源代码解读 十二 raid读写 - Linux系统
我们都知道,对一个linux块设备来说,都有一个对应的请求队列。注册在这个请求队列上的请求就是该块设备的请求入口。对于raid来说,分配struct mddev时就已经设置好了,在函数md_alloc中有这样的代码:
4846 blk_queue_make_request(mddev->queue, md_make_request); 4847 blk_set_stacking_limits(&mddev->queue->limits); 虽然全国的PM一直保持着稳健的增长,但丝毫也阻挡不了我们看代码的慧眼,在成千上万行的代码里我们依然能够迅速地找出raid读写入口就是md_make_request。 328/* Rather than calling directly into the personality make_request function, 329 * IO requests come here first so that we can check if the device is 330 * being suspended pending a reconfiguration. 331 * We hold a refcount over the call to ->make_request. By the time that 332 * call has finished, the bio has been linked into some internal structure 333 * and so is visible to ->quiesce(), so we don't need the refcount any more. 334 */ 我们在调用make_request函数之前,先检查设备是否因为重配置而挂起。在调用make_request函数之前,我们增加设备的引用计数,在make_request调用完成时再递减。增加设备引用计数主要是为调用->quiesce()之前保证下发到设备的IO已经完成。 335static void md_make_request(struct request_queue *q, struct bio *bio) 336{ 337 const int rw = bio_data_dir(bio); 338 struct mddev *mddev = q->queuedata; 339 int cpu; 340 unsigned int sectors; 341 342 if (mddev == NULL || mddev->pers == NULL 343 || !mddev->ready) { 344 bio_io_error(bio); 345 return; 346 } 347 smp_rmb(); /* Ensure implications of 'active' are visible */ 348 rcu_read_lock(); 349 if (mddev->suspended) { 350 DEFINE_WAIT(__wait); 351 for (;;) { 352 prepare_to_wait(&mddev->sb_wait, &__wait, 353 TASK_UNINTERRUPTIBLE); 354 if (!mddev->suspended) 355 break; 356 rcu_read_unlock(); 357 schedule(); 358 rcu_read_lock(); 359 } 360 finish_wait(&mddev->sb_wait, &__wait); 361 } 362 atomic_inc(&mddev->active_io); 363 rcu_read_unlock(); 364 365 /* 366 * save the sectors now since our bio can 367 * go away inside make_request 368 */ 369 sectors = bio_sectors(bio); 370 mddev->pers->make_request(mddev, bio); 371 372 cpu = part_stat_lock(); 373 part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]); 374 part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors); 375 part_stat_unlock(); 376 377 if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended) 378 wake_up(&mddev->sb_wait); 379} 337行,获取IO方向,用于设备信息统计 338行,获取阵列指针,该指针是在md_alloc中赋值的 342行,基本检查 348行,访问struct mddev信息加rcu读锁 349行,阵列suspend 350行,如果阵列suspend,即前面注释中讲的正在重配置,则加入sb_wait等待队列 360行,阵列完成suspend,从等待队列中移除 362行,递增阵列引用计数,在前面注释里有原因说明 370行,下发bio到阵列 372行,这个开始是信息统计 377行,递减阵列引用计数,如果正在重配置,则唤醒该进程 真正的数据通道命令也就370行这一句,其他的都是控制通道的。 对于raid5阵列,这个请求函数对应的是raid5.c中的make_request函数:
(编辑:佛山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |