123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092 |
- #include <linux/fs.h>
- #include <linux/slab.h>
- #include "jfs_incore.h"
- #include "jfs_superblock.h"
- #include "jfs_dmap.h"
- #include "jfs_imap.h"
- #include "jfs_lock.h"
- #include "jfs_metapage.h"
- #include "jfs_debug.h"
- #include "jfs_discard.h"
- #define BMAP_LOCK_INIT(bmp) mutex_init(&bmp->db_bmaplock)
- #define BMAP_LOCK(bmp) mutex_lock(&bmp->db_bmaplock)
- #define BMAP_UNLOCK(bmp) mutex_unlock(&bmp->db_bmaplock)
- static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks);
- static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval);
- static int dbBackSplit(dmtree_t * tp, int leafno);
- static int dbJoin(dmtree_t * tp, int leafno, int newval);
- static void dbAdjTree(dmtree_t * tp, int leafno, int newval);
- static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc,
- int level);
- static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results);
- static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks);
- static int dbAllocNear(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks,
- int l2nb, s64 * results);
- static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks);
- static int dbAllocDmapLev(struct bmap * bmp, struct dmap * dp, int nblocks,
- int l2nb,
- s64 * results);
- static int dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb,
- s64 * results);
- static int dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno,
- s64 * results);
- static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks);
- static int dbFindBits(u32 word, int l2nb);
- static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno);
- static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx);
- static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks);
- static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks);
- static int dbMaxBud(u8 * cp);
- static int blkstol2(s64 nb);
- static int cntlz(u32 value);
- static int cnttz(u32 word);
- static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks);
- static int dbInitDmap(struct dmap * dp, s64 blkno, int nblocks);
- static int dbInitDmapTree(struct dmap * dp);
- static int dbInitTree(struct dmaptree * dtp);
- static int dbInitDmapCtl(struct dmapctl * dcp, int level, int i);
- static int dbGetL2AGSize(s64 nblocks);
- static const s8 budtab[256] = {
- 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
- 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1
- };
- int dbMount(struct inode *ipbmap)
- {
- struct bmap *bmp;
- struct dbmap_disk *dbmp_le;
- struct metapage *mp;
- int i;
-
-
- bmp = kmalloc(sizeof(struct bmap), GFP_KERNEL);
- if (bmp == NULL)
- return -ENOMEM;
-
- mp = read_metapage(ipbmap,
- BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage,
- PSIZE, 0);
- if (mp == NULL) {
- kfree(bmp);
- return -EIO;
- }
-
- dbmp_le = (struct dbmap_disk *) mp->data;
- bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize);
- bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
- bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
- bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
- bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel);
- bmp->db_maxag = le32_to_cpu(dbmp_le->dn_maxag);
- bmp->db_agpref = le32_to_cpu(dbmp_le->dn_agpref);
- bmp->db_aglevel = le32_to_cpu(dbmp_le->dn_aglevel);
- bmp->db_agheight = le32_to_cpu(dbmp_le->dn_agheight);
- bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth);
- bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart);
- bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size);
- for (i = 0; i < MAXAG; i++)
- bmp->db_agfree[i] = le64_to_cpu(dbmp_le->dn_agfree[i]);
- bmp->db_agsize = le64_to_cpu(dbmp_le->dn_agsize);
- bmp->db_maxfreebud = dbmp_le->dn_maxfreebud;
-
- release_metapage(mp);
-
- bmp->db_ipbmap = ipbmap;
- JFS_SBI(ipbmap->i_sb)->bmap = bmp;
- memset(bmp->db_active, 0, sizeof(bmp->db_active));
-
- BMAP_LOCK_INIT(bmp);
- return (0);
- }
- int dbUnmount(struct inode *ipbmap, int mounterror)
- {
- struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
- if (!(mounterror || isReadOnly(ipbmap)))
- dbSync(ipbmap);
-
- truncate_inode_pages(ipbmap->i_mapping, 0);
-
- kfree(bmp);
- return (0);
- }
- int dbSync(struct inode *ipbmap)
- {
- struct dbmap_disk *dbmp_le;
- struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
- struct metapage *mp;
- int i;
-
-
- mp = read_metapage(ipbmap,
- BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage,
- PSIZE, 0);
- if (mp == NULL) {
- jfs_err("dbSync: read_metapage failed!");
- return -EIO;
- }
-
- dbmp_le = (struct dbmap_disk *) mp->data;
- dbmp_le->dn_mapsize = cpu_to_le64(bmp->db_mapsize);
- dbmp_le->dn_nfree = cpu_to_le64(bmp->db_nfree);
- dbmp_le->dn_l2nbperpage = cpu_to_le32(bmp->db_l2nbperpage);
- dbmp_le->dn_numag = cpu_to_le32(bmp->db_numag);
- dbmp_le->dn_maxlevel = cpu_to_le32(bmp->db_maxlevel);
- dbmp_le->dn_maxag = cpu_to_le32(bmp->db_maxag);
- dbmp_le->dn_agpref = cpu_to_le32(bmp->db_agpref);
- dbmp_le->dn_aglevel = cpu_to_le32(bmp->db_aglevel);
- dbmp_le->dn_agheight = cpu_to_le32(bmp->db_agheight);
- dbmp_le->dn_agwidth = cpu_to_le32(bmp->db_agwidth);
- dbmp_le->dn_agstart = cpu_to_le32(bmp->db_agstart);
- dbmp_le->dn_agl2size = cpu_to_le32(bmp->db_agl2size);
- for (i = 0; i < MAXAG; i++)
- dbmp_le->dn_agfree[i] = cpu_to_le64(bmp->db_agfree[i]);
- dbmp_le->dn_agsize = cpu_to_le64(bmp->db_agsize);
- dbmp_le->dn_maxfreebud = bmp->db_maxfreebud;
-
- write_metapage(mp);
-
- filemap_write_and_wait(ipbmap->i_mapping);
- diWriteSpecial(ipbmap, 0);
- return (0);
- }
- int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
- {
- struct metapage *mp;
- struct dmap *dp;
- int nb, rc;
- s64 lblkno, rem;
- struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
- struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
- struct super_block *sb = ipbmap->i_sb;
- IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
-
- if (unlikely((blkno == 0) || (blkno + nblocks > bmp->db_mapsize))) {
- IREAD_UNLOCK(ipbmap);
- printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
- (unsigned long long) blkno,
- (unsigned long long) nblocks);
- jfs_error(ip->i_sb, "block to be freed is outside the map\n");
- return -EIO;
- }
-
- if (JFS_SBI(sb)->flag & JFS_DISCARD)
- if (JFS_SBI(sb)->minblks_trim <= nblocks)
- jfs_issue_discard(ipbmap, blkno, nblocks);
-
- mp = NULL;
- for (rem = nblocks; rem > 0; rem -= nb, blkno += nb) {
-
- if (mp) {
- write_metapage(mp);
- }
-
- lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
- mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL) {
- IREAD_UNLOCK(ipbmap);
- return -EIO;
- }
- dp = (struct dmap *) mp->data;
-
- nb = min(rem, BPERDMAP - (blkno & (BPERDMAP - 1)));
-
- if ((rc = dbFreeDmap(bmp, dp, blkno, nb))) {
- jfs_error(ip->i_sb, "error in block map\n");
- release_metapage(mp);
- IREAD_UNLOCK(ipbmap);
- return (rc);
- }
- }
-
- write_metapage(mp);
- IREAD_UNLOCK(ipbmap);
- return (0);
- }
- int
- dbUpdatePMap(struct inode *ipbmap,
- int free, s64 blkno, s64 nblocks, struct tblock * tblk)
- {
- int nblks, dbitno, wbitno, rbits;
- int word, nbits, nwords;
- struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
- s64 lblkno, rem, lastlblkno;
- u32 mask;
- struct dmap *dp;
- struct metapage *mp;
- struct jfs_log *log;
- int lsn, difft, diffp;
- unsigned long flags;
-
- if (blkno + nblocks > bmp->db_mapsize) {
- printk(KERN_ERR "blkno = %Lx, nblocks = %Lx\n",
- (unsigned long long) blkno,
- (unsigned long long) nblocks);
- jfs_error(ipbmap->i_sb, "blocks are outside the map\n");
- return -EIO;
- }
-
- lsn = tblk->lsn;
- log = (struct jfs_log *) JFS_SBI(tblk->sb)->log;
- logdiff(difft, lsn, log);
-
- mp = NULL;
- lastlblkno = 0;
- for (rem = nblocks; rem > 0; rem -= nblks, blkno += nblks) {
-
- lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
- if (lblkno != lastlblkno) {
- if (mp) {
- write_metapage(mp);
- }
- mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE,
- 0);
- if (mp == NULL)
- return -EIO;
- metapage_wait_for_io(mp);
- }
- dp = (struct dmap *) mp->data;
-
- dbitno = blkno & (BPERDMAP - 1);
- word = dbitno >> L2DBWORD;
- nblks = min(rem, (s64)BPERDMAP - dbitno);
-
- for (rbits = nblks; rbits > 0;
- rbits -= nbits, dbitno += nbits) {
-
- wbitno = dbitno & (DBWORD - 1);
- nbits = min(rbits, DBWORD - wbitno);
-
- if (nbits < DBWORD) {
-
- mask =
- (ONES << (DBWORD - nbits) >> wbitno);
- if (free)
- dp->pmap[word] &=
- cpu_to_le32(~mask);
- else
- dp->pmap[word] |=
- cpu_to_le32(mask);
- word += 1;
- } else {
-
- nwords = rbits >> L2DBWORD;
- nbits = nwords << L2DBWORD;
-
- if (free)
- memset(&dp->pmap[word], 0,
- nwords * 4);
- else
- memset(&dp->pmap[word], (int) ONES,
- nwords * 4);
- word += nwords;
- }
- }
-
- if (lblkno == lastlblkno)
- continue;
- lastlblkno = lblkno;
- LOGSYNC_LOCK(log, flags);
- if (mp->lsn != 0) {
-
- logdiff(diffp, mp->lsn, log);
- if (difft < diffp) {
- mp->lsn = lsn;
-
- list_move(&mp->synclist, &tblk->synclist);
- }
-
- logdiff(difft, tblk->clsn, log);
- logdiff(diffp, mp->clsn, log);
- if (difft > diffp)
- mp->clsn = tblk->clsn;
- } else {
- mp->log = log;
- mp->lsn = lsn;
-
- log->count++;
- list_add(&mp->synclist, &tblk->synclist);
- mp->clsn = tblk->clsn;
- }
- LOGSYNC_UNLOCK(log, flags);
- }
-
- if (mp) {
- write_metapage(mp);
- }
- return (0);
- }
- int dbNextAG(struct inode *ipbmap)
- {
- s64 avgfree;
- int agpref;
- s64 hwm = 0;
- int i;
- int next_best = -1;
- struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
- BMAP_LOCK(bmp);
-
- avgfree = (u32)bmp->db_nfree / bmp->db_numag;
-
- agpref = bmp->db_agpref;
- if ((atomic_read(&bmp->db_active[agpref]) == 0) &&
- (bmp->db_agfree[agpref] >= avgfree))
- goto unlock;
-
- for (i = 0 ; i < bmp->db_numag; i++, agpref++) {
- if (agpref == bmp->db_numag)
- agpref = 0;
- if (atomic_read(&bmp->db_active[agpref]))
-
- continue;
- if (bmp->db_agfree[agpref] >= avgfree) {
-
- bmp->db_agpref = agpref;
- goto unlock;
- } else if (bmp->db_agfree[agpref] > hwm) {
-
- hwm = bmp->db_agfree[agpref];
- next_best = agpref;
- }
- }
-
- if (next_best != -1)
- bmp->db_agpref = next_best;
-
- unlock:
- BMAP_UNLOCK(bmp);
-
- return (bmp->db_agpref);
- }
- int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
- {
- int rc, agno;
- struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
- struct bmap *bmp;
- struct metapage *mp;
- s64 lblkno, blkno;
- struct dmap *dp;
- int l2nb;
- s64 mapSize;
- int writers;
-
- assert(nblocks > 0);
-
- l2nb = BLKSTOL2(nblocks);
- bmp = JFS_SBI(ip->i_sb)->bmap;
- mapSize = bmp->db_mapsize;
-
- if (hint >= mapSize) {
- jfs_error(ip->i_sb, "the hint is outside the map\n");
- return -EIO;
- }
-
- if (l2nb > bmp->db_agl2size) {
- IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
- rc = dbAllocAny(bmp, nblocks, l2nb, results);
- goto write_unlock;
- }
-
- if (hint == 0)
- goto pref_ag;
-
- blkno = hint + 1;
- if (blkno >= bmp->db_mapsize)
- goto pref_ag;
- agno = blkno >> bmp->db_agl2size;
-
- if ((blkno & (bmp->db_agsize - 1)) == 0)
-
- if (atomic_read(&bmp->db_active[agno]))
- goto pref_ag;
-
- if (nblocks <= BPERDMAP) {
- IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
-
- rc = -EIO;
- lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
- mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL)
- goto read_unlock;
- dp = (struct dmap *) mp->data;
-
- if ((rc = dbAllocNext(bmp, dp, blkno, (int) nblocks))
- != -ENOSPC) {
- if (rc == 0) {
- *results = blkno;
- mark_metapage_dirty(mp);
- }
- release_metapage(mp);
- goto read_unlock;
- }
- writers = atomic_read(&bmp->db_active[agno]);
- if ((writers > 1) ||
- ((writers == 1) && (JFS_IP(ip)->active_ag != agno))) {
-
- release_metapage(mp);
- IREAD_UNLOCK(ipbmap);
- goto pref_ag;
- }
-
- if ((rc =
- dbAllocNear(bmp, dp, blkno, (int) nblocks, l2nb, results))
- != -ENOSPC) {
- if (rc == 0)
- mark_metapage_dirty(mp);
- release_metapage(mp);
- goto read_unlock;
- }
-
- if ((rc = dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results))
- != -ENOSPC) {
- if (rc == 0)
- mark_metapage_dirty(mp);
- release_metapage(mp);
- goto read_unlock;
- }
- release_metapage(mp);
- IREAD_UNLOCK(ipbmap);
- }
-
- IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
- if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) != -ENOSPC)
- goto write_unlock;
- IWRITE_UNLOCK(ipbmap);
- pref_ag:
-
- agno = dbNextAG(ipbmap);
- IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
-
- if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) == -ENOSPC)
- rc = dbAllocAny(bmp, nblocks, l2nb, results);
- write_unlock:
- IWRITE_UNLOCK(ipbmap);
- return (rc);
- read_unlock:
- IREAD_UNLOCK(ipbmap);
- return (rc);
- }
- #ifdef _NOTYET
- int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
- {
- int rc;
- struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
- struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
- struct dmap *dp;
- s64 lblkno;
- struct metapage *mp;
- IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
-
- if (nblocks <= 0 || nblocks > BPERDMAP || blkno >= bmp->db_mapsize) {
- IREAD_UNLOCK(ipbmap);
- return -EINVAL;
- }
- if (nblocks > ((s64) 1 << bmp->db_maxfreebud)) {
-
- IREAD_UNLOCK(ipbmap);
- return -ENOSPC;
- }
-
- lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
- mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL) {
- IREAD_UNLOCK(ipbmap);
- return -EIO;
- }
- dp = (struct dmap *) mp->data;
-
- rc = dbAllocNext(bmp, dp, blkno, nblocks);
- IREAD_UNLOCK(ipbmap);
- if (rc == 0)
- mark_metapage_dirty(mp);
- release_metapage(mp);
- return (rc);
- }
- #endif
- int
- dbReAlloc(struct inode *ip,
- s64 blkno, s64 nblocks, s64 addnblocks, s64 * results)
- {
- int rc;
-
- if ((rc = dbExtend(ip, blkno, nblocks, addnblocks)) == 0) {
- *results = blkno;
- return (0);
- } else {
- if (rc != -ENOSPC)
- return (rc);
- }
-
- return (dbAlloc
- (ip, blkno + nblocks - 1, addnblocks + nblocks, results));
- }
- static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
- {
- struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
- s64 lblkno, lastblkno, extblkno;
- uint rel_block;
- struct metapage *mp;
- struct dmap *dp;
- int rc;
- struct inode *ipbmap = sbi->ipbmap;
- struct bmap *bmp;
-
- if (((rel_block = blkno & (sbi->nbperpage - 1))) &&
- (rel_block + nblocks + addnblocks > sbi->nbperpage))
- return -ENOSPC;
-
- lastblkno = blkno + nblocks - 1;
-
- extblkno = lastblkno + 1;
- IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
-
- bmp = sbi->bmap;
- if (lastblkno < 0 || lastblkno >= bmp->db_mapsize) {
- IREAD_UNLOCK(ipbmap);
- jfs_error(ip->i_sb, "the block is outside the filesystem\n");
- return -EIO;
- }
-
- if (addnblocks > BPERDMAP || extblkno >= bmp->db_mapsize ||
- (extblkno & (bmp->db_agsize - 1)) == 0) {
- IREAD_UNLOCK(ipbmap);
- return -ENOSPC;
- }
-
- lblkno = BLKTODMAP(extblkno, bmp->db_l2nbperpage);
- mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL) {
- IREAD_UNLOCK(ipbmap);
- return -EIO;
- }
- dp = (struct dmap *) mp->data;
-
- rc = dbAllocNext(bmp, dp, extblkno, (int) addnblocks);
- IREAD_UNLOCK(ipbmap);
-
- if (rc == 0)
- write_metapage(mp);
- else
-
- release_metapage(mp);
- return (rc);
- }
- static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks)
- {
- int dbitno, word, rembits, nb, nwords, wbitno, nw;
- int l2size;
- s8 *leaf;
- u32 mask;
- if (dp->tree.leafidx != cpu_to_le32(LEAFIND)) {
- jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmap page\n");
- return -EIO;
- }
-
- leaf = dp->tree.stree + le32_to_cpu(dp->tree.leafidx);
-
- dbitno = blkno & (BPERDMAP - 1);
- word = dbitno >> L2DBWORD;
-
- if (dbitno + nblocks > BPERDMAP)
- return -ENOSPC;
-
- if (leaf[word] == NOFREE)
- return -ENOSPC;
-
- for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
-
- wbitno = dbitno & (DBWORD - 1);
- nb = min(rembits, DBWORD - wbitno);
-
- if (nb < DBWORD) {
-
- mask = (ONES << (DBWORD - nb) >> wbitno);
- if ((mask & ~le32_to_cpu(dp->wmap[word])) != mask)
- return -ENOSPC;
- word += 1;
- } else {
-
- nwords = rembits >> L2DBWORD;
- nb = nwords << L2DBWORD;
-
- while (nwords > 0) {
-
- if (leaf[word] < BUDMIN)
- return -ENOSPC;
-
- l2size =
- min_t(int, leaf[word], NLSTOL2BSZ(nwords));
-
- nw = BUDSIZE(l2size, BUDMIN);
- nwords -= nw;
- word += nw;
- }
- }
- }
-
- return (dbAllocDmap(bmp, dp, blkno, nblocks));
- }
- static int
- dbAllocNear(struct bmap * bmp,
- struct dmap * dp, s64 blkno, int nblocks, int l2nb, s64 * results)
- {
- int word, lword, rc;
- s8 *leaf;
- if (dp->tree.leafidx != cpu_to_le32(LEAFIND)) {
- jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmap page\n");
- return -EIO;
- }
- leaf = dp->tree.stree + le32_to_cpu(dp->tree.leafidx);
-
- word = (blkno & (BPERDMAP - 1)) >> L2DBWORD;
- lword = min(word + 4, LPERDMAP);
-
- for (; word < lword; word++) {
-
- if (leaf[word] < l2nb)
- continue;
-
- blkno = le64_to_cpu(dp->start) + (word << L2DBWORD);
-
- if (leaf[word] < BUDMIN)
- blkno +=
- dbFindBits(le32_to_cpu(dp->wmap[word]), l2nb);
-
- if ((rc = dbAllocDmap(bmp, dp, blkno, nblocks)) == 0)
- *results = blkno;
- return (rc);
- }
- return -ENOSPC;
- }
- static int
- dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
- {
- struct metapage *mp;
- struct dmapctl *dcp;
- int rc, ti, i, k, m, n, agperlev;
- s64 blkno, lblkno;
- int budmin;
-
- if (l2nb > bmp->db_agl2size) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "allocation request is larger than the allocation group size\n");
- return -EIO;
- }
-
- blkno = (s64) agno << bmp->db_agl2size;
-
- if (bmp->db_agsize == BPERDMAP
- || bmp->db_agfree[agno] == bmp->db_agsize) {
- rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
- if ((rc == -ENOSPC) &&
- (bmp->db_agfree[agno] == bmp->db_agsize)) {
- printk(KERN_ERR "blkno = %Lx, blocks = %Lx\n",
- (unsigned long long) blkno,
- (unsigned long long) nblocks);
- jfs_error(bmp->db_ipbmap->i_sb,
- "dbAllocCtl failed in free AG\n");
- }
- return (rc);
- }
-
- lblkno = BLKTOCTL(blkno, bmp->db_l2nbperpage, bmp->db_aglevel);
- mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL)
- return -EIO;
- dcp = (struct dmapctl *) mp->data;
- budmin = dcp->budmin;
- if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
- jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
- release_metapage(mp);
- return -EIO;
- }
-
- agperlev =
- (1 << (L2LPERCTL - (bmp->db_agheight << 1))) / bmp->db_agwidth;
- ti = bmp->db_agstart + bmp->db_agwidth * (agno & (agperlev - 1));
-
- for (i = 0; i < bmp->db_agwidth; i++, ti++) {
-
- if (l2nb > dcp->stree[ti])
- continue;
-
- for (k = bmp->db_agheight; k > 0; k--) {
- for (n = 0, m = (ti << 2) + 1; n < 4; n++) {
- if (l2nb <= dcp->stree[m + n]) {
- ti = m + n;
- break;
- }
- }
- if (n == 4) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "failed descending stree\n");
- release_metapage(mp);
- return -EIO;
- }
- }
-
- if (bmp->db_aglevel == 2)
- blkno = 0;
- else if (bmp->db_aglevel == 1)
- blkno &= ~(MAXL1SIZE - 1);
- else
- blkno &= ~(MAXL0SIZE - 1);
- blkno +=
- ((s64) (ti - le32_to_cpu(dcp->leafidx))) << budmin;
-
- release_metapage(mp);
-
- if (l2nb < budmin) {
-
- if ((rc =
- dbFindCtl(bmp, l2nb, bmp->db_aglevel - 1,
- &blkno))) {
- if (rc == -ENOSPC) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "control page inconsistent\n");
- return -EIO;
- }
- return (rc);
- }
- }
-
- rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
- if (rc == -ENOSPC) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "unable to allocate blocks\n");
- rc = -EIO;
- }
- return (rc);
- }
-
- release_metapage(mp);
- return -ENOSPC;
- }
- static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results)
- {
- int rc;
- s64 blkno = 0;
-
- if ((rc = dbFindCtl(bmp, l2nb, bmp->db_maxlevel, &blkno)))
- return (rc);
-
- rc = dbAllocCtl(bmp, nblocks, l2nb, blkno, results);
- if (rc == -ENOSPC) {
- jfs_error(bmp->db_ipbmap->i_sb, "unable to allocate blocks\n");
- return -EIO;
- }
- return (rc);
- }
- s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen)
- {
- struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
- struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
- s64 nblocks, blkno;
- u64 trimmed = 0;
- int rc, l2nb;
- struct super_block *sb = ipbmap->i_sb;
- struct range2trim {
- u64 blkno;
- u64 nblocks;
- } *totrim, *tt;
-
- int count = 0, range_cnt;
- u64 max_ranges;
-
- IWRITE_LOCK(ipbmap, RDWRLOCK_DMAP);
- nblocks = bmp->db_agfree[agno];
- max_ranges = nblocks;
- do_div(max_ranges, minlen);
- range_cnt = min_t(u64, max_ranges + 1, 32 * 1024);
- totrim = kmalloc(sizeof(struct range2trim) * range_cnt, GFP_NOFS);
- if (totrim == NULL) {
- jfs_error(bmp->db_ipbmap->i_sb, "no memory for trim array\n");
- IWRITE_UNLOCK(ipbmap);
- return 0;
- }
- tt = totrim;
- while (nblocks >= minlen) {
- l2nb = BLKSTOL2(nblocks);
-
- rc = dbAllocAG(bmp, agno, nblocks, l2nb, &blkno);
- if (rc == 0) {
- tt->blkno = blkno;
- tt->nblocks = nblocks;
- tt++; count++;
-
- if (bmp->db_agfree[agno] == 0)
- break;
-
- nblocks = bmp->db_agfree[agno];
- continue;
- } else if (rc == -ENOSPC) {
-
- l2nb = BLKSTOL2(nblocks) - 1;
- nblocks = 1 << l2nb;
- } else {
-
- jfs_error(bmp->db_ipbmap->i_sb, "-EIO\n");
- break;
- }
-
- if (unlikely(count >= range_cnt - 1))
- break;
- }
- IWRITE_UNLOCK(ipbmap);
- tt->nblocks = 0;
- for (tt = totrim; tt->nblocks != 0; tt++) {
-
- if (!(JFS_SBI(sb)->flag & JFS_DISCARD))
- jfs_issue_discard(ip, tt->blkno, tt->nblocks);
- dbFree(ip, tt->blkno, tt->nblocks);
- trimmed += tt->nblocks;
- }
- kfree(totrim);
- return trimmed;
- }
- static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
- {
- int rc, leafidx, lev;
- s64 b, lblkno;
- struct dmapctl *dcp;
- int budmin;
- struct metapage *mp;
-
- for (lev = level, b = *blkno; lev >= 0; lev--) {
-
- lblkno = BLKTOCTL(b, bmp->db_l2nbperpage, lev);
- mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL)
- return -EIO;
- dcp = (struct dmapctl *) mp->data;
- budmin = dcp->budmin;
- if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "Corrupt dmapctl page\n");
- release_metapage(mp);
- return -EIO;
- }
-
- rc = dbFindLeaf((dmtree_t *) dcp, l2nb, &leafidx);
-
- release_metapage(mp);
-
- if (rc) {
- if (lev != level) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "dmap inconsistent\n");
- return -EIO;
- }
- return -ENOSPC;
- }
-
- b += (((s64) leafidx) << budmin);
-
- if (l2nb >= budmin)
- break;
- }
- *blkno = b;
- return (0);
- }
- static int
- dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
- {
- int rc, nb;
- s64 b, lblkno, n;
- struct metapage *mp;
- struct dmap *dp;
-
- if (l2nb <= L2BPERDMAP) {
-
- lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
- mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL)
- return -EIO;
- dp = (struct dmap *) mp->data;
-
- rc = dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results);
- if (rc == 0)
- mark_metapage_dirty(mp);
- release_metapage(mp);
- return (rc);
- }
-
- assert((blkno & (BPERDMAP - 1)) == 0);
-
- for (n = nblocks, b = blkno; n > 0; n -= nb, b += nb) {
-
- lblkno = BLKTODMAP(b, bmp->db_l2nbperpage);
- mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL) {
- rc = -EIO;
- goto backout;
- }
- dp = (struct dmap *) mp->data;
-
- if (dp->tree.stree[ROOT] != L2BPERDMAP) {
- release_metapage(mp);
- jfs_error(bmp->db_ipbmap->i_sb,
- "the dmap is not all free\n");
- rc = -EIO;
- goto backout;
- }
-
- nb = min_t(s64, n, BPERDMAP);
-
- if ((rc = dbAllocDmap(bmp, dp, b, nb))) {
- release_metapage(mp);
- goto backout;
- }
-
- write_metapage(mp);
- }
-
- *results = blkno;
- return (0);
-
- backout:
-
- for (n = nblocks - n, b = blkno; n > 0;
- n -= BPERDMAP, b += BPERDMAP) {
-
- lblkno = BLKTODMAP(b, bmp->db_l2nbperpage);
- mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL) {
-
- jfs_error(bmp->db_ipbmap->i_sb,
- "I/O Error: Block Leakage\n");
- continue;
- }
- dp = (struct dmap *) mp->data;
-
- if (dbFreeDmap(bmp, dp, b, BPERDMAP)) {
-
- release_metapage(mp);
- jfs_error(bmp->db_ipbmap->i_sb, "Block Leakage\n");
- continue;
- }
-
- write_metapage(mp);
- }
- return (rc);
- }
- static int
- dbAllocDmapLev(struct bmap * bmp,
- struct dmap * dp, int nblocks, int l2nb, s64 * results)
- {
- s64 blkno;
- int leafidx, rc;
-
- assert(l2nb <= L2BPERDMAP);
-
- if (dbFindLeaf((dmtree_t *) & dp->tree, l2nb, &leafidx))
- return -ENOSPC;
-
- blkno = le64_to_cpu(dp->start) + (leafidx << L2DBWORD);
-
- if (dp->tree.stree[leafidx + LEAFIND] < BUDMIN)
- blkno += dbFindBits(le32_to_cpu(dp->wmap[leafidx]), l2nb);
-
- if ((rc = dbAllocDmap(bmp, dp, blkno, nblocks)) == 0)
- *results = blkno;
- return (rc);
- }
- static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks)
- {
- s8 oldroot;
- int rc;
-
- oldroot = dp->tree.stree[ROOT];
-
- dbAllocBits(bmp, dp, blkno, nblocks);
-
- if (dp->tree.stree[ROOT] == oldroot)
- return (0);
-
- if ((rc = dbAdjCtl(bmp, blkno, dp->tree.stree[ROOT], 1, 0)))
- dbFreeBits(bmp, dp, blkno, nblocks);
- return (rc);
- }
- static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks)
- {
- s8 oldroot;
- int rc = 0, word;
-
- oldroot = dp->tree.stree[ROOT];
-
- rc = dbFreeBits(bmp, dp, blkno, nblocks);
-
- if (rc || (dp->tree.stree[ROOT] == oldroot))
- return (rc);
-
- if ((rc = dbAdjCtl(bmp, blkno, dp->tree.stree[ROOT], 0, 0))) {
- word = (blkno & (BPERDMAP - 1)) >> L2DBWORD;
-
- if (dp->tree.stree[word] == NOFREE)
- dbBackSplit((dmtree_t *) & dp->tree, word);
- dbAllocBits(bmp, dp, blkno, nblocks);
- }
- return (rc);
- }
- static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks)
- {
- int dbitno, word, rembits, nb, nwords, wbitno, nw, agno;
- dmtree_t *tp = (dmtree_t *) & dp->tree;
- int size;
- s8 *leaf;
-
- leaf = dp->tree.stree + LEAFIND;
-
- dbitno = blkno & (BPERDMAP - 1);
- word = dbitno >> L2DBWORD;
-
- assert(dbitno + nblocks <= BPERDMAP);
-
- for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
-
- wbitno = dbitno & (DBWORD - 1);
- nb = min(rembits, DBWORD - wbitno);
-
- if (nb < DBWORD) {
-
- dp->wmap[word] |= cpu_to_le32(ONES << (DBWORD - nb)
- >> wbitno);
-
- dbSplit(tp, word, BUDMIN,
- dbMaxBud((u8 *) & dp->wmap[word]));
- word += 1;
- } else {
-
- nwords = rembits >> L2DBWORD;
- memset(&dp->wmap[word], (int) ONES, nwords * 4);
-
- nb = nwords << L2DBWORD;
-
- for (; nwords > 0; nwords -= nw) {
- if (leaf[word] < BUDMIN) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "leaf page corrupt\n");
- break;
- }
-
- size = min_t(int, leaf[word],
- NLSTOL2BSZ(nwords));
-
- dbSplit(tp, word, size, NOFREE);
-
- nw = BUDSIZE(size, BUDMIN);
- word += nw;
- }
- }
- }
-
- le32_add_cpu(&dp->nfree, -nblocks);
- BMAP_LOCK(bmp);
-
- agno = blkno >> bmp->db_agl2size;
- if (agno > bmp->db_maxag)
- bmp->db_maxag = agno;
-
- bmp->db_agfree[agno] -= nblocks;
- bmp->db_nfree -= nblocks;
- BMAP_UNLOCK(bmp);
- }
- static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks)
- {
- int dbitno, word, rembits, nb, nwords, wbitno, nw, agno;
- dmtree_t *tp = (dmtree_t *) & dp->tree;
- int rc = 0;
- int size;
-
- dbitno = blkno & (BPERDMAP - 1);
- word = dbitno >> L2DBWORD;
-
- assert(dbitno + nblocks <= BPERDMAP);
-
- for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
-
- wbitno = dbitno & (DBWORD - 1);
- nb = min(rembits, DBWORD - wbitno);
-
- if (nb < DBWORD) {
-
- dp->wmap[word] &=
- cpu_to_le32(~(ONES << (DBWORD - nb)
- >> wbitno));
-
- rc = dbJoin(tp, word,
- dbMaxBud((u8 *) & dp->wmap[word]));
- if (rc)
- return rc;
- word += 1;
- } else {
-
- nwords = rembits >> L2DBWORD;
- memset(&dp->wmap[word], 0, nwords * 4);
-
- nb = nwords << L2DBWORD;
-
- for (; nwords > 0; nwords -= nw) {
-
- size =
- min(LITOL2BSZ
- (word, L2LPERDMAP, BUDMIN),
- NLSTOL2BSZ(nwords));
-
- rc = dbJoin(tp, word, size);
- if (rc)
- return rc;
-
- nw = BUDSIZE(size, BUDMIN);
- word += nw;
- }
- }
- }
-
- le32_add_cpu(&dp->nfree, nblocks);
- BMAP_LOCK(bmp);
-
- agno = blkno >> bmp->db_agl2size;
- bmp->db_nfree += nblocks;
- bmp->db_agfree[agno] += nblocks;
-
- if ((bmp->db_agfree[agno] == bmp->db_agsize && agno == bmp->db_maxag) ||
- (agno == bmp->db_numag - 1 &&
- bmp->db_agfree[agno] == (bmp-> db_mapsize & (BPERDMAP - 1)))) {
- while (bmp->db_maxag > 0) {
- bmp->db_maxag -= 1;
- if (bmp->db_agfree[bmp->db_maxag] !=
- bmp->db_agsize)
- break;
- }
-
- if (bmp->db_agpref > bmp->db_maxag)
- bmp->db_agpref = bmp->db_maxag;
- }
- BMAP_UNLOCK(bmp);
- return 0;
- }
- static int
- dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
- {
- struct metapage *mp;
- s8 oldroot;
- int oldval;
- s64 lblkno;
- struct dmapctl *dcp;
- int rc, leafno, ti;
-
- lblkno = BLKTOCTL(blkno, bmp->db_l2nbperpage, level);
- mp = read_metapage(bmp->db_ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL)
- return -EIO;
- dcp = (struct dmapctl *) mp->data;
- if (dcp->leafidx != cpu_to_le32(CTLLEAFIND)) {
- jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n");
- release_metapage(mp);
- return -EIO;
- }
-
- leafno = BLKTOCTLLEAF(blkno, dcp->budmin);
- ti = leafno + le32_to_cpu(dcp->leafidx);
-
- oldval = dcp->stree[ti];
- oldroot = dcp->stree[ROOT];
-
- if (alloc) {
-
- if (oldval == NOFREE) {
- rc = dbBackSplit((dmtree_t *) dcp, leafno);
- if (rc)
- return rc;
- oldval = dcp->stree[ti];
- }
- dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval);
- } else {
- rc = dbJoin((dmtree_t *) dcp, leafno, newval);
- if (rc)
- return rc;
- }
-
- if (dcp->stree[ROOT] != oldroot) {
-
- if (level < bmp->db_maxlevel) {
-
- if ((rc =
- dbAdjCtl(bmp, blkno, dcp->stree[ROOT], alloc,
- level + 1))) {
-
- if (alloc) {
- dbJoin((dmtree_t *) dcp, leafno,
- oldval);
- } else {
-
- if (dcp->stree[ti] == NOFREE)
- dbBackSplit((dmtree_t *)
- dcp, leafno);
- dbSplit((dmtree_t *) dcp, leafno,
- dcp->budmin, oldval);
- }
-
- release_metapage(mp);
- return (rc);
- }
- } else {
-
- assert(level == bmp->db_maxlevel);
- if (bmp->db_maxfreebud != oldroot) {
- jfs_error(bmp->db_ipbmap->i_sb,
- "the maximum free buddy is not the old root\n");
- }
- bmp->db_maxfreebud = dcp->stree[ROOT];
- }
- }
-
- write_metapage(mp);
- return (0);
- }
- static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
- {
- int budsz;
- int cursz;
- s8 *leaf = tp->dmt_stree + le32_to_cpu(tp->dmt_leafidx);
-
- if (leaf[leafno] > tp->dmt_budmin) {
-
- cursz = leaf[leafno] - 1;
- budsz = BUDSIZE(cursz, tp->dmt_budmin);
-
- while (cursz >= splitsz) {
-
- dbAdjTree(tp, leafno ^ budsz, cursz);
-
- cursz -= 1;
- budsz >>= 1;
- }
- }
-
- dbAdjTree(tp, leafno, newval);
- }
- static int dbBackSplit(dmtree_t * tp, int leafno)
- {
- int budsz, bud, w, bsz, size;
- int cursz;
- s8 *leaf = tp->dmt_stree + le32_to_cpu(tp->dmt_leafidx);
-
- assert(leaf[leafno] == NOFREE);
-
- size =
- LITOL2BSZ(leafno, le32_to_cpu(tp->dmt_l2nleafs),
- tp->dmt_budmin);
-
- budsz = BUDSIZE(size, tp->dmt_budmin);
-
- while (leaf[leafno] == NOFREE) {
-
- for (w = leafno, bsz = budsz;; bsz <<= 1,
- w = (w < bud) ? w : bud) {
- if (bsz >= le32_to_cpu(tp->dmt_nleafs)) {
- jfs_err("JFS: block map error in dbBackSplit");
- return -EIO;
- }
-
- bud = w ^ bsz;
-
- if (leaf[bud] != NOFREE) {
-
- cursz = leaf[bud] - 1;
- dbSplit(tp, bud, cursz, cursz);
- break;
- }
- }
- }
- if (leaf[leafno] != size) {
- jfs_err("JFS: wrong leaf value in dbBackSplit");
- return -EIO;
- }
- return 0;
- }
- static int dbJoin(dmtree_t * tp, int leafno, int newval)
- {
- int budsz, buddy;
- s8 *leaf;
-
- if (newval >= tp->dmt_budmin) {
-
- leaf = tp->dmt_stree + le32_to_cpu(tp->dmt_leafidx);
-
- budsz = BUDSIZE(newval, tp->dmt_budmin);
-
- while (budsz < le32_to_cpu(tp->dmt_nleafs)) {
-
- buddy = leafno ^ budsz;
-
- if (newval > leaf[buddy])
- break;
-
- if (newval < leaf[buddy])
- return -EIO;
-
- if (leafno < buddy) {
-
- dbAdjTree(tp, buddy, NOFREE);
- } else {
-
- dbAdjTree(tp, leafno, NOFREE);
- leafno = buddy;
- }
-
- newval += 1;
- budsz <<= 1;
- }
- }
-
- dbAdjTree(tp, leafno, newval);
- return 0;
- }
- static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
- {
- int lp, pp, k;
- int max;
-
- lp = leafno + le32_to_cpu(tp->dmt_leafidx);
-
- if (tp->dmt_stree[lp] == newval)
- return;
-
- tp->dmt_stree[lp] = newval;
-
- for (k = 0; k < le32_to_cpu(tp->dmt_height); k++) {
-
- lp = ((lp - 1) & ~0x03) + 1;
-
- pp = (lp - 1) >> 2;
-
- max = TREEMAX(&tp->dmt_stree[lp]);
-
- if (tp->dmt_stree[pp] == max)
- break;
-
- tp->dmt_stree[pp] = max;
-
- lp = pp;
- }
- }
- static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
- {
- int ti, n = 0, k, x = 0;
-
- if (l2nb > tp->dmt_stree[ROOT])
- return -ENOSPC;
-
- for (k = le32_to_cpu(tp->dmt_height), ti = 1;
- k > 0; k--, ti = ((ti + n) << 2) + 1) {
-
- for (x = ti, n = 0; n < 4; n++) {
-
- if (l2nb <= tp->dmt_stree[x + n])
- break;
- }
-
- assert(n < 4);
- }
-
- *leafidx = x + n - le32_to_cpu(tp->dmt_leafidx);
- return (0);
- }
- static int dbFindBits(u32 word, int l2nb)
- {
- int bitno, nb;
- u32 mask;
-
- nb = 1 << l2nb;
- assert(nb <= DBWORD);
-
- word = ~word;
- mask = ONES << (DBWORD - nb);
-
- for (bitno = 0; mask != 0; bitno += nb, mask >>= nb) {
- if ((mask & word) == mask)
- break;
- }
- ASSERT(bitno < 32);
-
- return (bitno);
- }
- static int dbMaxBud(u8 * cp)
- {
- signed char tmp1, tmp2;
-
- if (*((uint *) cp) == 0)
- return (BUDMIN);
-
- if (*((u16 *) cp) == 0 || *((u16 *) cp + 1) == 0)
- return (BUDMIN - 1);
-
- tmp1 = max(budtab[cp[2]], budtab[cp[3]]);
- tmp2 = max(budtab[cp[0]], budtab[cp[1]]);
- return (max(tmp1, tmp2));
- }
- static int cnttz(u32 word)
- {
- int n;
- for (n = 0; n < 32; n++, word >>= 1) {
- if (word & 0x01)
- break;
- }
- return (n);
- }
- static int cntlz(u32 value)
- {
- int n;
- for (n = 0; n < 32; n++, value <<= 1) {
- if (value & HIGHORDER)
- break;
- }
- return (n);
- }
- static int blkstol2(s64 nb)
- {
- int l2nb;
- s64 mask;
- mask = (s64) 1 << (64 - 1);
-
- for (l2nb = 0; l2nb < 64; l2nb++, mask >>= 1) {
-
- if (nb & mask) {
-
- l2nb = (64 - 1) - l2nb;
-
- if (~mask & nb)
- l2nb++;
- return (l2nb);
- }
- }
- assert(0);
- return 0;
- }
- int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks)
- {
- struct metapage *mp;
- struct dmap *dp;
- int nb, rc;
- s64 lblkno, rem;
- struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
- struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
- IREAD_LOCK(ipbmap, RDWRLOCK_DMAP);
-
- ASSERT(nblocks <= bmp->db_mapsize - blkno);
-
- mp = NULL;
- for (rem = nblocks; rem > 0; rem -= nb, blkno += nb) {
-
- if (mp) {
- write_metapage(mp);
- }
-
- lblkno = BLKTODMAP(blkno, bmp->db_l2nbperpage);
- mp = read_metapage(ipbmap, lblkno, PSIZE, 0);
- if (mp == NULL) {
- IREAD_UNLOCK(ipbmap);
- return -EIO;
- }
- dp = (struct dmap *) mp->data;
-
- nb = min(rem, BPERDMAP - (blkno & (BPERDMAP - 1)));
-
- if ((rc = dbAllocDmapBU(bmp, dp, blkno, nb))) {
- release_metapage(mp);
- IREAD_UNLOCK(ipbmap);
- return (rc);
- }
- }
-
- write_metapage(mp);
- IREAD_UNLOCK(ipbmap);
- return (0);
- }
- static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
- int nblocks)
- {
- int rc;
- int dbitno, word, rembits, nb, nwords, wbitno, agno;
- s8 oldroot;
- struct dmaptree *tp = (struct dmaptree *) & dp->tree;
-
- oldroot = tp->stree[ROOT];
-
- dbitno = blkno & (BPERDMAP - 1);
- word = dbitno >> L2DBWORD;
-
- assert(dbitno + nblocks <= BPERDMAP);
-
- for (rembits = nblocks; rembits > 0; rembits -= nb, dbitno += nb) {
-
- wbitno = dbitno & (DBWORD - 1);
- nb = min(rembits, DBWORD - wbitno);
-
- if (nb < DBWORD) {
-
- dp->wmap[word] |= cpu_to_le32(ONES << (DBWORD - nb)
- >> wbitno);
- word++;
- } else {
-
- nwords = rembits >> L2DBWORD;
- memset(&dp->wmap[word], (int) ONES, nwords * 4);
-
- nb = nwords << L2DBWORD;
- word += nwords;
- }
- }
-
- le32_add_cpu(&dp->nfree, -nblocks);
-
- dbInitDmapTree(dp);
- BMAP_LOCK(bmp);
-
- agno = blkno >> bmp->db_agl2size;
- if (agno > bmp->db_maxag)
- bmp->db_maxag = agno;
-
- bmp->db_agfree[agno] -= nblocks;
- bmp->db_nfree -= nblocks;
- BMAP_UNLOCK(bmp);
-
- if (tp->stree[ROOT] == oldroot)
- return (0);
-
- if ((rc = dbAdjCtl(bmp, blkno, tp->stree[ROOT], 1, 0)))
- dbFreeBits(bmp, dp, blkno, nblocks);
- return (rc);
- }
- int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
- {
- struct jfs_sb_info *sbi = JFS_SBI(ipbmap->i_sb);
- int nbperpage = sbi->nbperpage;
- int i, i0 = true, j, j0 = true, k, n;
- s64 newsize;
- s64 p;
- struct metapage *mp, *l2mp, *l1mp = NULL, *l0mp = NULL;
- struct dmapctl *l2dcp, *l1dcp, *l0dcp;
- struct dmap *dp;
- s8 *l0leaf, *l1leaf, *l2leaf;
- struct bmap *bmp = sbi->bmap;
- int agno, l2agsize, oldl2agsize;
- s64 ag_rem;
- newsize = blkno + nblocks;
- jfs_info("dbExtendFS: blkno:%Ld nblocks:%Ld newsize:%Ld",
- (long long) blkno, (long long) nblocks, (long long) newsize);
-
-
- bmp->db_mapsize = newsize;
- bmp->db_maxlevel = BMAPSZTOLEV(bmp->db_mapsize);
-
- l2agsize = dbGetL2AGSize(newsize);
- oldl2agsize = bmp->db_agl2size;
- bmp->db_agl2size = l2agsize;
- bmp->db_agsize = 1 << l2agsize;
-
- agno = bmp->db_numag;
- bmp->db_numag = newsize >> l2agsize;
- bmp->db_numag += ((u32) newsize % (u32) bmp->db_agsize) ? 1 : 0;
-
- if (l2agsize == oldl2agsize)
- goto extend;
- k = 1 << (l2agsize - oldl2agsize);
- ag_rem = bmp->db_agfree[0];
- for (i = 0, n = 0; i < agno; n++) {
- bmp->db_agfree[n] = 0;
-
- for (j = 0; j < k && i < agno; j++, i++) {
-
- bmp->db_agfree[n] += bmp->db_agfree[i];
- }
- }
- bmp->db_agfree[0] += ag_rem;
- for (; n < MAXAG; n++)
- bmp->db_agfree[n] = 0;
-
- bmp->db_maxag = bmp->db_maxag / k;
-
- extend:
-
- p = BMAPBLKNO + nbperpage;
- l2mp = read_metapage(ipbmap, p, PSIZE, 0);
- if (!l2mp) {
- jfs_error(ipbmap->i_sb, "L2 page could not be read\n");
- return -EIO;
- }
- l2dcp = (struct dmapctl *) l2mp->data;
-
- k = blkno >> L2MAXL1SIZE;
- l2leaf = l2dcp->stree + CTLLEAFIND + k;
- p = BLKTOL1(blkno, sbi->l2nbperpage);
-
- for (; k < LPERCTL; k++, p += nbperpage) {
-
- if (j0) {
-
- l1mp = read_metapage(ipbmap, p, PSIZE, 0);
- if (l1mp == NULL)
- goto errout;
- l1dcp = (struct dmapctl *) l1mp->data;
-
- j = (blkno & (MAXL1SIZE - 1)) >> L2MAXL0SIZE;
- l1leaf = l1dcp->stree + CTLLEAFIND + j;
- p = BLKTOL0(blkno, sbi->l2nbperpage);
- j0 = false;
- } else {
-
- l1mp = get_metapage(ipbmap, p, PSIZE, 0);
- if (l1mp == NULL)
- goto errout;
- l1dcp = (struct dmapctl *) l1mp->data;
-
- j = 0;
- l1leaf = l1dcp->stree + CTLLEAFIND;
- p += nbperpage;
- }
-
- for (; j < LPERCTL; j++) {
-
- if (i0) {
-
- l0mp = read_metapage(ipbmap, p, PSIZE, 0);
- if (l0mp == NULL)
- goto errout;
- l0dcp = (struct dmapctl *) l0mp->data;
-
- i = (blkno & (MAXL0SIZE - 1)) >>
- L2BPERDMAP;
- l0leaf = l0dcp->stree + CTLLEAFIND + i;
- p = BLKTODMAP(blkno,
- sbi->l2nbperpage);
- i0 = false;
- } else {
-
- l0mp = get_metapage(ipbmap, p, PSIZE, 0);
- if (l0mp == NULL)
- goto errout;
- l0dcp = (struct dmapctl *) l0mp->data;
-
- i = 0;
- l0leaf = l0dcp->stree + CTLLEAFIND;
- p += nbperpage;
- }
-
- for (; i < LPERCTL; i++) {
-
- if ((n = blkno & (BPERDMAP - 1))) {
-
- mp = read_metapage(ipbmap, p,
- PSIZE, 0);
- if (mp == NULL)
- goto errout;
- n = min(nblocks, (s64)BPERDMAP - n);
- } else {
-
- mp = read_metapage(ipbmap, p,
- PSIZE, 0);
- if (mp == NULL)
- goto errout;
- n = min_t(s64, nblocks, BPERDMAP);
- }
- dp = (struct dmap *) mp->data;
- *l0leaf = dbInitDmap(dp, blkno, n);
- bmp->db_nfree += n;
- agno = le64_to_cpu(dp->start) >> l2agsize;
- bmp->db_agfree[agno] += n;
- write_metapage(mp);
- l0leaf++;
- p += nbperpage;
- blkno += n;
- nblocks -= n;
- if (nblocks == 0)
- break;
- }
-
- *l1leaf = dbInitDmapCtl(l0dcp, 0, ++i);
- write_metapage(l0mp);
- l0mp = NULL;
- if (nblocks)
- l1leaf++;
- else {
-
- if (j > 0)
- break;
- else {
-
- bmp->db_maxfreebud = *l1leaf;
- release_metapage(l1mp);
- release_metapage(l2mp);
- goto finalize;
- }
- }
- }
-
- *l2leaf = dbInitDmapCtl(l1dcp, 1, ++j);
- write_metapage(l1mp);
- l1mp = NULL;
- if (nblocks)
- l2leaf++;
- else {
-
- if (k > 0)
- break;
- else {
-
- bmp->db_maxfreebud = *l2leaf;
- release_metapage(l2mp);
- goto finalize;
- }
- }
- }
- jfs_error(ipbmap->i_sb, "function has not returned as expected\n");
- errout:
- if (l0mp)
- release_metapage(l0mp);
- if (l1mp)
- release_metapage(l1mp);
- release_metapage(l2mp);
- return -EIO;
-
- finalize:
- return 0;
- }
- void dbFinalizeBmap(struct inode *ipbmap)
- {
- struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
- int actags, inactags, l2nl;
- s64 ag_rem, actfree, inactfree, avgfree;
- int i, n;
-
-
-
- actags = bmp->db_maxag + 1;
- inactags = bmp->db_numag - actags;
- ag_rem = bmp->db_mapsize & (bmp->db_agsize - 1);
-
- inactfree = (inactags && ag_rem) ?
- ((inactags - 1) << bmp->db_agl2size) + ag_rem
- : inactags << bmp->db_agl2size;
-
- actfree = bmp->db_nfree - inactfree;
- avgfree = (u32) actfree / (u32) actags;
-
- if (bmp->db_agfree[bmp->db_agpref] < avgfree) {
- for (bmp->db_agpref = 0; bmp->db_agpref < actags;
- bmp->db_agpref++) {
- if (bmp->db_agfree[bmp->db_agpref] >= avgfree)
- break;
- }
- if (bmp->db_agpref >= bmp->db_numag) {
- jfs_error(ipbmap->i_sb,
- "cannot find ag with average freespace\n");
- }
- }
-
- bmp->db_aglevel = BMAPSZTOLEV(bmp->db_agsize);
- l2nl =
- bmp->db_agl2size - (L2BPERDMAP + bmp->db_aglevel * L2LPERCTL);
- bmp->db_agheight = l2nl >> 1;
- bmp->db_agwidth = 1 << (l2nl - (bmp->db_agheight << 1));
- for (i = 5 - bmp->db_agheight, bmp->db_agstart = 0, n = 1; i > 0;
- i--) {
- bmp->db_agstart += n;
- n <<= 2;
- }
- }
- static int dbInitDmap(struct dmap * dp, s64 Blkno, int nblocks)
- {
- int blkno, w, b, r, nw, nb, i;
-
- blkno = Blkno & (BPERDMAP - 1);
- if (blkno == 0) {
- dp->nblocks = dp->nfree = cpu_to_le32(nblocks);
- dp->start = cpu_to_le64(Blkno);
- if (nblocks == BPERDMAP) {
- memset(&dp->wmap[0], 0, LPERDMAP * 4);
- memset(&dp->pmap[0], 0, LPERDMAP * 4);
- goto initTree;
- }
- } else {
- le32_add_cpu(&dp->nblocks, nblocks);
- le32_add_cpu(&dp->nfree, nblocks);
- }
-
- w = blkno >> L2DBWORD;
-
- for (r = nblocks; r > 0; r -= nb, blkno += nb) {
-
- b = blkno & (DBWORD - 1);
-
- nb = min(r, DBWORD - b);
-
- if (nb < DBWORD) {
-
- dp->wmap[w] &= cpu_to_le32(~(ONES << (DBWORD - nb)
- >> b));
- dp->pmap[w] &= cpu_to_le32(~(ONES << (DBWORD - nb)
- >> b));
-
- w++;
- } else {
-
- nw = r >> L2DBWORD;
- memset(&dp->wmap[w], 0, nw * 4);
- memset(&dp->pmap[w], 0, nw * 4);
-
- nb = nw << L2DBWORD;
- w += nw;
- }
- }
-
- if (blkno == BPERDMAP)
- goto initTree;
-
- w = blkno >> L2DBWORD;
-
- b = blkno & (DBWORD - 1);
- if (b) {
-
- dp->wmap[w] = dp->pmap[w] = cpu_to_le32(ONES >> b);
- w++;
- }
-
- for (i = w; i < LPERDMAP; i++)
- dp->pmap[i] = dp->wmap[i] = cpu_to_le32(ONES);
-
- initTree:
- return (dbInitDmapTree(dp));
- }
- static int dbInitDmapTree(struct dmap * dp)
- {
- struct dmaptree *tp;
- s8 *cp;
- int i;
-
- tp = &dp->tree;
- tp->nleafs = cpu_to_le32(LPERDMAP);
- tp->l2nleafs = cpu_to_le32(L2LPERDMAP);
- tp->leafidx = cpu_to_le32(LEAFIND);
- tp->height = cpu_to_le32(4);
- tp->budmin = BUDMIN;
-
- cp = tp->stree + le32_to_cpu(tp->leafidx);
- for (i = 0; i < LPERDMAP; i++)
- *cp++ = dbMaxBud((u8 *) & dp->wmap[i]);
-
- return (dbInitTree(tp));
- }
- static int dbInitTree(struct dmaptree * dtp)
- {
- int l2max, l2free, bsize, nextb, i;
- int child, parent, nparent;
- s8 *tp, *cp, *cp1;
- tp = dtp->stree;
-
- l2max = le32_to_cpu(dtp->l2nleafs) + dtp->budmin;
-
- for (l2free = dtp->budmin, bsize = 1; l2free < l2max;
- l2free++, bsize = nextb) {
-
- nextb = bsize << 1;
-
- for (i = 0, cp = tp + le32_to_cpu(dtp->leafidx);
- i < le32_to_cpu(dtp->nleafs);
- i += nextb, cp += nextb) {
-
- if (*cp == l2free && *(cp + bsize) == l2free) {
- *cp = l2free + 1;
- *(cp + bsize) = -1;
- }
- }
- }
-
- for (child = le32_to_cpu(dtp->leafidx),
- nparent = le32_to_cpu(dtp->nleafs) >> 2;
- nparent > 0; nparent >>= 2, child = parent) {
-
- parent = (child - 1) >> 2;
-
- for (i = 0, cp = tp + child, cp1 = tp + parent;
- i < nparent; i++, cp += 4, cp1++)
- *cp1 = TREEMAX(cp);
- }
- return (*tp);
- }
- static int dbInitDmapCtl(struct dmapctl * dcp, int level, int i)
- {
- s8 *cp;
- dcp->nleafs = cpu_to_le32(LPERCTL);
- dcp->l2nleafs = cpu_to_le32(L2LPERCTL);
- dcp->leafidx = cpu_to_le32(CTLLEAFIND);
- dcp->height = cpu_to_le32(5);
- dcp->budmin = L2BPERDMAP + L2LPERCTL * level;
-
- cp = &dcp->stree[CTLLEAFIND + i];
- for (; i < LPERCTL; i++)
- *cp++ = NOFREE;
-
- return (dbInitTree((struct dmaptree *) dcp));
- }
- static int dbGetL2AGSize(s64 nblocks)
- {
- s64 sz;
- s64 m;
- int l2sz;
- if (nblocks < BPERDMAP * MAXAG)
- return (L2BPERDMAP);
-
- m = ((u64) 1 << (64 - 1));
- for (l2sz = 64; l2sz >= 0; l2sz--, m >>= 1) {
- if (m & nblocks)
- break;
- }
- sz = (s64) 1 << l2sz;
- if (sz < nblocks)
- l2sz += 1;
-
- return (l2sz - L2MAXAG);
- }
- #define MAXL0PAGES (1 + LPERCTL)
- #define MAXL1PAGES (1 + LPERCTL * MAXL0PAGES)
- #define MAXL2PAGES (1 + LPERCTL * MAXL1PAGES)
- #define BMAPPGTOLEV(npages) \
- (((npages) <= 3 + MAXL0PAGES) ? 0 : \
- ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
- s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
- {
- struct super_block *sb = ipbmap->i_sb;
- s64 nblocks;
- s64 npages, ndmaps;
- int level, i;
- int complete, factor;
- nblocks = ipbmap->i_size >> JFS_SBI(sb)->l2bsize;
- npages = nblocks >> JFS_SBI(sb)->l2nbperpage;
- level = BMAPPGTOLEV(npages);
-
- ndmaps = 0;
- npages--;
-
- npages -= (2 - level);
- npages--;
- for (i = level; i >= 0; i--) {
- factor =
- (i == 2) ? MAXL1PAGES : ((i == 1) ? MAXL0PAGES : 1);
- complete = (u32) npages / factor;
- ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL :
- ((i == 1) ? LPERCTL : 1));
-
- npages = (u32) npages % factor;
-
- npages--;
- }
-
- nblocks = ndmaps << L2BPERDMAP;
- return (nblocks);
- }
|