disksim raid 部分源代码解析

                disksim的代码真的是不好读啊。

                首先从disksim_main.c开始里面是disksim开始执行的地方。从disksim开始运行到发请求在RAID上的重新映射的函数流程是这样:

               disksim_main.c::disksim_run_simulation()  -----> disksim.c:disksim_simulate_event(0) ------>curr=getnextevent 

                ------>disksim_iosim.c:io_internal_event()  ----------->case IO_REQUEST_ARRIVE ------------>disksim_iodriver.c:iodrver_request()

                ------>disksim_logorg.c:logorg_maprequest()

               这里先重点看logorg_maprequest():

      req = (outstand *) getfromextraq();
    ASSERT (req != NULL); 
      而getfromextraq是得到一个经过初始化的空的req变量
    req->arrtime = simtime;
    req->bcount = curr->bcount;    
    req->blkno = curr->blkno;
    req->devno = curr->devno;
    req->flags = curr->flags;
    req->busno = curr->busno;
    req->buf = curr->buf;
    req->reqopid = curr->opid;
    req->depend = NULL;
                代码中的bcount是指请求大小(以块为单位),其他的就是把event变为请求,关于event和请求之间的关系,可以看disksim源代码doc目录下的outline文件

              然后再看紧接着for循环内部的一个else:

   

   else {
            /* ???? */
            /*           for (j = 0; j < logorgs[i]->numdisks; j++) { */
            for(j = 0; j < logorgs[i]->actualnumdisks; j++) {
                if (curr->devno == logorgs[i]->devs[j].devno) {
                    if(logorg_overlap(logorgs[i], j, curr, logorgs[i]->blksperpart)) {
                        logorgno = i;
                        break;
                    }
                }
            }
            if (logorgno != -1) {
                break;
            }
        }
          RAID有两种Addressing mode(详见Manual 3.8节),自己暂时只能理解Parts,代码中的logorg就代表磁盘阵列的组织方式,其中请求从trace下发的时候是针对某个设备下发的,也就是有设备号。就是对于trace来说,它可能想着往某一块硬盘里写数据,但是经过disksim在RAID下对访问块号和设备号的重新映射,最后影响的磁盘可能不止一个。而这里先检查在对应的logorgs[i]内部的磁盘中是否有trace请求对应的设备,如果有的话,这次请求就在该logorgs[i]上处理就可以了。且logorg_overlap()函数会检查对应的磁盘是否能满足请求。检查完毕后,接下来就会在该logorgs[i]上进行处理:

      maptype = logorgs[logorgno]->maptype;

   reduntype = logorgs[logorgno]->reduntype;
      这里有两种情况,如果在参数中设定了Parity_*系列的参数,那么maptype会变为ASIS,(可以参见logorg_initialize )。如果没有设定Parity_*那么maptype就是参数中设定的maptype。如果理解了Parity_rotate参数的设定,其他maptype映射类型就很好理解了。所以来看一下logorg_parity_table()函数(如果参数为Parity_rotate,那么在logorg_initialize中会被转换为PARITY_TABLE)。为了重新映射请求,disksim会创建一个表格来存储对应的映射。下面是一个18个磁盘组成的RAID5对应的表格,每一个元素第一项对应设备号,第二项对应块号。因为可能是多个块组成一个stripe unit,多个stripe unit组成一个stripe. disksim raid 部分源代码解析_第1张图片

              有了这些知识后再来看logorg_parity_table():

      if (currlogorg->addrbyparts) {

      curr->blkno += curr->devno * currlogorg->blksperpart;
   }
       这里需要把块号重新映射为一个总的块号,因为trace想的块号是在一个磁盘用完了再用第二个磁盘,而使用raid后是把数据分散在每个盘上,所以需要重新映射,这里先计算出一个总的块号来进行重新映射。
   unitno = curr->blkno / stripeunit;           
   stripeno = unitno / partsperstripe;
   tablestart = (stripeno / currlogorg->tablestripes) * currlogorg->tablesize;//该条带号对应的表的开始块号
   stripeno = stripeno % currlogorg->tablestripes;//该条带号对应的表中的索引
   blkno = tablestart + table[(stripeno*(partsperstripe+1))].blkno;//该条带号对应的开始块号(对当前硬盘)
      一个stripe unit是有stripeunit个块组成的,所以unitno代表的是对应的第几个strip unit。然后stripeno对应的是第几个stripe。而tablestart和blkno都是对应于单个磁盘而不是整体的块号。

   

  

                

你可能感兴趣的:(源代码,raid)