dm-csum

Embed Size (px)

Citation preview

  • 8/2/2019 dm-csum

    1/22

    #include#include#include+#include+#include+#include+#include+#include+#include+#include+#include++#defineDM_MSG_PREFIX"csum"++#if1+#definedprint(...)printk(KERN_DEBUG__VA_ARGS__)+#else+#definedprint(...)+#endif+++/*Contextinformationfordevicemapper*/++typedefsector_t(map_data_sector_fn)(structdm_target*ti,sector_tdata);

    +typedefsector_t(get_imd_sector_fn)(structdm_target*ti,sector_tdata);++structcsum_c{+ /*databackingdevice*/+ structdm_dev*data_dev;+ sector_tdata_start;++ /*imdbackingdevice(canbethesameasdata_dev)*/+ structdm_dev*imd_dev;+ sector_timd_start;+ sector_timd_len;++ map_data_sector_fn*map_data_sector;

    + get_imd_sector_fn*get_imd_sector;+};+++/*TODO:usedecentlocking.Atthemoment,thissemaphoreislockedpriorto+*submissiontotheworkqueue,andgetsreleasedaftertheworkhasbeen+*processed.Thisisneededtoavoidconcurrentaccessestotheimdsectors.+*Inthefuture,finegrainedlockingwillbeimplemented.*/+staticDECLARE_MUTEX(wq_lock);+++/*+*Utilityfunctionsfordiskdatamanipulation

    +*/++/*Howmanysectorswereserveatthebeginningofthedatadevicefor+*identificationanddevicemetadata*/+#defineRESERVED_INITIAL_SECTORS_D1++/*Ifthemetadataisonadifferentdevice,howmanysectorswereserveat+*thebeginningforidentificationanddevicemetadata*/+#defineRESERVED_INITIAL_SECTORS_M1+

  • 8/2/2019 dm-csum

    2/22

    +/*Howmanydatasectorsforeachmetadatasector.Seetheinitialcommentfor+*arationaleonthevalue.*/+#defineSECTORS_PER_IMD62+++/*Returnhowmanysectorsareneededtostoretheimdinformationforthe+*givenamountofdatasectors*/+staticsector_timd_sectors_needed(sector_tsectors)+{+ returndm_sector_div_up(sectors,SECTORS_PER_IMD)*2;+}++/*Givenadmdevicesector,returnthecorrespondingdatadevicesectorto+*finditfrom.Wehaveonefunctiontousewhendataandmetadataarestored+*indifferentdevices,andonetousewhenthey'reinthesamedevice.Which+*onetousewillbedeterminedviafunctionpointersinthecontext+*structure.*/+staticsector_tmap_data_sector_diff(structdm_target*ti,sector_tdata)+{+ structcsum_c*cc=ti->private;++ /*Whenstoredindifferentdevices,dataisstoreddirectlyatthe+ *givenoffset*/+ returncc->data_start+RESERVED_INITIAL_SECTORS_D+

    + (data-ti->begin);+}++staticsector_tmap_data_sector_same(structdm_target*ti,sector_tdata)+{+ structcsum_c*cc=ti->private;++ /*Whenstoredinthesamedevice,interleavingmakesthingsalittle+ *morecomplicated.Theoffsetwillbethesameasiftherewasno+ *interleaving,plusthenumberofimdsectors.+ *Wecallimd_sectors_neededwith(data-ti->begin+1)becauseit+ *receivesanumberofsectors,so0meansnosectorsandnotan+ *offset.*/

    + returncc->data_start+RESERVED_INITIAL_SECTORS_D++ (data-ti->begin)+imd_sectors_needed(data-ti->begin+1);+}++/*Returntheimdsectorthatholdsthetupleforthegivendatasector.Its+*brotherimdsectorwillbetheresult+1,asthey'realwaysadjacent.*/+staticsector_tget_imd_sector_diff(structdm_target*ti,sector_tdata)+{+ returnRESERVED_INITIAL_SECTORS_M++ imd_sectors_needed(data-ti->begin+1);+}++staticsector_tget_imd_sector_same(structdm_target*ti,sector_tdata)

    +{+ sector_tisn=imd_sectors_needed(data-ti->begin+1);++ returnRESERVED_INITIAL_SECTORS_D+SECTORS_PER_IMD*((isn-2)/2)+ +(isn-2);+}+++/*+*Integritymetadatamanipulation

  • 8/2/2019 dm-csum

    3/22

    +*/++/*Eachsector'sintegritymetadata.Weonlyusecrcatthemoment.*/+structimd_tuple{+ __be16crc;+ __be16flags;+ __be32tag;+}__attribute__((packed));++/*imdsectorheader,holdsinternalmetadata*/+structimd_sector_header{+ /*8bitsisenoughforlast_updated,*/+ u8last_updated;+ u8unused1;+ __be16crc;+ __be32unused3;+}__attribute__((packed));++/*Returntheolderofm1andm2,orNULLifitwasimpossibletodetermine*/+staticstructimd_sector_header*older_imd(structimd_sector_header*m1,+ structimd_sector_header*m2)+{+ intl1,l2;+

    + /*wegetthevaluesintosomethingsignedsowecansubtractthem*/+ l1=m1->last_updated;+ l2=m2->last_updated;++ if(abs(l1-l2)>1){+ //dprint("wrap-around:%d%d%u\n",l1,l2,abs(l1-l2));+ if(l1==0){+ returnm2;+ }elseif(l2==0){+ returnm1;+ }else{+ returnNULL;+ }

    + }else{+ if(l1>l2){+ returnm2;+ }elseif(l1

  • 8/2/2019 dm-csum

    4/22

    ++ bio=bio_alloc(GFP_NOIO,1);+ if(bio==NULL)+ gotoerror;++ bio->bi_bdev=bdev;+ bio->bi_sector=sector;+ bio->bi_size=1024;+ bio->bi_rw|=READ;+ bio->bi_end_io=cb;+ bio->bi_private=private;+ if(bio_add_page(bio,page,1024,0)!=1024)+ gotoerror;++ returnbio;++error:+ if(page)+ __free_page(page);+ if(bio){+ bio->bi_end_io=NULL;+ bio_put(bio);+ }+

    + returnNULL;+}++/*CalculatetheCRCsforthesectorsingivenbio.Itassumesthereisenough+*spaceincrcforallthesectors(i.e.crccanholdatleast+*bio_sectors(bio)16bitintegers).*/+staticvoidcrc_sectors_from_bio(conststructbio*bio,u16*crc)+{+ intsegno;+ structbio_vec*bvec;+ unsignedlongflags;+ unsignedintsectors;+ size_tlen;

    + u16current_crc;++ /*bytesneededtocompletethecurrentCRC*/+ unsignedintbytes_needed;++ /*bytesleftinthecurrentbvec*/+ unsignedintleft_in_bvec;++ sectors=bio_sectors(bio);++ /*XXX:istherereallynootherwaythanusingbvec_kmap_irq()?*/+ current_crc=0;+ bytes_needed=512;

    + bio_for_each_segment(bvec,bio,segno){+ unsignedchar*data=bvec_kmap_irq(bvec,&flags);+ left_in_bvec=bvec->bv_len;++start:+ len=min(left_in_bvec,bytes_needed);+ current_crc=crc_ccitt(current_crc,data,len);++ bytes_needed-=len;+ left_in_bvec-=len;

  • 8/2/2019 dm-csum

    5/22

    ++ if(unlikely(bytes_needed)){+ /*weneedtogothroughthenextbvec*/+ bvec_kunmap_irq(data,&flags);+ continue;+ }++ sectors--;+ *crc=current_crc;+ crc++;+ current_crc=0;+ bytes_needed=512;++ if(left_in_bvec&&sectors){+ /*thisbvecstillhassomedataleft;ifwestill+ *havecrcstocalculate,useitforthenextone*/+ data+=len;+ gotostart;+ }++ bvec_kunmap_irq(data,&flags);+ }+}+

    +/*Updatetheimdinformationforthegivendatabio.Thefunctiondealswith+*theimdbiodirectly,thatholdsonepagewithbothimdsectors(M1and+*M2),asreturnedfromprepare_imd_read(),andassumesit'sbeenreadfrom+*disk(soitwillonlyupdatewhat'sneeded).+*+*Returns:+*-0onsuccess+*--1iftherewasamemoryerror+*--2iftherewasaconsistencyerror+*+*TODO:makeimd_biowritejustthesectorweneed+*/+staticintupdate_imd_bio(conststructbio*data_bio,structbio*imd_bio)

    +{+ inti;+ u16*crc;+ unsignedlongflags;+ unsignedchar*imd_buf;+ structimd_sector_header*m1,*m2,*older;+ structimd_tuple*t;++ crc=kmalloc(sizeof(u16)*bio_sectors(data_bio),GFP_NOIO);+ if(crc==NULL)+ return-1;++ crc_sectors_from_bio(data_bio,crc);

    ++ imd_buf=bvec_kmap_irq(bio_iovec(imd_bio),&flags);++ m1=(structimd_sector_header*)imd_buf;+ m2=(structimd_sector_header*)(imd_buf+512);++ older=older_imd(m1,m2);+ if(older==NULL){+ bvec_kunmap_irq(imd_buf,&flags);+ kfree(crc);

  • 8/2/2019 dm-csum

    6/22

    + return-2;+ }++ t=(structimd_tuple*)(older+1);+ t=t+data_bio->bi_sector%SECTORS_PER_IMD;++ for(i=0;icrc=*(crc+i);+ t++;+ }++ older->last_updated+=2;+ older->crc=crc_ccitt(0,(unsignedchar*)(older+1),+ 512-sizeof(structimd_sector_header));++ bvec_kunmap_irq(imd_buf,&flags);++ kfree(crc);++ return0;+}++/*VerifythattheCRCsfromdata_biomatchtheonesstoredinimd_bio(which+*containsbothM1andM2)*/

    +staticintverify_crc(structbio*data_bio,structbio*imd_bio)+{+ inti,r;+ u16*crc;+ unsignedlongflags;+ unsignedchar*imd_buf;+ structimd_sector_header*m1,*m2;+ structimd_tuple*m1t,*m2t;++ crc=kmalloc(sizeof(u16)*bio_sectors(data_bio),GFP_NOIO);+ if(crc==NULL)+ return-ENOMEM;+

    + crc_sectors_from_bio(data_bio,crc);++ imd_buf=bvec_kmap_irq(bio_iovec(imd_bio),&flags);++ m1=(structimd_sector_header*)imd_buf;+ m2=(structimd_sector_header*)(imd_buf+512);++ m1t=(structimd_tuple*)(m1+1);+ m1t=m1t+data_bio->bi_sector%SECTORS_PER_IMD;++ m2t=(structimd_tuple*)(m2+1);+ m2t=m2t+data_bio->bi_sector%SECTORS_PER_IMD;+

    + r=0;++ for(i=0;i=SECTORS_PER_IMD);+ if(m1t->crc!=*(crc+i)&&m2t->crc!=*(crc+i)){+ printk(KERN_WARNING+ "dm-csum:CRCerroratsector%lld\n",+ (unsignedlonglong)+ (data_bio->bi_sector+i));+ /*

  • 8/2/2019 dm-csum

    7/22

    + dprint("CRC:%llum1:%xm2:%xr:%x\n",+ (unsignedlonglong)+ (data_bio->bi_sector+i),+ m1t->crc,m2t->crc,*(crc+i));+ */+ r=-EIO;+ break;+ }else{+ /*+ dprint("OK:%llum1:%xm2:%xr:%x\n",+ (unsignedlonglong)(data_bio->bi_sector+i),+ m1t->crc,m2t->crc,*(crc+i));+ */+ }+ m1t++;+ m2t++;+ }++ /*TODO:validatetheimdsectorCRC*/++ bvec_kunmap_irq(imd_buf,&flags);++ kfree(crc);+

    + returnr;+}+++/*+*READhandling(nicebiosonly)+*+*Readsarehandledbyreadingtherequesteddata,andtheimdsector+*associatedwithit.Whenbothrequestsarecompleted,thedatachecksumis+*calculatedandcomparedagainstwhat'sintheimdsector.+*/++/*Usedtotrackpendingreads*/

    +structpending_read{+ spinlock_tlock;++ structdm_target*ti;+ structcsum_c*cc;+ structbio*orig_bio;++ structbio*data_bio;+ structbio*imd_bio;++ booldata_error;+ boolimd_error;+

    + /*numberofoperationspending*/+ unsignedintnr_pending;+};++#definepr_lock(pr)spin_lock(&((pr)->lock))+#definepr_unlock(pr)spin_unlock(&((pr)->lock))++staticvoidread_nice_bio(structdm_target*ti,structbio*bio);+staticstructbio*prepare_data_read(structbio*orig_bio,+ structblock_device*bdev,sector_tsector,bio_end_io_t*cb,

  • 8/2/2019 dm-csum

    8/22

    + void*private);+staticvoidread_complete(structbio*bio,interror);++/*Readanicebio*/+staticvoidread_nice_bio(structdm_target*ti,structbio*bio)+{+ structcsum_c*cc=ti->private;+ structpending_read*pr;++ pr=kmalloc(sizeof(*pr),GFP_NOIO);+ if(pr==NULL)+ gotoerror;++ spin_lock_init(&pr->lock);+ pr->ti=ti;+ pr->cc=cc;+ pr->orig_bio=bio;+ pr->data_error=false;+ pr->imd_error=false;++ pr->data_bio=prepare_data_read(pr->orig_bio,cc->data_dev->bdev,+ cc->map_data_sector(ti,pr->orig_bio->bi_sector),+ read_complete,pr);+ if(pr->data_bio==NULL)

    + gotoerror;++ pr->imd_bio=prepare_imd_read(cc->imd_dev->bdev,+ cc->get_imd_sector(ti,pr->orig_bio->bi_sector),+ read_complete,pr);+ if(pr->imd_bio==NULL)+ gotoerror;++ pr->nr_pending=2;++ submit_bio(pr->data_bio->bi_rw,pr->data_bio);+ submit_bio(pr->imd_bio->bi_rw,pr->imd_bio);+ return;

    ++error:+ bio_endio(bio,-ENOMEM);+ return;+}++/*Prepareanewbiotoreadthedatarequestedinorig_bio*/+staticstructbio*prepare_data_read(structbio*orig_bio,+ structblock_device*bdev,sector_tsector,bio_end_io_t*cb,+ void*private)+{+ structbio*bio;+

    + /*clonethebiosowedon'toverridetheoriginal'sbi_privateand+ *bi_end_io*/+ bio=bio_clone(orig_bio,GFP_NOIO);+ if(bio==NULL)+ returnNULL;++ bio->bi_bdev=bdev;+ bio->bi_sector=sector;+ bio->bi_end_io=cb;+ bio->bi_private=private;

  • 8/2/2019 dm-csum

    9/22

    ++ returnbio;+}++/*Readcompletioncallback*/+staticvoidread_complete(structbio*bio,interror)+{+ intresult=-EIO;+ structpending_read*pr=bio->bi_private;++ pr_lock(pr);++ pr->nr_pending--;++ if(pr->nr_pending>0){+ pr_unlock(pr);+ return;+ }++ /*weknowwehaveexclusiveaccesstothepr,noneedtolock+ *arounditanymore*/+ pr_unlock(pr);++ if(pr->data_error){

    + printk(KERN_WARNING"dm-csum:errorreadingdata\n");+ gotoexit;+ }elseif(pr->imd_error){+ printk(KERN_WARNING"dm-csum:errorreadingimd\n");+ gotoexit;+ }++ /*TODO:addanoptionforthosewhodonotwantthebiotofailon+ *CRCerrors*/+ result=verify_crc(pr->orig_bio,pr->imd_bio);++exit:+ /*TODO:usedecentlocking*/

    + up(&wq_lock);++ /*freethepageallocatedinprepare_imd_read()*/+ __free_page(pr->imd_bio->bi_io_vec->bv_page);++ /*XXX:istheorderingbetweenthisandbio_put(pr->data_bio)+ *important?Ithinknot,butconfirmationwouldn'thurt*/+ bio_endio(pr->orig_bio,result);++ bio_put(pr->data_bio);+ bio_put(pr->imd_bio);++ kfree(pr);

    +}++#undefpr_lock+#undefpr_unlock+++/*+*WRITEhandling(nicebiosonly)+*/+

  • 8/2/2019 dm-csum

    10/22

    +/*Usedtotrackpendingwrites*/+structpending_write{+ spinlock_tlock;++ structdm_target*ti;+ structcsum_c*cc;++ structbio*orig_bio;+ structbio*imd_bio;+ structbio*data_bio;++ boolerror;+ unsignedintnr_pending;+};++#definepw_lock(pw)spin_lock(&((pw)->lock))+#definepw_unlock(pw)spin_unlock(&((pw)->lock))++/*Writesbeginwithwrite_nice_bio(),thatqueuestheimdbioread.Whenthat+*bioisdone,write_stage1()getscalled,whichupdatestheimddataand+*thenqueuesboththeimdwriteandthedatawrite.Whenthoseare+*completed,write_stage2()getscalled,whichfinishesupandendsthe+*originalbio.*/+staticvoidwrite_nice_bio(structdm_target*ti,structbio*bio);

    +staticvoidwrite_stage1(structbio*bio,interror);+staticvoidwrite_stage2(structbio*bio,interror);++/*Writeanicebio*/+staticvoidwrite_nice_bio(structdm_target*ti,structbio*bio)+{+ structcsum_c*cc=ti->private;+ structpending_write*pw;++ pw=kmalloc(sizeof(*pw),GFP_NOIO);+ if(pw==NULL){+ bio_endio(bio,-ENOMEM);+ return;

    + }++ spin_lock_init(&pw->lock);+ pw->ti=ti;+ pw->cc=cc;+ pw->orig_bio=bio;+ pw->data_bio=NULL;+ pw->error=false;+ pw->nr_pending=0;++ pw->imd_bio=prepare_imd_read(cc->imd_dev->bdev,+ cc->get_imd_sector(ti,pw->orig_bio->bi_sector),+ write_stage1,pw);

    + if(pw->imd_bio==NULL){+ kfree(pw);+ bio_endio(bio,-ENOMEM);+ return;+ }++ submit_bio(pw->imd_bio->bi_rw,pw->imd_bio);+}++/*Calledwhentheimdbiohasbeenread*/

  • 8/2/2019 dm-csum

    11/22

    +staticvoidwrite_stage1(structbio*imd_bio,interror)+{+ intr;+ interr=-EIO;+ structpending_write*pw=imd_bio->bi_private;+ structcsum_c*cc=pw->cc;+ structdm_target*ti=pw->ti;+ structbio*data_bio;++ r=update_imd_bio(pw->orig_bio,imd_bio);+ if(r==-1){+ err=-ENOMEM;+ gotoerror;+ }elseif(r==-2){+ printk(KERN_WARNING"dm-csum:consistencyerrorupdating"+ "imdsector\n");+ err=-EIO;+ gotoerror;+ }++ /*preparebioforreuse*/+ imd_bio->bi_rw|=WRITE;+ imd_bio->bi_end_io=write_stage2;+

    + data_bio=bio_clone(pw->orig_bio,GFP_NOIO);+ if(data_bio==NULL){+ err=-ENOMEM;+ gotoerror;+ }++ data_bio->bi_private=pw;+ data_bio->bi_end_io=write_stage2;+ data_bio->bi_bdev=cc->data_dev->bdev;+ data_bio->bi_sector=cc->map_data_sector(ti,pw->orig_bio->bi_sector);++ /*databiotakesabarrier,soweknowtheimdwritewillhave+ *completedbeforeithitsthedisk*/

    + data_bio->bi_rw|=(1nr_pending=2;+ submit_bio(imd_bio->bi_rw,imd_bio);+ submit_bio(data_bio->bi_rw,data_bio);+ return;

    ++error:+ bio_endio(pw->orig_bio,err);+ __free_page(imd_bio->bi_io_vec->bv_page);+ bio_put(imd_bio);+ kfree(pw);+ return;+}++staticvoidwrite_stage2(structbio*bio,interror)

  • 8/2/2019 dm-csum

    12/22

    +{+ structpending_write*pw=bio->bi_private;++ pw_lock(pw);+ pw->nr_pending--;+ if(error)+ pw->error=true;++ if(pw->nr_pending){+ pw_unlock(pw);+ //dprint("ws2-\n");+ return;+ }++ /*ifwegothere,there'snoneedtolockpwanymoreasweknowwe+ *haveexclusiveaccess*/+ pw_unlock(pw);++ /*TODO:usedecentlocking*/+ up(&wq_lock);++ /*freetheimd_bioresources*/+ __free_page(pw->imd_bio->bi_io_vec->bv_page);+ bio_put(pw->imd_bio);

    ++ /*XXX:likeread_complete():istheorderbetweenthisand+ *bio_put(pw->data_bio)important?*/+ bio_endio(pw->orig_bio,pw->error?-EIO:0);++ bio_put(pw->data_bio);++ kfree(pw);+}++#undefpw_lock+#undefpw_unlock+

    ++/*+*Workqueuetoprocessbios.+*+*Itiscreatedindm_csum_init().+*+*TODO:handlemorethanonependingbio,anddispatchmorethanoneaslong+*astheydon'toverlap.Maybeoneworqueueperctx?Ormaybedelaythe+*creationoftheworkqueueuntilthefirstctx?+*/++staticstructworkqueue_struct*wq;+

    +structpending_work{+ structdm_target*ti;+ structbio*bio;+ structwork_structw;+};++staticvoidprocess_nice_bio(structwork_struct*work)+{+ structpending_work*pending;+ structdm_target*ti;

  • 8/2/2019 dm-csum

    13/22

    + structbio*bio;++ pending=container_of(work,structpending_work,w);++ ti=pending->ti;+ bio=pending->bio;++ /*TODO:usedecentlocking+ *Atthemoment,thislockisup()edatthefinalstageofthe+ *read/writecode,whenthebiohasbeenprocessed*/+ down(&wq_lock);++ switch(bio_data_dir(bio)){+ caseREAD:+ read_nice_bio(ti,bio);+ break;+ caseWRITE:+ write_nice_bio(ti,bio);+ break;+ default:+ dprint("Unknowndirection\n");+ BUG();+ break;+ }

    ++ kfree(pending);+}++staticintqueue_nice_bio(structdm_target*ti,structbio*bio)+{+ structpending_work*pending;++ pending=kmalloc(sizeof(structpending_work),GFP_NOIO);+ if(pending==NULL)+ return-ENOMEM;++ pending->ti=ti;

    + pending->bio=bio;++ INIT_WORK(&(pending->w),process_nice_bio);++ queue_work(wq,&(pending->w));++ return0;+}+++/*+*Evilbiohandling+*

    +*Evilbiosaresplitintoniceonesinadirection-independantway,andthen+*gothroughthedirection-dependantcode(whichispreparedtodealwith+*nicebiosonly,becauseitmakesthecodemuchsimpler).+*+*Whenallthenicebiosarecompleted,weendtheoriginal,evilbio.+*/++/*Determinesifabioisevil*/+staticintbio_is_evil(structdm_target*ti,structbio*bio)+{

  • 8/2/2019 dm-csum

    14/22

    + sector_tmapped_first,mapped_last;++ /*TODO:addacommentonwhywedothis*/+ mapped_first=map_data_sector_same(ti,bio->bi_sector);+ mapped_last=map_data_sector_same(ti,+ bio->bi_sector+bio_sectors(bio)-1);++ return(mapped_last-mapped_first)!=(bio_sectors(bio)-1);+}+++/*Usedtotrackpendingevilbios*/+structpending_evil_bio{+ spinlock_tlock;++ structcsum_c*cc;++ /*originalevilbio*/+ structbio*orig_bio;++ /*numberofbiospending*/+ unsignedintnr_pending;++ /*werethereanyerrors?*/

    + boolerror;++};++#definepeb_lock(peb)spin_lock(&((peb)->lock))+#definepeb_unlock(peb)spin_unlock(&((peb)->lock))++staticinthandle_evil_bio(structdm_target*ti,structbio*bio);+staticstructbio*prepare_nice_bio(structpending_evil_bio*peb,+ structbio*bio,sector_tbegin,sector_tsize);+staticvoidevil_bio_complete(structbio*bio,interror);++/*Handleanevilbio,bysplittingitintoniceonesandprocessingthem*/

    +staticinthandle_evil_bio(structdm_target*ti,structbio*bio)+{+ inti,r;+ sector_tfirst,last,prelude,postlude;+ unsignedintnmiddle,submitted_bios;+ structpending_evil_bio*peb;+ structbio*new;++ /*+ dprint("evilbio!s:%lun:%lul:%lud:%d\ti:%luo:%lu\t\tp:%p\n",+ bio->bi_sector,bio_sectors(bio),bio->bi_size,+ bio_data_dir(bio),+ bio->bi_idx,bio_iovec(bio)->bv_offset,

    + bio_iovec(bio)->bv_page);+ */++ peb=kmalloc(sizeof(*peb),GFP_NOIO);+ if(peb==NULL)+ return-ENOMEM;++ spin_lock_init(&peb->lock);+ peb->orig_bio=bio;+ peb->error=false;

  • 8/2/2019 dm-csum

    15/22

    + peb->cc=ti->private;++ /*Wewillsplitthebioin:+ *-optionallya"preludebio"ofsectorsbi_sector+bio_sectors(bio);++ /*Howmanysectorsuntilthefirstcut*/+ prelude=dm_sector_div_up(first,SECTORS_PER_IMD)+ *SECTORS_PER_IMD-first;++ /*Howmanysectorsfromthelastcutuntillast*/+ postlude=last-(dm_sector_div_up(last,SECTORS_PER_IMD)-1)+ *SECTORS_PER_IMD;++ /*HowmanySECTORS_PER_IMDarebetweenthefirstandlastcuts*/+ nmiddle=((last-postlude)-(first+prelude))/SECTORS_PER_IMD;+

    + peb->nr_pending=1+nmiddle+1;++ /*+ dprint("first:%lulast:%lupre:%lunm:%lupost:%lupending:%lu\n",+ first,last,prelude,nmiddle,postlude,+ peb->nr_pending);+ */++ submitted_bios=0;++ /*Fromnowon,accesstopebwillbelockedtoavoidraceswith+ *evil_bio_complete()*/+

    + /*Submitthepreludebio*/+ if(prelude){+ new=prepare_nice_bio(peb,bio,first,prelude);+ if(new==NULL){+ kfree(peb);+ return-ENOMEM;+ }++ r=queue_nice_bio(ti,new);+ if(r

  • 8/2/2019 dm-csum

    16/22

    + r=queue_nice_bio(ti,new);+ if(rnr_pending-=peb->nr_pending-submitted_bios;+ peb->error=true;++ if(peb->nr_pending==0){+ peb_unlock(peb);+ kfree(peb);+ return-ENOMEM;+ }++ peb_unlock(peb);+

    + return0;+}++/*Prepareanewnicebioclonedfromtheoriginalone*/+staticstructbio*prepare_nice_bio(structpending_evil_bio*peb,+ structbio*bio,sector_tbegin,sector_tsize)+{+ intsegno,advance,sofar;+ structbio*new;+ structbio_vec*bvec;++ new=bio_clone(bio,GFP_NOIO);+ if(new==NULL)

    + returnNULL;++ new->bi_sector=begin;+ new->bi_size=size*512;++ WARN_ON(bio_sectors(new)!=size);++ /*Makethenewbiostartintherightidxandoffset+ *TODO:thiscanbeoptimizedbecausewe'rewalkingthesamething+ *overandover*/

  • 8/2/2019 dm-csum

    17/22

  • 8/2/2019 dm-csum

    18/22

    + unsignedlonglongdata_offset,imd_offset;+ sector_tdata_dev_len;+ structcsum_c*cc;++ if(argc!=2&&argc!=4){+ ti->error="Incorrectnumberofarguments";+ return-EINVAL;+ }++ cc=kmalloc(sizeof(*cc),GFP_KERNEL);+ if(cc==NULL){+ ti->error="Cannotallocatecontextinformation";+ return-ENOMEM;+ }+ cc->data_dev=cc->imd_dev=NULL;+ cc->data_start=cc->imd_start=cc->imd_len=0;++ err=-EINVAL;++ if(sscanf(argv[1],"%llu",&data_offset)!=1){+ ti->error="Invaliddatadevoffset";+ gotoerror;+ }+ cc->data_start=data_offset;

    ++ /*Ifwehavebothdataandmetadataonthesamedevice,the+ *advertisedsizeofthedmdevicewillbeslightlylessthanthe+ *total,toaccountforthespacededicatedtothemetadata*/+ if(argc==2){+ data_dev_len=ti->len+imd_sectors_needed(ti->len);+ }else{+ data_dev_len=ti->len;+ }++ mode=dm_table_get_mode(ti->table);+ if(dm_get_device(ti,argv[0],cc->data_start,data_dev_len,mode,+ &(cc->data_dev))){

    + ti->error="datadevicelookupfailed";+ gotoerror;+ }++ if(argc==2){+ cc->map_data_sector=map_data_sector_same;+ cc->get_imd_sector=get_imd_sector_same;+ cc->imd_dev=cc->data_dev;+ }elseif(argc==4){+ if(sscanf(argv[3],"%llu",&imd_offset)!=1){+ ti->error="Invalidintegritydevoffset";+ gotoerror;+ }

    + cc->imd_start=imd_offset;+ cc->imd_len=imd_sectors_needed(ti->len);++ if(dm_get_device(ti,argv[2],cc->imd_start,+ cc->imd_len,mode,&(cc->imd_dev))){+ ti->error="Integritydevicelookupfailed";+ gotoerror;+ }++ cc->map_data_sector=map_data_sector_diff;

  • 8/2/2019 dm-csum

    19/22

    + cc->get_imd_sector=get_imd_sector_diff;+ }++ ti->private=cc;++ return0;++error:+ if(cc->data_dev){+ if(cc->data_dev==cc->imd_dev){+ dm_put_device(ti,cc->data_dev);+ }else{+ dm_put_device(ti,cc->data_dev);+ dm_put_device(ti,cc->imd_dev);+ }+ }+ kfree(cc);+ returnerr;+}++/*Destructor,undoeswhatwasdoneintheconstructor*/+staticvoidcsum_dtr(structdm_target*ti)+{+ structcsum_c*cc=ti->private;

    ++ if(cc->data_dev==cc->imd_dev){+ dm_put_device(ti,cc->data_dev);+ }else{+ dm_put_device(ti,cc->data_dev);+ dm_put_device(ti,cc->imd_dev);+ }++ kfree(cc);+}++/*Operationmapping*/+staticintcsum_map(structdm_target*ti,structbio*bio,

    + unionmap_info*map_context)+{+ intrv;++ if(bio_is_evil(ti,bio))+ rv=handle_evil_bio(ti,bio);+ else+ rv=queue_nice_bio(ti,bio);++ if(rv

  • 8/2/2019 dm-csum

    20/22

    + .module=THIS_MODULE,+ .ctr=csum_ctr,+ .dtr =csum_dtr,+ .map=csum_map,+};++staticint__initdm_csum_init(void)+{+ intdm_rv;++ wq=create_workqueue("dm-csum");+ if(wq==NULL)+ return-ENOMEM;++ dm_rv=dm_register_target(&csum_target);+ if(dm_rv

  • 8/2/2019 dm-csum

    21/22

    */

    #defineRESERVED_INITIAL_SECTORS_D1#defineRESERVED_INITIAL_SECTORS_M1#defineSECTORS_PER_IMD62

    structimd_tuple{__be16crc;__be16flags;__be32tag;}__attribute__((packed));

    structimd_sector_header{u8last_updated;u8unused1;__be16crc;__be32unused3;}__attribute__((packed));

    /*Formatfunctiontousewhenimdanddataareonthesamedevice*/intformat_same(intfd,off_ttotal_size){

    intr;off_toff;

    unsignedcharbuf[1024];structimd_sector_header*m1,*m2;

    memset(buf,0,sizeof(buf));

    m1=(structimd_sector_header*)buf;m2=(structimd_sector_header*)(buf+512);

    m1->last_updated=2;m2->last_updated=1;

    off=RESERVED_INITIAL_SECTORS_D*512;

    while(off

  • 8/2/2019 dm-csum

    22/22

    {intfd,imd_fd;off_ttotal_size;intsame;

    if(argc